From 31cc1b382fbcd77def12cd0ad4fe9fc0fabdf60b Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Mon, 11 Jan 2010 11:01:18 +1000 Subject: Correctly determine QScriptValue::isQObject() for QObjects using the QScriptDeclarativeClass. Task-number: QTBUG-6178 Reviewed-by: Kent Hansen Reviewed-by: Aaron Kennedy --- src/script/api/qscriptvalue.cpp | 12 ++++++++---- src/script/bridge/qscriptdeclarativeclass.cpp | 5 +++++ src/script/bridge/qscriptdeclarativeclass_p.h | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 286230f..b9be285 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -54,6 +54,7 @@ #include "bridge/qscriptvariant_p.h" #include "bridge/qscriptqobject_p.h" #include "bridge/qscriptdeclarativeclass_p.h" +#include "bridge/qscriptdeclarativeobject_p.h" /*! \since 4.3 @@ -1570,9 +1571,10 @@ QObject *QScriptValue::toQObject() const Q_D(const QScriptValue); if (isQObject()) { QScriptObject *object = static_cast(JSC::asObject(d->jscValue)); - return static_cast(object->delegate())->value(); - } else if (QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(*this)) { - return dc->toQObject(QScriptDeclarativeClass::object(*this)); + QScriptObjectDelegate *delegate = object->delegate(); + if (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject) + return static_cast(delegate)->scriptClass()->toQObject(QScriptDeclarativeClass::object(*this)); + return static_cast(delegate)->value(); } else if (isVariant()) { QVariant var = toVariant(); int type = var.userType(); @@ -2245,7 +2247,9 @@ bool QScriptValue::isQObject() const return false; QScriptObject *object = static_cast(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = object->delegate(); - return (delegate && (delegate->type() == QScriptObjectDelegate::QtObject)); + return (delegate && (delegate->type() == QScriptObjectDelegate::QtObject || + (delegate->type() == QScriptObjectDelegate::DeclarativeClassObject && + static_cast(delegate)->scriptClass()->isQObject()))); } /*! diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index df00ce9..5e363d2 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -319,6 +319,11 @@ QStringList QScriptDeclarativeClass::propertyNames(Object *object) return QStringList(); } +bool QScriptDeclarativeClass::isQObject() const +{ + return false; +} + QObject *QScriptDeclarativeClass::toQObject(Object *, bool *ok) { if (ok) *ok = false; diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 40e5051..f2557bd 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -97,6 +97,7 @@ public: virtual QStringList propertyNames(Object *); + virtual bool isQObject() const; virtual QObject *toQObject(Object *, bool *ok = 0); virtual QVariant toVariant(Object *, bool *ok = 0); -- cgit v0.12 From 8d76de98d93421395306941e59d136f1e7395d15 Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 11 Jan 2010 14:15:56 +1000 Subject: (Sqlite2) Fix for QTBUG-6421 Forgot to port the fix over to sqlite2 which seems to also be affected by the setForwardOnly caching bug as well. Task-number: QTBUG-6421 Reviewed-by: Justin McPherson --- src/sql/drivers/sqlite2/qsql_sqlite2.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp index 1c1a411..20cb01b 100644 --- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp +++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp @@ -110,10 +110,11 @@ public: const char *currentTail; sqlite_vm *currentMachine; - uint skippedStatus: 1; // the status of the fetchNext() that's skipped - uint skipRow: 1; // skip the next fetchNext()? - uint utf8: 1; + bool skippedStatus; // the status of the fetchNext() that's skipped + bool skipRow; // skip the next fetchNext()? + bool utf8; QSqlRecord rInf; + QVector firstRow; }; static const uint initial_cache_size = 128; @@ -192,6 +193,8 @@ bool QSQLite2ResultPrivate::fetchNext(QSqlCachedResult::ValueCache &values, int // already fetched Q_ASSERT(!initialFetch); skipRow = false; + for(int i=0;iskippedStatus = d->fetchNext(cache(), 0, true); + d->skippedStatus = d->fetchNext(d->firstRow, 0, true); if (lastError().isValid()) { setSelect(false); setActive(false); -- cgit v0.12 From d8ad9ac86dac9489b553e6416329308ae7d823d0 Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Mon, 11 Jan 2010 11:11:59 +0200 Subject: Fix for QTBUG-6408 QFontEngineS60::QFontEngineS60 called hundreds of times, taking up to 1ms each call. Use S60->ScreenDevice() to get/release fonts instead of create a new screen device each time. Task-number: QTBUG-6408 Reviewed-by: Jason Barron --- src/gui/text/qfontengine_s60.cpp | 36 +++++++----------------------------- src/gui/text/qfontengine_s60_p.h | 3 --- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index e279ad2..7fad188 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -45,12 +45,11 @@ #include #include "qimage.h" #include "qt_s60_p.h" -#include "qpixmap_s60_p.h" #include #include -#include -#include +#include +#include QT_BEGIN_NAMESPACE @@ -135,42 +134,21 @@ QFontEngineS60::QFontEngineS60(const QFontDef &request, const QFontEngineS60Exte { QFontEngine::fontDef = request; m_fontSizeInPixels = (request.pixelSize >= 0)? - request.pixelSize:pointsToPixels(request.pointSize); - - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - m_textRenderBitmap = q_check_ptr(new CFbsBitmap()); // CBase derived object needs check on new - const TSize bitmapSize(1, 1); // It is just a dummy bitmap that I need to keep the font alive (or maybe not) - qt_symbian_throwIfError(m_textRenderBitmap->Create(bitmapSize, EGray256)); - QT_TRAP_THROWING(m_textRenderBitmapDevice = CFbsBitmapDevice::NewL(m_textRenderBitmap)); - qt_symbian_throwIfError(m_textRenderBitmapDevice->CreateContext(m_textRenderBitmapGc)); - cache_cost = sizeof(QFontEngineS60) + bitmapSize.iHeight * bitmapSize.iWidth * 4; + request.pixelSize:pointsToPixels(request.pointSize); TFontSpec fontSpec(qt_QString2TPtrC(request.family), m_fontSizeInPixels); fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap); fontSpec.iFontStyle.SetPosture(request.style == QFont::StyleNormal?EPostureUpright:EPostureItalic); fontSpec.iFontStyle.SetStrokeWeight(request.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal); - const TInt errorCode = m_textRenderBitmapDevice->GetNearestFontInPixels(m_font, fontSpec); + const TInt errorCode = S60->screenDevice()->GetNearestFontToDesignHeightInPixels(m_font, fontSpec); Q_ASSERT(errorCode == 0); - m_textRenderBitmapGc->UseFont(m_font); - - lock.relock(); + + cache_cost = sizeof(QFontEngineS60); } QFontEngineS60::~QFontEngineS60() { - QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); - - m_textRenderBitmapGc->DiscardFont(); - delete m_textRenderBitmapGc; - m_textRenderBitmapGc = NULL; - m_textRenderBitmapDevice->ReleaseFont(m_font); - delete m_textRenderBitmapDevice; - m_textRenderBitmapDevice = NULL; - delete m_textRenderBitmap; - m_textRenderBitmap = NULL; - - lock.relock(); + S60->screenDevice()->ReleaseFont(m_font); } bool QFontEngineS60::stringToCMap(const QChar *characters, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const diff --git a/src/gui/text/qfontengine_s60_p.h b/src/gui/text/qfontengine_s60_p.h index 9e22245..b21f1c8 100644 --- a/src/gui/text/qfontengine_s60_p.h +++ b/src/gui/text/qfontengine_s60_p.h @@ -126,9 +126,6 @@ private: QFixed glyphAdvance(HB_Glyph glyph) const; - CFbsBitmap *m_textRenderBitmap; - CFbsBitmapDevice *m_textRenderBitmapDevice; - CFbsBitGc *m_textRenderBitmapGc; CFont* m_font; const QFontEngineS60Extensions *m_extensions; qreal m_fontSizeInPixels; -- cgit v0.12 From 22d30bd6c1e8355cb4520885b0d0fef3526cc4e9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Mon, 11 Jan 2010 14:09:44 +0100 Subject: [syncqt] Make -separate-module work with WebKit's directory structure Changed the syntax to allow for the situation where the .pro file is in a different directory than the header files to install. In this case the resulting Makefile is in WebCore/Makefile, so the references in headers.pri to for example qwebview.h has to be ../WebKit/qt/Api/qwebview.h. This doesn't affect any existing syncqt operations inside of Qt. Reviewed-by: Trust me --- bin/syncqt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/syncqt b/bin/syncqt index 3ac70a4..1fb5304 100755 --- a/bin/syncqt +++ b/bin/syncqt @@ -93,7 +93,7 @@ sub showUsage print " -windows Force platform to Windows (default: " . ($force_win ? "yes" : "no") . ")\n"; print " -showonly Show action but not perform (default: " . ($showonly ? "yes" : "no") . ")\n"; print " -outdir Specify output directory for sync (default: $out_basedir)\n"; - print " -separate-module : Create headers for with original headers in \n"; + print " -separate-module :: Create headers for with original headers in relative to \n"; print " -help This help\n"; exit 0; } @@ -646,10 +646,10 @@ while ( @ARGV ) { die "No such module: $val" unless(defined $modules{$val}); push @modules_to_sync, $val; } elsif ("$var" eq "separate-module") { - my ($module, $srcdir) = split(/:/, $val); - $modules{$module} = $srcdir; + my ($module, $prodir, $headerdir) = split(/:/, $val); + $modules{$module} = $prodir; push @modules_to_sync, $module; - delete $moduleheaders{$module} if ($moduleheaders{$module}); + $moduleheaders{$module} = $headerdir; $create_uic_class_map = 0; $create_private_headers = 0; } elsif ("$var" eq "output") { -- cgit v0.12 From a56a9b9d84c40de55255fc58be1ae80cdfaa0c35 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 11 Jan 2010 14:34:13 +0100 Subject: network internals: fix build on S60 Reviewed-by: Paul --- src/network/access/qnetworkaccesshttpbackend.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index ada00df..dacb2bb 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -596,7 +596,7 @@ void QNetworkAccessHttpBackend::open() // unsuitable proxies QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(QNetworkReply::NetworkError, QNetworkReply::ProxyNotFoundError), - Q_ARG(QString, QCoreApplication::translate("QNetworkAccessHttpBackend", "No suitable proxy found"))); + Q_ARG(QString, tr("No suitable proxy found"))); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); return; } -- cgit v0.12 From 7bd7dabe915df8833601a48de3fee6ad7fac82e9 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 13:54:35 +0100 Subject: QNAM HTTP: Check if socket already tries to connect. This should get rid of QAbstractSocket warnings we sometimes emit. Reviewed-by: Thiago Reviewed-by: Peter Hartmann --- src/network/access/qhttpnetworkconnectionchannel.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 7cf632f..b612d26 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -419,15 +419,22 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() bool QHttpNetworkConnectionChannel::ensureConnection() { + // resend this request after we receive the disconnected signal + if (socket->state() == QAbstractSocket::ClosingState) { + resendCurrent = true; + return false; + } + + // already trying to connect? + if (socket->state() == QAbstractSocket::HostLookupState || + socket->state() == QAbstractSocket::ConnectingState) { + return false; + } + // make sure that this socket is in a connected state, if not initiate // connection to the host. if (socket->state() != QAbstractSocket::ConnectedState) { // connect to the host if not already connected. - // resend this request after we receive the disconnected signal - if (socket->state() == QAbstractSocket::ClosingState) { - resendCurrent = true; - return false; - } state = QHttpNetworkConnectionChannel::ConnectingState; pendingEncrypt = connection->d_func()->encrypt; -- cgit v0.12 From e2a94baeed03edbaeea9b4658f2a820520e1363f Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 14:10:04 +0100 Subject: QNAM HTTP: Optimize eatWhitespace() Avoid calling socket->bytesAvailable(). Reviewed-by: Thiago --- src/network/access/qhttpnetworkconnectionchannel.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index b612d26..53c2596 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -625,10 +625,17 @@ void QHttpNetworkConnectionChannel::requeueCurrentlyPipelinedRequests() void QHttpNetworkConnectionChannel::eatWhitespace() { char c; - while (socket->bytesAvailable()) { - if (socket->peek(&c, 1) != 1) + do { + qint64 ret = socket->peek(&c, 1); + + // nothing read, fine. + if (ret == 0) return; + // EOF from socket? + if (ret == -1) + return; // FIXME, we need to stop processing. however the next stuff done will also do that. + // read all whitespace and line endings if (c == 11 || c == '\n' || c == '\r' || c == ' ' || c == 31) { socket->read(&c, 1); @@ -636,7 +643,7 @@ void QHttpNetworkConnectionChannel::eatWhitespace() } else { break; } - } + } while(true); } void QHttpNetworkConnectionChannel::handleStatus() -- cgit v0.12 From 36dcdcdf5b6869ded0401a879b1397ad9d20b324 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 13:24:15 +0100 Subject: QNAM HTTP: Fix readBuffer maximum size. QHttpNetworkReply has now a throttled mode. If this is activated, it will only read HTTP body when its internal buffer is empty. This means that QNetworkReply.setReadBufferSize() can finally be used for bandwidth limiting. Thanks to David Faure for helping out. Reviewed-By: Peter Hartmann --- src/network/access/qhttpnetworkconnection.cpp | 10 ++ src/network/access/qhttpnetworkconnection_p.h | 3 + .../access/qhttpnetworkconnectionchannel.cpp | 10 ++ src/network/access/qhttpnetworkreply.cpp | 12 +- src/network/access/qhttpnetworkreply_p.h | 2 + src/network/access/qnetworkaccessbackend.cpp | 6 + src/network/access/qnetworkaccessbackend_p.h | 1 + src/network/access/qnetworkaccesshttpbackend.cpp | 6 + src/network/access/qnetworkaccesshttpbackend_p.h | 2 + src/network/access/qnetworkreplyimpl.cpp | 3 + tests/manual/qnetworkreply/main.cpp | 130 +++++++++++++++++++++ tests/manual/qnetworkreply/qnetworkreply.pro | 13 +++ 12 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 tests/manual/qnetworkreply/main.cpp create mode 100644 tests/manual/qnetworkreply/qnetworkreply.pro diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 2c56524..b7dbeac 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -731,6 +731,16 @@ void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests() } } +void QHttpNetworkConnectionPrivate::readMoreLater(QHttpNetworkReply *reply) +{ + for (int i = 0 ; i < channelCount; ++i) { + if (channels[i].reply == reply) { + // emulate a readyRead() from the socket + QMetaObject::invokeMethod(&channels[i], "_q_readyRead", Qt::QueuedConnection); + return; + } + } +} QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent) : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 00eb1ef..76da883 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -174,6 +174,9 @@ public: void fillPipeline(QAbstractSocket *socket); bool fillPipeline(QList &queue, QHttpNetworkConnectionChannel &channel); + // read more HTTP body after the next event loop spin + void readMoreLater(QHttpNetworkReply *reply); + void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy); // private slots diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 53c2596..b1b0304 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -350,6 +350,16 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } break; case QHttpNetworkReplyPrivate::ReadingDataState: { + if (reply->d_func()->downstreamLimited && !reply->d_func()->responseData.isEmpty() && reply->d_func()->shouldEmitSignals()) { + // We already have some HTTP body data. We don't read more from the socket until + // this is fetched by QHttpNetworkAccessHttpBackend. If we would read more, + // we could not limit our read buffer usage. + // We only do this when shouldEmitSignals==true because our HTTP parsing + // always needs to parse the 401/407 replies. Therefore they don't really obey + // to the read buffer maximum size, but we don't care since they should be small. + return; + } + if (!reply->d_func()->isChunked() && !reply->d_func()->autoDecompress && reply->d_func()->bodyLength > 0) { // bulk files like images should fulfill these properties and diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 7025f1d..a5223d1 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -179,9 +179,19 @@ qint64 QHttpNetworkReply::bytesAvailableNextBlock() const QByteArray QHttpNetworkReply::readAny() { Q_D(QHttpNetworkReply); + // we'll take the last buffer, so schedule another read from http + if (d->downstreamLimited && d->responseData.bufferCount() == 1) + d->connection->d_func()->readMoreLater(this); return d->responseData.read(); } +void QHttpNetworkReply::setDownstreamLimited(bool dsl) +{ + Q_D(QHttpNetworkReply); + d->downstreamLimited = dsl; + d->connection->d_func()->readMoreLater(this); +} + bool QHttpNetworkReply::isFinished() const { return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState; @@ -201,7 +211,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl) forceConnectionCloseEnabled(false), currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false), autoDecompress(false), responseData(), requestIsPrepared(false) - ,pipeliningUsed(false) + ,pipeliningUsed(false), downstreamLimited(false) { } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index a8b4a79..af9266b 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -125,6 +125,7 @@ public: qint64 bytesAvailable() const; qint64 bytesAvailableNextBlock() const; QByteArray readAny(); + void setDownstreamLimited(bool t); bool isFinished() const; @@ -229,6 +230,7 @@ public: bool requestIsPrepared; bool pipeliningUsed; + bool downstreamLimited; }; diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index de947e8..8ac64d2 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -161,6 +161,12 @@ void QNetworkAccessBackend::downstreamReadyWrite() // do nothing } +void QNetworkAccessBackend::setDownstreamLimited(bool b) +{ + Q_UNUSED(b); + // do nothing +} + void QNetworkAccessBackend::copyFinished(QIODevice *) { // do nothing diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 30ef5b3..43d993c 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -116,6 +116,7 @@ public: // slot-like: virtual void downstreamReadyWrite(); + virtual void setDownstreamLimited(bool b); virtual void copyFinished(QIODevice *); virtual void ignoreSslErrors(); virtual void ignoreSslErrors(const QList &errors); diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index dacb2bb..a639e0d 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -657,6 +657,12 @@ void QNetworkAccessHttpBackend::downstreamReadyWrite() replyFinished(); } +void QNetworkAccessHttpBackend::setDownstreamLimited(bool b) +{ + if (httpReply) + httpReply->setDownstreamLimited(b); +} + void QNetworkAccessHttpBackend::replyReadyRead() { readFromHttp(); diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index 705323d..0eaf003 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -82,6 +82,8 @@ public: virtual bool waitForDownstreamReadyRead(int msecs); virtual void downstreamReadyWrite(); + virtual void setDownstreamLimited(bool b); + virtual void copyFinished(QIODevice *); #ifndef QT_NO_OPENSSL virtual void ignoreSslErrors(); diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 285864d..59c7d76 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -652,6 +652,9 @@ void QNetworkReplyImpl::setReadBufferSize(qint64 size) d->backendNotify(QNetworkReplyImplPrivate::NotifyDownstreamReadyWrite); QNetworkReply::setReadBufferSize(size); + + if (d->backend) + d->backend->setDownstreamLimited(d->readBufferMaxSize > 0); } #ifndef QT_NO_OPENSSL diff --git a/tests/manual/qnetworkreply/main.cpp b/tests/manual/qnetworkreply/main.cpp new file mode 100644 index 0000000..015d66e --- /dev/null +++ b/tests/manual/qnetworkreply/main.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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 test suite 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$ +** +****************************************************************************/ +// This file contains benchmarks for QNetworkReply functions. + +#include +#include +#include +#include +#include +#include +#include "../../auto/network-settings.h" + +#define BANDWIDTH_LIMIT_BYTES (1024*100) +#define TIME_ESTIMATION_SECONDS (97) + +class tst_qnetworkreply : public QObject +{ + Q_OBJECT + private slots: + void limiting_data(); + void limiting(); + +}; + +QNetworkReply *reply; + +class HttpReceiver : public QObject +{ + Q_OBJECT + public slots: + void finishedSlot() { + quint64 bytesPerSec = (reply->header(QNetworkRequest::ContentLengthHeader).toLongLong()) / (stopwatch.elapsed() / 1000.0); + qDebug() << "Finished HTTP(S) request with" << bytesPerSec << "bytes/sec"; + QVERIFY(bytesPerSec < BANDWIDTH_LIMIT_BYTES*1.05); + QVERIFY(bytesPerSec > BANDWIDTH_LIMIT_BYTES*0.95); + timer->stop(); + QTestEventLoop::instance().exitLoop(); + } + void readyReadSlot() { + } + void timeoutSlot() { + reply->read(BANDWIDTH_LIMIT_BYTES).size(); + } + void startTimer() { + stopwatch.start(); + timer = new QTimer(this); + QObject::connect(timer, SIGNAL(timeout()), this, SLOT(timeoutSlot())); + timer->start(1000); + } +protected: + QTimer *timer; + QTime stopwatch; +}; + +void tst_qnetworkreply::limiting_data() +{ + QTest::addColumn("url"); + + QTest::newRow("HTTP") << QUrl("http://" + QtNetworkSettings::serverName() + "/mediumfile"); +#ifndef QT_NO_OPENSSL + QTest::newRow("HTTP+SSL") << QUrl("https://" + QtNetworkSettings::serverName() + "/mediumfile"); +#endif + +} + +void tst_qnetworkreply::limiting() +{ + HttpReceiver receiver; + QNetworkAccessManager manager; + + QFETCH(QUrl, url); + QNetworkRequest req (url); + + qDebug() << "Starting. This will take a while (around" << TIME_ESTIMATION_SECONDS << "sec)."; + qDebug() << "Please check the actual bandwidth usage with a network monitor, e.g. the KDE"; + qDebug() << "network plasma widget. It should be around" << BANDWIDTH_LIMIT_BYTES << "bytes/sec."; + reply = manager.get(req); + reply->ignoreSslErrors(); + reply->setReadBufferSize(BANDWIDTH_LIMIT_BYTES); + QObject::connect(reply, SIGNAL(readyRead()), &receiver, SLOT(readyReadSlot())); + QObject::connect(reply, SIGNAL(finished()), &receiver, SLOT(finishedSlot())); + receiver.startTimer(); + + // event loop + QTestEventLoop::instance().enterLoop(TIME_ESTIMATION_SECONDS + 20); + QVERIFY(!QTestEventLoop::instance().timeout()); +} + + +QTEST_MAIN(tst_qnetworkreply) + +#include "main.moc" diff --git a/tests/manual/qnetworkreply/qnetworkreply.pro b/tests/manual/qnetworkreply/qnetworkreply.pro new file mode 100644 index 0000000..060acf5 --- /dev/null +++ b/tests/manual/qnetworkreply/qnetworkreply.pro @@ -0,0 +1,13 @@ +load(qttest_p4) +TEMPLATE = app +TARGET = tst_qnetworkreply +DEPENDPATH += . +INCLUDEPATH += . + +QT -= gui +QT += network + +CONFIG += release + +# Input +SOURCES += main.cpp -- cgit v0.12 From 96827cf7675c8555a97ff6b3ec8083940e27a41d Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 15:36:01 +0100 Subject: QNAM HTTP: Don't call d_func() so often Reviewed-by: Peter Hartmann --- .../access/qhttpnetworkconnectionchannel.cpp | 57 ++++++++++++---------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index b1b0304..da305a0 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -326,31 +326,34 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() lastStatus = reply->d_func()->statusCode; break; } - case QHttpNetworkReplyPrivate::ReadingHeaderState: - bytes += reply->d_func()->readHeader(socket); - if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) { - if (reply->d_func()->isGzipped() && reply->d_func()->autoDecompress) { + case QHttpNetworkReplyPrivate::ReadingHeaderState: { + QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); + bytes += replyPrivate->readHeader(socket); + if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) { + if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) { // remove the Content-Length from header - reply->d_func()->removeAutoDecompressHeader(); + replyPrivate->removeAutoDecompressHeader(); } else { - reply->d_func()->autoDecompress = false; + replyPrivate->autoDecompress = false; } - if (reply && reply->d_func()->statusCode == 100) { - reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState; + if (replyPrivate->statusCode == 100) { + replyPrivate->state = QHttpNetworkReplyPrivate::ReadingStatusState; break; // ignore } - if (reply->d_func()->shouldEmitSignals()) + if (replyPrivate->shouldEmitSignals()) emit reply->headerChanged(); - if (!reply->d_func()->expectContent()) { - reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState; + if (!replyPrivate->expectContent()) { + replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState; this->state = QHttpNetworkConnectionChannel::IdleState; allDone(); return; } } break; + } case QHttpNetworkReplyPrivate::ReadingDataState: { - if (reply->d_func()->downstreamLimited && !reply->d_func()->responseData.isEmpty() && reply->d_func()->shouldEmitSignals()) { + QHttpNetworkReplyPrivate *replyPrivate = reply->d_func(); + if (replyPrivate->downstreamLimited && !replyPrivate->responseData.isEmpty() && replyPrivate->shouldEmitSignals()) { // We already have some HTTP body data. We don't read more from the socket until // this is fetched by QHttpNetworkAccessHttpBackend. If we would read more, // we could not limit our read buffer usage. @@ -360,19 +363,19 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() return; } - if (!reply->d_func()->isChunked() && !reply->d_func()->autoDecompress - && reply->d_func()->bodyLength > 0) { + if (!replyPrivate->isChunked() && !replyPrivate->autoDecompress + && replyPrivate->bodyLength > 0) { // bulk files like images should fulfill these properties and // we can therefore save on memory copying - bytes = reply->d_func()->readBodyFast(socket, &reply->d_func()->responseData); - reply->d_func()->totalProgress += bytes; - if (reply->d_func()->shouldEmitSignals()) { + bytes = replyPrivate->readBodyFast(socket, &replyPrivate->responseData); + replyPrivate->totalProgress += bytes; + if (replyPrivate->shouldEmitSignals()) { QPointer replyPointer = reply; emit reply->readyRead(); // make sure that the reply is valid if (replyPointer.isNull()) return; - emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); + emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); // make sure that the reply is valid if (replyPointer.isNull()) return; @@ -383,16 +386,16 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // use the traditional slower reading (for compressed encoding, chunked encoding, // no content-length etc) QByteDataBuffer byteDatas; - bytes = reply->d_func()->readBody(socket, &byteDatas); + bytes = replyPrivate->readBody(socket, &byteDatas); if (bytes) { - if (reply->d_func()->autoDecompress) - reply->d_func()->appendCompressedReplyData(byteDatas); + if (replyPrivate->autoDecompress) + replyPrivate->appendCompressedReplyData(byteDatas); else - reply->d_func()->appendUncompressedReplyData(byteDatas); + replyPrivate->appendUncompressedReplyData(byteDatas); - if (!reply->d_func()->autoDecompress) { - reply->d_func()->totalProgress += bytes; - if (reply->d_func()->shouldEmitSignals()) { + if (!replyPrivate->autoDecompress) { + replyPrivate->totalProgress += bytes; + if (replyPrivate->shouldEmitSignals()) { QPointer replyPointer = reply; // important: At the point of this readyRead(), the byteDatas list must be empty, // else implicit sharing will trigger memcpy when the user is reading data! @@ -400,7 +403,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // make sure that the reply is valid if (replyPointer.isNull()) return; - emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); + emit reply->dataReadProgress(replyPrivate->totalProgress, replyPrivate->bodyLength); // make sure that the reply is valid if (replyPointer.isNull()) return; @@ -413,7 +416,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() #endif } } - if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) + if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) break; // everything done, fall through } -- cgit v0.12 From d1fe5a2c0b9d21b32e9d65b59f120776a79d022c Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 11 Jan 2010 15:23:06 +0100 Subject: fix typo in qreadwritelock's documentation Merge-request: 426 Reviewed-by: Thiago Macieira --- src/corelib/thread/qreadwritelock.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index 3463eab..bd07a97 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -82,7 +82,7 @@ QT_BEGIN_NAMESPACE Like QMutex, a QReadWriteLock can be recursively locked by the same thread when constructed in - \l{QReadWriteLock::RecursionMode}recursive mode}. In such cases, + \l{QReadWriteLock::RecursionMode}. In such cases, unlock() must be called the same number of times lockForWrite() or lockForRead() was called. Note that the lock type cannot be changed when trying to lock recursively, i.e. it is not possible @@ -266,12 +266,12 @@ bool QReadWriteLock::tryLockForRead(int timeout) return true; } - /*! +/*! Locks the lock for writing. This function will block the current thread if another thread has locked for reading or writing. \sa unlock() lockForRead() tryLockForWrite() - */ +*/ void QReadWriteLock::lockForWrite() { QMutexLocker lock(&d->mutex); -- cgit v0.12 From 02c6e391176f448ea2a45415140f432851aa376a Mon Sep 17 00:00:00 2001 From: Bernhard Rosenkraenzer Date: Mon, 11 Jan 2010 15:33:00 +0100 Subject: Fix code example The example given for QAudioOutput doesn't actually compile: QAudioOutput::start takes a pointer to a QIODevice, but it's passed a QFile (not the pointer). Merge-request: 418 Reviewed-by: Thiago Macieira --- src/multimedia/audio/qaudiooutput.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/multimedia/audio/qaudiooutput.cpp b/src/multimedia/audio/qaudiooutput.cpp index 613056c..b61aa4f 100644 --- a/src/multimedia/audio/qaudiooutput.cpp +++ b/src/multimedia/audio/qaudiooutput.cpp @@ -98,7 +98,7 @@ QT_BEGIN_NAMESPACE audio = new QAudioOutput(format, this); connect(audio,SIGNAL(stateChanged(QAudio::State)),SLOT(finishedPlaying(QAudio::State))); - audio->start(inputFile); + audio->start(&inputFile); \endcode -- cgit v0.12 From 088e1bce77aa2e780a79237b94393082490d771c Mon Sep 17 00:00:00 2001 From: Andre Pedralho Date: Mon, 11 Jan 2010 16:32:47 +0100 Subject: Added the 'framecapture' WebKit example to the default build. Merge-request: 2235 Reviewed-by: Thiago Macieira Reviewed-by: Simon Hausmann --- examples/webkit/webkit.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/webkit/webkit.pro b/examples/webkit/webkit.pro index c985ed5..76c8801 100644 --- a/examples/webkit/webkit.pro +++ b/examples/webkit/webkit.pro @@ -3,7 +3,8 @@ SUBDIRS += domtraversal \ formextractor \ previewer \ fancybrowser \ - simpleselector + simpleselector \ + framecapture contains(QT_CONFIG, openssl):SUBDIRS += googlechat -- cgit v0.12 From a6592a167c2c4d2714d701e49d332217749124f4 Mon Sep 17 00:00:00 2001 From: Ritt Konstantin Date: Mon, 11 Jan 2010 16:48:11 +0100 Subject: typo fix Merge-request: 2077 Reviewed-by: Thiago Macieira --- src/gui/itemviews/qtreeview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index e9643aa..efb8422 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -178,7 +178,7 @@ QT_BEGIN_NAMESPACE */ /*! - Constructs a table view with a \a parent to represent a model's + Constructs a tree view with a \a parent to represent a model's data. Use setModel() to set the model. \sa QAbstractItemModel -- cgit v0.12 From f10a3a1008c2ccbfbdf7f3e0cfe6af34c8a7db9c Mon Sep 17 00:00:00 2001 From: Jani Hautakangas Date: Mon, 11 Jan 2010 17:52:31 +0200 Subject: Fix for QTBUG-7267 Qs60Style::drawControl() does not align CE_ItemViewItem control element correctly if given widget is null. Uses now alignment hint value given in style option. Task-number: QTBUG-7267 Reviewed-by: Janne Koskinen --- src/gui/styles/qs60style.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index bcc993a..d78ea21 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -1363,7 +1363,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option, } } - int rightValue = widget ? widget->contentsRect().right() : 0; + int rightValue = widget ? widget->contentsRect().right() : voptAdj.rect.right(); if (isScrollBarVisible) rightValue -= scrollBarWidth; -- cgit v0.12 From 14412557e7523ca39698ca4f4aa40ebe9c051d77 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 16:09:12 +0100 Subject: QNAM HTTP Code: When starting new request, prefer connected sockets. Prefer a QHttpNetworkConnectionChannel which has a connected socket to a channel which doesn't have a connected socket. Reviewed-by: Peter Hartmann --- src/network/access/qhttpnetworkconnection.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index b7dbeac..20baac8 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -691,19 +691,31 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() channels[i].sendRequest(); } } + + // dequeue new ones + QAbstractSocket *socket = 0; for (int i = 0; i < channelCount; ++i) { QAbstractSocket *chSocket = channels[i].socket; - // send the request using the idle socket - if (!channels[i].isSocketBusy()) { + // try to get a free AND connected socket + if (!channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) { socket = chSocket; + dequeueAndSendRequest(socket); break; } } - // this socket is free, - if (socket) - dequeueAndSendRequest(socket); + if (!socket) { + for (int i = 0; i < channelCount; ++i) { + QAbstractSocket *chSocket = channels[i].socket; + // try to get a free unconnected socket + if (!channels[i].isSocketBusy()) { + socket = chSocket; + dequeueAndSendRequest(socket); + break; + } + } + } // try to push more into all sockets // ### FIXME we should move this to the beginning of the function -- cgit v0.12 From c69b85ebf532bf7daf0644f4b3d0b2a6c19ace1d Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 17:49:02 +0100 Subject: tst_qhttpnetworkconnection: Relax condition in getMultipleWithPriorities Test failed in 1 out of 5 cases. Relax the condition. It is not that bad if some (max connection count + 1) low priority requests finish first. Reviewed-by: Peter Hartmann --- tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index 6fa09d5..cafbc2c 100644 --- a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -939,7 +939,7 @@ public Q_SLOTS: else QFAIL("Wrong priority!?"); - QVERIFY(highPrioReceived >= lowPrioReceived); + QVERIFY(highPrioReceived + 7 >= lowPrioReceived); if (highPrioReceived + lowPrioReceived == requestCount) QTestEventLoop::instance().exitLoop(); -- cgit v0.12 From 1b1aab443117f818914ed2434a5ea7a1002d4cc9 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 17:58:52 +0100 Subject: tst_qhttpnetworkconnection: Test also HEAD in some tests Reviewed-by: TrustMe --- .../qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp index cafbc2c..f27f469 100644 --- a/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp +++ b/tests/auto/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp @@ -866,8 +866,11 @@ void tst_QHttpNetworkConnection::getMultipleWithPipeliningAndMultiplePriorities( QList replies; for (int i = 0; i < requestCount; i++) { - - QHttpNetworkRequest *request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt"); + QHttpNetworkRequest *request = 0; + if (i % 3) + request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Get); + else + request = new QHttpNetworkRequest("http://" + QtNetworkSettings::serverName() + "/qtest/rfc3252.txt", QHttpNetworkRequest::Head); if (i % 2 || i % 3) request->setPipeliningAllowed(true); @@ -957,7 +960,11 @@ void tst_QHttpNetworkConnection::getMultipleWithPriorities() QList replies; for (int i = 0; i < requestCount; i++) { - QHttpNetworkRequest *request = new QHttpNetworkRequest(url);; + QHttpNetworkRequest *request = 0; + if (i % 3) + request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Get); + else + request = new QHttpNetworkRequest(url, QHttpNetworkRequest::Head); if (i % 2) request->setPriority(QHttpNetworkRequest::HighPriority); -- cgit v0.12 From 3efc651f6695ec224374bf29ad5b695a8e492a65 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 11 Jan 2010 19:49:43 +0100 Subject: QNAM HTTP Code: Cache socket state inside ensureConnection() Reviewed-by: TrustMe --- src/network/access/qhttpnetworkconnectionchannel.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index da305a0..39d09aa 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -432,21 +432,23 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() bool QHttpNetworkConnectionChannel::ensureConnection() { + QAbstractSocket::SocketState socketState = socket->state(); + // resend this request after we receive the disconnected signal - if (socket->state() == QAbstractSocket::ClosingState) { + if (socketState == QAbstractSocket::ClosingState) { resendCurrent = true; return false; } // already trying to connect? - if (socket->state() == QAbstractSocket::HostLookupState || - socket->state() == QAbstractSocket::ConnectingState) { + if (socketState == QAbstractSocket::HostLookupState || + socketState == QAbstractSocket::ConnectingState) { return false; } // make sure that this socket is in a connected state, if not initiate // connection to the host. - if (socket->state() != QAbstractSocket::ConnectedState) { + if (socketState != QAbstractSocket::ConnectedState) { // connect to the host if not already connected. state = QHttpNetworkConnectionChannel::ConnectingState; pendingEncrypt = connection->d_func()->encrypt; -- cgit v0.12 From 8b56ffee8bb4ec0c56c2c05ccc1e088f6d9ae8a8 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 12 Jan 2010 09:42:00 +0100 Subject: Prevent a crash when creating an inputContext from the QApplication dtor. Complete the fix in f72165460d27860cabd51691f4d935fd74b50f80 by applying the same fix to Symbian and QWS. Task-number: QTBUG-7105 Reviewed-by: Alexis Reviewed-by: Jason McDonald --- src/gui/kernel/qwidget_qws.cpp | 2 +- src/gui/kernel/qwidget_s60.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp index 1f1dac6..b827e8b 100644 --- a/src/gui/kernel/qwidget_qws.cpp +++ b/src/gui/kernel/qwidget_qws.cpp @@ -287,7 +287,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) } else { // release previous focus information participating with // preedit preservation of qic -- while we still have a winId - QInputContext *qic = inputContext(); + QInputContext *qic = QApplicationPrivate::inputContext; if (qic) qic->widgetDestroyed(this); } diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 75c2e31..c65a162 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -1152,7 +1152,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows) if (d->ic) { delete d->ic; } else { - QInputContext *ic = inputContext(); + QInputContext *ic = QApplicationPrivate::inputContext; if (ic) { ic->widgetDestroyed(this); } -- cgit v0.12 From 2efba0002d26b584c771aa9260e6d699e5ff8da3 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Tue, 12 Jan 2010 10:03:50 +0100 Subject: doc: update snippets for QtScript function expressions With the JSC-based back-end it's necessary to wrap the function in parentheses. Task-number: QTBUG-6644 --- doc/src/snippets/code/doc_src_qtscript.qdoc | 6 +++--- doc/src/snippets/code/src_script_qscriptengine.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/src/snippets/code/doc_src_qtscript.qdoc b/doc/src/snippets/code/doc_src_qtscript.qdoc index 00dd716..a33a982 100644 --- a/doc/src/snippets/code/doc_src_qtscript.qdoc +++ b/doc/src/snippets/code/doc_src_qtscript.qdoc @@ -513,7 +513,7 @@ int main(int argc, char **argv) //! [47] QScriptEngine eng; QLineEdit *edit = new QLineEdit(...); -QScriptValue handler = eng.evaluate("function(text) { print('text was changed to', text); }"); +QScriptValue handler = eng.evaluate("(function(text) { print('text was changed to', text); })"); qScriptConnect(edit, SIGNAL(textChanged(const QString &)), QScriptValue(), handler); //! [47] @@ -521,7 +521,7 @@ qScriptConnect(edit, SIGNAL(textChanged(const QString &)), QScriptValue(), handl QLineEdit *edit1 = new QLineEdit(...); QLineEdit *edit2 = new QLineEdit(...); -QScriptValue handler = eng.evaluate("function() { print('I am', this.name); }"); +QScriptValue handler = eng.evaluate("(function() { print('I am', this.name); })"); QScriptValue obj1 = eng.newObject(); obj1.setProperty("name", "the walrus"); QScriptValue obj2 = eng.newObject(); @@ -790,7 +790,7 @@ QScriptValue counter_hybrid(QScriptContext *ctx, QScriptEngine *eng) { QScriptValue act = ctx->activationObject(); act.setProperty("count", 0); - return eng->evaluate("function() { return count++; }"); + return eng->evaluate("(function() { return count++; })"); } //! [74] diff --git a/doc/src/snippets/code/src_script_qscriptengine.cpp b/doc/src/snippets/code/src_script_qscriptengine.cpp index c82eb65..f0165fd 100644 --- a/doc/src/snippets/code/src_script_qscriptengine.cpp +++ b/doc/src/snippets/code/src_script_qscriptengine.cpp @@ -46,7 +46,7 @@ QScriptValue three = myEngine.evaluate("1 + 2"); //! [1] -QScriptValue fun = myEngine.evaluate("function(a, b) { return a + b; }"); +QScriptValue fun = myEngine.evaluate("(function(a, b) { return a + b; })"); QScriptValueList args; args << 1 << 2; QScriptValue threeAgain = fun.call(QScriptValue(), args); -- cgit v0.12 From eef74a19b867f307d7a0c0c47f3ee0ce2c4d283e Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 12 Jan 2010 11:31:34 +0100 Subject: my 4.6.1 changelog contributions --- dist/changes-4.6.1 | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/dist/changes-4.6.1 b/dist/changes-4.6.1 index 145e09e..b1eb6e2 100644 --- a/dist/changes-4.6.1 +++ b/dist/changes-4.6.1 @@ -46,6 +46,10 @@ QtCore QtGui ----- + - QApplication + * [QTBUG-6654] Fix crashes when deleting QWidgets in touch event + handlers. + - QPixmap * load() and loadFromData() can now support compressed GL textures in the DDS, ETC1, PVRTC2, and PVRTC4 formats if the OpenGL graphics @@ -54,6 +58,10 @@ QtGui - QGraphicsObject * 'id' property was removed. Use the 'objectName' property instead. + - QGraphicsScene + * [QTBUG-6654] Fix crashes when deleting QGraphicsItems in touch + event handlers. + QtDBus ------ @@ -118,12 +126,23 @@ Qt for Unix (X11 and Mac OS X) Qt for Linux/X11 ---------------- - - + - QGuiEventDispatcherGlib (internal class) + * Fix regression introduced in 4.6.0 that could cause X11 event + processing to starve timer events. + + - QFileSystemWatcher + * [QTBUG-4840] Fix memory leak in the dnotify implementation. Qt for Windows -------------- - - + - QAtomicPointer + * [QTBUG-6079] Fix compilation for 64-bit Windows targets. + + - QEventDispatchWin32 (internal class) + * [QTBUG-6083] Fix a performance regression introduced in 4.6.0 + that would cause all Qt posted events to be sent at 15-16ms + intervals (instead of as quickly as possible). Qt for Mac OS X --------------- -- cgit v0.12 From d1f73b7be62b0f6e9294b5d78ccd0680cb9fe118 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 12 Jan 2010 12:14:41 +0100 Subject: Update changelog with some of my stuff --- dist/changes-4.6.1 | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/dist/changes-4.6.1 b/dist/changes-4.6.1 index b1eb6e2..5255894 100644 --- a/dist/changes-4.6.1 +++ b/dist/changes-4.6.1 @@ -40,8 +40,11 @@ Optimizations QtCore ------ - - foo - * bar + - QFile + * Improve performance of getting the canonical filename on Linux + and Symbian by using realpath() system call + * Avoid stat() when opening a file + QtGui ----- @@ -71,8 +74,18 @@ QtDBus QtNetwork --------- - - foo - * bar + - QNetworkAccessManager + * HTTP: Smaller improvements + * HTTP: Send our locale with the HTTP request + * HTTP: Start Accept-language and Authorization header with capital letter + * file: Introduce special subclass for higher performance with file:// URLs + - QTcpSocket + * [QTBUG-5799] Fix waitForConnected() on Windows + - QNetworkProxyFactory + * Fixed systemProxyForQuery(), it could sometimes return invalid empty list + on Windows + - QHostInfo + * Use 5 parallel threads for host lookup instead of 1 QtOpenGL -------- -- cgit v0.12 From 04bdf9f6a77e9ebf96431f89b8240a037b3d2b09 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 12 Jan 2010 12:28:22 +0100 Subject: Updated WebKit from /home/shausman/src/webkit/trunk to qtwebkit/qtwebkit-4.6 ( bd6591b4acaf2172ab05702153ef539c0ac89cbb ) Changes in WebKit/qt since the last update: ++ b/WebKit/qt/ChangeLog 2009-12-18 Joe Ligman Reviewed by Kenneth Rohde Christiansen. [Qt] Add new API to QWebFrame to scrollRecursively starting with any css overflow then checking current frame and then ancestors https://bugs.webkit.org/show_bug.cgi?id=32668 * Api/qwebframe.cpp: (QWebFramePrivate::scrollOverflow): (QWebFrame::scrollRecursively): * Api/qwebframe.h: * Api/qwebframe_p.h: * tests/qwebframe/qwebframe.qrc: * tests/qwebframe/testiframe.html: Added. * tests/qwebframe/testiframe2.html: Added. * tests/qwebframe/tst_qwebframe.cpp: --- src/3rdparty/webkit/VERSION | 2 +- src/3rdparty/webkit/WebCore/ChangeLog | 13 ++++ .../webkit/WebCore/xml/XSLTProcessorQt.cpp | 30 ++++++++ src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp | 84 ++++++++++++++++++++++ src/3rdparty/webkit/WebKit/qt/Api/qwebframe_p.h | 2 + src/3rdparty/webkit/WebKit/qt/ChangeLog | 18 +++++ .../webkit/WebKit/qt/tests/qwebframe/qwebframe.qrc | 2 + .../WebKit/qt/tests/qwebframe/testiframe.html | 54 ++++++++++++++ .../WebKit/qt/tests/qwebframe/testiframe2.html | 21 ++++++ .../WebKit/qt/tests/qwebframe/tst_qwebframe.cpp | 67 +++++++++++++++++ 10 files changed, 292 insertions(+), 1 deletion(-) create mode 100644 src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe.html create mode 100644 src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe2.html diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION index 0b88429..b69ac98 100644 --- a/src/3rdparty/webkit/VERSION +++ b/src/3rdparty/webkit/VERSION @@ -8,4 +8,4 @@ The commit imported was from the and has the sha1 checksum - 99ccc1c3e4db5354246720f9b9aa3d282e64497d + bd6591b4acaf2172ab05702153ef539c0ac89cbb diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog index 516fadd..ab5b131 100644 --- a/src/3rdparty/webkit/WebCore/ChangeLog +++ b/src/3rdparty/webkit/WebCore/ChangeLog @@ -1,3 +1,16 @@ +2010-01-12 Jakub Wieczorek + + Reviewed by Adam Barth. + + [Qt] XSL stylesheets can load documents from a different origin + + https://bugs.webkit.org/show_bug.cgi?id=33423 + + * xml/XSLTProcessorQt.cpp: + (WebCore::XSLTUriResolver::XSLTUriResolver): + (WebCore::XSLTUriResolver::resolve): + (WebCore::XSLTProcessor::transformToString): + 2010-01-07 Yael Aharon Reviewed by Kenneth Rohde Christiansen. diff --git a/src/3rdparty/webkit/WebCore/xml/XSLTProcessorQt.cpp b/src/3rdparty/webkit/WebCore/xml/XSLTProcessorQt.cpp index 50ee427..3e05ca0 100644 --- a/src/3rdparty/webkit/WebCore/xml/XSLTProcessorQt.cpp +++ b/src/3rdparty/webkit/WebCore/xml/XSLTProcessorQt.cpp @@ -36,6 +36,7 @@ #include #include +#include #include #include #include @@ -87,6 +88,31 @@ void XSLTMessageHandler::handleMessage(QtMsgType type, const QString& descriptio sourceLocation.line(), sourceLocation.uri().toString()); } +class XSLTUriResolver : public QAbstractUriResolver { + +public: + XSLTUriResolver(Document* document); + virtual QUrl resolve(const QUrl& relative, const QUrl& baseURI) const; + +private: + Document* m_document; +}; + +XSLTUriResolver::XSLTUriResolver(Document* document) + : QAbstractUriResolver() + , m_document(document) +{ +} + +QUrl XSLTUriResolver::resolve(const QUrl& relative, const QUrl& baseURI) const +{ + QUrl url = baseURI.resolved(relative); + + if (!m_document->frame() || !m_document->securityOrigin()->canRequest(url)) + return QUrl(); + return url; +} + bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultString, String&) { bool success = false; @@ -107,6 +133,7 @@ bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultS QXmlQuery query(QXmlQuery::XSLT20); XSLTMessageHandler messageHandler(ownerDocument.get()); + XSLTUriResolver uriResolver(ownerDocument.get()); query.setMessageHandler(&messageHandler); XSLTProcessor::ParameterMap::iterator end = m_parameters.end(); @@ -132,6 +159,9 @@ bool XSLTProcessor::transformToString(Node* sourceNode, String&, String& resultS query.setFocus(&inputBuffer); query.setQuery(&styleSheetBuffer, QUrl(stylesheet->href())); + + query.setUriResolver(&uriResolver); + success = query.evaluateTo(&outputBuffer); outputBuffer.reset(); resultString = QString::fromUtf8(outputBuffer.readAll()).trimmed(); diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp index 90d98be..29bde0d 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp @@ -324,6 +324,45 @@ void QWebFramePrivate::renderPrivate(QPainter *painter, QWebFrame::RenderLayer l } } +static bool webframe_scrollOverflow(WebCore::Frame* frame, int dx, int dy) +{ + if (!frame || !frame->document() || !frame->eventHandler()) + return false; + + Node* node = frame->document()->focusedNode(); + if (!node) + node = frame->document()->elementFromPoint(frame->eventHandler()->currentMousePosition().x(), + frame->eventHandler()->currentMousePosition().y()); + if (!node) + return false; + + RenderObject* renderer = node->renderer(); + if (!renderer) + return false; + + if (renderer->isListBox()) + return false; + + RenderLayer* renderLayer = renderer->enclosingLayer(); + if (!renderLayer) + return false; + + bool scrolledHorizontal = false; + bool scrolledVertical = false; + + if (dx > 0) + scrolledHorizontal = renderLayer->scroll(ScrollRight, ScrollByPixel, dx); + else if (dx < 0) + scrolledHorizontal = renderLayer->scroll(ScrollLeft, ScrollByPixel, qAbs(dx)); + + if (dy > 0) + scrolledVertical = renderLayer->scroll(ScrollDown, ScrollByPixel, dy); + else if (dy < 0) + scrolledVertical = renderLayer->scroll(ScrollUp, ScrollByPixel, qAbs(dy)); + + return (scrolledHorizontal || scrolledVertical); +} + /*! \class QWebFrame \since 4.4 @@ -1008,6 +1047,51 @@ void QWebFrame::scroll(int dx, int dy) } /*! + \since 4.7 + \internal + Scrolls nested frames starting at this frame, \a dx pixels to the right + and \a dy pixels downward. Both \a dx and \a dy may be negative. First attempts + to scroll elements with CSS overflow followed by this frame. If this + frame doesn't scroll, attempts to scroll the parent + + \sa QWebFrame::scroll +*/ +bool QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy) +{ + Frame* frame = QWebFramePrivate::core(qFrame); + bool scrolledHorizontal = false; + bool scrolledVertical = false; + bool scrolledOverflow = webframe_scrollOverflow(frame, dx, dy); + + if (!scrolledOverflow) { + if (!frame || !frame->view()) + return false; + + do { + IntSize scrollOffset = frame->view()->scrollOffset(); + IntPoint maxScrollOffset = frame->view()->maximumScrollPosition(); + + if (dx > 0) // scroll right + scrolledHorizontal = scrollOffset.width() < maxScrollOffset.x(); + else if (dx < 0) // scroll left + scrolledHorizontal = scrollOffset.width() > 0; + + if (dy > 0) // scroll down + scrolledVertical = scrollOffset.height() < maxScrollOffset.y(); + else if (dy < 0) //scroll up + scrolledVertical = scrollOffset.height() > 0; + + if (scrolledHorizontal || scrolledVertical) { + frame->view()->scrollBy(IntSize(dx, dy)); + return true; + } + frame = frame->tree()->parent(); + } while (frame && frame->view()); + } + return (scrolledHorizontal || scrolledVertical || scrolledOverflow); +} + +/*! \property QWebFrame::scrollPosition \since 4.5 \brief the position the frame is currently scrolled to. diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebframe_p.h b/src/3rdparty/webkit/WebKit/qt/Api/qwebframe_p.h index 081e65d..095d134 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebframe_p.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebframe_p.h @@ -83,6 +83,8 @@ public: void renderPrivate(QPainter*, QWebFrame::RenderLayer, const QRegion& clip); + bool scrollOverflow(int dx, int dy); + QWebFrame *q; Qt::ScrollBarPolicy horizontalScrollBarPolicy; Qt::ScrollBarPolicy verticalScrollBarPolicy; diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index 31fad69..357b787 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,21 @@ +2009-12-18 Joe Ligman + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Add new API to QWebFrame to scrollRecursively starting with any css overflow + then checking current frame and then ancestors + https://bugs.webkit.org/show_bug.cgi?id=32668 + + * Api/qwebframe.cpp: + (QWebFramePrivate::scrollOverflow): + (QWebFrame::scrollRecursively): + * Api/qwebframe.h: + * Api/qwebframe_p.h: + * tests/qwebframe/qwebframe.qrc: + * tests/qwebframe/testiframe.html: Added. + * tests/qwebframe/testiframe2.html: Added. + * tests/qwebframe/tst_qwebframe.cpp: + 2010-01-07 Yael Aharon Reviewed by Kenneth Rohde Christiansen. diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/qwebframe.qrc b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/qwebframe.qrc index 9615e27..8afa0c1 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/qwebframe.qrc +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/qwebframe.qrc @@ -4,5 +4,7 @@ style.css test1.html test2.html +testiframe.html +testiframe2.html diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe.html b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe.html new file mode 100644 index 0000000..9f3ae85 --- /dev/null +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe.html @@ -0,0 +1,54 @@ + + + + + + + + +
You can use the overflow property when you want to have better control of the layout. Try to change the overflow property to: visible, hidden, auto, or inherit and see what happens. The default value is visible. +You can use the overflow property when you want to have better control of the layout. Try to change the overflow property to: visible, hidden, auto, or inherit and see what happens. The default value is visible. +You can use the overflow property when you want to have better control of the layout. Try to change the overflow property to: visible, hidden, auto, or inherit and see what happens. The default value is visible. +You can use the overflow property when you want to have better control of the layout. Try to change the overflow property to: visible, hidden, auto, or inherit and see what happens. The default value is visible. +You can use the overflow property when you want to have better control of the layout. Try to change the overflow property to: visible, hidden, auto, or inherit and see what happens. The default value is visible. +You can use the overflow property when you want to have better control of the layout. Try to change the overflow property to: visible, hidden, auto, or inherit and see what happens. The default value is visible.
+ + + + \ No newline at end of file diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe2.html b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe2.html new file mode 100644 index 0000000..1913a89 --- /dev/null +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/testiframe2.html @@ -0,0 +1,21 @@ + + + + + + + +
+ + \ No newline at end of file diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp index 8cc7953..609f8b4 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp @@ -606,6 +606,7 @@ private slots: void scrollPosition(); void evaluateWillCauseRepaint(); void qObjectWrapperWithSameIdentity(); + void scrollRecursively(); private: QString evalJS(const QString&s) { @@ -2824,5 +2825,71 @@ void tst_QWebFrame::qObjectWrapperWithSameIdentity() QCOMPARE(mainFrame->toPlainText(), QString("test2")); } +bool QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy); + +void tst_QWebFrame::scrollRecursively() +{ + // The test content is + // a nested frame set + // The main frame scrolls + // and has two children + // an iframe and a div overflow + // both scroll + QWebView webView; + QWebPage* webPage = webView.page(); + QSignalSpy loadSpy(webPage, SIGNAL(loadFinished(bool))); + QUrl url = QUrl("qrc:///testiframe.html"); + webPage->mainFrame()->load(url); + QTRY_COMPARE(loadSpy.count(), 1); + + QList children = webPage->mainFrame()->childFrames(); + QVERIFY(children.count() == 1); + + // 1st test + // call scrollRecursively over mainframe + // verify scrolled + // verify scroll postion changed + QPoint scrollPosition(webPage->mainFrame()->scrollPosition()); + QVERIFY(qtwebkit_webframe_scrollRecursively(webPage->mainFrame(), 10, 10)); + QVERIFY(scrollPosition != webPage->mainFrame()->scrollPosition()); + + // 2nd test + // call scrollRecursively over child iframe + // verify scrolled + // verify child scroll position changed + // verify parent's scroll position did not change + scrollPosition = webPage->mainFrame()->scrollPosition(); + QPoint childScrollPosition = children.at(0)->scrollPosition(); + QVERIFY(qtwebkit_webframe_scrollRecursively(children.at(0), 10, 10)); + QVERIFY(scrollPosition == webPage->mainFrame()->scrollPosition()); + QVERIFY(childScrollPosition != children.at(0)->scrollPosition()); + + // 3rd test + // call scrollRecursively over div overflow + // verify scrolled == true + // verify parent and child frame's scroll postion did not change + QWebElement div = webPage->mainFrame()->documentElement().findFirst("#content1"); + QMouseEvent evpres(QEvent::MouseMove, div.geometry().center(), Qt::NoButton, Qt::NoButton, Qt::NoModifier); + webPage->event(&evpres); + scrollPosition = webPage->mainFrame()->scrollPosition(); + childScrollPosition = children.at(0)->scrollPosition(); + QVERIFY(qtwebkit_webframe_scrollRecursively(webPage->mainFrame(), 5, 5)); + QVERIFY(childScrollPosition == children.at(0)->scrollPosition()); + QVERIFY(scrollPosition == webPage->mainFrame()->scrollPosition()); + + // 4th test + // call scrollRecursively twice over childs iframe + // verify scrolled == true first time + // verify parent's scroll == true second time + // verify parent and childs scroll position changed + childScrollPosition = children.at(0)->scrollPosition(); + QVERIFY(qtwebkit_webframe_scrollRecursively(children.at(0), -10, -10)); + QVERIFY(childScrollPosition != children.at(0)->scrollPosition()); + scrollPosition = webPage->mainFrame()->scrollPosition(); + QVERIFY(qtwebkit_webframe_scrollRecursively(children.at(0), -10, -10)); + QVERIFY(scrollPosition != webPage->mainFrame()->scrollPosition()); + +} + QTEST_MAIN(tst_QWebFrame) #include "tst_qwebframe.moc" -- cgit v0.12