From 4b5b74835f6323415f7df43ddb74caa078c4ab62 Mon Sep 17 00:00:00 2001
From: Peter Hartmann <peter.hartmann@nokia.com>
Date: Tue, 15 Dec 2009 16:48:03 +0100
Subject: fix Cocoa build

with change 83940f25, we used LIBS_PRIVATE on the Mac; somewhere
the line where we linked against the Mac libs in the network
kernel was lost.

Reviewed-By: Thiago
---
 src/network/kernel/kernel.pri | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index 8aa6ff4..d3e9774 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -23,7 +23,7 @@ SOURCES += kernel/qauthenticator.cpp \
 unix:SOURCES += kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
 win32:SOURCES += kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp
 
-mac:LIBS+= -framework SystemConfiguration
+mac:LIBS+= -framework SystemConfiguration -framework CoreFoundation
 mac:SOURCES += kernel/qnetworkproxy_mac.cpp
 else:win32:SOURCES += kernel/qnetworkproxy_win.cpp
 else:SOURCES += kernel/qnetworkproxy_generic.cpp
-- 
cgit v0.12


From c74d9d92f0d9c372de71ccf865edffae92a92d98 Mon Sep 17 00:00:00 2001
From: Volker Hilsheimer <volker.hilsheimer@nokia.com>
Date: Thu, 17 Dec 2009 14:45:04 +0100
Subject: Doc: fix typo

Fixes: QTBUG-6539
---
 src/network/access/qnetworkreply.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 9ab4057..e6ca367 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -171,7 +171,7 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
     \value UnknownProxyError            an unknown proxy-related error
     was detected
 
-    \value UnknownContentError          an unknonwn error related to
+    \value UnknownContentError          an unknown error related to
     the remote content was detected
 
     \value ProtocolFailure              a breakdown in protocol was
-- 
cgit v0.12


From face84c73a2196432020dda18755af7955d2de39 Mon Sep 17 00:00:00 2001
From: Markus Goetz <Markus.Goetz@nokia.com>
Date: Wed, 16 Dec 2009 14:10:36 +0100
Subject: Change QHostInfo to use 5 parallel lookup threads

Instead of sequentially looking up and potentially taking
a long time, we now do work in parallel.

Reviewed-by: ogoffart
Reviewed-by: lars
---
 src/network/kernel/qhostinfo.cpp       | 297 ++++++++++++++++++++++-----------
 src/network/kernel/qhostinfo_p.h       | 148 ++++++----------
 src/network/kernel/qhostinfo_win.cpp   |   6 +-
 tests/auto/qhostinfo/tst_qhostinfo.cpp |  49 +++++-
 4 files changed, 305 insertions(+), 195 deletions(-)

diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 98a39cd..e77a425 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -60,11 +60,9 @@
 
 QT_BEGIN_NAMESPACE
 
-Q_GLOBAL_STATIC(QHostInfoAgent, theAgent)
-void QHostInfoAgent::staticCleanup()
-{
-    theAgent()->cleanup();
-}
+#ifndef QT_NO_THREAD
+Q_GLOBAL_STATIC(QHostInfoLookupManager, theHostInfoLookupManager)
+#endif
 
 //#define QHOSTINFO_DEBUG
 
@@ -143,6 +141,9 @@ static QBasicAtomicInt theIdCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
 
     \snippet doc/src/snippets/code/src_network_kernel_qhostinfo.cpp 4
 
+    \note There is no guarantee on the order the signals will be emitted
+    if you start multiple requests with lookupHost().
+
     \sa abortHostLookup(), addresses(), error(), fromName()
 */
 int QHostInfo::lookupHost(const QString &name, QObject *receiver,
@@ -159,38 +160,32 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
 
     qRegisterMetaType<QHostInfo>("QHostInfo");
 
-#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
-    QWindowsSockInit bust; // makes sure WSAStartup was callled
-#endif
-
-    QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
-    result.data()->autoDelete = false;
-    QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
-                     receiver, member);
-    int id = result.data()->lookupId = theIdCounter.fetchAndAddRelaxed(1);
+    int id = theIdCounter.fetchAndAddRelaxed(1); // generate unique ID
 
     if (name.isEmpty()) {
-        QHostInfo info(id);
-        info.setError(QHostInfo::HostNotFound);
-        info.setErrorString(QObject::tr("No host name given"));
-        QMetaObject::invokeMethod(result.data(), "emitResultsReady", Qt::QueuedConnection,
-                                  Q_ARG(QHostInfo, info));
-        result.take()->autoDelete = true;
+        QHostInfo hostInfo(id);
+        hostInfo.setError(QHostInfo::HostNotFound);
+        hostInfo.setErrorString(QObject::tr("No host name given"));
+        QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
+        QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
+                         receiver, member, Qt::QueuedConnection);
+        result.data()->emitResultsReady(hostInfo);
         return id;
     }
 
