From 222a21187c3e3fe4ab6f436f30bde1b1dc0b2212 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 24 Sep 2010 00:22:05 +1000 Subject: Invalidate QStaticText coord cache when texture size changes If the glyph cache texture changes size, the texture coordinate array must be regenerated to point to the correct texture locations. Reviewed-By: Gunnar Sletta --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 2347e66..0426ffd 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1470,7 +1470,7 @@ namespace { { public: QOpenGLStaticTextUserData() - : QStaticTextUserData(OpenGLUserData) + : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0) { } @@ -1478,6 +1478,7 @@ namespace { { } + QSize cacheSize; QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; }; @@ -1542,6 +1543,12 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp // Use cache if backend optimizations is turned on vertexCoordinates = &userData->vertexCoordinateArray; textureCoordinates = &userData->textureCoordinateArray; + + QSize size(cache->width(), cache->height()); + if (userData->cacheSize != size) { + recreateVertexArrays = true; + userData->cacheSize = size; + } } -- cgit v0.12 From 7a14055269c31a389d895a2fffa1e9d897e1bee3 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 24 Sep 2010 00:28:30 +1000 Subject: Remove unnecessary attribute changes The only consumer of TextDrawingMode is drawCachedGlyphs, and it always sets these two attrib pointers anyway. Reviewed-By: Gunnar Sletta --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 0426ffd..42792ac 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -612,8 +612,6 @@ void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) } if (newMode == TextDrawingMode) { - setVertexAttributePointer(QT_VERTEX_COORDS_ATTR, (GLfloat*)vertexCoordinateArray.data()); - setVertexAttributePointer(QT_TEXTURE_COORDS_ATTR, (GLfloat*)textureCoordinateArray.data()); shaderManager->setHasComplexGeometry(true); } else { shaderManager->setHasComplexGeometry(false); -- cgit v0.12 From 8de9ec760810fea9c9cfccfe575a4693f2f5c024 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 28 Sep 2010 14:31:16 +1000 Subject: Only repopulate the glyph cache when we know something could have changed Reviewed-by: Gunnar Sletta --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 27 +++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 42792ac..6b0d2fa 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1499,9 +1499,22 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp staticTextItem->fontEngine->setGlyphCache(ctx, cache); } - cache->setPaintEnginePrivate(this); - cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, - staticTextItem->glyphPositions); + bool recreateVertexArrays = false; + if (staticTextItem->userDataNeedsUpdate) + recreateVertexArrays = true; + else if (staticTextItem->userData == 0) + recreateVertexArrays = true; + else if (staticTextItem->userData->type != QStaticTextUserData::OpenGLUserData) + recreateVertexArrays = true; + + // We only need to update the cache with new glyphs if we are actually going to recreate the vertex arrays. + // If the cache size has changed, we do need to regenerate the vertices, but we don't need to repopulate the + // cache so this text is performed before we test if the cache size has changed. + if (recreateVertexArrays) { + cache->setPaintEnginePrivate(this); + cache->populate(staticTextItem->fontEngine, staticTextItem->numGlyphs, staticTextItem->glyphs, + staticTextItem->glyphPositions); + } if (cache->width() == 0 || cache->height() == 0) return; @@ -1513,14 +1526,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp GLfloat dx = 1.0 / cache->width(); GLfloat dy = 1.0 / cache->height(); - bool recreateVertexArrays = false; - if (staticTextItem->userDataNeedsUpdate) - recreateVertexArrays = true; - else if (staticTextItem->userData == 0) - recreateVertexArrays = true; - else if (staticTextItem->userData->type != QStaticTextUserData::OpenGLUserData) - recreateVertexArrays = true; - // Use global arrays by default QGL2PEXVertexArray *vertexCoordinates = &vertexCoordinateArray; QGL2PEXVertexArray *textureCoordinates = &textureCoordinateArray; -- cgit v0.12 From 8f9ef5ca1cd24bf74004c8b12e4025b72ec7548b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 28 Sep 2010 14:32:26 +1000 Subject: Only set maskTexture sampler uniform once Qt always uses the same texture unit as the maskTexture, so it makes sense to set the uniform only once when the program is created. Reviewed-By: Gunnar Sletta --- src/opengl/gl2paintengineex/qglengineshadermanager.cpp | 17 +++++++++++++---- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 2 -- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 40b3641..ac87784 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -41,6 +41,7 @@ #include "qglengineshadermanager_p.h" #include "qglengineshadersource_p.h" +#include "qpaintengineex_opengl2_p.h" #if defined(QT_DEBUG) #include @@ -248,6 +249,7 @@ QByteArray QGLEngineSharedShaders::snippetNameStr(SnippetName name) #endif // The address returned here will only be valid until next time this function is called. +// The program is return bound. QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineShaderProg &prog) { for (int i = 0; i < cachedPrograms.size(); ++i) { @@ -255,6 +257,7 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS if (*cachedProg == prog) { // Move the program to the top of the list as a poor-man's cache algo cachedPrograms.move(i, 0); + cachedProg->program->bind(); return cachedProg; } } @@ -355,6 +358,14 @@ QGLEngineShaderProg *QGLEngineSharedShaders::findProgramInCache(const QGLEngineS qWarning() << error; break; } + + newProg->program->bind(); + + if (newProg->maskFragShader != QGLEngineSharedShaders::NoMaskFragmentShader) { + GLuint location = newProg->program->uniformLocation("maskTexture"); + newProg->program->setUniformValue(location, QT_MASK_TEXTURE_UNIT); + } + if (cachedPrograms.count() > 30) { // The cache is full, so delete the last 5 programs in the list. // These programs will be least used, as a program us bumped to @@ -769,10 +780,8 @@ bool QGLEngineShaderManager::useCorrectShaderProg() // At this point, requiredProgram is fully populated so try to find the program in the cache currentShaderProg = sharedShaders->findProgramInCache(requiredProgram); - if (currentShaderProg) { - currentShaderProg->program->bind(); - if (useCustomSrc) - customSrcStage->setUniforms(currentShaderProg->program); + if (currentShaderProg && useCustomSrc) { + customSrcStage->setUniforms(currentShaderProg->program); } // Make sure all the vertex attribute arrays the program uses are enabled (and the ones it diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 6b0d2fa..5dd66fe 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1666,7 +1666,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp glBindTexture(GL_TEXTURE_2D, cache->texture()); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); #else @@ -1702,7 +1701,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp lastMaskTextureUsed = cache->texture(); } updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, s->matrix.type() > QTransform::TxTranslate); - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); -- cgit v0.12 From 3a927312dbb797f03b351067210b83784c7132cb Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 28 Sep 2010 14:59:23 +1000 Subject: Minimize parameter changes on glyph cache textures Cache the last set filtering mode on glyph textures and update only when necessary. Reviewed-by: Gunnar Sletta --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 24 +++++++++++++++++----- .../gl2paintengineex/qtextureglyphcache_gl.cpp | 5 +++++ .../gl2paintengineex/qtextureglyphcache_gl_p.h | 8 ++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 5dd66fe..cb1ca8e 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1695,12 +1695,26 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp } //### TODO: Gamma correction - glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); - if (lastMaskTextureUsed != cache->texture()) { - glBindTexture(GL_TEXTURE_2D, cache->texture()); - lastMaskTextureUsed = cache->texture(); + QGLTextureGlyphCache::FilterMode filterMode = (s->matrix.type() > QTransform::TxTranslate)?QGLTextureGlyphCache::Linear:QGLTextureGlyphCache::Nearest; + if (lastMaskTextureUsed != cache->texture() || cache->filterMode() != filterMode) { + + glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT); + if (lastMaskTextureUsed != cache->texture()) { + glBindTexture(GL_TEXTURE_2D, cache->texture()); + lastMaskTextureUsed = cache->texture(); + } + + if (cache->filterMode() != filterMode) { + if (filterMode == QGLTextureGlyphCache::Linear) { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + } else { + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + cache->setFilterMode(filterMode); + } } - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, s->matrix.type() > QTransform::TxTranslate); #if defined(QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO) glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, 0); diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index f353995..9a5bac0 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -57,6 +57,7 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph , ctx(context) , m_width(0) , m_height(0) + , m_filterMode(Nearest) { // broken FBO readback is a bug in the SGX 1.3 and 1.4 drivers for the N900 where // copying between FBO's is broken if the texture is either GL_ALPHA or POT. The @@ -114,6 +115,9 @@ void QGLTextureGlyphCache::createTextureData(int width, int height) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + m_filterMode = Nearest; } void QGLTextureGlyphCache::resizeTextureData(int width, int height) @@ -152,6 +156,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + m_filterMode = Nearest; glBindTexture(GL_TEXTURE_2D, 0); glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tmp_texture, 0); diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index eb3693c..e22146d 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -83,6 +83,12 @@ public: inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; } + enum FilterMode { + Nearest, + Linear + }; + FilterMode filterMode() const { return m_filterMode; } + void setFilterMode(FilterMode m) { m_filterMode = m; } public Q_SLOTS: void contextDestroyed(const QGLContext *context) { @@ -117,6 +123,8 @@ private: int m_height; QGLShaderProgram *m_program; + + FilterMode m_filterMode; }; QT_END_NAMESPACE -- cgit v0.12 From fd9771c29d401d88779ab7c5d7715c9ca41dd723 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Wed, 22 Sep 2010 21:03:57 +0200 Subject: Make QmlDebug protocol more robust The protocol so far was client->server only. That is, there was no sane way for a client to check whether a plugin on the server (service) was available or not. E.g. calling Client::setEnabled(true) 'succeeded', without a check whether there is actually a service to talk to. The new protocol replaces this shortcoming by a service discovery mechanism: Both client & service announce their available plugins at handshake time, and later on if there are changes. The status is reflected in Client::status() and Service::Status() , which are either NotConnected - no network connection, or not registered properly Unavailable - TCP/IP connection works, but no plugin with the same name on the other side Enabled - You can connect to plugin on other side The status changes happen automatically (no setEnabled() anymore). Furthermore a version ID was added to the handshake, so that we can extend the protocol further in the future :) --- src/declarative/debugger/qdeclarativedebug.cpp | 56 ++++-- src/declarative/debugger/qdeclarativedebug_p.h | 7 +- .../debugger/qdeclarativedebugclient.cpp | 199 +++++++++++++++------ .../debugger/qdeclarativedebugclient_p.h | 10 +- .../debugger/qdeclarativedebugservice.cpp | 126 ++++++++++--- .../debugger/qdeclarativedebugservice_p.h | 9 +- .../debugger/qdeclarativedebugtrace.cpp | 8 +- .../qdeclarativedebug/tst_qdeclarativedebug.cpp | 5 +- .../tst_qdeclarativedebugclient.cpp | 60 +++---- .../tst_qdeclarativedebugservice.cpp | 41 ++--- tests/auto/declarative/shared/debugutil.cpp | 13 +- tests/auto/declarative/shared/debugutil_p.h | 8 +- 12 files changed, 362 insertions(+), 180 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebug.cpp b/src/declarative/debugger/qdeclarativedebug.cpp index 1ffe441..7a5e5f6 100644 --- a/src/declarative/debugger/qdeclarativedebug.cpp +++ b/src/declarative/debugger/qdeclarativedebug.cpp @@ -55,10 +55,12 @@ public: QDeclarativeEngineDebugClient(QDeclarativeDebugConnection *client, QDeclarativeEngineDebugPrivate *p); protected: + virtual void statusChanged(Status status); virtual void messageReceived(const QByteArray &); private: QDeclarativeEngineDebugPrivate *priv; + friend class QDeclarativeEngineDebugPrivate; }; class QDeclarativeEngineDebugPrivate : public QObjectPrivate @@ -66,7 +68,9 @@ class QDeclarativeEngineDebugPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QDeclarativeEngineDebug) public: QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *); + ~QDeclarativeEngineDebugPrivate(); + void statusChanged(QDeclarativeEngineDebug::Status status); void message(const QByteArray &); QDeclarativeEngineDebugClient *client; @@ -93,12 +97,18 @@ QDeclarativeEngineDebugClient::QDeclarativeEngineDebugClient(QDeclarativeDebugCo QDeclarativeEngineDebugPrivate *p) : QDeclarativeDebugClient(QLatin1String("QDeclarativeEngine"), client), priv(p) { - setEnabled(true); +} + +void QDeclarativeEngineDebugClient::statusChanged(Status status) +{ + if (priv) + priv->statusChanged(static_cast(status)); } void QDeclarativeEngineDebugClient::messageReceived(const QByteArray &data) { - priv->message(data); + if (priv) + priv->message(data); } QDeclarativeEngineDebugPrivate::QDeclarativeEngineDebugPrivate(QDeclarativeDebugConnection *c) @@ -106,6 +116,12 @@ QDeclarativeEngineDebugPrivate::QDeclarativeEngineDebugPrivate(QDeclarativeDebug { } +QDeclarativeEngineDebugPrivate::~QDeclarativeEngineDebugPrivate() +{ + if (client) + client->priv = 0; +} + int QDeclarativeEngineDebugPrivate::getId() { return nextId++; @@ -228,6 +244,11 @@ void QDeclarativeEngineDebugPrivate::decode(QDataStream &ds, QDeclarativeDebugCo } } +void QDeclarativeEngineDebugPrivate::statusChanged(QDeclarativeEngineDebug::Status status) +{ + emit q_func()->statusChanged(status); +} + void QDeclarativeEngineDebugPrivate::message(const QByteArray &data) { QDataStream ds(data); @@ -350,12 +371,19 @@ QDeclarativeEngineDebug::QDeclarativeEngineDebug(QDeclarativeDebugConnection *cl { } +QDeclarativeEngineDebug::Status QDeclarativeEngineDebug::status() const +{ + Q_D(const QDeclarativeEngineDebug); + + return static_cast(d->client->status()); +} + QDeclarativeDebugPropertyWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebugPropertyReference &property, QObject *parent) { Q_D(QDeclarativeEngineDebug); QDeclarativeDebugPropertyWatch *watch = new QDeclarativeDebugPropertyWatch(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { int queryId = d->getId(); watch->m_queryId = queryId; watch->m_client = this; @@ -384,7 +412,7 @@ QDeclarativeDebugObjectExpressionWatch *QDeclarativeEngineDebug::addWatch(const { Q_D(QDeclarativeEngineDebug); QDeclarativeDebugObjectExpressionWatch *watch = new QDeclarativeDebugObjectExpressionWatch(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { int queryId = d->getId(); watch->m_queryId = queryId; watch->m_client = this; @@ -407,7 +435,7 @@ QDeclarativeDebugWatch *QDeclarativeEngineDebug::addWatch(const QDeclarativeDebu Q_D(QDeclarativeEngineDebug); QDeclarativeDebugWatch *watch = new QDeclarativeDebugWatch(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { int queryId = d->getId(); watch->m_queryId = queryId; watch->m_client = this; @@ -443,7 +471,7 @@ void QDeclarativeEngineDebug::removeWatch(QDeclarativeDebugWatch *watch) d->watched.remove(watch->queryId()); - if (d->client && d->client->isConnected()) { + if (d->client && d->client->status() == QDeclarativeDebugClient::Enabled) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("NO_WATCH") << watch->queryId(); @@ -456,7 +484,7 @@ QDeclarativeDebugEnginesQuery *QDeclarativeEngineDebug::queryAvailableEngines(QO Q_D(QDeclarativeEngineDebug); QDeclarativeDebugEnginesQuery *query = new QDeclarativeDebugEnginesQuery(parent); - if (d->client->isConnected()) { + if (d->client->status() == QDeclarativeDebugClient::Enabled) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -478,7 +506,7 @@ QDeclarativeDebugRootContextQuery *QDeclarativeEngineDebug::queryRootContexts(co Q_D(QDeclarativeEngineDebug); QDeclarativeDebugRootContextQuery *query = new QDeclarativeDebugRootContextQuery(parent); - if (d->client->isConnected() && engine.debugId() != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && engine.debugId() != -1) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -500,7 +528,7 @@ QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObject(const QDeclar Q_D(QDeclarativeEngineDebug); QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent); - if (d->client->isConnected() && object.debugId() != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -523,7 +551,7 @@ QDeclarativeDebugObjectQuery *QDeclarativeEngineDebug::queryObjectRecursive(cons Q_D(QDeclarativeEngineDebug); QDeclarativeDebugObjectQuery *query = new QDeclarativeDebugObjectQuery(parent); - if (d->client->isConnected() && object.debugId() != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && object.debugId() != -1) { query->m_client = this; int queryId = d->getId(); query->m_queryId = queryId; @@ -546,7 +574,7 @@ QDeclarativeDebugExpressionQuery *QDeclarativeEngineDebug::queryExpressionResult Q_D(QDeclarativeEngineDebug); QDeclarativeDebugExpressionQuery *query = new QDeclarativeDebugExpressionQuery(parent); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { query->m_client = this; query->m_expr = expr; int queryId = d->getId(); @@ -570,7 +598,7 @@ bool QDeclarativeEngineDebug::setBindingForObject(int objectDebugId, const QStri { Q_D(QDeclarativeEngineDebug); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("SET_BINDING") << objectDebugId << propertyName << bindingExpression << isLiteralValue; @@ -585,7 +613,7 @@ bool QDeclarativeEngineDebug::resetBindingForObject(int objectDebugId, const QSt { Q_D(QDeclarativeEngineDebug); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("RESET_BINDING") << objectDebugId << propertyName; @@ -601,7 +629,7 @@ bool QDeclarativeEngineDebug::setMethodBody(int objectDebugId, const QString &me { Q_D(QDeclarativeEngineDebug); - if (d->client->isConnected() && objectDebugId != -1) { + if (d->client->status() == QDeclarativeDebugClient::Enabled && objectDebugId != -1) { QByteArray message; QDataStream ds(&message, QIODevice::WriteOnly); ds << QByteArray("SET_METHOD_BODY") << objectDebugId << methodName << methodBody; diff --git a/src/declarative/debugger/qdeclarativedebug_p.h b/src/declarative/debugger/qdeclarativedebug_p.h index 2b1a115..3d83e8a 100644 --- a/src/declarative/debugger/qdeclarativedebug_p.h +++ b/src/declarative/debugger/qdeclarativedebug_p.h @@ -69,7 +69,11 @@ class Q_DECLARATIVE_EXPORT QDeclarativeEngineDebug : public QObject { Q_OBJECT public: - QDeclarativeEngineDebug(QDeclarativeDebugConnection *, QObject * = 0); + enum Status { NotConnected, Unavailable, Enabled }; + + explicit QDeclarativeEngineDebug(QDeclarativeDebugConnection *, QObject * = 0); + + Status status() const; QDeclarativeDebugPropertyWatch *addWatch(const QDeclarativeDebugPropertyReference &, QObject *parent = 0); @@ -101,6 +105,7 @@ public: Q_SIGNALS: void newObjects(); + void statusChanged(Status status); private: Q_DECLARE_PRIVATE(QDeclarativeEngineDebug) diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp index 2e52b40..f7d7243 100644 --- a/src/declarative/debugger/qdeclarativedebugclient.cpp +++ b/src/declarative/debugger/qdeclarativedebugclient.cpp @@ -50,6 +50,20 @@ QT_BEGIN_NAMESPACE +const int protocolVersion = 1; +const QString serverId = QLatin1String("QDeclarativeDebugServer"); +const QString clientId = QLatin1String("QDeclarativeDebugClient"); + +class QDeclarativeDebugClientPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugClient) +public: + QDeclarativeDebugClientPrivate(); + + QString name; + QDeclarativeDebugConnection *client; +}; + class QDeclarativeDebugConnectionPrivate : public QObject { Q_OBJECT @@ -58,40 +72,123 @@ public: QDeclarativeDebugConnection *q; QPacketProtocol *protocol; - QStringList enabled; + bool gotHello; + QStringList serverPlugins; QHash plugins; + + void advertisePlugins(); + public Q_SLOTS: void connected(); void readyRead(); }; QDeclarativeDebugConnectionPrivate::QDeclarativeDebugConnectionPrivate(QDeclarativeDebugConnection *c) -: QObject(c), q(c), protocol(0) +: QObject(c), q(c), protocol(0), gotHello(false) { protocol = new QPacketProtocol(q, this); QObject::connect(c, SIGNAL(connected()), this, SLOT(connected())); QObject::connect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); } +void QDeclarativeDebugConnectionPrivate::advertisePlugins() +{ + if (!q->isConnected() || !gotHello) + return; + + QPacket pack; + pack << serverId << 1 << plugins.keys(); + protocol->send(pack); +} + void QDeclarativeDebugConnectionPrivate::connected() { QPacket pack; - pack << QString(QLatin1String("QDeclarativeDebugServer")) << enabled; + pack << serverId << 0 << protocolVersion << plugins.keys(); protocol->send(pack); } void QDeclarativeDebugConnectionPrivate::readyRead() { - QPacket pack = protocol->read(); - QString name; QByteArray message; - pack >> name >> message; + if (!gotHello) { + QPacket pack = protocol->read(); + QString name; + + pack >> name; + + bool validHello = false; + if (name == clientId) { + int op = -1; + pack >> op; + if (op == 0) { + int version = -1; + pack >> version; + if (version == protocolVersion) { + pack >> serverPlugins; + validHello = true; + } + } + } - QHash::Iterator iter = - plugins.find(name); - if (iter == plugins.end()) { - qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name; - } else { - (*iter)->messageReceived(message); + if (!validHello) { + qWarning("QDeclarativeDebugConnection: Invalid hello message"); + QObject::disconnect(protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); + return; + } + + qDebug() << "Available server side plugins: " << serverPlugins; + + QHash::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable; + if (serverPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugClient::Enabled; + iter.value()->statusChanged(newStatus); + } + gotHello = true; + } + + while (protocol->packetsAvailable()) { + QPacket pack = protocol->read(); + QString name; + pack >> name; + + if (name == clientId) { + int op = -1; + pack >> op; + + if (op == 1) { + // Service Discovery + QStringList oldServerPlugins = serverPlugins; + pack >> serverPlugins; + + QHash::Iterator iter = plugins.begin(); + for (; iter != plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugClient::Status newStatus = QDeclarativeDebugClient::Unavailable; + if (serverPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugClient::Enabled; + + if (oldServerPlugins.contains(pluginName) + != serverPlugins.contains(pluginName)) { + iter.value()->statusChanged(newStatus); + } + } + } else { + qWarning() << "QDeclarativeDebugConnection: Unknown control message id" << op; + } + } else { + QByteArray message; + pack >> message; + + QHash::Iterator iter = + plugins.find(name); + if (iter == plugins.end()) { + qWarning() << "QDeclarativeDebugConnection: Message received for missing plugin" << name; + } else { + (*iter)->messageReceived(message); + } + } } } @@ -100,24 +197,22 @@ QDeclarativeDebugConnection::QDeclarativeDebugConnection(QObject *parent) { } -bool QDeclarativeDebugConnection::isConnected() const +QDeclarativeDebugConnection::~QDeclarativeDebugConnection() { - return state() == ConnectedState; + QHash::iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + iter.value()->d_func()->client = 0; + iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected); + } } -class QDeclarativeDebugClientPrivate : public QObjectPrivate +bool QDeclarativeDebugConnection::isConnected() const { - Q_DECLARE_PUBLIC(QDeclarativeDebugClient) -public: - QDeclarativeDebugClientPrivate(); - - QString name; - QDeclarativeDebugConnection *client; - bool enabled; -}; + return state() == ConnectedState; +} QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate() -: client(0), enabled(false) +: client(0) { } @@ -137,60 +232,44 @@ QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name, d->client = 0; } else { d->client->d->plugins.insert(name, this); + d->client->d->advertisePlugins(); } } -QString QDeclarativeDebugClient::name() const +QDeclarativeDebugClient::~QDeclarativeDebugClient() { Q_D(const QDeclarativeDebugClient); - return d->name; + if (d->client && d->client->d) { + d->client->d->plugins.remove(d->name); + d->client->d->advertisePlugins(); + } } -bool QDeclarativeDebugClient::isEnabled() const +QString QDeclarativeDebugClient::name() const { Q_D(const QDeclarativeDebugClient); - return d->enabled; -} - -void QDeclarativeDebugClient::setEnabled(bool e) -{ - Q_D(QDeclarativeDebugClient); - if (e == d->enabled) - return; - - d->enabled = e; - - if (d->client) { - if (e) - d->client->d->enabled.append(d->name); - else - d->client->d->enabled.removeAll(d->name); - - if (d->client->state() == QTcpSocket::ConnectedState) { - QPacket pack; - pack << QString(QLatin1String("QDeclarativeDebugServer")); - if (e) pack << (int)1; - else pack << (int)2; - pack << d->name; - d->client->d->protocol->send(pack); - } - } + return d->name; } -bool QDeclarativeDebugClient::isConnected() const +QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const { Q_D(const QDeclarativeDebugClient); + if (!d->client + || !d->client->isConnected() + || !d->client->d->gotHello) + return NotConnected; - if (!d->client) - return false; - return d->client->isConnected(); + if (d->client->d->serverPlugins.contains(d->name)) + return Enabled; + + return Unavailable; } void QDeclarativeDebugClient::sendMessage(const QByteArray &message) { Q_D(QDeclarativeDebugClient); - if (!d->client || !d->client->isConnected()) + if (status() != Enabled) return; QPacket pack; @@ -198,6 +277,10 @@ void QDeclarativeDebugClient::sendMessage(const QByteArray &message) d->client->d->protocol->send(pack); } +void QDeclarativeDebugClient::statusChanged(Status status) +{ +} + void QDeclarativeDebugClient::messageReceived(const QByteArray &) { } diff --git a/src/declarative/debugger/qdeclarativedebugclient_p.h b/src/declarative/debugger/qdeclarativedebugclient_p.h index 4144a66..8d1706d 100644 --- a/src/declarative/debugger/qdeclarativedebugclient_p.h +++ b/src/declarative/debugger/qdeclarativedebugclient_p.h @@ -57,6 +57,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugConnection : public QTcpSocket Q_DISABLE_COPY(QDeclarativeDebugConnection) public: QDeclarativeDebugConnection(QObject * = 0); + ~QDeclarativeDebugConnection(); bool isConnected() const; private: @@ -73,18 +74,19 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugClient : public QObject Q_DISABLE_COPY(QDeclarativeDebugClient) public: + enum Status { NotConnected, Unavailable, Enabled }; + QDeclarativeDebugClient(const QString &, QDeclarativeDebugConnection *parent); + ~QDeclarativeDebugClient(); QString name() const; - bool isEnabled() const; - void setEnabled(bool); - - bool isConnected() const; + Status status() const; void sendMessage(const QByteArray &); protected: + virtual void statusChanged(Status); virtual void messageReceived(const QByteArray &); private: diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index 1f2bf4f..0fbc1e3 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -54,6 +54,30 @@ QT_BEGIN_NAMESPACE +/* + QDeclarativeDebug Protocol (Version 1): + + handshake: + 1. Client sends + "QDeclarativeDebugServer" 0 version pluginNames + version: an int representing the highest protocol version the client knows + pluginNames: plugins available on client side + 2. Server sends + "QDeclarativeDebugClient" 0 version pluginNames + version: an int representing the highest protocol version the client & server know + pluginNames: plugins available on server side. plugins both in the client and server message are enabled. + client plugin advertisement + 1. Client sends + "QDeclarativeDebugServer" 1 pluginNames + server plugin advertisement + 1. Server sends + "QDeclarativeDebugClient" 1 pluginNames + plugin communication: + Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin. + */ + +const int protocolVersion = 1; + class QDeclarativeDebugServerPrivate; class QDeclarativeDebugServer : public QObject { @@ -82,11 +106,13 @@ class QDeclarativeDebugServerPrivate : public QObjectPrivate public: QDeclarativeDebugServerPrivate(); + void advertisePlugins(); + int port; QTcpSocket *connection; QPacketProtocol *protocol; QHash plugins; - QStringList enabledPlugins; + QStringList clientPlugins; QTcpServer *tcpServer; bool gotHello; }; @@ -106,6 +132,18 @@ QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() { } +void QDeclarativeDebugServerPrivate::advertisePlugins() +{ + if (!connection + || connection->state() != QTcpSocket::ConnectedState + || !gotHello) + return; + + QPacket pack; + pack << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); + protocol->send(pack); +} + void QDeclarativeDebugServer::listen() { Q_D(QDeclarativeDebugServer); @@ -202,9 +240,13 @@ void QDeclarativeDebugServer::readyRead() if (!d->gotHello) { QPacket hello = d->protocol->read(); - QString name; - hello >> name >> d->enabledPlugins; - if (name != QLatin1String("QDeclarativeDebugServer")) { + + QString name; + int op; + hello >> name >> op; + + if (name != QLatin1String("QDeclarativeDebugServer") + || op != 0) { qWarning("QDeclarativeDebugServer: Invalid hello message"); QObject::disconnect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); d->protocol->deleteLater(); @@ -213,6 +255,23 @@ void QDeclarativeDebugServer::readyRead() d->connection = 0; return; } + + int version; + hello >> version >> d->clientPlugins; + + QHash::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugService::Enabled; + iter.value()->statusChanged(newStatus); + } + + QPacket helloAnswer; + helloAnswer << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); + d->protocol->send(helloAnswer); + d->connection->flush(); + d->gotHello = true; qWarning("QDeclarativeDebugServer: Connection established"); } @@ -226,32 +285,29 @@ void QDeclarativeDebugServer::readyRead() pack >> name; if (name == debugServer) { - int op = -1; QString plugin; - pack >> op >> plugin; + int op = -1; + pack >> op; if (op == 1) { - // Enable - if (!d->enabledPlugins.contains(plugin)) { - d->enabledPlugins.append(plugin); - QHash::Iterator iter = - d->plugins.find(plugin); - if (iter != d->plugins.end()) - (*iter)->enabledChanged(true); - } - - } else if (op == 2) { - // Disable - if (d->enabledPlugins.contains(plugin)) { - d->enabledPlugins.removeAll(plugin); - QHash::Iterator iter = - d->plugins.find(plugin); - if (iter != d->plugins.end()) - (*iter)->enabledChanged(false); + // Service Discovery + QStringList oldClientPlugins = d->clientPlugins; + pack >> d->clientPlugins; + + QHash::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugService::Enabled; + + if (oldClientPlugins.contains(pluginName) + != d->clientPlugins.contains(pluginName)) { + iter.value()->statusChanged(newStatus); + } } } else { qWarning("QDeclarativeDebugServer: Invalid control message %d", op); } - } else { QByteArray message; pack >> message; @@ -287,6 +343,16 @@ QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject d->server = 0; } else { d->server->d_func()->plugins.insert(name, this); + d->server->d_func()->advertisePlugins(); + } +} + +QDeclarativeDebugService::~QDeclarativeDebugService() +{ + Q_D(const QDeclarativeDebugService); + if (d->server) { + d->server->d_func()->plugins.remove(d->name); + d->server->d_func()->advertisePlugins(); } } @@ -296,10 +362,16 @@ QString QDeclarativeDebugService::name() const return d->name; } -bool QDeclarativeDebugService::isEnabled() const +QDeclarativeDebugService::Status QDeclarativeDebugService::status() const { Q_D(const QDeclarativeDebugService); - return (d->server && d->server->d_func()->enabledPlugins.contains(d->name)); + if (!d->server + || !d->server->hasDebuggingClient()) + return NotConnected; + if (d->server->d_func()->clientPlugins.contains(d->name)) + return Enabled; + + return Unavailable; } namespace { @@ -422,7 +494,7 @@ void QDeclarativeDebugService::sendMessage(const QByteArray &message) d->server->d_func()->connection->flush(); } -void QDeclarativeDebugService::enabledChanged(bool) +void QDeclarativeDebugService::statusChanged(Status) { } diff --git a/src/declarative/debugger/qdeclarativedebugservice_p.h b/src/declarative/debugger/qdeclarativedebugservice_p.h index c461ddf..0cadbe5 100644 --- a/src/declarative/debugger/qdeclarativedebugservice_p.h +++ b/src/declarative/debugger/qdeclarativedebugservice_p.h @@ -56,12 +56,15 @@ class Q_DECLARATIVE_EXPORT QDeclarativeDebugService : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QDeclarativeDebugService) Q_DISABLE_COPY(QDeclarativeDebugService) + public: - QDeclarativeDebugService(const QString &, QObject *parent = 0); + explicit QDeclarativeDebugService(const QString &, QObject *parent = 0); + ~QDeclarativeDebugService(); QString name() const; - bool isEnabled() const; + enum Status { NotConnected, Unavailable, Enabled }; + Status status() const; void sendMessage(const QByteArray &); @@ -74,7 +77,7 @@ public: static bool hasDebuggingClient(); protected: - virtual void enabledChanged(bool); + virtual void statusChanged(Status); virtual void messageReceived(const QByteArray &); private: diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index b2b0c8a..03e2d56 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -78,7 +78,7 @@ void QDeclarativeDebugTrace::endRange(RangeType t) void QDeclarativeDebugTrace::addEventImpl(EventType event) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; @@ -89,7 +89,7 @@ void QDeclarativeDebugTrace::addEventImpl(EventType event) void QDeclarativeDebugTrace::startRangeImpl(RangeType range) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; @@ -100,7 +100,7 @@ void QDeclarativeDebugTrace::startRangeImpl(RangeType range) void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; @@ -111,7 +111,7 @@ void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) void QDeclarativeDebugTrace::endRangeImpl(RangeType range) { - if (!isEnabled()) + if (status() != Enabled) return; QByteArray data; diff --git a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp index adba190..dd58baf 100644 --- a/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp +++ b/tests/auto/declarative/qdeclarativedebug/tst_qdeclarativedebug.cpp @@ -324,13 +324,16 @@ void tst_QDeclarativeDebug::initTestCase() bool ok = m_conn->waitForConnected(); Q_ASSERT(ok); QTRY_VERIFY(QDeclarativeDebugService::hasDebuggingClient()); - m_dbg = new QDeclarativeEngineDebug(m_conn, this); + QTRY_VERIFY(m_dbg->status() == QDeclarativeEngineDebug::Enabled); } void tst_QDeclarativeDebug::cleanupTestCase() { + delete m_dbg; + delete m_conn; qDeleteAll(m_components); + delete m_engine; } void tst_QDeclarativeDebug::setMethodBody() diff --git a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp index 7db0e60..72af3eb 100644 --- a/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp +++ b/tests/auto/declarative/qdeclarativedebugclient/tst_qdeclarativedebugclient.cpp @@ -66,9 +66,7 @@ private slots: void initTestCase(); void name(); - void isEnabled(); - void setEnabled(); - void isConnected(); + void status(); void sendMessage(); }; @@ -96,46 +94,33 @@ void tst_QDeclarativeDebugClient::name() QCOMPARE(client.name(), name); } -void tst_QDeclarativeDebugClient::isEnabled() +void tst_QDeclarativeDebugClient::status() { - QDeclarativeDebugClient client("tst_QDeclarativeDebugClient::isEnabled()", m_conn); - QCOMPARE(client.isEnabled(), false); -} + { + QDeclarativeDebugConnection dummyConn; + QDeclarativeDebugClient client("tst_QDeclarativeDebugClient::status()", &dummyConn); + QCOMPARE(client.status(), QDeclarativeDebugClient::NotConnected); + } -void tst_QDeclarativeDebugClient::setEnabled() -{ - QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::setEnabled()"); - QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::setEnabled()", m_conn); + QDeclarativeDebugTestClient client("tst_QDeclarativeDebugClient::status()", m_conn); + QCOMPARE(client.status(), QDeclarativeDebugClient::Unavailable); - QCOMPARE(service.isEnabled(), false); + { + QDeclarativeDebugTestService service("tst_QDeclarativeDebugClient::status()"); + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); + QCOMPARE(client.status(), QDeclarativeDebugClient::Enabled); + } + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); - client.setEnabled(true); - QCOMPARE(client.isEnabled(), true); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.isEnabled(), true); - - client.setEnabled(false); - QCOMPARE(client.isEnabled(), false); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.isEnabled(), false); -} - -void tst_QDeclarativeDebugClient::isConnected() -{ - QDeclarativeDebugClient client1("tst_QDeclarativeDebugClient::isConnected() A", m_conn); - QCOMPARE(client1.isConnected(), true); - - QDeclarativeDebugConnection conn; - QDeclarativeDebugClient client2("tst_QDeclarativeDebugClient::isConnected() B", &conn); - QCOMPARE(client2.isConnected(), false); - - QDeclarativeDebugClient client3("tst_QDeclarativeDebugClient::isConnected() C", 0); - QCOMPARE(client3.isConnected(), false); + QCOMPARE(client.status(), QDeclarativeDebugClient::Unavailable); // duplicate plugin name - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugClient: Conflicting plugin name \"tst_QDeclarativeDebugClient::isConnected() A\" "); - QDeclarativeDebugClient client4("tst_QDeclarativeDebugClient::isConnected() A", m_conn); - QCOMPARE(client4.isConnected(), false); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugClient: Conflicting plugin name \"tst_QDeclarativeDebugClient::status()\" "); + QDeclarativeDebugClient client2("tst_QDeclarativeDebugClient::status()", m_conn); + QCOMPARE(client2.status(), QDeclarativeDebugClient::NotConnected); + + QDeclarativeDebugClient client3("tst_QDeclarativeDebugClient::status3()", 0); + QCOMPARE(client3.status(), QDeclarativeDebugClient::NotConnected); } void tst_QDeclarativeDebugClient::sendMessage() @@ -145,6 +130,7 @@ void tst_QDeclarativeDebugClient::sendMessage() QByteArray msg = "hello!"; + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); client.sendMessage(msg); QByteArray resp = client.waitForResponse(); QCOMPARE(resp, msg); diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index 4683199..bce4713 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -66,8 +66,7 @@ private slots: void initTestCase(); void name(); - void isEnabled(); - void enabledChanged(); + void status(); void sendMessage(); void idForObject(); void objectForId(); @@ -97,31 +96,24 @@ void tst_QDeclarativeDebugService::name() QCOMPARE(service.name(), name); } -void tst_QDeclarativeDebugService::isEnabled() +void tst_QDeclarativeDebugService::status() { - QDeclarativeDebugTestService service("tst_QDeclarativeDebugService::isEnabled()", m_conn); - QCOMPARE(service.isEnabled(), false); + QDeclarativeDebugTestService service("tst_QDeclarativeDebugService::status()"); + QCOMPARE(service.status(), QDeclarativeDebugService::Unavailable); - QDeclarativeDebugTestClient client("tst_QDeclarativeDebugService::isEnabled()", m_conn); - client.setEnabled(true); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.isEnabled(), true); + { + QDeclarativeDebugTestClient client("tst_QDeclarativeDebugService::status()", m_conn); + QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(statusHasChanged())); + QCOMPARE(service.status(), QDeclarativeDebugService::Enabled); + } - QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugService: Conflicting plugin name \"tst_QDeclarativeDebugService::isEnabled()\" "); - QDeclarativeDebugService duplicate("tst_QDeclarativeDebugService::isEnabled()", m_conn); - QCOMPARE(duplicate.isEnabled(), false); -} - -void tst_QDeclarativeDebugService::enabledChanged() -{ - QDeclarativeDebugTestService service("tst_QDeclarativeDebugService::enabledChanged()"); - QDeclarativeDebugTestClient client("tst_QDeclarativeDebugService::enabledChanged()", m_conn); + QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(statusHasChanged())); + QCOMPARE(service.status(), QDeclarativeDebugService::Unavailable); - QCOMPARE(service.enabled, false); + QTest::ignoreMessage(QtWarningMsg, "QDeclarativeDebugService: Conflicting plugin name \"tst_QDeclarativeDebugService::status()\" "); - client.setEnabled(true); - QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(enabledStateChanged())); - QCOMPARE(service.enabled, true); + QDeclarativeDebugService duplicate("tst_QDeclarativeDebugService::status()"); + QCOMPARE(duplicate.status(), QDeclarativeDebugService::NotConnected); } void tst_QDeclarativeDebugService::sendMessage() @@ -131,6 +123,11 @@ void tst_QDeclarativeDebugService::sendMessage() QByteArray msg = "hello!"; + if (service.status() != QDeclarativeDebugService::Enabled) + QDeclarativeDebugTest::waitForSignal(&service, SIGNAL(statusHasChanged())); + if (client.status() != QDeclarativeDebugClient::Enabled) + QDeclarativeDebugTest::waitForSignal(&client, SIGNAL(statusHasChanged())); + client.sendMessage(msg); QByteArray resp = client.waitForResponse(); QCOMPARE(resp, msg); diff --git a/tests/auto/declarative/shared/debugutil.cpp b/tests/auto/declarative/shared/debugutil.cpp index c0c3eca..5f68e44 100644 --- a/tests/auto/declarative/shared/debugutil.cpp +++ b/tests/auto/declarative/shared/debugutil.cpp @@ -60,7 +60,7 @@ bool QDeclarativeDebugTest::waitForSignal(QObject *receiver, const char *member, } QDeclarativeDebugTestService::QDeclarativeDebugTestService(const QString &s, QObject *parent) - : QDeclarativeDebugService(s, parent), enabled(false) + : QDeclarativeDebugService(s, parent) { } @@ -69,10 +69,9 @@ void QDeclarativeDebugTestService::messageReceived(const QByteArray &ba) sendMessage(ba); } -void QDeclarativeDebugTestService::enabledChanged(bool e) +void QDeclarativeDebugTestService::statusChanged(Status) { - enabled = e; - emit enabledStateChanged(); + emit statusHasChanged(); } @@ -92,9 +91,13 @@ QByteArray QDeclarativeDebugTestClient::waitForResponse() return lastMsg; } +void QDeclarativeDebugTestClient::statusChanged(Status status) +{ + emit statusHasChanged(); +} + void QDeclarativeDebugTestClient::messageReceived(const QByteArray &ba) { lastMsg = ba; emit serverMessage(ba); } - diff --git a/tests/auto/declarative/shared/debugutil_p.h b/tests/auto/declarative/shared/debugutil_p.h index e6bb7ad..434e053 100644 --- a/tests/auto/declarative/shared/debugutil_p.h +++ b/tests/auto/declarative/shared/debugutil_p.h @@ -62,15 +62,13 @@ class QDeclarativeDebugTestService : public QDeclarativeDebugService Q_OBJECT public: QDeclarativeDebugTestService(const QString &s, QObject *parent = 0); - bool enabled; signals: - void enabledStateChanged(); + void statusHasChanged(); protected: virtual void messageReceived(const QByteArray &ba); - - virtual void enabledChanged(bool e); + virtual void statusChanged(Status status); }; class QDeclarativeDebugTestClient : public QDeclarativeDebugClient @@ -82,9 +80,11 @@ public: QByteArray waitForResponse(); signals: + void statusHasChanged(); void serverMessage(const QByteArray &); protected: + virtual void statusChanged(Status status); virtual void messageReceived(const QByteArray &ba); private: -- cgit v0.12 From 31dcf2b4028b1f76301fc69fccff0a9474a0a135 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Mon, 27 Sep 2010 10:56:00 +0200 Subject: QDeclarativeDebugService: Add bc autotest Although it's a private header we use qdeclarativedebugservice_p.h in creator / qmljsdebugger library. Working with a copy of the header in the autotest hopefully catches some bc breakages. --- .../private_headers/qdeclarativedebugservice_p.h | 92 ++++++++++++++++++++++ .../qdeclarativedebugservice.pro | 3 +- .../tst_qdeclarativedebugservice.cpp | 2 +- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativedebugservice/private_headers/qdeclarativedebugservice_p.h diff --git a/tests/auto/declarative/qdeclarativedebugservice/private_headers/qdeclarativedebugservice_p.h b/tests/auto/declarative/qdeclarativedebugservice/private_headers/qdeclarativedebugservice_p.h new file mode 100644 index 0000000..0cadbe5 --- /dev/null +++ b/tests/auto/declarative/qdeclarativedebugservice/private_headers/qdeclarativedebugservice_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** 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 QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVICE_H +#define QDECLARATIVEDEBUGSERVICE_H + +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServicePrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeDebugService : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeDebugService) + Q_DISABLE_COPY(QDeclarativeDebugService) + +public: + explicit QDeclarativeDebugService(const QString &, QObject *parent = 0); + ~QDeclarativeDebugService(); + + QString name() const; + + enum Status { NotConnected, Unavailable, Enabled }; + Status status() const; + + void sendMessage(const QByteArray &); + + static int idForObject(QObject *); + static QObject *objectForId(int); + + static QString objectToString(QObject *obj); + + static bool isDebuggingEnabled(); + static bool hasDebuggingClient(); + +protected: + virtual void statusChanged(Status); + virtual void messageReceived(const QByteArray &); + +private: + friend class QDeclarativeDebugServer; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_H + diff --git a/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro b/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro index a62e148..83bcadb 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro +++ b/tests/auto/declarative/qdeclarativedebugservice/qdeclarativedebugservice.pro @@ -2,7 +2,8 @@ load(qttest_p4) contains(QT_CONFIG,declarative): QT += network declarative macx:CONFIG -= app_bundle -HEADERS += ../shared/debugutil_p.h +HEADERS += ../shared/debugutil_p.h \ + private_headers/qdeclarativedebugservice_p.h SOURCES += tst_qdeclarativedebugservice.cpp \ ../shared/debugutil.cpp diff --git a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp index bce4713..945823a 100644 --- a/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp +++ b/tests/auto/declarative/qdeclarativedebugservice/tst_qdeclarativedebugservice.cpp @@ -50,8 +50,8 @@ #include #include #include -#include +#include "private_headers/qdeclarativedebugservice_p.h" #include "../../../shared/util.h" #include "../shared/debugutil_p.h" -- cgit v0.12 From a42989e696eac94221ddb781a133afaec5b48b12 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 28 Sep 2010 09:43:35 +0200 Subject: QmlViewer: Fix assert on exit (Windows) The QApplication object in main() is already destroyed when showWarnings() is called. Create another instance in this case. (Note that the assert will only be triggered for debug builds, while qmlviewer is built in release mode by default). Task-number: QTBUG-14009 Reviewed-by: Thomas Hartmann --- tools/qml/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index 78cd64d..bf183e5 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -89,6 +89,9 @@ QString warnings; void showWarnings() { if (!warnings.isEmpty()) { + int argc = 0; char **argv = 0; + QApplication application(argc, argv); // QApplication() in main has been destroyed already. + Q_UNUSED(application) QMessageBox::warning(0, QApplication::tr("Qt QML Viewer"), warnings); } } -- cgit v0.12 From cf4c64a8f155c179f51d2cddd81bae4701826871 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 28 Sep 2010 09:54:11 +0200 Subject: QmlViewer: Fix typo in comment --- tools/qml/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp index bf183e5..00d43c1 100644 --- a/tools/qml/main.cpp +++ b/tools/qml/main.cpp @@ -519,7 +519,7 @@ int main(int argc, char ** argv) #if defined (Q_OS_WIN) // Debugging output is not visible by default on Windows - - // therefore show modal dialog with errors instad. + // therefore show modal dialog with errors instead. atexit(showWarnings); #endif -- cgit v0.12 From 746954581f06e0bca98f25eb95dca09c663d47bf Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 28 Sep 2010 18:50:18 +1000 Subject: If a type is registered under several names, share the attached property object Task-number: QTBUG-13799 --- .../qml/qdeclarativecompiledbindings.cpp | 10 ++++----- src/declarative/qml/qdeclarativecompiler.cpp | 2 +- src/declarative/qml/qdeclarativemetatype.cpp | 25 +++++++++++++++++++++- src/declarative/qml/qdeclarativemetatype_p.h | 1 + src/declarative/qml/qdeclarativeproperty.cpp | 4 ++-- .../qml/qdeclarativetypenamescriptclass.cpp | 2 +- .../data/sharedAttachedObject.qml | 16 ++++++++++++++ .../qdeclarativeecmascript/testtypes.cpp | 1 + .../tst_qdeclarativeecmascript.cpp | 11 ++++++++++ 9 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/sharedAttachedObject.qml diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 9402596..5f0fd56 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -438,7 +438,7 @@ struct Instr { qint8 output; qint8 reg; quint8 exceptionId; - quint32 index; + quint32 id; } attached; struct { QML_INSTR_HEADER @@ -988,7 +988,7 @@ static void dumpInstruction(const Instr *instr) qWarning().nospace() << "\t" << "LoadRoot" << "\t\t" << instr->load.index << "\t" << instr->load.reg; break; case Instr::LoadAttached: - qWarning().nospace() << "\t" << "LoadAttached" << "\t\t" << instr->attached.output << "\t" << instr->attached.reg << "\t" << instr->attached.index; + qWarning().nospace() << "\t" << "LoadAttached" << "\t\t" << instr->attached.output << "\t" << instr->attached.reg << "\t" << instr->attached.id; break; case Instr::ConvertIntToReal: qWarning().nospace() << "\t" << "ConvertIntToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src; @@ -1225,7 +1225,7 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, output.setUndefined(); } else { QObject *attached = - qmlAttachedPropertiesObjectById(instr->attached.index, + qmlAttachedPropertiesObjectById(instr->attached.id, registers[instr->attached.reg].getQObject(), true); Q_ASSERT(attached); @@ -1895,7 +1895,7 @@ bool QDeclarativeBindingCompilerPrivate::parseName(AST::Node *node, Result &type attach.common.type = Instr::LoadAttached; attach.attached.output = reg; attach.attached.reg = reg; - attach.attached.index = attachType->index(); + attach.attached.id = attachType->attachedPropertiesId(); attach.attached.exceptionId = exceptionId(nameNodes.at(ii)); bytecode << attach; @@ -2011,7 +2011,7 @@ bool QDeclarativeBindingCompilerPrivate::parseName(AST::Node *node, Result &type attach.common.type = Instr::LoadAttached; attach.attached.output = reg; attach.attached.reg = reg; - attach.attached.index = attachType->index(); + attach.attached.id = attachType->attachedPropertiesId(); bytecode << attach; absType = 0; diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index e55dc92..8c5fd3a 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -1407,7 +1407,7 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, COMPILE_EXCEPTION(prop, tr("Invalid attached object assignment")); Q_ASSERT(type->attachedPropertiesFunction()); - prop->index = type->index(); + prop->index = type->attachedPropertiesId(); prop->value->metatype = type->attachedPropertiesType(); } else { // Setup regular property data diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index a5c878f..7a78a1f 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -146,6 +146,7 @@ public: const QMetaObject *m_baseMetaObject; QDeclarativeAttachedPropertiesFunc m_attachedPropertiesFunc; const QMetaObject *m_attachedPropertiesType; + int m_attachedPropertiesId; int m_parserStatusCast; int m_propertyValueSourceCast; int m_propertyValueInterceptorCast; @@ -155,8 +156,12 @@ public: QDeclarativeCustomParser *m_customParser; mutable volatile bool m_isSetup:1; mutable QList m_metaObjects; + + static QHash m_attachedPropertyIds; }; +QHash QDeclarativeTypePrivate::m_attachedPropertyIds; + QDeclarativeTypePrivate::QDeclarativeTypePrivate() : m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), @@ -198,6 +203,14 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe d->m_baseMetaObject = type.metaObject; d->m_attachedPropertiesFunc = type.attachedPropertiesFunction; d->m_attachedPropertiesType = type.attachedPropertiesMetaObject; + if (d->m_attachedPropertiesType) { + QHash::Iterator iter = d->m_attachedPropertyIds.find(d->m_baseMetaObject); + if (iter == d->m_attachedPropertyIds.end()) + iter = d->m_attachedPropertyIds.insert(d->m_baseMetaObject, index); + d->m_attachedPropertiesId = *iter; + } else { + d->m_attachedPropertiesId = -1; + } d->m_parserStatusCast = type.parserStatusCast; d->m_propertyValueSourceCast = type.valueSourceCast; d->m_propertyValueInterceptorCast = type.valueInterceptorCast; @@ -461,6 +474,16 @@ const QMetaObject *QDeclarativeType::attachedPropertiesType() const return d->m_attachedPropertiesType; } +/* +This is the id passed to qmlAttachedPropertiesById(). This is different from the index +for the case that a single class is registered under two or more names (eg. Item in +Qt 4.7 and QtQuick 1.0). +*/ +int QDeclarativeType::attachedPropertiesId() const +{ + return d->m_attachedPropertiesId; +} + int QDeclarativeType::parserStatusCast() const { return d->m_parserStatusCast; @@ -662,7 +685,7 @@ int QDeclarativeMetaType::attachedPropertiesFuncId(const QMetaObject *mo) QDeclarativeType *type = data->metaObjectToType.value(mo); if (type && type->attachedPropertiesFunction()) - return type->index(); + return type->attachedPropertiesId(); else return -1; } diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index f410547..382abd2 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -137,6 +137,7 @@ public: QDeclarativeAttachedPropertiesFunc attachedPropertiesFunction() const; const QMetaObject *attachedPropertiesType() const; + int attachedPropertiesId() const; int parserStatusCast() const; QVariant fromObject(QObject *) const; diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index d0dd2e8..bc20bff 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -220,7 +220,7 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); if (!func) return; // Not an attachable type - currentObject = qmlAttachedPropertiesObjectById(data->type->index(), currentObject); + currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject); if (!currentObject) return; // Something is broken with the attachable type } else { Q_ASSERT(data->typeNamespace); @@ -232,7 +232,7 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction(); if (!func) return; // Not an attachable type - currentObject = qmlAttachedPropertiesObjectById(data->type->index(), currentObject); + currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject); if (!currentObject) return; // Something is broken with the attachable type } } else { diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp index 764a8db..cba7b4a 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp +++ b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp @@ -129,7 +129,7 @@ QDeclarativeTypeNameScriptClass::queryProperty(Object *obj, const Identifier &na return 0; } else if (data->object) { // Must be an attached property - object = qmlAttachedPropertiesObjectById(data->type->index(), data->object); + object = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), data->object); if (!object) return 0; return ep->objectClass->queryProperty(object, name, flags, 0); } diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/sharedAttachedObject.qml b/tests/auto/declarative/qdeclarativeecmascript/data/sharedAttachedObject.qml new file mode 100644 index 0000000..817391d --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/sharedAttachedObject.qml @@ -0,0 +1,16 @@ +import Qt.test 1.0 +import Qt 4.7 + +MyQmlObject { + id: root + property bool test1: false + property bool test2: false + + MyQmlObject.value2: 7 + + Component.onCompleted: { + test1 = root.MyQmlObject.value2 == 7; + test2 = root.MyQmlObjectAlias.value2 == 7; + } +} + diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp index 8a4605a..810a0f7 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.cpp @@ -102,6 +102,7 @@ public: void registerTypes() { + qmlRegisterType("Qt.test", 1,0, "MyQmlObjectAlias"); qmlRegisterType("Qt.test", 1,0, "MyQmlObject"); qmlRegisterType("Qt.test", 1,0, "MyDeferredObject"); qmlRegisterType("Qt.test", 1,0, "MyQmlContainer"); diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index c10a110..4feb630 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -161,6 +161,7 @@ private slots: void nonscriptable(); void deleteLater(); void in(); + void sharedAttachedObject(); void include(); @@ -2583,6 +2584,16 @@ void tst_qdeclarativeecmascript::in() delete o; } +void tst_qdeclarativeecmascript::sharedAttachedObject() +{ + QDeclarativeComponent component(&engine, TEST_FILE("sharedAttachedObject.qml")); + QObject *o = component.create(); + QVERIFY(o != 0); + QCOMPARE(o->property("test1").toBool(), true); + QCOMPARE(o->property("test2").toBool(), true); + delete o; +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" -- cgit v0.12 From 30959e88498b2c8591145e30c8b497a76c12d8f6 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 28 Sep 2010 12:24:55 +0200 Subject: QmlDebugService: Check that there is a receiver before sending messages Reviewed-by: Christiaan Janssen --- src/declarative/debugger/qdeclarativedebugservice.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index 0fbc1e3..62f2f39 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -182,7 +182,9 @@ void QDeclarativeDebugServer::newConnection() bool QDeclarativeDebugServer::hasDebuggingClient() const { Q_D(const QDeclarativeDebugServer); - return d->gotHello; + return d->connection + && (d->connection->state() == QTcpSocket::ConnectedState) + && d->gotHello; } QDeclarativeDebugServer *QDeclarativeDebugServer::instance() @@ -485,7 +487,7 @@ void QDeclarativeDebugService::sendMessage(const QByteArray &message) { Q_D(QDeclarativeDebugService); - if (!d->server || !d->server->d_func()->connection) + if (status() != Enabled) return; QPacket pack; -- cgit v0.12 From 9caae83e1f2b9c56ee86b8523391e6a83ea724c5 Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Tue, 28 Sep 2010 12:48:13 +0200 Subject: QDeclarativeDebugClient: Fix gcc warning --- src/declarative/debugger/qdeclarativedebugclient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp index f7d7243..ce3faf6 100644 --- a/src/declarative/debugger/qdeclarativedebugclient.cpp +++ b/src/declarative/debugger/qdeclarativedebugclient.cpp @@ -277,7 +277,7 @@ void QDeclarativeDebugClient::sendMessage(const QByteArray &message) d->client->d->protocol->send(pack); } -void QDeclarativeDebugClient::statusChanged(Status status) +void QDeclarativeDebugClient::statusChanged(Status) { } -- cgit v0.12