summaryrefslogtreecommitdiffstats
path: root/config.profiles/harmattan/patches
diff options
context:
space:
mode:
Diffstat (limited to 'config.profiles/harmattan/patches')
-rw-r--r--config.profiles/harmattan/patches/default_widget_size.diff13
-rw-r--r--config.profiles/harmattan/patches/glshadercache.diff1003
-rw-r--r--config.profiles/harmattan/patches/icu.diff732
-rw-r--r--config.profiles/harmattan/patches/no_read_pro_from_quilt_dir.diff13
-rw-r--r--config.profiles/harmattan/patches/pinch_gesture_sent_twice.diff56
-rw-r--r--config.profiles/harmattan/patches/qgltexturecache.diff23
-rw-r--r--config.profiles/harmattan/patches/qwidget_x11.diff39
-rw-r--r--config.profiles/harmattan/patches/qwidget_x11_mapping.diff17
-rw-r--r--config.profiles/harmattan/patches/runtime-window-geometry-revert.diff12
-rw-r--r--config.profiles/harmattan/patches/series14
-rw-r--r--config.profiles/harmattan/patches/signon_authenticator4.diff230
-rw-r--r--config.profiles/harmattan/patches/temppath.diff28
-rw-r--r--config.profiles/harmattan/patches/tst_qprogressbar.diff19
-rw-r--r--config.profiles/harmattan/patches/tst_qscrollbar.diff12
-rw-r--r--config.profiles/harmattan/patches/tst_qvariant.diff21
15 files changed, 2232 insertions, 0 deletions
diff --git a/config.profiles/harmattan/patches/default_widget_size.diff b/config.profiles/harmattan/patches/default_widget_size.diff
new file mode 100644
index 0000000..1f72881
--- /dev/null
+++ b/config.profiles/harmattan/patches/default_widget_size.diff
@@ -0,0 +1,13 @@
+Index: qt-maemo-qtp/src/gui/kernel/qwidget.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/gui/kernel/qwidget.cpp
++++ qt-maemo-qtp/src/gui/kernel/qwidget.cpp
+@@ -1326,7 +1326,7 @@
+ data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,360,640);
+ }
+ #else
+- data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,640,480);
++ data.crect = parentWidget ? QRect(0,0,100,30) : QRect(0,0,854,480);
+ #endif
+
+ focus_next = focus_prev = q;
diff --git a/config.profiles/harmattan/patches/glshadercache.diff b/config.profiles/harmattan/patches/glshadercache.diff
new file mode 100644
index 0000000..2c6ad9a
--- /dev/null
+++ b/config.profiles/harmattan/patches/glshadercache.diff
@@ -0,0 +1,1003 @@
+Index: qt-maemo-qtp/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
++++ qt-maemo-qtp/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+@@ -42,12 +42,12 @@
+ #include "qglengineshadermanager_p.h"
+ #include "qglengineshadersource_p.h"
+ #include "qpaintengineex_opengl2_p.h"
++#include "qglshadercache_p.h"
+
+ #if defined(QT_DEBUG)
+ #include <QMetaEnum>
+ #endif
+
+-
+ QT_BEGIN_NAMESPACE
+
+ static void qt_shared_shaders_free(void *data)
+@@ -165,62 +165,89 @@
+
+ QGLShader* fragShader;
+ QGLShader* vertexShader;
+- QByteArray source;
++ QByteArray vertexSource;
++ QByteArray fragSource;
+
+ // Compile up the simple shader:
+- source.clear();
+- source.append(qShaderSnippets[MainVertexShader]);
+- source.append(qShaderSnippets[PositionOnlyVertexShader]);
+- vertexShader = new QGLShader(QGLShader::Vertex, context, this);
+- if (!vertexShader->compileSourceCode(source))
+- qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
+-
+- source.clear();
+- source.append(qShaderSnippets[MainFragmentShader]);
+- source.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
+- fragShader = new QGLShader(QGLShader::Fragment, context, this);
+- if (!fragShader->compileSourceCode(source))
+- qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
++ vertexSource.append(qShaderSnippets[MainVertexShader]);
++ vertexSource.append(qShaderSnippets[PositionOnlyVertexShader]);
++
++ fragSource.append(qShaderSnippets[MainFragmentShader]);
++ fragSource.append(qShaderSnippets[ShockingPinkSrcFragmentShader]);
+
+ simpleShaderProg = new QGLShaderProgram(context, this);
+- simpleShaderProg->addShader(vertexShader);
+- simpleShaderProg->addShader(fragShader);
+- simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+- simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
+- simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
+- simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
++
++ CachedShader simpleShaderCache(fragSource, vertexSource);
++
++ bool inCache = simpleShaderCache.load(simpleShaderProg, context);
++
++ if (!inCache) {
++ vertexShader = new QGLShader(QGLShader::Vertex, context, this);
++ if (!vertexShader->compileSourceCode(vertexSource))
++ qWarning("Vertex shader for simpleShaderProg (MainVertexShader & PositionOnlyVertexShader) failed to compile");
++
++ fragShader = new QGLShader(QGLShader::Fragment, context, this);
++ if (!fragShader->compileSourceCode(fragSource))
++ qWarning("Fragment shader for simpleShaderProg (MainFragmentShader & ShockingPinkSrcFragmentShader) failed to compile");
++
++ simpleShaderProg->addShader(vertexShader);
++ simpleShaderProg->addShader(fragShader);
++
++ simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
++ simpleShaderProg->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
++ simpleShaderProg->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
++ simpleShaderProg->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
++ }
++
+ simpleShaderProg->link();
+- if (!simpleShaderProg->isLinked()) {
++
++ if (simpleShaderProg->isLinked()) {
++ if (!inCache)
++ simpleShaderCache.store(simpleShaderProg, context);
++ } else {
+ qCritical() << "Errors linking simple shader:"
+ << simpleShaderProg->log();
+ }
+
+ // Compile the blit shader:
+- source.clear();
+- source.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
+- source.append(qShaderSnippets[UntransformedPositionVertexShader]);
+- vertexShader = new QGLShader(QGLShader::Vertex, context, this);
+- if (!vertexShader->compileSourceCode(source))
+- qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
+-
+- source.clear();
+- source.append(qShaderSnippets[MainFragmentShader]);
+- source.append(qShaderSnippets[ImageSrcFragmentShader]);
+- fragShader = new QGLShader(QGLShader::Fragment, context, this);
+- if (!fragShader->compileSourceCode(source))
+- qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
++ vertexSource.clear();
++ vertexSource.append(qShaderSnippets[MainWithTexCoordsVertexShader]);
++ vertexSource.append(qShaderSnippets[UntransformedPositionVertexShader]);
++
++ fragSource.clear();
++ fragSource.append(qShaderSnippets[MainFragmentShader]);
++ fragSource.append(qShaderSnippets[ImageSrcFragmentShader]);
+
+ blitShaderProg = new QGLShaderProgram(context, this);
+- blitShaderProg->addShader(vertexShader);
+- blitShaderProg->addShader(fragShader);
+- blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+- blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
++
++ CachedShader blitShaderCache(fragSource, vertexSource);
++
++ inCache = blitShaderCache.load(blitShaderProg, context);
++
++ if (!inCache) {
++ vertexShader = new QGLShader(QGLShader::Vertex, context, this);
++ if (!vertexShader->compileSourceCode(vertexSource))
++ qWarning("Vertex shader for blitShaderProg (MainWithTexCoordsVertexShader & UntransformedPositionVertexShader) failed to compile");
++
++ fragShader = new QGLShader(QGLShader::Fragment, context, this);
++ if (!fragShader->compileSourceCode(fragSource))
++ qWarning("Fragment shader for blitShaderProg (MainFragmentShader & ImageSrcFragmentShader) failed to compile");
++
++ blitShaderProg->addShader(vertexShader);
++ blitShaderProg->addShader(fragShader);
++
++ blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
++ blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
++ }
++
+ blitShaderProg->link();
+- if (!blitShaderProg->isLinked()) {
++ if (blitShaderProg->isLinked()) {
++ if (!inCache)
++ blitShaderCache.store(blitShaderProg, context);
++ } else {
+ qCritical() << "Errors linking blit shader:"
+- << simpleShaderProg->log();
++ << blitShaderProg->log();
+ }
+-
+ }
+
+ QGLEngineSharedShaders::~QGLEngineSharedShaders()
+@@ -262,99 +289,108 @@
+ }
+ }
+
+- QGLShader *vertexShader = 0;
+- QGLShader *fragShader = 0;
+- QGLEngineShaderProg *newProg = 0;
+- bool success = false;
++ QScopedPointer<QGLEngineShaderProg> newProg;
+
+ do {
+- QByteArray source;
++ QByteArray fragSource;
+ // Insert the custom stage before the srcPixel shader to work around an ATI driver bug
+ // where you cannot forward declare a function that takes a sampler as argument.
+ if (prog.srcPixelFragShader == CustomImageSrcFragmentShader)
+- source.append(prog.customStageSource);
+- source.append(qShaderSnippets[prog.mainFragShader]);
+- source.append(qShaderSnippets[prog.srcPixelFragShader]);
++ fragSource.append(prog.customStageSource);
++ fragSource.append(qShaderSnippets[prog.mainFragShader]);
++ fragSource.append(qShaderSnippets[prog.srcPixelFragShader]);
+ if (prog.compositionFragShader)
+- source.append(qShaderSnippets[prog.compositionFragShader]);
++ fragSource.append(qShaderSnippets[prog.compositionFragShader]);
+ if (prog.maskFragShader)
+- source.append(qShaderSnippets[prog.maskFragShader]);
+- fragShader = new QGLShader(QGLShader::Fragment, ctxGuard.context(), this);
+- QByteArray description;
++ fragSource.append(qShaderSnippets[prog.maskFragShader]);
++
++ QByteArray vertexSource;
++ vertexSource.append(qShaderSnippets[prog.mainVertexShader]);
++ vertexSource.append(qShaderSnippets[prog.positionVertexShader]);
++
++ QScopedPointer<QGLShaderProgram> shaderProgram(new QGLShaderProgram(ctxGuard.context(), this));
++
++ CachedShader shaderCache(fragSource, vertexSource);
++ bool inCache = shaderCache.load(shaderProgram.data(), ctxGuard.context());
++
++ if (!inCache) {
++
++ QScopedPointer<QGLShader> fragShader(new QGLShader(QGLShader::Fragment, ctxGuard.context(), this));
++ QByteArray description;
+ #if defined(QT_DEBUG)
+- // Name the shader for easier debugging
+- description.append("Fragment shader: main=");
+- description.append(snippetNameStr(prog.mainFragShader));
+- description.append(", srcPixel=");
+- description.append(snippetNameStr(prog.srcPixelFragShader));
+- if (prog.compositionFragShader) {
+- description.append(", composition=");
+- description.append(snippetNameStr(prog.compositionFragShader));
+- }
+- if (prog.maskFragShader) {
+- description.append(", mask=");
+- description.append(snippetNameStr(prog.maskFragShader));
+- }
+- fragShader->setObjectName(QString::fromLatin1(description));
++ // Name the shader for easier debugging
++ description.append("Fragment shader: main=");
++ description.append(snippetNameStr(prog.mainFragShader));
++ description.append(", srcPixel=");
++ description.append(snippetNameStr(prog.srcPixelFragShader));
++ if (prog.compositionFragShader) {
++ description.append(", composition=");
++ description.append(snippetNameStr(prog.compositionFragShader));
++ }
++ if (prog.maskFragShader) {
++ description.append(", mask=");
++ description.append(snippetNameStr(prog.maskFragShader));
++ }
++ fragShader->setObjectName(QString::fromLatin1(description));
+ #endif
+- if (!fragShader->compileSourceCode(source)) {
+- qWarning() << "Warning:" << description << "failed to compile!";
+- break;
+- }
++ if (!fragShader->compileSourceCode(fragSource)) {
++ qWarning() << "Warning:" << description << "failed to compile!";
++ break;
++ }
+
+- source.clear();
+- source.append(qShaderSnippets[prog.mainVertexShader]);
+- source.append(qShaderSnippets[prog.positionVertexShader]);
+- vertexShader = new QGLShader(QGLShader::Vertex, ctxGuard.context(), this);
++ QScopedPointer<QGLShader> vertexShader(new QGLShader(QGLShader::Vertex, ctxGuard.context(), this));
+ #if defined(QT_DEBUG)
+- // Name the shader for easier debugging
+- description.clear();
+- description.append("Vertex shader: main=");
+- description.append(snippetNameStr(prog.mainVertexShader));
+- description.append(", position=");
+- description.append(snippetNameStr(prog.positionVertexShader));
+- vertexShader->setObjectName(QString::fromLatin1(description));
++ // Name the shader for easier debugging
++ description.clear();
++ description.append("Vertex shader: main=");
++ description.append(snippetNameStr(prog.mainVertexShader));
++ description.append(", position=");
++ description.append(snippetNameStr(prog.positionVertexShader));
++ vertexShader->setObjectName(QString::fromLatin1(description));
+ #endif
+- if (!vertexShader->compileSourceCode(source)) {
+- qWarning() << "Warning:" << description << "failed to compile!";
+- break;
+- }
++ if (!vertexShader->compileSourceCode(vertexSource)) {
++ qWarning() << "Warning:" << description << "failed to compile!";
++ break;
++ }
+
+- newProg = new QGLEngineShaderProg(prog);
++ shaderProgram->addShader(vertexShader.take());
++ shaderProgram->addShader(fragShader.take());
+
+- // If the shader program's not found in the cache, create it now.
+- newProg->program = new QGLShaderProgram(ctxGuard.context(), this);
+- newProg->program->addShader(vertexShader);
+- newProg->program->addShader(fragShader);
+-
+- // We have to bind the vertex attribute names before the program is linked:
+- newProg->program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+- if (newProg->useTextureCoords)
+- newProg->program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+- if (newProg->useOpacityAttribute)
+- newProg->program->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
+- if (newProg->usePmvMatrixAttribute) {
+- newProg->program->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
+- newProg->program->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
+- newProg->program->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
++ // We have to bind the vertex attribute names before the program is linked:
++ shaderProgram->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
++ if (prog.useTextureCoords)
++ shaderProgram->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
++ if (prog.useOpacityAttribute)
++ shaderProgram->bindAttributeLocation("opacityArray", QT_OPACITY_ATTR);
++ if (prog.usePmvMatrixAttribute) {
++ shaderProgram->bindAttributeLocation("pmvMatrix1", QT_PMV_MATRIX_1_ATTR);
++ shaderProgram->bindAttributeLocation("pmvMatrix2", QT_PMV_MATRIX_2_ATTR);
++ shaderProgram->bindAttributeLocation("pmvMatrix3", QT_PMV_MATRIX_3_ATTR);
++ }
+ }
+
++ newProg.reset(new QGLEngineShaderProg(prog));
++ newProg->program = shaderProgram.take();
++
+ newProg->program->link();
+- if (!newProg->program->isLinked()) {
++ if (newProg->program->isLinked()) {
++ if (!inCache)
++ shaderCache.store(newProg->program, ctxGuard.context());
++ } else {
+ QLatin1String none("none");
+ QLatin1String br("\n");
+ QString error;
+- error = QLatin1String("Shader program failed to link,")
++ error = QLatin1String("Shader program failed to link,");
+ #if defined(QT_DEBUG)
+- + br
+- + QLatin1String(" Shaders Used:") + br
+- + QLatin1String(" ") + vertexShader->objectName() + QLatin1String(": ") + br
+- + QLatin1String(vertexShader->sourceCode()) + br
+- + QLatin1String(" ") + fragShader->objectName() + QLatin1String(": ") + br
+- + QLatin1String(fragShader->sourceCode()) + br
++ error += QLatin1String("\n Shaders Used:\n");
++ for (int i = 0; i < newProg->program->shaders().count(); ++i) {
++ QGLShader *shader = newProg->program->shaders().at(i);
++ error += QLatin1String(" ") + shader->objectName() + QLatin1String(": \n")
++ + QLatin1String(shader->sourceCode()) + br;
++ }
+ #endif
+- + QLatin1String(" Error Log:\n")
+- + QLatin1String(" ") + newProg->program->log();
++ error += QLatin1String(" Error Log:\n")
++ + QLatin1String(" ") + newProg->program->log();
+ qWarning() << error;
+ break;
+ }
+@@ -376,26 +412,10 @@
+ }
+ }
+
+- cachedPrograms.insert(0, newProg);
+-
+- success = true;
++ cachedPrograms.insert(0, newProg.data());
+ } while (false);
+
+- // Clean up everything if we weren't successful
+- if (!success) {
+- if (newProg) {
+- delete newProg; // Also deletes the QGLShaderProgram which in turn deletes the QGLShaders
+- newProg = 0;
+- }
+- else {
+- if (vertexShader)
+- delete vertexShader;
+- if (fragShader)
+- delete fragShader;
+- }
+- }
+-
+- return newProg;
++ return newProg.take();
+ }
+
+ void QGLEngineSharedShaders::cleanupCustomStage(QGLCustomShaderStage* stage)
+Index: qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_meego_p.h
+===================================================================
+--- /dev/null
++++ qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_meego_p.h
+@@ -0,0 +1,457 @@
++/****************************************************************************
++**
++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++** All rights reserved.
++** Contact: Nokia Corporation (qt-info@nokia.com)
++**
++** This file is part of the QtOpenGL module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** No Commercial Usage
++** This file contains pre-release code and may not be distributed.
++** You may use this file in accordance with the terms and conditions
++** contained in the Technology Preview License Agreement accompanying
++** this package.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** If you have questions regarding the use of this file, please contact
++** Nokia at qt-info@nokia.com.
++**
++**
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++//
++// W A R N I N G
++// -------------
++//
++// This file is not part of the Qt API. It exists purely as an
++// implementation detail. This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++#ifndef QGLSHADERCACHE_MEEGO_P_H
++#define QGLSHADERCACHE_MEEGO_P_H
++
++#include <QtCore/qglobal.h>
++
++#if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2)
++
++#include <QtCore/qcryptographichash.h>
++#include <QtCore/qsharedmemory.h>
++#include <QtCore/qsystemsemaphore.h>
++
++#ifndef QT_BOOTSTRAPPED
++# include <GLES2/gl2ext.h>
++#endif
++#if defined(QT_DEBUG) || defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE)
++# include <syslog.h>
++#endif
++
++QT_BEGIN_HEADER
++
++/*
++ This cache stores internal Qt shader programs in shared memory.
++
++ This header file is ugly on purpose and can only be included once. It is only to be used
++ for the internal shader cache, not as a generic cache for anyone's shaders.
++
++ The cache stores either ShaderCacheMaxEntries shader programs or ShaderCacheDataSize kilobytes
++ of shader programs, whatever limit is reached first.
++
++ The layout of the cache is as outlined in the CachedShaders struct. After some
++ integers, an array of headers is reserved, then comes the space for the actual binaries.
++
++ Shader Programs are identified by the md5sum of their frag and vertex shader source code.
++
++ Shader Programs are never removed. The cache never shrinks or re-shuffles. This is done
++ on purpose to ensure minimum amount of locking, no alignment problems and very few write
++ operations.
++
++ Note: Locking the shader cache could be expensive, because the entire system might hang.
++ That's why the cache is immutable to minimize the time we need to keep it locked.
++
++ Why is it Meego specific?
++
++ First, the size is chosen so that it fits to generic meego usage. Second, on Meego, there's
++ always at least one Qt application active (the launcher), so the cache will never be destroyed.
++ Only when the last Qt app exits, the cache dies, which should only be when someone kills the
++ X11 server. And last but not least it was only tested with Meego's SGX driver.
++
++ There's a small tool in src/opengl/util/meego that dumps the contents of the cache.
++ */
++
++// anonymous namespace, prevent exporting of the private symbols
++namespace
++{
++
++struct CachedShaderHeader
++{
++ /* the index in the data[] member of CachedShaders */
++ int index;
++ /* the size of the binary shader */
++ GLsizei size;
++ /* the format of the binary shader */
++ GLenum format;
++ /* the md5sum of the frag+vertex shaders */
++ char md5Sum[16];
++};
++
++enum
++{
++ /* The maximum amount of shader programs the cache can hold */
++ ShaderCacheMaxEntries = 20
++};
++
++typedef CachedShaderHeader CachedShaderHeaders[ShaderCacheMaxEntries];
++
++enum
++{
++ // ShaderCacheDataSize is 20k minus the other data members of CachedShaders
++ ShaderCacheDataSize = 1024 * ShaderCacheMaxEntries - sizeof(CachedShaderHeaders) - 2 * sizeof(int)
++};
++
++struct CachedShaders
++{
++ /* How much space is still available in the cache */
++ inline int availableSize() const { return ShaderCacheDataSize - dataSize; }
++
++ /* The current amount of cached shaders */
++ int shaderCount;
++
++ /* The current amount (in bytes) of cached data */
++ int dataSize;
++
++ /* The headers describing the shaders */
++ CachedShaderHeaders headers;
++
++ /* The actual binary data of the shader programs */
++ char data[ShaderCacheDataSize];
++};
++
++//#define QT_DEBUG_SHADER_CACHE
++#ifdef QT_DEBUG_SHADER_CACHE
++static QDebug shaderCacheDebug()
++{
++ return QDebug(QtDebugMsg);
++}
++#else
++static inline QNoDebug shaderCacheDebug() { return QNoDebug(); }
++#endif
++
++class ShaderCacheSharedMemory
++{
++public:
++ ShaderCacheSharedMemory()
++ : shm(QLatin1String("qt_gles2_shadercache_" QT_VERSION_STR))
++ {
++ // we need a system semaphore here, since cache creation and initialization must be atomic
++ QSystemSemaphore attachSemaphore(QLatin1String("qt_gles2_shadercache_mutex_" QT_VERSION_STR), 1);
++
++ if (!attachSemaphore.acquire()) {
++ shaderCacheDebug() << "Unable to require shader cache semaphore:" << attachSemaphore.errorString();
++ return;
++ }
++
++ if (shm.attach()) {
++ // success!
++ shaderCacheDebug() << "Attached to shader cache";
++ } else {
++
++ // no cache exists - create and initialize it
++ if (shm.create(sizeof(CachedShaders))) {
++ shaderCacheDebug() << "Created new shader cache";
++ initializeCache();
++ } else {
++ shaderCacheDebug() << "Unable to create shader cache:" << shm.errorString();
++ }
++ }
++
++ attachSemaphore.release();
++ }
++
++ inline bool isAttached() const { return shm.isAttached(); }
++
++ inline bool lock() { return shm.lock(); }
++ inline bool unlock() { return shm.unlock(); }
++ inline void *data() { return shm.data(); }
++ inline QString errorString() { return shm.errorString(); }
++
++ ~ShaderCacheSharedMemory()
++ {
++ if (!shm.detach())
++ shaderCacheDebug() << "Unable to detach shader cache" << shm.errorString();
++ }
++
++private:
++ void initializeCache()
++ {
++ // no need to lock the shared memory since we're already protected by the
++ // attach system semaphore.
++
++ void *data = shm.data();
++ Q_ASSERT(data);
++
++ memset(data, 0, sizeof(CachedShaders));
++ }
++
++ QSharedMemory shm;
++};
++
++class ShaderCacheLocker
++{
++public:
++ inline ShaderCacheLocker(ShaderCacheSharedMemory *cache)
++ : shm(cache->lock() ? cache : (ShaderCacheSharedMemory *)0)
++ {
++ if (!shm)
++ shaderCacheDebug() << "Unable to lock shader cache" << cache->errorString();
++ }
++
++ inline bool isLocked() const { return shm; }
++
++ inline ~ShaderCacheLocker()
++ {
++ if (!shm)
++ return;
++ if (!shm->unlock())
++ shaderCacheDebug() << "Unable to unlock shader cache" << shm->errorString();
++ }
++
++private:
++ ShaderCacheSharedMemory *shm;
++};
++
++#ifdef QT_BOOTSTRAPPED
++} // end namespace
++#else
++
++static void traceCacheOverflow(const char *message)
++{
++#if defined(QT_DEBUG) || defined (QT_MEEGO_EXPERIMENTAL_SHADERCACHE_TRACE)
++ openlog(qPrintable(QCoreApplication::applicationName()), LOG_PID | LOG_ODELAY, LOG_USER);
++ syslog(LOG_DEBUG, message);
++ closelog();
++#endif
++ shaderCacheDebug() << message;
++}
++
++Q_GLOBAL_STATIC(ShaderCacheSharedMemory, shaderCacheSharedMemory)
++
++/*
++ Finds the index of the shader program identified by md5Sum in the cache.
++ Note: Does NOT lock the cache for reading, the cache must already be locked!
++
++ Returns -1 when no shader was found.
++ */
++static int qt_cache_index_unlocked(const QByteArray &md5Sum, CachedShaders *cache)
++{
++ for (int i = 0; i < cache->shaderCount; ++i) {
++ if (qstrncmp(md5Sum.constData(), cache->headers[i].md5Sum, 16) == 0) {
++ return i;
++ }
++ }
++ return -1;
++}
++
++/* Returns the index of the shader identified by md5Sum */
++static int qt_cache_index(const QByteArray &md5Sum)
++{
++ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
++ if (!shm || !shm->isAttached())
++ return false;
++
++ Q_ASSERT(md5Sum.length() == 16);
++
++ ShaderCacheLocker locker(shm);
++ if (!locker.isLocked())
++ return false;
++
++ void *data = shm->data();
++ Q_ASSERT(data);
++
++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
++
++ return qt_cache_index_unlocked(md5Sum, cache);
++}
++
++/* Loads the cached shader at index \a shaderIndex into \a program
++ * Note: Since the cache is immutable, this operation doesn't lock the shared memory.
++ */
++static bool qt_cached_shader(QGLShaderProgram *program, const QGLContext *ctx, int shaderIndex)
++{
++ Q_ASSERT(shaderIndex >= 0 && shaderIndex <= ShaderCacheMaxEntries);
++ Q_ASSERT(program);
++
++ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
++ if (!shm || !shm->isAttached())
++ return false;
++
++ void *data = shm->data();
++ Q_ASSERT(data);
++
++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
++
++ shaderCacheDebug() << "fetching cached shader at index" << shaderIndex
++ << "dataIndex" << cache->headers[shaderIndex].index
++ << "size" << cache->headers[shaderIndex].size
++ << "format" << cache->headers[shaderIndex].format;
++
++ // call program->programId first, since that resolves the glProgramBinaryOES symbol
++ GLuint programId = program->programId();
++ glProgramBinaryOES(programId, cache->headers[shaderIndex].format,
++ cache->data + cache->headers[shaderIndex].index,
++ cache->headers[shaderIndex].size);
++
++ return true;
++}
++
++/* Stores the shader program in the cache. Returns false if there's an error with the cache, or
++ if the cache is too small to hold the shader. */
++static bool qt_cache_shader(const QGLShaderProgram *shader, const QGLContext *ctx, const QByteArray &md5Sum)
++{
++ ShaderCacheSharedMemory *shm = shaderCacheSharedMemory();
++ if (!shm || !shm->isAttached())
++ return false;
++
++ void *data = shm->data();
++ Q_ASSERT(data);
++
++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
++
++ ShaderCacheLocker locker(shm);
++ if (!locker.isLocked())
++ return false;
++
++ int cacheIdx = cache->shaderCount;
++ if (cacheIdx >= ShaderCacheMaxEntries) {
++ traceCacheOverflow("Qt OpenGL shader cache index overflow!");
++ return false;
++ }
++
++ // now that we have the lock on the shared memory, make sure no one
++ // inserted the shader already while we were unlocked
++ if (qt_cache_index_unlocked(md5Sum, cache) != -1)
++ return true; // already cached
++
++ shaderCacheDebug() << "Caching shader at index" << cacheIdx;
++
++ GLint binaryLength = 0;
++ glGetProgramiv(shader->programId(), GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength);
++
++ if (!binaryLength) {
++ shaderCacheDebug() << "Unable to determine binary shader size!";
++ return false;
++ }
++
++ if (binaryLength > cache->availableSize()) {
++ traceCacheOverflow("Qt OpenGL shader cache data overflow!");
++ return false;
++ }
++
++ GLsizei size = 0;
++ GLenum format = 0;
++ glGetProgramBinaryOES(shader->programId(), binaryLength, &size, &format,
++ cache->data + cache->dataSize);
++
++ if (!size) {
++ shaderCacheDebug() << "Unable to get binary shader!";
++ return false;
++ }
++
++ cache->headers[cacheIdx].index = cache->dataSize;
++ cache->dataSize += binaryLength;
++ ++cache->shaderCount;
++ cache->headers[cacheIdx].size = binaryLength;
++ cache->headers[cacheIdx].format = format;
++
++ memcpy(cache->headers[cacheIdx].md5Sum, md5Sum.constData(), 16);
++
++ shaderCacheDebug() << "cached shader size" << size
++ << "format" << format
++ << "binarySize" << binaryLength
++ << "cache index" << cacheIdx
++ << "data index" << cache->headers[cacheIdx].index;
++
++ return true;
++}
++
++} // namespace
++
++QT_BEGIN_NAMESPACE
++
++QT_MODULE(OpenGL)
++
++class CachedShader
++{
++public:
++ CachedShader(const QByteArray &fragSource, const QByteArray &vertexSource)
++ : cacheIdx(-1)
++ {
++ QCryptographicHash md5Hash(QCryptographicHash::Md5);
++
++ md5Hash.addData(fragSource);
++ md5Hash.addData(vertexSource);
++
++ md5Sum = md5Hash.result();
++ }
++
++ bool isCached()
++ {
++ return cacheIndex() != -1;
++ }
++
++ int cacheIndex()
++ {
++ if (cacheIdx != -1)
++ return cacheIdx;
++ cacheIdx = qt_cache_index(md5Sum);
++ return cacheIdx;
++ }
++
++ bool load(QGLShaderProgram *program, const QGLContext *ctx)
++ {
++ if (cacheIndex() == -1)
++ return false;
++ return qt_cached_shader(program, ctx, cacheIdx);
++ }
++
++ bool store(QGLShaderProgram *program, const QGLContext *ctx)
++ {
++ return qt_cache_shader(program, ctx, md5Sum);
++ }
++
++private:
++ QByteArray md5Sum;
++ int cacheIdx;
++};
++
++
++QT_END_NAMESPACE
++
++#endif
++
++QT_END_HEADER
++
++#endif
++#endif
+Index: qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_p.h
+===================================================================
+--- /dev/null
++++ qt-maemo-qtp/src/opengl/gl2paintengineex/qglshadercache_p.h
+@@ -0,0 +1,98 @@
++/****************************************************************************
++**
++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++** All rights reserved.
++** Contact: Nokia Corporation (qt-info@nokia.com)
++**
++** This file is part of the QtOpenGL module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** No Commercial Usage
++** This file contains pre-release code and may not be distributed.
++** You may use this file in accordance with the terms and conditions
++** contained in the Technology Preview License Agreement accompanying
++** this package.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** If you have questions regarding the use of this file, please contact
++** Nokia at qt-info@nokia.com.
++**
++**
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++//
++// W A R N I N G
++// -------------
++//
++// This file is not part of the Qt API. It exists purely as an
++// implementation detail. This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++#ifndef QGLSHADERCACHE_P_H
++#define QGLSHADERCACHE_P_H
++
++#include <QtCore/qglobal.h>
++
++#if defined(QT_MEEGO_EXPERIMENTAL_SHADERCACHE) && defined(QT_OPENGL_ES_2)
++# include "qglshadercache_meego_p.h"
++#else
++
++QT_BEGIN_HEADER
++
++QT_BEGIN_NAMESPACE
++
++QT_MODULE(OpenGL)
++
++class QGLShaderProgram;
++class QGLContext;
++
++class CachedShader
++{
++public:
++ inline CachedShader(const QByteArray &, const QByteArray &)
++ {}
++
++ inline bool isCached()
++ {
++ return false;
++ }
++
++ inline bool load(QGLShaderProgram *, const QGLContext *)
++ {
++ return false;
++ }
++
++ inline bool store(QGLShaderProgram *, const QGLContext *)
++ {
++ return false;
++ }
++};
++
++QT_END_NAMESPACE
++
++QT_END_HEADER
++
++#endif
++#endif
+Index: qt-maemo-qtp/src/opengl/opengl.pro
+===================================================================
+--- qt-maemo-qtp.orig/src/opengl/opengl.pro
++++ qt-maemo-qtp/src/opengl/opengl.pro
+@@ -58,7 +58,9 @@
+ gl2paintengineex/qglcustomshaderstage_p.h \
+ gl2paintengineex/qtriangulatingstroker_p.h \
+ gl2paintengineex/qtriangulator_p.h \
+- gl2paintengineex/qtextureglyphcache_gl_p.h
++ gl2paintengineex/qtextureglyphcache_gl_p.h \
++ gl2paintengineex/qglshadercache_p.h \
++ gl2paintengineex/qglshadercache_meego_p.h
+
+ SOURCES += qglshaderprogram.cpp \
+ qglpixmapfilter.cpp \
+Index: qt-maemo-qtp/src/opengl/util/meego/main.cpp
+===================================================================
+--- /dev/null
++++ qt-maemo-qtp/src/opengl/util/meego/main.cpp
+@@ -0,0 +1,48 @@
++#include <QtCore/qdebug.h>
++
++#define QT_DEBUG_SHADER_CACHE
++#define QT_MEEGO_EXPERIMENTAL_SHADERCACHE
++#define QT_OPENGL_ES_2
++#define QT_BOOTSTRAPPED
++
++typedef int GLsizei;
++typedef unsigned int GLenum;
++
++#include "../../gl2paintengineex/qglshadercache_meego_p.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++
++int main()
++{
++ ShaderCacheSharedMemory shm;
++
++ if (!shm.isAttached()) {
++ fprintf(stderr, "Unable to attach to shared memory\n");
++ return EXIT_FAILURE;
++ }
++
++ ShaderCacheLocker locker(&shm);
++ if (!locker.isLocked()) {
++ fprintf(stderr, "Unable to lock shared memory\n");
++ return EXIT_FAILURE;
++ }
++
++ void *data = shm.data();
++ Q_ASSERT(data);
++
++ CachedShaders *cache = reinterpret_cast<CachedShaders *>(data);
++
++ for (int i = 0; i < cache->shaderCount; ++i) {
++ printf("Shader %d: %d bytes\n", i, cache->headers[i].size);
++ }
++
++ printf("\nSummary:\n\n"
++ " Amount of cached shaders: %d\n"
++ " Bytes used: %d\n"
++ " Bytes available: %d\n",
++ cache->shaderCount, cache->dataSize, cache->availableSize());
++
++ return EXIT_SUCCESS;
++}
++
+Index: qt-maemo-qtp/src/opengl/util/meego/shader-cache-introspector.pro
+===================================================================
+--- /dev/null
++++ qt-maemo-qtp/src/opengl/util/meego/shader-cache-introspector.pro
+@@ -0,0 +1,7 @@
++TEMPLATE = app
++
++SOURCES += main.cpp
++
++TARGET = shader-cache-introspector
++
++QT = core
diff --git a/config.profiles/harmattan/patches/icu.diff b/config.profiles/harmattan/patches/icu.diff
new file mode 100644
index 0000000..16a17fd
--- /dev/null
+++ b/config.profiles/harmattan/patches/icu.diff
@@ -0,0 +1,732 @@
+diff --git a/configure b/configure
+index 3a748e2..77232dc 100755
+--- a/configure
++++ b/configure
+@@ -779,6 +779,7 @@ CFG_PULSEAUDIO=auto
+ CFG_COREWLAN=auto
+ CFG_ICD=auto
+ CFG_NOPROCESS=no
++CFG_ICU=no
+
+ # initalize variables used for installation
+ QT_INSTALL_PREFIX=
+@@ -940,7 +941,7 @@ while [ "$#" -gt 0 ]; do
+ VAL=no
+ ;;
+ #Qt style yes options
+- -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles)
++ -incremental|-qvfb|-profile|-shared|-static|-sm|-xinerama|-xshape|-xsync|-xinput|-xinput2|-egl|-reduce-exports|-pch|-separate-debug-info|-stl|-freetype|-xcursor|-xfixes|-xrandr|-xrender|-mitshm|-fontconfig|-xkb|-nis|-qdbus|-dbus|-dbus-linked|-glib|-gstreamer|-gtkstyle|-cups|-iconv|-largefile|-h|-help|-v|-verbose|-debug|-release|-fast|-accessibility|-confirm-license|-gnumake|-framework|-qt3support|-debug-and-release|-exceptions|-cocoa|-carbon|-universal|-prefix-install|-silent|-armfpa|-optimized-qmake|-dwarf2|-reduce-relocations|-sse|-openssl|-openssl-linked|-ptmalloc|-xmlpatterns|-phonon|-phonon-backend|-multimedia|-audio-backend|-svg|-declarative|-javascript-jit|-script|-scripttools|-rpath|-force-pkg-config|-s60|-usedeffiles|-icu)
+ VAR=`echo $1 | sed "s,^-\(.*\),\1,"`
+ VAL=yes
+ ;;
+@@ -2242,6 +2243,13 @@ while [ "$#" -gt 0 ]; do
+ QT_CFLAGS_FPU=$VAL
+ fi
+ ;;
++ icu)
++ if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
++ CFG_ICU="$VAL"
++ else
++ UNKNOWN_OPT=yes
++ fi
++ ;;
+ *)
+ UNKNOWN_OPT=yes
+ ;;
+@@ -7040,6 +7048,10 @@ if [ "$CFG_ICD" = "yes" ]; then
+ QT_CONFIG="$QT_CONFIG icd"
+ fi
+
++if [ "$CFG_ICU" = "yes" ]; then
++ QT_CONFIG="$QT_CONFIG icu"
++fi
++
+ #
+ # Some Qt modules are too advanced in C++ for some old compilers
+ # Detect here the platforms where they are known to work.
+diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
+index 7cdc256..11a85d5 100644
+--- a/src/corelib/tools/qchar.cpp
++++ b/src/corelib/tools/qchar.cpp
+@@ -57,6 +57,12 @@
+
+ QT_BEGIN_NAMESPACE
+
++#ifdef QT_USE_ICU
++// from qlocale_icu.cpp
++extern uint qt_u_toUpper(uint c);
++extern uint qt_u_toLower(uint c);
++#endif
++
+ #ifndef QT_NO_CODEC_FOR_C_STRINGS
+ # ifdef QT_NO_TEXTCODEC
+ # define QT_NO_CODEC_FOR_C_STRINGS
+@@ -1076,6 +1082,12 @@ QChar::UnicodeVersion QChar::unicodeVersion(ushort ucs2)
+ */
+ QChar QChar::toLower() const
+ {
++#ifdef QT_USE_ICU
++ uint res = qt_u_toLower(ucs);
++ if (res)
++ return QChar(res);
++ // else fall through
++#endif
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->lowerCaseSpecial)
+ return ucs + p->lowerCaseDiff;
+@@ -1090,6 +1102,12 @@ QChar QChar::toLower() const
+ */
+ uint QChar::toLower(uint ucs4)
+ {
++#ifdef QT_USE_ICU
++ uint res = qt_u_toLower(ucs4);
++ if (res)
++ return res;
++ // else fall through
++#endif
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+@@ -1106,6 +1124,12 @@ uint QChar::toLower(uint ucs4)
+ */
+ ushort QChar::toLower(ushort ucs2)
+ {
++#ifdef QT_USE_ICU
++ uint res = qt_u_toLower(ucs2);
++ if (res)
++ return res & 0xffff;
++ // else fall through
++#endif
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->lowerCaseSpecial)
+ return ucs2 + p->lowerCaseDiff;
+@@ -1118,6 +1142,12 @@ ushort QChar::toLower(ushort ucs2)
+ */
+ QChar QChar::toUpper() const
+ {
++#ifdef QT_USE_ICU
++ uint res = qt_u_toUpper(ucs);
++ if (res)
++ return QChar(res);
++ // else fall through
++#endif
+ const QUnicodeTables::Properties *p = qGetProp(ucs);
+ if (!p->upperCaseSpecial)
+ return ucs + p->upperCaseDiff;
+@@ -1132,6 +1162,12 @@ QChar QChar::toUpper() const
+ */
+ uint QChar::toUpper(uint ucs4)
+ {
++#ifdef QT_USE_ICU
++ uint res = qt_u_toUpper(ucs4);
++ if (res)
++ return res;
++ // else fall through
++#endif
+ if (ucs4 > UNICODE_LAST_CODEPOINT)
+ return ucs4;
+ const QUnicodeTables::Properties *p = qGetProp(ucs4);
+@@ -1148,6 +1184,12 @@ uint QChar::toUpper(uint ucs4)
+ */
+ ushort QChar::toUpper(ushort ucs2)
+ {
++#ifdef QT_USE_ICU
++ uint res = qt_u_toUpper(ucs2);
++ if (res)
++ return res & 0xffff;
++ // else fall through
++#endif
+ const QUnicodeTables::Properties *p = qGetProp(ucs2);
+ if (!p->upperCaseSpecial)
+ return ucs2 + p->upperCaseDiff;
+diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
+index 6515edb..5470048 100644
+--- a/src/corelib/tools/qlocale.cpp
++++ b/src/corelib/tools/qlocale.cpp
+@@ -134,6 +134,10 @@ void qt_symbianUpdateSystemPrivate();
+ void qt_symbianInitSystemLocale();
+ #endif
+
++#ifdef QT_USE_ICU
++extern bool qt_initIcu(const QString &localeName);
++#endif
++
+ /******************************************************************************
+ ** Helpers for accessing Qt locale database
+ */
+@@ -2346,6 +2350,10 @@ void QLocale::setDefault(const QLocale &locale)
+ {
+ default_lp = locale.d();
+ default_number_options = locale.numberOptions();
++
++#ifdef QT_USE_ICU
++ qt_initIcu(locale.name());
++#endif
+ }
+
+ /*!
+diff --git a/src/corelib/tools/qlocale_icu.cpp b/src/corelib/tools/qlocale_icu.cpp
+new file mode 100644
+index 0000000..7fe3801
+--- /dev/null
++++ b/src/corelib/tools/qlocale_icu.cpp
+@@ -0,0 +1,247 @@
++/****************************************************************************
++**
++** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
++** All rights reserved.
++** Contact: Nokia Corporation (qt-info@nokia.com)
++**
++** This file is part of the QtCore module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** No Commercial Usage
++** This file contains pre-release code and may not be distributed.
++** You may use this file in accordance with the terms and conditions
++** contained in the Technology Preview License Agreement accompanying
++** this package.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 2.1 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 2.1 requirements
++** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
++**
++** In addition, as a special exception, Nokia gives you certain additional
++** rights. These rights are described in the Nokia Qt LGPL Exception
++** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
++**
++** If you have questions regarding the use of this file, please contact
++** Nokia at qt-info@nokia.com.
++**
++**
++**
++**
++**
++**
++**
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++#include "qglobal.h"
++#include "qlibrary.h"
++#include "qdebug.h"
++
++#include "unicode/uversion.h"
++#include "unicode/ucol.h"
++
++QT_BEGIN_NAMESPACE
++
++typedef UCollator *(*Ptr_ucol_open)(const char *loc, UErrorCode *status);
++typedef void (*Ptr_ucol_close)(UCollator *coll);
++typedef UCollationResult (*Ptr_ucol_strcoll)(const UCollator *coll, const UChar *source, int32_t sourceLength, const UChar *target, int32_t targetLength);
++typedef int32_t (*Ptr_u_strToCase)(UChar *dest, int32_t destCapacity, const UChar *src, int32_t srcLength, const char *locale, UErrorCode *pErrorCode);
++
++static Ptr_ucol_open ptr_ucol_open = 0;
++static Ptr_ucol_strcoll ptr_ucol_strcoll = 0;
++static Ptr_ucol_close ptr_ucol_close = 0;
++static Ptr_u_strToCase ptr_u_strToUpper = 0;
++static Ptr_u_strToCase ptr_u_strToLower = 0;
++
++enum LibLoadStatus
++{
++ ErrorLoading = -1,
++ NotLoaded = 0,
++ Loaded = 1
++};
++
++static LibLoadStatus status = NotLoaded;
++
++static UCollator *icuCollator = 0;
++
++#define STRINGIFY2(x) #x
++#define STRINGIFY(x) STRINGIFY2(x)
++
++bool qt_initIcu(const QString &localeString)
++{
++ if (status == ErrorLoading)
++ return false;
++
++ if (status == NotLoaded) {
++
++ // resolve libicui18n
++ QLibrary lib(QLatin1String("icui18n"), QLatin1String(U_ICU_VERSION_SHORT));
++ if (!lib.load()) {
++ qWarning() << "Unable to load library icui18n" << lib.errorString();
++ status = ErrorLoading;
++ return false;
++ }
++
++ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open");
++ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close");
++ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll");
++
++ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
++ // try again with decorated symbol names
++ ptr_ucol_open = (Ptr_ucol_open)lib.resolve("ucol_open" STRINGIFY(U_ICU_VERSION_SUFFIX));
++ ptr_ucol_close = (Ptr_ucol_close)lib.resolve("ucol_close" STRINGIFY(U_ICU_VERSION_SUFFIX));
++ ptr_ucol_strcoll = (Ptr_ucol_strcoll)lib.resolve("ucol_strcoll" STRINGIFY(U_ICU_VERSION_SUFFIX));
++ }
++
++ if (!ptr_ucol_open || !ptr_ucol_close || !ptr_ucol_strcoll) {
++ ptr_ucol_open = 0;
++ ptr_ucol_close = 0;
++ ptr_ucol_strcoll = 0;
++
++ qWarning("Unable to find symbols in icui18n");
++ status = ErrorLoading;
++ return false;
++ }
++
++ // resolve libicuuc
++ QLibrary ucLib(QLatin1String("icuuc"), QLatin1String(U_ICU_VERSION_SHORT));
++ if (!ucLib.load()) {
++ qWarning() << "Unable to load library icuuc" << ucLib.errorString();
++ status = ErrorLoading;
++ return false;
++ }
++
++ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper");
++ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower");
++
++ if (!ptr_u_strToUpper || !ptr_u_strToLower) {
++ ptr_u_strToUpper = (Ptr_u_strToCase)ucLib.resolve("u_strToUpper" STRINGIFY(U_ICU_VERSION_SUFFIX));
++ ptr_u_strToLower = (Ptr_u_strToCase)ucLib.resolve("u_strToLower" STRINGIFY(U_ICU_VERSION_SUFFIX));
++ }
++
++ if (!ptr_u_strToUpper || !ptr_u_strToLower) {
++ ptr_u_strToUpper = 0;
++ ptr_u_strToLower = 0;
++
++ qWarning("Unable to find symbols in icuuc");
++ status = ErrorLoading;
++ return false;
++ }
++
++ // success :)
++ status = Loaded;
++ }
++
++ if (icuCollator) {
++ ptr_ucol_close(icuCollator);
++ icuCollator = 0;
++ }
++
++ UErrorCode icuStatus = U_ZERO_ERROR;
++ icuCollator = ptr_ucol_open(localeString.toLatin1().constData(), &icuStatus);
++
++ if (!icuCollator) {
++ qWarning("Unable to open locale %s in ICU, error code %d", qPrintable(localeString), icuStatus);
++ return false;
++ }
++
++ return true;
++}
++
++bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result)
++{
++ Q_ASSERT(result);
++ Q_ASSERT(source);
++ Q_ASSERT(target);
++
++ if (!icuCollator)
++ return false;
++
++ *result = ptr_ucol_strcoll(icuCollator, reinterpret_cast<const UChar *>(source), int32_t(sourceLength),
++ reinterpret_cast<const UChar *>(target), int32_t(targetLength));
++
++ return true;
++}
++
++// caseFunc can either be u_strToUpper or u_strToLower
++static bool qt_u_strToCase(const QString &str, QString *out, const QLocale &locale, Ptr_u_strToCase caseFunc)
++{
++ Q_ASSERT(out);
++
++ if (!icuCollator)
++ return false;
++
++ QString result(str.size(), Qt::Uninitialized);
++
++ UErrorCode status = U_ZERO_ERROR;
++
++ int32_t size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
++ reinterpret_cast<const UChar *>(str.constData()), str.size(),
++ locale.name().toLatin1().constData(), &status);
++
++ if (U_FAILURE(status))
++ return false;
++
++ if (size < result.size()) {
++ result.resize(size);
++ } else if (size > result.size()) {
++ qDebug() << "RESULT SIZE MISMATCH";
++ // the resulting string is larger than our source string
++ result.resize(size);
++
++ status = U_ZERO_ERROR;
++ size = caseFunc(reinterpret_cast<UChar *>(result.data()), result.size(),
++ reinterpret_cast<const UChar *>(str.constData()), str.size(),
++ locale.name().toLatin1().constData(), &status);
++
++ if (U_FAILURE(status))
++ return false;
++
++ // if the sizes don't match now, we give up.
++ if (size != result.size())
++ return false;
++ }
++
++ *out = result;
++ return true;
++}
++
++bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale)
++{
++ return qt_u_strToCase(str, out, locale, ptr_u_strToUpper);
++}
++
++bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale)
++{
++ return qt_u_strToCase(str, out, locale, ptr_u_strToLower);
++}
++
++uint qt_u_toUpper(uint c)
++{
++ if (c > 0xffff)
++ return 0;
++
++ QString out;
++ if (qt_u_strToUpper(QChar(c), &out, QLocale()) && !out.isEmpty())
++ return out.at(0).unicode();
++ return 0;
++}
++
++uint qt_u_toLower(uint c)
++{
++ if (c > 0xffff)
++ return 0;
++
++ QString out;
++ if (qt_u_strToLower(QChar(c), &out, QLocale()) && !out.isEmpty())
++ return out.at(0).unicode();
++ return 0;
++}
++
++QT_END_NAMESPACE
+diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
+index d641d74..0f5cee1 100644
+--- a/src/corelib/tools/qstring.cpp
++++ b/src/corelib/tools/qstring.cpp
+@@ -112,6 +112,13 @@ int qFindString(const QChar *haystack, int haystackLen, int from,
+ int qFindStringBoyerMoore(const QChar *haystack, int haystackLen, int from,
+ const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
+
++#ifdef QT_USE_ICU
++// qlocale_icu.cpp
++extern bool qt_ucol_strcoll(const QChar *source, int sourceLength, const QChar *target, int targetLength, int *result);
++extern bool qt_u_strToUpper(const QString &str, QString *out, const QLocale &locale);
++extern bool qt_u_strToLower(const QString &str, QString *out, const QLocale &locale);
++#endif
++
+
+ // Unicode case-insensitive comparison
+ static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be)
+@@ -4808,6 +4815,14 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
+ TPtrC p2 = TPtrC16(reinterpret_cast<const TUint16 *>(data2), length2);
+ return p1.CompareC(p2);
+ #elif defined(Q_OS_UNIX)
++# if defined(QT_USE_ICU)
++ int res;
++ if (qt_ucol_strcoll(data1, length1, data2, length2, &res)) {
++ if (res == 0)
++ res = ucstrcmp(data1, length1, data2, length2);
++ return res;
++ } // else fall through
++# endif
+ // declared in <string.h>
+ int delta = strcoll(toLocal8Bit_helper(data1, length1), toLocal8Bit_helper(data2, length2));
+ if (delta == 0)
+@@ -4943,6 +4958,15 @@ QString QString::toLower() const
+ if (!d->size)
+ return *this;
+
++#ifdef QT_USE_ICU
++ {
++ QString result;
++ if (qt_u_strToLower(*this, &result, QLocale()))
++ return result;
++ // else fall through and use Qt's toUpper
++ }
++#endif
++
+ const ushort *e = d->data + d->size;
+
+ // this avoids one out of bounds check in the loop
+@@ -5034,6 +5058,15 @@ QString QString::toUpper() const
+ if (!d->size)
+ return *this;
+
++#ifdef QT_USE_ICU
++ {
++ QString result;
++ if (qt_u_strToUpper(*this, &result, QLocale()))
++ return result;
++ // else fall through and use Qt's toUpper
++ }
++#endif
++
+ const ushort *e = d->data + d->size;
+
+ // this avoids one out of bounds check in the loop
+diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
+index d81ab04..46c39f3 100644
+--- a/src/corelib/tools/tools.pri
++++ b/src/corelib/tools/tools.pri
+@@ -92,6 +92,11 @@ else:SOURCES += tools/qelapsedtimer_generic.cpp
+ contains(QT_CONFIG, zlib):include($$PWD/../../3rdparty/zlib.pri)
+ else:include($$PWD/../../3rdparty/zlib_dependency.pri)
+
++contains(QT_CONFIG,icu) {
++ SOURCES += tools/qlocale_icu.cpp
++ DEFINES += QT_USE_ICU
++}
++
+ DEFINES += HB_EXPORT=Q_CORE_EXPORT
+ INCLUDEPATH += ../3rdparty/harfbuzz/src
+ HEADERS += ../3rdparty/harfbuzz/src/harfbuzz.h
+diff --git a/tests/auto/qchar/qchar.pro b/tests/auto/qchar/qchar.pro
+index 3813e4e..d991365 100644
+--- a/tests/auto/qchar/qchar.pro
++++ b/tests/auto/qchar/qchar.pro
+@@ -13,3 +13,5 @@ symbian: {
+ } else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+ }
++
++contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU
+diff --git a/tests/auto/qchar/tst_qchar.cpp b/tests/auto/qchar/tst_qchar.cpp
+index 45dd7eb..514a836 100644
+--- a/tests/auto/qchar/tst_qchar.cpp
++++ b/tests/auto/qchar/tst_qchar.cpp
+@@ -103,7 +103,8 @@ tst_QChar::~tst_QChar()
+ { }
+
+ void tst_QChar::initTestCase()
+-{ }
++{
++}
+
+ void tst_QChar::cleanupTestCase()
+ { }
+@@ -114,6 +115,7 @@ void tst_QChar::init()
+ int argc = 0;
+ app = new QCoreApplication(argc, NULL);
+ #endif
++ QLocale::setDefault(QLocale::C);
+ }
+
+ void tst_QChar::cleanup()
+@@ -143,9 +145,36 @@ void tst_QChar::toUpper()
+ QVERIFY(QChar::toUpper((uint)0x1c8) == 0x1c7);
+ QVERIFY(QChar::toUpper((uint)0x1c9) == 0x1c7);
+
+- QVERIFY(QChar::toUpper((uint)0x10400) == 0x10400);
+- QVERIFY(QChar::toUpper((uint)0x10428) == 0x10400);
++ QCOMPARE(QChar::toUpper((uint)0x10400), 0x10400u);
++ QCOMPARE(QChar::toUpper((uint)0x10428), 0x10400u);
++
++#ifdef QT_USE_ICU
++ QCOMPARE(QChar('i').toUpper(), QChar('I'));
++ QCOMPARE(QChar::toUpper(ushort('i')), ushort('I'));
++ QCOMPARE(QChar::toUpper(uint('i')), uint('I'));
++
++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey));
++
++ // in Turkish locale, upper-caseing a 'i' will result in a capital I plus dot (0x0130)
++ QCOMPARE(QChar('i').toUpper(), QChar(0x0130u));
++ QCOMPARE(QChar::toUpper(ushort('i')), ushort(0x0130u));
++ QCOMPARE(QChar::toUpper(uint('i')), 0x0130u);
++
++ // upper-casing a lower-case i without dot (0x0131) will result in 'I'
++ QCOMPARE(QChar(0x0131u).toUpper(), QChar('I'));
++ QCOMPARE(QChar::toUpper(ushort(0x0131u)), ushort('I'));
++ QCOMPARE(QChar::toUpper(uint(0x0131u)), uint('I'));
++
++ // upper-casing an upper-case 0x0130 should do nothing
++ QCOMPARE(QChar(0x0130u).toUpper(), QChar(0x0130u));
++ QCOMPARE(QChar::toUpper(ushort(0x0130u)), ushort(0x0130u));
++ QCOMPARE(QChar::toUpper(uint(0x0130u)), uint(0x0130u));
+
++ // upper-casing an upper-case I should do nothing
++ QCOMPARE(QChar('I').toUpper(), QChar('I'));
++ QCOMPARE(QChar::toUpper(ushort('I')), ushort('I'));
++ QCOMPARE(QChar::toUpper(uint('I')), uint('I'));
++#endif
+ }
+
+ void tst_QChar::toLower()
+@@ -170,6 +199,34 @@ void tst_QChar::toLower()
+
+ QVERIFY(QChar::toLower((uint)0x10400) == 0x10428);
+ QVERIFY(QChar::toLower((uint)0x10428) == 0x10428);
++
++#ifdef QT_USE_ICU
++ QCOMPARE(QChar('I').toLower(), QChar('i'));
++ QCOMPARE(QChar::toLower(ushort('I')), ushort('i'));
++ QCOMPARE(QChar::toLower(uint('I')), uint('i'));
++
++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey));
++
++ // in turkish locale, lower-casing an 'I' will result with a lower-case i without dot (0x0131)
++ QCOMPARE(QChar('I').toLower(), QChar(0x0131u));
++ QCOMPARE(QChar::toLower(ushort('I')), ushort(0x0131u));
++ QCOMPARE(QChar::toLower(uint('I')), uint(0x0131u));
++
++ // lower-casing a captial I with dot (0x0130) will result in 'i'
++ QCOMPARE(QChar(0x0130u).toLower(), QChar('i'));
++ QCOMPARE(QChar::toLower(ushort(0x0130u)), ushort('i'));
++ QCOMPARE(QChar::toLower(uint(0x0130u)), uint('i'));
++
++ // lower-casing a lower-case i should do nothing
++ QCOMPARE(QChar('i').toLower(), QChar('i'));
++ QCOMPARE(QChar::toLower(ushort('i')), ushort('i'));
++ QCOMPARE(QChar::toLower(uint('i')), uint('i'));
++
++ // lower-casing a lower-case i without dot (0x0131) should do nothing
++ QCOMPARE(QChar(0x0131u).toLower(), QChar(0x0131u));
++ QCOMPARE(QChar::toLower(ushort(0x0131u)), ushort(0x0131u));
++ QCOMPARE(QChar::toLower(uint(0x0131u)), uint(0x0131u));
++#endif
+ }
+
+ void tst_QChar::toTitle()
+diff --git a/tests/auto/qstring/qstring.pro b/tests/auto/qstring/qstring.pro
+index ed758c6..92dd755 100644
+--- a/tests/auto/qstring/qstring.pro
++++ b/tests/auto/qstring/qstring.pro
+@@ -6,3 +6,5 @@ symbian:LIBS += -llibm
+ QT = core
+
+ DEFINES += QT_NO_CAST_TO_ASCII
++
++contains(QT_CONFIG,icu):DEFINES += QT_USE_ICU
+diff --git a/tests/auto/qstring/tst_qstring.cpp b/tests/auto/qstring/tst_qstring.cpp
+index ecae3d8..6baf9fc 100644
+--- a/tests/auto/qstring/tst_qstring.cpp
++++ b/tests/auto/qstring/tst_qstring.cpp
+@@ -210,6 +210,8 @@ private slots:
+ void task262677remove();
+ void QTBUG10404_compareRef();
+ void QTBUG9281_arg_locale();
++
++ void toUpperLower_icu();
+ };
+
+ typedef QList<int> IntList;
+@@ -1544,6 +1546,11 @@ void tst_QString::toUpper()
+ QCOMPARE( lower.toUpper(), upper);
+
+
++#ifdef QT_USE_ICU
++ // test doesn't work with ICU support, since QChar is unaware of any locale
++ QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue);
++ QVERIFY(false);
++#else
+ for (int i = 0; i < 65536; ++i) {
+ QString str(1, QChar(i));
+ QString upper = str.toUpper();
+@@ -1551,6 +1558,7 @@ void tst_QString::toUpper()
+ if (upper.length() == 1)
+ QVERIFY(upper == QString(1, QChar(i).toUpper()));
+ }
++#endif
+ }
+
+ void tst_QString::toLower()
+@@ -1582,6 +1590,11 @@ void tst_QString::toLower()
+ upper += QChar(QChar::lowSurrogate(0x10400));
+ QCOMPARE( upper.toLower(), lower);
+
++#ifdef QT_USE_ICU
++ // test doesn't work with ICU support, since QChar is unaware of any locale
++ QEXPECT_FAIL("", "test doesn't work with ICU support, since QChar is unaware of any locale", Continue);
++ QVERIFY(false);
++#else
+ for (int i = 0; i < 65536; ++i) {
+ QString str(1, QChar(i));
+ QString lower = str.toLower();
+@@ -1589,6 +1602,7 @@ void tst_QString::toLower()
+ if (lower.length() == 1)
+ QVERIFY(str.toLower() == QString(1, QChar(i).toLower()));
+ }
++#endif
+ }
+
+ void tst_QString::trimmed()
+@@ -4200,6 +4214,8 @@ void tst_QString::localeAwareCompare()
+
+ #elif defined (Q_WS_MAC)
+ QSKIP("Setting the locale is not supported on OS X (you can set the C locale, but that won't affect CFStringCompare which is used to compare strings)", SkipAll);
++#elif defined(QT_USE_ICU)
++ QLocale::setDefault(QLocale(locale));
+ #else
+ if (!locale.isEmpty()) {
+ const char *newLocale = setlocale(LC_ALL, locale.toLatin1());
+@@ -4211,6 +4227,11 @@ void tst_QString::localeAwareCompare()
+ }
+ #endif
+
++#ifdef QT_USE_ICU
++ // ### for c1, ICU disagrees with libc on how to compare
++ QEXPECT_FAIL("c1", "ICU disagrees with test", Abort);
++#endif
++
+ int testres = QString::localeAwareCompare(s1, s2);
+ if (result < 0) {
+ QVERIFY(testres < 0);
+@@ -4912,6 +4933,40 @@ void tst_QString::QTBUG9281_arg_locale()
+ QLocale::setDefault(QLocale::C);
+ }
+
++void tst_QString::toUpperLower_icu()
++{
++#ifndef QT_USE_ICU
++ QSKIP("Qt was built without ICU support", QTest::SkipAll);
++#endif
++
++ QString s = QString::fromLatin1("i");
++
++ QCOMPARE(s.toUpper(), QString::fromLatin1("I"));
++ QCOMPARE(s.toLower(), QString::fromLatin1("i"));
++
++ QLocale::setDefault(QLocale(QLocale::Turkish, QLocale::Turkey));
++
++ // turkish locale has a capital I with a dot (U+0130, utf8 c4b0)
++
++ QCOMPARE(s.toUpper(), QString::fromUtf8("\xc4\xb0"));
++ QCOMPARE(QString::fromUtf8("\xc4\xb0").toLower(), s);
++
++ // nothing should happen here
++ QCOMPARE(s.toLower(), s);
++ QCOMPARE(QString::fromLatin1("I").toUpper(), QString::fromLatin1("I"));
++
++ // U+0131, utf8 c4b1 is the lower-case i without a dot
++ QString sup = QString::fromUtf8("\xc4\xb1");
++
++ QCOMPARE(sup.toUpper(), QString::fromLatin1("I"));
++ QCOMPARE(QString::fromLatin1("I").toLower(), sup);
++
++ // nothing should happen here
++ QCOMPARE(sup.toLower(), sup);
++ QCOMPARE(QString::fromLatin1("i").toLower(), QString::fromLatin1("i"));
++
++ // the cleanup function will restore the default locale
++}
+
+
+ QTEST_APPLESS_MAIN(tst_QString)
diff --git a/config.profiles/harmattan/patches/no_read_pro_from_quilt_dir.diff b/config.profiles/harmattan/patches/no_read_pro_from_quilt_dir.diff
new file mode 100644
index 0000000..f5ddb67
--- /dev/null
+++ b/config.profiles/harmattan/patches/no_read_pro_from_quilt_dir.diff
@@ -0,0 +1,13 @@
+Index: qt-maemo-qtp/configure
+===================================================================
+--- qt-maemo-qtp.orig/configure
++++ qt-maemo-qtp/configure
+@@ -8465,7 +8465,7 @@
+ # .projects.3 -> the rest
+ rm -f .projects .projects.1 .projects.2 .projects.3
+
+-QMAKE_PROJECTS=`find "$relpath/." -name '*.pro' -print | sed 's-/\./-/-'`
++QMAKE_PROJECTS=`find "$relpath/." -name '*.pro' -a ! -path '*/.pc/*' -print | sed 's-/\./-/-'`
+ if [ -z "$AWK" ]; then
+ for p in `echo $QMAKE_PROJECTS`; do
+ echo "$p" >> .projects
diff --git a/config.profiles/harmattan/patches/pinch_gesture_sent_twice.diff b/config.profiles/harmattan/patches/pinch_gesture_sent_twice.diff
new file mode 100644
index 0000000..61dfbf9
--- /dev/null
+++ b/config.profiles/harmattan/patches/pinch_gesture_sent_twice.diff
@@ -0,0 +1,56 @@
+Index: qt-maemo-qtp/src/gui/kernel/qstandardgestures.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/gui/kernel/qstandardgestures.cpp
++++ qt-maemo-qtp/src/gui/kernel/qstandardgestures.cpp
+@@ -66,6 +66,9 @@
+ #else
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
+ #endif
++ } else if (target) {
++ return 0; // this assumes the target is a QGraphicsObject, so we return
++ // NULL to indicate that the recognizer doesn't support graphicsobject
+ }
+ return new QPanGesture;
+ }
+@@ -157,7 +160,11 @@
+ {
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
++ } else if (target) {
++ return 0; // this assumes the target is a QGraphicsObject, so we return
++ // NULL to indicate that the recognizer doesn't support graphicsobject
+ }
++
+ return new QPinchGesture;
+ }
+
+@@ -286,6 +293,9 @@
+ {
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
++ } else if (target) {
++ return 0; // this assumes the target is a QGraphicsObject, so we return
++ // NULL to indicate that the recognizer doesn't support graphicsobject
+ }
+ return new QSwipeGesture;
+ }
+@@ -424,6 +434,9 @@
+ {
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
++ } else if (target) {
++ return 0; // this assumes the target is a QGraphicsObject, so we return
++ // NULL to indicate that the recognizer doesn't support graphicsobject
+ }
+ return new QTapGesture;
+ }
+@@ -495,6 +508,9 @@
+ {
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
++ } else if (target) {
++ return 0; // this assumes the target is a QGraphicsObject, so we return
++ // NULL to indicate that the recognizer doesn't support graphicsobject
+ }
+ return new QTapAndHoldGesture;
+ }
diff --git a/config.profiles/harmattan/patches/qgltexturecache.diff b/config.profiles/harmattan/patches/qgltexturecache.diff
new file mode 100644
index 0000000..0fa8ad2
--- /dev/null
+++ b/config.profiles/harmattan/patches/qgltexturecache.diff
@@ -0,0 +1,23 @@
+Index: qt-maemo-qtp/src/opengl/qgl.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/opengl/qgl.cpp
++++ qt-maemo-qtp/src/opengl/qgl.cpp
+@@ -1831,18 +1831,6 @@
+ void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost)
+ {
+ QWriteLocker locker(&m_lock);
+- if (m_cache.totalCost() + cost > m_cache.maxCost()) {
+- // the cache is full - make an attempt to remove something
+- const QList<QGLTextureCacheKey> keys = m_cache.keys();
+- int i = 0;
+- while (i < m_cache.count()
+- && (m_cache.totalCost() + cost > m_cache.maxCost())) {
+- QGLTexture *tex = m_cache.object(keys.at(i));
+- if (tex->context == ctx)
+- m_cache.remove(keys.at(i));
+- ++i;
+- }
+- }
+ const QGLTextureCacheKey cacheKey = {key, QGLContextPrivate::contextGroup(ctx)};
+ m_cache.insert(cacheKey, texture, cost);
+ }
diff --git a/config.profiles/harmattan/patches/qwidget_x11.diff b/config.profiles/harmattan/patches/qwidget_x11.diff
new file mode 100644
index 0000000..8bcb011
--- /dev/null
+++ b/config.profiles/harmattan/patches/qwidget_x11.diff
@@ -0,0 +1,39 @@
+commit 4ecc45086102807901a3bd2b9e02a169ca212716
+Author: Harald Fernengel <harald.fernengel@nokia.com>
+Date: Thu Dec 9 10:51:01 2010 +0100
+
+ Fix a rare race condition when showing windows
+
+ When setting a window to translucent shortly before showing it with the
+ OpenGL graphics system, the hijacking would call XDestroyWindow without
+ resetting the internal state. This might lead to the window waiting for
+ a map notify message forever.
+
+ The patch now properly resets the internal state when destroying the old
+ window, so it'll get mapped correctly when show() is called.
+
+ Reviewed-by: Denis Dzyubenko
+
+Index: qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/gui/kernel/qwidget_x11.cpp
++++ qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp
+@@ -961,8 +961,17 @@
+ inputContext->setFocusWidget(q);
+ }
+
+- if (destroyw)
++ if (destroyw) {
+ qt_XDestroyWindow(q, dpy, destroyw);
++ if (QTLWExtra *topData = maybeTopData()) {
++#ifndef QT_NO_XSYNC
++ if (topData->syncUpdateCounter)
++ XSyncDestroyCounter(dpy, topData->syncUpdateCounter);
++#endif
++ // we destroyed our old window - reset the top-level state
++ createTLSysExtra();
++ }
++ }
+
+ // newly created windows are positioned at the window system's
+ // (0,0) position. If the parent uses wrect mapping to expand the
diff --git a/config.profiles/harmattan/patches/qwidget_x11_mapping.diff b/config.profiles/harmattan/patches/qwidget_x11_mapping.diff
new file mode 100644
index 0000000..4866cfb
--- /dev/null
+++ b/config.profiles/harmattan/patches/qwidget_x11_mapping.diff
@@ -0,0 +1,17 @@
+Index: qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/gui/kernel/qwidget_x11.cpp
++++ qt-maemo-qtp/src/gui/kernel/qwidget_x11.cpp
+@@ -1353,6 +1353,12 @@
+ //cannot trust that !isWindow() implies parentWidget() before create
+ return (q->isWindow() || !q->parentWidget()) ? p : q->parentWidget()->d_func()->mapToGlobal(p);
+ }
++
++ // we're not embedded - use the client rect to compute the global position
++ if (!q->window()->d_func()->topData()->embedded)
++ return mapFromWS(QPoint(pos.x() - q->data->crect.left(), pos.y() - q->data->crect.top()));
++
++ // otherwise, go through the (slow-ish) X11 round-trip
+ int x, y;
+ Window child;
+ QPoint p = mapToWS(pos);
diff --git a/config.profiles/harmattan/patches/runtime-window-geometry-revert.diff b/config.profiles/harmattan/patches/runtime-window-geometry-revert.diff
new file mode 100644
index 0000000..af55a60
--- /dev/null
+++ b/config.profiles/harmattan/patches/runtime-window-geometry-revert.diff
@@ -0,0 +1,12 @@
+Index: qt-maemo-qtp/src/gui/painting/qgraphicssystem_runtime.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/gui/painting/qgraphicssystem_runtime.cpp
++++ qt-maemo-qtp/src/gui/painting/qgraphicssystem_runtime.cpp
+@@ -285,7 +285,6 @@
+
+ void QRuntimeWindowSurface::setGeometry(const QRect &rect)
+ {
+- QWindowSurface::setGeometry(rect);
+ m_windowSurface->setGeometry(rect);
+ }
+
diff --git a/config.profiles/harmattan/patches/series b/config.profiles/harmattan/patches/series
new file mode 100644
index 0000000..f2ee5f9
--- /dev/null
+++ b/config.profiles/harmattan/patches/series
@@ -0,0 +1,14 @@
+tst_qscrollbar.diff
+signon_authenticator4.diff
+pinch_gesture_sent_twice.diff
+no_read_pro_from_quilt_dir.diff
+tst_qvariant.diff
+icu.diff
+qgltexturecache.diff
+qwidget_x11.diff
+qwidget_x11_mapping.diff
+glshadercache.diff
+temppath.diff
+tst_qprogressbar.diff
+default_widget_size.diff
+runtime-window-geometry-revert.diff
diff --git a/config.profiles/harmattan/patches/signon_authenticator4.diff b/config.profiles/harmattan/patches/signon_authenticator4.diff
new file mode 100644
index 0000000..63e8d51
--- /dev/null
+++ b/config.profiles/harmattan/patches/signon_authenticator4.diff
@@ -0,0 +1,230 @@
+Index: qt-maemo-qtp/src/3rdparty/signon/signon.pri
+===================================================================
+--- /dev/null
++++ qt-maemo-qtp/src/3rdparty/signon/signon.pri
+@@ -0,0 +1,2 @@
++# signon dependency
++CONFIG += qdbus
+Index: qt-maemo-qtp/src/network/access/access.pri
+===================================================================
+--- qt-maemo-qtp.orig/src/network/access/access.pri
++++ qt-maemo-qtp/src/network/access/access.pri
+@@ -61,3 +61,4 @@
+ access/qnetworkdiskcache.cpp
+
+ include($$PWD/../../3rdparty/zlib_dependency.pri)
++include($$PWD/../../3rdparty/signon/signon.pri)
+Index: qt-maemo-qtp/src/network/kernel/qauthenticator.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/network/kernel/qauthenticator.cpp
++++ qt-maemo-qtp/src/network/kernel/qauthenticator.cpp
+@@ -129,6 +129,9 @@
+ \sa QSslSocket
+ */
+
++#ifndef QT_NO_SIGNON
++#include <QtDBus/QtDBus>
++#endif //QT_NO_SIGNON
+
+ /*!
+ Constructs an empty authentication object
+@@ -421,17 +424,40 @@
+ {
+ QByteArray response;
+ const char *methodString = 0;
++#ifndef QT_NO_SIGNON
++ bool valid = false;
++ qint32 id = 0;
++#endif //QT_NO_SIGNON
++
+ switch(method) {
+ case QAuthenticatorPrivate::None:
+ methodString = "";
+ phase = Done;
+ break;
+ case QAuthenticatorPrivate::Plain:
++#ifndef QT_NO_SIGNON
++ id = this->options.value(QLatin1String("identity")).toInt(&valid);
++ if (valid) {
++ //get response from sso
++ QVariantMap signon = signonResponse(id, QLatin1String("password"),QVariantMap());
++ response = '\0' + signon.value(QLatin1String("UserName")).toString().toUtf8()
++ + '\0' + signon.value(QLatin1String("Secret")).toString().toUtf8();
++ } else
++#endif //QT_NO_SIGNON
+ response = '\0' + user.toUtf8() + '\0' + password.toUtf8();
+ phase = Done;
+ break;
+ case QAuthenticatorPrivate::Basic:
+ methodString = "Basic ";
++#ifndef QT_NO_SIGNON
++ id = this->options.value(QLatin1String("identity")).toInt(&valid);
++ if (valid) {
++ //get response from sso
++ QVariantMap signon = signonResponse(id, QLatin1String("password"),QVariantMap());
++ response = signon.value(QLatin1String("UserName")).toString().toLatin1()
++ + ':' + signon.value(QLatin1String("Secret")).toString().toLatin1();
++ } else
++#endif //QT_NO_SIGNON
+ response = user.toLatin1() + ':' + password.toLatin1();
+ response = response.toBase64();
+ phase = Done;
+@@ -613,6 +639,90 @@
+ return hash.result().toHex();
+ }
+
++#ifndef QT_NO_SIGNON
++
++static QVariantMap signonResponse(const quint32 id, const QString &method, QVariantMap args)
++{
++ //check dbus connection
++ QDBusConnection connection = QDBusConnection::sessionBus();
++ if (!QDBusConnection::sessionBus().isConnected()) {
++ qCritical() << "DBus connection failed";
++ return QVariantMap();
++ }
++
++ QDBusMessage msg =
++ QDBusMessage::createMethodCall(QLatin1String("com.nokia.SingleSignOn"),
++ QLatin1String("/com/nokia/SingleSignOn") ,
++ QLatin1String("com.nokia.SingleSignOn.AuthService"),
++ QLatin1String("getAuthSessionObjectPath"));
++ msg << id << method;
++ QDBusReply<QString> pathReply = connection.call(msg);
++
++ QString sessionPath;
++ if (pathReply.isValid()) {
++ sessionPath = pathReply.value();
++ } else {
++ qDebug() << pathReply.error();
++ return QVariantMap();
++ }
++
++ //authenticate using auth session
++ msg = QDBusMessage::createMethodCall(QLatin1String("com.nokia.SingleSignOn"),
++ sessionPath, QString(),
++ QLatin1String("process"));
++ msg << args << method;
++ QDBusReply<QVariantMap> reply = connection.call(msg);
++
++ if (reply.isValid()) {
++ QVariantMap map = reply.value();
++ return map;
++ } else {
++ qDebug() << reply.error();
++ return QVariantMap();
++ }
++ return QVariantMap();
++}
++
++static QByteArray signonDigestMd5(
++ const quint32 id,
++ const QByteArray &alg,
++ QString &user,
++ const QByteArray &realm,
++ const QByteArray &nonce, /* nonce from server */
++ QByteArray &nonceCount, /* 8 hex digits */
++ QByteArray &cNonce, /* client nonce */
++ const QByteArray &qop, /* qop-value: "", "auth", "auth-int" */
++ const QByteArray &method, /* method from the request */
++ const QByteArray &digestUri, /* requested URL */
++ const QByteArray &hEntity /* H(entity body) if qop="auth-int" */
++ )
++{
++ QByteArray digest = QByteArray();
++ nonceCount = "00000001";
++
++ QVariantMap args;
++ args.insert(QLatin1String("Algorithm"), alg);
++ args.insert(QLatin1String("Realm"), QLatin1String(realm));
++ args.insert(QLatin1String("nonce"), nonce);
++ args.insert(QLatin1String("nonceCount"), nonceCount);
++ args.insert(QLatin1String("cNonce"), cNonce);
++ args.insert(QLatin1String("qop"), qop);
++ args.insert(QLatin1String("method"), method);
++ args.insert(QLatin1String("digestUri"), digestUri);
++ args.insert(QLatin1String("Entity"), hEntity);
++
++ QVariantMap response = signonResponse(id, QLatin1String("digest"), args);
++
++ if (response.isEmpty())
++ return digest;
++ digest = response.value(QLatin1String("Digest")).toByteArray();
++ user = response.value(QLatin1String("UserName")).toString();
++ cNonce = response.value(QLatin1String("cNonce")).toByteArray();
++
++ return digest;
++}
++#endif //QT_NO_SIGNON
++
+ QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge, const QByteArray &method, const QByteArray &path)
+ {
+ QHash<QByteArray,QByteArray> options = parseDigestAuthenticationChallenge(challenge);
+@@ -625,9 +735,23 @@
+ QByteArray nonce = options.value("nonce");
+ QByteArray opaque = options.value("opaque");
+ QByteArray qop = options.value("qop");
++ QByteArray response;
+
+ // qDebug() << "calculating digest: method=" << method << "path=" << path;
+- QByteArray response = digestMd5ResponseHelper(options.value("algorithm"), user.toLatin1(),
++
++#ifndef QT_NO_SIGNON
++ bool valid = false;
++ qint32 id = this->options.value(QLatin1String("identity")).toInt(&valid);
++ if (valid) {
++ //get response from sso
++ response = signonDigestMd5(id, options.value("algorithm"), user,
++ realm.toLatin1(),
++ nonce, nonceCountString,
++ cnonce, qop, method,
++ path, QByteArray());
++ } else
++#endif //QT_NO_SIGNON
++ response = digestMd5ResponseHelper(options.value("algorithm"), user.toLatin1(),
+ realm.toLatin1(), password.toLatin1(),
+ nonce, nonceCountString,
+ cnonce, qop, method,
+Index: qt-maemo-qtp/src/network/kernel/qauthenticator_p.h
+===================================================================
+--- qt-maemo-qtp.orig/src/network/kernel/qauthenticator_p.h
++++ qt-maemo-qtp/src/network/kernel/qauthenticator_p.h
+@@ -109,6 +109,23 @@
+
+ };
+
++#ifndef QT_NO_SIGNON
++ static QVariantMap signonResponse(const quint32 id, const QString &method, QVariantMap args);
++ static QByteArray signonDigestMd5(
++ const quint32 id,
++ const QByteArray &alg,
++ QString &user,
++ const QByteArray &realm,
++ const QByteArray &nonce, /* nonce from server */
++ QByteArray &nonceCount, /* 8 hex digits */
++ QByteArray &cNonce, /* client nonce */
++ const QByteArray &qop, /* qop-value: "", "auth", "auth-int" */
++ const QByteArray &method, /* method from the request */
++ const QByteArray &digestUri, /* requested URL */
++ const QByteArray &hEntity /* H(entity body) if qop="auth-int" */
++ );
++#endif //QT_NO_SIGNON
++
+
+ QT_END_NAMESPACE
+
+Index: qt-maemo-qtp/src/src.pro
+===================================================================
+--- qt-maemo-qtp.orig/src/src.pro
++++ qt-maemo-qtp/src/src.pro
+@@ -4,8 +4,9 @@
+ unset(SRC_SUBDIRS)
+ win32:SRC_SUBDIRS += src_winmain
+ symbian:SRC_SUBDIRS += src_s60main
+-SRC_SUBDIRS += src_corelib src_xml src_network src_sql src_testlib
++SRC_SUBDIRS += src_corelib src_xml
+ !symbian:contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus
++SRC_SUBDIRS += src_network src_sql src_testlib
+ !contains(QT_CONFIG, no-gui): SRC_SUBDIRS += src_gui
+ !wince*:!symbian:!vxworks:contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_qt3support
+
diff --git a/config.profiles/harmattan/patches/temppath.diff b/config.profiles/harmattan/patches/temppath.diff
new file mode 100644
index 0000000..065c2d0
--- /dev/null
+++ b/config.profiles/harmattan/patches/temppath.diff
@@ -0,0 +1,28 @@
+Index: qt-maemo-qtp/mkspecs/linux-g++-maemo/qplatformdefs.h
+===================================================================
+--- qt-maemo-qtp.orig/mkspecs/linux-g++-maemo/qplatformdefs.h
++++ qt-maemo-qtp/mkspecs/linux-g++-maemo/qplatformdefs.h
+@@ -43,3 +43,8 @@
+
+ #define QT_GUI_DOUBLE_CLICK_RADIUS 20
+ #define QT_GUI_DRAG_DISTANCE 16
++
++// TMPDIR sometimes points to /tmp and sometimes to /var/tmp
++// To guarantee native platform key generation for QSharedMemory and friends,
++// we must hard code the temp path to /var/tmp here.
++#define QT_UNIX_TEMP_PATH_OVERRIDE "/var/tmp"
+Index: qt-maemo-qtp/src/corelib/io/qfsfileengine_unix.cpp
+===================================================================
+--- qt-maemo-qtp.orig/src/corelib/io/qfsfileengine_unix.cpp
++++ qt-maemo-qtp/src/corelib/io/qfsfileengine_unix.cpp
+@@ -643,7 +643,9 @@
+
+ QString QFSFileEngine::tempPath()
+ {
+-#if defined(Q_OS_SYMBIAN)
++#if defined(QT_UNIX_TEMP_PATH_OVERRIDE)
++ QString temp = QLatin1String(QT_UNIX_TEMP_PATH_OVERRIDE);
++#elif defined(Q_OS_SYMBIAN)
+ TFileName symbianPath = PathInfo::PhoneMemoryRootPath();
+ QString temp = QDir::fromNativeSeparators(qt_TDesC2QString(symbianPath));
+ temp += QLatin1String( "temp/");
diff --git a/config.profiles/harmattan/patches/tst_qprogressbar.diff b/config.profiles/harmattan/patches/tst_qprogressbar.diff
new file mode 100644
index 0000000..d252fe3
--- /dev/null
+++ b/config.profiles/harmattan/patches/tst_qprogressbar.diff
@@ -0,0 +1,19 @@
+Index: qt-maemo-qtp/tests/auto/qprogressbar/tst_qprogressbar.cpp
+===================================================================
+--- qt-maemo-qtp.orig/tests/auto/qprogressbar/tst_qprogressbar.cpp
++++ qt-maemo-qtp/tests/auto/qprogressbar/tst_qprogressbar.cpp
+@@ -179,10 +179,14 @@
+ bar.repainted = false;
+ bar.setFormat("%v of %m (%p%)");
+ qApp->processEvents();
++
++#if 0 // Removed
+ #ifndef Q_WS_MAC
+ // The Mac scroll bar is animated, which means we get paint events all the time.
+ QVERIFY(!bar.repainted);
+ #endif
++#endif
++
+ QCOMPARE(bar.text(), QString("1 of 10 (10%)"));
+ bar.setRange(5, 5);
+ bar.setValue(5);
diff --git a/config.profiles/harmattan/patches/tst_qscrollbar.diff b/config.profiles/harmattan/patches/tst_qscrollbar.diff
new file mode 100644
index 0000000..3c777a9
--- /dev/null
+++ b/config.profiles/harmattan/patches/tst_qscrollbar.diff
@@ -0,0 +1,12 @@
+Index: qt-maemo-qtp/tests/auto/qscrollbar/tst_qscrollbar.cpp
+===================================================================
+--- qt-maemo-qtp.orig/tests/auto/qscrollbar/tst_qscrollbar.cpp
++++ qt-maemo-qtp/tests/auto/qscrollbar/tst_qscrollbar.cpp
+@@ -104,6 +104,7 @@
+
+ void tst_QScrollBar::task_209492()
+ {
++ QSKIP("Unstable test on Harmattan", SkipSingle);
+ class MyScrollArea : public QScrollArea
+ {
+ public:
diff --git a/config.profiles/harmattan/patches/tst_qvariant.diff b/config.profiles/harmattan/patches/tst_qvariant.diff
new file mode 100644
index 0000000..bcded52
--- /dev/null
+++ b/config.profiles/harmattan/patches/tst_qvariant.diff
@@ -0,0 +1,21 @@
+Index: qt-maemo-qtp/tests/auto/qvariant/tst_qvariant.cpp
+===================================================================
+--- qt-maemo-qtp.orig/tests/auto/qvariant/tst_qvariant.cpp
++++ qt-maemo-qtp/tests/auto/qvariant/tst_qvariant.cpp
+@@ -3122,6 +3122,7 @@
+
+ void tst_QVariant::numericalConvert()
+ {
++ int low_int = 3;
+ QVariant vfloat(float(5.3));
+ QVariant vdouble(double(5.3));
+ QVariant vreal(qreal(5.3));
+@@ -3137,7 +3138,7 @@
+
+ for(int i = 0; i < vect.size(); i++) {
+ double num = 5.3;
+- if (i >= 3 && i <= 7)
++ if (i >= low_int && i <= 7)
+ num = 5;
+ QVariant *v = vect.at(i);
+ QCOMPARE(v->toFloat() , float(num));