-    QHostInfoAgent *agent = theAgent();
-    agent->addHostName(name, result.take());
-
-#if !defined QT_NO_THREAD
-    if (!agent->isRunning())
-        agent->start();
+#ifdef QT_NO_THREAD
+    QHostInfo hostInfo = QHostInfoAgent::fromName(name);
+    hostInfo.setLookupId(id);
+    QScopedPointer<QHostInfoResult> result(new QHostInfoResult);
+    QObject::connect(result.data(), SIGNAL(resultsReady(QHostInfo)),
+                     receiver, member, Qt::QueuedConnection);
+    result.data()->emitResultsReady(hostInfo);
 #else
-//    if (!agent->isRunning())
-	agent->run();
-//    else
-//	agent->wakeOne();
+    QHostInfoRunnable* runnable = new QHostInfoRunnable(name, id);
+    QObject::connect(&runnable->resultEmitter, SIGNAL(resultsReady(QHostInfo)), receiver, member, Qt::QueuedConnection);
+    theHostInfoLookupManager()->scheduleLookup(runnable);
 #endif
+
     return id;
 }
 
@@ -201,8 +196,12 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
 */
 void QHostInfo::abortHostLookup(int id)
 {
-    QHostInfoAgent *agent = theAgent();
-    agent->abortLookup(id);
+#ifndef QT_NO_THREAD
+    theHostInfoLookupManager()->abortLookup(id);
+#else
+    // we cannot abort if it was non threaded.. the result signal has already been posted
+    Q_UNUSED(id);
+#endif
 }
 
 /*!
@@ -228,70 +227,6 @@ QHostInfo QHostInfo::fromName(const QString &name)
 }
 
 /*!
-    \internal
-    Pops a query off the queries list, performs a blocking call to
-    QHostInfoAgent::lookupHost(), and emits the resultsReady()
-    signal. This process repeats until the queries list is empty.
-*/
-void QHostInfoAgent::run()
-{
-#ifndef QT_NO_THREAD
-    // Dont' allow thread termination during event delivery, but allow it
-    // during the actual blocking host lookup stage.
-    setTerminationEnabled(false);
-    forever
-#endif
-    {
-        QHostInfoQuery *query;
-        {
-#ifndef QT_NO_THREAD
-            // the queries list is shared between threads. lock all
-            // access to it.
-            QMutexLocker locker(&mutex);
-            if (!quit && queries.isEmpty())
-                cond.wait(&mutex);
-            if (quit) {
-                // Reset the quit variable in case QCoreApplication is
-                // destroyed and recreated.
-                quit = false;
-                break;
-            }
-	    if (queries.isEmpty())
-		continue;
-#else
-	    if (queries.isEmpty())
-		return;
-#endif
-            query = queries.takeFirst();
-            pendingQueryId = query->object->lookupId;
-        }
-
-#if defined(QHOSTINFO_DEBUG)
-        qDebug("QHostInfoAgent::run(%p): looking up \"%s\"", this,
-               query->hostName.toLatin1().constData());
-#endif
-
-#ifndef QT_NO_THREAD
-        // Start query - allow termination at this point, but not outside. We
-        // don't want to all termination during event delivery, but we don't
-        // want the lookup to prevent the app from quitting (the agent
-        // destructor terminates the thread).
-        setTerminationEnabled(true);
-#endif
-        QHostInfo info = fromName(query->hostName);
-#ifndef QT_NO_THREAD
-        setTerminationEnabled(false);
-#endif
-
-        int id = query->object->lookupId;
-        info.setLookupId(id);
-        if (pendingQueryId == id)
-            query->object->emitResultsReady(info);
-        delete query;
-    }
-}
-
-/*!
     \enum QHostInfo::HostInfoError
 
     This enum describes the various errors that can occur when trying
@@ -467,4 +402,174 @@ void QHostInfo::setErrorString(const QString &str)
     \sa hostName()
 */
 
