diff options
168 files changed, 3238 insertions, 2819 deletions
diff --git a/.qmake.conf b/.qmake.conf index 8c302d7039..6d42bbdd34 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -4,4 +4,4 @@ CONFIG += warning_clean QT_SOURCE_TREE = $$PWD QT_BUILD_TREE = $$shadowed($$PWD) -MODULE_VERSION = 5.8.0 +MODULE_VERSION = 5.9.0 @@ -515,6 +515,24 @@ QT_EXT_PREFIX= # default qpa platform # Android vars +if [ -z "$ANDROID_SDK_ROOT" ]; then + if [ "$UNAME_SYSTEM" = "Darwin" ] && [ -d "$HOME/Library/Android/sdk" ]; then + ANDROID_SDK_ROOT="$HOME/Library/Android/sdk" + elif [ "$UNAME_SYSTEM" = "Linux" ] && [ -d "$HOME/Android/Sdk" ]; then + ANDROID_SDK_ROOT="$HOME/Android/Sdk" + fi +fi + +if [ -z "$ANDROID_NDK_ROOT" ]; then + if [ -d "$ANDROID_SDK_ROOT/ndk-bundle" ]; then + ANDROID_NDK_ROOT="$ANDROID_SDK_ROOT/ndk-bundle" + elif [ "$UNAME_SYSTEM" = "Darwin" ] && [ -d "$HOME/Library/Android/sdk/ndk-bundle" ]; then + ANDROID_NDK_ROOT="$HOME/Library/Android/sdk/ndk-bundle" + elif [ "$UNAME_SYSTEM" = "Linux" ] && [ -d "$HOME/Android/Sdk/ndk-bundle" ]; then + ANDROID_NDK_ROOT="$HOME/Android/Sdk/ndk-bundle" + fi +fi + CFG_DEFAULT_ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT CFG_DEFAULT_ANDROID_SDK_ROOT=$ANDROID_SDK_ROOT CFG_DEFAULT_ANDROID_PLATFORM=android-16 @@ -1696,9 +1714,11 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; qfsfileengine_win.o \ qlocale_win.o \ qsettings_win.o \ + qoperatingsystemversion_win.o \ qsystemlibrary.o \ registry.o" EXTRA_SRCS="\"\$(SOURCE_PATH)/src/corelib/corelib/io/qfilesystemengine_win.cpp\" \ + \"\$(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp\" \ \"\$(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp\" \ \"\$(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp\" \ \"\$(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp\" \ @@ -1731,12 +1751,12 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; EXTRA_OBJS="$EXTRA_OBJS \ qsettings_mac.o \ qcore_mac.o \ - qcore_mac_objc.o \ + qoperatingsystemversion_darwin.o \ qcore_foundation.o" EXTRA_SRCS="$EXTRA_SRCS \ \"\$(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp\" \ \"\$(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp\" \ - \"\$(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm\" \ + \"\$(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm\" \ \"\$(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm\"" fi diff --git a/configure.json b/configure.json index 85ef23a186..9bdc50c05c 100644 --- a/configure.json +++ b/configure.json @@ -972,6 +972,7 @@ }, "widgets": { "label": "Qt Widgets", + "autoDetect": "!config.tvos && !config.watchos", "condition": "features.gui", "output": [ "privateFeature", diff --git a/examples/opengl/computegles31/Qt-logo-medium.png b/examples/opengl/computegles31/Qt-logo-medium.png Binary files differnew file mode 100644 index 0000000000..a1ca1f1830 --- /dev/null +++ b/examples/opengl/computegles31/Qt-logo-medium.png diff --git a/examples/opengl/computegles31/computegles31.pro b/examples/opengl/computegles31/computegles31.pro new file mode 100644 index 0000000000..5b9d7e4387 --- /dev/null +++ b/examples/opengl/computegles31/computegles31.pro @@ -0,0 +1,9 @@ +HEADERS = $$PWD/glwindow.h + +SOURCES = $$PWD/glwindow.cpp \ + $$PWD/main.cpp + +RESOURCES += computegles31.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/opengl/computegles31 +INSTALLS += target diff --git a/examples/opengl/computegles31/computegles31.qrc b/examples/opengl/computegles31/computegles31.qrc new file mode 100644 index 0000000000..b99eb0a82e --- /dev/null +++ b/examples/opengl/computegles31/computegles31.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>Qt-logo-medium.png</file> + </qresource> +</RCC> diff --git a/examples/opengl/computegles31/glwindow.cpp b/examples/opengl/computegles31/glwindow.cpp new file mode 100644 index 0000000000..d2cea169a1 --- /dev/null +++ b/examples/opengl/computegles31/glwindow.cpp @@ -0,0 +1,423 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "glwindow.h" +#include <QImage> +#include <QOpenGLShaderProgram> +#include <QOpenGLContext> +#include <QOpenGLFunctions> +#include <QOpenGLExtraFunctions> +//#include <QtGui/qopenglext.h> +#include <QtGui/qopengl.h> +#include <QDebug> +#include <QTimer> +#include <math.h> + +#ifndef GL_READ_WRITE +#define GL_READ_WRITE 0x88BA +#endif + +#ifndef GL_RGBA8 +#define GL_RGBA8 0x8058 +#endif + +#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#endif + +GLWindow::GLWindow() + : m_texImageInput(0), + m_texImageTmp(0), + m_texImageProcessed(0), + m_shaderDisplay(0), + m_shaderComputeV(0), + m_shaderComputeH(0), + m_blurRadius(0.0f), + m_animate(true) +{ + const float animationStart = 0.0; + const float animationEnd = 10.0; + const float animationLength = 1000; + + m_animationGroup = new QSequentialAnimationGroup(this); + m_animationGroup->setLoopCount(-1); + + m_animationForward = new QPropertyAnimation(this, QByteArrayLiteral("blurRadius")); + m_animationForward->setStartValue(animationStart); + m_animationForward->setEndValue(animationEnd); + m_animationForward->setDuration(animationLength); + m_animationGroup->addAnimation(m_animationForward); + + m_animationBackward = new QPropertyAnimation(this, QByteArrayLiteral("blurRadius")); + m_animationBackward->setStartValue(animationEnd); + m_animationBackward->setEndValue(animationStart); + m_animationBackward->setDuration(animationLength); + m_animationGroup->addAnimation(m_animationBackward); + + m_animationGroup->start(); +} + +GLWindow::~GLWindow() +{ + makeCurrent(); + delete m_texImageInput; + delete m_texImageProcessed; + delete m_texImageTmp; + delete m_shaderDisplay; + delete m_shaderComputeH; + delete m_shaderComputeV; + delete m_animationGroup; + delete m_animationForward; + delete m_animationBackward; +} + +void GLWindow::setBlurRadius(float blurRadius) +{ + int radius = int(blurRadius); + if (radius != m_blurRadius) { + m_blurRadius = radius; + update(); + } +} + +void GLWindow::setAnimating(bool animate) +{ + m_animate = animate; + if (animate) + m_animationGroup->start(); + else + m_animationGroup->stop(); +} + +void GLWindow::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Space) { // pause + setAnimating(!m_animate); + } + update(); +} + + + + +static const char *vsDisplaySource = + "const vec4 vertices[4] = vec4[4] (\n" + " vec4( -1.0, 1.0, 0.0, 1.0),\n" + " vec4( -1.0, -1.0, 0.0, 1.0),\n" + " vec4( 1.0, 1.0, 0.0, 1.0),\n" + " vec4( 1.0, -1.0, 0.0, 1.0)\n" + ");\n" + "const vec2 texCoords[4] = vec2[4] (\n" + " vec2( 0.0, 1.0),\n" + " vec2( 0.0, 0.0),\n" + " vec2( 1.0, 1.0),\n" + " vec2( 1.0, 0.0)\n" + ");\n" + "out vec2 texCoord;\n" + "uniform mat4 matProjection;\n" + "uniform vec2 imageRatio;\n" + "void main() {\n" + " gl_Position = matProjection * ( vertices[gl_VertexID] * vec4(imageRatio,0,1) );\n" + " texCoord = texCoords[gl_VertexID];\n" + "}\n"; + +static const char *fsDisplaySource = + "in lowp vec2 texCoord; \n" + "uniform sampler2D samImage; \n" + "layout(location = 0) out lowp vec4 color;\n" + "void main() {\n" + " lowp vec4 texColor = texture(samImage,texCoord);\n" + " color = vec4(texColor.rgb, 1.0);\n" + "}\n"; + +static const char *csComputeSourceV = + //"#extension GL_EXT_gpu_shader5 : require \n" + "#define COMPUTEPATCHSIZE 32 \n" + "#define IMGFMT rgba8 \n" + "layout (local_size_x = COMPUTEPATCHSIZE, local_size_y = COMPUTEPATCHSIZE) in;\n" + "layout(binding=0, IMGFMT) uniform highp image2D inputImage; // Use a sampler to improve performance \n" + "layout(binding=1, IMGFMT) uniform highp image2D resultImage;\n" + "uniform int radius;\n" + "const float cutoff = 2.2;\n" + "float sigma = clamp(float(radius) / cutoff,0.02,100.0);\n" // Const initialization with dynamically uniform expressions doesn't work in GLES + "float expFactor = 1.0 / (2.0 * sigma * sigma);\n" // Same here + + "float gaussian(float distance) {\n" + " return exp( -(distance * distance) * expFactor);\n" + "}\n" + + "void main() {\n" + " ivec2 imgSize = imageSize(resultImage);\n" + " int x = int(gl_GlobalInvocationID.x);\n" + " int y = int(gl_GlobalInvocationID.y);\n" + " if ( (x >= imgSize.x) || (y >= imgSize.y) ) return;\n" + " vec4 sumPixels = vec4(0.0);\n" + " float sumWeights = 0.0;\n" + " int left = clamp(x - radius, 0, imgSize.x - 1);\n" + " int right = clamp(x + radius, 0, imgSize.x - 1);\n" + " int top = clamp(y - radius, 0, imgSize.y - 1);\n" + " int bottom = clamp(y + radius, 0, imgSize.y - 1);\n" + " for (int iY = top; iY <= bottom; iY++) {\n" + " float dy = float(abs(iY - y));\n" + " vec4 imgValue = imageLoad(inputImage, ivec2(x,iY));\n" + " float weight = gaussian(dy);\n" + " sumWeights += weight;\n" + " sumPixels += (imgValue * weight);\n" + " }\n" + " sumPixels /= sumWeights;\n" + " imageStore(resultImage, ivec2(x,y), sumPixels);" + "}\n"; + +static const char *csComputeSourceH = + //"#extension GL_EXT_gpu_shader5 : require \n" + "#define COMPUTEPATCHSIZE 32 \n" + "#define IMGFMT rgba8 \n" + "layout (local_size_x = COMPUTEPATCHSIZE, local_size_y = COMPUTEPATCHSIZE) in;\n" + "layout(binding=0, IMGFMT) uniform highp image2D inputImage; // Use a sampler to improve performance \n" + "layout(binding=1, IMGFMT) uniform highp image2D resultImage;\n" + "uniform int radius;\n" + "const float cutoff = 2.2;\n" + "float sigma = clamp(float(radius) / cutoff,0.02,100.0);\n" + "float expFactor = 1.0 / (2.0 * sigma * sigma);\n" + + "float gaussian(float distance) {\n" + " return exp( -(distance * distance) * expFactor);\n" + "}\n" + + "void main() {\n" + " ivec2 imgSize = imageSize(resultImage);\n" + " int x = int(gl_GlobalInvocationID.x);\n" + " int y = int(gl_GlobalInvocationID.y);\n" + " if ( (x >= imgSize.x) || (y >= imgSize.y) ) return;\n" + " vec4 sumPixels = vec4(0.0);\n" + " float sumWeights = 0.0;\n" + " int left = clamp(x - radius, 0, imgSize.x - 1);\n" + " int right = clamp(x + radius, 0, imgSize.x - 1);\n" + " int top = clamp(y - radius, 0, imgSize.y - 1);\n" + " int bottom = clamp(y + radius, 0, imgSize.y - 1);\n" + " for (int iX = left; iX <= right; iX++) {\n" + " float dx = float(abs(iX - x));\n" + " vec4 imgValue = imageLoad(inputImage, ivec2(iX,y));\n" + " float weight = gaussian(dx);\n" + " sumWeights += weight;\n" + " sumPixels += (imgValue * weight);\n" + " }\n" + " sumPixels /= sumWeights;\n" + " imageStore(resultImage, ivec2(x,y), sumPixels);" + "}\n"; + + + +QByteArray versionedShaderCode(const char *src) +{ + QByteArray versionedSrc; + + if (QOpenGLContext::currentContext()->isOpenGLES()) + versionedSrc.append(QByteArrayLiteral("#version 310 es\n")); + else + versionedSrc.append(QByteArrayLiteral("#version 430\n")); + + versionedSrc.append(src); + return versionedSrc; +} + +void computeProjection(int winWidth, int winHeight, int imgWidth, int imgHeight, QMatrix4x4 &outProjection, QSizeF &outQuadSize) +{ + float ratioImg = float(imgWidth) / float(imgHeight); + float ratioCanvas = float(winWidth) / float(winHeight); + + float correction = ratioImg / ratioCanvas; + float rescaleFactor = 1.0f; + float quadWidth = 1.0f; + float quadHeight = 1.0f; + + if (correction < 1.0f) // canvas larger than image -- height = 1.0, vertical black bands + { + quadHeight = 1.0f; + quadWidth = 1.0f * ratioImg; + rescaleFactor = ratioCanvas; + correction = 1.0f / rescaleFactor; + } + else // image larger than canvas -- width = 1.0, horizontal black bands + { + quadWidth = 1.0f; + quadHeight = 1.0f / ratioImg; + correction = 1.0f / ratioCanvas; + } + + const float frustumWidth = 1.0f * rescaleFactor; + const float frustumHeight = 1.0f * rescaleFactor * correction; + + outProjection = QMatrix4x4(); + outProjection.ortho( + -frustumWidth, + frustumWidth, + -frustumHeight, + frustumHeight, + -1.0f, + 1.0f); + outQuadSize = QSizeF(quadWidth,quadHeight); +} + +void GLWindow::initializeGL() +{ + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + qDebug() << "Got a " + << ctx->format().majorVersion() + << "." + << ctx->format().minorVersion() + << ((ctx->format().renderableType() == QSurfaceFormat::OpenGLES) ? (" GLES") : (" GL")) + << " context"; + //QOpenGLFunctions *f = ctx->functions(); + + if (m_texImageInput) { + delete m_texImageInput; + m_texImageInput = 0; + } + QImage img(":/Qt-logo-medium.png"); + Q_ASSERT(!img.isNull()); + m_texImageInput = new QOpenGLTexture(img.convertToFormat(QImage::Format_RGBA8888).mirrored()); + + if (m_texImageTmp) { + delete m_texImageTmp; + m_texImageTmp = 0; + } + m_texImageTmp = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_texImageTmp->setFormat(m_texImageInput->format()); + m_texImageTmp->setSize(m_texImageInput->width(),m_texImageInput->height()); + m_texImageTmp->allocateStorage(QOpenGLTexture::RGBA,QOpenGLTexture::UInt8); // WTF? + + if (m_texImageProcessed) { + delete m_texImageProcessed; + m_texImageProcessed = 0; + } + m_texImageProcessed = new QOpenGLTexture(QOpenGLTexture::Target2D); + m_texImageProcessed->setFormat(m_texImageInput->format()); + m_texImageProcessed->setSize(m_texImageInput->width(),m_texImageInput->height()); + m_texImageProcessed->allocateStorage(QOpenGLTexture::RGBA,QOpenGLTexture::UInt8); + + m_texImageProcessed->setMagnificationFilter(QOpenGLTexture::Linear); + m_texImageProcessed->setMinificationFilter(QOpenGLTexture::Linear); + m_texImageProcessed->setWrapMode(QOpenGLTexture::ClampToEdge); + + if (m_shaderDisplay) { + delete m_shaderDisplay; + m_shaderDisplay = 0; + } + m_shaderDisplay = new QOpenGLShaderProgram; + // Prepend the correct version directive to the sources. The rest is the + // same, thanks to the common GLSL syntax. + m_shaderDisplay->addShaderFromSourceCode(QOpenGLShader::Vertex, versionedShaderCode(vsDisplaySource)); + m_shaderDisplay->addShaderFromSourceCode(QOpenGLShader::Fragment, versionedShaderCode(fsDisplaySource)); + m_shaderDisplay->link(); + + if (m_shaderComputeV) { + delete m_shaderComputeV; + m_shaderComputeV = 0; + } + m_shaderComputeV = new QOpenGLShaderProgram; + m_shaderComputeV->addShaderFromSourceCode(QOpenGLShader::Compute, versionedShaderCode(csComputeSourceV)); + m_shaderComputeV->link(); + + if (m_shaderComputeH) { + delete m_shaderComputeH; + m_shaderComputeH = 0; + } + m_shaderComputeH = new QOpenGLShaderProgram; + m_shaderComputeH->addShaderFromSourceCode(QOpenGLShader::Compute, versionedShaderCode(csComputeSourceH)); + m_shaderComputeH->link(); +} + +void GLWindow::resizeGL(int w, int h) +{ + computeProjection(w,h,m_texImageInput->width(),m_texImageInput->height(),m_proj,m_quadSize); +} + +QSize getWorkGroups(int workGroupSize, const QSize &imageSize) +{ + int x = imageSize.width(); + x = (x % workGroupSize) ? (x / workGroupSize) + 1 : (x / workGroupSize); + int y = imageSize.height(); + y = (y % workGroupSize) ? (y / workGroupSize) + 1 : (y / workGroupSize); + return QSize(x,y); +} + +void GLWindow::paintGL() +{ + // Now use QOpenGLExtraFunctions instead of QOpenGLFunctions as we want to + // do more than what GL(ES) 2.0 offers. + QOpenGLExtraFunctions *f = QOpenGLContext::currentContext()->extraFunctions(); + + + // Process input image + QSize workGroups = getWorkGroups( 32, QSize(m_texImageInput->width(), m_texImageInput->height())); + // Pass 1 + f->glBindImageTexture(0, m_texImageInput->textureId(), 0, 0, 0, GL_READ_WRITE, GL_RGBA8); + f->glBindImageTexture(1, m_texImageTmp->textureId(), 0, 0, 0, GL_READ_WRITE, GL_RGBA8); + m_shaderComputeV->bind(); + m_shaderComputeV->setUniformValue("radius",m_blurRadius); + f->glDispatchCompute(workGroups.width(),workGroups.height(),1); + f->glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + m_shaderComputeV->release(); + // Pass 2 + f->glBindImageTexture(0, m_texImageTmp->textureId(), 0, 0, 0, GL_READ_WRITE, GL_RGBA8); + f->glBindImageTexture(1, m_texImageProcessed->textureId(), 0, 0, 0, GL_READ_WRITE, GL_RGBA8); + m_shaderComputeH->bind(); + m_shaderComputeH->setUniformValue("radius",m_blurRadius); + f->glDispatchCompute(workGroups.width(),workGroups.height(),1); + f->glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT); + m_shaderComputeH->release(); + // Compute cleanup + f->glBindImageTexture(0, 0, 0, 0, 0, GL_READ_WRITE, GL_RGBA8); + f->glBindImageTexture(1, 0, 0, 0, 0, GL_READ_WRITE, GL_RGBA8); + + // Display processed image + f->glClearColor(0, 0, 0, 1); + f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + m_texImageProcessed->bind(GL_TEXTURE0); + m_shaderDisplay->bind(); + m_shaderDisplay->setUniformValue("matProjection",m_proj); + m_shaderDisplay->setUniformValue("imageRatio",m_quadSize); + m_shaderDisplay->setUniformValue("samImage",0); + f->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + m_shaderDisplay->release(); + m_texImageProcessed->release(GL_TEXTURE0); +} + diff --git a/examples/opengl/computegles31/glwindow.h b/examples/opengl/computegles31/glwindow.h new file mode 100644 index 0000000000..a55c5491be --- /dev/null +++ b/examples/opengl/computegles31/glwindow.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef GLWIDGET_H +#define GLWIDGET_H + +#include <QOpenGLWindow> +#include <QOpenGLTexture> +#include <QMatrix4x4> +#include <QVector3D> +#include <QKeyEvent> +#include <QPropertyAnimation> +#include <QSequentialAnimationGroup> +#include <QRectF> + +QT_BEGIN_NAMESPACE + +class QOpenGLTexture; +class QOpenGLShaderProgram; +class QOpenGLBuffer; +class QOpenGLVertexArrayObject; + +QT_END_NAMESPACE + +class GLWindow : public QOpenGLWindow +{ + Q_OBJECT + Q_PROPERTY(float blurRadius READ blurRadius WRITE setBlurRadius) + +public: + GLWindow(); + ~GLWindow(); + + void initializeGL(); + void resizeGL(int w, int h); + void paintGL(); + + float blurRadius() const { return m_blurRadius; } + void setBlurRadius(float blurRadius); + +protected: + void keyPressEvent(QKeyEvent *e) Q_DECL_OVERRIDE; + void setAnimating(bool animate); + +private: + QPropertyAnimation *m_animationForward; + QPropertyAnimation *m_animationBackward; + QSequentialAnimationGroup *m_animationGroup; + QOpenGLTexture *m_texImageInput; + QOpenGLTexture *m_texImageTmp; + QOpenGLTexture *m_texImageProcessed; + QOpenGLShaderProgram *m_shaderDisplay; + QOpenGLShaderProgram *m_shaderComputeV; + QOpenGLShaderProgram *m_shaderComputeH; + QMatrix4x4 m_proj; + QSizeF m_quadSize; + + int m_blurRadius; + bool m_animate; +}; + +#endif diff --git a/examples/opengl/computegles31/main.cpp b/examples/opengl/computegles31/main.cpp new file mode 100644 index 0000000000..ff2a1e622d --- /dev/null +++ b/examples/opengl/computegles31/main.cpp @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QGuiApplication> +#include <QSurfaceFormat> +#include <QOffscreenSurface> +#include <QOpenGLContext> +#include <QDebug> +#include <QPair> +#include "glwindow.h" + +bool OGLSupports(int major, int minor, bool gles = false) +{ + QOpenGLContext ctx; + QSurfaceFormat fmt; + fmt.setVersion(major, minor); + if (gles) + fmt.setRenderableType(QSurfaceFormat::OpenGLES); + else + fmt.setRenderableType(QSurfaceFormat::OpenGL); + + ctx.setFormat(fmt); + ctx.create(); + if (!ctx.isValid()) + return false; + int ctxMajor = ctx.format().majorVersion(); + int ctxMinor = ctx.format().minorVersion(); + bool isGles = (ctx.format().renderableType() == QSurfaceFormat::OpenGLES); + + if (isGles != gles) return false; + if (ctxMajor < major) return false; + if (ctxMajor == major && ctxMinor < minor) + return false; + return true; +} + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + qDebug() << "Support for GL 2.0 "<<( OGLSupports(2,0) ? "yes" : "no"); + qDebug() << "Support for GL 2.1 "<<( OGLSupports(2,1) ? "yes" : "no"); + qDebug() << "Support for GL 3.0 "<<( OGLSupports(3,0) ? "yes" : "no"); + qDebug() << "Support for GL 3.1 "<<( OGLSupports(3,1) ? "yes" : "no"); + qDebug() << "Support for GL 3.2 "<<( OGLSupports(3,2) ? "yes" : "no"); + qDebug() << "Support for GL 3.3 "<<( OGLSupports(3,3) ? "yes" : "no"); + qDebug() << "Support for GL 4.0 "<<( OGLSupports(4,0) ? "yes" : "no"); + qDebug() << "Support for GL 4.1 "<<( OGLSupports(4,1) ? "yes" : "no"); + qDebug() << "Support for GL 4.2 "<<( OGLSupports(4,2) ? "yes" : "no"); + qDebug() << "Support for GL 4.3 "<<( OGLSupports(4,3) ? "yes" : "no"); + qDebug() << "Support for GL 4.4 "<<( OGLSupports(4,4) ? "yes" : "no"); + qDebug() << "Support for GL 4.5 "<<( OGLSupports(4,5) ? "yes" : "no"); + qDebug() << "Support for GLES 2.0 "<<( OGLSupports(2,0,true) ? "yes" : "no"); + qDebug() << "Support for GLES 3.0 "<<( OGLSupports(3,0,true) ? "yes" : "no"); + qDebug() << "Support for GLES 3.1 "<<( OGLSupports(3,1,true) ? "yes" : "no"); + qDebug() << "Support for GLES 3.2 "<<( OGLSupports(3,2,true) ? "yes" : "no"); + + QSurfaceFormat fmt; + fmt.setDepthBufferSize(24); + + // Request OpenGL 4.3 compatibility or OpenGL ES 3.1. + if (OGLSupports(4,3)) { + qDebug("Requesting 4.3 compatibility context"); + fmt.setVersion(4, 3); + fmt.setRenderableType(QSurfaceFormat::OpenGL); + fmt.setProfile(QSurfaceFormat::CompatibilityProfile); + } else if (OGLSupports(3,1,true)) { + qDebug("Requesting 3.1 GLES context"); + fmt.setVersion(3, 1); + fmt.setRenderableType(QSurfaceFormat::OpenGLES); + } else { + qWarning("Error: This system does not support OpenGL Compute Shaders! Exiting."); + return -1; + } + QSurfaceFormat::setDefaultFormat(fmt); + + GLWindow glWindow; + glWindow.showMaximized(); + + return app.exec(); +} diff --git a/examples/opengl/opengl.pro b/examples/opengl/opengl.pro index a102e08733..ef44201494 100644 --- a/examples/opengl/opengl.pro +++ b/examples/opengl/opengl.pro @@ -14,7 +14,8 @@ qtHaveModule(widgets) { qopenglwidget \ cube \ textures \ - hellogles3 + hellogles3 \ + computegles31 } EXAMPLE_FILES += \ diff --git a/examples/widgets/desktop/systray/window.cpp b/examples/widgets/desktop/systray/window.cpp index 518f03d4b5..ac05f16341 100644 --- a/examples/widgets/desktop/systray/window.cpp +++ b/examples/widgets/desktop/systray/window.cpp @@ -161,10 +161,16 @@ void Window::iconActivated(QSystemTrayIcon::ActivationReason reason) void Window::showMessage() { showIconCheckBox->setChecked(true); - QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::MessageIcon( + QSystemTrayIcon::MessageIcon msgIcon = QSystemTrayIcon::MessageIcon( typeComboBox->itemData(typeComboBox->currentIndex()).toInt()); - trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon, + if (msgIcon == QSystemTrayIcon::NoIcon) { + QIcon icon(iconComboBox->itemIcon(iconComboBox->currentIndex())); + trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), icon, durationSpinBox->value() * 1000); + } else { + trayIcon->showMessage(titleEdit->text(), bodyEdit->toPlainText(), msgIcon, + durationSpinBox->value() * 1000); + } } //! [5] @@ -216,6 +222,8 @@ void Window::createMessageGroupBox() typeComboBox->addItem(style()->standardIcon( QStyle::SP_MessageBoxCritical), tr("Critical"), QSystemTrayIcon::Critical); + typeComboBox->addItem(QIcon(), tr("Custom icon"), + QSystemTrayIcon::NoIcon); typeComboBox->setCurrentIndex(1); durationLabel = new QLabel(tr("Duration:")); diff --git a/mkspecs/common/gcc-base-mac.conf b/mkspecs/common/gcc-base-mac.conf index e9bf780ec1..34211b764d 100644 --- a/mkspecs/common/gcc-base-mac.conf +++ b/mkspecs/common/gcc-base-mac.conf @@ -12,12 +12,11 @@ include(gcc-base.conf) QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__=4 __APPLE_CC__ -QMAKE_LFLAGS += -headerpad_max_install_names - QMAKE_LFLAGS_SHLIB += -single_module -dynamiclib QMAKE_LFLAGS_PLUGIN += $$QMAKE_LFLAGS_SHLIB QMAKE_LFLAGS_INCREMENTAL += -undefined suppress -flat_namespace QMAKE_LFLAGS_SONAME += -install_name$${LITERAL_WHITESPACE} +QMAKE_LFLAGS_HEADERPAD += -headerpad_max_install_names QMAKE_LFLAGS_VERSION += -current_version$${LITERAL_WHITESPACE} QMAKE_LFLAGS_COMPAT_VERSION += -compatibility_version$${LITERAL_WHITESPACE} diff --git a/mkspecs/common/ios/clang.conf b/mkspecs/common/ios/clang.conf deleted file mode 100644 index f45b89665f..0000000000 --- a/mkspecs/common/ios/clang.conf +++ /dev/null @@ -1,29 +0,0 @@ -# -# compiler settings for iOS clang compilers -# - -# iOS build flags -QMAKE_IOS_CFLAGS += -fvisibility=hidden -fpascal-strings -fmessage-length=0 -QMAKE_IOS_CFLAGS += -Wno-trigraphs -Wreturn-type -Wparentheses -Wswitch -Wno-unused-parameter -Wunused-variable -Wunused-value -Wno-shorten-64-to-32 -Wno-sign-conversion -QMAKE_IOS_CXXFLAGS += -fvisibility-inlines-hidden - -# Based on the following information, http://clang.llvm.org/doxygen/ObjCRuntime_8h_source.html, -# we can conclude that it's safe to always pass the following flags -QMAKE_IOS_OBJ_CFLAGS += -fobjc-nonfragile-abi -fobjc-legacy-dispatch - -# But these only apply to non-ARM targets -!contains(QT_ARCH, arm): QMAKE_IOS_CFLAGS += -fexceptions -fasm-blocks - -# Clang 3.1 (and above) flags -QMAKE_IOS_CFLAGS += -Wno-missing-field-initializers -Wno-missing-prototypes -Wno-implicit-atomic-properties -Wformat -Wno-missing-braces -Wno-unused-function -Wno-unused-label -Wuninitialized -Wno-unknown-pragmas -Wno-shadow -Wno-four-char-constants -Wno-sign-compare -Wpointer-sign -Wno-newline-eof -Wdeprecated-declarations -Winvalid-offsetof -Wno-conversion -QMAKE_IOS_CXXFLAGS += -Wno-non-virtual-dtor -Wno-overloaded-virtual -Wno-exit-time-destructors -QMAKE_IOS_OBJ_CFLAGS += -Wno-deprecated-implementations -Wprotocol -Wno-selector -Wno-strict-selector-match -Wno-undeclared-selector - -# Set build flags -QMAKE_CFLAGS += $$QMAKE_IOS_CFLAGS -QMAKE_CXXFLAGS += $$QMAKE_IOS_CFLAGS $$QMAKE_IOS_CXXFLAGS -QMAKE_OBJECTIVE_CFLAGS += $$QMAKE_IOS_OBJ_CFLAGS - -QMAKE_IOS_CFLAGS = -QMAKE_IOS_CXXFLAGS = -QMAKE_IOS_OBJ_CFLAGS = diff --git a/mkspecs/common/uikit.conf b/mkspecs/common/uikit.conf index bfbab36db6..de0fb33351 100644 --- a/mkspecs/common/uikit.conf +++ b/mkspecs/common/uikit.conf @@ -3,7 +3,7 @@ # QMAKE_PLATFORM += uikit -CONFIG += bitcode reduce_exports +CONFIG += bitcode reduce_exports shallow_bundle no_qt_rpath INCLUDEPATH += $$PWD/uikit DEFINES += DARWIN_NO_CARBON diff --git a/mkspecs/common/uikit/clang.conf b/mkspecs/common/uikit/clang.conf new file mode 100644 index 0000000000..6b9b7eea8e --- /dev/null +++ b/mkspecs/common/uikit/clang.conf @@ -0,0 +1,7 @@ +# +# compiler settings for iOS/tvOS/watchOS clang compilers +# + +# Based on the following information, http://clang.llvm.org/doxygen/ObjCRuntime_8h_source.html, +# we can conclude that it's safe to always pass the following flags +QMAKE_OBJECTIVE_CFLAGS += -fobjc-nonfragile-abi -fobjc-legacy-dispatch diff --git a/mkspecs/common/ios/qmake.conf b/mkspecs/common/uikit/qmake.conf index daf66ac5ea..e2e166cdad 100644 --- a/mkspecs/common/ios/qmake.conf +++ b/mkspecs/common/uikit/qmake.conf @@ -1,5 +1,5 @@ # -# Common build settings for all iOS configurations +# Common build settings for all iOS/tvOS/watchOS configurations # QT_QPA_DEFAULT_PLATFORM = ios diff --git a/mkspecs/darwin-g++/qmake.conf b/mkspecs/darwin-g++/qmake.conf index 09c55456ec..85955f7af0 100644 --- a/mkspecs/darwin-g++/qmake.conf +++ b/mkspecs/darwin-g++/qmake.conf @@ -56,7 +56,6 @@ QMAKE_LIBDIR_OPENGL = /usr/X11R6/lib QMAKE_LINK = c++ QMAKE_LINK_SHLIB = c++ -QMAKE_LFLAGS += -headerpad_max_install_names QMAKE_LFLAGS = QMAKE_LFLAGS_RELEASE = QMAKE_LFLAGS_DEBUG = @@ -65,6 +64,7 @@ QMAKE_LFLAGS_SHLIB = -prebind -dynamiclib -single_module QMAKE_LFLAGS_PLUGIN = -prebind -bundle QMAKE_LFLAGS_THREAD = QMAKE_LFLAGS_SONAME += -install_name$${LITERAL_WHITESPACE} +QMAKE_LFLAGS_HEADERPAD += -headerpad_max_install_names QMAKE_LFLAGS_VERSION = -current_version$${LITERAL_WHITESPACE} QMAKE_LFLAGS_COMPAT_VERSION = -compatibility_version$${LITERAL_WHITESPACE} diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf index 7bf6b4a716..7e6a845024 100644 --- a/mkspecs/features/mac/default_post.prf +++ b/mkspecs/features/mac/default_post.prf @@ -24,6 +24,15 @@ qt { } } +# Add the same default rpaths as Xcode does for new projects. +# This is especially important for iOS/tvOS/watchOS where no other option is possible. +!no_default_rpath { + QMAKE_RPATHDIR += @executable_path/Frameworks + equals(TEMPLATE, lib):!plugin:lib_bundle: QMAKE_RPATHDIR += @loader_path/Frameworks +} + +!bitcode: QMAKE_LFLAGS += $$QMAKE_LFLAGS_HEADERPAD + macx-xcode:!isEmpty(QMAKE_XCODE_DEBUG_INFORMATION_FORMAT) { debug_information_format.name = DEBUG_INFORMATION_FORMAT debug_information_format.value = $$QMAKE_XCODE_DEBUG_INFORMATION_FORMAT diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index bd54565e01..e58e452620 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -244,13 +244,13 @@ contains(qt_module_deps, qml): \ # copy qml files. this part is platform spesific. mac { - osx { + !shallow_bundle { # Note: user can override QMAKE_BUNDLE_QML from pro file to change target bundle path isEmpty(QMAKE_QML_BUNDLE_PATH):QMAKE_QML_BUNDLE_PATH = "Resources/qt_qml" qmlTargetPath = $$OUT_PWD/$${TARGET}.app/Contents/$$QMAKE_QML_BUNDLE_PATH qtconfTargetPath = $$OUT_PWD/$${TARGET}.app/Contents/Resources/qt.conf } else { - # iOS: flat bundle layout (no Contents/Resources) + # shallow bundle layout (no Contents/Resources) isEmpty(QMAKE_QML_BUNDLE_PATH):QMAKE_QML_BUNDLE_PATH = "qt_qml" qmlTargetPath = $CODESIGNING_FOLDER_PATH/$$QMAKE_QML_BUNDLE_PATH qtconfTargetPath = $CODESIGNING_FOLDER_PATH/qt.conf diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 708815d9f9..0f43af10ed 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -33,11 +33,13 @@ defineReplace(qtRelativeRPathBase) { darwin { if(equals(TEMPLATE, app):app_bundle)|\ if(equals(TEMPLATE, lib):plugin:plugin_bundle) { - ios: return($$target.path/$${TARGET}.app) + shallow_bundle: return($$target.path/$${TARGET}.app) return($$target.path/$${TARGET}.app/Contents/MacOS) } - equals(TEMPLATE, lib):!plugin:lib_bundle: \ + equals(TEMPLATE, lib):!plugin:lib_bundle { + shallow_bundle: return($$target.path/$${TARGET}.framework) return($$target.path/$${TARGET}.framework/Versions/Current) + } } return($$target.path) } diff --git a/mkspecs/features/resolve_target.prf b/mkspecs/features/resolve_target.prf index 629a02a4f3..8678c33ecd 100644 --- a/mkspecs/features/resolve_target.prf +++ b/mkspecs/features/resolve_target.prf @@ -32,7 +32,17 @@ win32 { mac { equals(TEMPLATE, lib) { - lib_bundle { + plugin:plugin_bundle { + !isEmpty(QMAKE_PLUGIN_BUNDLE_NAME): \ + plugin_target = $$QMAKE_PLUGIN_BUNDLE_NAME + else: \ + plugin_target = $$TARGET + QMAKE_RESOLVED_BUNDLE = $${QMAKE_RESOLVED_TARGET}$${plugin_target}.plugin + !shallow_bundle: \ + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_BUNDLE}/Contents/MacOS/$${TARGET} + else: \ + QMAKE_RESOLVED_TARGET = $${QMAKE_RESOLVED_BUNDLE}$${TARGET} + } else: !plugin:lib_bundle { !isEmpty(QMAKE_FRAMEWORK_BUNDLE_NAME): \ framework_target = $$QMAKE_FRAMEWORK_BUNDLE_NAME else: \ diff --git a/mkspecs/macx-clang-32/Info.plist.app b/mkspecs/macx-clang-32/Info.plist.app deleted file mode 100644 index 8e44bd7f60..0000000000 --- a/mkspecs/macx-clang-32/Info.plist.app +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>NSPrincipalClass</key> - <string>NSApplication</string> - <key>CFBundleIconFile</key> - <string>@ICON@</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>This file was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-clang-32/Info.plist.dSYM.in b/mkspecs/macx-clang-32/Info.plist.dSYM.in deleted file mode 100644 index a8c8d0d4fb..0000000000 --- a/mkspecs/macx-clang-32/Info.plist.dSYM.in +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version=\"1.0\" encoding=\"UTF-8\"?> -<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> -<plist version=\"1.0\"> - <dict> - <key>CFBundleIdentifier</key> - <string>com.apple.xcode.dsym.$${BUNDLEIDENTIFIER}</string> - <key>CFBundlePackageType</key> - <string>dSYM</string> - <key>CFBundleSignature</key> - <string>????</string> -!!IF !isEmpty(VERSION) - <key>CFBundleShortVersionString</key> - <string>$${VER_MAJ}.$${VER_MIN}</string> - <key>CFBundleVersion</key> - <string>$${VER_MAJ}.$${VER_MIN}.$${VER_PAT}</string> -!!ENDIF - </dict> -</plist> diff --git a/mkspecs/macx-clang-32/Info.plist.lib b/mkspecs/macx-clang-32/Info.plist.lib deleted file mode 100644 index 7cbdb9af12..0000000000 --- a/mkspecs/macx-clang-32/Info.plist.lib +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundlePackageType</key> - <string>FMWK</string> - <key>CFBundleShortVersionString</key> - <string>@SHORT_VERSION@</string> - <key>CFBundleVersion</key> - <string>@FULL_VERSION@</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@LIBRARY@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-clang-32/qmake.conf b/mkspecs/macx-clang-32/qmake.conf deleted file mode 100644 index ba3c7cab6c..0000000000 --- a/mkspecs/macx-clang-32/qmake.conf +++ /dev/null @@ -1,16 +0,0 @@ -# -# qmake configuration for 32-bit Clang on OS X -# - -include(../common/macx.conf) -include(../common/gcc-base-mac.conf) -include(../common/clang.conf) -include(../common/clang-mac.conf) - -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 - -QMAKE_CFLAGS += -arch i386 -QMAKE_CXXFLAGS += -arch i386 -QMAKE_LFLAGS += -arch i386 - -load(qt_config) diff --git a/mkspecs/macx-clang-32/qplatformdefs.h b/mkspecs/macx-clang-32/qplatformdefs.h deleted file mode 100644 index 063491dd90..0000000000 --- a/mkspecs/macx-clang-32/qplatformdefs.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../common/mac/qplatformdefs.h" - diff --git a/mkspecs/macx-clang/qmake.conf b/mkspecs/macx-clang/qmake.conf index 4d56d771a1..b78f249f65 100644 --- a/mkspecs/macx-clang/qmake.conf +++ b/mkspecs/macx-clang/qmake.conf @@ -2,11 +2,11 @@ # qmake configuration for Clang on OS X # +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 + include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 - load(qt_config) diff --git a/mkspecs/macx-g++-32/Info.plist.app b/mkspecs/macx-g++-32/Info.plist.app deleted file mode 100644 index 8e44bd7f60..0000000000 --- a/mkspecs/macx-g++-32/Info.plist.app +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>NSPrincipalClass</key> - <string>NSApplication</string> - <key>CFBundleIconFile</key> - <string>@ICON@</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>This file was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-g++-32/Info.plist.dSYM.in b/mkspecs/macx-g++-32/Info.plist.dSYM.in deleted file mode 100644 index a8c8d0d4fb..0000000000 --- a/mkspecs/macx-g++-32/Info.plist.dSYM.in +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version=\"1.0\" encoding=\"UTF-8\"?> -<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> -<plist version=\"1.0\"> - <dict> - <key>CFBundleIdentifier</key> - <string>com.apple.xcode.dsym.$${BUNDLEIDENTIFIER}</string> - <key>CFBundlePackageType</key> - <string>dSYM</string> - <key>CFBundleSignature</key> - <string>????</string> -!!IF !isEmpty(VERSION) - <key>CFBundleShortVersionString</key> - <string>$${VER_MAJ}.$${VER_MIN}</string> - <key>CFBundleVersion</key> - <string>$${VER_MAJ}.$${VER_MIN}.$${VER_PAT}</string> -!!ENDIF - </dict> -</plist> diff --git a/mkspecs/macx-g++-32/Info.plist.lib b/mkspecs/macx-g++-32/Info.plist.lib deleted file mode 100644 index 7cbdb9af12..0000000000 --- a/mkspecs/macx-g++-32/Info.plist.lib +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundlePackageType</key> - <string>FMWK</string> - <key>CFBundleShortVersionString</key> - <string>@SHORT_VERSION@</string> - <key>CFBundleVersion</key> - <string>@FULL_VERSION@</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@LIBRARY@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-g++-32/qmake.conf b/mkspecs/macx-g++-32/qmake.conf deleted file mode 100644 index 3cd707d537..0000000000 --- a/mkspecs/macx-g++-32/qmake.conf +++ /dev/null @@ -1,23 +0,0 @@ -#macx-g++ (different from g++.conf) - -# -# qmake configuration for macx-g++ -# -# OS X + command-line compiler -# - -MAKEFILE_GENERATOR = UNIX -CONFIG += app_bundle incremental global_init_link_order lib_version_first -QMAKE_INCREMENTAL_STYLE = sublib - -include(../common/macx.conf) -include(../common/gcc-base-mac.conf) -include(../common/g++-macx.conf) - -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 - -QMAKE_CFLAGS += -arch i386 -QMAKE_CXXFLAGS += -arch i386 -QMAKE_LFLAGS += -arch i386 - -load(qt_config) diff --git a/mkspecs/macx-g++-32/qplatformdefs.h b/mkspecs/macx-g++-32/qplatformdefs.h deleted file mode 100644 index 063491dd90..0000000000 --- a/mkspecs/macx-g++-32/qplatformdefs.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../common/mac/qplatformdefs.h" - diff --git a/mkspecs/macx-g++/qmake.conf b/mkspecs/macx-g++/qmake.conf index 5b3105c668..880cc7d930 100644 --- a/mkspecs/macx-g++/qmake.conf +++ b/mkspecs/macx-g++/qmake.conf @@ -10,10 +10,10 @@ MAKEFILE_GENERATOR = UNIX CONFIG += app_bundle incremental global_init_link_order lib_version_first QMAKE_INCREMENTAL_STYLE = sublib +QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 + include(../common/macx.conf) include(../common/gcc-base-mac.conf) include(../common/g++-macx.conf) -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 - load(qt_config) diff --git a/mkspecs/macx-g++40/Info.plist.app b/mkspecs/macx-g++40/Info.plist.app deleted file mode 100644 index 8e44bd7f60..0000000000 --- a/mkspecs/macx-g++40/Info.plist.app +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>NSPrincipalClass</key> - <string>NSApplication</string> - <key>CFBundleIconFile</key> - <string>@ICON@</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>This file was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-g++40/Info.plist.dSYM.in b/mkspecs/macx-g++40/Info.plist.dSYM.in deleted file mode 100644 index a8c8d0d4fb..0000000000 --- a/mkspecs/macx-g++40/Info.plist.dSYM.in +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version=\"1.0\" encoding=\"UTF-8\"?> -<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> -<plist version=\"1.0\"> - <dict> - <key>CFBundleIdentifier</key> - <string>com.apple.xcode.dsym.$${BUNDLEIDENTIFIER}</string> - <key>CFBundlePackageType</key> - <string>dSYM</string> - <key>CFBundleSignature</key> - <string>????</string> -!!IF !isEmpty(VERSION) - <key>CFBundleShortVersionString</key> - <string>$${VER_MAJ}.$${VER_MIN}</string> - <key>CFBundleVersion</key> - <string>$${VER_MAJ}.$${VER_MIN}.$${VER_PAT}</string> -!!ENDIF - </dict> -</plist> diff --git a/mkspecs/macx-g++40/Info.plist.lib b/mkspecs/macx-g++40/Info.plist.lib deleted file mode 100644 index 7cbdb9af12..0000000000 --- a/mkspecs/macx-g++40/Info.plist.lib +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundlePackageType</key> - <string>FMWK</string> - <key>CFBundleShortVersionString</key> - <string>@SHORT_VERSION@</string> - <key>CFBundleVersion</key> - <string>@FULL_VERSION@</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@LIBRARY@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-g++40/qmake.conf b/mkspecs/macx-g++40/qmake.conf deleted file mode 100644 index 308cc2007c..0000000000 --- a/mkspecs/macx-g++40/qmake.conf +++ /dev/null @@ -1,27 +0,0 @@ -#macx-g++ (different from g++.conf) - -# -# qmake configuration for macx-g++ -# -# OS X + command-line compiler -# - -MAKEFILE_GENERATOR = UNIX -CONFIG += app_bundle incremental global_init_link_order lib_version_first -QMAKE_INCREMENTAL_STYLE = sublib - -include(../common/macx.conf) -include(../common/gcc-base-mac.conf) -include(../common/g++-macx.conf) - -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 - -QMAKE_CC = gcc-4.0 -QMAKE_CXX = g++-4.0 - -QMAKE_LINK = $$QMAKE_CXX -QMAKE_LINK_SHLIB = $$QMAKE_CXX -QMAKE_LINK_C = $$QMAKE_CC -QMAKE_LINK_C_SHLIB = $$QMAKE_CC - -load(qt_config) diff --git a/mkspecs/macx-g++40/qplatformdefs.h b/mkspecs/macx-g++40/qplatformdefs.h deleted file mode 100644 index 063491dd90..0000000000 --- a/mkspecs/macx-g++40/qplatformdefs.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../common/mac/qplatformdefs.h" - diff --git a/mkspecs/macx-g++42/Info.plist.app b/mkspecs/macx-g++42/Info.plist.app deleted file mode 100644 index 8e44bd7f60..0000000000 --- a/mkspecs/macx-g++42/Info.plist.app +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>NSPrincipalClass</key> - <string>NSApplication</string> - <key>CFBundleIconFile</key> - <string>@ICON@</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>This file was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-g++42/Info.plist.dSYM.in b/mkspecs/macx-g++42/Info.plist.dSYM.in deleted file mode 100644 index a8c8d0d4fb..0000000000 --- a/mkspecs/macx-g++42/Info.plist.dSYM.in +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version=\"1.0\" encoding=\"UTF-8\"?> -<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> -<plist version=\"1.0\"> - <dict> - <key>CFBundleIdentifier</key> - <string>com.apple.xcode.dsym.$${BUNDLEIDENTIFIER}</string> - <key>CFBundlePackageType</key> - <string>dSYM</string> - <key>CFBundleSignature</key> - <string>????</string> -!!IF !isEmpty(VERSION) - <key>CFBundleShortVersionString</key> - <string>$${VER_MAJ}.$${VER_MIN}</string> - <key>CFBundleVersion</key> - <string>$${VER_MAJ}.$${VER_MIN}.$${VER_PAT}</string> -!!ENDIF - </dict> -</plist> diff --git a/mkspecs/macx-g++42/Info.plist.lib b/mkspecs/macx-g++42/Info.plist.lib deleted file mode 100644 index 7cbdb9af12..0000000000 --- a/mkspecs/macx-g++42/Info.plist.lib +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundlePackageType</key> - <string>FMWK</string> - <key>CFBundleShortVersionString</key> - <string>@SHORT_VERSION@</string> - <key>CFBundleVersion</key> - <string>@FULL_VERSION@</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@LIBRARY@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-g++42/qmake.conf b/mkspecs/macx-g++42/qmake.conf deleted file mode 100644 index b24cb7f3f3..0000000000 --- a/mkspecs/macx-g++42/qmake.conf +++ /dev/null @@ -1,27 +0,0 @@ -#macx-g++ (different from g++.conf) - -# -# qmake configuration for macx-g++ -# -# OS X + command-line compiler -# - -MAKEFILE_GENERATOR = UNIX -CONFIG += app_bundle incremental global_init_link_order lib_version_first -QMAKE_INCREMENTAL_STYLE = sublib - -include(../common/macx.conf) -include(../common/gcc-base-mac.conf) -include(../common/g++-macx.conf) - -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 - -QMAKE_CC = gcc-4.2 -QMAKE_CXX = g++-4.2 - -QMAKE_LINK = $$QMAKE_CXX -QMAKE_LINK_SHLIB = $$QMAKE_CXX -QMAKE_LINK_C = $$QMAKE_CC -QMAKE_LINK_C_SHLIB = $$QMAKE_CC - -load(qt_config) diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf index 35e55f799e..990f3b39ee 100644 --- a/mkspecs/macx-icc/qmake.conf +++ b/mkspecs/macx-icc/qmake.conf @@ -64,13 +64,14 @@ QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG QMAKE_LINK = icpc QMAKE_LINK_SHLIB = icpc -QMAKE_LFLAGS = -headerpad_max_install_names +QMAKE_LFLAGS = QMAKE_LFLAGS_RELEASE = QMAKE_LFLAGS_DEBUG = QMAKE_LFLAGS_SHLIB = -single_module -dynamiclib QMAKE_LFLAGS_INCREMENTAL = -undefined suppress -flat_namespace QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB QMAKE_LFLAGS_SONAME = -install_name$${LITERAL_WHITESPACE} +QMAKE_LFLAGS_HEADERPAD = -headerpad_max_install_names QMAKE_LFLAGS_THREAD = QMAKE_LFLAGS_RPATH = -Wl,-rpath, QMAKE_LFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG diff --git a/mkspecs/macx-ios-clang/qmake.conf b/mkspecs/macx-ios-clang/qmake.conf index e21445deb7..3f6d133a76 100644 --- a/mkspecs/macx-ios-clang/qmake.conf +++ b/mkspecs/macx-ios-clang/qmake.conf @@ -14,7 +14,7 @@ include(../common/ios.conf) include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) -include(../common/ios/clang.conf) -include(../common/ios/qmake.conf) +include(../common/uikit/clang.conf) +include(../common/uikit/qmake.conf) load(qt_config) diff --git a/mkspecs/macx-llvm/Info.plist.app b/mkspecs/macx-llvm/Info.plist.app deleted file mode 100644 index 8e44bd7f60..0000000000 --- a/mkspecs/macx-llvm/Info.plist.app +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>NSPrincipalClass</key> - <string>NSApplication</string> - <key>CFBundleIconFile</key> - <string>@ICON@</string> - <key>CFBundlePackageType</key> - <string>APPL</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@EXECUTABLE@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>This file was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-llvm/Info.plist.dSYM.in b/mkspecs/macx-llvm/Info.plist.dSYM.in deleted file mode 100644 index a8c8d0d4fb..0000000000 --- a/mkspecs/macx-llvm/Info.plist.dSYM.in +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version=\"1.0\" encoding=\"UTF-8\"?> -<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> -<plist version=\"1.0\"> - <dict> - <key>CFBundleIdentifier</key> - <string>com.apple.xcode.dsym.$${BUNDLEIDENTIFIER}</string> - <key>CFBundlePackageType</key> - <string>dSYM</string> - <key>CFBundleSignature</key> - <string>????</string> -!!IF !isEmpty(VERSION) - <key>CFBundleShortVersionString</key> - <string>$${VER_MAJ}.$${VER_MIN}</string> - <key>CFBundleVersion</key> - <string>$${VER_MAJ}.$${VER_MIN}.$${VER_PAT}</string> -!!ENDIF - </dict> -</plist> diff --git a/mkspecs/macx-llvm/Info.plist.lib b/mkspecs/macx-llvm/Info.plist.lib deleted file mode 100644 index 7cbdb9af12..0000000000 --- a/mkspecs/macx-llvm/Info.plist.lib +++ /dev/null @@ -1,22 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> -<plist version="1.0"> -<dict> - <key>CFBundlePackageType</key> - <string>FMWK</string> - <key>CFBundleShortVersionString</key> - <string>@SHORT_VERSION@</string> - <key>CFBundleVersion</key> - <string>@FULL_VERSION@</string> - <key>CFBundleGetInfoString</key> - <string>Created by Qt/QMake</string> - <key>CFBundleSignature</key> - <string>@TYPEINFO@</string> - <key>CFBundleExecutable</key> - <string>@LIBRARY@</string> - <key>CFBundleIdentifier</key> - <string>@BUNDLEIDENTIFIER@</string> - <key>NOTE</key> - <string>Please, do NOT change this file -- It was generated by Qt/QMake.</string> -</dict> -</plist> diff --git a/mkspecs/macx-llvm/qmake.conf b/mkspecs/macx-llvm/qmake.conf deleted file mode 100644 index 0434d29b50..0000000000 --- a/mkspecs/macx-llvm/qmake.conf +++ /dev/null @@ -1,26 +0,0 @@ -#macx-g++ (different from g++.conf) - -# -# qmake configuration for macx-g++ -# -# OS X + command-line compiler -# - -MAKEFILE_GENERATOR = UNIX -CONFIG += app_bundle incremental global_init_link_order lib_version_first -QMAKE_INCREMENTAL_STYLE = sublib - -include(../common/macx.conf) -include(../common/gcc-base-mac.conf) -include(../common/llvm.conf) - -QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.9 - -QMAKE_XCODE_GCC_VERSION = com.apple.compilers.llvmgcc42 - -QMAKE_OBJCFLAGS_PRECOMPILE = -x objective-c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_OBJCFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE -QMAKE_OBJCXXFLAGS_PRECOMPILE = -x objective-c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} -QMAKE_OBJCXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE - -load(qt_config) diff --git a/mkspecs/macx-llvm/qplatformdefs.h b/mkspecs/macx-llvm/qplatformdefs.h deleted file mode 100644 index 063491dd90..0000000000 --- a/mkspecs/macx-llvm/qplatformdefs.h +++ /dev/null @@ -1,41 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/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 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "../common/mac/qplatformdefs.h" - diff --git a/mkspecs/macx-tvos-clang/qmake.conf b/mkspecs/macx-tvos-clang/qmake.conf index e945cc9d28..d233f5b7b3 100644 --- a/mkspecs/macx-tvos-clang/qmake.conf +++ b/mkspecs/macx-tvos-clang/qmake.conf @@ -4,8 +4,6 @@ QMAKE_TVOS_DEPLOYMENT_TARGET = 9.1 -INCLUDEPATH += $$PWD/tvos - QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 3 QMAKE_APPLE_DEVICE_ARCHS = arm64 @@ -15,7 +13,7 @@ include(../common/tvos.conf) include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) -include(../common/ios/clang.conf) -include(../common/ios/qmake.conf) +include(../common/uikit/clang.conf) +include(../common/uikit/qmake.conf) load(qt_config) diff --git a/mkspecs/macx-watchos-clang/qmake.conf b/mkspecs/macx-watchos-clang/qmake.conf index 03c05ad717..f68848d1e7 100644 --- a/mkspecs/macx-watchos-clang/qmake.conf +++ b/mkspecs/macx-watchos-clang/qmake.conf @@ -4,8 +4,6 @@ QMAKE_WATCHOS_DEPLOYMENT_TARGET = 2.2 -INCLUDEPATH += $$PWD/watchos - QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 4 QMAKE_APPLE_DEVICE_ARCHS = armv7k @@ -15,7 +13,7 @@ include(../common/watchos.conf) include(../common/gcc-base-mac.conf) include(../common/clang.conf) include(../common/clang-mac.conf) -include(../common/ios/clang.conf) -include(../common/ios/qmake.conf) +include(../common/uikit/clang.conf) +include(../common/uikit/qmake.conf) load(qt_config) diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix index ffbd0d4545..b9c967c3c7 100644 --- a/qmake/Makefile.unix +++ b/qmake/Makefile.unix @@ -18,7 +18,7 @@ QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtext qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \ 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 \ + qcryptographichash.o qxmlstream.o qxmlutils.o qlogging.o qoperatingsystemversion.o \ qjson.o qjsondocument.o qjsonparser.o qjsonarray.o qjsonobject.o qjsonvalue.o \ $(QTOBJS) @@ -272,6 +272,15 @@ qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp qcore_mac.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp +qoperatingsystemversion.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp + +qoperatingsystemversion_win.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp + +qoperatingsystemversion_darwin.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm + $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm + qcore_mac_objc.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32 index fc225ff098..971b6db84d 100644 --- a/qmake/Makefile.win32 +++ b/qmake/Makefile.win32 @@ -105,6 +105,8 @@ QTOBJS= \ qlocale_win.obj \ qmalloc.obj \ qmap.obj \ + qoperatingsystemversion.obj \ + qoperatingsystemversion_win.obj \ qregexp.obj \ qtextcodec.obj \ qutfcodec.obj \ diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 85a5ba56c3..e602734155 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1113,6 +1113,8 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) } bool copyBundleResources = project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app"; ProStringList bundle_resources_files; + ProStringList embedded_frameworks; + QMap<ProString, ProStringList> embedded_plugins; // Copy Bundle Data if (!project->isEmpty("QMAKE_BUNDLE_DATA")) { ProStringList bundle_file_refs; @@ -1123,6 +1125,11 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) for(int i = 0; i < bundle_data.count(); i++) { ProStringList bundle_files; ProString path = project->first(ProKey(bundle_data[i] + ".path")); + const bool isEmbeddedFramework = ((!osx && path == QLatin1String("Frameworks")) + || (osx && path == QLatin1String("Contents/Frameworks"))); + const ProString pluginsPrefix = ProString(osx ? QLatin1String("Contents/PlugIns") : QLatin1String("PlugIns")); + const bool isEmbeddedPlugin = (path == pluginsPrefix) || path.startsWith(pluginsPrefix + "/"); + //all files const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files")); for(int file = 0; file < files.count(); file++) { @@ -1140,19 +1147,29 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) bundle_files += file_key; t << "\t\t" << file_key << " = {\n" << "\t\t\t" << writeSettings("fileRef", file_ref_key) << ";\n" - << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";\n" - << "\t\t};\n"; + << "\t\t\t" << writeSettings("isa", "PBXBuildFile", SettingsNoQuote) << ";\n"; + if (isEmbeddedFramework || isEmbeddedPlugin || name.endsWith(".dylib") || name.endsWith(".framework")) + t << "\t\t\t" << writeSettings("settings", "{ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }", SettingsNoQuote) << ";\n"; + t << "\t\t};\n"; } if (copyBundleResources && ((!osx && path.isEmpty()) || (osx && path == QLatin1String("Contents/Resources")))) { for (const ProString &s : qAsConst(bundle_files)) bundle_resources_files << s; + } else if (copyBundleResources && isEmbeddedFramework) { + for (const ProString &s : qAsConst(bundle_files)) + embedded_frameworks << s; + } else if (copyBundleResources && isEmbeddedPlugin) { + for (const ProString &s : qAsConst(bundle_files)) { + ProString subpath = (path == pluginsPrefix) ? ProString() : path.mid(pluginsPrefix.size() + 1); + embedded_plugins[subpath] << s; + } } else { QString phase_key = keyFor("QMAKE_PBX_BUNDLE_COPY." + bundle_data[i]); - if (!project->isEmpty(ProKey(bundle_data[i] + ".version"))) { - //### - } + //if (!project->isActiveConfig("shallow_bundle") + // && !project->isEmpty(ProKey(bundle_data[i] + ".version"))) { + //} project->values("QMAKE_PBX_BUILDPHASES").append(phase_key); t << "\t\t" << phase_key << " = {\n" @@ -1196,6 +1213,35 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("name", grp) << ";\n" << "\t\t};\n"; + + QString grp2("Embed Frameworks"), key2 = keyFor(grp2); + project->values("QMAKE_PBX_BUILDPHASES").append(key2); + t << "\t\t" << key2 << " = {\n" + << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("dstPath", "") << ";\n" + << "\t\t\t" << writeSettings("dstSubfolderSpec", "10", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("files", embedded_frameworks, SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("name", grp2) << ";\n" + << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" + << "\t\t};\n"; + + QMapIterator<ProString, ProStringList> it(embedded_plugins); + while (it.hasNext()) { + it.next(); + QString suffix = !it.key().isEmpty() ? (" (" + it.key() + ")") : QString(); + QString grp3("Embed PlugIns" + suffix), key3 = keyFor(grp3); + project->values("QMAKE_PBX_BUILDPHASES").append(key3); + t << "\t\t" << key3 << " = {\n" + << "\t\t\t" << writeSettings("isa", "PBXCopyFilesBuildPhase", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("buildActionMask", "2147483647", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("dstPath", it.key()) << ";\n" + << "\t\t\t" << writeSettings("dstSubfolderSpec", "13", SettingsNoQuote) << ";\n" + << "\t\t\t" << writeSettings("files", it.value(), SettingsAsList, 4) << ";\n" + << "\t\t\t" << writeSettings("name", grp3) << ";\n" + << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" + << "\t\t};\n"; + } } //REFERENCE @@ -1515,9 +1561,15 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) plist_in_text.replace(QLatin1String("@ICON@"), (project->isEmpty("ICON") ? QString("") : project->first("ICON").toQString().section(Option::dir_sep, -1))); if (project->first("TEMPLATE") == "app") { - plist_in_text.replace(QLatin1String("@EXECUTABLE@"), project->first("QMAKE_ORIG_TARGET").toQString()); + ProString app_bundle_name = project->first("QMAKE_APPLICATION_BUNDLE_NAME"); + if (app_bundle_name.isEmpty()) + app_bundle_name = project->first("QMAKE_ORIG_TARGET"); + plist_in_text.replace(QLatin1String("@EXECUTABLE@"), app_bundle_name.toQString()); } else { - plist_in_text.replace(QLatin1String("@LIBRARY@"), project->first("QMAKE_ORIG_TARGET").toQString()); + ProString lib_bundle_name = project->first("QMAKE_FRAMEWORK_BUNDLE_NAME"); + if (lib_bundle_name.isEmpty()) + lib_bundle_name = project->first("QMAKE_ORIG_TARGET"); + plist_in_text.replace(QLatin1String("@LIBRARY@"), lib_bundle_name.toQString()); } QString bundlePrefix = project->first("QMAKE_TARGET_BUNDLE_PREFIX").toQString(); if (bundlePrefix.isEmpty()) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 349dcd2f40..794d04a6e9 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -599,10 +599,13 @@ UnixMakefileGenerator::defaultInstall(const QString &t) plain_targ = escapeFilePath(plain_targ); if (bundle != NoBundle) { QString suffix; - if (project->first("TEMPLATE") == "lib") - suffix = "/Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/$(TARGET)"; - else + if (project->first("TEMPLATE") == "lib") { + if (!project->isActiveConfig("shallow_bundle")) + suffix += "/Versions/" + project->first("QMAKE_FRAMEWORK_VERSION"); + suffix += "/$(TARGET)"; + } else { suffix = "/" + project->first("QMAKE_BUNDLE_LOCATION") + "/$(QMAKE_TARGET)"; + } dst_targ += suffix; if (bundle == SolidBundle) { if (!ret.isEmpty()) diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index 6fa355390f..3d12ffd65c 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -596,9 +596,10 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << var("QMAKE_LINK_SHLIB_CMD") << "\n\t" << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGETD)`\"", false) << "\n\t" << "-$(MOVE) $(TARGET) $(DESTDIR)$(TARGETD)\n\t" - << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGET0)`\"", false) << "\n\t" - << varGlue("QMAKE_LN_SHLIB", "-", " ", - " Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t"; + << mkdir_p_asstring("\"`dirname $(DESTDIR)$(TARGET0)`\"", false) << "\n\t"; + if (!project->isActiveConfig("shallow_bundle")) + t << varGlue("QMAKE_LN_SHLIB", "-", " ", + " Versions/Current/$(TARGET) $(DESTDIR)$(TARGET0)") << "\n\t"; if(!project->isEmpty("QMAKE_POST_LINK")) t << "\n\t" << var("QMAKE_POST_LINK"); t << endl << endl; @@ -777,10 +778,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) } else { info_plist = escapeFilePath(fileFixify(info_plist)); } - bool isFramework = project->first("TEMPLATE") == "lib" && project->isActiveConfig("lib_bundle"); + bool isFramework = project->first("TEMPLATE") == "lib" + && !project->isActiveConfig("plugin") + && project->isActiveConfig("lib_bundle"); + bool isShallowBundle = project->isActiveConfig("shallow_bundle"); QString info_plist_out = bundle_dir + - (isFramework ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/Info.plist") - : "Contents/Info.plist"); + (!isShallowBundle + ? (isFramework + ? ("Versions/" + project->first("QMAKE_FRAMEWORK_VERSION") + "/Resources/") + : "Contents/") + : QString()) + + "Info.plist"; bundledFiles << info_plist_out; alldeps << info_plist_out; QString destdir = info_plist_out.section(Option::dir_sep, 0, -2); @@ -814,14 +822,22 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) commonSedArgs << "-e \"s,@BUNDLEIDENTIFIER@," << bundleIdentifier << ",g\" "; if (!isFramework) { + ProString app_bundle_name = var("QMAKE_APPLICATION_BUNDLE_NAME"); + if (app_bundle_name.isEmpty()) + app_bundle_name = var("QMAKE_ORIG_TARGET"); + + ProString plugin_bundle_name = var("QMAKE_PLUGIN_BUNDLE_NAME"); + if (plugin_bundle_name.isEmpty()) + plugin_bundle_name = var("QMAKE_ORIG_TARGET"); + QString icon = fileFixify(var("ICON")); t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@sed "; for (const ProString &arg : qAsConst(commonSedArgs)) t << arg; t << "-e \"s,@ICON@," << icon.section(Option::dir_sep, -1) << ",g\" " - << "-e \"s,@EXECUTABLE@," << var("QMAKE_ORIG_TARGET") << ",g\" " - << "-e \"s,@LIBRARY@," << var("QMAKE_ORIG_TARGET") << ",g\" " + << "-e \"s,@EXECUTABLE@," << app_bundle_name << ",g\" " + << "-e \"s,@LIBRARY@," << plugin_bundle_name << ",g\" " << "-e \"s,@TYPEINFO@,"<< (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" " << "" << info_plist << " >" << info_plist_out << endl; @@ -838,12 +854,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "@$(COPY_FILE) " << escapeFilePath(icon) << ' ' << icon_path_f << endl; } } else { - symlinks[bundle_dir + "Resources"] = "Versions/Current/Resources"; + ProString lib_bundle_name = var("QMAKE_FRAMEWORK_BUNDLE_NAME"); + if (lib_bundle_name.isEmpty()) + lib_bundle_name = var("QMAKE_ORIG_TARGET"); + + if (!isShallowBundle) + symlinks[bundle_dir + "Resources"] = "Versions/Current/Resources"; t << "@$(DEL_FILE) " << info_plist_out << "\n\t" << "@sed "; for (const ProString &arg : qAsConst(commonSedArgs)) t << arg; - t << "-e \"s,@LIBRARY@," << var("QMAKE_ORIG_TARGET") << ",g\" " + t << "-e \"s,@LIBRARY@," << lib_bundle_name << ",g\" " << "-e \"s,@TYPEINFO@," << (project->isEmpty("QMAKE_PKGINFO_TYPEINFO") ? QString::fromLatin1("????") : project->first("QMAKE_PKGINFO_TYPEINFO").left(4)) << ",g\" " @@ -857,18 +878,20 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) for(int i = 0; i < bundle_data.count(); i++) { const ProStringList &files = project->values(ProKey(bundle_data[i] + ".files")); QString path = bundle_dir; - const ProKey vkey(bundle_data[i] + ".version"); const ProKey pkey(bundle_data[i] + ".path"); - if (!project->isEmpty(vkey)) { - QString version = project->first(vkey) + "/" + - project->first("QMAKE_FRAMEWORK_VERSION") + "/"; - ProString name = project->first(pkey); - int pos = name.indexOf('/'); - if (pos > 0) - name = name.mid(0, pos); - symlinks[Option::fixPathToTargetOS(path + name)] = - project->first(vkey) + "/Current/" + name; - path += version; + if (!project->isActiveConfig("shallow_bundle")) { + const ProKey vkey(bundle_data[i] + ".version"); + if (!project->isEmpty(vkey)) { + QString version = project->first(vkey) + "/" + + project->first("QMAKE_FRAMEWORK_VERSION") + "/"; + ProString name = project->first(pkey); + int pos = name.indexOf('/'); + if (pos > 0) + name = name.mid(0, pos); + symlinks[Option::fixPathToTargetOS(path + name)] = + project->first(vkey) + "/Current/" + name; + path += version; + } } path += project->first(pkey).toQString(); path = Option::fixPathToTargetOS(path); @@ -906,15 +929,17 @@ UnixMakefileGenerator::writeMakeParts(QTextStream &t) << "@$(SYMLINK) " << escapeFilePath(symIt.value()) << ' ' << bundle_dir_f << endl; } - QString currentLink = bundle_dir + "Versions/Current"; - QString currentLink_f = escapeDependencyPath(currentLink); - bundledFiles << currentLink; - alldeps << currentLink; - t << currentLink_f << ": $(MAKEFILE)\n\t" - << mkdir_p_asstring(bundle_dir + "Versions") << "\n\t" - << "@-$(DEL_FILE) " << currentLink_f << "\n\t" - << "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION") - << ' ' << currentLink_f << endl; + if (!project->isActiveConfig("shallow_bundle")) { + QString currentLink = bundle_dir + "Versions/Current"; + QString currentLink_f = escapeDependencyPath(currentLink); + bundledFiles << currentLink; + alldeps << currentLink; + t << currentLink_f << ": $(MAKEFILE)\n\t" + << mkdir_p_asstring(bundle_dir + "Versions") << "\n\t" + << "@-$(DEL_FILE) " << currentLink_f << "\n\t" + << "@$(SYMLINK) " << project->first("QMAKE_FRAMEWORK_VERSION") + << ' ' << currentLink_f << endl; + } } } @@ -1186,12 +1211,17 @@ void UnixMakefileGenerator::init2() bundle_loc.prepend("/"); if(!bundle_loc.endsWith("/")) bundle_loc += "/"; - project->values("TARGET_").append(project->first("QMAKE_BUNDLE") + - bundle_loc + project->first("TARGET")); - project->values("TARGET_x.y").append(project->first("QMAKE_BUNDLE") + - "/Versions/" + - project->first("QMAKE_FRAMEWORK_VERSION") + - bundle_loc + project->first("TARGET")); + const QString target = project->first("QMAKE_BUNDLE") + + bundle_loc + project->first("TARGET"); + project->values("TARGET_").append(target); + if (!project->isActiveConfig("shallow_bundle")) { + project->values("TARGET_x.y").append(project->first("QMAKE_BUNDLE") + + "/Versions/" + + project->first("QMAKE_FRAMEWORK_VERSION") + + bundle_loc + project->first("TARGET")); + } else { + project->values("TARGET_x.y").append(target); + } } else if(project->isActiveConfig("plugin")) { QString prefix; if(!project->isActiveConfig("no_plugin_name_prefix")) diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro index 1bfeabb8c4..5ec86bf78f 100644 --- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro +++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro @@ -11,7 +11,7 @@ load(qt_helper_lib) SHAPERS += opentype # HB's main shaper; enabling it should be enough most of the time # native shaper on Apple platforms; could be used alone to handle both OT and AAT fonts -darwin:!if(watchos:CONFIG(simulator, simulator|device)): SHAPERS += coretext +darwin: SHAPERS += coretext DEFINES += HAVE_CONFIG_H DEFINES += HB_NO_UNICODE_FUNCS HB_DISABLE_DEPRECATED @@ -155,4 +155,14 @@ contains(SHAPERS, coretext) { # On Mac OS they are part of the ApplicationServices umbrella framework, # even in 10.8 where they were also made available stand-alone. LIBS_PRIVATE += -framework ApplicationServices + + # CoreText is documented to be available on watchOS, but the headers aren't present + # in the watchOS Simulator SDK like they are supposed to be. Work around the problem + # by adding the device SDK's headers to the search path as a fallback. + # rdar://25314492, rdar://27844864 + watchos:CONFIG(simulator, simulator|device) { + QMAKE_CXXFLAGS += \ + -F$$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks \ + -F$$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks + } } diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 6a8948822c..afcd20a9c1 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -2,6 +2,8 @@ HEADERS += \ global/qglobal.h \ + global/qoperatingsystemversion.h \ + global/qoperatingsystemversion_p.h \ global/qsystemdetection.h \ global/qcompilerdetection.h \ global/qprocessordetection.h \ @@ -27,11 +29,15 @@ SOURCES += \ global/qlibraryinfo.cpp \ global/qmalloc.cpp \ global/qnumeric.cpp \ + global/qoperatingsystemversion.cpp \ global/qlogging.cpp \ global/qhooks.cpp VERSIONTAGGING_SOURCES = global/qversiontagging.cpp +darwin: SOURCES += global/qoperatingsystemversion_darwin.mm +win32: SOURCES += global/qoperatingsystemversion_win.cpp + # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 743d9d14a5..c78e6f2482 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -45,6 +45,8 @@ #include "qthreadstorage.h" #include "qdir.h" #include "qdatetime.h" +#include "qoperatingsystemversion.h" +#include "qoperatingsystemversion_p.h" #include <private/qlocale_tools_p.h> #include <qmutex.h> @@ -1088,12 +1090,14 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! + \deprecated \variable QSysInfo::WindowsVersion \brief the version of the Windows operating system on which the application is run. */ /*! + \deprecated \fn QSysInfo::WindowsVersion QSysInfo::windowsVersion() \since 4.4 @@ -1103,12 +1107,14 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! + \deprecated \variable QSysInfo::MacintoshVersion \brief the version of the Macintosh operating system on which the application is run. */ /*! + \deprecated \fn QSysInfo::MacVersion QSysInfo::macVersion() Returns the version of Darwin (\macos or iOS) on which the @@ -1126,6 +1132,7 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! + \deprecated \enum QSysInfo::WinVersion This enum provides symbolic names for the various versions of the @@ -1182,6 +1189,7 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! + \deprecated \enum QSysInfo::MacVersion This enum provides symbolic names for the various versions of the @@ -1943,28 +1951,31 @@ QT_BEGIN_INCLUDE_NAMESPACE #include "qnamespace.h" QT_END_INCLUDE_NAMESPACE +#if QT_DEPRECATED_SINCE(5, 9) QSysInfo::MacVersion QSysInfo::macVersion() { - const QAppleOperatingSystemVersion version = qt_apple_os_version(); // qtcore_mac_objc.mm + const auto version = QOperatingSystemVersion::current(); #if defined(Q_OS_OSX) - return QSysInfo::MacVersion(Q_MV_OSX(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_OSX(version.majorVersion(), version.minorVersion())); #elif defined(Q_OS_IOS) - return QSysInfo::MacVersion(Q_MV_IOS(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_IOS(version.majorVersion(), version.minorVersion())); #elif defined(Q_OS_TVOS) - return QSysInfo::MacVersion(Q_MV_TVOS(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_TVOS(version.majorVersion(), version.minorVersion())); #elif defined(Q_OS_WATCHOS) - return QSysInfo::MacVersion(Q_MV_WATCHOS(version.major, version.minor)); + return QSysInfo::MacVersion(Q_MV_WATCHOS(version.majorVersion(), version.minorVersion())); #else return QSysInfo::MV_Unknown; #endif } const QSysInfo::MacVersion QSysInfo::MacintoshVersion = QSysInfo::macVersion(); +#endif -#ifdef Q_OS_OSX -static const char *osxVer_helper(QAppleOperatingSystemVersion version = qt_apple_os_version()) +#ifdef Q_OS_DARWIN +static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current()) { - if (version.major == 10) { - switch (version.minor) { +#ifdef Q_OS_MACOS + if (version.majorVersion() == 10) { + switch (version.minorVersion()) { case 9: return "Mavericks"; case 10: @@ -1976,6 +1987,9 @@ static const char *osxVer_helper(QAppleOperatingSystemVersion version = qt_apple } } // unknown, future version +#else + Q_UNUSED(version); +#endif return 0; } #endif @@ -2016,140 +2030,30 @@ QWindowsSockInit::~QWindowsSockInit() Q_GLOBAL_STATIC(QWindowsSockInit, winsockInit) # endif // QT_BOOTSTRAPPED -#ifdef Q_OS_WINRT -static inline HMODULE moduleHandleForFunction(LPCVOID address) -{ - // This is a widely used, decades-old technique for retrieving the handle - // of a module and is effectively equivalent to GetModuleHandleEx - // (which is unavailable on WinRT) - MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 }; - if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0) - return 0; - return reinterpret_cast<HMODULE>(mbi.AllocationBase); -} -#endif - -static inline OSVERSIONINFOEX determineWinOsVersion() -{ - OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0}; - -#define GetProcAddressA GetProcAddress - - // GetModuleHandle is not supported in WinRT and linking to it at load time - // will not pass the Windows App Certification Kit... but it exists and is functional, - // so use some unusual but widely used techniques to get a pointer to it -#ifdef Q_OS_WINRT - // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL - HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast<LPCVOID>(VirtualQuery)); - if (Q_UNLIKELY(!kernelModule)) - return result; - - // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs) - typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR); - GetModuleHandleFunction pGetModuleHandle = reinterpret_cast<GetModuleHandleFunction>( - GetProcAddressA(kernelModule, "GetModuleHandleW")); - if (Q_UNLIKELY(!pGetModuleHandle)) - return result; -#else -#define pGetModuleHandle GetModuleHandleW -#endif - -#ifndef Q_OS_WINCE - HMODULE ntdll = pGetModuleHandle(L"ntdll.dll"); - if (Q_UNLIKELY(!ntdll)) - return result; - - // NTSTATUS is not defined on WinRT - typedef LONG NTSTATUS; - typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); - - // RtlGetVersion is documented public API but we must load it dynamically - // because linking to it at load time will not pass the Windows App Certification Kit - // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx - RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>( - GetProcAddressA(ntdll, "RtlGetVersion")); - if (Q_UNLIKELY(!pRtlGetVersion)) - return result; - - // GetVersionEx() has been deprecated in Windows 8.1 and will return - // only Windows 8 from that version on, so use the kernel API function. - pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS -#else // !Q_OS_WINCE - GetVersionEx(&result); -#endif - return result; -} - -static OSVERSIONINFOEX winOsVersion() -{ - OSVERSIONINFOEX realResult = determineWinOsVersion(); -#ifdef QT_DEBUG - { - if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) { - OSVERSIONINFOEX result = realResult; - result.dwMajorVersion = 0; - result.dwMinorVersion = 0; - - // Erase any build number and service pack information - result.dwBuildNumber = 0; - result.szCSDVersion[0] = L'\0'; - result.wServicePackMajor = 0; - result.wServicePackMinor = 0; - - const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE"); - if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") { - result.dwMajorVersion = 6; - result.dwMinorVersion = 1; - } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") { - result.dwMajorVersion = 6; - result.dwMinorVersion = 2; - } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") { - result.dwMajorVersion = 6; - result.dwMinorVersion = 3; - } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") { - result.dwMajorVersion = 10; - } else { - return realResult; - } - - if (winVerOverride == "2008_R2" - || winVerOverride == "2012" - || winVerOverride == "2012_R2" - || winVerOverride == "2016") { - // If the current host OS is a domain controller and the override OS - // is also a server type OS, preserve that information - if (result.wProductType == VER_NT_WORKSTATION) - result.wProductType = VER_NT_SERVER; - } else { - // Any other OS must be a workstation OS type - result.wProductType = VER_NT_WORKSTATION; - } - } - } -#endif - return realResult; -} - +#if QT_DEPRECATED_SINCE(5, 9) QSysInfo::WinVersion QSysInfo::windowsVersion() { - const OSVERSIONINFOEX osver = winOsVersion(); - if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 1) + const auto version = QOperatingSystemVersion::current(); + if (version.majorVersion() == 6 && version.minorVersion() == 1) return QSysInfo::WV_WINDOWS7; - if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 2) + if (version.majorVersion() == 6 && version.minorVersion() == 2) return QSysInfo::WV_WINDOWS8; - if (osver.dwMajorVersion == 6 && osver.dwMinorVersion == 3) + if (version.majorVersion() == 6 && version.minorVersion() == 3) return QSysInfo::WV_WINDOWS8_1; - if (osver.dwMajorVersion == 10 && osver.dwMinorVersion == 0) + if (version.majorVersion() == 10 && version.minorVersion() == 0) return QSysInfo::WV_WINDOWS10; return QSysInfo::WV_NT_based; } +const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion(); +#endif static QString winSp_helper() { - const qint16 major = winOsVersion().wServicePackMajor; + const auto osv = qWindowsVersionInfo(); + const qint16 major = osv.wServicePackMajor; if (major) { QString sp = QStringLiteral(" SP ") + QString::number(major); - const qint16 minor = winOsVersion().wServicePackMinor; + const qint16 minor = osv.wServicePackMinor; if (minor) sp += QLatin1Char('.') + QString::number(minor); @@ -2158,9 +2062,10 @@ static QString winSp_helper() return QString(); } -static const char *winVer_helper() +static const char *osVer_helper(QOperatingSystemVersion version = QOperatingSystemVersion::current()) { - const OSVERSIONINFOEX osver = winOsVersion(); + Q_UNUSED(version); + const OSVERSIONINFOEX osver = qWindowsVersionInfo(); const bool workstation = osver.wProductType == VER_NT_WORKSTATION; #define Q_WINVER(major, minor) (major << 8 | minor) @@ -2179,8 +2084,6 @@ static const char *winVer_helper() return 0; } -const QSysInfo::WinVersion QSysInfo::WindowsVersion = QSysInfo::windowsVersion(); - #endif #if defined(Q_OS_UNIX) # if (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD) @@ -2361,6 +2264,67 @@ static bool findUnixOsVersion(QUnixOSVersion &v) # endif // USE_ETC_OS_RELEASE #endif // Q_OS_UNIX +#ifdef Q_OS_ANDROID +static const char *osVer_helper(QOperatingSystemVersion) +{ +/* Data: + + + +Cupcake +Donut +Eclair +Eclair +Eclair +Froyo +Gingerbread +Gingerbread +Honeycomb +Honeycomb +Honeycomb +Ice Cream Sandwich +Ice Cream Sandwich +Jelly Bean +Jelly Bean +Jelly Bean +KitKat +KitKat +Lollipop +Lollipop +Marshmallow +Nougat + */ + static const char versions_string[] = + "\0" + "Cupcake\0" + "Donut\0" + "Eclair\0" + "Froyo\0" + "Gingerbread\0" + "Honeycomb\0" + "Ice Cream Sandwich\0" + "Jelly Bean\0" + "KitKat\0" + "Lollipop\0" + "Marshmallow\0" + "Nougat\0" + "\0"; + + static const int versions_indices[] = { + 0, 0, 0, 1, 9, 15, 15, 15, + 22, 28, 28, 40, 40, 40, 50, 50, + 69, 69, 69, 80, 80, 87, 87, 96, + 108, -1 + }; + + static const int versions_count = (sizeof versions_indices) / (sizeof versions_indices[0]); + + // https://source.android.com/source/build-numbers.html + // https://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels + const int sdk_int = QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT"); + return &versions_string[versions_indices[qBound(0, sdk_int, versions_count - 1)]]; +} +#endif /*! \since 5.4 @@ -2609,9 +2573,9 @@ QString QSysInfo::kernelType() QString QSysInfo::kernelVersion() { #ifdef Q_OS_WIN - const OSVERSIONINFOEX osver = winOsVersion(); - return QString::number(int(osver.dwMajorVersion)) + QLatin1Char('.') + QString::number(int(osver.dwMinorVersion)) - + QLatin1Char('.') + QString::number(int(osver.dwBuildNumber)); + const auto osver = QOperatingSystemVersion::current(); + return QString::number(osver.majorVersion()) + QLatin1Char('.') + QString::number(osver.minorVersion()) + + QLatin1Char('.') + QString::number(osver.microVersion()); #else struct utsname u; if (uname(&u) == 0) @@ -2679,8 +2643,8 @@ QString QSysInfo::productType() #elif defined(Q_OS_WATCHOS) return QStringLiteral("watchos"); #elif defined(Q_OS_MACOS) - const QAppleOperatingSystemVersion version = qt_apple_os_version(); - if (version.major == 10 && version.minor < 12) + const auto version = QOperatingSystemVersion::current(); + if (version.majorVersion() == 10 && version.minorVersion() < 12) return QStringLiteral("osx"); return QStringLiteral("macos"); #elif defined(Q_OS_DARWIN) @@ -2720,20 +2684,17 @@ QString QSysInfo::productType() */ QString QSysInfo::productVersion() { -#if defined(Q_OS_MAC) - const QAppleOperatingSystemVersion version = qt_apple_os_version(); - return QString::number(version.major) + QLatin1Char('.') + QString::number(version.minor); +#if defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) + const auto version = QOperatingSystemVersion::current(); + return QString::number(version.majorVersion()) + QLatin1Char('.') + QString::number(version.minorVersion()); #elif defined(Q_OS_WIN) - const char *version = winVer_helper(); + const char *version = osVer_helper(); if (version) { const QLatin1Char spaceChar(' '); return QString::fromLatin1(version).remove(spaceChar).toLower() + winSp_helper().remove(spaceChar).toLower(); } // fall through -// Android should not fall through to the Unix code -#elif defined(Q_OS_ANDROID) - return QJNIObjectPrivate::getStaticObjectField("android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString(); #elif defined(USE_ETC_OS_RELEASE) // Q_OS_UNIX QUnixOSVersion unixOsVersion; findUnixOsVersion(unixOsVersion); @@ -2761,44 +2722,23 @@ QString QSysInfo::productVersion() */ QString QSysInfo::prettyProductName() { -#if defined(Q_OS_IOS) - return QLatin1String("iOS ") + productVersion(); -#elif defined(Q_OS_TVOS) - return QLatin1String("tvOS ") + productVersion(); -#elif defined(Q_OS_WATCHOS) - return QLatin1String("watchOS ") + productVersion(); -#elif defined(Q_OS_MACOS) - const QAppleOperatingSystemVersion version = qt_apple_os_version(); - const char *name = osxVer_helper(version); - if (name) { - return (version.major == 10 && version.minor < 12 - ? QLatin1String("OS X ") - : QLatin1String("macOS ")) - + QLatin1String(name) - + QLatin1String(" (") + QString::number(version.major) - + QLatin1Char('.') + QString::number(version.minor) - + QLatin1Char(')'); - } else { - return QLatin1String("macOS ") - + QString::number(version.major) + QLatin1Char('.') - + QString::number(version.minor); - } -#elif defined(Q_OS_WINPHONE) - return QLatin1String("Windows Phone ") + QLatin1String(winVer_helper()); -#elif defined(Q_OS_WIN) - const char *name = winVer_helper(); - const OSVERSIONINFOEX osver = winOsVersion(); +#if defined(Q_OS_WINPHONE) + return QLatin1String("Windows Phone ") + QLatin1String(osVer_helper()); +#elif defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN) || defined(Q_OS_WIN) + const auto version = QOperatingSystemVersion::current(); + const char *name = osVer_helper(version); if (name) - return QLatin1String("Windows ") + QLatin1String(name) + winSp_helper() - + QLatin1String(" (") + QString::number(osver.dwMajorVersion) - + QLatin1Char('.') + QString::number(osver.dwMinorVersion) + return version.name() + QLatin1Char(' ') + QLatin1String(name) +# if defined(Q_OS_WIN) + + winSp_helper() +# endif + + QLatin1String(" (") + QString::number(version.majorVersion()) + + QLatin1Char('.') + QString::number(version.minorVersion()) + QLatin1Char(')'); - else - return QLatin1String("Windows ") - + QString::number(osver.dwMajorVersion) + QLatin1Char('.') - + QString::number(osver.dwMinorVersion); -#elif defined(Q_OS_ANDROID) - return QLatin1String("Android ") + productVersion(); + else + return version.name() + QLatin1Char(' ') + + QString::number(version.majorVersion()) + QLatin1Char('.') + + QString::number(version.minorVersion()); #elif defined(Q_OS_HAIKU) return QLatin1String("Haiku ") + productVersion(); #elif defined(Q_OS_UNIX) diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp new file mode 100644 index 0000000000..14dc109b3e --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion.cpp @@ -0,0 +1,394 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion.h" +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) +#include "qoperatingsystemversion_p.h" +#endif + +#include <qversionnumber.h> + +#if defined(Q_OS_ANDROID) +#include <private/qjni_p.h> +#endif + +QT_BEGIN_NAMESPACE + +/*! + \class QOperatingSystemVersion + \inmodule QtCore + \since 5.9 + \brief The QOperatingSystemVersion class provides information about the operating system version. + + Unlike other version functions in QSysInfo, QOperatingSystemVersion provides access to the full + version number that \a developers typically use to vary behavior or determine whether to enable + APIs or features based on the operating system version (as opposed to the kernel version number + or marketing version). + + This class is also a complete replacement for QSysInfo::macVersion and QSysInfo::windowsVersion, + additionally providing access to the third (micro) version number component. + + Presently, Android, Apple Platforms (iOS, macOS, tvOS, and watchOS), and Windows are supported. + + The \a majorVersion(), \a minorVersion(), and \a microVersion() functions return the parts of + the operating system version number based on: + + \table + \header \li Platforms \li Value + \row \li Android \li result of parsing + \l{https://developer.android.com/reference/android/os/Build.VERSION.html#RELEASE}{"android.os.Build.VERSION.RELEASE"} + using QVersionNumber, with a fallback to + \l{https://developer.android.com/reference/android/os/Build.VERSION.html#SDK_INT}{"android.os.Build.VERSION.SDK_INT"} + to determine the major and minor version component if the former fails + \row \li Apple Platforms \li majorVersion, minorVersion, and patchVersion from + \l{https://developer.apple.com/reference/foundation/nsprocessinfo/1410906-operatingsystemversion?language=objc}{"NSProcessInfo.operatingSystemVersion"} + \row \li Windows \li dwMajorVersion, dwMinorVersion, and dwBuildNumber from + \l{https://msdn.microsoft.com/en-us/library/mt723418.aspx}{"RtlGetVersion"} - + note that this function ALWAYS return the version number of the underlying operating system, + as opposed to the shim underneath GetVersionEx that hides the real version number + if the application is not manifested for that version of the OS + \endtable +*/ + +/*! + \fn QOperatingSystemVersion::QOperatingSystemVersion(int maj, int min, int mic) + + Constructs a QOperatingSystemVersion consisting of the OS type \a os, and + major, minor, and micro version numbers \a maj, \a min and \a mic, respectively. +*/ + +/*! + \fn QOperatingSystemVersion QOperatingSystemVersion::current() + + Returns a QOperatingSystemVersion indicating the current OS and its version number. +*/ +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN) +QOperatingSystemVersion QOperatingSystemVersion::current() +{ + QOperatingSystemVersion version; + version.m_os = currentType(); +#if defined(Q_OS_ANDROID) +#ifndef QT_BOOTSTRAPPED + const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField( + "android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString()); + if (!v.isNull()) { + version.m_major = v.majorVersion(); + version.m_minor = v.minorVersion(); + version.m_micro = v.microVersion(); + return version; + } +#endif + + version.m_major = -1; + version.m_minor = -1; + + static const int versions[][2] = { + { 1, 0 }, // API level 1 + { 1, 1 }, // API level 2 + { 1, 5 }, // API level 3 + { 1, 6 }, // API level 4 + { 2, 0 }, // API level 5 + { 2, 0 }, // API level 6 + { 2, 1 }, // API level 7 + { 2, 2 }, // API level 8 + { 2, 3 }, // API level 9 + { 2, 3 }, // API level 10 + { 3, 0 }, // API level 11 + { 3, 1 }, // API level 12 + { 3, 2 }, // API level 13 + { 4, 0 }, // API level 14 + { 4, 0 }, // API level 15 + { 4, 1 }, // API level 16 + { 4, 2 }, // API level 17 + { 4, 3 }, // API level 18 + { 4, 4 }, // API level 19 + { 4, 4 }, // API level 20 + { 5, 0 }, // API level 21 + { 5, 1 }, // API level 22 + { 6, 0 }, // API level 23 + { 7, 0 }, // API level 24 + }; + + // This will give us at least the first 2 version components + const int sdk = static_cast<int>(QJNIObjectPrivate::getStaticField<jint>("android/os/Build$VERSION", "SDK_INT")); + if (sdk >= 1 && sdk <= sizeof(versions) / sizeof(versions[0])) { + version.m_major = versions[sdk - 1][0]; + version.m_minor = versions[sdk - 1][1]; + } + + // API level 6 was exactly version 2.0.1 + version.m_micro = sdk == 6 ? 1 : -1; +#else + version.m_major = -1; + version.m_minor = -1; + version.m_micro = -1; +#endif + return version; +} +#endif + +static inline int compareVersionComponents(int lhs, int rhs) +{ + return lhs >= 0 && rhs >= 0 ? lhs - rhs : 0; +} + +/*! + \fn int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1, + const QOperatingSystemVersion &v2) + + Compares \a v1 with \a v2 and returns an integer less than, equal to, or + greater than zero, depending on whether \a v1 is less than, equal to, or + greater than \a v2, respectively. + + Comparisons are performed by comparing the version number components of + \a v1 and \a v2. + + \note This function cannot take the OS type into account; you should use + the overloaded comparison operators to compare QOperatingSystemVersions + in a safe manner. +*/ +int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2) +{ + if (v1.m_major == v2.m_major) { + if (v1.m_minor == v2.m_minor) { + return compareVersionComponents(v1.m_micro, v2.m_micro); + } + return compareVersionComponents(v1.m_minor, v2.m_minor); + } + return compareVersionComponents(v1.m_major, v2.m_major); +} + +#ifndef QT_BOOTSTRAPPED +/*! + \fn QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version, + QOperatingSystemVersion::OSType os) + + Returns a QOperatingSystemVersion consisting of the OS type \a os and version number \a version. +*/ +QOperatingSystemVersion QOperatingSystemVersion::fromVersionNumber(const QVersionNumber &version, + QOperatingSystemVersion::OSType os) +{ + return QOperatingSystemVersion(os, version.majorVersion(), version.minorVersion(), version.microVersion()); +} + +/*! + \fn QOperatingSystemVersion QOperatingSystemVersion::toVersionNumber() const + + Returns the QOperatingSystemVersion's version number as a QVersionNumber. +*/ +QVersionNumber QOperatingSystemVersion::toVersionNumber() const +{ + return QVersionNumber(m_major, m_minor, m_micro); +} +#endif + +/*! + \fn int QOperatingSystemVersion::majorVersion() const + + Returns the major version number, that is, the first segment of the operating system's version number. + + See the main class documentation for what the major version number is on a given operating system. + + -1 indicates an unknown or absent version number component. + + \sa minorVersion(), microVersion() +*/ + +/*! + \fn int QOperatingSystemVersion::minorVersion() const + + Returns the minor version number, that is, the second segment of the operating system's version number. + + See the main class documentation for what the minor version number is on a given operating system. + + -1 indicates an unknown or absent version number component. + + \sa majorVersion(), macro() +*/ + +/*! + \fn int QOperatingSystemVersion::microVersion() const + + Returns the micro version number, that is, the third segment of the operating system's version number. + + See the main class documentation for what the micro version number is on a given operating system. + + -1 indicates an unknown or absent version number component. + + \sa majorVersion(), minorVersion() +*/ + +/*! + \fn QOperatingSystemVersion::OSType QOperatingSystemVersion::type() const + + Returns the OS type identified by the QOperatingSystemVersion. + + \sa typeName() +*/ + +/*! + \fn QString QOperatingSystemVersion::name() const + + Returns a string representation of the OS type identified by the QOperatingSystemVersion. + + \sa type() +*/ +QString QOperatingSystemVersion::name() const +{ + switch (type()) { + case QOperatingSystemVersion::Windows: + return QStringLiteral("Windows"); + case QOperatingSystemVersion::MacOS: { + if (majorVersion() < 10) + return QStringLiteral("Mac OS"); + if (majorVersion() == 10 && minorVersion() < 8) + return QStringLiteral("Mac OS X"); + if (majorVersion() == 10 && minorVersion() < 12) + return QStringLiteral("OS X"); + return QStringLiteral("macOS"); + } + case QOperatingSystemVersion::IOS: { + if (majorVersion() < 4) + return QStringLiteral("iPhone OS"); + return QStringLiteral("iOS"); + } + case QOperatingSystemVersion::TvOS: + return QStringLiteral("tvOS"); + case QOperatingSystemVersion::WatchOS: + return QStringLiteral("watchOS"); + case QOperatingSystemVersion::Android: + return QStringLiteral("Android"); + case QOperatingSystemVersion::Unknown: + default: + return QString(); + } +} + +/*! + \variable QOperatingSystemVersion::Windows7 + \brief a version corresponding to Windows 7 (version 6.1). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows7 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 1); + +/*! + \variable QOperatingSystemVersion::Windows8 + \brief a version corresponding to Windows 8 (version 6.2). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows8 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 2); + +/*! + \variable QOperatingSystemVersion::Windows8_1 + \brief a version corresponding to Windows 8.1 (version 6.3). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows8_1 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 3); + +/*! + \variable QOperatingSystemVersion::Windows10 + \brief a version corresponding to Windows 10 (version 10.0). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::Windows10 = QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10); + +/*! + \variable QOperatingSystemVersion::OSXMavericks + \brief a version corresponding to OS X Mavericks (version 10.9). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXMavericks = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 9); + +/*! + \variable QOperatingSystemVersion::OSXYosemite + \brief a version corresponding to OS X Yosemite (version 10.10). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXYosemite = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 10); + +/*! + \variable QOperatingSystemVersion::OSXElCapitan + \brief a version corresponding to OS X El Capitan (version 10.11). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::OSXElCapitan = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 11); + +/*! + \variable QOperatingSystemVersion::MacOSSierra + \brief a version corresponding to macOS Sierra (version 10.12). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::MacOSSierra = QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 12); + +/*! + \variable QOperatingSystemVersion::AndroidJellyBean + \brief a version corresponding to Android Jelly Bean (versions 4.1 - 4.3). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 1); + +/*! + \variable QOperatingSystemVersion::AndroidKitKat + \brief a version corresponding to Android KitKat (version 4.4). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidKitKat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 4); + +/*! + \variable QOperatingSystemVersion::AndroidLollipop + \brief a version corresponding to Android Lollipop (versions 5.0 - 5.1). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop = QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 0); + +/*! + \variable QOperatingSystemVersion::AndroidMarshmallow + \brief a version corresponding to Android Marshmallow (version 6.0). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidMarshmallow = QOperatingSystemVersion(QOperatingSystemVersion::Android, 6); + +/*! + \variable QOperatingSystemVersion::AndroidNougat + \brief a version corresponding to Android Nougat (version 7.0). + \since 5.9 + */ +const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat = QOperatingSystemVersion(QOperatingSystemVersion::Android, 7); + +QT_END_NAMESPACE diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h new file mode 100644 index 0000000000..33c3d33bcc --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/qglobal.h> + +#ifndef QOPERATINGSYSTEMVERSION_H +#define QOPERATINGSYSTEMVERSION_H + +QT_BEGIN_NAMESPACE + +class QString; +class QVersionNumber; + +class Q_CORE_EXPORT QOperatingSystemVersion +{ +public: + enum OSType { + Unknown = 0, + Windows, + MacOS, + IOS, + TvOS, + WatchOS, + Android + }; + + static const QOperatingSystemVersion Windows7; + static const QOperatingSystemVersion Windows8; + static const QOperatingSystemVersion Windows8_1; + static const QOperatingSystemVersion Windows10; + + static const QOperatingSystemVersion OSXMavericks; + static const QOperatingSystemVersion OSXYosemite; + static const QOperatingSystemVersion OSXElCapitan; + static const QOperatingSystemVersion MacOSSierra; + + static const QOperatingSystemVersion AndroidJellyBean; + static const QOperatingSystemVersion AndroidKitKat; + static const QOperatingSystemVersion AndroidLollipop; + static const QOperatingSystemVersion AndroidMarshmallow; + static const QOperatingSystemVersion AndroidNougat; + + QOperatingSystemVersion(const QOperatingSystemVersion &other) = default; + Q_DECL_CONSTEXPR QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1) + : m_os(osType), m_major(vmajor), m_minor(vminor), m_micro(vmicro) { } + + static QOperatingSystemVersion current(); + + static int compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2); + + QOperatingSystemVersion fromVersionNumber(const QVersionNumber &version, OSType os); + QVersionNumber toVersionNumber() const; + + Q_DECL_CONSTEXPR int majorVersion() const { return m_major; } + Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; } + Q_DECL_CONSTEXPR int microVersion() const { return m_micro; } + + Q_DECL_CONSTEXPR OSType type() const { return m_os; } + QString name() const; + +private: + QOperatingSystemVersion() = default; + OSType m_os; + int m_major; + int m_minor; + int m_micro; +}; + +inline bool operator>(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) > 0; } + +inline bool operator>=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) >= 0; } + +inline bool operator<(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) < 0; } + +inline bool operator<=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) <= 0; } + +inline bool operator==(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) == 0; } + +inline bool operator!=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs) +{ return !(lhs == rhs); } + +QT_END_NAMESPACE + +#endif // QOPERATINGSYSTEMVERSION_H diff --git a/src/corelib/global/qoperatingsystemversion_darwin.mm b/src/corelib/global/qoperatingsystemversion_darwin.mm new file mode 100644 index 0000000000..3dd007cbb3 --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion_darwin.mm @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion_p.h" +#import <Foundation/Foundation.h> + +#ifdef Q_OS_IOS +#import <UIKit/UIKit.h> +#endif + +QT_BEGIN_NAMESPACE + +typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response); + +QOperatingSystemVersion QOperatingSystemVersion::current() +{ + QOperatingSystemVersion v; + v.m_os = currentType(); + v.m_major = -1; + v.m_minor = -1; + v.m_micro = -1; +#if QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS) + if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) { + NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion; + v.m_major = osv.majorVersion; + v.m_minor = osv.minorVersion; + v.m_micro = osv.patchVersion; + return v; + } +#endif + // Use temporary variables so we can return 0.0.0 (unknown version) + // in case of an error partway through determining the OS version + qint32 major = 0, minor = 0, patch = 0; +#if QT_MACOS_IOS_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0) +#if defined(Q_OS_IOS) + @autoreleasepool { + NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."]; + major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0; + minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0; + patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0; + } +#elif defined(Q_OS_MACOS) + static GestaltFunction pGestalt = 0; + if (!pGestalt) { + CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices")); + pGestalt = reinterpret_cast<GestaltFunction>(CFBundleGetFunctionPointerForName(b, + CFSTR("Gestalt"))); + } + if (!pGestalt) + return v; + if (pGestalt('sys1', &major) != 0) + return v; + if (pGestalt('sys2', &minor) != 0) + return v; + if (pGestalt('sys3', &patch) != 0) + return v; +#endif +#endif + v.m_major = major; + v.m_minor = minor; + v.m_micro = patch; + return v; +} + +QT_END_NAMESPACE diff --git a/mkspecs/macx-g++42/qplatformdefs.h b/src/corelib/global/qoperatingsystemversion_p.h index 063491dd90..f227e98dd1 100644 --- a/mkspecs/macx-g++42/qplatformdefs.h +++ b/src/corelib/global/qoperatingsystemversion_p.h @@ -3,7 +3,7 @@ ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** -** This file is part of the qmake spec of the Qt Toolkit. +** This file is part of the QtCore module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage @@ -37,5 +37,35 @@ ** ****************************************************************************/ -#include "../common/mac/qplatformdefs.h" +#include "qoperatingsystemversion.h" +#ifdef Q_OS_WIN +#include <qt_windows.h> +#endif + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_WIN +OSVERSIONINFOEX qWindowsVersionInfo(); +#endif + +static inline QOperatingSystemVersion::OSType currentType() +{ +#if defined(Q_OS_WIN) + return QOperatingSystemVersion::Windows; +#elif defined(Q_OS_MACOS) + return QOperatingSystemVersion::MacOS; +#elif defined(Q_OS_IOS) + return QOperatingSystemVersion::IOS; +#elif defined(Q_OS_TVOS) + return QOperatingSystemVersion::TvOS; +#elif defined(Q_OS_WATCHOS) + return QOperatingSystemVersion::WatchOS; +#elif defined(Q_OS_ANDROID) + return QOperatingSystemVersion::Android; +#else + return QOperatingSystemVersion::Unknown; +#endif +} + +QT_END_NAMESPACE diff --git a/src/corelib/global/qoperatingsystemversion_win.cpp b/src/corelib/global/qoperatingsystemversion_win.cpp new file mode 100644 index 0000000000..060ca2f7da --- /dev/null +++ b/src/corelib/global/qoperatingsystemversion_win.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** 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 The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/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 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qoperatingsystemversion_p.h" +#include <qt_windows.h> +#include <qbytearray.h> + +QT_BEGIN_NAMESPACE + +#ifdef Q_OS_WINRT +static inline HMODULE moduleHandleForFunction(LPCVOID address) +{ + // This is a widely used, decades-old technique for retrieving the handle + // of a module and is effectively equivalent to GetModuleHandleEx + // (which is unavailable on WinRT) + MEMORY_BASIC_INFORMATION mbi = { 0, 0, 0, 0, 0, 0, 0 }; + if (VirtualQuery(address, &mbi, sizeof(mbi)) == 0) + return 0; + return reinterpret_cast<HMODULE>(mbi.AllocationBase); +} +#endif + +static inline OSVERSIONINFOEX determineWinOsVersion() +{ + OSVERSIONINFOEX result = { sizeof(OSVERSIONINFOEX), 0, 0, 0, 0, {'\0'}, 0, 0, 0, 0, 0}; + +#define GetProcAddressA GetProcAddress + + // GetModuleHandle is not supported in WinRT and linking to it at load time + // will not pass the Windows App Certification Kit... but it exists and is functional, + // so use some unusual but widely used techniques to get a pointer to it +#ifdef Q_OS_WINRT + // 1. Get HMODULE of kernel32.dll, using the address of some function exported by that DLL + HMODULE kernelModule = moduleHandleForFunction(reinterpret_cast<LPCVOID>(VirtualQuery)); + if (Q_UNLIKELY(!kernelModule)) + return result; + + // 2. Get pointer to GetModuleHandle so we can then load other arbitrary modules (DLLs) + typedef HMODULE(WINAPI *GetModuleHandleFunction)(LPCWSTR); + GetModuleHandleFunction pGetModuleHandle = reinterpret_cast<GetModuleHandleFunction>( + GetProcAddressA(kernelModule, "GetModuleHandleW")); + if (Q_UNLIKELY(!pGetModuleHandle)) + return result; +#else +#define pGetModuleHandle GetModuleHandleW +#endif + +#ifndef Q_OS_WINCE + HMODULE ntdll = pGetModuleHandle(L"ntdll.dll"); + if (Q_UNLIKELY(!ntdll)) + return result; + + // NTSTATUS is not defined on WinRT + typedef LONG NTSTATUS; + typedef NTSTATUS (NTAPI *RtlGetVersionFunction)(LPOSVERSIONINFO); + + // RtlGetVersion is documented public API but we must load it dynamically + // because linking to it at load time will not pass the Windows App Certification Kit + // https://msdn.microsoft.com/en-us/library/windows/hardware/ff561910.aspx + RtlGetVersionFunction pRtlGetVersion = reinterpret_cast<RtlGetVersionFunction>( + GetProcAddressA(ntdll, "RtlGetVersion")); + if (Q_UNLIKELY(!pRtlGetVersion)) + return result; + + // GetVersionEx() has been deprecated in Windows 8.1 and will return + // only Windows 8 from that version on, so use the kernel API function. + pRtlGetVersion((LPOSVERSIONINFO) &result); // always returns STATUS_SUCCESS +#else // !Q_OS_WINCE + GetVersionEx(&result); +#endif + return result; +} + +OSVERSIONINFOEX qWindowsVersionInfo() +{ + OSVERSIONINFOEX realResult = determineWinOsVersion(); +#ifdef QT_DEBUG + { + if (Q_UNLIKELY(qEnvironmentVariableIsSet("QT_WINVER_OVERRIDE"))) { + OSVERSIONINFOEX result = realResult; + result.dwMajorVersion = 0; + result.dwMinorVersion = 0; + + // Erase any build number and service pack information + result.dwBuildNumber = 0; + result.szCSDVersion[0] = L'\0'; + result.wServicePackMajor = 0; + result.wServicePackMinor = 0; + + const QByteArray winVerOverride = qgetenv("QT_WINVER_OVERRIDE"); + if (winVerOverride == "WINDOWS7" || winVerOverride == "2008_R2") { + result.dwMajorVersion = 6; + result.dwMinorVersion = 1; + } else if (winVerOverride == "WINDOWS8" || winVerOverride == "2012") { + result.dwMajorVersion = 6; + result.dwMinorVersion = 2; + } else if (winVerOverride == "WINDOWS8_1" || winVerOverride == "2012_R2") { + result.dwMajorVersion = 6; + result.dwMinorVersion = 3; + } else if (winVerOverride == "WINDOWS10" || winVerOverride == "2016") { + result.dwMajorVersion = 10; + } else { + return realResult; + } + + if (winVerOverride == "2008_R2" + || winVerOverride == "2012" + || winVerOverride == "2012_R2" + || winVerOverride == "2016") { + // If the current host OS is a domain controller and the override OS + // is also a server type OS, preserve that information + if (result.wProductType == VER_NT_WORKSTATION) + result.wProductType = VER_NT_SERVER; + } else { + // Any other OS must be a workstation OS type + result.wProductType = VER_NT_WORKSTATION; + } + } + } +#endif + return realResult; +} + +QOperatingSystemVersion QOperatingSystemVersion::current() +{ + QOperatingSystemVersion v; + v.m_os = currentType(); + const OSVERSIONINFOEX osv = qWindowsVersionInfo(); + v.m_major = osv.dwMajorVersion; + v.m_minor = osv.dwMinorVersion; + v.m_micro = osv.dwBuildNumber; + return v; +} + +QT_END_NAMESPACE diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index 23f412aa6a..5ec55d467c 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -79,7 +79,8 @@ public: # endif }; #endif - enum WinVersion { +#if QT_DEPRECATED_SINCE(5, 9) + enum QT_DEPRECATED_X("Use QOperatingSystemVersion") WinVersion { WV_None = 0x0000, WV_32s = 0x0001, @@ -117,19 +118,25 @@ public: WV_CE_6 = 0x0400, WV_CE_based = 0x0f00 }; +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") +QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations") +QT_WARNING_DISABLE_INTEL(1478) +QT_WARNING_DISABLE_MSVC(4996) #if defined(Q_OS_WIN) || defined(Q_OS_CYGWIN) - static const WinVersion WindowsVersion; - static WinVersion windowsVersion(); + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion; + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion(); #else - static const WinVersion WindowsVersion = WV_None; - static WinVersion windowsVersion() { return WV_None; } + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const WinVersion WindowsVersion = WV_None; + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static WinVersion windowsVersion() { return WV_None; } #endif +QT_WARNING_POP #define Q_MV_OSX(major, minor) (major == 10 ? minor + 2 : (major == 9 ? 1 : 0)) #define Q_MV_IOS(major, minor) (QSysInfo::MV_IOS | major << 4 | minor) #define Q_MV_TVOS(major, minor) (QSysInfo::MV_TVOS | major << 4 | minor) #define Q_MV_WATCHOS(major, minor) (QSysInfo::MV_WATCHOS | major << 4 | minor) - enum MacVersion { + enum QT_DEPRECATED_X("Use QOperatingSystemVersion") MacVersion { MV_None = 0xffff, MV_Unknown = 0x0000, @@ -198,13 +205,20 @@ public: MV_WATCHOS_2_2 = Q_MV_WATCHOS(2, 2), MV_WATCHOS_3_0 = Q_MV_WATCHOS(3, 0) }; +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations") +QT_WARNING_DISABLE_CLANG("-Wdeprecated-declarations") +QT_WARNING_DISABLE_INTEL(1478) +QT_WARNING_DISABLE_MSVC(4996) #if defined(Q_OS_MAC) - static const MacVersion MacintoshVersion; - static MacVersion macVersion(); + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion; + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion(); #else - static const MacVersion MacintoshVersion = MV_None; - static MacVersion macVersion() { return MV_None; } + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static const MacVersion MacintoshVersion = MV_None; + QT_DEPRECATED_X("Use QOperatingSystemVersion::current()") static MacVersion macVersion() { return MV_None; } #endif +QT_WARNING_POP +#endif // QT_DEPRECATED_SINCE(5, 9) static QString buildCpuArchitecture(); static QString currentCpuArchitecture(); diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index ac58677b77..994ed88791 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -95,10 +95,11 @@ public: Qt_5_6 = 17, Qt_5_7 = Qt_5_6, Qt_5_8 = Qt_5_7, -#if QT_VERSION >= 0x050900 + Qt_5_9 = Qt_5_8, +#if QT_VERSION >= 0x050a00 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_8 + Qt_DefaultCompiledVersion = Qt_5_9 }; enum ByteOrder { @@ -222,6 +223,98 @@ private: QDataStream::Status oldStatus; }; +template <typename Container> +QDataStream &readArrayBasedContainer(QDataStream &s, Container &c) +{ + StreamStateSaver stateSaver(&s); + + c.clear(); + quint32 n; + s >> n; + c.reserve(n); + for (quint32 i = 0; i < n; ++i) { + typename Container::value_type t; + s >> t; + if (s.status() != QDataStream::Ok) { + c.clear(); + break; + } + c.append(t); + } + + return s; +} + +template <typename Container> +QDataStream &readListBasedContainer(QDataStream &s, Container &c) +{ + StreamStateSaver stateSaver(&s); + + c.clear(); + quint32 n; + s >> n; + for (quint32 i = 0; i < n; ++i) { + typename Container::value_type t; + s >> t; + if (s.status() != QDataStream::Ok) { + c.clear(); + break; + } + c << t; + } + + return s; +} + +template <typename Container> +QDataStream &readAssociativeContainer(QDataStream &s, Container &c) +{ + StreamStateSaver stateSaver(&s); + + c.clear(); + quint32 n; + s >> n; + for (quint32 i = 0; i < n; ++i) { + typename Container::key_type k; + typename Container::mapped_type t; + s >> k >> t; + if (s.status() != QDataStream::Ok) { + c.clear(); + break; + } + c.insertMulti(k, t); + } + + return s; +} + +template <typename Container> +QDataStream &writeSequentialContainer(QDataStream &s, const Container &c) +{ + s << quint32(c.size()); + for (const typename Container::value_type &t : c) + s << t; + + return s; +} + +template <typename Container> +QDataStream &writeAssociativeContainer(QDataStream &s, const Container &c) +{ + s << quint32(c.size()); + // Deserialization should occur in the reverse order. + // Otherwise, value() will return the least recently inserted + // value instead of the most recently inserted one. + auto it = c.constEnd(); + auto begin = c.constBegin(); + while (it != begin) { + --it; + s << it.key() << it.value(); + } + + return s; +} + } // QtPrivate namespace /***************************************************************************** @@ -265,209 +358,75 @@ inline QDataStream &QDataStream::operator<<(quint64 i) { return *this << qint64(i); } template <typename T> -QDataStream& operator>>(QDataStream& s, QList<T>& l) +inline QDataStream &operator>>(QDataStream &s, QList<T> &l) { - QtPrivate::StreamStateSaver stateSaver(&s); - - l.clear(); - quint32 c; - s >> c; - l.reserve(c); - for(quint32 i = 0; i < c; ++i) - { - T t; - s >> t; - if (s.status() != QDataStream::Ok) { - l.clear(); - break; - } - l.append(t); - } - - return s; + return QtPrivate::readArrayBasedContainer(s, l); } template <typename T> -QDataStream& operator<<(QDataStream& s, const QList<T>& l) +inline QDataStream &operator<<(QDataStream &s, const QList<T> &l) { - s << quint32(l.size()); - for (int i = 0; i < l.size(); ++i) - s << l.at(i); - return s; + return QtPrivate::writeSequentialContainer(s, l); } template <typename T> -QDataStream& operator>>(QDataStream& s, QLinkedList<T>& l) +inline QDataStream &operator>>(QDataStream &s, QLinkedList<T> &l) { - QtPrivate::StreamStateSaver stateSaver(&s); - - l.clear(); - quint32 c; - s >> c; - for(quint32 i = 0; i < c; ++i) - { - T t; - s >> t; - if (s.status() != QDataStream::Ok) { - l.clear(); - break; - } - l.append(t); - } - - return s; + return QtPrivate::readListBasedContainer(s, l); } template <typename T> -QDataStream& operator<<(QDataStream& s, const QLinkedList<T>& l) +inline QDataStream &operator<<(QDataStream &s, const QLinkedList<T> &l) { - s << quint32(l.size()); - typename QLinkedList<T>::ConstIterator it = l.constBegin(); - for(; it != l.constEnd(); ++it) - s << *it; - return s; + return QtPrivate::writeSequentialContainer(s, l); } template<typename T> -QDataStream& operator>>(QDataStream& s, QVector<T>& v) +inline QDataStream &operator>>(QDataStream &s, QVector<T> &v) { - QtPrivate::StreamStateSaver stateSaver(&s); - - v.clear(); - quint32 c; - s >> c; - v.resize(c); - for(quint32 i = 0; i < c; ++i) { - T t; - s >> t; - if (s.status() != QDataStream::Ok) { - v.clear(); - break; - } - v[i] = t; - } - - return s; + return QtPrivate::readArrayBasedContainer(s, v); } template<typename T> -QDataStream& operator<<(QDataStream& s, const QVector<T>& v) +inline QDataStream &operator<<(QDataStream &s, const QVector<T> &v) { - s << quint32(v.size()); - for (typename QVector<T>::const_iterator it = v.begin(); it != v.end(); ++it) - s << *it; - return s; + return QtPrivate::writeSequentialContainer(s, v); } template <typename T> -QDataStream &operator>>(QDataStream &in, QSet<T> &set) +inline QDataStream &operator>>(QDataStream &s, QSet<T> &set) { - QtPrivate::StreamStateSaver stateSaver(&in); - - set.clear(); - quint32 c; - in >> c; - for (quint32 i = 0; i < c; ++i) { - T t; - in >> t; - if (in.status() != QDataStream::Ok) { - set.clear(); - break; - } - set << t; - } - - return in; + return QtPrivate::readListBasedContainer(s, set); } template <typename T> -QDataStream& operator<<(QDataStream &out, const QSet<T> &set) +inline QDataStream &operator<<(QDataStream &s, const QSet<T> &set) { - out << quint32(set.size()); - typename QSet<T>::const_iterator i = set.constBegin(); - while (i != set.constEnd()) { - out << *i; - ++i; - } - return out; + return QtPrivate::writeSequentialContainer(s, set); } template <class Key, class T> -Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QHash<Key, T> &hash) +inline QDataStream &operator>>(QDataStream &s, QHash<Key, T> &hash) { - QtPrivate::StreamStateSaver stateSaver(&in); - - hash.clear(); - quint32 n; - in >> n; - - for (quint32 i = 0; i < n; ++i) { - if (in.status() != QDataStream::Ok) - break; - - Key k; - T t; - in >> k >> t; - hash.insertMulti(k, t); - } - - if (in.status() != QDataStream::Ok) - hash.clear(); - return in; + return QtPrivate::readAssociativeContainer(s, hash); } template <class Key, class T> -Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash) +inline QDataStream &operator<<(QDataStream &s, const QHash<Key, T> &hash) { - out << quint32(hash.size()); - typename QHash<Key, T>::ConstIterator it = hash.end(); - typename QHash<Key, T>::ConstIterator begin = hash.begin(); - while (it != begin) { - --it; - out << it.key() << it.value(); - } - return out; + return QtPrivate::writeAssociativeContainer(s, hash); } -#ifdef Q_QDOC + template <class Key, class T> -Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<Key, T> &map) -#else -template <class aKey, class aT> -Q_OUTOFLINE_TEMPLATE QDataStream &operator>>(QDataStream &in, QMap<aKey, aT> &map) -#endif +inline QDataStream &operator>>(QDataStream &s, QMap<Key, T> &map) { - QtPrivate::StreamStateSaver stateSaver(&in); - - map.clear(); - quint32 n; - in >> n; - - map.detach(); - for (quint32 i = 0; i < n; ++i) { - if (in.status() != QDataStream::Ok) - break; - - aKey key; - aT value; - in >> key >> value; - map.insertMulti(key, value); - } - if (in.status() != QDataStream::Ok) - map.clear(); - return in; + return QtPrivate::readAssociativeContainer(s, map); } template <class Key, class T> -Q_OUTOFLINE_TEMPLATE QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map) +inline QDataStream &operator<<(QDataStream &s, const QMap<Key, T> &map) { - out << quint32(map.size()); - typename QMap<Key, T>::ConstIterator it = map.end(); - typename QMap<Key, T>::ConstIterator begin = map.begin(); - while (it != begin) { - --it; - out << it.key() << it.value(); - } - return out; + return QtPrivate::writeAssociativeContainer(s, map); } #ifndef QT_NO_DATASTREAM diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index cdb64d08e1..663d9cd61d 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -38,7 +38,7 @@ ****************************************************************************/ #include "qfilesystemengine_p.h" - +#include "qoperatingsystemversion.h" #include "qplatformdefs.h" #include "qsysinfo.h" #include "private/qabstractfileengine_p.h" @@ -637,7 +637,7 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry) FILE_SHARE_READ, OPEN_EXISTING, NULL); #endif // Q_OS_WINRT if (handle) { - result = QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8 ? + result = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ? fileIdWin8(handle) : fileId(handle); CloseHandle(handle); } diff --git a/src/corelib/io/qfilesystemiterator_win.cpp b/src/corelib/io/qfilesystemiterator_win.cpp index 2ce7bd7a4b..9140118872 100644 --- a/src/corelib/io/qfilesystemiterator_win.cpp +++ b/src/corelib/io/qfilesystemiterator_win.cpp @@ -39,6 +39,7 @@ #include "qfilesystemiterator_p.h" #include "qfilesystemengine_p.h" +#include "qoperatingsystemversion.h" #include "qplatformdefs.h" #include "qvector.h" @@ -93,7 +94,7 @@ bool QFileSystemIterator::advance(QFileSystemEntry &fileEntry, QFileSystemMetaDa haveData = true; int infoLevel = 0 ; // FindExInfoStandard; DWORD dwAdditionalFlags = 0; - if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS7) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows7) { dwAdditionalFlags = 2; // FIND_FIRST_EX_LARGE_FETCH infoLevel = 1 ; // FindExInfoBasic; } diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index fcdc1e362b..b67afe0e0f 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -136,7 +136,18 @@ Q_DECLARE_TYPEINFO(QConfFileCustomFormat, Q_MOVABLE_TYPE); typedef QHash<QString, QConfFile *> ConfFileHash; typedef QCache<QString, QConfFile> ConfFileCache; -typedef QHash<int, QString> PathHash; +namespace { + struct Path + { + // Note: Defining constructors explicitly because of buggy C++11 + // implementation in MSVC (uniform initialization). + Path() {} + Path(const QString & p, bool ud) : path(p), userDefined(ud) {} + QString path; + bool userDefined; //!< true - user defined, overridden by setPath + }; +} +typedef QHash<int, Path> PathHash; typedef QVector<QConfFileCustomFormat> CustomFormatVector; Q_GLOBAL_STATIC(ConfFileHash, usedHashFunc) @@ -228,7 +239,7 @@ void QConfFile::clearCache() // QSettingsPrivate QSettingsPrivate::QSettingsPrivate(QSettings::Format format) - : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), spec(0), fallbacks(true), + : format(format), scope(QSettings::UserScope /* nothing better to put */), iniCodec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError) { } @@ -236,7 +247,7 @@ QSettingsPrivate::QSettingsPrivate(QSettings::Format format) QSettingsPrivate::QSettingsPrivate(QSettings::Format format, QSettings::Scope scope, const QString &organization, const QString &application) : format(format), scope(scope), organizationName(organization), applicationName(application), - iniCodec(0), spec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError) + iniCodec(0), fallbacks(true), pendingChanges(false), status(QSettings::NoError) { } @@ -944,7 +955,7 @@ void QConfFileSettingsPrivate::initFormat() void QConfFileSettingsPrivate::initAccess() { - if (confFiles[spec]) { + if (!confFiles.isEmpty()) { if (format > QSettings::IniFormat) { if (!readFunc) setStatus(QSettings::AccessError); @@ -1065,22 +1076,22 @@ static void initDefaultPaths(QMutexLocker *locker) */ #ifdef Q_OS_WIN pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), - windowsConfigPath(CSIDL_APPDATA) + QDir::separator()); + Path(windowsConfigPath(CSIDL_APPDATA) + QDir::separator(), false)); pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), - windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator()); + Path(windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator(), false)); #else const QString userPath = make_user_path(); - pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), userPath); - pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), systemPath); + pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::UserScope), Path(userPath, false)); + pathHash->insert(pathHashKey(QSettings::IniFormat, QSettings::SystemScope), Path(systemPath, false)); #ifndef Q_OS_MAC - pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), userPath); - pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), systemPath); + pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::UserScope), Path(userPath, false)); + pathHash->insert(pathHashKey(QSettings::NativeFormat, QSettings::SystemScope), Path(systemPath, false)); #endif #endif // Q_OS_WIN } } -static QString getPath(QSettings::Format format, QSettings::Scope scope) +static Path getPath(QSettings::Format format, QSettings::Scope scope) { Q_ASSERT((int)QSettings::NativeFormat == 0); Q_ASSERT((int)QSettings::IniFormat == 1); @@ -1090,14 +1101,23 @@ static QString getPath(QSettings::Format format, QSettings::Scope scope) if (pathHash->isEmpty()) initDefaultPaths(&locker); - QString result = pathHash->value(pathHashKey(format, scope)); - if (!result.isEmpty()) + Path result = pathHash->value(pathHashKey(format, scope)); + if (!result.path.isEmpty()) return result; // fall back on INI path return pathHash->value(pathHashKey(QSettings::IniFormat, scope)); } +#if defined(QT_BUILD_INTERNAL) && defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS) +// Note: Suitable only for autotests. +void Q_AUTOTEST_EXPORT clearDefaultPaths() +{ + QMutexLocker locker(&settingsGlobalMutex); + pathHashFunc()->clear(); +} +#endif // QT_BUILD_INTERNAL && Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS + QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format, QSettings::Scope scope, const QString &organization, @@ -1105,7 +1125,6 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format, : QSettingsPrivate(format, scope, organization, application), nextPosition(0x40000000) // big positive number { - int i; initFormat(); QString org = organization; @@ -1118,22 +1137,43 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(QSettings::Format format, QString orgFile = org + extension; if (scope == QSettings::UserScope) { - QString userPath = getPath(format, QSettings::UserScope); + Path userPath = getPath(format, QSettings::UserScope); if (!application.isEmpty()) - confFiles[F_User | F_Application].reset(QConfFile::fromName(userPath + appFile, true)); - confFiles[F_User | F_Organization].reset(QConfFile::fromName(userPath + orgFile, true)); + confFiles.append(QConfFile::fromName(userPath.path + appFile, true)); + confFiles.append(QConfFile::fromName(userPath.path + orgFile, true)); } - QString systemPath = getPath(format, QSettings::SystemScope); - if (!application.isEmpty()) - confFiles[F_System | F_Application].reset(QConfFile::fromName(systemPath + appFile, false)); - confFiles[F_System | F_Organization].reset(QConfFile::fromName(systemPath + orgFile, false)); - - for (i = 0; i < NumConfFiles; ++i) { - if (confFiles[i]) { - spec = i; - break; + Path systemPath = getPath(format, QSettings::SystemScope); +#if defined(Q_XDG_PLATFORM) && !defined(QT_NO_STANDARDPATHS) + // check if the systemPath wasn't overridden by QSettings::setPath() + if (!systemPath.userDefined) { + // Note: We can't use QStandardPaths::locateAll() as we need all the + // possible files (not just the existing ones) and there is no way + // to exclude user specific (XDG_CONFIG_HOME) directory from the search. + QStringList dirs = QStandardPaths::standardLocations(QStandardPaths::GenericConfigLocation); + // remove the QStandardLocation::writableLocation() (XDG_CONFIG_HOME) + if (!dirs.isEmpty()) + dirs.takeFirst(); + QStringList paths; + if (!application.isEmpty()) { + paths.reserve(dirs.size() * 2); + for (const auto &dir : qAsConst(dirs)) + paths.append(dir + QLatin1Char('/') + appFile); + } else { + paths.reserve(dirs.size()); } + for (const auto &dir : qAsConst(dirs)) + paths.append(dir + QLatin1Char('/') + orgFile); + + // Note: No check for existence of files is done intentionaly. + for (const auto &path : qAsConst(paths)) + confFiles.append(QConfFile::fromName(path, false)); + } else +#endif // Q_XDG_PLATFORM && !QT_NO_STANDARDPATHS + { + if (!application.isEmpty()) + confFiles.append(QConfFile::fromName(systemPath.path + appFile, false)); + confFiles.append(QConfFile::fromName(systemPath.path + orgFile, false)); } initAccess(); @@ -1146,7 +1186,7 @@ QConfFileSettingsPrivate::QConfFileSettingsPrivate(const QString &fileName, { initFormat(); - confFiles[0].reset(QConfFile::fromName(fileName, true)); + confFiles.append(QConfFile::fromName(fileName, true)); initAccess(); } @@ -1157,40 +1197,39 @@ QConfFileSettingsPrivate::~QConfFileSettingsPrivate() ConfFileHash *usedHash = usedHashFunc(); ConfFileCache *unusedCache = unusedCacheFunc(); - for (int i = 0; i < NumConfFiles; ++i) { - if (confFiles[i] && !confFiles[i]->ref.deref()) { - if (confFiles[i]->size == 0) { - delete confFiles[i].take(); + for (auto conf_file : qAsConst(confFiles)) { + if (!conf_file->ref.deref()) { + if (conf_file->size == 0) { + delete conf_file; } else { if (usedHash) - usedHash->remove(confFiles[i]->name); + usedHash->remove(conf_file->name); if (unusedCache) { QT_TRY { // compute a better size? - unusedCache->insert(confFiles[i]->name, confFiles[i].data(), - 10 + (confFiles[i]->originalKeys.size() / 4)); - confFiles[i].take(); + unusedCache->insert(conf_file->name, conf_file, + 10 + (conf_file->originalKeys.size() / 4)); } QT_CATCH(...) { // out of memory. Do not cache the file. - delete confFiles[i].take(); + delete conf_file; } } else { // unusedCache is gone - delete the entry to prevent a memory leak - delete confFiles[i].take(); + delete conf_file; } } } - // prevent the ScopedPointer to deref it again. - confFiles[i].take(); } } void QConfFileSettingsPrivate::remove(const QString &key) { - QConfFile *confFile = confFiles[spec].data(); - if (!confFile) + if (confFiles.isEmpty()) return; + // Note: First config file is always the most specific. + QConfFile *confFile = confFiles.at(0); + QSettingsKey theKey(key, caseSensitivity); QSettingsKey prefix(key + QLatin1Char('/'), caseSensitivity); QMutexLocker locker(&confFile->mutex); @@ -1214,10 +1253,12 @@ void QConfFileSettingsPrivate::remove(const QString &key) void QConfFileSettingsPrivate::set(const QString &key, const QVariant &value) { - QConfFile *confFile = confFiles[spec].data(); - if (!confFile) + if (confFiles.isEmpty()) return; + // Note: First config file is always the most specific. + QConfFile *confFile = confFiles.at(0); + QSettingsKey theKey(key, caseSensitivity, nextPosition++); QMutexLocker locker(&confFile->mutex); confFile->removedKeys.remove(theKey); @@ -1230,29 +1271,27 @@ bool QConfFileSettingsPrivate::get(const QString &key, QVariant *value) const ParsedSettingsMap::const_iterator j; bool found = false; - for (int i = 0; i < NumConfFiles; ++i) { - if (QConfFile *confFile = confFiles[i].data()) { - QMutexLocker locker(&confFile->mutex); + for (auto confFile : qAsConst(confFiles)) { + QMutexLocker locker(&confFile->mutex); - if (!confFile->addedKeys.isEmpty()) { - j = confFile->addedKeys.constFind(theKey); - found = (j != confFile->addedKeys.constEnd()); - } - if (!found) { - ensureSectionParsed(confFile, theKey); - j = confFile->originalKeys.constFind(theKey); - found = (j != confFile->originalKeys.constEnd() - && !confFile->removedKeys.contains(theKey)); - } + if (!confFile->addedKeys.isEmpty()) { + j = confFile->addedKeys.constFind(theKey); + found = (j != confFile->addedKeys.constEnd()); + } + if (!found) { + ensureSectionParsed(confFile, theKey); + j = confFile->originalKeys.constFind(theKey); + found = (j != confFile->originalKeys.constEnd() + && !confFile->removedKeys.contains(theKey)); + } - if (found && value) - *value = *j; + if (found && value) + *value = *j; - if (found) - return true; - if (!fallbacks) - break; - } + if (found) + return true; + if (!fallbacks) + break; } return false; } @@ -1265,34 +1304,31 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec QSettingsKey thePrefix(prefix, caseSensitivity); int startPos = prefix.size(); - for (int i = 0; i < NumConfFiles; ++i) { - if (QConfFile *confFile = confFiles[i].data()) { - QMutexLocker locker(&confFile->mutex); + for (auto confFile : qAsConst(confFiles)) { + QMutexLocker locker(&confFile->mutex); - if (thePrefix.isEmpty()) { - ensureAllSectionsParsed(confFile); - } else { - ensureSectionParsed(confFile, thePrefix); - } - - j = const_cast<const ParsedSettingsMap *>( - &confFile->originalKeys)->lowerBound( thePrefix); - while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) { - if (!confFile->removedKeys.contains(j.key())) - processChild(j.key().originalCaseKey().midRef(startPos), spec, result); - ++j; - } + if (thePrefix.isEmpty()) + ensureAllSectionsParsed(confFile); + else + ensureSectionParsed(confFile, thePrefix); - j = const_cast<const ParsedSettingsMap *>( - &confFile->addedKeys)->lowerBound(thePrefix); - while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) { + j = const_cast<const ParsedSettingsMap *>( + &confFile->originalKeys)->lowerBound( thePrefix); + while (j != confFile->originalKeys.constEnd() && j.key().startsWith(thePrefix)) { + if (!confFile->removedKeys.contains(j.key())) processChild(j.key().originalCaseKey().midRef(startPos), spec, result); - ++j; - } + ++j; + } - if (!fallbacks) - break; + j = const_cast<const ParsedSettingsMap *>( + &confFile->addedKeys)->lowerBound(thePrefix); + while (j != confFile->addedKeys.constEnd() && j.key().startsWith(thePrefix)) { + processChild(j.key().originalCaseKey().midRef(startPos), spec, result); + ++j; } + + if (!fallbacks) + break; } std::sort(result.begin(), result.end()); result.erase(std::unique(result.begin(), result.end()), @@ -1302,10 +1338,12 @@ QStringList QConfFileSettingsPrivate::children(const QString &prefix, ChildSpec void QConfFileSettingsPrivate::clear() { - QConfFile *confFile = confFiles[spec].data(); - if (!confFile) + if (confFiles.isEmpty()) return; + // Note: First config file is always the most specific. + QConfFile *confFile = confFiles.at(0); + QMutexLocker locker(&confFile->mutex); ensureAllSectionsParsed(confFile); confFile->addedKeys.clear(); @@ -1317,12 +1355,9 @@ void QConfFileSettingsPrivate::sync() // people probably won't be checking the status a whole lot, so in case of // error we just try to go on and make the best of it - for (int i = 0; i < NumConfFiles; ++i) { - QConfFile *confFile = confFiles[i].data(); - if (confFile) { - QMutexLocker locker(&confFile->mutex); - syncConfFile(i); - } + for (auto confFile : qAsConst(confFiles)) { + QMutexLocker locker(&confFile->mutex); + syncConfFile(confFile); } } @@ -1333,10 +1368,11 @@ void QConfFileSettingsPrivate::flush() QString QConfFileSettingsPrivate::fileName() const { - QConfFile *confFile = confFiles[spec].data(); - if (!confFile) + if (confFiles.isEmpty()) return QString(); - return confFile->name; + + // Note: First config file is always the most specific. + return confFiles.at(0)->name; } bool QConfFileSettingsPrivate::isWritable() const @@ -1344,16 +1380,14 @@ bool QConfFileSettingsPrivate::isWritable() const if (format > QSettings::IniFormat && !writeFunc) return false; - QConfFile *confFile = confFiles[spec].data(); - if (!confFile) + if (confFiles.isEmpty()) return false; - return confFile->isWritable(); + return confFiles.at(0)->isWritable(); } -void QConfFileSettingsPrivate::syncConfFile(int confFileNo) +void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile) { - QConfFile *confFile = confFiles[confFileNo].data(); bool readOnly = confFile->addedKeys.isEmpty() && confFile->removedKeys.isEmpty(); /* @@ -2183,9 +2217,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, \list 1 \li \c{$HOME/.config/MySoft/Star Runner.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.conf}) \li \c{$HOME/.config/MySoft.conf} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.conf}) - \li \c{/etc/xdg/MySoft/Star Runner.conf} - \li \c{/etc/xdg/MySoft.conf} + \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.conf} + \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.conf} \endlist + \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used. On \macos versions 10.2 and 10.3, these files are used by default: @@ -2220,9 +2255,10 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, \list 1 \li \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini}) \li \c{$HOME/.config/MySoft.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft.ini}) - \li \c{/etc/xdg/MySoft/Star Runner.ini} - \li \c{/etc/xdg/MySoft.ini} + \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft/Star Runner.ini} + \li for each directory <dir> in $XDG_CONFIG_DIRS: \c{<dir>/MySoft.ini} \endlist + \note If XDG_CONFIG_DIRS is unset, the default value of \c{/etc/xdg} is used. On Windows, the following files are used: @@ -3374,7 +3410,7 @@ void QSettings::setPath(Format format, Scope scope, const QString &path) PathHash *pathHash = pathHashFunc(); if (pathHash->isEmpty()) initDefaultPaths(&locker); - pathHash->insert(pathHashKey(format, scope), path + QDir::separator()); + pathHash->insert(pathHashKey(format, scope), Path(path + QDir::separator(), true)); } /*! diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp index bc397055ff..4ad5a7b398 100644 --- a/src/corelib/io/qsettings_mac.cpp +++ b/src/corelib/io/qsettings_mac.cpp @@ -419,20 +419,15 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString & javaPackageName.prepend(QLatin1String("com.")); suiteId = javaPackageName; - if (scope == QSettings::SystemScope) - spec |= F_System; - - if (application.isEmpty()) { - spec |= F_Organization; - } else { + if (!application.isEmpty()) { javaPackageName += QLatin1Char('.'); javaPackageName += application; applicationId = javaPackageName; } numDomains = 0; - for (int i = (spec & F_System) ? 1 : 0; i < 2; ++i) { - for (int j = (spec & F_Organization) ? 1 : 0; j < 3; ++j) { + for (int i = (scope == QSettings::SystemScope) ? 1 : 0; i < 2; ++i) { + for (int j = (application.isEmpty()) ? 1 : 0; j < 3; ++j) { SearchDomain &domain = domains[numDomains++]; domain.userName = (i == 0) ? kCFPreferencesCurrentUser : kCFPreferencesAnyUser; if (j == 0) @@ -573,7 +568,7 @@ bool QMacSettingsPrivate::isWritable() const QString QMacSettingsPrivate::fileName() const { QString result; - if ((spec & F_System) == 0) + if (scope == QSettings::UserScope) result = QDir::homePath(); result += QLatin1String("/Library/Preferences/"); result += QCFString::toQString(domains[0].applicationOrSuiteId); diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index e6d3413bab..639605d8c4 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -236,19 +236,6 @@ public: QTextCodec *codec); static QStringList splitArgs(const QString &s, int idx); - /* - The numeric values of these enums define their search order. For example, - F_User | F_Organization is searched before F_System | F_Application, - because their values are respectively 1 and 2. - */ - enum { - F_Application = 0x0, - F_Organization = 0x1, - F_User = 0x0, - F_System = 0x2, - NumConfFiles = 4 - }; - QSettings::Format format; QSettings::Scope scope; QString organizationName; @@ -258,7 +245,6 @@ public: protected: QStack<QSettingsGroup> groupStack; QString groupPrefix; - int spec; bool fallbacks; bool pendingChanges; mutable QSettings::Status status; @@ -293,7 +279,7 @@ public: private: void initFormat(); void initAccess(); - void syncConfFile(int confFileNo); + void syncConfFile(QConfFile *confFile); bool writeIniFile(QIODevice &device, const ParsedSettingsMap &map); #ifdef Q_OS_MAC bool readPlistFile(const QByteArray &data, ParsedSettingsMap *map) const; @@ -302,7 +288,7 @@ private: void ensureAllSectionsParsed(QConfFile *confFile) const; void ensureSectionParsed(QConfFile *confFile, const QSettingsKey &key) const; - QScopedSharedPointer<QConfFile> confFiles[NumConfFiles]; + QVector<QConfFile *> confFiles; QSettings::ReadFunc readFunc; QSettings::WriteFunc writeFunc; QString extension; diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp index 3773b72606..9885da1af9 100644 --- a/src/corelib/io/qstorageinfo.cpp +++ b/src/corelib/io/qstorageinfo.cpp @@ -260,7 +260,7 @@ QByteArray QStorageInfo::fileSystemType() const devpath like \c /dev/sda0 for local storages. On Windows, it returns the UNC path starting with \c \\\\?\\ for local storages (in other words, the volume GUID). - \sa rootPath() + \sa rootPath(), subvolume() */ QByteArray QStorageInfo::device() const { @@ -268,6 +268,26 @@ QByteArray QStorageInfo::device() const } /*! + \since 5.8 + Returns the subvolume name for this volume. + + Some filesystem types allow multiple subvolumes inside one device, which + may be mounted in different paths. If the subvolume could be detected, it + is returned here. The format of the subvolume name is specific to each + filesystem type. + + If this volume was not mounted from a subvolume of a larger filesystem or + if the subvolume could not be detected, this function returns an empty byte + array. + + \sa device() +*/ +QByteArray QStorageInfo::subvolume() const +{ + return d->subvolume; +} + +/*! Returns the human-readable name of a filesystem, usually called \c label. Not all filesystems support this feature. In this case, the value returned by diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h index 8941c11a16..e2d9747ceb 100644 --- a/src/corelib/io/qstorageinfo.h +++ b/src/corelib/io/qstorageinfo.h @@ -71,6 +71,7 @@ public: QString rootPath() const; QByteArray device() const; + QByteArray subvolume() const; QByteArray fileSystemType() const; QString name() const; QString displayName() const; @@ -100,7 +101,7 @@ inline bool operator==(const QStorageInfo &first, const QStorageInfo &second) { if (first.d == second.d) return true; - return first.device() == second.device(); + return first.device() == second.device() && first.rootPath() == second.rootPath(); } inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second) diff --git a/src/corelib/io/qstorageinfo_p.h b/src/corelib/io/qstorageinfo_p.h index a14fa8480a..ec5bb785e3 100644 --- a/src/corelib/io/qstorageinfo_p.h +++ b/src/corelib/io/qstorageinfo_p.h @@ -85,6 +85,7 @@ protected: public: QString rootPath; QByteArray device; + QByteArray subvolume; QByteArray fileSystemType; QString name; diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index ae5c42ffd1..fcc7b8ca50 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -120,6 +120,7 @@ public: inline QString rootPath() const; inline QByteArray fileSystemType() const; inline QByteArray device() const; + inline QByteArray options() const; private: #if defined(Q_OS_BSD4) QT_STATFSBUF *stat_buf; @@ -133,6 +134,7 @@ private: QByteArray m_rootPath; QByteArray m_fileSystemType; QByteArray m_device; + QByteArray m_options; #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD) FILE *fp; mntent mnt; @@ -228,6 +230,11 @@ inline QByteArray QStorageIterator::device() const return QByteArray(stat_buf[currentIndex].f_mntfromname); } +inline QByteArray QStorageIterator::options() const +{ + return QByteArray(); +} + #elif defined(Q_OS_SOLARIS) static const char pathMounted[] = "/etc/mnttab"; @@ -301,6 +308,7 @@ inline bool QStorageIterator::next() m_device = data.at(0); m_rootPath = data.at(1); m_fileSystemType = data.at(2); + m_options = data.at(3); return true; } @@ -320,6 +328,11 @@ inline QByteArray QStorageIterator::device() const return m_device; } +inline QByteArray QStorageIterator::options() const +{ + return m_options; +} + #elif defined(Q_OS_LINUX) || defined(Q_OS_HURD) static const char pathMounted[] = "/etc/mtab"; @@ -363,6 +376,11 @@ inline QByteArray QStorageIterator::device() const return QByteArray(mnt.mnt_fsname); } +inline QByteArray QStorageIterator::options() const +{ + return QByteArray(mnt.mnt_opts); +} + #elif defined(Q_OS_HAIKU) inline QStorageIterator::QStorageIterator() { @@ -420,6 +438,11 @@ inline QByteArray QStorageIterator::device() const return m_device; } +inline QByteArray QStorageIterator::options() const +{ + return QByteArray(); +} + #else inline QStorageIterator::QStorageIterator() @@ -455,8 +478,35 @@ inline QByteArray QStorageIterator::device() const return QByteArray(); } +inline QByteArray QStorageIterator::options() const +{ + return QByteArray(); +} + #endif +static QByteArray extractSubvolume(const QStorageIterator &it) +{ +#ifdef Q_OS_LINUX + if (it.fileSystemType() == "btrfs") { + const QByteArrayList opts = it.options().split(','); + QByteArray id; + for (const QByteArray &opt : opts) { + static const char subvol[] = "subvol="; + static const char subvolid[] = "subvolid="; + if (opt.startsWith(subvol)) + return std::move(opt).mid(strlen(subvol)); + if (opt.startsWith(subvolid)) + id = std::move(opt).mid(strlen(subvolid)); + } + + // if we didn't find the subvolume name, return the subvolume ID + return id; + } +#endif + return QByteArray(); +} + void QStorageInfoPrivate::initRootPath() { rootPath = QFileInfo(rootPath).canonicalFilePath(); @@ -483,6 +533,7 @@ void QStorageInfoPrivate::initRootPath() rootPath = mountDir; device = it.device(); fileSystemType = fsName; + subvolume = extractSubvolume(it); } } } diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp index 6e50a8513e..b2bf9fce97 100644 --- a/src/corelib/io/qtemporarydir.cpp +++ b/src/corelib/io/qtemporarydir.cpp @@ -305,6 +305,33 @@ QString QTemporaryDir::path() const } /*! + \since 5.9 + + Returns the path name of a file in the temporary directory. + Does \e not check if the file actually exists in the directory. + Redundant multiple separators or "." and ".." directories in + \a fileName are not removed (see QDir::cleanPath()). Absolute + paths are not allowed. +*/ +QString QTemporaryDir::filePath(const QString &fileName) const +{ + if (QDir::isAbsolutePath(fileName)) { + qWarning("QTemporaryDir::filePath: Absolute paths are not allowed: %s", qUtf8Printable(fileName)); + return QString(); + } + + if (!d_ptr->success) + return QString(); + + QString ret = d_ptr->pathOrError; + if (!fileName.isEmpty()) { + ret += QLatin1Char('/'); + ret += fileName; + } + return ret; +} + +/*! Returns \c true if the QTemporaryDir is in auto remove mode. Auto-remove mode will automatically delete the directory from disk upon destruction. This makes it very easy to create your diff --git a/src/corelib/io/qtemporarydir.h b/src/corelib/io/qtemporarydir.h index 2e70d34ae4..3f6b70a2eb 100644 --- a/src/corelib/io/qtemporarydir.h +++ b/src/corelib/io/qtemporarydir.h @@ -65,6 +65,7 @@ public: bool remove(); QString path() const; + QString filePath(const QString &fileName) const; private: QScopedPointer<QTemporaryDirPrivate> d_ptr; diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp index 4fdb1505ff..9b565bff9d 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/io/qtextstream.cpp @@ -2547,6 +2547,7 @@ QTextStream &QTextStream::operator<<(double f) } uint flags = 0; + const QLocale::NumberOptions numberOptions = locale().numberOptions(); if (numberFlags() & ShowBase) flags |= QLocaleData::ShowBase; if (numberFlags() & ForceSign) @@ -2555,12 +2556,18 @@ QTextStream &QTextStream::operator<<(double f) flags |= QLocaleData::UppercaseBase; if (numberFlags() & UppercaseDigits) flags |= QLocaleData::CapitalEorX; - if (numberFlags() & ForcePoint) - flags |= QLocaleData::Alternate; - if (locale() != QLocale::c() && !(locale().numberOptions() & QLocale::OmitGroupSeparator)) + if (numberFlags() & ForcePoint) { + flags |= QLocaleData::ForcePoint; + + // Only for backwards compatibility + flags |= QLocaleData::AddTrailingZeroes | QLocaleData::ShowBase; + } + if (locale() != QLocale::c() && !(numberOptions & QLocale::OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; - if (!(locale().numberOptions() & QLocale::OmitLeadingZeroInExponent)) + if (!(numberOptions & QLocale::OmitLeadingZeroInExponent)) flags |= QLocaleData::ZeroPadExponent; + if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot) + flags |= QLocaleData::AddTrailingZeroes; const QLocaleData *dd = d->locale.d->m_data; QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags); diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm index ee1a290386..42f5699928 100644 --- a/src/corelib/kernel/qcore_mac_objc.mm +++ b/src/corelib/kernel/qcore_mac_objc.mm @@ -47,14 +47,8 @@ #include <qdebug.h> -#if defined(Q_OS_IOS) -#import <UIKit/UIKit.h> -#endif - QT_BEGIN_NAMESPACE -typedef qint16 (*GestaltFunction)(quint32 selector, qint32 *response); - NSString *QCFString::toNSString(const QString &string) { // The const cast below is safe: CfStringRef is immutable and so is NSString. @@ -98,54 +92,6 @@ QT_FOR_EACH_MUTABLE_CORE_GRAPHICS_TYPE(QT_DECLARE_WEAK_QDEBUG_OPERATOR_FOR_CF_TY // ------------------------------------------------------------------------- -QAppleOperatingSystemVersion qt_apple_os_version() -{ - QAppleOperatingSystemVersion v = {0, 0, 0}; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_8_0) || defined(Q_OS_TVOS) || defined(Q_OS_WATCHOS) - if ([NSProcessInfo instancesRespondToSelector:@selector(operatingSystemVersion)]) { - NSOperatingSystemVersion osv = NSProcessInfo.processInfo.operatingSystemVersion; - v.major = osv.majorVersion; - v.minor = osv.minorVersion; - v.patch = osv.patchVersion; - return v; - } -#endif - // Use temporary variables so we can return 0.0.0 (unknown version) - // in case of an error partway through determining the OS version - qint32 major = 0, minor = 0, patch = 0; -#if QT_MAC_DEPLOYMENT_TARGET_BELOW(__MAC_10_10, __IPHONE_8_0) -#if defined(Q_OS_IOS) - @autoreleasepool { - NSArray *parts = [UIDevice.currentDevice.systemVersion componentsSeparatedByString:@"."]; - major = parts.count > 0 ? [[parts objectAtIndex:0] intValue] : 0; - minor = parts.count > 1 ? [[parts objectAtIndex:1] intValue] : 0; - patch = parts.count > 2 ? [[parts objectAtIndex:2] intValue] : 0; - } -#elif defined(Q_OS_OSX) - static GestaltFunction pGestalt = 0; - if (!pGestalt) { - CFBundleRef b = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.CoreServices")); - pGestalt = reinterpret_cast<GestaltFunction>(CFBundleGetFunctionPointerForName(b, - CFSTR("Gestalt"))); - } - if (!pGestalt) - return v; - if (pGestalt('sys1', &major) != 0) - return v; - if (pGestalt('sys2', &minor) != 0) - return v; - if (pGestalt('sys3', &patch) != 0) - return v; -#endif -#endif - v.major = major; - v.minor = minor; - v.patch = patch; - return v; -} - -// ------------------------------------------------------------------------- - QMacAutoReleasePool::QMacAutoReleasePool() : pool([[NSAutoreleasePool alloc] init]) { diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 63e1cb48dc..8a710a8a1f 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -137,12 +137,6 @@ private: QString string; }; -typedef struct { - int major, minor, patch; -} QAppleOperatingSystemVersion; - -QAppleOperatingSystemVersion qt_apple_os_version(); - #ifdef Q_OS_OSX Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key); Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode); diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 1a0efae2dc..ebeb083abf 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -42,6 +42,7 @@ #include "qcoreapplication.h" #include <private/qsystemlibrary_p.h> +#include "qoperatingsystemversion.h" #include "qpair.h" #include "qset.h" #include "qsocketnotifier.h" @@ -236,7 +237,7 @@ static inline UINT inputTimerMask() // QTBUG 28513, QTBUG-29097, QTBUG-29435: QS_TOUCH, QS_POINTER became part of // QS_INPUT in Windows Kit 8. They should not be used when running on pre-Windows 8. #if WINVER > 0x0601 - if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) result &= ~(QS_TOUCH | QS_POINTER); #endif // WINVER > 0x0601 return result; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 63b02d2c0c..d7cc0bce46 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -3943,7 +3943,6 @@ QList<QByteArray> QObject::dynamicPropertyNames() const static void dumpRecursive(int level, QObject *object) { -#if defined(QT_DEBUG) if (object) { QByteArray buf; buf.fill(' ', level / 2 * 8); @@ -3972,19 +3971,11 @@ static void dumpRecursive(int level, QObject *object) dumpRecursive(level+1, children.at(i)); } } -#else - Q_UNUSED(level) - Q_UNUSED(object) -#endif } /*! Dumps a tree of children to the debug output. - This function is useful for debugging, but does nothing if the - library has been compiled in release mode (i.e. without debugging - information). - \sa dumpObjectInfo() */ @@ -3997,16 +3988,11 @@ void QObject::dumpObjectTree() Dumps information about signal connections, etc. for this object to the debug output. - This function is useful for debugging, but does nothing if the - library has been compiled in release mode (i.e. without debugging - information). - \sa dumpObjectTree() */ void QObject::dumpObjectInfo() { -#if defined(QT_DEBUG) qDebug("OBJECT %s::%s", metaObject()->className(), objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data()); @@ -4066,7 +4052,6 @@ void QObject::dumpObjectInfo() } else { qDebug(" <None>"); } -#endif } #ifndef QT_NO_USERDATA diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 55af7256be..a04536b18b 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -63,6 +63,29 @@ QT_WARNING_POP static const QArrayData &qt_array_empty = qt_array[0]; static const QArrayData &qt_array_unsharable_empty = qt_array[1]; +static inline size_t calculateBlockSize(size_t &capacity, size_t objectSize, size_t headerSize, + uint options) +{ + // Calculate the byte size + // allocSize = objectSize * capacity + headerSize, but checked for overflow + // plus padded to grow in size + if (options & QArrayData::Grow) { + auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize); + capacity = r.elementCount; + return r.size; + } else { + return qCalculateBlockSize(capacity, objectSize, headerSize); + } +} + +static QArrayData *reallocateData(QArrayData *header, size_t allocSize, uint options) +{ + header = static_cast<QArrayData *>(::realloc(header, allocSize)); + if (header) + header->capacityReserved = bool(options & QArrayData::CapacityReserved); + return header; +} + QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, size_t capacity, AllocationOptions options) Q_DECL_NOTHROW { @@ -91,18 +114,7 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, if (headerSize > size_t(MaxAllocSize)) return 0; - // Calculate the byte size - // allocSize = objectSize * capacity + headerSize, but checked for overflow - // plus padded to grow in size - size_t allocSize; - if (options & Grow) { - auto r = qCalculateGrowingBlockSize(capacity, objectSize, headerSize); - capacity = r.elementCount; - allocSize = r.size; - } else { - allocSize = qCalculateBlockSize(capacity, objectSize, headerSize); - } - + size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); QArrayData *header = static_cast<QArrayData *>(::malloc(allocSize)); if (header) { quintptr data = (quintptr(header) + sizeof(QArrayData) + alignment - 1) @@ -122,6 +134,21 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, return header; } +QArrayData *QArrayData::reallocateUnaligned(QArrayData *data, size_t objectSize, size_t capacity, + AllocationOptions options) Q_DECL_NOTHROW +{ + Q_ASSERT(data); + Q_ASSERT(data->isMutable()); + Q_ASSERT(!data->ref.isShared()); + + size_t headerSize = sizeof(QArrayData); + size_t allocSize = calculateBlockSize(capacity, objectSize, headerSize, options); + QArrayData *header = static_cast<QArrayData *>(reallocateData(data, allocSize, options)); + if (header) + header->alloc = capacity; + return header; +} + void QArrayData::deallocate(QArrayData *data, size_t objectSize, size_t alignment) Q_DECL_NOTHROW { diff --git a/src/corelib/tools/qarraydata.h b/src/corelib/tools/qarraydata.h index 5a369baf08..bc20932cca 100644 --- a/src/corelib/tools/qarraydata.h +++ b/src/corelib/tools/qarraydata.h @@ -115,6 +115,9 @@ struct Q_CORE_EXPORT QArrayData static QArrayData *allocate(size_t objectSize, size_t alignment, size_t capacity, AllocationOptions options = Default) Q_DECL_NOTHROW Q_REQUIRED_RESULT; + static QArrayData *reallocateUnaligned(QArrayData *data, size_t objectSize, + size_t newCapacity, AllocationOptions newOptions = Default) + Q_DECL_NOTHROW Q_REQUIRED_RESULT; static void deallocate(QArrayData *data, size_t objectSize, size_t alignment) Q_DECL_NOTHROW; @@ -222,6 +225,14 @@ struct QTypedArrayData Q_ALIGNOF(AlignmentDummy), capacity, options)); } + static QTypedArrayData *reallocateUnaligned(QTypedArrayData *data, size_t capacity, + AllocationOptions options = Default) + { + Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData)); + return static_cast<QTypedArrayData *>(QArrayData::reallocateUnaligned(data, sizeof(T), + capacity, options)); + } + static void deallocate(QArrayData *data) { Q_STATIC_ASSERT(sizeof(QTypedArrayData) == sizeof(QArrayData)); diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 9298472305..7d9c5dc325 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -663,6 +663,20 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel) */ #ifndef QT_NO_COMPRESS +namespace { +struct QByteArrayDataDeleter +{ + static inline void cleanup(QTypedArrayData<char> *d) + { if (d) QTypedArrayData<char>::deallocate(d); } +}; +} + +static QByteArray invalidCompressedData() +{ + qWarning("qUncompress: Input data is corrupted"); + return QByteArray(); +} + QByteArray qUncompress(const uchar* data, int nbytes) { if (!data) { @@ -677,53 +691,29 @@ QByteArray qUncompress(const uchar* data, int nbytes) ulong expectedSize = uint((data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] )); ulong len = qMax(expectedSize, 1ul); - QScopedPointer<QByteArray::Data, QScopedPointerPodDeleter> d; + const ulong maxPossibleSize = MaxAllocSize - sizeof(QByteArray::Data); + if (Q_UNLIKELY(len >= maxPossibleSize)) { + // QByteArray does not support that huge size anyway. + return invalidCompressedData(); + } + QScopedPointer<QByteArray::Data, QByteArrayDataDeleter> d(QByteArray::Data::allocate(expectedSize + 1)); + if (Q_UNLIKELY(d.data() == nullptr)) + return invalidCompressedData(); + + d->size = expectedSize; forever { ulong alloc = len; - if (len >= (1u << 31u) - sizeof(QByteArray::Data)) { - //QByteArray does not support that huge size anyway. - qWarning("qUncompress: Input data is corrupted"); - return QByteArray(); - } - QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + alloc + 1)); - if (!p) { - // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS - qWarning("qUncompress: could not allocate enough memory to uncompress data"); - return QByteArray(); - } - d.take(); // realloc was successful - d.reset(p); - d->offset = sizeof(QByteArrayData); - d->size = 0; // Shut up valgrind "uninitialized variable" warning int res = ::uncompress((uchar*)d->data(), &len, data+4, nbytes-4); switch (res) { case Z_OK: - if (len != alloc) { - if (len >= (1u << 31u) - sizeof(QByteArray::Data)) { - //QByteArray does not support that huge size anyway. - qWarning("qUncompress: Input data is corrupted"); - return QByteArray(); - } - QByteArray::Data *p = static_cast<QByteArray::Data *>(::realloc(d.data(), sizeof(QByteArray::Data) + len + 1)); - if (!p) { - // we are not allowed to crash here when compiling with QT_NO_EXCEPTIONS - qWarning("qUncompress: could not allocate enough memory to uncompress data"); - return QByteArray(); - } - d.take(); // realloc was successful - d.reset(p); - } - d->ref.initializeOwned(); + Q_ASSERT(len <= alloc); + Q_UNUSED(alloc); d->size = len; - d->alloc = uint(len) + 1u; - d->capacityReserved = false; - d->offset = sizeof(QByteArrayData); d->data()[len] = 0; - { QByteArrayDataPtr dataPtr = { d.take() }; return QByteArray(dataPtr); @@ -735,6 +725,17 @@ QByteArray qUncompress(const uchar* data, int nbytes) case Z_BUF_ERROR: len *= 2; + if (Q_UNLIKELY(len >= maxPossibleSize)) { + // QByteArray does not support that huge size anyway. + return invalidCompressedData(); + } else { + // grow the block + QByteArray::Data *p = QByteArray::Data::reallocateUnaligned(d.data(), len + 1); + if (Q_UNLIKELY(p == nullptr)) + return invalidCompressedData(); + d.take(); // don't free + d.reset(p); + } continue; case Z_DATA_ERROR: @@ -1707,19 +1708,8 @@ void QByteArray::reallocData(uint alloc, Data::AllocationOptions options) Data::deallocate(d); d = x; } else { - size_t blockSize; - if (options & Data::Grow) { - auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data)); - blockSize = r.size; - alloc = uint(r.elementCount); - } else { - blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data)); - } - - Data *x = static_cast<Data *>(::realloc(d, blockSize)); + Data *x = Data::reallocateUnaligned(d, alloc, options); Q_CHECK_PTR(x); - x->alloc = alloc; - x->capacityReserved = (options & Data::CapacityReserved) ? 1 : 0; d = x; } } diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index f8611b3e68..ac8054ce82 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -926,7 +926,7 @@ QString QDate::toString(Qt::DateFormat format) const */ QString QDate::toString(const QString& format) const { - return QLocale::system().toString(*this, format); + return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6 } #endif //QT_NO_DATESTRING @@ -1330,6 +1330,7 @@ QDate QDate::fromString(const QString &string, const QString &format) QDate date; #ifndef QT_BOOTSTRAPPED QDateTimeParser dt(QVariant::Date, QDateTimeParser::FromString); + // dt.setDefaultLocale(QLocale::c()); ### Qt 6 if (dt.parseFormat(format)) dt.fromString(string, &date, 0); #else @@ -1666,7 +1667,7 @@ QString QTime::toString(Qt::DateFormat format) const */ QString QTime::toString(const QString& format) const { - return QLocale::system().toString(*this, format); + return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6 } #endif //QT_NO_DATESTRING /*! @@ -2018,6 +2019,7 @@ QTime QTime::fromString(const QString &string, const QString &format) QTime time; #ifndef QT_BOOTSTRAPPED QDateTimeParser dt(QVariant::Time, QDateTimeParser::FromString); + // dt.setDefaultLocale(QLocale::c()); ### Qt 6 if (dt.parseFormat(format)) dt.fromString(string, 0, &time); #else @@ -3881,7 +3883,7 @@ QString QDateTime::toString(Qt::DateFormat format) const */ QString QDateTime::toString(const QString& format) const { - return QLocale::system().toString(*this, format); + return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6 } #endif //QT_NO_DATESTRING @@ -4934,6 +4936,7 @@ QDateTime QDateTime::fromString(const QString &string, const QString &format) QDate date; QDateTimeParser dt(QVariant::DateTime, QDateTimeParser::FromString); + // dt.setDefaultLocale(QLocale::c()); ### Qt 6 if (dt.parseFormat(format) && dt.fromString(string, &date, &time)) return QDateTime(date, time); #else diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 7809c513d6..c25ee5ffbe 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -2024,6 +2024,8 @@ QString QLocale::toString(double i, char f, int prec) const flags |= QLocaleData::ThousandsGroup; if (!(d->m_numberOptions & OmitLeadingZeroInExponent)) flags |= QLocaleData::ZeroPadExponent; + if (d->m_numberOptions & IncludeTrailingZeroesAfterDot) + flags |= QLocaleData::AddTrailingZeroes; return d->m_data->doubleToString(i, prec, form, -1, flags); } @@ -2785,7 +2787,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q reinterpret_cast<ushort *>(digits.data())[i] += z; } - bool always_show_decpt = (flags & Alternate || flags & ForcePoint); + bool always_show_decpt = (flags & ForcePoint); switch (form) { case DFExponent: { num_str = exponentForm(_zero, decimal, exponential, group, plus, minus, @@ -2800,7 +2802,7 @@ QString QLocaleData::doubleToString(const QChar _zero, const QChar plus, const Q break; } case DFSignificantDigits: { - PrecisionMode mode = (flags & Alternate) ? + PrecisionMode mode = (flags & AddTrailingZeroes) ? PMSignificantDigits : PMChopTrailingZeros; int cutoff = precision < 0 ? 6 : precision; @@ -2905,7 +2907,7 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group, for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i) num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0')); - if ((flags & Alternate || flags & ShowBase) + if ((flags & ShowBase) && base == 8 && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0'))) num_str.prepend(QLatin1Char('0')); @@ -2926,10 +2928,10 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group, --num_pad_chars; // leave space for optional '0x' in hex form - if (base == 16 && (flags & Alternate || flags & ShowBase)) + if (base == 16 && (flags & ShowBase)) num_pad_chars -= 2; // leave space for optional '0b' in binary form - else if (base == 2 && (flags & Alternate || flags & ShowBase)) + else if (base == 2 && (flags & ShowBase)) num_pad_chars -= 2; for (int i = 0; i < num_pad_chars; ++i) @@ -2939,9 +2941,9 @@ QString QLocaleData::longLongToString(const QChar zero, const QChar group, if (flags & CapitalEorX) num_str = num_str.toUpper(); - if (base == 16 && (flags & Alternate || flags & ShowBase)) + if (base == 16 && (flags & ShowBase)) num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x")); - if (base == 2 && (flags & Alternate || flags & ShowBase)) + if (base == 2 && (flags & ShowBase)) num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b")); // add sign @@ -2988,7 +2990,7 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group, for (int i = num_str.length()/* - cnt_thousand_sep*/; i < precision; ++i) num_str.prepend(base == 10 ? zero : QChar::fromLatin1('0')); - if ((flags & Alternate || flags & ShowBase) + if ((flags & ShowBase) && base == 8 && (num_str.isEmpty() || num_str[0].unicode() != QLatin1Char('0'))) num_str.prepend(QLatin1Char('0')); @@ -3003,10 +3005,10 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group, int num_pad_chars = width - num_str.length(); // leave space for optional '0x' in hex form - if (base == 16 && flags & Alternate) + if (base == 16 && flags & ShowBase) num_pad_chars -= 2; // leave space for optional '0b' in binary form - else if (base == 2 && flags & Alternate) + else if (base == 2 && flags & ShowBase) num_pad_chars -= 2; for (int i = 0; i < num_pad_chars; ++i) @@ -3016,9 +3018,9 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group, if (flags & CapitalEorX) num_str = num_str.toUpper(); - if (base == 16 && (flags & Alternate || flags & ShowBase)) + if (base == 16 && flags & ShowBase) num_str.prepend(QLatin1String(flags & UppercaseBase ? "0X" : "0x")); - else if (base == 2 && (flags & Alternate || flags & ShowBase)) + else if (base == 2 && flags & ShowBase) num_str.prepend(QLatin1String(flags & UppercaseBase ? "0B" : "0b")); // add sign @@ -3079,25 +3081,37 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti out = in.toLatin1(); else break; + } else if (out == '.') { + // Fail if more than one decimal point or point after e + if (decpt_idx != -1 || exponent_idx != -1) + return false; + decpt_idx = idx; + } else if (out == 'e' || out == 'E') { + exponent_idx = idx; } if (number_options & QLocale::RejectLeadingZeroInExponent) { - if (out == 'e' || out == 'E') { - exponent_idx = idx; - } else if (exponent_idx != -1) { - if (out >= '1' && out <= '9') - exponent_idx = -1; // leading digit is not 0, forget exponent_idx - else if (out == '0' && idx < l - 1) + if (exponent_idx != -1 && out == '0' && idx < l - 1) { + // After the exponent there can only be '+', '-' or digits. + // If we find a '0' directly after some non-digit, then that is a leading zero. + if (result->last() < '0' || result->last() > '9') return false; } } + if (number_options & QLocale::RejectTrailingZeroesAfterDot) { + // If we've seen a decimal point and the last character after the exponent is 0, then + // that is a trailing zero. + if (decpt_idx >= 0 && idx == exponent_idx && result->last() == '0') + return false; + } + if (!(number_options & QLocale::RejectGroupSeparator)) { if (start_of_digits_idx == -1 && out >= '0' && out <= '9') { start_of_digits_idx = idx; } else if (out == ',') { - // Don't allow group chars after the decimal point - if (decpt_idx != -1) + // Don't allow group chars after the decimal point or exponent + if (decpt_idx != -1 || exponent_idx != -1) return false; // check distance from the last separator or from the beginning of the digits @@ -3114,12 +3128,6 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti ++idx; continue; } else if (out == '.' || out == 'e' || out == 'E') { - // Fail if more than one decimal point - if (out == '.' && decpt_idx != -1) - return false; - if (decpt_idx == -1) - decpt_idx = idx; - // check distance from the last separator // ### FIXME: Some locales allow other groupings! See https://en.wikipedia.org/wiki/Thousands_separator if (last_separator_idx != -1 && idx - last_separator_idx != 4) @@ -3145,6 +3153,12 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti return false; } + if (number_options & QLocale::RejectTrailingZeroesAfterDot) { + // In decimal form, the last character can be a trailing zero if we've seen a decpt. + if (decpt_idx != -1 && exponent_idx == -1 && result->last() == '0') + return false; + } + result->append('\0'); return idx == l; } diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h index 657fce9fa1..bd89e48234 100644 --- a/src/corelib/tools/qlocale.h +++ b/src/corelib/tools/qlocale.h @@ -897,7 +897,9 @@ public: OmitGroupSeparator = 0x01, RejectGroupSeparator = 0x02, OmitLeadingZeroInExponent = 0x04, - RejectLeadingZeroInExponent = 0x08 + RejectLeadingZeroInExponent = 0x08, + IncludeTrailingZeroesAfterDot = 0x10, + RejectTrailingZeroesAfterDot = 0x20 }; Q_DECLARE_FLAGS(NumberOptions, NumberOption) diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc index f4b49095df..88b071e161 100644 --- a/src/corelib/tools/qlocale.qdoc +++ b/src/corelib/tools/qlocale.qdoc @@ -969,7 +969,8 @@ setNumberOptions(). \value DefaultNumberOptions This option represents the default behavior, with - group separators and with one leading zero in single digit exponents. + group separators, with one leading zero in single digit exponents, and + without trailing zeroes after the decimal dot. \value OmitGroupSeparator If this option is set, the number-to-string functions will not insert group separators in their return values. The default is to insert group separators. @@ -984,6 +985,14 @@ functions will fail if they encounter an exponent padded with zeroes when parsing a floating point number in scientific notation. The default is to accept such padding. + \value IncludeTrailingZeroesAfterDot If this option is set, the number-to-string + functions will pad numbers with zeroes to the requested precision in "g" + or "most concise" mode, even if the number of significant digits is lower + than the requested precision. The default is to omit trailing zeroes. + \value RejectTrailingZeroesAfterDot If this option is set, the string-to-number + functions will fail if they encounter trailing zeroes after the decimal + dot when parsing a number in scientific or decimal representation. The + default is to accept trailing zeroes. \sa setNumberOptions(), numberOptions() */ diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h index c83c9d3333..74d8e5f381 100644 --- a/src/corelib/tools/qlocale_p.h +++ b/src/corelib/tools/qlocale_p.h @@ -193,7 +193,7 @@ public: enum Flags { NoFlags = 0, - Alternate = 0x01, + AddTrailingZeroes = 0x01, ZeroPadded = 0x02, LeftAdjusted = 0x04, BlankBeforePositive = 0x08, @@ -204,7 +204,7 @@ public: ShowBase = 0x80, UppercaseBase = 0x100, ZeroPadExponent = 0x200, - ForcePoint = Alternate + ForcePoint = 0x400 }; enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode }; diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index bf1bc3e650..942df9e0dd 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1758,17 +1758,11 @@ void QString::resize(int size, QChar fillChar) void QString::reallocData(uint alloc, bool grow) { - size_t blockSize; - if (grow) { - auto r = qCalculateGrowingBlockSize(alloc, sizeof(QChar), sizeof(Data)); - blockSize = r.size; - alloc = uint(r.elementCount); - } else { - blockSize = qCalculateBlockSize(alloc, sizeof(QChar), sizeof(Data)); - } + auto allocOptions = d->detachFlags(); + if (grow) + allocOptions |= QArrayData::Grow; if (d->ref.isShared() || IS_RAW_DATA(d)) { - Data::AllocationOptions allocOptions(d->capacityReserved ? Data::CapacityReserved : 0); Data *x = Data::allocate(alloc, allocOptions); Q_CHECK_PTR(x); x->size = qMin(int(alloc) - 1, d->size); @@ -1778,11 +1772,9 @@ void QString::reallocData(uint alloc, bool grow) Data::deallocate(d); d = x; } else { - Data *p = static_cast<Data *>(::realloc(d, blockSize)); + Data *p = Data::reallocateUnaligned(d, alloc, allocOptions); Q_CHECK_PTR(p); d = p; - d->alloc = alloc; - d->offset = sizeof(QStringData); } } @@ -5916,7 +5908,10 @@ static uint parse_flag_characters(const char * &c) Q_DECL_NOTHROW uint flags = QLocaleData::ZeroPadExponent; while (true) { switch (*c) { - case '#': flags |= QLocaleData::Alternate; break; + case '#': + flags |= QLocaleData::ShowBase | QLocaleData::AddTrailingZeroes + | QLocaleData::ForcePoint; + break; case '0': flags |= QLocaleData::ZeroPadded; break; case '-': flags |= QLocaleData::LeftAdjusted; break; case ' ': flags |= QLocaleData::BlankBeforePositive; break; @@ -6174,7 +6169,7 @@ QString QString::vasprintf(const char *cformat, va_list ap) case 'p': { void *arg = va_arg(ap, void*); const quint64 i = reinterpret_cast<quintptr>(arg); - flags |= QLocaleData::Alternate; + flags |= QLocaleData::ShowBase; subst = QLocaleData::c()->unsLongLongToString(i, precision, 16, width, flags); ++c; break; @@ -7749,10 +7744,13 @@ QString QString::arg(double a, int fieldWidth, char fmt, int prec, QChar fillCha if (d.locale_occurrences > 0) { QLocale locale; - if (!(locale.numberOptions() & QLocale::OmitGroupSeparator)) + const QLocale::NumberOptions numberOptions = locale.numberOptions(); + if (!(numberOptions & QLocale::OmitGroupSeparator)) flags |= QLocaleData::ThousandsGroup; - if (!(locale.numberOptions() & QLocale::OmitLeadingZeroInExponent)) + if (!(numberOptions & QLocale::OmitLeadingZeroInExponent)) flags |= QLocaleData::ZeroPadExponent; + if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot) + flags |= QLocaleData::AddTrailingZeroes; locale_arg = locale.d->m_data->doubleToString(a, prec, form, fieldWidth, flags); } diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp index db118edf04..094f44b2ab 100644 --- a/src/gui/image/qicon.cpp +++ b/src/gui/image/qicon.cpp @@ -137,8 +137,8 @@ static qreal qt_effective_device_pixel_ratio(QWindow *window = 0) return qApp->devicePixelRatio(); // Don't know which window to target. } -QIconPrivate::QIconPrivate() - : engine(0), ref(1), +QIconPrivate::QIconPrivate(QIconEngine *e) + : engine(e), ref(1), serialNum(serialNumCounter.fetchAndAddRelaxed(1)), detach_no(0), is_mask(false) @@ -673,9 +673,8 @@ QIcon::QIcon(const QString &fileName) ownership of the engine. */ QIcon::QIcon(QIconEngine *engine) - :d(new QIconPrivate) + :d(new QIconPrivate(engine)) { - d->engine = engine; } /*! @@ -950,8 +949,7 @@ void QIcon::detach() d = 0; return; } else if (d->ref.load() != 1) { - QIconPrivate *x = new QIconPrivate; - x->engine = d->engine->clone(); + QIconPrivate *x = new QIconPrivate(d->engine->clone()); if (!d->ref.deref()) delete d; d = x; @@ -974,10 +972,8 @@ void QIcon::addPixmap(const QPixmap &pixmap, Mode mode, State state) if (pixmap.isNull()) return; detach(); - if (!d) { - d = new QIconPrivate; - d->engine = new QPixmapIconEngine; - } + if (!d) + d = new QIconPrivate(new QPixmapIconEngine); d->engine->addPixmap(pixmap, mode, state); } @@ -1037,8 +1033,7 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State if (!engine) engine = iconEngineFromSuffix(fileName, QMimeDatabase().mimeTypeForFile(info).preferredSuffix()); #endif // !QT_NO_MIMETYPE - d = new QIconPrivate; - d->engine = engine ? engine : new QPixmapIconEngine; + d = new QIconPrivate(engine ? engine : new QPixmapIconEngine); } d->engine->addFile(fileName, size, mode, state); @@ -1240,12 +1235,10 @@ bool QIcon::hasThemeIcon(const QString &name) */ void QIcon::setIsMask(bool isMask) { - if (!d) { - d = new QIconPrivate; - d->engine = new QPixmapIconEngine; - } else { + if (!d) + d = new QIconPrivate(new QPixmapIconEngine); + else detach(); - } d->is_mask = isMask; } @@ -1326,22 +1319,17 @@ QDataStream &operator>>(QDataStream &s, QIcon &icon) QString key; s >> key; if (key == QLatin1String("QPixmapIconEngine")) { - icon.d = new QIconPrivate; - QIconEngine *engine = new QPixmapIconEngine; - icon.d->engine = engine; - engine->read(s); + icon.d = new QIconPrivate(new QPixmapIconEngine); + icon.d->engine->read(s); } else if (key == QLatin1String("QIconLoaderEngine")) { - icon.d = new QIconPrivate; - QIconEngine *engine = new QIconLoaderEngine(); - icon.d->engine = engine; - engine->read(s); + icon.d = new QIconPrivate(new QIconLoaderEngine()); + icon.d->engine->read(s); } else { const int index = loader()->indexOf(key); if (index != -1) { if (QIconEnginePlugin *factory = qobject_cast<QIconEnginePlugin*>(loader()->instance(index))) { if (QIconEngine *engine= factory->create()) { - icon.d = new QIconPrivate; - icon.d->engine = engine; + icon.d = new QIconPrivate(engine); engine->read(s); } // factory } // instance diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index a978a72192..aa358e88af 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE class QIconPrivate { public: - QIconPrivate(); + explicit QIconPrivate(QIconEngine *e); ~QIconPrivate() { delete engine; diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 1a8fc599ce..4f4f543ba8 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -42,6 +42,7 @@ #include "qopenglcontext.h" #include "qopenglfunctions.h" +#include "qoperatingsystemversion.h" #include "qoffscreensurface.h" #include <QtCore/QDebug> @@ -221,29 +222,25 @@ struct OsTypeTerm static QString hostOsRelease() { QString ver; #ifdef Q_OS_WIN - switch (QSysInfo::windowsVersion()) { - case QSysInfo::WV_XP: - case QSysInfo::WV_2003: - ver = QStringLiteral("xp"); - break; - case QSysInfo::WV_VISTA: - ver = QStringLiteral("vista"); - break; - case QSysInfo::WV_WINDOWS7: + const auto osver = QOperatingSystemVersion::current(); +#define Q_WINVER(major, minor) (major << 8 | minor) + switch (Q_WINVER(osver.majorVersion(), osver.minorVersion())) { + case Q_WINVER(6, 1): ver = QStringLiteral("7"); break; - case QSysInfo::WV_WINDOWS8: + case Q_WINVER(6, 2): ver = QStringLiteral("8"); break; - case QSysInfo::WV_WINDOWS8_1: + case Q_WINVER(6, 3): ver = QStringLiteral("8.1"); break; - case QSysInfo::WV_WINDOWS10: + case Q_WINVER(10, 0): ver = QStringLiteral("10"); break; default: break; } +#undef Q_WINVER #endif return ver; } diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp index 61343e5f5a..6f5aff14aa 100644 --- a/src/gui/opengl/qopenglshaderprogram.cpp +++ b/src/gui/opengl/qopenglshaderprogram.cpp @@ -162,6 +162,79 @@ QT_BEGIN_NAMESPACE based on the core feature (requires OpenGL >= 4.3). */ + +// For GLES 3.1/3.2 +#ifndef GL_GEOMETRY_SHADER +#define GL_GEOMETRY_SHADER 0x8DD9 +#endif +#ifndef GL_TESS_CONTROL_SHADER +#define GL_TESS_CONTROL_SHADER 0x8E88 +#endif +#ifndef GL_TESS_EVALUATION_SHADER +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#endif +#ifndef GL_COMPUTE_SHADER +#define GL_COMPUTE_SHADER 0x91B9 +#endif +#ifndef GL_MAX_GEOMETRY_OUTPUT_VERTICES +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#endif +#ifndef GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#endif +#ifndef GL_PATCH_VERTICES +#define GL_PATCH_VERTICES 0x8E72 +#endif +#ifndef GL_PATCH_DEFAULT_OUTER_LEVEL +#define GL_PATCH_DEFAULT_OUTER_LEVEL 0x8E74 +#endif +#ifndef GL_PATCH_DEFAULT_INNER_LEVEL +#define GL_PATCH_DEFAULT_INNER_LEVEL 0x8E73 +#endif + +static inline bool isFormatGLES(const QSurfaceFormat &f) +{ + return (f.renderableType() == QSurfaceFormat::OpenGLES); +} + +static inline bool supportsGeometry(const QSurfaceFormat &f) +{ +#ifndef QT_OPENGL_ES_2 + if (!isFormatGLES(f)) + return (f.version() >= qMakePair<int, int>(3, 2)); + else + return false; +#else + Q_UNUSED(f); + return false; +#endif +} + +static inline bool supportsCompute(const QSurfaceFormat &f) +{ +#ifndef QT_OPENGL_ES_2 + if (!isFormatGLES(f)) + return (f.version() >= qMakePair<int, int>(4, 3)); + else + return (f.version() >= qMakePair<int, int>(3, 1)); +#else + return (f.version() >= qMakePair<int, int>(3, 1)); +#endif +} + +static inline bool supportsTessellation(const QSurfaceFormat &f) +{ +#ifndef QT_OPENGL_ES_2 + if (!isFormatGLES(f)) + return (f.version() >= qMakePair<int, int>(4, 0)); + else + return false; +#else + Q_UNUSED(f); + return false; +#endif +} + class QOpenGLShaderPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QOpenGLShader) @@ -171,22 +244,16 @@ public: , shaderType(type) , compiled(false) , glfuncs(new QOpenGLFunctions(ctx)) -#ifndef QT_OPENGL_ES_2 , supportsGeometryShaders(false) , supportsTessellationShaders(false) -#endif + , supportsComputeShaders(false) { -#ifndef QT_OPENGL_ES_2 - if (!ctx->isOpenGLES()) { - QSurfaceFormat f = ctx->format(); - - // Geometry shaders require OpenGL >= 3.2 - if (shaderType & QOpenGLShader::Geometry) - supportsGeometryShaders = (f.version() >= qMakePair<int, int>(3, 2)); - else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation)) - supportsTessellationShaders = (f.version() >= qMakePair<int, int>(4, 0)); - } -#endif + if (shaderType & QOpenGLShader::Geometry) + supportsGeometryShaders = supportsGeometry(ctx->format()); + else if (shaderType & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation)) + supportsTessellationShaders = supportsTessellation(ctx->format()); + else if (shaderType & QOpenGLShader::Compute) + supportsComputeShaders = supportsCompute(ctx->format()); } ~QOpenGLShaderPrivate(); @@ -197,13 +264,13 @@ public: QOpenGLFunctions *glfuncs; -#ifndef QT_OPENGL_ES_2 // Support for geometry shaders bool supportsGeometryShaders; - // Support for tessellation shaders bool supportsTessellationShaders; -#endif + // Support for compute shaders + bool supportsComputeShaders; + bool create(); bool compile(QOpenGLShader *q); @@ -232,21 +299,15 @@ bool QOpenGLShaderPrivate::create() GLuint shader; if (shaderType == QOpenGLShader::Vertex) { shader = glfuncs->glCreateShader(GL_VERTEX_SHADER); -#if defined(QT_OPENGL_3_2) } else if (shaderType == QOpenGLShader::Geometry && supportsGeometryShaders) { shader = glfuncs->glCreateShader(GL_GEOMETRY_SHADER); -#endif -#if defined(QT_OPENGL_4) } else if (shaderType == QOpenGLShader::TessellationControl && supportsTessellationShaders) { shader = glfuncs->glCreateShader(GL_TESS_CONTROL_SHADER); } else if (shaderType == QOpenGLShader::TessellationEvaluation && supportsTessellationShaders) { shader = glfuncs->glCreateShader(GL_TESS_EVALUATION_SHADER); -#endif -#if defined(QT_OPENGL_4_3) - } else if (shaderType == QOpenGLShader::Compute) { + } else if (shaderType == QOpenGLShader::Compute && supportsComputeShaders) { shader = glfuncs->glCreateShader(GL_COMPUTE_SHADER); -#endif - } else { + } else if (shaderType == QOpenGLShader::Fragment) { shader = glfuncs->glCreateShader(GL_FRAGMENT_SHADER); } if (!shader) { @@ -3219,10 +3280,8 @@ void QOpenGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4 int QOpenGLShaderProgram::maxGeometryOutputVertices() const { GLint n = 0; -#if defined(QT_OPENGL_3_2) Q_D(const QOpenGLShaderProgram); d->glfuncs->glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES, &n); -#endif return n; } @@ -3246,7 +3305,7 @@ int QOpenGLShaderProgram::maxGeometryOutputVertices() const */ void QOpenGLShaderProgram::setPatchVertexCount(int count) { -#if defined(QT_OPENGL_4) +#ifndef QT_OPENGL_ES_2 Q_D(QOpenGLShaderProgram); if (d->tessellationFuncs) d->tessellationFuncs->glPatchParameteri(GL_PATCH_VERTICES, count); @@ -3265,13 +3324,15 @@ void QOpenGLShaderProgram::setPatchVertexCount(int count) */ int QOpenGLShaderProgram::patchVertexCount() const { +#ifndef QT_OPENGL_ES_2 int patchVertices = 0; -#if defined(QT_OPENGL_4) Q_D(const QOpenGLShaderProgram); if (d->tessellationFuncs) d->tessellationFuncs->glGetIntegerv(GL_PATCH_VERTICES, &patchVertices); -#endif return patchVertices; +#else + return 0; +#endif } /*! @@ -3293,21 +3354,21 @@ int QOpenGLShaderProgram::patchVertexCount() const */ void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float> &levels) { -#if defined(QT_OPENGL_4) - QVector<float> tessLevels = levels; - - // Ensure we have the required 4 outer tessellation levels - // Use default of 1 for missing entries (same as spec) - const int argCount = 4; - if (tessLevels.size() < argCount) { - tessLevels.reserve(argCount); - for (int i = tessLevels.size(); i < argCount; ++i) - tessLevels.append(1.0f); - } - +#ifndef QT_OPENGL_ES_2 Q_D(QOpenGLShaderProgram); - if (d->tessellationFuncs) + if (d->tessellationFuncs) { + QVector<float> tessLevels = levels; + + // Ensure we have the required 4 outer tessellation levels + // Use default of 1 for missing entries (same as spec) + const int argCount = 4; + if (tessLevels.size() < argCount) { + tessLevels.reserve(argCount); + for (int i = tessLevels.size(); i < argCount; ++i) + tessLevels.append(1.0f); + } d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data()); + } #else Q_UNUSED(levels); #endif @@ -3330,13 +3391,15 @@ void QOpenGLShaderProgram::setDefaultOuterTessellationLevels(const QVector<float */ QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const { +#ifndef QT_OPENGL_ES_2 QVector<float> tessLevels(4, 1.0f); -#if defined(QT_OPENGL_4) Q_D(const QOpenGLShaderProgram); if (d->tessellationFuncs) d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_OUTER_LEVEL, tessLevels.data()); -#endif return tessLevels; +#else + return QVector<float>(); +#endif } /*! @@ -3358,21 +3421,21 @@ QVector<float> QOpenGLShaderProgram::defaultOuterTessellationLevels() const */ void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float> &levels) { -#if defined(QT_OPENGL_4) - QVector<float> tessLevels = levels; - - // Ensure we have the required 2 inner tessellation levels - // Use default of 1 for missing entries (same as spec) - const int argCount = 2; - if (tessLevels.size() < argCount) { - tessLevels.reserve(argCount); - for (int i = tessLevels.size(); i < argCount; ++i) - tessLevels.append(1.0f); - } - +#ifndef QT_OPENGL_ES_2 Q_D(QOpenGLShaderProgram); - if (d->tessellationFuncs) + if (d->tessellationFuncs) { + QVector<float> tessLevels = levels; + + // Ensure we have the required 2 inner tessellation levels + // Use default of 1 for missing entries (same as spec) + const int argCount = 2; + if (tessLevels.size() < argCount) { + tessLevels.reserve(argCount); + for (int i = tessLevels.size(); i < argCount; ++i) + tessLevels.append(1.0f); + } d->tessellationFuncs->glPatchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data()); + } #else Q_UNUSED(levels); #endif @@ -3395,13 +3458,15 @@ void QOpenGLShaderProgram::setDefaultInnerTessellationLevels(const QVector<float */ QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const { +#ifndef QT_OPENGL_ES_2 QVector<float> tessLevels(2, 1.0f); -#if defined(QT_OPENGL_4) Q_D(const QOpenGLShaderProgram); if (d->tessellationFuncs) d->tessellationFuncs->glGetFloatv(GL_PATCH_DEFAULT_INNER_LEVEL, tessLevels.data()); -#endif return tessLevels; +#else + return QVector<float>(); +#endif } @@ -3414,16 +3479,11 @@ QVector<float> QOpenGLShaderProgram::defaultInnerTessellationLevels() const */ bool QOpenGLShaderProgram::hasOpenGLShaderPrograms(QOpenGLContext *context) { -#if !defined(QT_OPENGL_ES_2) if (!context) context = QOpenGLContext::currentContext(); if (!context) return false; return QOpenGLFunctions(context).hasOpenGLFeature(QOpenGLFunctions::Shaders); -#else - Q_UNUSED(context); - return true; -#endif } /*! @@ -3454,33 +3514,12 @@ bool QOpenGLShader::hasOpenGLShaders(ShaderType type, QOpenGLContext *context) if ((type & ~(Geometry | Vertex | Fragment | TessellationControl | TessellationEvaluation | Compute)) || type == 0) return false; - QSurfaceFormat format = context->format(); - if (type == Geometry) { -#ifndef QT_OPENGL_ES_2 - // Geometry shaders require OpenGL 3.2 or newer - QSurfaceFormat format = context->format(); - return (!context->isOpenGLES()) - && (format.version() >= qMakePair<int, int>(3, 2)); -#else - // No geometry shader support in OpenGL ES2 - return false; -#endif - } else if (type == TessellationControl || type == TessellationEvaluation) { -#if !defined(QT_OPENGL_ES_2) - return (!context->isOpenGLES()) - && (format.version() >= qMakePair<int, int>(4, 0)); -#else - // No tessellation shader support in OpenGL ES2 - return false; -#endif - } else if (type == Compute) { -#if defined(QT_OPENGL_4_3) - return (format.version() >= qMakePair<int, int>(4, 3)); -#else - // No compute shader support without OpenGL 4.3 or newer - return false; -#endif - } + if (type & QOpenGLShader::Geometry) + return supportsGeometry(context->format()); + else if (type & (QOpenGLShader::TessellationControl | QOpenGLShader::TessellationEvaluation)) + return supportsTessellation(context->format()); + else if (type & QOpenGLShader::Compute) + return supportsCompute(context->format()); // Unconditional support of vertex and fragment shaders implicitly assumes // a minimum OpenGL version of 2.0 diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm index 6af12c19d8..a29d60ca6e 100644 --- a/src/gui/painting/qcoregraphics.mm +++ b/src/gui/painting/qcoregraphics.mm @@ -39,6 +39,7 @@ #include <QtGui/private/qpaintengine_p.h> #include <QtCore/qdebug.h> #include <QtCore/qcoreapplication.h> +#include <QtCore/qoperatingsystemversion.h> QT_BEGIN_NAMESPACE @@ -119,7 +120,7 @@ QT_END_NAMESPACE + (NSGraphicsContext *)qt_graphicsContextWithCGContext:(CGContextRef)graphicsPort flipped:(BOOL)initialFlippedState { #if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_10, __IPHONE_NA) - if (QT_PREPEND_NAMESPACE(QSysInfo::MacintoshVersion) >= QT_PREPEND_NAMESPACE(QSysInfo::MV_10_10)) + if (QT_PREPEND_NAMESPACE(QOperatingSystemVersion::current()) >= QT_PREPEND_NAMESPACE(QOperatingSystemVersion::OSXYosemite)) return [self graphicsContextWithCGContext:graphicsPort flipped:initialFlippedState]; #endif return [self graphicsContextWithGraphicsPort:graphicsPort flipped:initialFlippedState]; diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 085c073bb1..c9747877f7 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -198,8 +198,15 @@ bool QDesktopServices::openUrl(const QUrl &url) return false; QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration(); - if (!platformIntegration) + if (Q_UNLIKELY(!platformIntegration)) { + QCoreApplication *application = QCoreApplication::instance(); + if (Q_UNLIKELY(!application)) + qWarning("QDesktopServices::openUrl: Please instantiate the QGuiApplication object " + "first"); + else if (Q_UNLIKELY(!qobject_cast<QGuiApplication *>(application))) + qWarning("QDesktopServices::openUrl: Application is not a GUI application"); return false; + } QPlatformServices *platformServices = platformIntegration->services(); if (!platformServices) { diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 24ada3a81f..612abb9044 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -299,6 +299,11 @@ void QHttpNetworkReply::setSpdyWasUsed(bool spdy) d_func()->spdyUsed = spdy; } +qint64 QHttpNetworkReply::removedContentLength() const +{ + return d_func()->removedContentLength; +} + bool QHttpNetworkReply::isRedirecting() const { return d_func()->isRedirecting(); @@ -326,6 +331,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) currentlyReceivedDataInWindow(0), currentlyUploadedDataInWindow(0), totallyUploadedData(0), + removedContentLength(-1), connection(0), autoDecompress(false), responseData(), requestIsPrepared(false) ,pipeliningUsed(false), spdyUsed(false), downstreamLimited(false) @@ -398,12 +404,12 @@ void QHttpNetworkReplyPrivate::removeAutoDecompressHeader() end = fields.end(); while (it != end) { if (qstricmp(name.constData(), it->first.constData()) == 0) { + removedContentLength = strtoull(it->second.constData(), nullptr, 0); fields.erase(it); break; } ++it; } - } bool QHttpNetworkReplyPrivate::findChallenge(bool forProxy, QByteArray &challenge) const diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index f3b007f594..faab03f056 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -139,6 +139,7 @@ public: bool isPipeliningUsed() const; bool isSpdyUsed() const; void setSpdyWasUsed(bool spdy); + qint64 removedContentLength() const; bool isRedirecting() const; @@ -255,6 +256,7 @@ public: qint32 currentlyReceivedDataInWindow; // only for SPDY qint32 currentlyUploadedDataInWindow; // only for SPDY qint64 totallyUploadedData; // only for SPDY + qint64 removedContentLength; QPointer<QHttpNetworkConnection> connection; QPointer<QHttpNetworkConnectionChannel> connectionChannel; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 1dca7f02fb..e71911cec2 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -234,6 +234,7 @@ QHttpThreadDelegate::QHttpThreadDelegate(QObject *parent) : , isPipeliningUsed(false) , isSpdyUsed(false) , incomingContentLength(-1) + , removedContentLength(-1) , incomingErrorCode(QNetworkReply::NoError) , downloadBuffer() , httpConnection(0) @@ -623,6 +624,7 @@ void QHttpThreadDelegate::headerChangedSlot() incomingReasonPhrase = httpReply->reasonPhrase(); isPipeliningUsed = httpReply->isPipeliningUsed(); incomingContentLength = httpReply->contentLength(); + removedContentLength = httpReply->removedContentLength(); isSpdyUsed = httpReply->isSpdyUsed(); emit downloadMetaData(incomingHeaders, @@ -631,6 +633,7 @@ void QHttpThreadDelegate::headerChangedSlot() isPipeliningUsed, downloadBuffer, incomingContentLength, + removedContentLength, isSpdyUsed); } diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h index 64c58cf648..6d1ea11f29 100644 --- a/src/network/access/qhttpthreaddelegate_p.h +++ b/src/network/access/qhttpthreaddelegate_p.h @@ -112,6 +112,7 @@ public: bool isPipeliningUsed; bool isSpdyUsed; qint64 incomingContentLength; + qint64 removedContentLength; QNetworkReply::NetworkError incomingErrorCode; QString incomingErrorDetail; #ifndef QT_NO_BEARERMANAGEMENT @@ -141,7 +142,7 @@ signals: void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *); #endif void downloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, bool, - QSharedPointer<char>, qint64, bool); + QSharedPointer<char>, qint64, qint64, bool); void downloadProgress(qint64, qint64); void downloadData(const QByteArray &); void error(QNetworkReply::NetworkError, const QString &); diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 7f39c942a3..4b5422ce29 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -63,7 +63,6 @@ class QNetworkProxyQuery; class QNetworkRequest; class QStringList; class QUrl; -class QUrlInfo; class QSslConfiguration; class QNetworkAccessManagerPrivate; diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index b5e44fa29a..f70f11d384 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -805,10 +805,11 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq Qt::QueuedConnection); QObject::connect(delegate, SIGNAL(downloadMetaData(QList<QPair<QByteArray,QByteArray> >, int, QString, bool, - QSharedPointer<char>, qint64, bool)), + QSharedPointer<char>, qint64, qint64, + bool)), q, SLOT(replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >, int, QString, bool, - QSharedPointer<char>, qint64, bool)), + QSharedPointer<char>, qint64, qint64, bool)), Qt::QueuedConnection); QObject::connect(delegate, SIGNAL(downloadProgress(qint64,qint64)), q, SLOT(replyDownloadProgressSlot(qint64,qint64)), @@ -913,6 +914,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq delegate->isPipeliningUsed, QSharedPointer<char>(), delegate->incomingContentLength, + delegate->removedContentLength, delegate->isSpdyUsed); replyDownloadData(delegate->synchronousDownloadData); httpError(delegate->incomingErrorCode, delegate->incomingErrorDetail); @@ -924,6 +926,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq delegate->isPipeliningUsed, QSharedPointer<char>(), delegate->incomingContentLength, + delegate->removedContentLength, delegate->isSpdyUsed); replyDownloadData(delegate->synchronousDownloadData); } @@ -1151,7 +1154,9 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode) void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &hm, int sc, const QString &rp, bool pu, QSharedPointer<char> db, - qint64 contentLength, bool spdyWasUsed) + qint64 contentLength, + qint64 removedContentLength, + bool spdyWasUsed) { Q_Q(QNetworkReplyHttpImpl); Q_UNUSED(contentLength); @@ -1197,6 +1202,8 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte q->setAttribute(QNetworkRequest::HttpStatusCodeAttribute, statusCode); q->setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, reasonPhrase); + if (removedContentLength != -1) + q->setAttribute(QNetworkRequest::OriginalContentLengthAttribute, removedContentLength); // is it a redirection? if (!isHttpRedirectResponse()) diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index 868fa617b6..255c23006e 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -114,7 +114,7 @@ public: Q_PRIVATE_SLOT(d_func(), void replyFinished()) Q_PRIVATE_SLOT(d_func(), void replyDownloadMetaData(QList<QPair<QByteArray,QByteArray> >, int, QString, bool, QSharedPointer<char>, - qint64, bool)) + qint64, qint64, bool)) Q_PRIVATE_SLOT(d_func(), void replyDownloadProgressSlot(qint64,qint64)) Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *)) Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &)) @@ -280,7 +280,7 @@ public: void replyDownloadData(QByteArray); void replyFinished(); void replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &, int, const QString &, - bool, QSharedPointer<char>, qint64, bool); + bool, QSharedPointer<char>, qint64, qint64, bool); void replyDownloadProgressSlot(qint64,qint64); void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpError(QNetworkReply::NetworkError error, const QString &errorString); diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp index 29362b81e2..bc2507ca51 100644 --- a/src/network/access/qnetworkrequest.cpp +++ b/src/network/access/qnetworkrequest.cpp @@ -282,6 +282,13 @@ QT_BEGIN_NAMESPACE that is redirecting from "https" to "http" protocol, are not allowed. (This value was introduced in 5.6.) + \value OriginalContentLengthAttribute + Replies only, type QMetaType::Int + Holds the original content-length attribute before being invalidated and + removed from the header when the data is compressed and the request was + marked to be decompressed automatically. + (This value was introduced in 5.9.) + \value User Special type. Additional information can be passed in QVariants with types ranging from User to UserMax. The default diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h index ad8f5bddd9..9a3a7f0fb5 100644 --- a/src/network/access/qnetworkrequest.h +++ b/src/network/access/qnetworkrequest.h @@ -91,6 +91,7 @@ public: FollowRedirectsAttribute, HTTP2AllowedAttribute, HTTP2WasUsedAttribute, + OriginalContentLengthAttribute, User = 1000, UserMax = 32767 diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 8f37e28669..7ef387beb4 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -57,8 +57,7 @@ win32: { mac { LIBS_PRIVATE += -framework CoreFoundation - !uikit: LIBS_PRIVATE += -framework CoreServices - !if(watchos:CONFIG(device, simulator|device)): LIBS_PRIVATE += -framework SystemConfiguration + !uikit: LIBS_PRIVATE += -framework CoreServices -framework SystemConfiguration } osx:SOURCES += kernel/qnetworkproxy_mac.cpp diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index f5dc9fcdcd..ca65f8a015 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -181,13 +181,7 @@ long QSslSocketPrivate::sslLibraryVersionNumber() QString QSslSocketPrivate::sslLibraryVersionString() { - switch (QSysInfo::windowsVersion()) { - case QSysInfo::WV_WINDOWS8_1: - return QStringLiteral("Windows Runtime 8.1 SSL library"); - default: - break; - } - return QStringLiteral("Windows Runtime SSL library"); + return QStringLiteral("Windows Runtime, ") + QSysInfo::prettyProductName(); } long QSslSocketPrivate::sslLibraryBuildVersionNumber() diff --git a/src/platformsupport/fontdatabases/fontdatabases.pri b/src/platformsupport/fontdatabases/fontdatabases.pri index f8e51f2a6d..1ea7f42204 100644 --- a/src/platformsupport/fontdatabases/fontdatabases.pri +++ b/src/platformsupport/fontdatabases/fontdatabases.pri @@ -1,4 +1,4 @@ -darwin:!if(watchos:CONFIG(simulator, simulator|device)) { +darwin { include($$PWD/mac/coretext.pri) } else { !win32|qtConfig(freetype) { diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri index 4d19a59226..e1132cfcbe 100644 --- a/src/platformsupport/fontdatabases/mac/coretext.pri +++ b/src/platformsupport/fontdatabases/mac/coretext.pri @@ -14,3 +14,13 @@ else: \ # On Mac OS they are part of the ApplicationServices umbrella framework, # even in 10.8 where they were also made available stand-alone. LIBS_PRIVATE += -framework ApplicationServices + +# CoreText is documented to be available on watchOS, but the headers aren't present +# in the watchOS Simulator SDK like they are supposed to be. Work around the problem +# by adding the device SDK's headers to the search path as a fallback. +# rdar://25314492, rdar://27844864 +watchos:CONFIG(simulator, simulator|device) { + QMAKE_CXXFLAGS += \ + -F$$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks \ + -F$$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks +} diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index 7d11023b78..de4fa95530 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -132,7 +132,7 @@ Qt::DropAction QCocoaDrag::drag(QDrag *o) QPixmap pm = dragPixmap(m_drag, hotSpot); QSize pmDeviceIndependentSize = pm.size() / pm.devicePixelRatio(); NSImage *nsimage = qt_mac_create_nsimage(pm); - [nsimage setSize:pmDeviceIndependentSize.toCGSize()]; + [nsimage setSize:NSSizeFromCGSize(pmDeviceIndependentSize.toCGSize())]; QMacPasteboard dragBoard((CFStringRef) NSDragPboard, QMacInternalPasteboardMime::MIME_DND); m_drag->mimeData()->setData(QLatin1String("application/x-qt-mime-type-name"), QByteArray("dummy")); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 0375dd85f2..c0055852c2 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -62,6 +62,7 @@ #include <stdlib.h> #include <qabstracteventdispatcher.h> #include <qsysinfo.h> +#include <qoperatingsystemversion.h> #include <qglobal.h> #include <QDir> @@ -163,7 +164,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); [mSavePanel setDelegate:self]; #if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_11) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_11) + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXElCapitan) mOpenPanel.accessoryViewDisclosed = YES; #endif diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index b2fd0580bc..87a0991098 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -514,7 +514,7 @@ QRect QCocoaWindow::geometry() const NSRect screenRect = [[m_contentView window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; NSPoint screenPoint = screenRect.origin; QPoint position = qt_mac_flipPoint(screenPoint).toPoint(); - QSize size = QRectF::fromCGRect([m_contentView bounds]).toRect().size(); + QSize size = QRectF::fromCGRect(NSRectToCGRect([m_contentView bounds])).toRect().size(); return QRect(position, size); } @@ -1117,7 +1117,7 @@ void QCocoaWindow::propagateSizeHints() QSize sizeIncrement = windowSizeIncrement(); if (sizeIncrement.isEmpty()) sizeIncrement = QSize(1, 1); - [m_nsWindow setResizeIncrements:sizeIncrement.toCGSize()]; + [m_nsWindow setResizeIncrements:NSSizeFromCGSize(sizeIncrement.toCGSize())]; QRect rect = geometry(); QSize baseSize = windowBaseSize(); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 8d3b970158..ee0bf75606 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -340,10 +340,10 @@ static bool _q_dontOverrideCtrlLMB = false; geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height); } else if (m_platformWindow->m_contentViewIsToBeEmbedded) { // embedded child window, use the frame rect ### merge with case below - geometry = QRectF::fromCGRect([self bounds]).toRect(); + geometry = QRectF::fromCGRect(NSRectToCGRect([self bounds])).toRect(); } else { // child window, use the frame rect - geometry = QRectF::fromCGRect([self frame]).toRect(); + geometry = QRectF::fromCGRect(NSRectToCGRect([self frame])).toRect(); } if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry()) @@ -557,7 +557,7 @@ static bool _q_dontOverrideCtrlLMB = false; - (void) drawRect:(NSRect)dirtyRect { - qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_window << QRectF::fromCGRect(dirtyRect); + qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_window << QRectF::fromCGRect(NSRectToCGRect(dirtyRect)); #ifndef QT_NO_OPENGL if (m_glContext && m_shouldSetGLContextinDrawRect) { @@ -1347,7 +1347,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) - (bool)handleGestureAsBeginEnd:(NSEvent *)event { - if (QSysInfo::QSysInfo::MacintoshVersion < QSysInfo::MV_10_11) + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXElCapitan) return false; if ([event phase] == NSEventPhaseBegan) { diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 94dd643116..9799e29cf2 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -60,6 +60,7 @@ #include <QtPlatformSupport/private/qcoretextfontdatabase_p.h> #include <QtPlatformSupport/private/qmacmime_p.h> #include <QDir> +#include <QOperatingSystemVersion> #import <AudioToolbox/AudioServices.h> @@ -117,7 +118,7 @@ QIOSIntegration::QIOSIntegration() m_touchDevice = new QTouchDevice; m_touchDevice->setType(QTouchDevice::TouchScreen); QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition; - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) { if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) touchCapabilities |= QTouchDevice::Pressure; } diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm index 50d5442f17..4f0c667861 100644 --- a/src/plugins/platforms/ios/qiosmessagedialog.mm +++ b/src/plugins/platforms/ios/qiosmessagedialog.mm @@ -39,6 +39,7 @@ #import <UIKit/UIKit.h> +#include <QtCore/qoperatingsystemversion.h> #include <QtGui/qwindow.h> #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> @@ -109,7 +110,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win if (m_alertController // Ensure that the dialog is not showing already || !options() // Some message dialogs don't have options (QErrorMessage) || windowModality == Qt::NonModal // We can only do modal dialogs - || QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) // API limitation + || QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) // API limitation return false; m_alertController = [[UIAlertController diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 013061a6d2..86bce0d70b 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -45,6 +45,7 @@ #include "qiosapplicationdelegate.h" #include "qiosviewcontroller.h" #include "quiview.h" +#include <QtCore/qoperatingsystemversion.h> #include <QtGui/private/qwindow_p.h> #include <private/qcoregraphics_p.h> @@ -274,7 +275,7 @@ void QIOSScreen::updateProperties() if (m_uiScreen == [UIScreen mainScreen]) { Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation)); - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_8_0) { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { // On iOS < 8.0 the UIScreen geometry is always in portait, and the system applies // the screen rotation to the root view-controller's view instead of directly to the // screen, like iOS 8 and above does. @@ -302,7 +303,7 @@ void QIOSScreen::updateProperties() if (m_geometry != previousGeometry) { QRectF physicalGeometry; - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { // We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ? Qt::LandscapeOrientation : Qt::PortraitOrientation; @@ -407,7 +408,7 @@ Qt::ScreenOrientation QIOSScreen::nativeOrientation() const { CGRect nativeBounds = #if !defined(Q_OS_TVOS) && QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_8_0) - QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_8_0 ? m_uiScreen.nativeBounds : + QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8) ? m_uiScreen.nativeBounds : #endif m_uiScreen.bounds; diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm index 9d73a296fa..462da0a978 100644 --- a/src/plugins/platforms/ios/qiostextinputoverlay.mm +++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm @@ -219,7 +219,7 @@ static void executeBlockWithoutAnimation(Block block) borderLayer.borderColor = [[UIColor lightGrayColor] CGColor]; [self addSublayer:borderLayer]; - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) { // [UIView snapshotViewAfterScreenUpdates:] is available since iOS 7.0. // Just silently ignore showing the loupe for older versions. self.hidden = YES; @@ -267,7 +267,7 @@ static void executeBlockWithoutAnimation(Block block) - (void)display { - if (QSysInfo::MacintoshVersion < QSysInfo::MV_IOS_7_0) + if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) return; // Take a snapshow of the target view, magnify the area around the focal diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 5c493617b1..25bfa2ad90 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -48,6 +48,7 @@ #include "qiosmenu.h" #endif +#include <QtCore/qoperatingsystemversion.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qwindow_p.h> #include <qpa/qwindowsysteminterface_p.h> @@ -298,7 +299,7 @@ QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice(); QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities(); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) { if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) touchCapabilities |= QTouchDevice::Pressure; else diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index ff115a2249..5d4afe8fb2 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -1053,11 +1053,24 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BS return S_FALSE; } -HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR) +HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::put_accValue(VARIANT, BSTR value) { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - return DISP_E_MEMBERNOTFOUND; + + if (!accessible || !accessible->isValid()) { + return E_FAIL; + } + + QString qstrValue = QString::fromWCharArray(value); + + if (accessible->valueInterface()) { + accessible->valueInterface()->setCurrentValue(qstrValue); + } else { + accessible->setText(QAccessible::Value, qstrValue); + } + + return S_OK; } // moz: [important] diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index d4cdf3ef3c..10d38f2a0c 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -68,6 +68,7 @@ #include <QtCore/QHash> #include <QtCore/QStringList> #include <QtCore/QDebug> +#include <QtCore/QOperatingSystemVersion> #include <QtCore/QSysInfo> #include <QtCore/QScopedArrayPointer> #include <QtCore/private/qsystemlibrary_p.h> @@ -186,7 +187,7 @@ QWindowsShcoreDLL::QWindowsShcoreDLL() void QWindowsShcoreDLL::init() { - if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1) + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1) return; QSystemLibrary library(QStringLiteral("SHCore")); getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness"); diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 26a5131927..9519b509bc 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -190,6 +190,20 @@ static inline Qt::KeyboardModifiers toQtKeyboardModifiers(DWORD keyState) return modifiers; } +static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState) +{ + Qt::MouseButtons buttons = Qt::NoButton; + + if (keyState & MK_LBUTTON) + buttons |= Qt::LeftButton; + if (keyState & MK_RBUTTON) + buttons |= Qt::RightButton; + if (keyState & MK_MBUTTON) + buttons |= Qt::MidButton; + + return buttons; +} + /*! \class QWindowsOleDropSource \brief Implementation of IDropSource @@ -405,16 +419,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState) break; } - // grfKeyState is broken on CE & some Windows XP versions, - // therefore we need to check the state manually - if ((GetAsyncKeyState(VK_LBUTTON) == 0) - && (GetAsyncKeyState(VK_MBUTTON) == 0) - && (GetAsyncKeyState(VK_RBUTTON) == 0)) { - hr = ResultFromScode(DRAGDROP_S_DROP); - break; - } - - const Qt::MouseButtons buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState); + const Qt::MouseButtons buttons = toQtMouseButtons(grfKeyState); if (m_currentButtons == Qt::NoButton) { m_currentButtons = buttons; } else { @@ -538,7 +543,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState, QWindowsDrag *windowsDrag = QWindowsDrag::instance(); const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect); QGuiApplicationPrivate::modifier_buttons = toQtKeyboardModifiers(grfKeyState); - QGuiApplicationPrivate::mouse_buttons = QWindowsMouseHandler::keyStateToMouseButtons(grfKeyState); + QGuiApplicationPrivate::mouse_buttons = toQtMouseButtons(grfKeyState); const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(), m_lastPoint, actions); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index d577d46b96..d1d7be123d 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -130,7 +130,7 @@ typedef struct qt_xcb_ge_event_t { static inline bool isXIEvent(xcb_generic_event_t *event, int opCode) { - qt_xcb_ge_event_t *e = (qt_xcb_ge_event_t *)event; + qt_xcb_ge_event_t *e = reinterpret_cast<qt_xcb_ge_event_t *>(event); return e->extension == opCode; } @@ -249,7 +249,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) // Find a fake screen const auto scrs = virtualDesktop->screens(); for (QPlatformScreen *scr : scrs) { - QXcbScreen *xcbScreen = (QXcbScreen *)scr; + QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(scr); if (xcbScreen->output() == XCB_NONE) { screen = xcbScreen; break; @@ -375,7 +375,7 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen) // When primary screen is removed, set the new primary screen // which belongs to the primary virtual desktop. if (screen->isPrimary()) { - QXcbScreen *newPrimary = (QXcbScreen *)virtualDesktop->screens().at(0); + QXcbScreen *newPrimary = static_cast<QXcbScreen *>(virtualDesktop->screens().at(0)); newPrimary->setPrimary(true); const int idx = m_screens.indexOf(newPrimary); if (idx > 0) @@ -709,7 +709,7 @@ QXcbConnection::~QXcbConnection() delete m_glIntegration; #ifdef XCB_USE_XLIB - XCloseDisplay((Display *)m_xlib_display); + XCloseDisplay(static_cast<Display *>(m_xlib_display)); #else xcb_disconnect(xcb_connection()); #endif @@ -752,7 +752,7 @@ QXcbWindow *QXcbConnection::platformWindowFromId(xcb_window_t id) #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, windowMember, handler) \ { \ - event_t *e = (event_t *)event; \ + event_t *e = reinterpret_cast<event_t *>(event); \ if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->windowMember)) { \ handled = eventListener->handleGenericEvent(event, &result); \ if (!handled) \ @@ -763,7 +763,7 @@ break; #define HANDLE_KEYBOARD_EVENT(event_t, handler) \ { \ - event_t *e = (event_t *)event; \ + event_t *e = reinterpret_cast<event_t *>(event); \ if (QXcbWindowEventListener *eventListener = windowEventListenerFromId(e->event)) { \ handled = eventListener->handleGenericEvent(event, &result); \ if (!handled) \ @@ -1182,11 +1182,11 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state); HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); case XCB_MAPPING_NOTIFY: - m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); + m_keyboard->handleMappingNotifyEvent(reinterpret_cast<xcb_mapping_notify_event_t *>(event)); break; case XCB_SELECTION_REQUEST: { - xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)event; + xcb_selection_request_event_t *sr = reinterpret_cast<xcb_selection_request_event_t *>(event); #ifndef QT_NO_DRAGANDDROP if (sr->selection == atom(QXcbAtom::XdndSelection)) m_drag->handleSelectionRequest(sr); @@ -1200,19 +1200,19 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) break; } case XCB_SELECTION_CLEAR: - setTime(((xcb_selection_clear_event_t *)event)->time); + setTime((reinterpret_cast<xcb_selection_clear_event_t *>(event))->time); #ifndef QT_NO_CLIPBOARD - m_clipboard->handleSelectionClearRequest((xcb_selection_clear_event_t *)event); + m_clipboard->handleSelectionClearRequest(reinterpret_cast<xcb_selection_clear_event_t *>(event)); #endif handled = true; break; case XCB_SELECTION_NOTIFY: - setTime(((xcb_selection_notify_event_t *)event)->time); + setTime((reinterpret_cast<xcb_selection_notify_event_t *>(event))->time); handled = false; break; case XCB_PROPERTY_NOTIFY: { - xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; + xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event); if (pn->atom == atom(QXcbAtom::_NET_WORKAREA)) { QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(pn->window); if (virtualDesktop) @@ -1237,7 +1237,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) if (!handled) { if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) { - xcb_xfixes_selection_notify_event_t *notify_event = (xcb_xfixes_selection_notify_event_t *)event; + xcb_xfixes_selection_notify_event_t *notify_event = reinterpret_cast<xcb_xfixes_selection_notify_event_t *>(event); setTime(notify_event->timestamp); #ifndef QT_NO_CLIPBOARD m_clipboard->handleXFixesSelectionRequest(notify_event); @@ -1247,10 +1247,10 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) handled = true; } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { - updateScreens((xcb_randr_notify_event_t *)event); + updateScreens(reinterpret_cast<xcb_randr_notify_event_t *>(event)); handled = true; } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { - xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event; + xcb_randr_screen_change_notify_event_t *change_event = reinterpret_cast<xcb_randr_screen_change_notify_event_t *>(event); for (QXcbScreen *s : qAsConst(m_screens)) { if (s->root() == change_event->root ) s->handleScreenChange(change_event); @@ -1359,7 +1359,7 @@ void QXcbEventReader::run() void QXcbEventReader::addEvent(xcb_generic_event_t *event) { if ((event->response_type & ~0x80) == XCB_CLIENT_MESSAGE - && ((xcb_client_message_event_t *)event)->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION)) + && (reinterpret_cast<xcb_client_message_event_t *>(event))->type == m_connection->atom(QXcbAtom::_QT_CLOSE_CONNECTION)) m_connection = 0; m_events << event; } @@ -1425,7 +1425,7 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) event.type = atom(a); event.data.data32[0] = id; - Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event)); + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event))); Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener)); xcb_flush(xcb_connection()); } @@ -1445,7 +1445,7 @@ namespace if ((event->response_type & ~0x80) != type) { return false; } else { - xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; + xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event); if ((pn->window == window) && (pn->atom == atom)) return true; } @@ -1473,7 +1473,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp() event = checkEvent(checker); } - xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; + xcb_property_notify_event_t *pn = reinterpret_cast<xcb_property_notify_event_t *>(event); xcb_timestamp_t timestamp = pn->time; free(event); @@ -1497,7 +1497,8 @@ xcb_window_t QXcbConnection::getQtSelectionOwner() { if (!m_qtSelectionOwner) { xcb_screen_t *xcbScreen = primaryVirtualDesktop()->screen(); - int x = 0, y = 0, w = 3, h = 3; + int16_t x = 0, y = 0; + uint16_t w = 3, h = 3; m_qtSelectionOwner = xcb_generate_id(xcb_connection()); Q_XCB_CALL(xcb_create_window(xcb_connection(), XCB_COPY_FROM_PARENT, // depth -- same as root @@ -1686,7 +1687,7 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex, for (int j = nextIndex; j < eventqueue->size(); ++j) { xcb_generic_event_t *next = eventqueue->at(j); if (isValid(next) && next->response_type == XCB_CONFIGURE_NOTIFY - && ((xcb_configure_notify_event_t *)next)->event == ((xcb_configure_notify_event_t*)event)->event) + && reinterpret_cast<xcb_configure_notify_event_t *>(next)->event == reinterpret_cast<xcb_configure_notify_event_t *>(event)->event) { return true; } @@ -1715,7 +1716,7 @@ void QXcbConnection::processXcbEvents() (*eventqueue)[i] = 0; if (!(event->response_type & ~0x80)) { - handleXcbError((xcb_generic_error_t *)event); + handleXcbError(reinterpret_cast<xcb_generic_error_t *>(event)); continue; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index f6ba828a15..c9fc27997b 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -694,7 +694,7 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE); #endif #endif -#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) +#define DISPLAY_FROM_XCB(object) (reinterpret_cast<Display *>(object->connection()->xlib_display())) #define CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(object) ((XVisualInfo *)(object->connection()->createVisualInfoForDefaultVisualId())) template<typename T> diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 1c13f8edc2..c175967054 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -103,6 +103,9 @@ #if defined(Q_OS_MACX) #include <IOKit/pwr_mgt/IOPMLib.h> +#include <mach/task.h> +#include <mach/mach_init.h> +#include <CoreFoundation/CFPreferences.h> #endif #include <vector> @@ -137,6 +140,40 @@ static bool debuggerPresent() return pid != 0; #elif defined(Q_OS_WIN) return IsDebuggerPresent(); +#elif defined(Q_OS_MACOS) + auto equals = [](CFStringRef str1, CFStringRef str2) -> bool { + return CFStringCompare(str1, str2, kCFCompareCaseInsensitive) == kCFCompareEqualTo; + }; + + // Check if there is an exception handler for the process: + mach_msg_type_number_t portCount = 0; + exception_mask_t masks[EXC_TYPES_COUNT]; + mach_port_t ports[EXC_TYPES_COUNT]; + exception_behavior_t behaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t flavors[EXC_TYPES_COUNT]; + exception_mask_t mask = EXC_MASK_ALL & ~(EXC_MASK_RESOURCE | EXC_MASK_GUARD); + kern_return_t result = task_get_exception_ports(mach_task_self(), mask, masks, &portCount, + ports, behaviors, flavors); + if (result == KERN_SUCCESS) { + for (mach_msg_type_number_t portIndex = 0; portIndex < portCount; ++portIndex) { + if (MACH_PORT_VALID(ports[portIndex])) { + return true; + } + } + } + + // Ok, no debugger attached. So, let's see if CrashReporter will throw up a dialog. If so, we + // leave it to the OS to do the stack trace. + CFStringRef crashReporterType = static_cast<CFStringRef>( + CFPreferencesCopyAppValue(CFSTR("DialogType"), CFSTR("com.apple.CrashReporter"))); + if (crashReporterType == nullptr) + return true; + + const bool createsStackTrace = + !equals(crashReporterType, CFSTR("server")) && + !equals(crashReporterType, CFSTR("none")); + CFRelease(crashReporterType); + return createsStackTrace; #else // TODO return false; diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index 8a1e1fd6e3..68b6b28945 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -40,6 +40,7 @@ SOURCES += \ ../../corelib/global/qlogging.cpp \ ../../corelib/global/qmalloc.cpp \ ../../corelib/global/qnumeric.cpp \ + ../../corelib/global/qoperatingsystemversion.cpp \ ../../corelib/io/qabstractfileengine.cpp \ ../../corelib/io/qbuffer.cpp \ ../../corelib/io/qdatastream.cpp \ @@ -108,7 +109,8 @@ unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \ ../../corelib/io/qfilesystemiterator_unix.cpp \ ../../corelib/io/qfsfileengine_unix.cpp -win32:SOURCES += ../../corelib/io/qfilesystemengine_win.cpp \ +win32:SOURCES += ../../corelib/global/qoperatingsystemversion_win.cpp \ + ../../corelib/io/qfilesystemengine_win.cpp \ ../../corelib/io/qfilesystemiterator_win.cpp \ ../../corelib/io/qfsfileengine_win.cpp \ ../../corelib/kernel/qcoreapplication_win.cpp \ @@ -119,6 +121,7 @@ mac { ../../corelib/kernel/qcoreapplication_mac.cpp \ ../../corelib/kernel/qcore_mac.cpp OBJECTIVE_SOURCES += \ + ../../corelib/global/qoperatingsystemversion_darwin.mm \ ../../corelib/kernel/qcore_mac_objc.mm \ ../../corelib/kernel/qcore_foundation.mm diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp index a99d6adf07..dcbe400224 100644 --- a/src/tools/uic/cpp/cppwriteincludes.cpp +++ b/src/tools/uic/cpp/cppwriteincludes.cpp @@ -114,8 +114,9 @@ void WriteIncludes::acceptUI(DomUI *node) TreeWalker::acceptUI(node); - if (!m_uic->option().includeFile.isEmpty()) - m_globalIncludes.insert(m_uic->option().includeFile, true); + const auto includeFile = m_uic->option().includeFile; + if (!includeFile.isEmpty()) + m_globalIncludes.insert(includeFile); writeHeaders(m_globalIncludes, true); writeHeaders(m_localIncludes, false); @@ -272,10 +273,11 @@ void WriteIncludes::insertInclude(const QString &header, bool global) fprintf(stderr, "%s %s %d\n", Q_FUNC_INFO, qPrintable(header), global); OrderedSet &includes = global ? m_globalIncludes : m_localIncludes; - if (includes.contains(header)) + // Insert (if not already done). + const bool isNewHeader = includes.insert(header).second; + if (!isNewHeader) return; - // Insert. Also remember base name for quick check of suspicious custom plugins - includes.insert(header, false); + // Also remember base name for quick check of suspicious custom plugins const QString lowerBaseName = QFileInfo(header).completeBaseName ().toLower(); m_includeBaseNames.insert(lowerBaseName); } @@ -286,13 +288,11 @@ void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global) const QChar closingQuote = global ? QLatin1Char('>') : QLatin1Char('"'); // Check for the old headers 'qslider.h' and replace by 'QtGui/QSlider' - const OrderedSet::const_iterator cend = headers.constEnd(); - for (OrderedSet::const_iterator sit = headers.constBegin(); sit != cend; ++sit) { - const StringMap::const_iterator hit = m_oldHeaderToNewHeader.constFind(sit.key()); - const bool mapped = hit != m_oldHeaderToNewHeader.constEnd(); - const QString header = mapped ? hit.value() : sit.key(); - if (!QStringRef(&header).trimmed().isEmpty()) - m_output << "#include " << openingQuote << header << closingQuote << QLatin1Char('\n'); + for (const QString &header : headers) { + const QString value = m_oldHeaderToNewHeader.value(header, header); + const auto trimmed = QStringRef(&value).trimmed(); + if (!trimmed.isEmpty()) + m_output << "#include " << openingQuote << trimmed << closingQuote << QLatin1Char('\n'); } } diff --git a/src/tools/uic/cpp/cppwriteincludes.h b/src/tools/uic/cpp/cppwriteincludes.h index 397c6a26e1..7a6a499536 100644 --- a/src/tools/uic/cpp/cppwriteincludes.h +++ b/src/tools/uic/cpp/cppwriteincludes.h @@ -35,6 +35,8 @@ #include <qset.h> #include <qstring.h> +#include <set> + QT_BEGIN_NAMESPACE class QTextStream; @@ -72,7 +74,7 @@ private: void add(const QString &className, bool determineHeader = true, const QString &header = QString(), bool global = false); private: - typedef QMap<QString, bool> OrderedSet; + typedef std::set<QString> OrderedSet; void insertIncludeForClass(const QString &className, QString header = QString(), bool global = false); void insertInclude(const QString &header, bool global); void writeHeaders(const OrderedSet &headers, bool global); diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp index e6fda103fb..bd9f0c6e01 100644 --- a/src/widgets/accessible/simplewidgets.cpp +++ b/src/widgets/accessible/simplewidgets.cpp @@ -468,21 +468,15 @@ QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > QAccessibleDisplay::relations(QAccessible::Relation match /* = QAccessible::AllRelations */) const { QVector<QPair<QAccessibleInterface*, QAccessible::Relation> > rels = QAccessibleWidget::relations(match); - if (match & QAccessible::Labelled) { - QVarLengthArray<QObject *, 4> relatedObjects; - #ifndef QT_NO_SHORTCUT + if (match & QAccessible::Labelled) { if (QLabel *label = qobject_cast<QLabel*>(object())) { - relatedObjects.append(label->buddy()); - } -#endif - for (int i = 0; i < relatedObjects.count(); ++i) { const QAccessible::Relation rel = QAccessible::Labelled; - QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(relatedObjects.at(i)); - if (iface) + if (QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(label->buddy())) rels.append(qMakePair(iface, rel)); } } +#endif return rels; } diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp index 9d8e7c4b66..1a38f43d35 100644 --- a/src/widgets/dialogs/qwizard_win.cpp +++ b/src/widgets/dialogs/qwizard_win.cpp @@ -46,6 +46,7 @@ #include "qwizard.h" #include "qpaintengine.h" #include "qapplication.h" +#include <QtCore/QOperatingSystemVersion> #include <QtCore/QVariant> #include <QtCore/QDebug> #include <QtGui/QMouseEvent> @@ -715,7 +716,7 @@ int QVistaHelper::topOffset() if (vistaState() != VistaAero) return titleBarSize() + 3; static const int aeroOffset = - QSysInfo::WindowsVersion == QSysInfo::WV_WINDOWS7 ? + QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8 ? QStyleHelper::dpiScaled(4) : QStyleHelper::dpiScaled(13); return aeroOffset + titleBarSize(); } diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp index 6e10d18e11..6a9036997c 100644 --- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.cpp @@ -2575,10 +2575,12 @@ void QGraphicsAnchorLayoutPrivate::identifyFloatItems(const QSet<AnchorData *> & for (const AnchorData *ad : visited) identifyNonFloatItems_helper(ad, &nonFloating); - QSet<QGraphicsLayoutItem *> allItems; - foreach (QGraphicsLayoutItem *item, items) - allItems.insert(item); - m_floatItems[orientation] = allItems - nonFloating; + QSet<QGraphicsLayoutItem *> floatItems; + for (QGraphicsLayoutItem *item : qAsConst(items)) { + if (!nonFloating.contains(item)) + floatItems.insert(item); + } + m_floatItems[orientation] = std::move(floatItems); } diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index dd0edc7c80..02079fb8d5 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -91,12 +91,6 @@ extern Q_GUI_EXPORT bool qt_is_gui_used; extern QClipboard *qt_clipboard; #endif -#if defined (Q_OS_WIN32) || defined (Q_OS_CYGWIN) -extern QSysInfo::WinVersion qt_winver; -#elif defined (Q_OS_MAC) -extern QSysInfo::MacVersion qt_macver; -#endif - typedef QHash<QByteArray, QFont> FontHash; FontHash *qt_app_fonts_hash(); diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm index 1f17810fc9..6fbc7c9eea 100644 --- a/src/widgets/styles/qmacstyle_mac.mm +++ b/src/widgets/styles/qmacstyle_mac.mm @@ -84,6 +84,7 @@ #include <qtoolbutton.h> #include <qtreeview.h> #include <qtableview.h> +#include <qoperatingsystemversion.h> #include <qwizard.h> #include <qdebug.h> #include <qlibrary.h> @@ -1310,7 +1311,7 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem bdi->adornment = kThemeAdornmentFocus; if (combo->activeSubControls & QStyle::SC_ComboBoxArrow) bdi->state = kThemeStatePressed; - else if (tds == kThemeStateInactive && QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) + else if (tds == kThemeStateInactive && QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite) bdi->state = kThemeStateActive; else bdi->state = tds; @@ -1632,7 +1633,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti || slider->tickPosition == QSlider::TicksBothSides; tdi->bounds = qt_hirectForQRect(slider->rect); - if (isScrollbar || QSysInfo::MacintoshVersion < QSysInfo::MV_10_10) { + if (isScrollbar || QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite) { tdi->min = slider->minimum; tdi->max = slider->maximum; tdi->value = slider->sliderPosition; @@ -1944,7 +1945,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD const bool button = opt->type == QStyleOption::SO_Button; const bool viewItem = opt->type == QStyleOption::SO_ViewItem; const bool pressed = bdi->state == kThemeStatePressed; - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; + const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite; if (button && pressed) { if (bdi->kind == kThemePushButton) { @@ -3579,7 +3580,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QWindow *window = w && w->window() ? w->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; + const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite; switch (ce) { case CE_HeaderSection: if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) { @@ -3971,7 +3972,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter bool hasIcon = !btn.icon.isNull(); bool hasText = !btn.text.isEmpty(); - if (!hasMenu && QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) { + if (!hasMenu && QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) { if (tds == kThemeStatePressed || (tds == kThemeStateActive && ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton) @@ -4076,8 +4077,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QStyleOptionComboBox comboCopy = *cb; comboCopy.direction = Qt::LeftToRight; if (opt->state & QStyle::State_Small) - comboCopy.rect.translate(0, w ? 0 : (QSysInfo::macVersion() >= QSysInfo::MV_10_10 ? 0 : -2)); // Supports Qt Quick Controls - else if (QSysInfo::macVersion() == QSysInfo::MV_10_9) + comboCopy.rect.translate(0, w ? 0 : (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite ? 0 : -2)); // Supports Qt Quick Controls + else if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXMavericks + && QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite) comboCopy.rect.translate(0, 1); QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); } @@ -5289,7 +5291,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : QStyleHelper::styleObjectWindow(opt->styleObject); const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window); - const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10; + const bool usingYosemiteOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite; switch (cc) { case CC_Slider: case CC_ScrollBar: @@ -5933,7 +5935,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex drawToolbarButtonArrow(tb->rect, tds, cg); } if (tb->state & State_On) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) { QWindow *window = 0; if (widget && widget->window()) window = widget->window()->windowHandle(); @@ -6297,7 +6299,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op switch (sc) { case SC_ComboBoxEditField:{ ret = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi); - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_10) + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXYosemite) ret.setHeight(ret.height() - 1); break; } case SC_ComboBoxArrow:{ @@ -6756,7 +6758,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, case CT_ComboBox: { sz.rwidth() += 50; const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt); - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || (cb && !cb->editable)) + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::OSXYosemite || (cb && !cb->editable)) sz.rheight() += 2; break; } diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp index bf5aad0187..8c91e3a420 100644 --- a/src/widgets/styles/qwindowsvistastyle.cpp +++ b/src/widgets/styles/qwindowsvistastyle.cpp @@ -39,6 +39,7 @@ #include "qwindowsvistastyle_p.h" #include "qwindowsvistastyle_p_p.h" +#include <qoperatingsystemversion.h> #include <qscreen.h> #include <qwindow.h> #include <private/qstyleanimation_p.h> @@ -1752,7 +1753,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle theme.stateId = stateId; d->drawBackground(theme); - if (QSysInfo::WindowsVersion < QSysInfo::WV_WINDOWS8) { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) { const QRect gripperBounds = QWindowsXPStylePrivate::scrollBarGripperBounds(flags, widget, &theme); // Draw gripper if there is enough space if (!gripperBounds.isEmpty() && flags & State_Enabled) { diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index 2a418167f1..9dfd35cadb 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -59,6 +59,25 @@ QT_BEGIN_NAMESPACE +static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon) +{ + QStyle::StandardPixmap stdIcon; + switch (icon) { + case QSystemTrayIcon::Information: + stdIcon = QStyle::SP_MessageBoxInformation; + break; + case QSystemTrayIcon::Warning: + stdIcon = QStyle::SP_MessageBoxWarning; + break; + case QSystemTrayIcon::Critical: + stdIcon = QStyle::SP_MessageBoxCritical; + break; + case QSystemTrayIcon::NoIcon: + return QIcon(); + } + return QApplication::style()->standardIcon(stdIcon); +} + /*! \class QSystemTrayIcon \brief The QSystemTrayIcon class provides an icon for an application in the system tray. @@ -382,11 +401,29 @@ bool QSystemTrayIcon::supportsMessages() \sa show(), supportsMessages() */ void QSystemTrayIcon::showMessage(const QString& title, const QString& msg, - QSystemTrayIcon::MessageIcon icon, int msecs) + QSystemTrayIcon::MessageIcon msgIcon, int msecs) { Q_D(QSystemTrayIcon); if (d->visible) - d->showMessage_sys(title, msg, icon, msecs); + d->showMessage_sys(title, msg, messageIcon2qIcon(msgIcon), msgIcon, msecs); +} + +/*! + \fn void QSystemTrayIcon::showMessage(const QString &title, const QString &message, const QIcon &icon, int millisecondsTimeoutHint) + + \overload showMessage() + + Shows a balloon message for the entry with the given \a title, \a message, + and custom icon \a icon for the time specified in \a millisecondsTimeoutHint. + + \since 5.9 +*/ +void QSystemTrayIcon::showMessage(const QString &title, const QString &msg, + const QIcon &icon, int msecs) +{ + Q_D(QSystemTrayIcon); + if (d->visible) + d->showMessage_sys(title, msg, icon, QSystemTrayIcon::NoIcon, msecs); } void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason reason) @@ -398,9 +435,9 @@ void QSystemTrayIconPrivate::_q_emitActivated(QPlatformSystemTrayIcon::Activatio ////////////////////////////////////////////////////////////////////// static QBalloonTip *theSolitaryBalloonTip = 0; -void QBalloonTip::showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& message, QSystemTrayIcon *trayIcon, - const QPoint& pos, int timeout, bool showArrow) +void QBalloonTip::showBalloon(const QIcon &icon, const QString &title, + const QString &message, QSystemTrayIcon *trayIcon, + const QPoint &pos, int timeout, bool showArrow) { hideBalloon(); if (message.isEmpty() && title.isEmpty()) @@ -434,8 +471,8 @@ bool QBalloonTip::isBalloonVisible() return theSolitaryBalloonTip; } -QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& message, QSystemTrayIcon *ti) +QBalloonTip::QBalloonTip(const QIcon &icon, const QString &title, + const QString &message, QSystemTrayIcon *ti) : QWidget(0, Qt::ToolTip), trayIcon(ti), timerId(-1) { setAttribute(Qt::WA_DeleteOnClose); @@ -482,26 +519,10 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title msgLabel->setFixedSize(limit, msgLabel->heightForWidth(limit)); } - QIcon si; - switch (icon) { - case QSystemTrayIcon::Warning: - si = style()->standardIcon(QStyle::SP_MessageBoxWarning); - break; - case QSystemTrayIcon::Critical: - si = style()->standardIcon(QStyle::SP_MessageBoxCritical); - break; - case QSystemTrayIcon::Information: - si = style()->standardIcon(QStyle::SP_MessageBoxInformation); - break; - case QSystemTrayIcon::NoIcon: - default: - break; - } - QGridLayout *layout = new QGridLayout; - if (!si.isNull()) { + if (!icon.isNull()) { QLabel *iconLabel = new QLabel; - iconLabel->setPixmap(si.pixmap(iconSize, iconSize)); + iconLabel->setPixmap(icon.pixmap(iconSize, iconSize)); iconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); iconLabel->setMargin(2); layout->addWidget(iconLabel, 0, 0); @@ -678,52 +699,6 @@ void QSystemTrayIconPrivate::remove_sys_qpa() qpa_sys->cleanup(); } -QRect QSystemTrayIconPrivate::geometry_sys_qpa() const -{ - return qpa_sys->geometry(); -} - -void QSystemTrayIconPrivate::updateIcon_sys_qpa() -{ - qpa_sys->updateIcon(icon); -} - -void QSystemTrayIconPrivate::updateMenu_sys_qpa() -{ - if (menu) { - addPlatformMenu(menu); - qpa_sys->updateMenu(menu->platformMenu()); - } -} - -void QSystemTrayIconPrivate::updateToolTip_sys_qpa() -{ - qpa_sys->updateToolTip(toolTip); -} - -void QSystemTrayIconPrivate::showMessage_sys_qpa(const QString &title, - const QString &message, - QSystemTrayIcon::MessageIcon icon, - int msecs) -{ - QIcon notificationIcon; - switch (icon) { - case QSystemTrayIcon::Information: - notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxInformation); - break; - case QSystemTrayIcon::Warning: - notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxWarning); - break; - case QSystemTrayIcon::Critical: - notificationIcon = QApplication::style()->standardIcon(QStyle::SP_MessageBoxCritical); - break; - default: - break; - } - qpa_sys->showMessage(title, message, notificationIcon, - static_cast<QPlatformSystemTrayIcon::MessageIcon>(icon), msecs); -} - void QSystemTrayIconPrivate::addPlatformMenu(QMenu *menu) const { if (menu->platformMenu()) diff --git a/src/widgets/util/qsystemtrayicon.h b/src/widgets/util/qsystemtrayicon.h index fb238c92b0..918dd0478e 100644 --- a/src/widgets/util/qsystemtrayicon.h +++ b/src/widgets/util/qsystemtrayicon.h @@ -101,6 +101,7 @@ public Q_SLOTS: void setVisible(bool visible); inline void show() { setVisible(true); } inline void hide() { setVisible(false); } + void showMessage(const QString &title, const QString &msg, const QIcon &icon, int msecs = 10000); void showMessage(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon = QSystemTrayIcon::Information, int msecs = 10000); diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h index 79e824f4b7..3f5cab40be 100644 --- a/src/widgets/util/qsystemtrayicon_p.h +++ b/src/widgets/util/qsystemtrayicon_p.h @@ -84,7 +84,8 @@ public: void updateToolTip_sys(); void updateMenu_sys(); QRect geometry_sys() const; - void showMessage_sys(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs); + void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon, + QSystemTrayIcon::MessageIcon msgIcon, int msecs); static bool isSystemTrayAvailable_sys(); static bool supportsMessages_sys(); @@ -101,11 +102,7 @@ public: private: void install_sys_qpa(); void remove_sys_qpa(); - void updateIcon_sys_qpa(); - void updateToolTip_sys_qpa(); - void updateMenu_sys_qpa(); - QRect geometry_sys_qpa() const; - void showMessage_sys_qpa(const QString &title, const QString &msg, QSystemTrayIcon::MessageIcon icon, int secs); + void addPlatformMenu(QMenu *menu) const; }; @@ -113,16 +110,16 @@ class QBalloonTip : public QWidget { Q_OBJECT public: - static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& msg, QSystemTrayIcon *trayIcon, - const QPoint& pos, int timeout, bool showArrow = true); + static void showBalloon(const QIcon &icon, const QString &title, + const QString &msg, QSystemTrayIcon *trayIcon, + const QPoint &pos, int timeout, bool showArrow = true); static void hideBalloon(); static bool isBalloonVisible(); static void updateBalloonPosition(const QPoint& pos); private: - QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title, - const QString& msg, QSystemTrayIcon *trayIcon); + QBalloonTip(const QIcon &icon, const QString &title, + const QString &msg, QSystemTrayIcon *trayIcon); ~QBalloonTip(); void balloon(const QPoint&, int, bool); diff --git a/src/widgets/util/qsystemtrayicon_qpa.cpp b/src/widgets/util/qsystemtrayicon_qpa.cpp index 643f17a5fe..8399732a4a 100644 --- a/src/widgets/util/qsystemtrayicon_qpa.cpp +++ b/src/widgets/util/qsystemtrayicon_qpa.cpp @@ -76,7 +76,7 @@ void QSystemTrayIconPrivate::remove_sys() QRect QSystemTrayIconPrivate::geometry_sys() const { if (qpa_sys) - return geometry_sys_qpa(); + return qpa_sys->geometry(); else return QRect(); } @@ -84,19 +84,21 @@ QRect QSystemTrayIconPrivate::geometry_sys() const void QSystemTrayIconPrivate::updateIcon_sys() { if (qpa_sys) - updateIcon_sys_qpa(); + qpa_sys->updateIcon(icon); } void QSystemTrayIconPrivate::updateMenu_sys() { - if (qpa_sys) - updateMenu_sys_qpa(); + if (qpa_sys && menu) { + addPlatformMenu(menu); + qpa_sys->updateMenu(menu->platformMenu()); + } } void QSystemTrayIconPrivate::updateToolTip_sys() { if (qpa_sys) - updateToolTip_sys_qpa(); + qpa_sys->updateToolTip(toolTip); } bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys() @@ -118,10 +120,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys() } void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, - QSystemTrayIcon::MessageIcon icon, int msecs) + const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs) { if (qpa_sys) - showMessage_sys_qpa(title, message, icon, msecs); + qpa_sys->showMessage(title, message, icon, + static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs); } QT_END_NAMESPACE diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp index 2da24e482b..638d2050fb 100644 --- a/src/widgets/util/qsystemtrayicon_win.cpp +++ b/src/widgets/util/qsystemtrayicon_win.cpp @@ -81,11 +81,14 @@ struct Q_NOTIFYICONIDENTIFIER { # define NIN_BALLOONTIMEOUT (WM_USER + 4) # define NIN_BALLOONUSERCLICK (WM_USER + 5) # define NIF_SHOWTIP 0x00000080 +# define NIIF_LARGE_ICON 0x00000020 # define NOTIFYICON_VERSION_4 4 #endif #define Q_MSGFLT_ALLOW 1 +Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &); + typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation); typedef BOOL (WINAPI *PtrChangeWindowMessageFilter)(UINT message, DWORD dwFlag); typedef BOOL (WINAPI *PtrChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, void* pChangeFilterStruct); @@ -107,7 +110,7 @@ public: ~QSystemTrayIconSys(); bool trayMessage(DWORD msg); void setIconContents(NOTIFYICONDATA &data); - bool showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs); + bool showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs); QRect findIconGeometry(UINT iconId); HICON createIcon(); bool winEvent(MSG *m, long *result); @@ -184,7 +187,7 @@ static inline HWND createTrayIconMessageWindow() QSystemTrayIconSys::QSystemTrayIconSys(HWND hwnd, QSystemTrayIcon *object) : m_hwnd(hwnd), hIcon(0), q(object) - , notifyIconSize(NOTIFYICONDATA_V2_SIZE), version(NOTIFYICON_VERSION) + , notifyIconSize(sizeof(NOTIFYICONDATA)), version(NOTIFYICON_VERSION_4) , ignoreNextMouseRelease(false) { @@ -237,11 +240,7 @@ void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd) qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip)/sizeof(wchar_t)); } -#ifndef NIIF_LARGE_ICON -# define NIIF_LARGE_ICON 0x00000020 -#endif - -bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, QSystemTrayIcon::MessageIcon type, uint uSecs) +bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs) { NOTIFYICONDATA tnd; memset(&tnd, 0, notifyIconSize); @@ -249,23 +248,32 @@ bool QSystemTrayIconSys::showMessage(const QString &title, const QString &messag qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64); tnd.uID = q_uNOTIFYICONID; - switch (type) { - case QSystemTrayIcon::Information: + tnd.dwInfoFlags = NIIF_USER; + + HICON *phIcon = &tnd.hIcon; + QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON)); + if (version == NOTIFYICON_VERSION_4) { + const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON)); + QSize more = icon.actualSize(largeIcon); + if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) { + tnd.dwInfoFlags |= NIIF_LARGE_ICON; + size = largeIcon; + } + phIcon = &tnd.hBalloonIcon; + } + QPixmap pm = icon.pixmap(size); + if (pm.isNull()) { tnd.dwInfoFlags = NIIF_INFO; - break; - case QSystemTrayIcon::Warning: - tnd.dwInfoFlags = NIIF_WARNING; - break; - case QSystemTrayIcon::Critical: - tnd.dwInfoFlags = NIIF_ERROR; - break; - case QSystemTrayIcon::NoIcon: - tnd.dwInfoFlags = hIcon ? NIIF_USER : NIIF_NONE; - break; + } else { + if (pm.size() != size) { + qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d", + pm.size().width(), pm.size().height(), size.width(), size.height()); + pm = pm.scaled(size, Qt::IgnoreAspectRatio); + } + *phIcon = qt_pixmapToWinHICON(pm); } - if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) - tnd.dwInfoFlags |= NIIF_LARGE_ICON; tnd.cbSize = notifyIconSize; + tnd.uVersion = version; tnd.hWnd = m_hwnd; tnd.uTimeout = uSecs; tnd.uFlags = NIF_INFO | NIF_SHOWTIP; @@ -296,8 +304,6 @@ bool QSystemTrayIconSys::trayMessage(DWORD msg) return success; } -Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &); - HICON QSystemTrayIconSys::createIcon() { const HICON oldIcon = hIcon; @@ -509,7 +515,8 @@ QRect QSystemTrayIconSys::findIconGeometry(UINT iconId) void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &messageIn, - QSystemTrayIcon::MessageIcon type, + const QIcon &icon, + QSystemTrayIcon::MessageIcon, int timeOut) { if (!sys || !allowsMessages()) @@ -522,7 +529,7 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title, if (message.isEmpty() && !title.isEmpty()) message.append(QLatin1Char(' ')); - sys->showMessage(title, message, type, uSecs); + sys->showMessage(title, message, icon, uSecs); } QRect QSystemTrayIconPrivate::geometry_sys() const diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index ea0604b6ed..20ab0f6377 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -284,7 +284,7 @@ void QSystemTrayIconPrivate::install_sys() QRect QSystemTrayIconPrivate::geometry_sys() const { if (qpa_sys) - return geometry_sys_qpa(); + return qpa_sys->geometry(); if (!sys) return QRect(); return sys->globalGeometry(); @@ -307,7 +307,7 @@ void QSystemTrayIconPrivate::remove_sys() void QSystemTrayIconPrivate::updateIcon_sys() { if (qpa_sys) { - updateIcon_sys_qpa(); + qpa_sys->updateIcon(icon); return; } if (sys) @@ -316,14 +316,16 @@ void QSystemTrayIconPrivate::updateIcon_sys() void QSystemTrayIconPrivate::updateMenu_sys() { - if (qpa_sys) - updateMenu_sys_qpa(); + if (qpa_sys && menu) { + addPlatformMenu(menu); + qpa_sys->updateMenu(menu->platformMenu()); + } } void QSystemTrayIconPrivate::updateToolTip_sys() { if (qpa_sys) { - updateToolTip_sys_qpa(); + qpa_sys->updateToolTip(toolTip); return; } if (!sys) @@ -357,10 +359,11 @@ bool QSystemTrayIconPrivate::supportsMessages_sys() } void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString &message, - QSystemTrayIcon::MessageIcon icon, int msecs) + const QIcon &icon, QSystemTrayIcon::MessageIcon msgIcon, int msecs) { if (qpa_sys) { - showMessage_sys_qpa(title, message, icon, msecs); + qpa_sys->showMessage(title, message, icon, + static_cast<QPlatformSystemTrayIcon::MessageIcon>(msgIcon), msecs); return; } if (!sys) diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp index 2f039cbcd8..0e8a784423 100644 --- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp +++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp @@ -159,6 +159,7 @@ private slots: void iniCodec(); void bom(); + void testXdg(); private: void cleanupTestFiles(); @@ -3397,5 +3398,77 @@ void tst_QSettings::consistentRegistryStorage() } #endif +#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(QT_NO_STANDARDPATHS) +QT_BEGIN_NAMESPACE +extern void clearDefaultPaths(); +QT_END_NAMESPACE +#endif +void tst_QSettings::testXdg() +{ +#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) && !defined(Q_OS_ANDROID) && !defined(QT_NO_STANDARDPATHS) + // Note: The XDG_CONFIG_DIRS test must be done before overriding the system path + // by QSettings::setPath/setSystemIniPath (used in cleanupTestFiles()). + clearDefaultPaths(); + + // Initialize the env. variable & populate testing files. + const QStringList config_dirs = { settingsPath("xdg_1st"), settingsPath("xdg_2nd"), settingsPath("xdg_3rd") }; + qputenv("XDG_CONFIG_DIRS", config_dirs.join(':').toUtf8()); + QList<QSettings *> xdg_orgs, xdg_apps; + for (const auto & dir : config_dirs) { + xdg_orgs << new QSettings{dir + "/software.org.conf", QSettings::NativeFormat}; + xdg_apps << new QSettings{dir + "/software.org/KillerAPP.conf", QSettings::NativeFormat}; + } + Q_ASSERT(config_dirs.size() == 3 && xdg_orgs.size() == 3 && xdg_apps.size() == 3); + for (int i = 0; i < 3; ++i) { + xdg_orgs[i]->setValue("all", QString{"all_org%1"}.arg(i)); + xdg_apps[i]->setValue("all", QString{"all_app%1"}.arg(i)); + xdg_orgs[i]->setValue("all_only_org", QString{"all_only_org%1"}.arg(i)); + xdg_apps[i]->setValue("all_only_app", QString{"all_only_app%1"}.arg(i)); + + if (i > 0) { + xdg_orgs[i]->setValue("from2nd", QString{"from2nd_org%1"}.arg(i)); + xdg_apps[i]->setValue("from2nd", QString{"from2nd_app%1"}.arg(i)); + xdg_orgs[i]->setValue("from2nd_only_org", QString{"from2nd_only_org%1"}.arg(i)); + xdg_apps[i]->setValue("from2nd_only_app", QString{"from2nd_only_app%1"}.arg(i)); + } + + if (i > 1) { + xdg_orgs[i]->setValue("from3rd", QString{"from3rd_org%1"}.arg(i)); + xdg_apps[i]->setValue("from3rd", QString{"from3rd_app%1"}.arg(i)); + xdg_orgs[i]->setValue("from3rd_only_org", QString{"from3rd_only_org%1"}.arg(i)); + xdg_apps[i]->setValue("from3rd_only_app", QString{"from3rd_only_app%1"}.arg(i)); + } + } + qDeleteAll(xdg_apps); + qDeleteAll(xdg_orgs); + + // Do the test. + QSettings app{QSettings::SystemScope, "software.org", "KillerAPP"}, org{QSettings::SystemScope, "software.org"}; + + QVERIFY(app.value("all").toString() == "all_app0"); + QVERIFY(org.value("all").toString() == "all_org0"); + QVERIFY(app.value("all_only_org").toString() == "all_only_org0"); + QVERIFY(org.value("all_only_org").toString() == "all_only_org0"); + QVERIFY(app.value("all_only_app").toString() == "all_only_app0"); + QVERIFY(org.value("all_only_app").toString() == QString{}); + + QVERIFY(app.value("from2nd").toString() == "from2nd_app1"); + QVERIFY(org.value("from2nd").toString() == "from2nd_org1"); + QVERIFY(app.value("from2nd_only_org").toString() == "from2nd_only_org1"); + QVERIFY(org.value("from2nd_only_org").toString() == "from2nd_only_org1"); + QVERIFY(app.value("from2nd_only_app").toString() == "from2nd_only_app1"); + QVERIFY(org.value("from2nd_only_app").toString() == QString{}); + + QVERIFY(app.value("from3rd").toString() == "from3rd_app2"); + QVERIFY(org.value("from3rd").toString() == "from3rd_org2"); + QVERIFY(app.value("from3rd_only_org").toString() == "from3rd_only_org2"); + QVERIFY(org.value("from3rd_only_org").toString() == "from3rd_only_org2"); + QVERIFY(app.value("from3rd_only_app").toString() == "from3rd_only_app2"); + QVERIFY(org.value("from3rd_only_app").toString() == QString{}); +#else + QSKIP("This test is performed in QT_BUILD_INTERNAL on Q_XDG_PLATFORM with use of standard paths only."); +#endif +} + QTEST_MAIN(tst_QSettings) #include "tst_qsettings.moc" diff --git a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp index 5b18ab9d68..0b536f26de 100644 --- a/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp +++ b/tests/auto/corelib/io/qstandardpaths/tst_qstandardpaths.cpp @@ -372,7 +372,7 @@ void tst_qstandardpaths::testFindExecutable_data() QTest::newRow("win-cmd-nosuffix") << QString() << QString::fromLatin1("cmd") << cmdPath; - if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS8) { + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8) { // The logo executable on Windows 8 is perfectly suited for testing that the // suffix mechanism is not thrown off by dots in the name. const QString logo = QLatin1String("microsoft.windows.softwarelogo.showdesktop"); diff --git a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp index 487c13be94..758bbead84 100644 --- a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp +++ b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp @@ -57,6 +57,8 @@ private slots: void fileTemplate_data(); void getSetCheck(); void fileName(); + void filePath_data(); + void filePath(); void autoRemove(); void nonWritableCurrentDir(); void openOnRootDrives(); @@ -204,6 +206,29 @@ void tst_QTemporaryDir::fileName() QCOMPARE(absoluteFilePath, absoluteTempPath); } +void tst_QTemporaryDir::filePath_data() +{ + QTest::addColumn<QString>("templatePath"); + QTest::addColumn<QString>("fileName"); + + QTest::newRow("0") << QString() << "/tmpfile"; + QTest::newRow("1") << QString() << "tmpfile"; + QTest::newRow("2") << "XXXXX" << "tmpfile"; + QTest::newRow("3") << "YYYYY" << "subdir/file"; +} + +void tst_QTemporaryDir::filePath() +{ + QFETCH(QString, templatePath); + QFETCH(QString, fileName); + + QTemporaryDir dir(templatePath); + const QString filePath = dir.filePath(fileName); + const QString expectedFilePath = QDir::isAbsolutePath(fileName) ? + QString() : dir.path() + QLatin1Char('/') + fileName; + QCOMPARE(filePath, expectedFilePath); +} + void tst_QTemporaryDir::autoRemove() { // Test auto remove diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 0f7f75fb2e..fea185c48f 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -3401,14 +3401,12 @@ void tst_QObject::dumpObjectInfo() QObject a, b; QObject::connect(&a, SIGNAL(destroyed(QObject*)), &b, SLOT(deleteLater())); a.disconnect(&b); -#ifdef QT_DEBUG QTest::ignoreMessage(QtDebugMsg, "OBJECT QObject::unnamed"); QTest::ignoreMessage(QtDebugMsg, " SIGNALS OUT"); QTest::ignoreMessage(QtDebugMsg, " signal: destroyed(QObject*)"); QTest::ignoreMessage(QtDebugMsg, " <Disconnected receiver>"); QTest::ignoreMessage(QtDebugMsg, " SIGNALS IN"); QTest::ignoreMessage(QtDebugMsg, " <None>"); -#endif a.dumpObjectInfo(); // should not crash } diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 0c41f66357..65887e50d3 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -65,6 +65,8 @@ private slots: void simpleVectorReserve(); void allocate_data(); void allocate(); + void reallocate_data() { allocate_data(); } + void reallocate(); void alignment_data(); void alignment(); void typedData(); @@ -742,6 +744,54 @@ void tst_QArrayData::allocate() } } +void tst_QArrayData::reallocate() +{ + QFETCH(size_t, objectSize); + QFETCH(size_t, alignment); + QFETCH(QArrayData::AllocationOptions, allocateOptions); + QFETCH(bool, isCapacityReserved); + QFETCH(const QArrayData *, commonEmpty); + + // Maximum alignment that can be requested is that of QArrayData, + // otherwise, we can't use reallocate(). + Q_ASSERT(alignment <= Q_ALIGNOF(QArrayData)); + + // Minimum alignment that can be requested is that of QArrayData. + // Typically, this alignment is sizeof(void *) and ensured by malloc. + size_t minAlignment = qMax(alignment, Q_ALIGNOF(QArrayData)); + + int capacity = 10; + Deallocator keeper(objectSize, minAlignment); + QArrayData *data = QArrayData::allocate(objectSize, minAlignment, capacity, + QArrayData::AllocationOptions(allocateOptions) & ~QArrayData::Grow); + keeper.headers.append(data); + + memset(data->data(), 'A', objectSize * capacity); + data->size = capacity; + + // now try to reallocate + int newCapacity = 40; + data = QArrayData::reallocateUnaligned(data, objectSize, newCapacity, + QArrayData::AllocationOptions(allocateOptions)); + QVERIFY(data); + keeper.headers.clear(); + keeper.headers.append(data); + + QCOMPARE(data->size, capacity); + if (allocateOptions & QArrayData::Grow) + QVERIFY(data->alloc > uint(newCapacity)); + else + QCOMPARE(data->alloc, uint(newCapacity)); + QCOMPARE(data->capacityReserved, uint(isCapacityReserved)); +#if !defined(QT_NO_UNSHARABLE_CONTAINERS) + QFETCH(bool, isSharable); + QCOMPARE(data->ref.isSharable(), isSharable); +#endif + + for (int i = 0; i < capacity; ++i) + QCOMPARE(static_cast<char *>(data->data())[i], 'A'); +} + class Unaligned { char dummy[8]; diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 8d9a789507..7681f4755c 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -1754,6 +1754,30 @@ void tst_QLocale::numberOptions() QVERIFY(ok); locale.toDouble(QString("1.24e+01"), &ok); QVERIFY(!ok); + + QCOMPARE(locale.toString(12.4, 'g', 5), QString("12.4")); + locale.setNumberOptions(QLocale::IncludeTrailingZeroesAfterDot); + QCOMPARE(locale.numberOptions(), QLocale::IncludeTrailingZeroesAfterDot); + QCOMPARE(locale.toString(12.4, 'g', 5), QString("12.400")); + + locale.toDouble(QString("1.24e+01"), &ok); + QVERIFY(ok); + locale.toDouble(QString("1.2400e+01"), &ok); + QVERIFY(ok); + locale.toDouble(QString("12.4"), &ok); + QVERIFY(ok); + locale.toDouble(QString("12.400"), &ok); + QVERIFY(ok); + locale.setNumberOptions(QLocale::RejectTrailingZeroesAfterDot); + QCOMPARE(locale.numberOptions(), QLocale::RejectTrailingZeroesAfterDot); + locale.toDouble(QString("1.24e+01"), &ok); + QVERIFY(ok); + locale.toDouble(QString("1.2400e+01"), &ok); + QVERIFY(!ok); + locale.toDouble(QString("12.4"), &ok); + QVERIFY(ok); + locale.toDouble(QString("12.400"), &ok); + QVERIFY(!ok); } void tst_QLocale::negativeNumbers() diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 43e05c95f9..61927862f7 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -104,10 +104,10 @@ class tst_QNetworkReply: public QObject Q_OBJECT #ifndef QT_NO_NETWORKPROXY - struct ProxyData { + struct ProxyData + { ProxyData(const QNetworkProxy &p, const QByteArray &t, bool auth) - : tag(t), proxy(p), requiresAuthentication(auth) - { } + : tag(t), proxy(p), requiresAuthentication(auth) {} QByteArray tag; QNetworkProxy proxy; bool requiresAuthentication; @@ -115,7 +115,8 @@ class tst_QNetworkReply: public QObject #endif // !QT_NO_NETWORKPROXY static bool seedCreated; - static QString createUniqueExtension() { + static QString createUniqueExtension() + { if (!seedCreated) { qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) + QCoreApplication::applicationPid()); seedCreated = true; // not thread-safe, but who cares @@ -534,7 +535,7 @@ QT_END_NAMESPACE QString errorMsg = call; \ if (!errorMsg.isEmpty()) \ QFAIL(qPrintable(errorMsg)); \ - } while (0); + } while (0) #ifndef QT_NO_SSL static void setupSslServer(QSslSocket* serverSocket) @@ -546,6 +547,7 @@ static void setupSslServer(QSslSocket* serverSocket) serverSocket->setProtocol(QSsl::AnyProtocol); serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem"); serverSocket->setPrivateKey(testDataDir + "/certs/server.key"); + serverSocket->startServerEncryption(); } #endif @@ -592,31 +594,30 @@ protected: void incomingConnection(qintptr socketDescriptor) { //qDebug() << "incomingConnection" << socketDescriptor << "doSsl:" << doSsl << "ipv6:" << ipv6; - if (!doSsl) { - client = new QTcpSocket; - client->setSocketDescriptor(socketDescriptor); - connectSocketSignals(); - } else { #ifndef QT_NO_SSL - QSslSocket *serverSocket = new QSslSocket; - serverSocket->setParent(this); - if (serverSocket->setSocketDescriptor(socketDescriptor)) { - connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>))); - setupSslServer(serverSocket); - serverSocket->startServerEncryption(); - client = serverSocket; - connectSocketSignals(); - } else { + if (doSsl) { + QSslSocket *serverSocket = new QSslSocket(this); + if (!serverSocket->setSocketDescriptor(socketDescriptor)) { delete serverSocket; return; } + connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>))); + // connect(serverSocket, &QSslSocket::encrypted, this, &SslServer::ready); ? + setupSslServer(serverSocket); + client = serverSocket; + } else #endif + { + client = new QTcpSocket; + client->setSocketDescriptor(socketDescriptor); } + connectSocketSignals(); client->setParent(this); ++totalConnections; } - virtual void reply() { + virtual void reply() + { Q_ASSERT(!client.isNull()); // we need to emulate the bytesWrittenSlot call if the data is empty. if (dataToTransmit.size() == 0) { @@ -673,7 +674,8 @@ public slots: } } - void bytesWrittenSlot() { + void bytesWrittenSlot() + { Q_ASSERT(!client.isNull()); // Disconnect and delete in next cycle (else Windows clients will fail with RemoteHostClosedError). if (doClose && client->bytesToWrite() == 0) { @@ -918,7 +920,8 @@ class BlockingTcpServer : public QTcpServer public: BlockingTcpServer(bool ssl) : doSsl(ssl), sslSocket(0) {} - QTcpSocket* waitForNextConnectionSocket() { + QTcpSocket* waitForNextConnectionSocket() + { waitForNewConnection(-1); if (doSsl) { if (!sslSocket) @@ -939,7 +942,6 @@ public: serverSocket->setSocketDescriptor(socketDescriptor); connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(slotSslErrors(QList<QSslError>))); setupSslServer(serverSocket); - serverSocket->startServerEncryption(); sslSocket = serverSocket; } else #endif @@ -1420,14 +1422,12 @@ static QByteArray msgWaitForFinished(QNetworkReplyPtr &reply) QString result; QDebug debug(&result); debug << reply->url(); - if (reply->isFinished()) { - if (reply->error() == QNetworkReply::NoError) - debug << "finished."; - else - debug << "failed: #" << reply->error() << reply->errorString(); - } else { + if (!reply->isFinished()) debug << "timed out."; - } + else if (reply->error() == QNetworkReply::NoError) + debug << "finished."; + else + debug << "failed: #" << reply->error() << reply->errorString(); return result.toLocal8Bit(); } @@ -1442,7 +1442,7 @@ int tst_QNetworkReply::waitForFinish(QNetworkReplyPtr &reply) QSignalSpy spy(reply.data(), SIGNAL(downloadProgress(qint64,qint64))); while (!reply->isFinished()) { QTimer::singleShot(5000, loop, SLOT(quit())); - if ( loop->exec() == Timeout && count == spy.count() && !reply->isFinished()) { + if (loop->exec() == Timeout && count == spy.count() && !reply->isFinished()) { returnCode = Timeout; break; } @@ -1456,12 +1456,14 @@ int tst_QNetworkReply::waitForFinish(QNetworkReplyPtr &reply) void tst_QNetworkReply::finished() { - loop->exit(returnCode = Success); + if (loop) + loop->exit(returnCode = Success); } void tst_QNetworkReply::gotError() { - loop->exit(returnCode = Failure); + if (loop) + loop->exit(returnCode = Failure); disconnect(QObject::sender(), SIGNAL(finished()), this, 0); } @@ -4764,11 +4766,13 @@ void tst_QNetworkReply::ioPostToHttpNoBufferFlag() } #ifndef QT_NO_SSL -class SslServer : public QTcpServer { +class SslServer : public QTcpServer +{ Q_OBJECT public: SslServer() : socket(0), m_ssl(true) {} - void incomingConnection(qintptr socketDescriptor) { + void incomingConnection(qintptr socketDescriptor) + { QSslSocket *serverSocket = new QSslSocket; serverSocket->setParent(this); @@ -4778,16 +4782,9 @@ public: emit newPlainConnection(serverSocket); return; } - QString testDataDir = QFileInfo(QFINDTESTDATA("rfc3252.txt")).absolutePath(); - if (testDataDir.isEmpty()) - testDataDir = QCoreApplication::applicationDirPath(); - connect(serverSocket, SIGNAL(encrypted()), this, SLOT(encryptedSlot())); - serverSocket->setProtocol(QSsl::AnyProtocol); connect(serverSocket, SIGNAL(sslErrors(QList<QSslError>)), serverSocket, SLOT(ignoreSslErrors())); - serverSocket->setLocalCertificate(testDataDir + "/certs/server.pem"); - serverSocket->setPrivateKey(testDataDir + "/certs/server.key"); - serverSocket->startServerEncryption(); + setupSslServer(serverSocket); } else { delete serverSocket; } @@ -4796,11 +4793,13 @@ signals: void newEncryptedConnection(QSslSocket *s); void newPlainConnection(QSslSocket *s); public slots: - void encryptedSlot() { + void encryptedSlot() + { socket = (QSslSocket*) sender(); emit newEncryptedConnection(socket); } - void readyReadSlot() { + void readyReadSlot() + { // for the incoming sockets, not the server socket //qDebug() << static_cast<QSslSocket*>(sender())->bytesAvailable() << static_cast<QSslSocket*>(sender())->encryptedBytesAvailable(); } @@ -4846,7 +4845,7 @@ void tst_QNetworkReply::ioPostToHttpsUploadProgress() disconnect(&server, SIGNAL(newEncryptedConnection(QSslSocket*)), &QTestEventLoop::instance(), SLOT(exitLoop())); - incomingSocket->setReadBufferSize(1*1024); + incomingSocket->setReadBufferSize(1024); // some progress should have been made QTRY_VERIFY(!spy.isEmpty()); QList<QVariant> args = spy.last(); @@ -4950,7 +4949,7 @@ void tst_QNetworkReply::ioGetFromBuiltinHttp() QCOMPARE(reply->header(QNetworkRequest::ContentLengthHeader).toLongLong(), (qint64)testData.size()); if (reader.data.size() < testData.size()) { // oops? - QCOMPARE(reader.data, testData.mid(0, reader.data.size())); + QCOMPARE(reader.data, testData.left(reader.data.size())); qDebug() << "The data is incomplete, the last" << testData.size() - reader.data.size() << "bytes are missing"; } QCOMPARE(reader.data.size(), testData.size()); @@ -4997,7 +4996,7 @@ void tst_QNetworkReply::ioPostToHttpUploadProgress() QVERIFY(incomingSocket); disconnect(&server, SIGNAL(newConnection()), &QTestEventLoop::instance(), SLOT(exitLoop())); - incomingSocket->setReadBufferSize(1*1024); + incomingSocket->setReadBufferSize(1024); QTestEventLoop::instance().enterLoop(5); // some progress should have been made QVERIFY(!spy.isEmpty()); @@ -5699,12 +5698,14 @@ void tst_QNetworkReply::httpProxyCommands() QCOMPARE(uaheader, QByteArray("User-Agent: QNetworkReplyAutoTest/1.0")); } -class ProxyChangeHelper : public QObject { +class ProxyChangeHelper : public QObject +{ Q_OBJECT public: ProxyChangeHelper() : QObject(), signalCount(0) {}; public slots: - void finishedSlot() { + void finishedSlot() + { signalCount++; if (signalCount == 2) QMetaObject::invokeMethod(&QTestEventLoop::instance(), "exitLoop", Qt::QueuedConnection); @@ -5950,7 +5951,8 @@ void tst_QNetworkReply::httpReUsingConnectionSequential() reply2->deleteLater(); } -class HttpReUsingConnectionFromFinishedSlot : public QObject { +class HttpReUsingConnectionFromFinishedSlot : public QObject +{ Q_OBJECT public: QNetworkReply* reply1; @@ -5958,7 +5960,8 @@ public: QUrl url; QNetworkAccessManager manager; public slots: - void finishedSlot() { + void finishedSlot() + { QVERIFY(!reply1->error()); QFETCH(bool, doDeleteLater); @@ -6006,7 +6009,8 @@ void tst_QNetworkReply::httpReUsingConnectionFromFinishedSlot() QCOMPARE(server.totalConnections, 1); } -class HttpRecursiveCreationHelper : public QObject { +class HttpRecursiveCreationHelper : public QObject +{ Q_OBJECT public: @@ -6022,7 +6026,8 @@ public: int requestsStartedCount_readyRead; int requestsFinishedCount; public slots: - void finishedSlot() { + void finishedSlot() + { requestsFinishedCount++; QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); @@ -6041,7 +6046,8 @@ public slots: reply->deleteLater(); } - void readyReadSlot() { + void readyReadSlot() + { QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); QVERIFY(!reply->error()); @@ -6050,7 +6056,8 @@ public slots: requestsStartedCount_readyRead++; } } - void startOne() { + void startOne() + { QUrl url = "http://" + QtNetworkSettings::serverName() + "/qtest/fluke.gif"; QNetworkRequest request(url); QNetworkReply *reply = manager.get(request); @@ -6419,7 +6426,8 @@ void tst_QNetworkReply::getFromHttpIntoBuffer() } // FIXME we really need to consolidate all those server implementations -class GetFromHttpIntoBuffer2Server : QObject { +class GetFromHttpIntoBuffer2Server : QObject +{ Q_OBJECT qint64 dataSize; qint64 dataSent; @@ -6429,26 +6437,28 @@ class GetFromHttpIntoBuffer2Server : QObject { bool chunkedEncoding; public: - GetFromHttpIntoBuffer2Server (qint64 ds, bool sscl, bool ce) : dataSize(ds), dataSent(0), - client(0), serverSendsContentLength(sscl), chunkedEncoding(ce) { + GetFromHttpIntoBuffer2Server (qint64 ds, bool sscl, bool ce) + : dataSize(ds), dataSent(0), client(0), + serverSendsContentLength(sscl), chunkedEncoding(ce) + { server.listen(); connect(&server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot())); } - int serverPort() { - return server.serverPort(); - } + int serverPort() { return server.serverPort(); } public slots: - void newConnectionSlot() { + void newConnectionSlot() + { client = server.nextPendingConnection(); client->setParent(this); connect(client, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); connect(client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot(qint64))); } - void readyReadSlot() { + void readyReadSlot() + { client->readAll(); client->write("HTTP/1.0 200 OK\n"); if (serverSendsContentLength) @@ -6458,7 +6468,8 @@ public slots: client->write("Connection: close\n\n"); } - void bytesWrittenSlot(qint64 amount) { + void bytesWrittenSlot(qint64 amount) + { Q_UNUSED(amount); if (dataSent == dataSize && client) { // close eventually @@ -6492,7 +6503,8 @@ public slots: } }; -class GetFromHttpIntoBuffer2Client : QObject { +class GetFromHttpIntoBuffer2Client : QObject +{ Q_OBJECT private: bool useDownloadBuffer; @@ -6509,7 +6521,8 @@ public: } public slots: - void metaDataChangedSlot() { + void metaDataChangedSlot() + { if (useDownloadBuffer) { QSharedPointer<char> sharedPointer = qvariant_cast<QSharedPointer<char> >(reply->attribute(QNetworkRequest::DownloadBufferAttribute)); QVERIFY(!sharedPointer.isNull()); // It will be 0 if it failed @@ -6519,7 +6532,8 @@ public: QVERIFY(bytesAvailableList.isEmpty()); } - void readyReadSlot() { + void readyReadSlot() + { QVERIFY(!reply->isFinished()); qint64 bytesAvailable = reply->bytesAvailable(); @@ -6541,7 +6555,8 @@ public: // Add bytesAvailable to a list an parse } - void finishedSlot() { + void finishedSlot() + { // We should have already received all readyRead QVERIFY(!bytesAvailableList.isEmpty()); QCOMPARE(bytesAvailableList.last(), uploadSize); @@ -6947,17 +6962,17 @@ void tst_QNetworkReply::authenticationWithDifferentRealm() } #endif // !QT_NO_NETWORKPROXY -class QtBug13431Helper : public QObject { +class QtBug13431Helper : public QObject +{ Q_OBJECT public: QNetworkReply* m_reply; QTimer m_dlTimer; public slots: - void replyFinished(QNetworkReply*) { - QTestEventLoop::instance().exitLoop(); - } + void replyFinished(QNetworkReply*) { QTestEventLoop::instance().exitLoop(); } - void onReadAndReschedule() { + void onReadAndReschedule() + { const qint64 bytesReceived = m_reply->bytesAvailable(); if (bytesReceived && m_reply->readBufferSize()) { QByteArray data = m_reply->read(bytesReceived); @@ -7105,7 +7120,8 @@ void tst_QNetworkReply::qtbug22660gzipNoContentLengthEmptyContent() QCOMPARE(reply->readAll(), QByteArray()); } -class QtBug27161Helper : public QObject { +class QtBug27161Helper : public QObject +{ Q_OBJECT public: QtBug27161Helper(MiniHttpServer & server, const QByteArray & data): @@ -7115,16 +7131,19 @@ public: connect(&m_server, SIGNAL(newConnection()), this, SLOT(newConnectionSlot())); } public slots: - void newConnectionSlot(){ + void newConnectionSlot() + { connect(m_server.client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot())); } - void bytesWrittenSlot(){ + void bytesWrittenSlot() + { disconnect(m_server.client, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWrittenSlot())); m_Timer.singleShot(100, this, SLOT(timeoutSlot())); } - void timeoutSlot(){ + void timeoutSlot() + { m_server.doClose = true; // we need to emulate the bytesWrittenSlot call if the data is empty. if (m_data.size() == 0) @@ -7553,10 +7572,12 @@ void tst_QNetworkReply::httpUserAgent() void tst_QNetworkReply::synchronousAuthenticationCache() { - class MiniAuthServer : public MiniHttpServer { + class MiniAuthServer : public MiniHttpServer + { public: - MiniAuthServer(QThread *thread) : MiniHttpServer(QByteArray(), false, thread) {}; - virtual void reply() { + MiniAuthServer(QThread *thread) : MiniHttpServer(QByteArray(), false, thread) {} + virtual void reply() + { dataToTransmit = "HTTP/1.0 401 Unauthorized\r\n" @@ -7968,7 +7989,8 @@ public: qint64 bandwidthQuota; QTimer timer; - RateLimitedUploadDevice(QByteArray d) : QIODevice(),data(d),read(0),bandwidthQuota(0) { + RateLimitedUploadDevice(QByteArray d) : QIODevice(),data(d),read(0),bandwidthQuota(0) + { buffer.setData(data); buffer.open(QIODevice::ReadOnly); timer.setInterval(200); @@ -7976,12 +7998,14 @@ public: timer.start(); } - virtual qint64 writeData(const char* , qint64 ) { + virtual qint64 writeData(const char* , qint64 ) + { Q_ASSERT(false); return 0; } - virtual qint64 readData(char* data, qint64 maxlen) { + virtual qint64 readData(char* data, qint64 maxlen) + { //qDebug() << Q_FUNC_INFO << maxlen << bandwidthQuota; maxlen = qMin(maxlen, buffer.bytesAvailable()); maxlen = qMin(maxlen, bandwidthQuota); @@ -7998,24 +8022,17 @@ public: //qDebug() << Q_FUNC_INFO << maxlen << bandwidthQuota << read << ret << buffer.bytesAvailable(); return ret; } - virtual bool atEnd() const { - return buffer.atEnd(); - } - virtual qint64 size() const{ - return data.length(); - } + virtual bool atEnd() const { return buffer.atEnd(); } + virtual qint64 size() const { return data.length(); } qint64 bytesAvailable() const { return buffer.bytesAvailable() + QIODevice::bytesAvailable(); } - virtual bool isSequential() const{ // random access, we can seek - return false; - } - virtual bool seek ( qint64 pos ) { - return buffer.seek(pos); - } + virtual bool isSequential() const { return false; } // random access, we can seek + virtual bool seek (qint64 pos) { return buffer.seek(pos); } protected slots: - void timeoutSlot() { + void timeoutSlot() + { //qDebug() << Q_FUNC_INFO; bandwidthQuota = 8*1024; // fill quota emit readyRead(); @@ -8205,9 +8222,7 @@ signals: void corruptFileUploadReceived(); public slots: - void closeDelayed() { - m_socket->close(); - } + void closeDelayed() { m_socket->close(); } void readyReadSlot() { @@ -8232,17 +8247,18 @@ public slots: // We had received some data but it is corrupt! qDebug() << "CORRUPT" << m_receivedData.count(); - // Use this to track down the pattern of the corruption and conclude the source -// QFile a("/tmp/corrupt"); -// a.open(QIODevice::WriteOnly); -// a.write(m_receivedData); -// a.close(); +#if 0 // Use this to track down the pattern of the corruption and conclude the source + QFile a("/tmp/corrupt"); + a.open(QIODevice::WriteOnly); + a.write(m_receivedData); + a.close(); -// QFile b("/tmp/correct"); -// b.open(QIODevice::WriteOnly); -// b.write(m_expectedData); -// b.close(); + QFile b("/tmp/correct"); + b.open(QIODevice::WriteOnly); + b.write(m_expectedData); + b.close(); //exit(1); +#endif emit corruptFileUploadReceived(); } else { emit correctFileUploadReceived(); @@ -8259,26 +8275,26 @@ public: int m_repliesFinished; int m_expectedReplies; QByteArray m_expectedData; - PutWithServerClosingConnectionImmediatelyServer() : SslServer(), m_correctUploads(0), m_corruptUploads(0), m_repliesFinished(0), m_expectedReplies(0) + PutWithServerClosingConnectionImmediatelyServer() + : SslServer(), m_correctUploads(0), m_corruptUploads(0), + m_repliesFinished(0), m_expectedReplies(0) { QObject::connect(this, SIGNAL(newEncryptedConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*))); QObject::connect(this, SIGNAL(newPlainConnection(QSslSocket*)), this, SLOT(createHandlerForConnection(QSslSocket*))); } public slots: - void createHandlerForConnection(QSslSocket* s) { + void createHandlerForConnection(QSslSocket* s) + { PutWithServerClosingConnectionImmediatelyHandler *handler = new PutWithServerClosingConnectionImmediatelyHandler(s, m_expectedData); handler->setParent(this); QObject::connect(handler, SIGNAL(correctFileUploadReceived()), this, SLOT(increaseCorrect())); QObject::connect(handler, SIGNAL(corruptFileUploadReceived()), this, SLOT(increaseCorrupt())); } - void increaseCorrect() { - m_correctUploads++; - } - void increaseCorrupt() { - m_corruptUploads++; - } - void replyFinished() { + void increaseCorrect() { m_correctUploads++; } + void increaseCorrupt() { m_corruptUploads++; } + void replyFinished() + { m_repliesFinished++; if (m_repliesFinished == m_expectedReplies) { QTestEventLoop::instance().exitLoop(); diff --git a/tests/auto/other/atwrapper/.gitignore b/tests/auto/other/atwrapper/.gitignore deleted file mode 100644 index 162ad53af6..0000000000 --- a/tests/auto/other/atwrapper/.gitignore +++ /dev/null @@ -1 +0,0 @@ -tst_atwrapper diff --git a/tests/auto/other/atwrapper/TODO b/tests/auto/other/atwrapper/TODO deleted file mode 100644 index 23a70c3c9e..0000000000 --- a/tests/auto/other/atwrapper/TODO +++ /dev/null @@ -1,17 +0,0 @@ -* Get rid of "Keep baseline" on test failure page (Lars) !! DONE !! -* Make to autotest (Simon) !! DONE !! -* Add visual diff (Everyone ;)) !! DONE !! -* Add flicker (Simon/Jesper) !! DONE !! -* Add third image -- base-baseline (Lars) !! DONE !! -* Add "view baselines" gallery, including the "base base line" (Lars) !! DONE !! -* Add PS printer driver engine test thingy (Eskil) !! DONE !! -* Add platform by platform comparison perl script. (Morton) -* Fix the QDateTime.fromString() weirdness on win32 in xmldata.cpp (Jesper) -* Have one result per page view (Lars) !! DONE !! -* Have "platform - hostname" on test overview (Lars) !! DONE !! -* Have the links on the overview page only show failures for that host.(All)!! DONE !! -* "onion skin" diff. (Jesper) -* Promote all to baseline -* Switch all to flicker/onion/whatever -* Add javascript confirmation for "make baseline" -* Make "single view" more stable diff --git a/tests/auto/other/atwrapper/atWrapper.cpp b/tests/auto/other/atwrapper/atWrapper.cpp deleted file mode 100644 index 8f623538f9..0000000000 --- a/tests/auto/other/atwrapper/atWrapper.cpp +++ /dev/null @@ -1,636 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <atWrapper.h> -#include <datagenerator/datagenerator.h> - -#include <QString> -#include <QHash> -#include <QFile> -#include <QFtp> -#include <QObject> -#include <QHostInfo> -#include <QWidget> -#include <QImage> -#include <QtTest/QSignalSpy> -#include <QLibraryInfo> - -static const char *ArthurDir = "../../arthur"; - -#include <string.h> - -atWrapper::atWrapper() -{ - - // initTests(); - -} - -bool atWrapper::initTests(bool *haveBaseline) -{ - qDebug() << "Running test on buildkey:" << QLibraryInfo::buildKey() << " qt version:" << qVersion(); - - qDebug( "Initializing tests..." ); - - if (!loadConfig( QHostInfo::localHostName().split( "." ).first() + ".ini" )) - return false; - - //Reset the FTP environment where the results are stored - *haveBaseline = setupFTP(); - - // Retrieve the latest test result baseline from the FTP server. - downloadBaseline(); - return true; -} - -void atWrapper::downloadBaseline() -{ - - qDebug() << "Now downloading baseline..."; - - QFtp ftp; - - QObject::connect( &ftp, SIGNAL(listInfo(QUrlInfo)), this, SLOT(ftpMgetAddToList(QUrlInfo)) ); - - //Making sure that the needed local directories exist. - - QHashIterator<QString, QString> j(enginesToTest); - - while ( j.hasNext() ) - { - j.next(); - - QDir dir( output ); - - if ( !dir.cd( j.key() + ".baseline" ) ) - dir.mkdir( j.key() + ".baseline" ); - - } - - //FTP to the host specified in the config file, and retrieve the test result baseline. - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - - ftp.cd( ftpBaseDir ); - - QHashIterator<QString, QString> i(enginesToTest); - while ( i.hasNext() ) - { - i.next(); - mgetDirList.clear(); - mgetDirList << i.key() + ".baseline"; - ftp.cd( i.key() + ".baseline" ); - ftp.list(); - ftp.cd( ".." ); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); - - ftpMgetDone( true ); - } - - ftp.close(); - ftp.close(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); - -} - -void atWrapper::ftpMgetAddToList( const QUrlInfo &urlInfo ) -{ - //Simply adding to the list of files to download. - mgetDirList << urlInfo.name(); - -} - -void atWrapper::ftpMgetDone( bool error) -{ - Q_UNUSED( error ); - - //Downloading the files listed in mgetDirList... - QFtp ftp; - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - - QFile* file; - - if ( mgetDirList.size() > 1 ) - for ( int i = 1; i < mgetDirList.size(); ++i ) - { - file = new QFile( QString( output ) + QLatin1Char('/') + mgetDirList.at( 0 ) - + QLatin1Char('/') + mgetDirList.at( i ) ); - if (file->open(QIODevice::WriteOnly)) { - ftp.get( ftpBaseDir + QLatin1Char('/') + mgetDirList.at( 0 ) + QLatin1Char('/') + mgetDirList.at( i ), file ); - ftp.list(); //Only there to fill up a slot in the pendingCommands queue. - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); - file->close(); - } else { - qDebug() << "Couldn't open file for writing: " << file->fileName(); - } - } - - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); -} - -void atWrapper::uploadFailed( QString dir, QString filename, QByteArray filedata ) -{ - //Upload a failed test case image to the FTP server. - QFtp ftp; - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - - ftp.cd( ftpBaseDir ); - ftp.cd( dir ); - - ftp.put( filedata, filename, QFtp::Binary ); - - ftp.close(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); -} - -// returns false if no baseline exists -bool atWrapper::setupFTP() -{ - qDebug( "Setting up FTP environment" ); - - QString dir = ""; - ftpMkDir( ftpBaseDir ); - - ftpBaseDir += QLatin1Char('/') + QLibraryInfo::buildKey(); - - ftpMkDir( ftpBaseDir ); - - ftpBaseDir += QLatin1Char('/') + QString( qVersion() ); - - ftpMkDir( ftpBaseDir ); - - QHashIterator<QString, QString> i(enginesToTest); - QHashIterator<QString, QString> j(enginesToTest); - - bool haveBaseline = true; - //Creating the baseline directories for each engine - while ( i.hasNext() ) - { - i.next(); - //qDebug() << "Creating dir with key:" << i.key(); - ftpMkDir( ftpBaseDir + QLatin1Char('/') + QString( i.key() ) + ".failed" ); - ftpMkDir( ftpBaseDir + QLatin1Char('/') + QString( i.key() ) + ".diff" ); - if (!ftpMkDir( ftpBaseDir + QLatin1Char('/') + QString( i.key() ) + ".baseline" )) - haveBaseline = false; - } - - - QFtp ftp; - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - - ftp.cd( ftpBaseDir ); - //Deleting previous failed directory and all the files in it, then recreating it. - while ( j.hasNext() ) - { - j.next(); - rmDirList.clear(); - rmDirList << ftpBaseDir + QLatin1Char('/') + j.key() + ".failed/"; - ftpRmDir( j.key() + ".failed" ); - ftp.rmdir( j.key() + ".failed" ); - ftp.mkdir( j.key() + ".failed" ); - ftp.list(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); - - rmDirList.clear(); - rmDirList << ftpBaseDir + QLatin1Char('/') + j.key() + ".diff/"; - ftpRmDir( j.key() + ".diff" ); - ftp.rmdir( j.key() + ".diff" ); - ftp.mkdir( j.key() + ".diff" ); - ftp.list(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); - - } - - ftp.close(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); - - return haveBaseline; -} - -void atWrapper::ftpRmDir( QString dir ) -{ - //Hack to remove a populated directory. (caveat: containing only files and empty dirs, not recursive!) - qDebug() << "Now removing directory: " << dir; - QFtp ftp; - QObject::connect( &ftp, SIGNAL(listInfo(QUrlInfo)), this, SLOT(ftpRmDirAddToList(QUrlInfo)) ); - QObject::connect( &ftp, SIGNAL(done(bool)), this, SLOT(ftpRmDirDone(bool)) ); - - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - - ftp.list( ftpBaseDir + "/" + dir ); - ftp.close(); - ftp.close(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); -} - -void atWrapper::ftpRmDirDone( bool error ) -{ - //Deleting each file in the directory listning, rmDirList. - Q_UNUSED( error ); - - QFtp ftp; - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - - if ( rmDirList.size() > 1 ) - for (int i = 1; i < rmDirList.size(); ++i) - ftp.remove( rmDirList.at(0) + rmDirList.at( i ) ); - - ftp.close(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); -} - -// returns false if the directory already exists -bool atWrapper::ftpMkDir( QString dir ) -{ - //Simply used to avoid QFTP from bailing out and loosing a queue of commands. - // IE: conveniance. - QFtp ftp; - - QSignalSpy commandSpy(&ftp, SIGNAL(commandFinished(int,bool))); - - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - const int command = ftp.mkdir( dir ); - ftp.close(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); - - for (int i = 0; i < commandSpy.count(); ++i) - if (commandSpy.at(i).at(0) == command) - return commandSpy.at(i).at(1).toBool(); - - return false; -} - - -void atWrapper::ftpRmDirAddToList( const QUrlInfo &urlInfo ) -{ - //Just adding the file to the list for deletion - rmDirList << urlInfo.name(); -} - - -bool atWrapper::executeTests() -{ - qDebug("Executing the tests..."); - - QHashIterator<QString, QString> i(enginesToTest); - - DataGenerator generator; - - //Running datagenerator against all the frameworks specified in the config file. - while ( i.hasNext() ) - { - - i.next(); - - qDebug( "Now testing: " + i.key().toLatin1() ); - - char* params[13]; - //./bin/datagenerator -framework data/framework.ini -engine OpenGL -suite 1.1 -output outtest - - - QByteArray eng = i.key().toLatin1(); - QByteArray fwk = framework.toLatin1(); - QByteArray sut = suite.toLatin1(); - QByteArray out = output.toLatin1(); - QByteArray siz = size.toLatin1(); - QByteArray fill = fillColor.toLatin1(); - - params[1] = "-framework"; - params[2] = fwk.data(); - params[3] = "-engine"; - params[4] = eng.data(); - params[5] = "-suite"; - params[6] = sut.data(); - params[7] = "-output"; - params[8] = out.data(); - params[9] = "-size"; - params[10] = siz.data(); - params[11] = "-fill"; - params[12] = fill.data(); - - generator.run( 13, params ); - } - - return true; -} - -void atWrapper::createBaseline() -{ - qDebug( "Now uploading a baseline of only the latest test values" ); - - QHashIterator<QString, QString> i(enginesToTest); - - QDir dir( output ); - QFtp ftp; - ftp.connectToHost( ftpHost ); - ftp.login( ftpUser, ftpPass ); - ftp.cd( ftpBaseDir ); - //Upload all the latest test results to the FTP server's baseline directory. - while ( i.hasNext() ) - { - - i.next(); - dir.cd( i.key() ); - ftp.cd( i.key() + ".baseline" ); - dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); - dir.setNameFilters( QStringList() << "*.png" ); - QFileInfoList list = dir.entryInfoList(); - dir.cd( ".." ); - for (int n = 0; n < list.size(); n++) - { - QFileInfo fileInfo = list.at( n ); - QFile file( QString( output ) + QLatin1Char('/') + i.key() + QLatin1Char('/') + fileInfo.fileName() ); - file.open( QIODevice::ReadOnly ); - QByteArray fileData = file.readAll(); - //qDebug() << "Sending up:" << fileInfo.fileName() << "with file size" << fileData.size(); - file.close(); - ftp.put( fileData, fileInfo.fileName(), QFtp::Binary ); - } - - ftp.cd( ".." ); - } - - ftp.close(); - - while ( ftp.hasPendingCommands() ) - QCoreApplication::instance()->processEvents(); -} - -bool atWrapper::compare() -{ - qDebug( "Now comparing the results to the baseline" ); - - QHashIterator<QString, QString> i(enginesToTest); - - while ( i.hasNext() ) - { - i.next(); - - compareDirs( output , i.key() ); - - } - - return true; -} - -void atWrapper::compareDirs( QString basedir, QString target ) -{ - - QDir dir( basedir ); - - /* The following should be redundant now. - - if ( !dir.cd( target + ".failed" ) ) - dir.mkdir( target + ".failed" ); - else - dir.cdUp(); - - */ - - if ( !dir.cd( target + ".diff" ) ) - dir.mkdir( target + ".diff" ); - else - dir.cdUp(); - - - - //Perform comparisons between the two directories. - - dir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks); - dir.setNameFilters( QStringList() << "*.png" ); - dir.cd( target + ".baseline" ); - QFileInfoList list = dir.entryInfoList(); - - for (int i = 0; i < list.size(); ++i) - { - QFileInfo fileInfo = list.at(i); - diff ( basedir, target, fileInfo.fileName() ); - } -} - -bool atWrapper::diff( QString basedir, QString dir, QString target ) -{ - //Comparing the two specified files, and then uploading them to - //the ftp server if they differ - - basedir += QLatin1Char('/') + dir; - QString one = basedir + ".baseline/" + target; - QString two = basedir + QLatin1Char('/') + target; - - QFile file( one ); - - file.open( QIODevice::ReadOnly ); - QByteArray contentsOfOne = file.readAll(); - file.close(); - - file.setFileName( two ); - - file.open( QIODevice::ReadOnly ); - QByteArray contentsOfTwo = file.readAll(); - file.close(); - - if ( contentsOfTwo.size() == 0 ) - { - qDebug() << "No test result found for baseline: " << one; - file.setFileName( one ); - file.open( QIODevice::ReadOnly ); - file.copy( basedir + ".failed/" + target + "_missing" ); - uploadFailed( dir + ".failed", target + "_missing", contentsOfTwo ); - return false; - } - - - if ( ( memcmp( contentsOfOne, contentsOfTwo, contentsOfOne.size() ) ) == 0 ) - return true; - else - { - qDebug() << "Sorry, the result did not match: " << one; - file.setFileName( two ); - file.open( QIODevice::ReadOnly ); - file.copy( basedir + ".failed/" + target ); - file.close(); - uploadFailed( dir + ".failed", target, contentsOfTwo ); - uploadDiff( basedir, dir, target ); - return false; - } -} - -void atWrapper::uploadDiff( QString basedir, QString dir, QString filename ) -{ - - qDebug() << basedir; - QImage im1( basedir + ".baseline/" + filename ); - QImage im2( basedir + QLatin1Char('/') + filename ); - - QImage im3(im1.size(), QImage::Format_ARGB32); - - im1 = im1.convertToFormat(QImage::Format_ARGB32); - im2 = im2.convertToFormat(QImage::Format_ARGB32); - - for ( int y=0; y<im1.height(); ++y ) - { - uint *s = (uint *) im1.scanLine(y); - uint *d = (uint *) im2.scanLine(y); - uint *w = (uint *) im3.scanLine(y); - - for ( int x=0; x<im1.width(); ++x ) - { - if (*s != *d) - *w = 0xff000000; - else - *w = 0xffffffff; - w++; - s++; - d++; - } - } - - im3.save( basedir + ".diff/" + filename ,"PNG"); - - QFile file( basedir + ".diff/" + filename ); - file.open( QIODevice::ReadOnly ); - QByteArray contents = file.readAll(); - file.close(); - - uploadFailed( dir + ".diff", filename, contents ); - -} - -bool atWrapper::loadConfig( QString path ) -{ - qDebug() << "Loading config file from ... " << path; - configPath = path; - //If there is no config file, don't proceed; - if ( !QFile::exists( path ) ) - { - return false; - } - - - QSettings settings( path, QSettings::IniFormat, this ); - - - //FIXME: Switch to QStringList or something, hash is not needed! - int numEngines = settings.beginReadArray("engines"); - - for ( int i = 0; i < numEngines; ++i ) - { - settings.setArrayIndex(i); - enginesToTest.insert( settings.value( "engine" ).toString(), "Info here please :p" ); - } - - settings.endArray(); - - framework = QString(ArthurDir) + QDir::separator() + settings.value( "framework" ).toString(); - suite = settings.value( "suite" ).toString(); - output = settings.value( "output" ).toString(); - size = settings.value( "size", "480,360" ).toString(); - fillColor = settings.value( "fill", "white" ).toString(); - ftpUser = settings.value( "ftpUser" ).toString(); - ftpPass = settings.value( "ftpPass" ).toString(); - ftpHost = settings.value( "ftpHost" ).toString(); - ftpBaseDir = settings.value( "ftpBaseDir" ).toString(); - - - QDir::current().mkdir( output ); - - output += QLatin1Char('/') + QLibraryInfo::buildKey(); - - QDir::current().mkdir( output ); - - output += QLatin1Char('/') + QString( qVersion() ); - - QDir::current().mkdir( output ); - - - ftpBaseDir += QLatin1Char('/') + QHostInfo::localHostName().split( QLatin1Char('.') ).first(); - - -/* - framework = "data/framework.ini"; - suite = "1.1"; - output = "testresults"; - ftpUser = "anonymous"; - ftpPass = "anonymouspass"; - ftpHost = "kramer.troll.no"; - ftpBaseDir = "/arthurtest"; -*/ - return true; -} - -bool atWrapper::runAutoTests() -{ - //SVG needs this widget... - QWidget dummy; - - bool haveBaseline = false; - - if (!initTests(&haveBaseline)) - return false; - executeTests(); - - if ( !haveBaseline ) - { - qDebug( " First run! Creating baseline..." ); - createBaseline(); - } - else - { - qDebug( " Comparing results..." ); - compare(); - } - return true; -} diff --git a/tests/auto/other/atwrapper/atWrapper.h b/tests/auto/other/atwrapper/atWrapper.h deleted file mode 100644 index dab2b579e3..0000000000 --- a/tests/auto/other/atwrapper/atWrapper.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#ifndef ATWRAPPER_H -#define ATWRAPPER_H - -#include <QHash> -#include <QString> -#include <QUrlInfo> -#include <QColor> - -class atWrapper : public QObject -{ - Q_OBJECT - - public: - atWrapper(); - bool runAutoTests(); - - private: - bool executeTests(); - bool initTests(bool *haveBaseline); - bool compare(); - void createBaseline(); - bool loadConfig( QString ); - void compareDirs( QString, QString ); - bool diff( QString, QString, QString ); - void downloadBaseline(); - void uploadFailed( QString, QString, QByteArray ); - bool ftpMkDir( QString ); - void ftpRmDir( QString ); - bool setupFTP(); - void uploadDiff( QString, QString, QString ); - - QHash<QString, QString> enginesToTest; - QString framework; - QString suite; - QString output; - QString size; - QString ftpUser; - QString ftpPass; - QString ftpHost; - QString ftpBaseDir; - QList<QString> rmDirList; - QList<QString> mgetDirList; - QString configPath; - QString fillColor; - - private slots: - void ftpRmDirAddToList( const QUrlInfo &urlInfo ); - void ftpRmDirDone( bool ); - void ftpMgetAddToList( const QUrlInfo &urlInfo ); - void ftpMgetDone( bool ); -}; - -#endif diff --git a/tests/auto/other/atwrapper/atWrapper.pro b/tests/auto/other/atwrapper/atWrapper.pro deleted file mode 100644 index 1617ae89d1..0000000000 --- a/tests/auto/other/atwrapper/atWrapper.pro +++ /dev/null @@ -1,21 +0,0 @@ -ARTHUR=$$QT_SOURCE_TREE/tests/arthur -COMMON_FOLDER = $$ARTHUR/common -include($$ARTHUR/arthurtester.pri) -INCLUDEPATH += $$ARTHUR -DEFINES += SRCDIR=\\\"$$PWD\\\" - -QT += xml svg network testlib - -qtHaveModule(opengl): QT += opengl - -include($$ARTHUR/datagenerator/datagenerator.pri) - -CONFIG += testcase - -HEADERS += atWrapper.h -SOURCES += atWrapperAutotest.cpp atWrapper.cpp - -TARGET = tst_atwrapper - -#include($$COMMON_FOLDER/common.pri) -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/auto/other/atwrapper/atWrapperAutotest.cpp b/tests/auto/other/atwrapper/atWrapperAutotest.cpp deleted file mode 100644 index ea40cc92b9..0000000000 --- a/tests/auto/other/atwrapper/atWrapperAutotest.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** 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 The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> -#include "atWrapper.h" -#include <QApplication> - -class atWrapperAutotest: public QObject -{ - -Q_OBJECT - -public slots: - void init(); - -private slots: - void runTest(); -}; - -void atWrapperAutotest::init() -{ -#ifndef Q_OS_IRIX - QDir::setCurrent(SRCDIR); -#endif -} - -void atWrapperAutotest::runTest() -{ - - //QApplication app(argc, argv); - - atWrapper wrapper; - if (!wrapper.runAutoTests()) - QSKIP("Arthur not tested on this machine"); - QVERIFY(true); -} - -QTEST_MAIN(atWrapperAutotest) -#include "atWrapperAutotest.moc" diff --git a/tests/auto/other/atwrapper/desert.ini b/tests/auto/other/atwrapper/desert.ini deleted file mode 100644 index 6d8605252d..0000000000 --- a/tests/auto/other/atwrapper/desert.ini +++ /dev/null @@ -1,14 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=1.1 - -[engines] -1\engine=NativeXRender -2\engine=PDF -3\engine=Raster -size=3 diff --git a/tests/auto/other/atwrapper/ephron.ini b/tests/auto/other/atwrapper/ephron.ini deleted file mode 100644 index eeccb3b6ef..0000000000 --- a/tests/auto/other/atwrapper/ephron.ini +++ /dev/null @@ -1,14 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=oxygen -size=256 -fill=transparent - -[engines] -1\engine=Raster -size=1 diff --git a/tests/auto/other/atwrapper/gullgubben.ini b/tests/auto/other/atwrapper/gullgubben.ini deleted file mode 100644 index 3a664dddd5..0000000000 --- a/tests/auto/other/atwrapper/gullgubben.ini +++ /dev/null @@ -1,12 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=1.1 - -[engines] -1\engine=OpenGL -size=1 diff --git a/tests/auto/other/atwrapper/honshu.ini b/tests/auto/other/atwrapper/honshu.ini deleted file mode 100644 index 3b7751a128..0000000000 --- a/tests/auto/other/atwrapper/honshu.ini +++ /dev/null @@ -1,16 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=1.1 - -[engines] -1\engine=NativeWin32 -2\engine=PDF -3\engine=Raster -4\engine=OpenGL -5\engine=WinPrint -size=5 diff --git a/tests/auto/other/atwrapper/kramer.ini b/tests/auto/other/atwrapper/kramer.ini deleted file mode 100644 index 289d8a8b7e..0000000000 --- a/tests/auto/other/atwrapper/kramer.ini +++ /dev/null @@ -1,12 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=1.1 - -[engines] -1\engine=Raster -size=1 diff --git a/tests/auto/other/atwrapper/scruffy.ini b/tests/auto/other/atwrapper/scruffy.ini deleted file mode 100644 index 329f537e6f..0000000000 --- a/tests/auto/other/atwrapper/scruffy.ini +++ /dev/null @@ -1,15 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.nokia.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=1.1 - -[engines] -1\engine=NativeMac -2\engine=PDF -3\engine=Raster -4\engine=OpenGL -size=4 diff --git a/tests/auto/other/atwrapper/spareribs.ini b/tests/auto/other/atwrapper/spareribs.ini deleted file mode 100644 index 78ff9e985f..0000000000 --- a/tests/auto/other/atwrapper/spareribs.ini +++ /dev/null @@ -1,14 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=1.1 - -[engines] -1\engine=NativeWin32 -2\engine=PDF -3\engine=Raster -size=3 diff --git a/tests/auto/other/atwrapper/titan.ini b/tests/auto/other/atwrapper/titan.ini deleted file mode 100644 index 3a0b0dfd31..0000000000 --- a/tests/auto/other/atwrapper/titan.ini +++ /dev/null @@ -1,13 +0,0 @@ -[General] -framework=data/framework.ini -ftpBaseDir=/arthurtest -ftpHost=kramer.troll.no -ftpPass=anonymouspass -ftpUser=anonymous -output=testresults -suite=1.1 - -[engines] -1\engine=NativeXRender -2\engine=OpenGL -size=2 diff --git a/tests/auto/other/other.pro b/tests/auto/other/other.pro index 0babac4b6f..a12f08488d 100644 --- a/tests/auto/other/other.pro +++ b/tests/auto/other/other.pro @@ -2,7 +2,6 @@ TEMPLATE=subdirs QT_FOR_CONFIG += gui-private SUBDIRS=\ - # atwrapper \ # QTBUG-19452 compiler \ gestures \ lancelot \ diff --git a/tests/baselineserver/shared/baselineprotocol.cpp b/tests/baselineserver/shared/baselineprotocol.cpp index 3335ff8ffc..be060ef745 100644 --- a/tests/baselineserver/shared/baselineprotocol.cpp +++ b/tests/baselineserver/shared/baselineprotocol.cpp @@ -90,19 +90,14 @@ PlatformInfo PlatformInfo::localHostInfo() #endif #if defined(Q_OS_LINUX) pi.insert(PI_OSName, QLS("Linux")); - QProcess uname; - uname.start(QLS("uname"), QStringList() << QLS("-r")); - if (uname.waitForFinished(3000)) - pi.insert(PI_OSVersion, QString::fromLocal8Bit(uname.readAllStandardOutput().constData()).simplified()); #elif defined(Q_OS_WIN) pi.insert(PI_OSName, QLS("Windows")); - pi.insert(PI_OSVersion, QString::number(QSysInfo::windowsVersion())); -#elif defined(Q_OS_MAC) - pi.insert(PI_OSName, QLS("MacOS")); - pi.insert(PI_OSVersion, QString::number(QSysInfo::macVersion())); +#elif defined(Q_OS_DARWIN) + pi.insert(PI_OSName, QLS("Darwin")); #else pi.insert(PI_OSName, QLS("Other")); #endif + pi.insert(PI_OSVersion, QSysInfo::kernelVersion()); #ifndef QT_NO_PROCESS QProcess git; diff --git a/tests/manual/qstorageinfo/printvolumes.cpp b/tests/manual/qstorageinfo/printvolumes.cpp index 1b1660b433..31047c2fcd 100644 --- a/tests/manual/qstorageinfo/printvolumes.cpp +++ b/tests/manual/qstorageinfo/printvolumes.cpp @@ -48,11 +48,15 @@ void printVolumes(const QList<QStorageInfo> &volumes, int (*printer)(const char if (info.fileSystemType() != fsAndType) fsAndType += " (" + info.fileSystemType() + ')'; - printf("%-19s R%c ", fsAndType.constData(), info.isReadOnly() ? 'O' : 'W'); + printer("%-19s R%c ", fsAndType.constData(), info.isReadOnly() ? 'O' : 'W'); if (fsAndType.size() > 19) - printf("\n%23s", ""); + printer("\n%23s", ""); - printf("%10llu %10llu %5u ", info.bytesTotal() / 1024, info.bytesFree() / 1024, info.blockSize()); - printf("%-16s %s\n", qPrintable(info.name()), qPrintable(info.rootPath())); + printer("%10llu %10llu %5u ", info.bytesTotal() / 1024, info.bytesFree() / 1024, info.blockSize()); + if (!info.subvolume().isEmpty()) + printer("subvol=%-18s ", qPrintable(info.subvolume())); + else + printer("%-25s ", qPrintable(info.name())); + printer("%s\n", qPrintable(info.rootPath())); } } diff --git a/tests/manual/qsysinfo/main.cpp b/tests/manual/qsysinfo/main.cpp index 5add1e4f74..5b391e5dfd 100644 --- a/tests/manual/qsysinfo/main.cpp +++ b/tests/manual/qsysinfo/main.cpp @@ -27,11 +27,12 @@ ****************************************************************************/ #include <QCoreApplication> +#include <QOperatingSystemVersion> #include <QSysInfo> #include <stdio.h> -// I'm lazy +#if QT_DEPRECATED_SINCE(5, 9) #define CASE_VERSION(v) case QSysInfo::v: return QT_STRINGIFY(v) QByteArray windowsVersionToString(QSysInfo::WinVersion v) @@ -108,6 +109,7 @@ QByteArray macVersionToString(QSysInfo::MacVersion v) } return "MacVersion(Q_MV_OSX(10, " + QByteArray::number(v - 2) + "))"; } +#endif int main(int argc, char *argv[]) { @@ -116,10 +118,12 @@ int main(int argc, char *argv[]) printf("QSysInfo::WordSize = %d\n", QSysInfo::WordSize); printf("QSysInfo::ByteOrder = QSysInfo::%sEndian\n", QSysInfo::ByteOrder == QSysInfo::LittleEndian ? "Little" : "Big"); +#if QT_DEPRECATED_SINCE(5, 9) printf("QSysInfo::WindowsVersion = QSysInfo::%s\n", windowsVersionToString(QSysInfo::WindowsVersion).constData()); printf("QSysInfo::MacintoshVersion = QSysInfo::%s\n", macVersionToString(QSysInfo::MacintoshVersion).constData()); +#endif printf("QSysInfo::buildCpuArchitecture() = %s\n", qPrintable(QSysInfo::buildCpuArchitecture())); printf("QSysInfo::currentCpuArchitecture() = %s\n", qPrintable(QSysInfo::currentCpuArchitecture())); printf("QSysInfo::buildAbi() = %s\n", qPrintable(QSysInfo::buildAbi())); @@ -130,5 +134,12 @@ int main(int argc, char *argv[]) printf("QSysInfo::prettyProductName() = %s\n", qPrintable(QSysInfo::prettyProductName())); printf("QSysInfo::machineHostName() = %s\n", qPrintable(QSysInfo::machineHostName())); + const auto osv = QOperatingSystemVersion::current(); + printf("QOperatingSystemVersion::current() = %s %d.%d.%d\n", + qPrintable(osv.name()), + osv.majorVersion(), + osv.minorVersion(), + osv.microVersion()); + return 0; } diff --git a/tools/configure/Makefile.mingw b/tools/configure/Makefile.mingw index ed13c1a776..f20822f8ba 100644 --- a/tools/configure/Makefile.mingw +++ b/tools/configure/Makefile.mingw @@ -48,6 +48,8 @@ OBJECTS = \ qfsfileengine_win.o \ qfsfileengine_iterator.o \ qiodevice.o \ + qoperatingsystemversion.o \ + qoperatingsystemversion_win.o \ qringbuffer.o \ qdebug.o \ qtextstream.o \ diff --git a/tools/configure/Makefile.win32 b/tools/configure/Makefile.win32 index aae3d57ce3..55453ad0bc 100644 --- a/tools/configure/Makefile.win32 +++ b/tools/configure/Makefile.win32 @@ -37,6 +37,8 @@ OBJECTS = \ qtextcodec.obj \ qglobal.obj \ qnumeric.obj \ + qoperatingsystemversion.obj \ + qoperatingsystemversion_win.obj \ qbuffer.obj \ qdatastream.obj \ qdir.obj \ @@ -114,6 +116,8 @@ qutfcodec.obj: $(CORESRC)\codecs\qutfcodec.cpp $(PCH) qtextcodec.obj: $(CORESRC)\codecs\qtextcodec.cpp $(PCH) qglobal.obj: $(CORESRC)\global\qglobal.cpp $(PCH) qnumeric.obj: $(CORESRC)\global\qnumeric.cpp $(PCH) +qoperatingsystemversion.obj: $(CORESRC)\global\qoperatingsystemversion.cpp $(PCH) +qoperatingsystemversion_win.obj: $(CORESRC)\global\qoperatingsystemversion_win.cpp $(PCH) qbuffer.obj: $(CORESRC)\io\qbuffer.cpp $(PCH) qdatastream.obj: $(CORESRC)\io\qdatastream.cpp $(PCH) qdir.obj: $(CORESRC)\io\qdir.cpp $(PCH) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index bf2d7aa8a7..f678ae61ca 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -895,10 +895,12 @@ void Configure::buildQmake() << " qfilesystemiterator_win.o \\" << endl << " qfsfileengine_win.o \\" << endl << " qlocale_win.o \\" << endl + << " qoperatingsystemversion_win.o \\" << endl << " qsettings_win.o \\" << endl << " qsystemlibrary.o \\" << endl << " registry.o" << endl - << "QTSRCS=\"$(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp\" \\" << endl + << "QTSRCS=\"$(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp\" \\" << endl + << " \"$(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp\" \\" << endl << " \"$(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp\" \\" << endl << " \"$(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp\" \\" << endl << " \"$(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp\" \\" << endl |