+#ifndef QT_NO_THREAD
+QHostInfoRunnable::QHostInfoRunnable(QString hn, int i) : toBeLookedUp(hn), id(i)
+{
+    setAutoDelete(true);
+}
+
+// the QHostInfoLookupManager will at some point call this via a QThreadPool
+void QHostInfoRunnable::run()
+{
+    QHostInfoLookupManager *manager = theHostInfoLookupManager();
+    // check aborted
+    if (manager->wasAborted(id)) {
+        manager->lookupFinished(this);
+        return;
+    }
+
+    // check cache
+    // FIXME
+
+    // if not in cache: OS lookup
+    QHostInfo hostInfo = QHostInfoAgent::fromName(toBeLookedUp);
+
+    // save to cache
+    // FIXME
+
+    // check aborted again
+    if (manager->wasAborted(id)) {
+        manager->lookupFinished(this);
+        return;
+    }
+
+    // signal emission
+    hostInfo.setLookupId(id);
+    resultEmitter.emitResultsReady(hostInfo);
+
+    manager->lookupFinished(this);
+
+    // thread goes back to QThreadPool
+}
+
+QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), wasDeleted(false)
+{
+    moveToThread(QCoreApplicationPrivate::mainThread());
+    threadPool.setMaxThreadCount(5); // do 5 DNS lookups in parallel
+}
+
+QHostInfoLookupManager::~QHostInfoLookupManager()
+{
+    wasDeleted = true;
+}
+
+void QHostInfoLookupManager::work()
+{
+    if (wasDeleted)
+        return;
+
+    // goals of this function:
+    //  - launch new lookups via the thread pool
+    //  - make sure only one lookup per host/IP is in progress
+
+    QMutexLocker locker(&mutex);
+
+    if (!finishedLookups.isEmpty()) {
+        // remove ID from aborted if it is in there
+        for (int i = 0; i < finishedLookups.length(); i++) {
+           abortedLookups.removeAll(finishedLookups.at(i)->id);
+        }
+
+        finishedLookups.clear();
+    }
+
+    if (!postponedLookups.isEmpty()) {
+        // try to start the postponed ones
+
+        QMutableListIterator<QHostInfoRunnable*> iterator(postponedLookups);
+        while (iterator.hasNext()) {
+            QHostInfoRunnable* postponed = iterator.next();
+
+            // check if none of the postponed hostnames is currently running
+            bool alreadyRunning = false;
+            for (int i = 0; i < currentLookups.length(); i++) {
+                if (currentLookups.at(i)->toBeLookedUp == postponed->toBeLookedUp) {
+                    alreadyRunning = true;
+                    break;
+                }
+            }
+            if (!alreadyRunning) {
+                iterator.remove();
+                scheduledLookups.prepend(postponed); // prepend! we want to finish it ASAP
+            }
+        }
+    }
+
+    if (!scheduledLookups.isEmpty()) {
+        // try to start the new ones
+        QMutableListIterator<QHostInfoRunnable*> iterator(scheduledLookups);
+        while (iterator.hasNext()) {
+            QHostInfoRunnable *scheduled = iterator.next();
+
+            // check if a lookup for this host is already running, then postpone
+            for (int i = 0; i < currentLookups.size(); i++) {
+                if (currentLookups.at(i)->toBeLookedUp == scheduled->toBeLookedUp) {
+                    iterator.remove();
+                    postponedLookups.append(scheduled);
+                    scheduled = 0;
+                    break;
+                }
+            }
+
+            if (scheduled && threadPool.tryStart(scheduled)) {
+                // runnable now running in new thread, track this in currentLookups
+                iterator.remove();
+                currentLookups.append(scheduled);
+            } else if (scheduled) {
+                // wanted to start, but could not because thread pool is busy
+                break;
+            } else {
+                // was postponed, continue iterating
+                continue;
+            }
+        };
+    }
+}
+
+// called by QHostInfo
+void QHostInfoLookupManager::scheduleLookup(QHostInfoRunnable *r)
+{
+    if (wasDeleted)
+        return;
+
+    QMutexLocker locker(&this->mutex);
+    scheduledLookups.enqueue(r);
+    work();
+}
+
+// called by QHostInfo
+void QHostInfoLookupManager::abortLookup(int id)
+{
+    if (wasDeleted)
+        return;
+
+    QMutexLocker locker(&this->mutex);
+    if (!abortedLookups.contains(id))
+        abortedLookups.append(id);
+}
+
+// called from QHostInfoRunnable
+bool QHostInfoLookupManager::wasAborted(int id)
+{
+    if (wasDeleted)
+        return true;
+
+    QMutexLocker locker(&this->mutex);
+    return abortedLookups.contains(id);
+}
+
+// called from QHostInfoRunnable
+void QHostInfoLookupManager::lookupFinished(QHostInfoRunnable *r)
+{
+    if (wasDeleted)
+        return;
+
+    QMutexLocker locker(&this->mutex);
+    currentLookups.removeOne(r);
+    finishedLookups.append(r);
+    work();
+}
+
+#endif // QT_NO_THREAD
+
 QT_END_NAMESPACE
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index afd3570..643bb73 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -61,17 +61,17 @@
 #include "QtCore/qobject.h"
 #include "QtCore/qpointer.h"
 
-#if !defined QT_NO_THREAD
+#ifndef QT_NO_THREAD
 #include "QtCore/qthread.h"
-#    define QHostInfoAgentBase QThread
-#else
-#    define QHostInfoAgentBase QObject
+#include "QtCore/qthreadpool.h"
+#include "QtCore/qmutex.h"
+#include "QtCore/qrunnable.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qqueue.h"
 #endif
 
 QT_BEGIN_NAMESPACE
 
-static const int QHOSTINFO_THREAD_WAIT = 250; // ms
-
 class QHostInfoResult : public QObject
 {
     Q_OBJECT
@@ -79,102 +79,18 @@ public Q_SLOTS:
     inline void emitResultsReady(const QHostInfo &info)
     {
         emit resultsReady(info);
-        if (autoDelete)
-            delete this;
     }
 
 Q_SIGNALS:
-    void resultsReady(const QHostInfo &info);
-
-public:
-    int lookupId;
-    bool autoDelete;
+    void resultsReady(const QHostInfo info);
 };
 
-struct QHostInfoQuery
-{
-    inline QHostInfoQuery() : object(0) {}
-    inline ~QHostInfoQuery() { delete object; }
-    inline QHostInfoQuery(const QString &name, QHostInfoResult *result)
-        : hostName(name), object(result) {}
-
-    QString hostName;
-    QHostInfoResult *object;
-};
-
-class QHostInfoAgent : public QHostInfoAgentBase
+// needs to be QObject because fromName calls tr()
+class QHostInfoAgent : public QObject
 {
     Q_OBJECT
 public:
-    inline QHostInfoAgent()
-    {
-        // There is a chance that there will be two instances of
-        // QHostInfoAgent if two threads try to get Q_GLOBAL_STATIC
-        // object at the same time. The second object will be deleted
-        // immediately before anyone uses it, but we need to be
-        // careful about what we do in the constructor.
-        static QBasicAtomicInt done = Q_BASIC_ATOMIC_INITIALIZER(0);
-        if (done.testAndSetRelaxed(0, 1))
-            qAddPostRoutine(staticCleanup);
-        moveToThread(QCoreApplicationPrivate::mainThread());
-        quit = false;
-        pendingQueryId = -1;
-    }
-    inline ~QHostInfoAgent()
-    { cleanup(); }
-
-    void run();
     static QHostInfo fromName(const QString &hostName);
-
-    inline void addHostName(const QString &name, QHostInfoResult *result)
-    {
-        QMutexLocker locker(&mutex);
-        queries << new QHostInfoQuery(name, result);
-        cond.wakeOne();
-    }
-
-    inline void abortLookup(int id)
-    {
-        QMutexLocker locker(&mutex);
-        for (int i = 0; i < queries.size(); ++i) {
-            QHostInfoResult *result = queries.at(i)->object;
-            if (result->lookupId == id) {
-                result->disconnect();
-                delete queries.takeAt(i);
-                return;
-            }
-        }
-        if (pendingQueryId == id)
-            pendingQueryId = -1;
-    }
-
-    static void staticCleanup();
-
-public Q_SLOTS:
-    inline void cleanup()
-    {
-        {
-            QMutexLocker locker(&mutex);
-            qDeleteAll(queries);
-            queries.clear();
-            quit = true;
-            cond.wakeOne();
-        }
-#ifndef QT_NO_THREAD
-        if (!wait(QHOSTINFO_THREAD_WAIT)) {
-            terminate();
-            // Don't wait forever; see QTBUG-5296.
-            wait(QHOSTINFO_THREAD_WAIT);
-        }
-#endif
-    }
-
-private:
-    QList<QHostInfoQuery *> queries;
-    QMutex mutex;
-    QWaitCondition cond;
-    volatile bool quit;
-    int pendingQueryId;
 };
 
 class QHostInfoPrivate
@@ -194,6 +110,52 @@ public:
     int lookupId;
 };
 
+#ifndef QT_NO_THREAD
+// the following classes are used for the (normal) case: We use multiple threads to lookup DNS
+
+class QHostInfoRunnable : public QRunnable
+{
+public:
+    QHostInfoRunnable (QString hn, int i);
+    void run();
+
+    QString toBeLookedUp;
+    int id;
+    QHostInfoResult resultEmitter;
+};
+
+class QHostInfoLookupManager : public QObject
+{
+    Q_OBJECT
+public:
+    QHostInfoLookupManager();
+    ~QHostInfoLookupManager();
+
+    void work();
+
+    // called from QHostInfo
+    void scheduleLookup(QHostInfoRunnable *r);
+    void abortLookup(int id);
+
+    // called from QHostInfoRunnable
+    void lookupFinished(QHostInfoRunnable *r);
+    bool wasAborted(int id);
+
+protected:
+    QList<QHostInfoRunnable*> currentLookups; // in progress
+    QList<QHostInfoRunnable*> postponedLookups; // postponed because in progress for same host
+    QQueue<QHostInfoRunnable*> scheduledLookups; // not yet started
+    QList<QHostInfoRunnable*> finishedLookups; // recently finished
+    QList<int> abortedLookups; // ids of aborted lookups
+
+    QThreadPool threadPool;
+
+    QMutex mutex;
+
+    bool wasDeleted;
+};
+#endif
+
 QT_END_NAMESPACE
 
 #endif // QHOSTINFO_P_H
diff --git a/src/network/kernel/qhostinfo_win.cpp b/src/network/kernel/qhostinfo_win.cpp
index 720aaa5..727a8b0 100644
--- a/src/network/kernel/qhostinfo_win.cpp
+++ b/src/network/kernel/qhostinfo_win.cpp
@@ -105,11 +105,7 @@ static void resolveLibrary()
 #include <qmutex.h>
 QMutex qPrivCEMutex;
 #endif
-/*
-    Performs a blocking call to gethostbyname or getaddrinfo, stores
-    the results in a QHostInfo structure and emits the
-    resultsReady() signal.
-*/
+
 QHostInfo QHostInfoAgent::fromName(const QString &hostName)
 {
 #if defined(Q_OS_WINCE)
diff --git a/tests/auto/qhostinfo/tst_qhostinfo.cpp b/tests/auto/qhostinfo/tst_qhostinfo.cpp
index 4d63e10..348c41b 100644
--- a/tests/auto/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/qhostinfo/tst_qhostinfo.cpp
@@ -88,6 +88,7 @@
 #endif
 
 #include "../network-settings.h"
+#include "../../shared/util.h"
 
 //TESTED_CLASS=
 //TESTED_FILES=
@@ -124,6 +125,9 @@ private slots:
     void raceCondition();
     void threadSafety();
 
+    void multipleSameLookups();
+    void multipleDifferentLookups();
+
 protected slots:
     void resultsReady(const QHostInfo &);
 
@@ -131,6 +135,7 @@ private:
     bool ipv6LookupsAvailable;
     bool ipv6Available;
     bool lookupDone;
+    int lookupsDoneCounter;
     QHostInfo lookupResults;
 };
 
@@ -411,11 +416,53 @@ void tst_QHostInfo::threadSafety()
     }
 }
 
+// this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all,
+// not about getting correct IPs
+void tst_QHostInfo::multipleSameLookups()
+{
+    const int COUNT = 10;
+    lookupsDoneCounter = 0;
+
+    for (int i = 0; i < COUNT; i++)
+        QHostInfo::lookupHost("localhost", this, SLOT(resultsReady(const QHostInfo)));
+
+    QTRY_VERIFY(lookupsDoneCounter == COUNT);
+
+    // spin two seconds more to see if it is not more :)
+    QTestEventLoop::instance().enterLoop(2);
+    QTRY_VERIFY(lookupsDoneCounter == COUNT);
+}
+
+// this test is for the multi-threaded QHostInfo rewrite. It is about getting results at all,
+// not about getting correct IPs
+void tst_QHostInfo::multipleDifferentLookups()
+{
+    QStringList hostnameList;
+    hostnameList << "www.ovi.com" << "www.nokia.com" << "qt.nokia.com" << "www.trolltech.com" << "troll.no"
+            << "www.qtcentre.org" << "forum.nokia.com" << "www.forum.nokia.com" << "wiki.forum.nokia.com"
+            << "www.nokia.no" << "nokia.de" << "127.0.0.1" << "----";
+
+    const int COUNT = hostnameList.size();
+    lookupsDoneCounter = 0;
+
+    for (int i = 0; i < hostnameList.size(); i++)
+        QHostInfo::lookupHost(hostnameList.at(i), this, SLOT(resultsReady(const QHostInfo)));
+
+    // give some time
+    QTestEventLoop::instance().enterLoop(5);
+    // try_verify gives some more time
+    QTRY_VERIFY(lookupsDoneCounter == COUNT);
+
+    // spin two seconds more to see if it is not more than expected
+    QTestEventLoop::instance().enterLoop(2);
+    QTRY_VERIFY(lookupsDoneCounter == COUNT);
+}
+
 void tst_QHostInfo::resultsReady(const QHostInfo &hi)
 {
     lookupDone = true;
     lookupResults = hi;
-
+    lookupsDoneCounter++;
     QTestEventLoop::instance().exitLoop();
 }
 
-- 
cgit v0.12


From d64c29e18cedace91bea31d83b62e5c0b6c6049e Mon Sep 17 00:00:00 2001
From: Denis Dzyubenko <denis.dzyubenko@nokia.com>
Date: Thu, 17 Dec 2009 15:11:42 +0100
Subject: Fixed QResource to respect the explicitely set locale
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

When using QResource directly, the loader should respect the locale that the
user asked to use for the resource.

Reviewed-by: João Abecasis
---
 src/corelib/io/qresource.cpp                       |  2 +-
 tests/auto/qresourceengine/tst_qresourceengine.cpp | 22 ++++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 5c543d4..a061ad1 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -273,7 +273,7 @@ QResourcePrivate::load(const QString &file)
     QString cleaned = cleanPath(file);
     for(int i = 0; i < list->size(); ++i) {
         QResourceRoot *res = list->at(i);
-        const int node = res->findNode(cleaned);
+        const int node = res->findNode(cleaned, locale);
         if(node != -1) {
             if(related.isEmpty()) {
                 container = res->isContainer(node);
diff --git a/tests/auto/qresourceengine/tst_qresourceengine.cpp b/tests/auto/qresourceengine/tst_qresourceengine.cpp
index cc6eda3..ed7de23 100644
--- a/tests/auto/qresourceengine/tst_qresourceengine.cpp
+++ b/tests/auto/qresourceengine/tst_qresourceengine.cpp
@@ -62,6 +62,7 @@ private slots:
     void searchPath_data();
     void searchPath();
     void doubleSlashInRoot();
+    void setLocale();
 
 private:
     QString builddir;
@@ -460,6 +461,27 @@ void tst_QResourceEngine::doubleSlashInRoot()
     QVERIFY(QFile::exists("://secondary_root/runtime_resource/search_file.txt"));
 }
 
+void tst_QResourceEngine::setLocale()
+{
+    QLocale::setDefault(QLocale::c());
+
+    // default constructed QResource gets the default locale
+    QResource resource;
+    resource.setFileName("aliasdir/aliasdir.txt");
+    QVERIFY(!resource.isCompressed());
+
+    // change the default locale and make sure it doesn't affect the resource
+    QLocale::setDefault(QLocale("de_CH"));
+    QVERIFY(!resource.isCompressed());
+
+    // then explicitly set the locale on qresource
+    resource.setLocale(QLocale("de_CH"));
+    QVERIFY(resource.isCompressed());
+
+    // the reset the default locale back
+    QLocale::setDefault(QLocale::system());
+}
+
 QTEST_MAIN(tst_QResourceEngine)
 
 #include "tst_qresourceengine.moc"
-- 
cgit v0.12


From 371420d5f31a04b91c01807139d49e97db040bee Mon Sep 17 00:00:00 2001
From: Martin Smith <msmith@trolltech.com>
Date: Fri, 18 Dec 2009 10:06:20 +0100
Subject: doc: Fixed typos. Task-number: QTBUG-6898

---
 doc/src/qt4-intro.qdoc             | 2 +-
 src/activeqt/container/qaxbase.cpp | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/src/qt4-intro.qdoc b/doc/src/qt4-intro.qdoc
index fb1d0e4..a90544f 100644
--- a/doc/src/qt4-intro.qdoc
+++ b/doc/src/qt4-intro.qdoc
@@ -549,7 +549,7 @@
     the state machine, it is also easier to use the framework for
     animating GUIs, for instance.
 
-    See \l{The State Machine Framework} documentation for more infromation.
+    See \l{The State Machine Framework} documentation for more information.
 
     \section1 Multi-Touch and Gestures
 
diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp
index 3795f56..ed7ac29 100644
--- a/src/activeqt/container/qaxbase.cpp
+++ b/src/activeqt/container/qaxbase.cpp
@@ -909,7 +909,7 @@ QAxMetaObject *QAxBase::internalMetaObject() const
     \property QAxBase::control
     \brief the name of the COM object wrapped by this QAxBase object.
 
-    Setting this property initilializes the COM object. Any COM object
+    Setting this property initializes the COM object. Any COM object
     previously set is shut down.
 
     The most efficient way to set this property is by using the
-- 
cgit v0.12


From 03f28cfc174dbad3d9531b29b6dfed9983ea5d73 Mon Sep 17 00:00:00 2001
From: Benjamin Poulain <benjamin.poulain@nokia.com>
Date: Fri, 18 Dec 2009 13:42:35 +0100
Subject: Improve the performance of the Anomaly browser demo

Some minor changes to improve the demo:
-use QUrl::fromUserInput()
-scroll a surface instead of moving the widgets
 to minimize the repaint
-use the animation framework instead of QTimeLine
---
 demos/embedded/anomaly/src/BrowserWindow.cpp | 146 ++++++++++++---------------
 demos/embedded/anomaly/src/BrowserWindow.h   |  12 ++-
 2 files changed, 70 insertions(+), 88 deletions(-)

diff --git a/demos/embedded/anomaly/src/BrowserWindow.cpp b/demos/embedded/anomaly/src/BrowserWindow.cpp
index 1036735..1163b6a 100644
--- a/demos/embedded/anomaly/src/BrowserWindow.cpp
+++ b/demos/embedded/anomaly/src/BrowserWindow.cpp
@@ -43,92 +43,44 @@
 
 #include <QtCore>
 #include <QtGui>
+#include <QPropertyAnimation>
+#include <QResizeEvent>
 
 #include "BrowserView.h"
 #include "HomeView.h"
 
 BrowserWindow::BrowserWindow()
-    : QWidget()
-    , m_homeView(0)
-    , m_browserView(0)
+    : m_slidingSurface(new QWidget(this))
+    , m_homeView(new HomeView(m_slidingSurface))
+    , m_browserView(new BrowserView(m_slidingSurface))
+    , m_animation(new QPropertyAnimation(this, "slideValue"))
 {
-    m_timeLine = new QTimeLine(300, this);
-    m_timeLine->setCurveShape(QTimeLine::EaseInOutCurve);
-    QTimer::singleShot(0, this, SLOT(initialize()));
-}
-
-void BrowserWindow::initialize()
-{
-    m_homeView = new HomeView(this);
-    m_browserView = new BrowserView(this);
+    m_slidingSurface->setAutoFillBackground(true);
 
-    m_homeView->hide();
     m_homeView->resize(size());
-    m_homeView->move(0, 0);
 
-    m_browserView->hide();
     m_browserView->resize(size());
-    m_browserView->move(0, 0);
 
     connect(m_homeView, SIGNAL(addressEntered(QString)), SLOT(gotoAddress(QString)));
     connect(m_homeView, SIGNAL(urlActivated(QUrl)), SLOT(navigate(QUrl)));
 
     connect(m_browserView, SIGNAL(menuButtonClicked()), SLOT(showHomeView()));
 
-    m_homeView->setVisible(false);
-    m_browserView->setVisible(false);
-    slide(0);
+    m_animation->setDuration(200);
+    connect(m_animation, SIGNAL(finished()), SLOT(animationFinished()));
 
-    connect(m_timeLine, SIGNAL(frameChanged(int)), SLOT(slide(int)));
+    setSlideValue(0.0f);
 }
 
-
-// from Demo Browser
-QUrl guessUrlFromString(const QString &string)
+void BrowserWindow::gotoAddress(const QString &address)
 {
-    QString urlStr = string.trimmed();
-    QRegExp test(QLatin1String("^[a-zA-Z]+\\:.*"));
-
-    // Check if it looks like a qualified URL. Try parsing it and see.
-    bool hasSchema = test.exactMatch(urlStr);
-    if (hasSchema) {
-        QUrl url = QUrl::fromEncoded(urlStr.toUtf8(), QUrl::TolerantMode);
-        if (url.isValid())
-            return url;
-    }
-
-    // Might be a file.
-    if (QFile::exists(urlStr)) {
-        QFileInfo info(urlStr);
-        return QUrl::fromLocalFile(info.absoluteFilePath());
-    }
-
-    // Might be a shorturl - try to detect the schema.
-    if (!hasSchema) {
-        int dotIndex = urlStr.indexOf(QLatin1Char('.'));
-        if (dotIndex != -1) {
-            QString prefix = urlStr.left(dotIndex).toLower();
-            QString schema = (prefix == QString("ftp")) ? prefix.toLatin1() : QString("http");
-            QString location = schema + "://" + urlStr;
-            QUrl url = QUrl::fromEncoded(location.toUtf8(), QUrl::TolerantMode);
-            if (url.isValid())
-                return url;
-        }
-    }
-
-    // Fall back to QUrl's own tolerant parser.
-    QUrl url = QUrl::fromEncoded(string.toUtf8(), QUrl::TolerantMode);
-
-    // finally for cases where the user just types in a hostname add http
-    if (url.scheme().isEmpty())
-        url = QUrl::fromEncoded("http://" + string.toUtf8(), QUrl::TolerantMode);
-    return url;
+    m_browserView->navigate(QUrl::fromUserInput(address));
+    showBrowserView();
 }
 
-void BrowserWindow::gotoAddress(const QString &address)
+void BrowserWindow::animationFinished()
 {
-    m_browserView->navigate(guessUrlFromString(address));
-    showBrowserView();
+    m_animation->setDirection(QAbstractAnimation::Forward);
 }
 
 void BrowserWindow::navigate(const QUrl &url)
@@ -137,31 +89,44 @@ void BrowserWindow::navigate(const QUrl &url)
     showBrowserView();
 }
 
-void BrowserWindow::slide(int pos)
+void BrowserWindow::setSlideValue(qreal slideRatio)
 {
-    m_browserView->move(pos, 0);
-    m_homeView->move(pos - width(), 0);
-    m_browserView->show();
-    m_homeView->show();
+    // we use a ratio to handle resize corectly
+    const int pos = -qRound(slideRatio * width());
+    m_slidingSurface->scroll(pos - m_homeView->x(), 0);
+
+    if (qFuzzyCompare(slideRatio, static_cast<qreal>(1.0f))) {
+        m_browserView->show();
+        m_homeView->hide();
+    } else if (qFuzzyCompare(slideRatio, static_cast<qreal>(0.0f))) {
+        m_homeView->show();
+        m_browserView->hide();
+    } else {
+        m_browserView->show();
+        m_homeView->show();
+    }
 }
 
-void BrowserWindow::showHomeView()
+qreal BrowserWindow::slideValue() const
 {
-    if (m_timeLine->state() != QTimeLine::NotRunning)
-        return;
+    Q_ASSERT(m_slidingSurface->x() < width());
+    return static_cast<qreal>(qAbs(m_homeView->x())) / width();
+}
 
-    m_timeLine->setFrameRange(0, width());
-    m_timeLine->start();
+void BrowserWindow::showHomeView()
+{
+    m_animation->setStartValue(slideValue());
+    m_animation->setEndValue(0.0f);
+    m_animation->start();
     m_homeView->setFocus();
 }
 
 void BrowserWindow::showBrowserView()
 {
-    if (m_timeLine->state() != QTimeLine::NotRunning)
-        return;
+    m_animation->setStartValue(slideValue());
+    m_animation->setEndValue(1.0f);
+    m_animation->start();
 
-    m_timeLine->setFrameRange(width(), 0);
-    m_timeLine->start();
     m_browserView->setFocus();
 }
 
@@ -170,18 +135,31 @@ void BrowserWindow::keyReleaseEvent(QKeyEvent *event)
     QWidget::keyReleaseEvent(event);
 
     if (event->key() == Qt::Key_F3) {
-        if (m_homeView->isVisible())
-            showBrowserView();
-        else
+        if (m_animation->state() == QAbstractAnimation::Running) {
+            const QAbstractAnimation::Direction direction =  m_animation->direction() == QAbstractAnimation::Forward
+                                                             ? QAbstractAnimation::Forward
+                                                                 : QAbstractAnimation::Backward;
+            m_animation->setDirection(direction);
+        } else if (qFuzzyCompare(slideValue(), static_cast<qreal>(1.0f)))
             showHomeView();
+        else
+            showBrowserView();
+        event->accept();
     }
 }
 
 void BrowserWindow::resizeEvent(QResizeEvent *event)
 {
-    if (m_homeView)
-        m_homeView->resize(size());
+    const QSize newSize = event->size();
+    m_slidingSurface->resize(newSize.width() * 2, newSize.height());
+
+    m_homeView->resize(newSize);
+    m_homeView->move(0, 0);
+
+    m_browserView->resize(newSize);
+    m_browserView->move(newSize.width(), 0);
 
-    if (m_browserView)
-        m_browserView->resize(size());
+    const QSize oldSize = event->oldSize();
+    const qreal oldSlidingRatio = static_cast<qreal>(qAbs(m_slidingSurface->x())) / oldSize.width();
+    setSlideValue(oldSlidingRatio);
 }
diff --git a/demos/embedded/anomaly/src/BrowserWindow.h b/demos/embedded/anomaly/src/BrowserWindow.h
index 9647efb..2b77939 100644
--- a/demos/embedded/anomaly/src/BrowserWindow.h
+++ b/demos/embedded/anomaly/src/BrowserWindow.h
@@ -43,7 +43,7 @@
 #define BROWSERWINDOW_H
 
 #include <QWidget>
-class QTimeLine;
+class QPropertyAnimation;
 class QUrl;
 
 class BrowserView;
@@ -52,28 +52,32 @@ class HomeView;
 class BrowserWindow : public QWidget
 {
     Q_OBJECT
+    Q_PROPERTY(qreal slideValue READ slideValue WRITE setSlideValue)
 
 public:
     BrowserWindow();
 
 private slots:
-    void initialize();
     void navigate(const QUrl &url);
     void gotoAddress(const QString &address);
+    void animationFinished();
 
 public slots:
     void showBrowserView();
     void showHomeView();
-    void slide(int);
 
 protected:
     void keyReleaseEvent(QKeyEvent *event);
     void resizeEvent(QResizeEvent *event);
 
 private:
+    void setSlideValue(qreal);
+    qreal slideValue() const;
+
+    QWidget *m_slidingSurface;
     HomeView *m_homeView;
     BrowserView *m_browserView;
-    QTimeLine *m_timeLine;
+    QPropertyAnimation *m_animation;
 };
 
 #endif // BROWSERWINDOW_H
-- 
cgit v0.12


From 12e2c9075e694897ae52048c2069f57a22ef4031 Mon Sep 17 00:00:00 2001
From: Martin Smith <msmith@trolltech.com>
Date: Fri, 18 Dec 2009 14:23:13 +0100
Subject: doc: Added a missing \sa command, plus a \l in the text.

Task-number: QTBUG-6288
---
 src/corelib/kernel/qobject.cpp | 15 ++++++++-------
 tools/qdoc3/cppcodeparser.cpp  |  6 +++---
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 4370ee0..305ec4f 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -578,12 +578,13 @@ int QMetaCallEvent::placeMetaCall(QObject *object)
     protected functions connectNotify() and disconnectNotify() make
     it possible to track connections.
 
-    QObjects organize themselves in object trees. When you create a
-    QObject with another object as parent, the object will
-    automatically add itself to the parent's children() list. The
-    parent takes ownership of the object; i.e., it will automatically
-    delete its children in its destructor. You can look for an object
-    by name and optionally type using findChild() or findChildren().
+    QObjects organize themselves in \l {Object Trees and Object
+    Ownership} {object trees}. When you create a QObject with another
+    object as parent, the object will automatically add itself to the
+    parent's children() list. The parent takes ownership of the
+    object; i.e., it will automatically delete its children in its
+    destructor. You can look for an object by name and optionally type
+    using findChild() or findChildren().
 
     Every object has an objectName() and its class name can be found
     via the corresponding metaObject() (see QMetaObject::className()).
@@ -682,7 +683,7 @@ int QMetaCallEvent::placeMetaCall(QObject *object)
     \l{Writing Source Code for Translation} document.
 
     \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
-        {Object Trees and Object Ownership}
+    \sa {Object Trees and Object Ownership}
 */
 
 /*!
diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp
index 41a2456..9ec7fdf 100644
--- a/tools/qdoc3/cppcodeparser.cpp
+++ b/tools/qdoc3/cppcodeparser.cpp
@@ -2318,9 +2318,9 @@ void CppCodeParser::createExampleFileNodes(FakeNode *fake)
                             exampleFile.mid(sizeOfBoringPartOfName),
                             Node::File);
     foreach (const QString &imageFile, imageFiles) {
-        FakeNode* newFake = new FakeNode(fake,
-                                         imageFile.mid(sizeOfBoringPartOfName),
-                                         Node::Image);
+        new FakeNode(fake,
+                     imageFile.mid(sizeOfBoringPartOfName),
+                     Node::Image);
     }
 }
 
-- 
cgit v0.12