From 5a22a926f8f10597a431036533550f05fdf52d85 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 26 Aug 2009 13:34:42 +0200 Subject: implement proxying of JSObject::putWithAttributes() on Global Object Otherwise the property is stored on the wrong object (the proxy). This fix makes the Qt bindings generated by qtscriptgenerator work again. --- src/script/bridge/qscriptglobalobject.cpp | 9 +++++++++ src/script/bridge/qscriptglobalobject_p.h | 4 ++++ tests/auto/qscriptengine/tst_qscriptengine.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/src/script/bridge/qscriptglobalobject.cpp b/src/script/bridge/qscriptglobalobject.cpp index c929e12..3fa5879 100644 --- a/src/script/bridge/qscriptglobalobject.cpp +++ b/src/script/bridge/qscriptglobalobject.cpp @@ -100,6 +100,15 @@ void GlobalObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName JSC::JSGlobalObject::put(exec, propertyName, value, slot); } +void GlobalObject::putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, + JSC::JSValue value, unsigned attributes) +{ + if (customGlobalObject) + customGlobalObject->putWithAttributes(exec, propertyName, value, attributes); + else + JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes); +} + bool GlobalObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, bool checkDontDelete) { diff --git a/src/script/bridge/qscriptglobalobject_p.h b/src/script/bridge/qscriptglobalobject_p.h index eff24a2..11b1482 100644 --- a/src/script/bridge/qscriptglobalobject_p.h +++ b/src/script/bridge/qscriptglobalobject_p.h @@ -74,6 +74,8 @@ public: JSC::PropertySlot&); virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); + virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, + JSC::JSValue value, unsigned attributes); virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName, bool checkDontDelete = true); @@ -115,6 +117,8 @@ public: virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot) { originalGlobalObject->JSC::JSGlobalObject::put(exec, propertyName, value, slot); } + virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, unsigned attributes) + { originalGlobalObject->JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes); } virtual bool deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, bool checkDontDelete = true) { return originalGlobalObject->JSC::JSGlobalObject::deleteProperty(exec, propertyName, checkDontDelete); } diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index df74144..b0ba922 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -1107,6 +1107,31 @@ void tst_QScriptEngine::globalObjectProperties() } } QVERIFY(remainingNames.isEmpty()); + + // create property with no attributes + { + QString name = QString::fromLatin1("foo"); + QVERIFY(!global.property(name).isValid()); + QScriptValue val(123); + global.setProperty(name, val); + QVERIFY(global.property(name).equals(val)); + QVERIFY(global.propertyFlags(name) == 0); + global.setProperty(name, QScriptValue()); + QVERIFY(!global.property(name).isValid()); + } + // create property with attributes + { + QString name = QString::fromLatin1("bar"); + QVERIFY(!global.property(name).isValid()); + QScriptValue val(QString::fromLatin1("ciao")); + QScriptValue::PropertyFlags flags = QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration; + global.setProperty(name, val, flags); + QVERIFY(global.property(name).equals(val)); + QEXPECT_FAIL("", "custom Global Object properties don't retain attributes", Continue); + QCOMPARE(global.propertyFlags(name), flags); + global.setProperty(name, QScriptValue()); + QVERIFY(!global.property(name).isValid()); + } } void tst_QScriptEngine::globalObjectGetterSetterProperty() -- cgit v0.12 From de3939532af08c37e709d1bae8cf50a57d6f63be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 26 Aug 2009 10:54:33 +0200 Subject: Added missing precision specifiers to custom shader effect. The precision specifiers need to be there on OpenGL ES 2.0. Reviewed-by: Tom --- examples/effects/customshader/customshadereffect.cpp | 2 +- src/opengl/gl2paintengineex/qglengineshadermanager_p.h | 2 +- src/opengl/gl2paintengineex/qglengineshadersource_p.h | 2 +- src/opengl/qglpixmapfilter.cpp | 2 +- src/opengl/qgraphicsshadereffect.cpp | 10 +++++----- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/effects/customshader/customshadereffect.cpp b/examples/effects/customshader/customshadereffect.cpp index 08e4324..69fdb15 100644 --- a/examples/effects/customshader/customshadereffect.cpp +++ b/examples/effects/customshader/customshadereffect.cpp @@ -44,7 +44,7 @@ static char const colorizeShaderCode[] = "uniform lowp vec4 effectColor;\n" - "mediump vec4 customShader(sampler2D imageTexture, vec2 textureCoords) {\n" + "mediump vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {\n" " vec4 src = texture2D(imageTexture, textureCoords);\n" " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n" " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n" diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index d5241a8..ace6b63 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -209,7 +209,7 @@ (QGLCustomShaderStage). The shader will implement a pre-defined method name which Qt's fragment pipeline will call: - lowp vec4 customShader(sampler2d src, vec2 srcCoords) + lowp vec4 customShader(lowp sampler2d imageTexture, highp vec2 textureCoords) The provided src and srcCoords parameters can be used to sample from the source image. diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index cf930f3..a8e2e72 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -293,7 +293,7 @@ static const char* const qglslImageSrcFragmentShader = "\ static const char* const qglslCustomSrcFragmentShader = "\ varying highp vec2 textureCoords; \ uniform sampler2D imageTexture; \ - lowp vec4 customShader(sampler2D texture, vec2 coords); \ + lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \ lowp vec4 srcPixel() { \ return customShader(imageTexture, textureCoords); \ }"; diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index e1ee61a..df7811e 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -418,7 +418,7 @@ QByteArray QGLPixmapBlurFilter::generateBlurShader(int radius, bool gaussianBlur source.append("uniform highp vec4 clip;\n"); } - source.append("lowp vec4 customShader(sampler2D src, vec2 srcCoords) {\n"); + source.append("lowp vec4 customShader(lowp sampler2D src, highp vec2 srcCoords) {\n"); QVector sampleOffsets; QVector weights; diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index d3f52f6..5e37d62 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE The specific effect is defined by a fragment of GLSL source code supplied to setPixelShaderFragment(). This source code must define a function with the signature - \c{lowp vec4 customShader(sampler2D imageTexture, vec2 textureCoords)} + \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)} that returns the source pixel value to use in the paint engine's shader program. The shader fragment is linked with the regular shader code used by the GL2 paint engine @@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE \code static char const colorizeShaderCode[] = "uniform lowp vec4 effectColor;\n" - "lowp vec4 customShader(sampler2D imageTexture, vec2 textureCoords) {\n" + "lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) {\n" " vec4 src = texture2D(imageTexture, textureCoords);\n" " float gray = dot(src.rgb, vec3(0.212671, 0.715160, 0.072169));\n" " vec4 colorize = 1.0-((1.0-gray)*(1.0-effectColor));\n" @@ -130,7 +130,7 @@ QT_BEGIN_NAMESPACE */ static const char qglslDefaultImageFragmentShader[] = "\ - lowp vec4 customShader(sampler2D imageTexture, vec2 textureCoords) { \ + lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) { \ return texture2D(imageTexture, textureCoords); \ }\n"; @@ -215,13 +215,13 @@ QByteArray QGraphicsShaderEffect::pixelShaderFragment() const this shader effect to \a code. The \a code must define a GLSL function with the signature - \c{lowp vec4 customShader(sampler2D imageTexture, vec2 textureCoords)} + \c{lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords)} that returns the source pixel value to use in the paint engine's shader program. The following is the default pixel shader fragment, which draws a pixmap with no effect applied: \code - lowp vec4 customShader(sampler2D imageTexture, vec2 textureCoords) { + lowp vec4 customShader(lowp sampler2D imageTexture, highp vec2 textureCoords) { return texture2D(imageTexture, textureCoords); } \endcode -- cgit v0.12 From e9ffb5b0918e800edfba6b697c7a14ef6c7fa8e1 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 26 Aug 2009 13:57:29 +0200 Subject: fix performance issue with QScriptValue::propertyFlags() Calling QScriptEngine::toStringHandle() is dead slow, so don't call it; use JSC::Identifier directly. This is the same issue as was fixed for setProperty() in commit a8574172dd5e6bc11cf6f69b6fad5a063549e88d. --- src/script/api/qscriptvalue.cpp | 65 ++++++++++++---------- src/script/api/qscriptvalue_p.h | 2 + tests/auto/qscriptvalue/tst_qscriptvalue.cpp | 1 + tests/benchmarks/qscriptvalue/tst_qscriptvalue.cpp | 12 ++++ 4 files changed, 52 insertions(+), 28 deletions(-) diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 1d08676..984ad1b 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -393,6 +393,37 @@ void QScriptValuePrivate::setProperty(const JSC::Identifier &id, const QScriptVa } } +QScriptValue::PropertyFlags QScriptValuePrivate::propertyFlags(const JSC::Identifier &id, + const QScriptValue::ResolveFlags &mode) const +{ + JSC::ExecState *exec = engine->currentFrame; + JSC::JSObject *object = JSC::asObject(jscValue); + unsigned attribs = 0; + if (!object->getPropertyAttributes(exec, id, attribs)) { + if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) { + QScriptValue proto = engine->scriptValueFromJSCValue(object->prototype()); + return QScriptValuePrivate::get(proto)->propertyFlags(id, mode); + } + return 0; + } + QScriptValue::PropertyFlags result = 0; + if (attribs & JSC::ReadOnly) + result |= QScriptValue::ReadOnly; + if (attribs & JSC::DontEnum) + result |= QScriptValue::SkipInEnumeration; + if (attribs & JSC::DontDelete) + result |= QScriptValue::Undeletable; + //We cannot rely on attribs JSC::Setter/Getter because they are not necesserly set by JSC (bug?) + if (attribs & JSC::Getter || !object->lookupGetter(exec, id).isUndefinedOrNull()) + result |= QScriptValue::PropertyGetter; + if (attribs & JSC::Setter || !object->lookupSetter(exec, id).isUndefinedOrNull()) + result |= QScriptValue::PropertySetter; + if (attribs & QScript::QObjectMemberAttribute) + result |= QScriptValue::QObjectMember; + result |= QScriptValue::PropertyFlag(attribs & QScriptValue::UserRange); + return result; +} + QVariant &QScriptValuePrivate::variantValue() const { Q_ASSERT(jscValue.isObject(&QScriptObject::info)); @@ -1817,9 +1848,11 @@ void QScriptValue::setProperty(const QScriptString &name, QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name, const ResolveFlags &mode) const { - if (!isObject()) + Q_D(const QScriptValue); + if (!d || !d->isJSC() || !d->jscValue.isObject()) return 0; - return propertyFlags(engine()->toStringHandle(name), mode); + JSC::ExecState *exec = d->engine->currentFrame; + return d->propertyFlags(JSC::Identifier(exec, name), mode); } @@ -1835,33 +1868,9 @@ QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &nam const ResolveFlags &mode) const { Q_D(const QScriptValue); - if (!isObject()) - return 0; - JSC::ExecState *exec = d->engine->currentFrame; - JSC::JSObject *object = JSC::asObject(d->jscValue); - JSC::Identifier id = name.d_ptr->identifier; - unsigned attribs = 0; - if (!object->getPropertyAttributes(exec, id, attribs)) { - if ((mode & QScriptValue::ResolvePrototype) && object->prototype()) - return d->engine->scriptValueFromJSCValue(object->prototype()).propertyFlags(name, mode); + if (!d || !d->isJSC() || !d->jscValue.isObject() || !name.isValid()) return 0; - } - QScriptValue::PropertyFlags result = 0; - if (attribs & JSC::ReadOnly) - result |= QScriptValue::ReadOnly; - if (attribs & JSC::DontEnum) - result |= QScriptValue::SkipInEnumeration; - if (attribs & JSC::DontDelete) - result |= QScriptValue::Undeletable; - //We cannot rely on attribs JSC::Setter/Getter because they are not necesserly set by JSC (bug?) - if (attribs & JSC::Getter || !object->lookupGetter(exec, id).isUndefinedOrNull()) - result |= QScriptValue::PropertyGetter; - if (attribs & JSC::Setter || !object->lookupSetter(exec, id).isUndefinedOrNull()) - result |= QScriptValue::PropertySetter; - if (attribs & QScript::QObjectMemberAttribute) - result |= QScriptValue::QObjectMember; - result |= QScriptValue::PropertyFlag(attribs & QScriptValue::UserRange); - return result; + return d->propertyFlags(name.d_ptr->identifier, mode); } /*! diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h index 3e952af..c440013 100644 --- a/src/script/api/qscriptvalue_p.h +++ b/src/script/api/qscriptvalue_p.h @@ -104,6 +104,8 @@ public: inline QScriptValue property(const QString &, int resolveMode) const; void setProperty(const JSC::Identifier &id, const QScriptValue &value, const QScriptValue::PropertyFlags &flags); + QScriptValue::PropertyFlags propertyFlags( + const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode) const; void detachFromEngine(); diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index 3f231f2..e712017 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -2106,6 +2106,7 @@ void tst_QScriptValue::getSetProperty() object.setProperty(foo, num); QVERIFY(object.property(foo).strictlyEquals(num)); QVERIFY(object.property("foo").strictlyEquals(num)); + QVERIFY(object.propertyFlags(foo) == 0); } void tst_QScriptValue::getSetPrototype() diff --git a/tests/benchmarks/qscriptvalue/tst_qscriptvalue.cpp b/tests/benchmarks/qscriptvalue/tst_qscriptvalue.cpp index 904674e..b637591 100644 --- a/tests/benchmarks/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/benchmarks/qscriptvalue/tst_qscriptvalue.cpp @@ -68,6 +68,7 @@ private slots: void toQObject(); void property(); void setProperty(); + void propertyFlags(); }; tst_QScriptValue::tst_QScriptValue() @@ -189,5 +190,16 @@ void tst_QScriptValue::setProperty() } } +void tst_QScriptValue::propertyFlags() +{ + QScriptEngine engine; + QScriptValue obj = engine.newObject(); + QString propertyName = QString::fromLatin1("foo"); + obj.setProperty(propertyName, 123, QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly); + QBENCHMARK { + (void)obj.propertyFlags(propertyName); + } +} + QTEST_MAIN(tst_QScriptValue) #include "tst_qscriptvalue.moc" -- cgit v0.12 From b5f00cdc0a63ea598d7af908240f0de5ac141262 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 26 Aug 2009 13:49:42 +0200 Subject: QToolbar now collapses when dragged Previously it wouldn't and the layout could appear to be broken. Task-number: 248817 Reviewed-by: Gabriel De Dietrich --- src/gui/widgets/qtoolbar.cpp | 2 +- src/gui/widgets/qtoolbarlayout.cpp | 4 ++-- src/gui/widgets/qtoolbarlayout_p.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp index bf44ea1..89e6d7a 100644 --- a/src/gui/widgets/qtoolbar.cpp +++ b/src/gui/widgets/qtoolbar.cpp @@ -391,7 +391,7 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event) void QToolBarPrivate::unplug(const QRect &_r) { Q_Q(QToolBar); - + layout->setExpanded(false, false); QRect r = _r; r.moveTopLeft(q->mapToGlobal(QPoint(0, 0))); setWindowState(true, true, r); diff --git a/src/gui/widgets/qtoolbarlayout.cpp b/src/gui/widgets/qtoolbarlayout.cpp index d3c5b4b..1f2ca60 100644 --- a/src/gui/widgets/qtoolbarlayout.cpp +++ b/src/gui/widgets/qtoolbarlayout.cpp @@ -642,7 +642,7 @@ QSize QToolBarLayout::expandedSize(const QSize &size) const return result; } -void QToolBarLayout::setExpanded(bool exp) +void QToolBarLayout::setExpanded(bool exp, bool animated) { if (exp == expanded) return; @@ -665,7 +665,7 @@ void QToolBarLayout::setExpanded(bool exp) layoutActions(rect.size()); } } - layout->layoutState.toolBarAreaLayout.apply(true); + layout->layoutState.toolBarAreaLayout.apply(animated); } } diff --git a/src/gui/widgets/qtoolbarlayout_p.h b/src/gui/widgets/qtoolbarlayout_p.h index fe81d2f..bb40e215 100644 --- a/src/gui/widgets/qtoolbarlayout_p.h +++ b/src/gui/widgets/qtoolbarlayout_p.h @@ -111,8 +111,8 @@ public: void updateMarginAndSpacing(); bool hasExpandFlag() const; -public slots: - void setExpanded(bool b); +public Q_SLOTS: + void setExpanded(bool b, bool animated = true); private: QList items; -- cgit v0.12 From d0f31c800b90a57c622d5d0d41b6fc3c2f9f9b49 Mon Sep 17 00:00:00 2001 From: Leonardo Sobral Cunha Date: Wed, 26 Aug 2009 14:13:17 +0200 Subject: Fixes typo in doc and missing return in anchor layout Reviewed-by: janarve --- src/gui/graphicsview/qgraphicsanchorlayout.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index 2894c59..b088f12 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -65,8 +65,9 @@ automatically added to the layout, and if items are removed, all their anchors will be automatically removed - \section1 Size Hints and Size Policies in QGraphicsLinearLayout - QGraphicsLinearLayout respects each item's size hints and size policies. However it does + \section1 Size Hints and Size Policies in QGraphicsAnchorLayout + + QGraphicsAnchorLayout respects each item's size hints and size policies. However it does not respect stretch factors currently. This might change in the future, so please refrain from using stretch factors in anchor layout to avoid any future regressions. @@ -228,6 +229,7 @@ void QGraphicsAnchorLayout::setAnchorSpacing(const QGraphicsLayoutItem *firstIte if (!d->setAnchorSize(firstItem, firstEdge, secondItem, secondEdge, &spacing)) { qWarning("setAnchorSpacing: The anchor does not exist."); + return; } invalidate(); } -- cgit v0.12 From 38d04ac09a3916ad33489e0d60e87c32f86fd117 Mon Sep 17 00:00:00 2001 From: Jedrzej Nowacki Date: Wed, 26 Aug 2009 14:07:25 +0200 Subject: Fix column number in QScriptEngineAgent with JIT enabled Column number in executed JS source code is correctly passed to debugger. Few autotest were repaired. Reviewed-by: Kent Hansen --- src/3rdparty/webkit/JavaScriptCore/jit/JITOpcodes.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/3rdparty/webkit/JavaScriptCore/jit/JITOpcodes.cpp b/src/3rdparty/webkit/JavaScriptCore/jit/JITOpcodes.cpp index b669dfa..8371229 100644 --- a/src/3rdparty/webkit/JavaScriptCore/jit/JITOpcodes.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/jit/JITOpcodes.cpp @@ -763,6 +763,7 @@ void JIT::emit_op_debug(Instruction* currentInstruction) stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); + stubCall.addArgument(Imm32(currentInstruction[4].u.operand)); stubCall.call(); } -- cgit v0.12 From 2eaf970b886c4c5c70fbc8d3081f8b572d0cfdf5 Mon Sep 17 00:00:00 2001 From: Jason Barron Date: Wed, 26 Aug 2009 14:24:37 +0200 Subject: Remove superfluous '.data()' call from dashStroker. The extra ".data()" call is not needed here because QScopedPointer overloads operator!() to do the right thing here. Reviewed-by: Eskil Blomfeldt --- src/gui/painting/qpaintengine_raster.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 72bb164..5f6e1d6 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -791,7 +791,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen) if(pen_style == Qt::SolidLine) { s->stroker = &d->basicStroker; } else if (pen_style != Qt::NoPen) { - if (!d->dashStroker.data()) + if (!d->dashStroker) d->dashStroker.reset(new QDashStroker(&d->basicStroker)); if (pen.isCosmetic()) { d->dashStroker->setClipRect(d->deviceRect); -- cgit v0.12 From a49d181c2700123a0c9af922c86b89914b402e9d Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 26 Aug 2009 11:26:53 +0200 Subject: Compile fix for mingw --- src/3rdparty/phonon/ds9/backend.h | 2 +- src/3rdparty/phonon/ds9/mediaobject.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/3rdparty/phonon/ds9/backend.h b/src/3rdparty/phonon/ds9/backend.h index 9b2c2a2..8b020c2 100644 --- a/src/3rdparty/phonon/ds9/backend.h +++ b/src/3rdparty/phonon/ds9/backend.h @@ -64,7 +64,7 @@ namespace Phonon Filter getAudioOutputFilter(int index) const; - static QMutex *Backend::directShowMutex(); + static QMutex *directShowMutex(); Q_SIGNALS: void objectDescriptionChanged(ObjectDescriptionType); diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp index 579517f..e42dff9 100644 --- a/src/3rdparty/phonon/ds9/mediaobject.cpp +++ b/src/3rdparty/phonon/ds9/mediaobject.cpp @@ -21,9 +21,7 @@ along with this library. If not, see . #include #include -#ifndef Q_CC_MSVC #include -#endif //Q_CC_MSVC #include #include #include -- cgit v0.12 From b69a8a9f6a88f6da971fd18641cfac26cc1035f5 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 26 Aug 2009 14:38:48 +0200 Subject: Revert "qglobal.h now has the definition for WINVER" This reverts commit f7ebdd380d16a7be9713930b5ab41c32e996dcdb. defining WINVER in qglobal.h is about to be reverted. --- src/corelib/global/qt_windows.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h index 6e3f242..dd722f9 100644 --- a/src/corelib/global/qt_windows.h +++ b/src/corelib/global/qt_windows.h @@ -53,6 +53,13 @@ #endif #endif +#if defined(Q_CC_MINGW) +// mingw's windows.h does not set _WIN32_WINNT, resulting breaking compilation +#ifndef WINVER +#define WINVER 0x500 +#endif +#endif + #include #ifdef _WIN32_WCE -- cgit v0.12 From f607562328a7c7f9ee0c7048aba365dcea042b4f Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 26 Aug 2009 14:39:29 +0200 Subject: Doc: Noted a limitation in using slashes in settings section names. Task-number: 254511 Reviewed-by: Trust Me --- src/corelib/io/qsettings.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 8612e03..db0c696 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -2118,12 +2118,12 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, Custom types registered using qRegisterMetaType() and qRegisterMetaTypeStreamOperators() can be stored using QSettings. - \section1 Key Syntax + \section1 Section and Key Syntax Setting keys can contain any Unicode characters. The Windows registry and INI files use case-insensitive keys, whereas the Carbon Preferences API on Mac OS X uses case-sensitive keys. To - avoid portability problems, follow these two simple rules: + avoid portability problems, follow these simple rules: \list 1 \o Always refer to the same key using the same case. For example, @@ -2134,7 +2134,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, example, if you have a key called "MainWindow", don't try to save another key as "mainwindow". - \o Do not use slashes ('/' and '\\') in key names; the + \o Do not use slashes ('/' and '\\') in section or key names; the backslash character is used to separate sub keys (see below). On windows '\\' are converted by QSettings to '/', which makes them identical. -- cgit v0.12 From eb39ecce531f67b4f8b791f76796ab9010c9e745 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 26 Aug 2009 14:59:51 +0200 Subject: Avoid undefined text metrics when GetTextMetrics() in QFontEngineWin If GetTextMetrics() should fail, the results are undefined. When the undefined data are used, e.g. when painting text, this can cause a crash. To avoid the crash and make it clear that the metrics cannot be retrieved, we zero out the entire structure. Task-number: 251172 Reviewed-by: gunnar --- src/gui/text/qfontengine_win.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp index 173b822..7a9d958 100644 --- a/src/gui/text/qfontengine_win.cpp +++ b/src/gui/text/qfontengine_win.cpp @@ -327,8 +327,10 @@ QFontEngineWin::QFontEngineWin(const QString &name, HFONT _hfont, bool stockFont BOOL res = GetTextMetrics(hdc, &tm); fontDef.fixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH); - if (!res) + if (!res) { qErrnoWarning("QFontEngineWin: GetTextMetrics failed"); + ZeroMemory(&tm, sizeof(TEXTMETRIC)); + } cache_cost = tm.tmHeight * tm.tmAveCharWidth * 2000; getCMap(); -- cgit v0.12 From 42ff4d0a4c5af1f4e136f5772706367f1775c4bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 26 Aug 2009 15:05:25 +0200 Subject: doc: fixes qdoc warnings/errors related to the Graphics Effect framework. Reviewed-by: Kavindra --- src/gui/effects/qgraphicseffect.cpp | 206 +++++++++++++++++++++++------------ src/gui/kernel/qwidget.cpp | 9 ++ src/opengl/qgraphicsshadereffect.cpp | 2 +- 3 files changed, 145 insertions(+), 72 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 9ed01df..0289914 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -108,7 +108,7 @@ QT_BEGIN_NAMESPACE /*! \class QGraphicsEffectSource - \brief The QGraphicsEffectSource represents the source on which a + \brief The QGraphicsEffectSource class represents the source on which a QGraphicsEffect is installed on. \since 4.6 @@ -119,12 +119,19 @@ QT_BEGIN_NAMESPACE QGraphicsEffectSource also provides a pixmap() function which creates a pixmap with the source painted into it. - \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect. + \sa QGraphicsItem::setGraphicsEffect(), QWidget::setGraphicsEffect(). +*/ + +/*! + \internal */ QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent) : QObject(dd, parent) {} +/*! + Destroys the effect source. +*/ QGraphicsEffectSource::~QGraphicsEffectSource() {} @@ -167,8 +174,8 @@ const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const } /*! - Returns a pointer to the widget if this source is a QWidget; otherwis - returns 0. + Returns a pointer to the widget if this source is a QWidget; otherwise + returns 0. \sa graphicsItem() */ @@ -199,7 +206,6 @@ const QStyleOption *QGraphicsEffectSource::styleOption() const \sa QGraphicsEffect::draw() */ - void QGraphicsEffectSource::draw(QPainter *painter) { d_func()->draw(painter); @@ -312,8 +318,6 @@ QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const Using this property, you can disable certain effects on slow platforms, in order to ensure that the user interface is responsive. - - \sa enabledChanged() */ bool QGraphicsEffect::isEnabled() const { @@ -337,6 +341,7 @@ void QGraphicsEffect::setEnabled(bool enable) \fn void QGraphicsEffect::enabledChanged(bool enabled) This signal is emitted whenever the effect is enabled or disabled. + The \a enabled parameter holds the effects's new enabled state. \sa isEnabled() */ @@ -423,15 +428,26 @@ void QGraphicsEffect::sourceChanged(ChangeFlags flags) \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ + +/*! + Constructs a new QGraphicsGrayscale instance. + The \a parent parameter is passed to QGraphicsEffect's constructor. +*/ QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate, parent) { } +/*! + Destroys the effect. +*/ QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() { } +/*! + \reimp +*/ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsGrayscaleEffect); @@ -454,7 +470,7 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so /*! \class QGraphicsColorizeEffect - \brief The QGraphicsColorizeEffect provides a colorize effect. + \brief The QGraphicsColorizeEffect class provides a colorize effect. \since 4.6 A colorize effect renders the source with a tint of its color(). The color @@ -465,31 +481,35 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsOpacityEffect */ + +/*! + Constructs a new QGraphicsColorizeEffect instance. + The \a parent parameter is passed to QGraphicsEffect's constructor. +*/ QGraphicsColorizeEffect::QGraphicsColorizeEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsColorizeEffectPrivate, parent) { } +/*! + Destroys the effect. +*/ QGraphicsColorizeEffect::~QGraphicsColorizeEffect() { } /*! - Returns the color. + \property QGraphicsColorizeEffect::color + \brief the color of the effect. - \sa setColor(), colorChanged() -*/ + By default, the color is light blue (QColor(0, 0, 192)). +*/; QColor QGraphicsColorizeEffect::color() const { Q_D(const QGraphicsColorizeEffect); return d->filter->color(); } -/*! - Sets the color to the given \a color. - - \sa color(), colorChanged() -*/ void QGraphicsColorizeEffect::setColor(const QColor &color) { Q_D(QGraphicsColorizeEffect); @@ -504,8 +524,12 @@ void QGraphicsColorizeEffect::setColor(const QColor &color) \fn void QGraphicsColorizeEffect::colorChanged(const QColor &color) This signal is emitted whenever the effect's color changes. + The \a color parameter holds the effect's new color. */ +/*! + \reimp +*/ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsColorizeEffect); @@ -527,7 +551,7 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou /*! \class QGraphicsPixelizeEffect - \brief The QGraphicsPixelizeEffect provides a pixelize effect. + \brief The QGraphicsPixelizeEffect class provides a pixelize effect. \since 4.6 A pixelize effect renders the source in lower resolution. This effect is @@ -539,19 +563,31 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ + +/*! + Constructs a new QGraphicsPixelizeEffect instance. + The \a parent parameter is passed to QGraphicsEffect's constructor. +*/ QGraphicsPixelizeEffect::QGraphicsPixelizeEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsPixelizeEffectPrivate, parent) { } +/*! + Destroys the effect. +*/ QGraphicsPixelizeEffect::~QGraphicsPixelizeEffect() { } /*! - Returns the size of a pixel. + \property QGraphicsPixelizeEffect::pixelSize + \brief the size of a pixel in the effect. - \sa setPixelSize(), pixelSizeChanged() + Setting the pixel size to 2 means two pixels in the source will be used to + represent one pixel. Using a bigger size results in lower resolution. + + By default, the pixel size is 3. */ int QGraphicsPixelizeEffect::pixelSize() const { @@ -559,14 +595,6 @@ int QGraphicsPixelizeEffect::pixelSize() const return d->pixelSize; } -/*! - Sets the size of a pixel to the given \a size. - - Setting \a size to 2 means two pixels in the source will be used to - represent one pixel. Using a bigger size results in lower resolution. - - \sa pixelSize(), pixelSizeChanged() -*/ void QGraphicsPixelizeEffect::setPixelSize(int size) { Q_D(QGraphicsPixelizeEffect); @@ -581,6 +609,7 @@ void QGraphicsPixelizeEffect::setPixelSize(int size) \fn void QGraphicsPixelizeEffect::pixelSizeChanged(int size) This signal is emitted whenever the effect's pixel size changes. + The \a size parameter holds the effect's new pixel size. */ static inline void pixelize(QImage *image, int pixelSize) @@ -604,6 +633,9 @@ static inline void pixelize(QImage *image, int pixelSize) } } +/*! + \reimp +*/ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsPixelizeEffect); @@ -636,7 +668,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou /*! \class QGraphicsBlurEffect - \brief The QGraphicsBlurEffect provides a blur effect. + \brief The QGraphicsBlurEffect class provides a blur effect. \since 4.6 A blur effect blurs the source. This effect is useful for reducing details, @@ -649,19 +681,31 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou \sa QGraphicsDropShadowEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ + +/*! + Constructs a new QGraphicsBlurEffect instance. + The \a parent parameter is passed to QGraphicsEffect's constructor. +*/ QGraphicsBlurEffect::QGraphicsBlurEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsBlurEffectPrivate, parent) { } +/*! + Destroys the effect. +*/ QGraphicsBlurEffect::~QGraphicsBlurEffect() { } /*! - Returns the blur radius. + \property QGraphicsBlurEffect::blurRadius + \brief the blur radius of the effect. + + Using a smaller radius results in a sharper appearance, whereas a bigger + radius results in a more blurred appearance. - \sa setBlurRadius(), blurRadiusChanged() + By default, the blur radius is 5 pixels. */ int QGraphicsBlurEffect::blurRadius() const { @@ -669,14 +713,6 @@ int QGraphicsBlurEffect::blurRadius() const return d->filter->radius(); } -/*! - Sets the blur radius to the given \a radius. - - Using a smaller radius results in a sharper appearance, whereas a bigger - radius results in a more blurred appearance. - - \sa blurRadius(), blurRadiusChanged() -*/ void QGraphicsBlurEffect::setBlurRadius(int radius) { Q_D(QGraphicsBlurEffect); @@ -692,14 +728,21 @@ void QGraphicsBlurEffect::setBlurRadius(int radius) \fn void QGraphicsBlurEffect::blurRadiusChanged(int radius) This signal is emitted whenever the effect's blur radius changes. + The \a radius parameter holds the effect's new blur radius. */ +/*! + \reimp +*/ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsBlurEffect); return d->filter->boundingRectFor(rect); } +/*! + \reimp +*/ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); @@ -742,19 +785,30 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) \sa QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ + +/*! + Constructs a new QGraphicsDropShadowEffect instance. + The \a parent parameter is passed to QGraphicsEffect's constructor. +*/ QGraphicsDropShadowEffect::QGraphicsDropShadowEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsDropShadowEffectPrivate, parent) { } +/*! + Destroys the effect. +*/ QGraphicsDropShadowEffect::~QGraphicsDropShadowEffect() { } /*! - Returns the shadow offset in pixels. + \property QGraphicsDropShadowEffect::offset + \brief the shadow offset in pixels. - \sa setOffset(), blurRadius(), color(), offsetChanged() + By default, the offset is 8 pixels towards the lower right. + + \sa blurRadius(), color() */ QPointF QGraphicsDropShadowEffect::offset() const { @@ -762,11 +816,6 @@ QPointF QGraphicsDropShadowEffect::offset() const return d->filter->offset(); } -/*! - Sets the shadow offset in pixels to the given \a offset. - - \sa offset(), setBlurRadius(), setColor(), offsetChanged() -*/ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) { Q_D(QGraphicsDropShadowEffect); @@ -782,12 +831,19 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset) \fn void QGraphicsDropShadowEffect::offsetChanged(const QPointF &offset) This signal is emitted whenever the effect's shadow offset changes. + The \a offset parameter holds the effect's new shadow offset. */ /*! - Returns the radius in pixels of the blur on the drop shadow. + \property QGraphicsDropShadowEffect::blurRadius + \brief the blur radius in pixels of the drop shadow. + + Using a smaller radius results in a sharper shadow, whereas using a bigger + radius results in a more blurred shadow. + + By default, the blur radius is 1 pixel. - \sa setBlurRadius(), color(), offset(), blurRadiusChanged() + \sa color(), offset(). */ int QGraphicsDropShadowEffect::blurRadius() const { @@ -795,15 +851,6 @@ int QGraphicsDropShadowEffect::blurRadius() const return d->filter->blurRadius(); } -/*! - Sets the radius in pixels of the blur on the drop shadow to the - \a blurRadius specified. - - Using a smaller radius results in a sharper shadow, whereas using a bigger - radius results in a more blurred shadow. - - \sa blurRadius(), setColor(), setOffset(), blurRadiusChanged() -*/ void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) { Q_D(QGraphicsDropShadowEffect); @@ -819,12 +866,17 @@ void QGraphicsDropShadowEffect::setBlurRadius(int blurRadius) \fn void QGraphicsDropShadowEffect::blurRadiusChanged(int blurRadius) This signal is emitted whenever the effect's blur radius changes. + The \a blurRadius parameter holds the effect's new blur radius. */ /*! - Returns the color of the drop shadow. + \property QGraphicsDropShadowEffect::color + \brief the color of the drop shadow. + + By default, the drop color is a semi-transparent dark gray + (QColor(63, 63, 63, 180)). - \sa setColor, offset(), blurRadius(), colorChanged() + \sa offset(), blurRadius() */ QColor QGraphicsDropShadowEffect::color() const { @@ -832,11 +884,6 @@ QColor QGraphicsDropShadowEffect::color() const return d->filter->color(); } -/*! - Sets the color of the drop shadow to the given \a color. - - \sa color(), setOffset(), setBlurRadius(), colorChanged() -*/ void QGraphicsDropShadowEffect::setColor(const QColor &color) { Q_D(QGraphicsDropShadowEffect); @@ -851,14 +898,21 @@ void QGraphicsDropShadowEffect::setColor(const QColor &color) \fn void QGraphicsDropShadowEffect::colorChanged(const QColor &color) This signal is emitted whenever the effect's color changes. + The \a color parameter holds the effect's new color. */ +/*! + \reimp +*/ QRectF QGraphicsDropShadowEffect::boundingRectFor(const QRectF &rect) const { Q_D(const QGraphicsDropShadowEffect); return d->filter->boundingRectFor(rect); } +/*! + \reimp +*/ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsDropShadowEffect); @@ -897,19 +951,31 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect */ + +/*! + Constructs a new QGraphicsOpacityEffect instance. + The \a parent parameter is passed to QGraphicsEffect's constructor. +*/ QGraphicsOpacityEffect::QGraphicsOpacityEffect(QObject *parent) : QGraphicsEffect(*new QGraphicsOpacityEffectPrivate, parent) { } +/*! + Destroys the effect. +*/ QGraphicsOpacityEffect::~QGraphicsOpacityEffect() { } /*! - Returns the opacity. + \property QGraphicsOpacityEffect::opacity + \brief the opacity of the effect. + + The value should be in the range of 0.0 to 1.0, where 0.0 is + fully transparent and 1.0 is fully opaque. - \sa setOpacity(), opacityChanged() + By default, the opacity is 0.7. */ qreal QGraphicsOpacityEffect::opacity() const { @@ -917,12 +983,6 @@ qreal QGraphicsOpacityEffect::opacity() const return d->opacity; } -/*! - Sets the opacity to the given \a opacity. The value should be in the range - of 0.0 to 1.0, where 0.0 is fully transparent and 1.0 is fully opaque. - - \sa opacity(), opacityChanged() -*/ void QGraphicsOpacityEffect::setOpacity(qreal opacity) { Q_D(QGraphicsOpacityEffect); @@ -939,8 +999,12 @@ void QGraphicsOpacityEffect::setOpacity(qreal opacity) \fn void QGraphicsOpacityEffect::opacityChanged(qreal opacity) This signal is emitted whenever the effect's opacity changes. + The \a opacity parameter holds the effect's new opacity. */ +/*! + \reimp +*/ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsOpacityEffect); diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 62d0848..d39044a 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -4970,6 +4970,13 @@ void QWidgetPrivate::setSoftKeys_sys(const QList &softkeys) } #endif // !defined(Q_OS_SYMBIAN) +/*! + Returns a pointer to this widget's effect if it has one; otherwise 0. + + \since 4.6 + + \sa setGraphicsEffect() +*/ QGraphicsEffect *QWidget::graphicsEffect() const { Q_D(const QWidget); @@ -4987,6 +4994,8 @@ QGraphicsEffect *QWidget::graphicsEffect() const \note This function will apply the effect on itself and all its children. \since 4.6 + + \sa graphicsEffect() */ void QWidget::setGraphicsEffect(QGraphicsEffect *effect) { diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index 5e37d62..e8cc7a1 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -126,7 +126,7 @@ QT_BEGIN_NAMESPACE the drawItem() method will draw its item argument directly with no effect applied. - \sa QGrapicsEffect + \sa QGraphicsEffect */ static const char qglslDefaultImageFragmentShader[] = "\ -- cgit v0.12 From d973b81e10b499982b5a7484fc09a6bcd1cf9295 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 26 Aug 2009 13:35:16 +0200 Subject: More test for QByteArray::fromBase64 that tests invalid input --- tests/auto/qbytearray/tst_qbytearray.cpp | 54 ++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/tests/auto/qbytearray/tst_qbytearray.cpp b/tests/auto/qbytearray/tst_qbytearray.cpp index 4ec02bc..7951864 100644 --- a/tests/auto/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/qbytearray/tst_qbytearray.cpp @@ -90,6 +90,8 @@ private slots: void split(); void base64_data(); void base64(); + void fromBase64_data(); + void fromBase64(); void qvsnprintf(); void qstrlen(); void qstrnlen(); @@ -460,6 +462,10 @@ void tst_QByteArray::base64_data() for (int i = 0; i < 256; ++i) ba[i] = i; QTest::newRow("f") << ba << QByteArray("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=="); + + QTest::newRow("g") << QByteArray("foo\0bar", 7) << QByteArray("Zm9vAGJhcg=="); + QTest::newRow("h") << QByteArray("f\xd1oo\x9cbar") << QByteArray("ZtFvb7py"); + QTest::newRow("i") << QByteArray("\"\0\0\0\0\0\0\"", 8) << QByteArray("IgAAAAAAACI="); } @@ -475,6 +481,54 @@ void tst_QByteArray::base64() QCOMPARE(arr64, base64); } +//different from the previous test as the input are invalid +void tst_QByteArray::fromBase64_data() +{ + QTest::addColumn("rawdata"); + QTest::addColumn("base64"); + + QTest::newRow("1") << QByteArray("") << QByteArray(" "); + QTest::newRow("2") << QByteArray("1") << QByteArray("MQ"); + QTest::newRow("3") << QByteArray("12") << QByteArray("MTI "); + QTest::newRow("4") << QByteArray("123") << QByteArray("M=TIz"); + QTest::newRow("5") << QByteArray("1234") << QByteArray("MTI zN A "); + QTest::newRow("6") << QByteArray("\n") << QByteArray("Cg"); + QTest::newRow("7") << QByteArray("a\n") << QByteArray("======YQo="); + QTest::newRow("8") << QByteArray("ab\n") << QByteArray("Y\nWIK"); + QTest::newRow("9") << QByteArray("abc\n") << QByteArray("YWJjCg=="); + QTest::newRow("a") << QByteArray("abcd\n") << QByteArray("YWJ\1j\x9cZAo="); + QTest::newRow("b") << QByteArray("abcde\n") << QByteArray("YW JjZ\n G\tUK"); + QTest::newRow("c") << QByteArray("abcdef\n") << QByteArray("YWJjZGVmCg="); + QTest::newRow("d") << QByteArray("abcdefg\n") << QByteArray("YWJ\rjZGVmZwo"); + QTest::newRow("e") << QByteArray("abcdefgh\n") << QByteArray("YWJjZGVmZ2gK"); + + QByteArray ba; + ba.resize(256); + for (int i = 0; i < 256; ++i) + ba[i] = i; + QTest::newRow("f") << ba << QByteArray("AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Nj\n" + "c4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1u\n" + "b3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpa\n" + "anqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd\n" + "3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w== "); + + + QTest::newRow("g") << QByteArray("foo\0bar", 7) << QByteArray("Zm9vAGJhcg"); + QTest::newRow("h") << QByteArray("f\xd1oo\x9cbar") << QByteArray("ZtFv\0b7py", 9); + QTest::newRow("i") << QByteArray("\"\0\0\0\0\0\0\"", 8) << QByteArray("IgAAAAAAACI"); + +} + + +void tst_QByteArray::fromBase64() +{ + QFETCH(QByteArray, rawdata); + QFETCH(QByteArray, base64); + + QByteArray arr = QByteArray::fromBase64(base64); + QCOMPARE(arr, rawdata); +} + void tst_QByteArray::qvsnprintf() { char buf[20]; -- cgit v0.12 From 3d1cf992b28ffa9f3b18414bddd24865075fd953 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 26 Aug 2009 15:09:09 +0200 Subject: tst_QObject: test that we connect to the right signals when there is overloards This test would not pass if we sorted the signals by alphabetical order in the moc (in order to do a binary search) --- tests/auto/qobject/tst_qobject.cpp | 94 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index a08f620..65dc742 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -120,6 +120,7 @@ private slots: void uniqConnection(); void interfaceIid(); void deleteQObjectWhenDeletingEvent(); + void overloads(); protected: }; @@ -2903,11 +2904,11 @@ void tst_QObject::uniqConnection() void tst_QObject::interfaceIid() { - QCOMPARE(QByteArray(qobject_interface_iid()), + QCOMPARE(QByteArray(qobject_interface_iid()), QByteArray(Bleh_iid)); - QCOMPARE(QByteArray(qobject_interface_iid()), + QCOMPARE(QByteArray(qobject_interface_iid()), QByteArray("com.qtest.foobar")); - QCOMPARE(QByteArray(qobject_interface_iid()), + QCOMPARE(QByteArray(qobject_interface_iid()), QByteArray()); } @@ -2927,6 +2928,93 @@ void tst_QObject::deleteQObjectWhenDeletingEvent() QCoreApplication::removePostedEvents(&o); // here you would get a deadlock } +class OverloadObject : public QObject +{ + friend class tst_QObject; + Q_OBJECT + signals: + void sig(int i, char c, qreal m = 12) const; + void sig(int i, int j = 12); + void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const; + void other(int a = 0); + void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0); + void sig(double r = 0.5); + public slots: + void slo(int i, int j = 43) + { + s_num += 1; + i1_num = i; + i2_num = j; + } + void slo(QObject *o, QObject *p = qApp, QObject *q = qApp, QObject *r = qApp) + { + s_num += 10; + o1_obj = o; + o2_obj = p; + o3_obj = q; + o4_obj = r; + } + void slo() + { + s_num += 100; + } + + public: + int s_num; + int i1_num; + int i2_num; + QObject *o1_obj; + QObject *o2_obj; + QObject *o3_obj; + QObject *o4_obj; +}; + +void tst_QObject::overloads() +{ + OverloadObject obj1; + OverloadObject obj2; + QObject obj3; + obj1.s_num = 0; + obj2.s_num = 0; + + connect (&obj1, SIGNAL(sig(int)) , &obj1, SLOT(slo(int))); + connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *)) , &obj1, SLOT(slo(QObject * , QObject *, QObject *))); + + connect (&obj1, SIGNAL(sig(QObject *, QObject *, QObject *, QObject *)) , &obj2, SLOT(slo(QObject * , QObject *, QObject *))); + connect (&obj1, SIGNAL(sig(QObject *)) , &obj2, SLOT(slo())); + connect (&obj1, SIGNAL(sig(int, int)) , &obj2, SLOT(slo(int, int))); + + emit obj1.sig(0.5); //connected to nothing + emit obj1.sig(1, 'a'); //connected to nothing + QCOMPARE(obj1.s_num, 0); + QCOMPARE(obj2.s_num, 0); + + emit obj1.sig(1); //this signal is connected + QCOMPARE(obj1.s_num, 1); + QCOMPARE(obj1.i1_num, 1); + QCOMPARE(obj1.i2_num, 43); //default argument of the slot + + QCOMPARE(obj2.s_num, 1); + QCOMPARE(obj2.i1_num, 1); + QCOMPARE(obj2.i2_num, 12); //default argument of the signal + + + emit obj1.sig(&obj2); //this signal is conencted to obj2 + QCOMPARE(obj1.s_num, 1); + QCOMPARE(obj2.s_num, 101); + emit obj1.sig(&obj2, &obj3); //this signal is connected + QCOMPARE(obj1.s_num, 11); + QCOMPARE(obj1.o1_obj, &obj2); + QCOMPARE(obj1.o2_obj, &obj3); + QCOMPARE(obj1.o3_obj, (QObject *)0); //default arg of the signal + QCOMPARE(obj1.o4_obj, qApp); //default arg of the slot + + QCOMPARE(obj2.s_num, 111); + QCOMPARE(obj2.o1_obj, &obj2); + QCOMPARE(obj2.o2_obj, &obj3); + QCOMPARE(obj2.o3_obj, (QObject *)0); //default arg of the signal + QCOMPARE(obj2.o4_obj, qApp); //default arg of the slot +} QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" -- cgit v0.12 From 25c7f57c21dd22eaa38b4b511aa754a1be711bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 26 Aug 2009 15:09:34 +0200 Subject: Remove Graphics View dependency from QGraphicsShaderEffect. Graphics effects are no longer in the Graphics View module. --- src/opengl/qgraphicsshadereffect.cpp | 4 ---- src/opengl/qgraphicsshadereffect.h | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index e8cc7a1..293413c 100644 --- a/src/opengl/qgraphicsshadereffect.cpp +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -51,8 +51,6 @@ QT_BEGIN_NAMESPACE -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - /*! \class QGraphicsShaderEffect \brief The QGraphicsShaderEffect class is the base class for creating @@ -313,6 +311,4 @@ void QGraphicsShaderEffect::setUniforms(QGLShaderProgram *program) Q_UNUSED(program); } -#endif // QT_NO_GRAPHICSVIEW - QT_END_NAMESPACE diff --git a/src/opengl/qgraphicsshadereffect.h b/src/opengl/qgraphicsshadereffect.h index c4637d7..672973b 100644 --- a/src/opengl/qgraphicsshadereffect.h +++ b/src/opengl/qgraphicsshadereffect.h @@ -50,8 +50,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) -#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW - class QGLShaderProgram; class QGLCustomShaderEffectStage; class QGraphicsShaderEffectPrivate; @@ -78,8 +76,6 @@ private: friend class QGLCustomShaderEffectStage; }; -#endif // QT_NO_GRAPHICSVIEW - QT_END_NAMESPACE QT_END_HEADER -- cgit v0.12 From 88ecc8c8250505129ccff2660c60412996e2fd85 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 26 Aug 2009 15:30:48 +0200 Subject: QAbstractItemView sometimes doesn't allow changing the selection If you do a selection with the mouse and react to selectionChanged by changing the selection. Those changes would be overwritten by QAbstractItemView::mouseReleaseEvent. It is useless to set the selection on mouse release. We already do that on mouse press. Task-number: 250683 Reviewed-by: ogoffart --- src/gui/itemviews/qabstractitemview.cpp | 3 --- tests/auto/qtreeview/tst_qtreeview.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index bca5df7..ccc57d7 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -1661,9 +1661,6 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event) EditTrigger trigger = (selectedClicked ? SelectedClicked : NoEditTriggers); bool edited = edit(index, trigger, event); - if (d->selectionModel) - d->selectionModel->select(index, selectionCommand(index, event)); - setState(NoState); if (click) { diff --git a/tests/auto/qtreeview/tst_qtreeview.cpp b/tests/auto/qtreeview/tst_qtreeview.cpp index d28c3c3..44185e7 100644 --- a/tests/auto/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/qtreeview/tst_qtreeview.cpp @@ -232,6 +232,7 @@ private slots: void task250683_wrongSectionSize(); void task239271_addRowsWithFirstColumnHidden(); void task254234_proxySort(); + void task248022_changeSelection(); }; class QtTestModel: public QAbstractItemModel @@ -3435,5 +3436,33 @@ void tst_QTreeView::task254234_proxySort() QCOMPARE(view.model()->data(view.model()->index(1,1)).toString(), QString::fromLatin1("g")); } +class TreeView : public QTreeView +{ + Q_OBJECT +public slots: + void handleSelectionChanged() + { + //let's select the last item + QModelIndex idx = model()->index(0, 0); + selectionModel()->select(QItemSelection(idx, idx), QItemSelectionModel::Select); + disconnect(selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(handleSelectionChanged())); + } +}; + +void tst_QTreeView::task248022_changeSelection() +{ + //we check that changing the selection between the mouse press and the mouse release + //works correctly + TreeView view; + QStringList list = QStringList() << "1" << "2"; + QStringListModel model(list); + view.setSelectionMode(QAbstractItemView::ExtendedSelection); + view.setModel(&model); + view.connect(view.selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(handleSelectionChanged())); + QTest::mouseClick(view.viewport(), Qt::LeftButton, 0, view.visualRect(model.index(1)).center()); + QCOMPARE(view.selectionModel()->selectedIndexes().count(), list.count()); +} + + QTEST_MAIN(tst_QTreeView) #include "tst_qtreeview.moc" -- cgit v0.12 From 478f18e37a04849f4577ded7ba60d8360b6c5c90 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 26 Aug 2009 15:38:45 +0200 Subject: QMainWindow: adding autotest for the size of the central widget It just ensures that the central widget gets its correct size (ie. sizehint) when a menu bar is present. --- tests/auto/qmainwindow/tst_qmainwindow.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/auto/qmainwindow/tst_qmainwindow.cpp b/tests/auto/qmainwindow/tst_qmainwindow.cpp index e118c65..9156e5e 100644 --- a/tests/auto/qmainwindow/tst_qmainwindow.cpp +++ b/tests/auto/qmainwindow/tst_qmainwindow.cpp @@ -106,6 +106,7 @@ private slots: void isSeparator(); void setCursor(); void addToolbarAfterShow(); + void centralWidgetSize(); }; // Testing get/set functions @@ -1336,6 +1337,19 @@ public: } }; +class MyWidget : public QWidget +{ +public: + MyWidget(QWidget *parent = 0) : QWidget(parent) + { + } + + QSize sizeHint() const + { + return QSize(200, 200); + } +}; + void tst_QMainWindow::hideBeforeLayout() { QMainWindow win; @@ -1650,6 +1664,18 @@ void tst_QMainWindow::addToolbarAfterShow() QVERIFY(!toolBar.isHidden()); } +void tst_QMainWindow::centralWidgetSize() +{ + QMainWindow mainWindow; + mainWindow.menuBar()->addMenu("menu"); + + MyWidget widget; + mainWindow.setCentralWidget(&widget); + + mainWindow.show(); + QTest::qWait(100); + QCOMPARE(widget.size(), widget.sizeHint()); +} QTEST_MAIN(tst_QMainWindow) -- cgit v0.12 From 5ef11e48dd3bd8a6d51028128ee957aba27b0100 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 26 Aug 2009 16:04:21 +0200 Subject: Doc: Added a performance section to the Graphics View overview. Task-number: 253749 Reviewed-by: Trust Me --- doc/src/frameworks-technologies/graphicsview.qdoc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/doc/src/frameworks-technologies/graphicsview.qdoc b/doc/src/frameworks-technologies/graphicsview.qdoc index 8d7ea2c..397cb19 100644 --- a/doc/src/frameworks-technologies/graphicsview.qdoc +++ b/doc/src/frameworks-technologies/graphicsview.qdoc @@ -551,4 +551,24 @@ the widget is transformed resolution independently, allowing the fonts and style to stay crisp when zoomed in. (Note that the effect of resolution independence depends on the style.) + + \section1 Performance + + \section2 Floating Point Instructions + + In order to accurately and quickly apply transformations and effects to + items, Graphics View is built with the assumption that the user's hardware + is able to provide reasonable performance for floating point instructions. + + Many workstations and desktop computers are equipped with suitable hardware + to accelerate this kind of computation, but some embedded devices may only + provide libraries to handle mathematical operations or emulate floating + point instructions in software. + + As a result, certain kinds of effects may be slower than expected on certain + devices. It may be possible to compensate for this performance hit by making + optimizations in other areas; for example, by using \l{#OpenGL Rendering}{OpenGL} + to render a scene. However, any such optimizations may themselves cause a + reduction in performance if they also rely on the presence of floating point + hardware. */ -- cgit v0.12 From 5be87d57602d72c225943f052783c1053cd3d81a Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 26 Aug 2009 16:02:30 +0200 Subject: don't crash when attempting to access properties of a JS Object that belonged to a deleted script engine When the engine is deleted, the JSValue is invalidated, but the QScriptValue's type will still be QScriptValuePrivate::JSC. Use a new helper function, isObject(), that checks both that the value is of type JSC _and_ that it is valid, before calling JSValue::isObject() (JSValue::isObject() assumes that the value is valid). --- src/script/api/qscriptvalue.cpp | 47 ++++++++++++++-------------- src/script/api/qscriptvalue_p.h | 6 ++++ tests/auto/qscriptvalue/tst_qscriptvalue.cpp | 2 ++ 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 984ad1b..7fd1efe 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -278,7 +278,7 @@ qsreal ToInteger(qsreal n) QScriptValue QScriptValuePrivate::property(const JSC::Identifier &id, int resolveMode) const { - Q_ASSERT(isJSC()); + Q_ASSERT(isObject()); JSC::ExecState *exec = engine->currentFrame; JSC::JSObject *object = jscValue.getObject(); JSC::PropertySlot slot(const_cast(object)); @@ -301,7 +301,7 @@ QScriptValue QScriptValuePrivate::property(const JSC::Identifier &id, int resolv QScriptValue QScriptValuePrivate::property(quint32 index, int resolveMode) const { - Q_ASSERT(isJSC()); + Q_ASSERT(isObject()); JSC::ExecState *exec = engine->currentFrame; JSC::JSObject *object = jscValue.getObject(); JSC::PropertySlot slot(const_cast(object)); @@ -784,7 +784,7 @@ QScriptValue &QScriptValue::operator=(const QScriptValue &other) bool QScriptValue::isError() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return false; return d->jscValue.isObject(&JSC::ErrorInstance::info); } @@ -798,7 +798,7 @@ bool QScriptValue::isError() const bool QScriptValue::isArray() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return false; return d->jscValue.isObject(&JSC::JSArray::info); } @@ -812,7 +812,7 @@ bool QScriptValue::isArray() const bool QScriptValue::isDate() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return false; return d->jscValue.isObject(&JSC::DateInstance::info); } @@ -826,7 +826,7 @@ bool QScriptValue::isDate() const bool QScriptValue::isRegExp() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return false; return d->jscValue.isObject(&JSC::RegExpObject::info); } @@ -841,7 +841,7 @@ bool QScriptValue::isRegExp() const QScriptValue QScriptValue::prototype() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return QScriptValue(); return d->engine->scriptValueFromJSCValue(JSC::asObject(d->jscValue)->prototype()); } @@ -860,7 +860,7 @@ QScriptValue QScriptValue::prototype() const void QScriptValue::setPrototype(const QScriptValue &prototype) { Q_D(QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return; if (prototype.isValid() && prototype.engine() && (prototype.engine() != engine())) { @@ -890,7 +890,7 @@ void QScriptValue::setPrototype(const QScriptValue &prototype) QScriptValue QScriptValue::scope() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return QScriptValue(); // ### make hidden property return d->property(QLatin1String("__qt_scope__"), QScriptValue::ResolveLocal); @@ -902,7 +902,7 @@ QScriptValue QScriptValue::scope() const void QScriptValue::setScope(const QScriptValue &scope) { Q_D(QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return; if (scope.isValid() && scope.engine() && (scope.engine() != engine())) { @@ -934,7 +934,7 @@ void QScriptValue::setScope(const QScriptValue &scope) bool QScriptValue::instanceOf(const QScriptValue &other) const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject() || !other.isObject()) + if (!d || !d->isObject() || !other.isObject()) return false; if (other.engine() != engine()) { qWarning("QScriptValue::instanceof: " @@ -1693,7 +1693,7 @@ void QScriptValue::setProperty(const QString &name, const QScriptValue &value, const PropertyFlags &flags) { Q_D(QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return; JSC::ExecState *exec = d->engine->currentFrame; d->setProperty(JSC::Identifier(exec, name), value, flags); @@ -1718,7 +1718,7 @@ QScriptValue QScriptValue::property(const QString &name, const ResolveFlags &mode) const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return QScriptValue(); return d->property(name, mode); } @@ -1740,7 +1740,7 @@ QScriptValue QScriptValue::property(quint32 arrayIndex, const ResolveFlags &mode) const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return QScriptValue(); return d->property(arrayIndex, mode); } @@ -1761,7 +1761,7 @@ void QScriptValue::setProperty(quint32 arrayIndex, const QScriptValue &value, const PropertyFlags &flags) { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return; if (value.engine() && (value.engine() != engine())) { qWarning("QScriptValue::setProperty() failed: " @@ -1811,7 +1811,7 @@ QScriptValue QScriptValue::property(const QScriptString &name, const ResolveFlags &mode) const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject() || !name.isValid()) + if (!d || !d->isObject() || !name.isValid()) return QScriptValue(); return d->property(name.d_ptr->identifier, mode); } @@ -1834,7 +1834,7 @@ void QScriptValue::setProperty(const QScriptString &name, const PropertyFlags &flags) { Q_D(QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject() || !name.isValid()) + if (!d || !d->isObject() || !name.isValid()) return; d->setProperty(name.d_ptr->identifier, value, flags); } @@ -1849,7 +1849,7 @@ QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name, const ResolveFlags &mode) const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return 0; JSC::ExecState *exec = d->engine->currentFrame; return d->propertyFlags(JSC::Identifier(exec, name), mode); @@ -1868,7 +1868,7 @@ QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QScriptString &nam const ResolveFlags &mode) const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject() || !name.isValid()) + if (!d || !d->isObject() || !name.isValid()) return 0; return d->propertyFlags(name.d_ptr->identifier, mode); } @@ -2272,7 +2272,7 @@ bool QScriptValue::isUndefined() const bool QScriptValue::isObject() const { Q_D(const QScriptValue); - return d && d->isJSC() && d->jscValue.isObject(); + return d && d->isObject(); } /*! @@ -2319,10 +2319,9 @@ bool QScriptValue::isQObject() const bool QScriptValue::isQMetaObject() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return false; return JSC::asObject(d->jscValue)->isObject(&QScript::QMetaObjectWrapperObject::info); - return false; } /*! @@ -2346,7 +2345,7 @@ bool QScriptValue::isValid() const QScriptValue QScriptValue::data() const { Q_D(const QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return QScriptValue(); if (d->jscValue.isObject(&QScriptObject::info)) { QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); @@ -2368,7 +2367,7 @@ QScriptValue QScriptValue::data() const void QScriptValue::setData(const QScriptValue &data) { Q_D(QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject()) + if (!d || !d->isObject()) return; JSC::JSValue other = d->engine->scriptValueToJSCValue(data); if (d->jscValue.isObject(&QScriptObject::info)) { diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h index c440013..6d57d32 100644 --- a/src/script/api/qscriptvalue_p.h +++ b/src/script/api/qscriptvalue_p.h @@ -85,6 +85,7 @@ public: inline void initFrom(const QString &value); inline bool isJSC() const; + inline bool isObject() const; QVariant &variantValue() const; void setVariantValue(const QVariant &value); @@ -144,6 +145,11 @@ inline bool QScriptValuePrivate::isJSC() const return (type == JSC); } +inline bool QScriptValuePrivate::isObject() const +{ + return isJSC() && jscValue && jscValue.isObject(); +} + // Rest of inline functions implemented in qscriptengine_p.h QT_END_NAMESPACE diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index e712017..b125965 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -3278,6 +3278,8 @@ void tst_QScriptValue::engineDeleted() QVERIFY(v4.engine() == 0); QVERIFY(v5.isValid()); QVERIFY(v5.engine() == 0); + + QVERIFY(!v3.property("foo").isValid()); } void tst_QScriptValue::valueOfWithClosure() -- cgit v0.12 From fad842cebeab8cba78141edd10756a51885f448b Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 23 Jul 2009 11:04:25 +0100 Subject: Add move API to QAbstractItemModel. This adds the function beginMoveRows, endMoveRows, beginMoveColumns, endMoveColumns Reviewed-by: Olivier Goffart Acknowledged-by: Thierry Merge-request: 972 --- src/corelib/kernel/qabstractitemmodel.cpp | 327 ++++++++ src/corelib/kernel/qabstractitemmodel.h | 13 + src/corelib/kernel/qabstractitemmodel_p.h | 7 + tests/auto/qabstractitemmodel/dynamictreemodel.cpp | 245 ++++++ tests/auto/qabstractitemmodel/dynamictreemodel.h | 141 ++++ .../auto/qabstractitemmodel/qabstractitemmodel.pro | 5 +- .../qabstractitemmodel/tst_qabstractitemmodel.cpp | 841 ++++++++++++++++++++- 7 files changed, 1577 insertions(+), 2 deletions(-) create mode 100644 tests/auto/qabstractitemmodel/dynamictreemodel.cpp create mode 100644 tests/auto/qabstractitemmodel/dynamictreemodel.h diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 3b7059b..fb0afcc 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -599,6 +599,118 @@ void QAbstractItemModelPrivate::rowsInserted(const QModelIndex &parent, } } +void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation) +{ + Q_Q(QAbstractItemModel); + QVector persistent_moved_explicitly; + QVector persistent_moved_in_source; + QVector persistent_moved_in_destination; + + QHash::const_iterator it; + const QHash::const_iterator begin = persistent.indexes.constBegin(); + const QHash::const_iterator end = persistent.indexes.constEnd(); + + const bool sameParent = (srcParent == destinationParent); + const bool movingUp = (srcFirst > destinationChild); + + for ( it = begin; it != end; ++it) { + QPersistentModelIndexData *data = *it; + const QModelIndex &index = data->index; + const QModelIndex &parent = index.parent(); + const bool isSourceIndex = (parent == srcParent); + const bool isDestinationIndex = (parent == destinationParent); + + int childPosition; + if (orientation == Qt::Vertical) + childPosition = index.row(); + else + childPosition = index.column(); + + if (!index.isValid() || !(isSourceIndex || isDestinationIndex ) ) + continue; + + if (!sameParent && isDestinationIndex) { + if (childPosition >= destinationChild) + persistent_moved_in_destination.append(data); + continue; + } + + if (sameParent && movingUp && childPosition < destinationChild) + continue; + + if (sameParent && !movingUp && childPosition < srcFirst ) + continue; + + if (!sameParent && childPosition < srcFirst) + continue; + + if (sameParent && (childPosition > srcLast) && (childPosition >= destinationChild )) + continue; + + if ((childPosition <= srcLast) && (childPosition >= srcFirst)) { + persistent_moved_explicitly.append(data); + } else { + persistent_moved_in_source.append(data); + } + } + persistent.moved.push(persistent_moved_explicitly); + persistent.moved.push(persistent_moved_in_source); + persistent.moved.push(persistent_moved_in_destination); +} + +/*! + \internal + + Moves persistent indexes \a indexes by amount \a change. The change will be either a change in row value or a change in + column value depending on the value of \a orientation. The indexes may also be moved to a different parent if \a parent + differs from the existing parent for the index. +*/ +void QAbstractItemModelPrivate::movePersistentIndexes(QVector indexes, int change, const QModelIndex &parent, Qt::Orientation orientation) +{ + QVector::const_iterator it; + const QVector::const_iterator begin = indexes.constBegin(); + const QVector::const_iterator end = indexes.constEnd(); + + for (it = begin; it != end; ++it) + { + QPersistentModelIndexData *data = *it; + + int row = data->index.row(); + int column = data->index.column(); + + if (Qt::Vertical == orientation) + row += change; + else + column += change; + + persistent.indexes.erase(persistent.indexes.find(data->index)); + data->index = q_func()->index(row, column, parent); + if (data->index.isValid()) { + persistent.insertMultiAtEnd(data->index, data); + } else { + qWarning() << "QAbstractItemModel::endMoveRows: Invalid index (" << row << "," << column << ") in model" << q_func(); + } + } +} + +void QAbstractItemModelPrivate::itemsMoved(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation) +{ + QVector moved_in_destination = persistent.moved.pop(); + QVector moved_in_source = persistent.moved.pop(); + QVector moved_explicitly = persistent.moved.pop(); + + const bool sameParent = (sourceParent == destinationParent); + const bool movingUp = (sourceFirst > destinationChild); + + const int explicit_change = (!sameParent || movingUp) ? destinationChild - sourceFirst : destinationChild - sourceLast - 1 ; + const int source_change = (!sameParent || !movingUp) ? -1*(sourceLast - sourceFirst + 1) : sourceLast - sourceFirst + 1 ; + const int destination_change = sourceLast - sourceFirst + 1; + + movePersistentIndexes(moved_explicitly, explicit_change, destinationParent, orientation); + movePersistentIndexes(moved_in_source, source_change, sourceParent, orientation); + movePersistentIndexes(moved_in_destination, destination_change, destinationParent, orientation); +} + void QAbstractItemModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last) { @@ -1370,6 +1482,36 @@ QAbstractItemModel::~QAbstractItemModel() */ /*! + \fn void QAbstractItemModel::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) + + This signal is emitted after rows have been moved within the + model. The items between \a sourceStart and \a sourceEnd + inclusive, under the given \a sourceParent item have been moved to \a destinationParent + starting at the row \a destinationRow. + + \bold{Note:} Components connected to this signal use it to adapt to changes + in the model's dimensions. It can only be emitted by the QAbstractItemModel + implementation, and cannot be explicitly emitted in subclass code. + + \sa beginMoveRows() +*/ + +/*! + \fn void QAbstractItemModel::rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) + + This signal is emitted just before rows are moved within the + model. The items that will be moved are those between \a sourceStart and \a sourceEnd + inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent + starting at the row \a destinationRow. + + \bold{Note:} Components connected to this signal use it to adapt to changes + in the model's dimensions. It can only be emitted by the QAbstractItemModel + implementation, and cannot be explicitly emitted in subclass code. + + \sa beginMoveRows() +*/ + +/*! \fn void QAbstractItemModel::columnsInserted(const QModelIndex &parent, int start, int end) This signal is emitted after columns have been inserted into the model. The @@ -2284,6 +2426,116 @@ void QAbstractItemModel::endRemoveRows() } /*! + Returns whether a move operation is valid. + + A move operation is not allowed if it moves a continuous range of rows to a destination within + itself, or if it attempts to move a row to one of its own descendants. + + \internal +*/ +bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int start, int end, const QModelIndex &destinationParent, int destinationStart, Qt::Orientation orientation) +{ + Q_Q(QAbstractItemModel); + // Don't move the range within itself. + if ( ( destinationParent == srcParent ) + && ( destinationStart >= start ) + && ( destinationStart <= end + 1) ) + return false; + + QModelIndex destinationAncestor = destinationParent; + int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column(); + forever { + if (destinationAncestor == srcParent) { + if (pos >= start && pos <= end) + return false; + break; + } + + if (!destinationAncestor.isValid()) + break; + + pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column(); + destinationAncestor = destinationAncestor.parent(); + } + + return true; +} + +/*! + Begins a row move operation. + + When reimplementing a subclass, this method simplifies moving entities + in your model. This method is responsible for moving persistent indexes + in the model, which you would otherwise be required to do yourself. + + Using beginMoveRows and endMoveRows is an alternative to emitting + layoutAboutToBeChanged and layoutChanged directly along with changePersistentIndexes. + layoutAboutToBeChanged is emitted by this method for compatibility reasons. + + The \a sourceParent index corresponds to the parent from which the + rows are moved; \a sourceFirst and \a sourceLast are the row numbers of the + rows to be moved. The \a destinationParent index corresponds to the parent into which + the rows are moved. The \a destinationRow is the row to which the rows will be moved. + That is, the index at row \a sourceFirst in \a sourceParent will become row \a destinationRow + in \a destinationParent. Its siblings will be moved correspondingly. + + Note that \a sourceParent and \a destinationParent may be the same, in which case you must + ensure that the \a destinationRow is not within the range of \a sourceFirst and \a sourceLast. + You must also ensure that you do not attempt to move a row to one of its own chilren or ancestors. + This method returns false if either condition is true, in which case you should abort your move operation. + + \sa endMoveRows() + + \since 4.6 +*/ +bool QAbstractItemModel::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild) +{ + Q_ASSERT(sourceFirst >= 0); + Q_ASSERT(sourceLast >= sourceFirst); + Q_ASSERT(destinationChild >= 0); + Q_D(QAbstractItemModel); + + if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) { + return false; + } + + d->changes.push(QAbstractItemModelPrivate::Change(sourceParent, sourceFirst, sourceLast)); + int destinationLast = destinationChild + (sourceLast - sourceFirst); + d->changes.push(QAbstractItemModelPrivate::Change(destinationParent, destinationChild, destinationLast)); + + d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical); + emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild); + emit layoutAboutToBeChanged(); + return true; +} + +/*! + Ends a row move operation. + + When implementing a subclass, you must call this + function \e after moving data within the model's underlying data + store. + + layoutChanged is emitted by this method for compatibility reasons. + + \sa beginMoveRows() + + \since 4.6 +*/ +void QAbstractItemModel::endMoveRows() +{ + Q_D(QAbstractItemModel); + + QAbstractItemModelPrivate::Change insertChange = d->changes.pop(); + QAbstractItemModelPrivate::Change removeChange = d->changes.pop(); + + d->itemsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first, Qt::Vertical); + + emit rowsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first); + emit layoutChanged(); +} + +/*! Begins a column insertion operation. When reimplementing insertColumns() in a subclass, you must call this @@ -2406,6 +2658,81 @@ void QAbstractItemModel::endRemoveColumns() } /*! + Begins a column move operation. + + When reimplementing a subclass, this method simplifies moving entities + in your model. This method is responsible for moving persistent indexes + in the model, which you would otherwise be required to do yourself. + + Using beginMoveColumns and endMoveColumns is an alternative to emitting + layoutAboutToBeChanged and layoutChanged directly along with changePersistentIndexes. + layoutAboutToBeChanged is emitted by this method for compatibility reasons. + + The \a sourceParent index corresponds to the parent from which the + columns are moved; \a sourceFirst and \a sourceLast are the column numbers of the + columns to be moved. The \a destinationParent index corresponds to the parent into which + the columns are moved. The \a destinationColumn is the column to which the columns will be moved. + That is, the index at column \a sourceFirst in \a sourceParent will become column \a destinationColumn + in \a destinationParent. Its siblings will be moved correspondingly. + + Note that \a sourceParent and \a destinationParent may be the same, in which case you must + ensure that the \a destinationColumn is not within the range of \a sourceFirst and \a sourceLast. + You must also ensure that you do not attempt to move a row to one of its own chilren or ancestors. + This method returns false if either condition is true, in which case you should abort your move operation. + + \sa endMoveColumns() + + \since 4.6 +*/ +bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild) +{ + Q_ASSERT(sourceFirst >= 0); + Q_ASSERT(sourceLast >= sourceFirst); + Q_ASSERT(destinationChild >= 0); + Q_D(QAbstractItemModel); + + if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) { + return false; + } + + d->changes.push(QAbstractItemModelPrivate::Change(sourceParent, sourceFirst, sourceLast)); + int destinationLast = destinationChild + (sourceLast - sourceFirst); + d->changes.push(QAbstractItemModelPrivate::Change(destinationParent, destinationChild, destinationLast)); + + d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal); + + emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild); + emit layoutAboutToBeChanged(); + return true; +} + +/*! + Ends a column move operation. + + When implementing a subclass, you must call this + function \e after moving data within the model's underlying data + store. + + layoutChanged is emitted by this method for compatibility reasons. + + \sa beginMoveColumns() + + \since 4.6 +*/ +void QAbstractItemModel::endMoveColumns() +{ + Q_D(QAbstractItemModel); + + QAbstractItemModelPrivate::Change insertChange = d->changes.pop(); + QAbstractItemModelPrivate::Change removeChange = d->changes.pop(); + + d->itemsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first, Qt::Horizontal); + + emit columnsMoved(removeChange.parent, removeChange.first, removeChange.last, insertChange.parent, insertChange.first); + emit layoutChanged(); +} + +/*! Resets the model to its original state in any attached views. The view to which the model is attached to will be reset as well. diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h index 00f6cb2..b47e4cb 100644 --- a/src/corelib/kernel/qabstractitemmodel.h +++ b/src/corelib/kernel/qabstractitemmodel.h @@ -252,6 +252,13 @@ private: // can only be emitted by QAbstractItemModel void modelAboutToBeReset(); void modelReset(); + void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow ); + void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row ); + + void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn ); + void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column ); + + public Q_SLOTS: virtual bool submit(); virtual void revert(); @@ -272,12 +279,18 @@ protected: void beginRemoveRows(const QModelIndex &parent, int first, int last); void endRemoveRows(); + bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationRow); + void endMoveRows(); + void beginInsertColumns(const QModelIndex &parent, int first, int last); void endInsertColumns(); void beginRemoveColumns(const QModelIndex &parent, int first, int last); void endRemoveColumns(); + bool beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationColumn); + void endMoveColumns(); + void reset(); void changePersistentIndex(const QModelIndex &from, const QModelIndex &to); diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index e81e627..aae3cba 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -80,6 +80,7 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate public: QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {} void removePersistentIndexData(QPersistentModelIndexData *data); + void movePersistentIndexes(QVector indexes, int change, const QModelIndex &parent, Qt::Orientation orientation); void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last); void rowsInserted(const QModelIndex &parent, int first, int last); void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last); @@ -91,6 +92,10 @@ public: static QAbstractItemModel *staticEmptyModel(); static bool variantLessThan(const QVariant &v1, const QVariant &v2); + void itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation); + void itemsMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation); + bool allowMove(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation); + inline QModelIndex createIndex(int row, int column, void *data = 0) const { return q_func()->createIndex(row, column, data); } @@ -132,6 +137,8 @@ public: Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l) {} QModelIndex parent; int first, last; + + bool isValid() { return first >= 0 && last >= 0; } }; QStack changes; diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.cpp b/tests/auto/qabstractitemmodel/dynamictreemodel.cpp new file mode 100644 index 0000000..6c3e0cb --- /dev/null +++ b/tests/auto/qabstractitemmodel/dynamictreemodel.cpp @@ -0,0 +1,245 @@ +/* + Copyright (c) 2009 Stephen Kelly + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "dynamictreemodel.h" + +#include +#include +#include + +#include + +#include + +DynamicTreeModel::DynamicTreeModel(QObject *parent) + : QAbstractItemModel(parent), + nextId(1) +{ +} + +QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &parent) const +{ +// if (column != 0) +// return QModelIndex(); + + + if ( column < 0 || row < 0 ) + return QModelIndex(); + + QList > childIdColumns = m_childItems.value(parent.internalId()); + + + if (childIdColumns.size() == 0) + return QModelIndex(); + + if (column >= childIdColumns.size()) + return QModelIndex(); + + QList rowIds = childIdColumns.at(column); + + if ( row >= rowIds.size()) + return QModelIndex(); + + qint64 id = rowIds.at(row); + + return createIndex(row, column, reinterpret_cast(id)); + +} + +qint64 DynamicTreeModel::findParentId(qint64 searchId) const +{ + if (searchId <= 0) + return -1; + + QHashIterator > > i(m_childItems); + while (i.hasNext()) + { + i.next(); + QListIterator > j(i.value()); + while (j.hasNext()) + { + QList l = j.next(); + if (l.contains(searchId)) + { + return i.key(); + } + } + } + return -1; +} + +QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + qint64 searchId = index.internalId(); + qint64 parentId = findParentId(searchId); + // Will never happen for valid index, but what the hey... + if (parentId <= 0) + return QModelIndex(); + + qint64 grandParentId = findParentId(parentId); + if (grandParentId < 0) + grandParentId = 0; + + int column = 0; + QList childList = m_childItems.value(grandParentId).at(column); + + int row = childList.indexOf(parentId); + + return createIndex(row, column, reinterpret_cast(parentId)); + +} + +int DynamicTreeModel::rowCount(const QModelIndex &index ) const +{ + QList > cols = m_childItems.value(index.internalId()); + + if (cols.size() == 0 ) + return 0; + + if (index.column() > 0) + return 0; + + return cols.at(0).size(); +} + +int DynamicTreeModel::columnCount(const QModelIndex &index ) const +{ +// Q_UNUSED(index); + return m_childItems.value(index.internalId()).size(); +} + +QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (Qt::DisplayRole == role) + { + return m_items.value(index.internalId()); + } + return QVariant(); +} + +void DynamicTreeModel::clear() +{ + m_items.clear(); + m_childItems.clear(); + nextId = 1; + reset(); +} + + +ModelChangeCommand::ModelChangeCommand( DynamicTreeModel *model, QObject *parent ) + : QObject(parent), m_model(model), m_numCols(1), m_startRow(-1), m_endRow(-1) +{ + +} + +QModelIndex ModelChangeCommand::findIndex(QList rows) +{ + const int col = 0; + QModelIndex parent = QModelIndex(); + QListIterator i(rows); + while (i.hasNext()) + { + parent = m_model->index(i.next(), col, parent); + Q_ASSERT(parent.isValid()); + } + return parent; +} + +ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent ) + : ModelChangeCommand(model, parent) +{ + +} + +void ModelInsertCommand::doCommand() +{ + QModelIndex parent = findIndex(m_rowNumbers); + m_model->beginInsertRows(parent, m_startRow, m_endRow); + qint64 parentId = parent.internalId(); + for (int row = m_startRow; row <= m_endRow; row++) + { + for(int col = 0; col < m_numCols; col++ ) + { + if (m_model->m_childItems[parentId].size() <= col) + { + m_model->m_childItems[parentId].append(QList()); + } +// QString name = QUuid::createUuid().toString(); + qint64 id = m_model->newId(); + QString name = QString::number(id); + + m_model->m_items.insert(id, name); + m_model->m_childItems[parentId][col].insert(row, id); + + } + } + m_model->endInsertRows(); +} + + +ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) + : ModelChangeCommand(model, parent) +{ + +} + +void ModelMoveCommand::doCommand() +{ + QModelIndex srcParent = findIndex(m_rowNumbers); + QModelIndex destParent = findIndex(m_destRowNumbers); + + if (!m_model->beginMoveRows(srcParent, m_startRow, m_endRow, destParent, m_destRow)) + { + return; + } + + for (int column = 0; column < m_numCols; ++column) + { + QList l = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1 ); + + for (int i = m_startRow; i <= m_endRow ; i++) + { + m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow); + } + int d; + if (m_destRow < m_startRow) + d = m_destRow; + else + { + if (srcParent == destParent) + d = m_destRow - (m_endRow - m_startRow + 1); + else + d = m_destRow - (m_endRow - m_startRow) + 1; + } + + foreach(const qint64 id, l) + { + m_model->m_childItems[destParent.internalId()][column].insert(d++, id); + } + } + + m_model->endMoveRows(); +} + diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.h b/tests/auto/qabstractitemmodel/dynamictreemodel.h new file mode 100644 index 0000000..88e293c --- /dev/null +++ b/tests/auto/qabstractitemmodel/dynamictreemodel.h @@ -0,0 +1,141 @@ +/* + Copyright (c) 2009 Stephen Kelly + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef DYNAMICTREEMODEL_H +#define DYNAMICTREEMODEL_H + +#include + +#include +#include + +#include + +#include + +template class QList; + +class DynamicTreeModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + DynamicTreeModel(QObject *parent = 0); + + QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + int rowCount(const QModelIndex &index = QModelIndex()) const; + int columnCount(const QModelIndex &index = QModelIndex()) const; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + + void clear(); + +protected slots: + + /** + Finds the parent id of the string with id @p searchId. + + Returns -1 if not found. + */ + qint64 findParentId(qint64 searchId) const; + +private: + QHash m_items; + QHash > > m_childItems; + qint64 nextId; + qint64 newId() { return nextId++; }; + + QModelIndex m_nextParentIndex; + int m_nextRow; + + int m_depth; + int maxDepth; + + friend class ModelInsertCommand; + friend class ModelMoveCommand; + +}; + + +class ModelChangeCommand : public QObject +{ + Q_OBJECT +public: + + ModelChangeCommand( DynamicTreeModel *model, QObject *parent = 0 ); + + virtual ~ModelChangeCommand() {} + + void setAncestorRowNumbers(QList rowNumbers) { m_rowNumbers = rowNumbers; } + + QModelIndex findIndex(QList rows); + + void setStartRow(int row) { m_startRow = row; } + + void setEndRow(int row) { m_endRow = row; } + + void setNumCols(int cols) { m_numCols = cols; } + + virtual void doCommand() = 0; + +protected: + DynamicTreeModel* m_model; + QList m_rowNumbers; + int m_numCols; + int m_startRow; + int m_endRow; + +}; + +typedef QList ModelChangeCommandList; + +class ModelInsertCommand : public ModelChangeCommand +{ + Q_OBJECT + +public: + + ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0 ); + virtual ~ModelInsertCommand() {} + + virtual void doCommand(); +}; + +class ModelMoveCommand : public ModelChangeCommand +{ + Q_OBJECT +public: + ModelMoveCommand(DynamicTreeModel *model, QObject *parent); + + virtual ~ModelMoveCommand() {} + + virtual void doCommand(); + + void setDestAncestors( QList rows ) { m_destRowNumbers = rows; } + + void setDestRow(int row) { m_destRow = row; } + +protected: + QList m_destRowNumbers; + int m_destRow; +}; + + +#endif diff --git a/tests/auto/qabstractitemmodel/qabstractitemmodel.pro b/tests/auto/qabstractitemmodel/qabstractitemmodel.pro index 5ad1020..84ed5a2 100644 --- a/tests/auto/qabstractitemmodel/qabstractitemmodel.pro +++ b/tests/auto/qabstractitemmodel/qabstractitemmodel.pro @@ -1,3 +1,6 @@ load(qttest_p4) -SOURCES += tst_qabstractitemmodel.cpp +SOURCES += tst_qabstractitemmodel.cpp dynamictreemodel.cpp +HEADERS += dynamictreemodel.h + QT = core + diff --git a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp index e99ce06..9c83474 100644 --- a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp +++ b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp @@ -46,6 +46,10 @@ //TESTED_CLASS=QAbstractListModel QAbstractTableModel //TESTED_FILES= +#include "dynamictreemodel.h" + +Q_DECLARE_METATYPE(QModelIndex) + /*! Note that this doesn't test models, but any functionality that QAbstractItemModel shoudl provide */ @@ -86,6 +90,30 @@ private slots: void complexChangesWithPersistent(); + void testMoveSameParentUp_data(); + void testMoveSameParentUp(); + + void testMoveSameParentDown_data(); + void testMoveSameParentDown(); + + void testMoveToGrandParent_data(); + void testMoveToGrandParent(); + + void testMoveToSibling_data(); + void testMoveToSibling(); + + void testMoveToUncle_data(); + void testMoveToUncle(); + + void testMoveToDescendants(); + + void testMoveWithinOwnRange_data(); + void testMoveWithinOwnRange(); + + +private: + DynamicTreeModel *m_model; + }; /*! @@ -242,7 +270,20 @@ void tst_QAbstractItemModel::cleanupTestCase() void tst_QAbstractItemModel::init() { - + m_model = new DynamicTreeModel(this); + + ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this); + insertCommand->setNumCols(4); + insertCommand->setStartRow(0); + insertCommand->setEndRow(9); + insertCommand->doCommand(); + + insertCommand = new ModelInsertCommand(m_model, this); + insertCommand->setAncestorRowNumbers(QList() << 5); + insertCommand->setNumCols(4); + insertCommand->setStartRow(0); + insertCommand->setEndRow(9); + insertCommand->doCommand(); } void tst_QAbstractItemModel::cleanup() @@ -815,5 +856,803 @@ void tst_QAbstractItemModel::complexChangesWithPersistent() } +void tst_QAbstractItemModel::testMoveSameParentDown_data() +{ + QTest::addColumn("startRow"); + QTest::addColumn("endRow"); + QTest::addColumn("destRow"); + + // Move from the start to the middle + QTest::newRow("move01") << 0 << 2 << 8; + // Move from the start to the end + QTest::newRow("move02") << 0 << 2 << 10; + // Move from the middle to the middle + QTest::newRow("move03") << 3 << 5 << 8; + // Move from the middle to the end + QTest::newRow("move04") << 3 << 5 << 10; +} + +void tst_QAbstractItemModel::testMoveSameParentDown() +{ + QFETCH( int, startRow); + QFETCH( int, endRow); + QFETCH( int, destRow); + + QList persistentList; + QModelIndexList indexList; + + for (int column = 0; column < m_model->columnCount(); ++column) + { + for (int row= 0; row < m_model->rowCount(); ++row) + { + QModelIndex idx = m_model->index(row, column); + QVERIFY(idx.isValid()); + indexList << idx; + persistentList << QPersistentModelIndex(idx); + } + } + + QModelIndex parent = m_model->index(5, 0); + for (int column = 0; column < m_model->columnCount(); ++column) + { + for (int row= 0; row < m_model->rowCount(parent); ++row) + { + QModelIndex idx = m_model->index(row, column, parent); + QVERIFY(idx.isValid()); + indexList << idx; + persistentList << QPersistentModelIndex(idx); + } + } + + QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + + ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); + moveCommand->setNumCols(4); + moveCommand->setStartRow(startRow); + moveCommand->setEndRow(endRow); + moveCommand->setDestRow(destRow); + moveCommand->doCommand(); + + QVariantList beforeSignal = beforeSpy.takeAt(0); + QVariantList afterSignal = afterSpy.takeAt(0); + + QCOMPARE(beforeSignal.size(), 5); + QCOMPARE(beforeSignal.at(0).value(), QModelIndex()); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value(), QModelIndex()); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value(), QModelIndex()); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value(), QModelIndex()); + QCOMPARE(afterSignal.at(4).toInt(), destRow); + + for (int i = 0; i < indexList.size(); i++) + { + QModelIndex idx = indexList.at(i); + QModelIndex persistentIndex = persistentList.at(i); + if (idx.parent() == QModelIndex()) + { + int row = idx.row(); + if ( row >= startRow) + { + if (row <= endRow) + { + QCOMPARE(row + destRow - endRow - 1, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(idx.parent(), persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } else if ( row < destRow) + { + QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(idx.parent(), persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } else + { + QCOMPARE(idx, persistentIndex); + } + } else + { + QCOMPARE(idx, persistentIndex); + } + } else + { + QCOMPARE(idx, persistentIndex); + } + } +} + +void tst_QAbstractItemModel::testMoveSameParentUp_data() +{ + QTest::addColumn("startRow"); + QTest::addColumn("endRow"); + QTest::addColumn("destRow"); + + // Move from the middle to the start + QTest::newRow("move01") << 5 << 7 << 0; + // Move from the end to the start + QTest::newRow("move02") << 8 << 9 << 0; + // Move from the middle to the middle + QTest::newRow("move03") << 5 << 7 << 2; + // Move from the end to the middle + QTest::newRow("move04") << 8 << 9 << 5; +} + +void tst_QAbstractItemModel::testMoveSameParentUp() +{ + + QFETCH( int, startRow); + QFETCH( int, endRow); + QFETCH( int, destRow); + + QList persistentList; + QModelIndexList indexList; + + for (int column = 0; column < m_model->columnCount(); ++column) + { + for (int row= 0; row < m_model->rowCount(); ++row) + { + QModelIndex idx = m_model->index(row, column); + QVERIFY(idx.isValid()); + indexList << idx; + persistentList << QPersistentModelIndex(idx); + } + } + + QModelIndex parent = m_model->index(2, 0); + for (int column = 0; column < m_model->columnCount(); ++column) + { + for (int row= 0; row < m_model->rowCount(parent); ++row) + { + QModelIndex idx = m_model->index(row, column, parent); + QVERIFY(idx.isValid()); + indexList << idx; + persistentList << QPersistentModelIndex(idx); + } + } + + QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + + + ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); + moveCommand->setNumCols(4); + moveCommand->setStartRow(startRow); + moveCommand->setEndRow(endRow); + moveCommand->setDestRow(destRow); + moveCommand->doCommand(); + + QVariantList beforeSignal = beforeSpy.takeAt(0); + QVariantList afterSignal = afterSpy.takeAt(0); + + QCOMPARE(beforeSignal.size(), 5); + QCOMPARE(beforeSignal.at(0).value(), QModelIndex()); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value(), QModelIndex()); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value(), QModelIndex()); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value(), QModelIndex()); + QCOMPARE(afterSignal.at(4).toInt(), destRow); + + + for (int i = 0; i < indexList.size(); i++) + { + QModelIndex idx = indexList.at(i); + QModelIndex persistentIndex = persistentList.at(i); + if (idx.parent() == QModelIndex()) + { + int row = idx.row(); + if ( row >= destRow) + { + if (row < startRow) + { + QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(idx.parent(), persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } else if ( row <= endRow) + { + QCOMPARE(row + destRow - startRow, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(idx.parent(), persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } else + { + QCOMPARE(idx, persistentIndex); + } + } else + { + QCOMPARE(idx, persistentIndex); + } + } else + { + QCOMPARE(idx, persistentIndex); + } + } +} + +void tst_QAbstractItemModel::testMoveToGrandParent_data() +{ + QTest::addColumn("startRow"); + QTest::addColumn("endRow"); + QTest::addColumn("destRow"); + + // Move from the start to the middle + QTest::newRow("move01") << 0 << 2 << 8; + // Move from the start to the end + QTest::newRow("move02") << 0 << 2 << 10; + // Move from the middle to the middle + QTest::newRow("move03") << 3 << 5 << 8; + // Move from the middle to the end + QTest::newRow("move04") << 3 << 5 << 10; + + // Move from the middle to the start + QTest::newRow("move05") << 5 << 7 << 0; + // Move from the end to the start + QTest::newRow("move06") << 8 << 9 << 0; + // Move from the middle to the middle + QTest::newRow("move07") << 5 << 7 << 2; + // Move from the end to the middle + QTest::newRow("move08") << 8 << 9 << 5; + + // Moving to the same row in a different parent doesn't confuse things. + QTest::newRow("move09") << 8 << 8 << 8; + + // Moving to the row of my parent and its neighbours doesn't confuse things + QTest::newRow("move09") << 8 << 8 << 4; + QTest::newRow("move10") << 8 << 8 << 5; + QTest::newRow("move11") << 8 << 8 << 6; + + // Moving everything from one parent to another + QTest::newRow("move12") << 0 << 9 << 10; +} + +void tst_QAbstractItemModel::testMoveToGrandParent() +{ + + QFETCH( int, startRow); + QFETCH( int, endRow); + QFETCH( int, destRow); + + QList persistentList; + QModelIndexList indexList; + QModelIndexList parentsList; + + for (int column = 0; column < m_model->columnCount(); ++column) + { + for (int row= 0; row < m_model->rowCount(); ++row) + { + QModelIndex idx = m_model->index(row, column); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + } + + QModelIndex sourceIndex = m_model->index(5, 0); + for (int column = 0; column < m_model->columnCount(); ++column) + { + for (int row= 0; row < m_model->rowCount(sourceIndex); ++row) + { + QModelIndex idx = m_model->index(row, column, sourceIndex); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + } + + QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + + + ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); + moveCommand->setAncestorRowNumbers(QList() << 5); + moveCommand->setNumCols(4); + moveCommand->setStartRow(startRow); + moveCommand->setEndRow(endRow); + moveCommand->setDestRow(destRow); + moveCommand->doCommand(); + + QVariantList beforeSignal = beforeSpy.takeAt(0); + QVariantList afterSignal = afterSpy.takeAt(0); + + QCOMPARE(beforeSignal.size(), 5); + QCOMPARE(beforeSignal.at(0).value(), sourceIndex); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value(), QModelIndex()); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value(), sourceIndex); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value(), QModelIndex()); + QCOMPARE(afterSignal.at(4).toInt(), destRow); + + for (int i = 0; i < indexList.size(); i++) + { + QModelIndex idx = indexList.at(i); + QModelIndex idxParent = parentsList.at(i); + QModelIndex persistentIndex = persistentList.at(i); + int row = idx.row(); + if (idxParent == QModelIndex()) + { + if ( row >= destRow) + { + QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(idxParent, persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } else + { + QCOMPARE(idx, persistentIndex); + } + } else + { + if (row < startRow) + { + QCOMPARE(idx, persistentIndex); + } else if (row <= endRow) + { + QCOMPARE(row + destRow - startRow, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(QModelIndex(), persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } else { + QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + + if (idxParent.row() >= destRow) + { + QModelIndex adjustedParent; + adjustedParent = idxParent.sibling( idxParent.row() + endRow - startRow + 1, idxParent.column()); + QCOMPARE(adjustedParent, persistentIndex.parent()); + } else + { + QCOMPARE(idxParent, persistentIndex.parent()); + } + QCOMPARE(idx.model(), persistentIndex.model()); + } + } + } +} + +void tst_QAbstractItemModel::testMoveToSibling_data() +{ + QTest::addColumn("startRow"); + QTest::addColumn("endRow"); + QTest::addColumn("destRow"); + + // Move from the start to the middle + QTest::newRow("move01") << 0 << 2 << 8; + // Move from the start to the end + QTest::newRow("move02") << 0 << 2 << 10; + // Move from the middle to the middle + QTest::newRow("move03") << 2 << 4 << 8; + // Move from the middle to the end + QTest::newRow("move04") << 2 << 4 << 10; + + // Move from the middle to the start + QTest::newRow("move05") << 8 << 8 << 0; + // Move from the end to the start + QTest::newRow("move06") << 8 << 9 << 0; + // Move from the middle to the middle + QTest::newRow("move07") << 6 << 8 << 2; + // Move from the end to the middle + QTest::newRow("move08") << 8 << 9 << 5; + + // Moving to the same row in a different parent doesn't confuse things. + QTest::newRow("move09") << 8 << 8 << 8; + + // Moving to the row of my target and its neighbours doesn't confuse things + QTest::newRow("move09") << 8 << 8 << 4; + QTest::newRow("move10") << 8 << 8 << 5; + QTest::newRow("move11") << 8 << 8 << 6; +} + +void tst_QAbstractItemModel::testMoveToSibling() +{ + + QFETCH( int, startRow); + QFETCH( int, endRow); + QFETCH( int, destRow); + + QList persistentList; + QModelIndexList indexList; + QModelIndexList parentsList; + + const int column = 0; + + for (int i= 0; i < m_model->rowCount(); ++i) + { + QModelIndex idx = m_model->index(i, column); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + + QModelIndex destIndex = m_model->index(5, 0); + QModelIndex sourceIndex; + for (int i= 0; i < m_model->rowCount(destIndex); ++i) + { + QModelIndex idx = m_model->index(i, column, destIndex); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + + QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + + + ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); + moveCommand->setNumCols(4); + moveCommand->setStartRow(startRow); + moveCommand->setEndRow(endRow); + moveCommand->setDestAncestors(QList() << 5); + moveCommand->setDestRow(destRow); + moveCommand->doCommand(); + + QVariantList beforeSignal = beforeSpy.takeAt(0); + QVariantList afterSignal = afterSpy.takeAt(0); + + QCOMPARE(beforeSignal.size(), 5); + QCOMPARE(beforeSignal.at(0).value(), sourceIndex); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value(), destIndex); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value(), sourceIndex); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value(), destIndex); + QCOMPARE(afterSignal.at(4).toInt(), destRow); + + for (int i = 0; i < indexList.size(); i++) + { + QModelIndex idx = indexList.at(i); + QModelIndex idxParent = parentsList.at(i); + QModelIndex persistentIndex = persistentList.at(i); + + QModelIndex adjustedDestination = destIndex.sibling(destIndex.row() - (endRow - startRow + 1), destIndex.column()); + int row = idx.row(); + if (idxParent == destIndex) + { + if ( row >= destRow) + { + QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + if (idxParent.row() > startRow) + { + QCOMPARE(adjustedDestination, persistentIndex.parent()); + } else { + QCOMPARE(destIndex, persistentIndex.parent()); + } + QCOMPARE(idx.model(), persistentIndex.model()); + } else + { + QCOMPARE(idx, persistentIndex); + } + } else + { + if (row < startRow) + { + QCOMPARE(idx, persistentIndex); + } else if (row <= endRow) + { + QCOMPARE(row + destRow - startRow, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + if (destIndex.row() > startRow) + { + QCOMPARE(adjustedDestination, persistentIndex.parent()); + } else { + QCOMPARE(destIndex, persistentIndex.parent()); + } + + QCOMPARE(idx.model(), persistentIndex.model()); + + } else { + QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(idxParent, persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } + } + } +} + +void tst_QAbstractItemModel::testMoveToUncle_data() +{ + + QTest::addColumn("startRow"); + QTest::addColumn("endRow"); + QTest::addColumn("destRow"); + + // Move from the start to the middle + QTest::newRow("move01") << 0 << 2 << 8; + // Move from the start to the end + QTest::newRow("move02") << 0 << 2 << 10; + // Move from the middle to the middle + QTest::newRow("move03") << 3 << 5 << 8; + // Move from the middle to the end + QTest::newRow("move04") << 3 << 5 << 10; + + // Move from the middle to the start + QTest::newRow("move05") << 5 << 7 << 0; + // Move from the end to the start + QTest::newRow("move06") << 8 << 9 << 0; + // Move from the middle to the middle + QTest::newRow("move07") << 5 << 7 << 2; + // Move from the end to the middle + QTest::newRow("move08") << 8 << 9 << 5; + + // Moving to the same row in a different parent doesn't confuse things. + QTest::newRow("move09") << 8 << 8 << 8; + + // Moving to the row of my parent and its neighbours doesn't confuse things + QTest::newRow("move09") << 8 << 8 << 4; + QTest::newRow("move10") << 8 << 8 << 5; + QTest::newRow("move11") << 8 << 8 << 6; + + // Moving everything from one parent to another + QTest::newRow("move12") << 0 << 9 << 10; +} + +void tst_QAbstractItemModel::testMoveToUncle() +{ + // Need to have some extra rows available. + ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this); + insertCommand->setAncestorRowNumbers(QList() << 9); + insertCommand->setNumCols(4); + insertCommand->setStartRow(0); + insertCommand->setEndRow(9); + insertCommand->doCommand(); + + QFETCH( int, startRow); + QFETCH( int, endRow); + QFETCH( int, destRow); + + QList persistentList; + QModelIndexList indexList; + QModelIndexList parentsList; + + const int column = 0; + + QModelIndex sourceIndex = m_model->index(9, 0); + for (int i= 0; i < m_model->rowCount(sourceIndex); ++i) + { + QModelIndex idx = m_model->index(i, column, sourceIndex); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + + QModelIndex destIndex = m_model->index(5, 0); + for (int i= 0; i < m_model->rowCount(destIndex); ++i) + { + QModelIndex idx = m_model->index(i, column, destIndex); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + + QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + + ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); + moveCommand->setAncestorRowNumbers(QList() << 9); + moveCommand->setNumCols(4); + moveCommand->setStartRow(startRow); + moveCommand->setEndRow(endRow); + moveCommand->setDestAncestors(QList() << 5); + moveCommand->setDestRow(destRow); + moveCommand->doCommand(); + + QVariantList beforeSignal = beforeSpy.takeAt(0); + QVariantList afterSignal = afterSpy.takeAt(0); + + QCOMPARE(beforeSignal.size(), 5); + QCOMPARE(beforeSignal.at(0).value(), sourceIndex); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value(), destIndex); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value(), sourceIndex); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value(), destIndex); + QCOMPARE(afterSignal.at(4).toInt(), destRow); + + for (int i = 0; i < indexList.size(); i++) + { + QModelIndex idx = indexList.at(i); + QModelIndex idxParent = parentsList.at(i); + QModelIndex persistentIndex = persistentList.at(i); + + int row = idx.row(); + if (idxParent == destIndex) + { + if ( row >= destRow) + { + QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(destIndex, persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } else + { + QCOMPARE(idx, persistentIndex); + } + } else + { + if (row < startRow) + { + QCOMPARE(idx, persistentIndex); + } else if (row <= endRow) + { + QCOMPARE(row + destRow - startRow, persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(destIndex, persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + + } else { + QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); + QCOMPARE(idx.column(), persistentIndex.column()); + QCOMPARE(idxParent, persistentIndex.parent()); + QCOMPARE(idx.model(), persistentIndex.model()); + } + } + } +} + +void tst_QAbstractItemModel::testMoveToDescendants() +{ + // Attempt to move a row to its ancestors depth rows deep. + const int depth = 6; + + // Need to have some extra rows available in a tree. + QList rows; + ModelInsertCommand *insertCommand; + for (int i = 0; i < depth; i++) + { + insertCommand = new ModelInsertCommand(m_model, this); + insertCommand->setAncestorRowNumbers(rows); + insertCommand->setNumCols(4); + insertCommand->setStartRow(0); + insertCommand->setEndRow(9); + insertCommand->doCommand(); + rows << 9; + } + + QList persistentList; + QModelIndexList indexList; + QModelIndexList parentsList; + + const int column = 0; + + QModelIndex sourceIndex = m_model->index(9, 0); + for (int i= 0; i < m_model->rowCount(sourceIndex); ++i) + { + QModelIndex idx = m_model->index(i, column, sourceIndex); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + + QModelIndex destIndex = m_model->index(5, 0); + for (int i= 0; i < m_model->rowCount(destIndex); ++i) + { + QModelIndex idx = m_model->index(i, column, destIndex); + QVERIFY(idx.isValid()); + indexList << idx; + parentsList << idx.parent(); + persistentList << QPersistentModelIndex(idx); + } + + QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + + ModelMoveCommand *moveCommand; + QList ancestors; + while (ancestors.size() < depth) + { + ancestors << 9; + for (int row = 0; row <= 9; row++) + { + moveCommand = new ModelMoveCommand(m_model, this); + moveCommand->setNumCols(4); + moveCommand->setStartRow(9); + moveCommand->setEndRow(9); + moveCommand->setDestAncestors(ancestors); + moveCommand->setDestRow(row); + moveCommand->doCommand(); + + QVERIFY(beforeSpy.size() == 0); + QVERIFY(afterSpy.size() == 0); + } + } +} + +void tst_QAbstractItemModel::testMoveWithinOwnRange_data() +{ + QTest::addColumn("startRow"); + QTest::addColumn("endRow"); + QTest::addColumn("destRow"); + + QTest::newRow("move01") << 0 << 0 << 0; + QTest::newRow("move02") << 0 << 0 << 1; + QTest::newRow("move03") << 0 << 5 << 0; + QTest::newRow("move04") << 0 << 5 << 1; + QTest::newRow("move05") << 0 << 5 << 2; + QTest::newRow("move06") << 0 << 5 << 3; + QTest::newRow("move07") << 0 << 5 << 4; + QTest::newRow("move08") << 0 << 5 << 5; + QTest::newRow("move09") << 0 << 5 << 6; + QTest::newRow("move08") << 3 << 5 << 5; + QTest::newRow("move08") << 3 << 5 << 6; + QTest::newRow("move09") << 4 << 5 << 5; + QTest::newRow("move10") << 4 << 5 << 6; + QTest::newRow("move11") << 5 << 5 << 5; + QTest::newRow("move12") << 5 << 5 << 6; + QTest::newRow("move13") << 5 << 9 << 9; + QTest::newRow("move14") << 5 << 9 << 10; + QTest::newRow("move15") << 6 << 9 << 9; + QTest::newRow("move16") << 6 << 9 << 10; + QTest::newRow("move17") << 7 << 9 << 9; + QTest::newRow("move18") << 7 << 9 << 10; + QTest::newRow("move19") << 8 << 9 << 9; + QTest::newRow("move20") << 8 << 9 << 10; + QTest::newRow("move21") << 9 << 9 << 9; + QTest::newRow("move22") << 0 << 9 << 10; + +} + +void tst_QAbstractItemModel::testMoveWithinOwnRange() +{ + + QFETCH( int, startRow); + QFETCH( int, endRow); + QFETCH( int, destRow); + + + QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); + + ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); + moveCommand->setNumCols(4); + moveCommand->setStartRow(startRow); + moveCommand->setEndRow(endRow); + moveCommand->setDestRow(destRow); + moveCommand->doCommand(); + + QVERIFY(beforeSpy.size() == 0); + QVERIFY(afterSpy.size() == 0); + + +} + + + QTEST_MAIN(tst_QAbstractItemModel) #include "tst_qabstractitemmodel.moc" -- cgit v0.12 From 98f62f60605bec8ba152e56dd32308e9a5afb5c4 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 26 Aug 2009 16:41:40 +0200 Subject: Fix build of autotest on MSVC Reviewed-by: ogoffart --- tests/auto/qobject/tst_qobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 65dc742..b20c0e0 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -2933,7 +2933,7 @@ class OverloadObject : public QObject friend class tst_QObject; Q_OBJECT signals: - void sig(int i, char c, qreal m = 12) const; + void sig(int i, char c, qreal m = 12); void sig(int i, int j = 12); void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const; void other(int a = 0); -- cgit v0.12 From ca57a8122970ed408f50fed05f77d3a973676165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 26 Aug 2009 17:00:12 +0200 Subject: doc: Misspelled class names. --- src/gui/effects/qgraphicseffect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 0289914..f620878 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -61,13 +61,13 @@ Qt provides the following standard effects: \list - \o QGraphicsGrayScaleEffect - renders the item in shades of gray + \o QGraphicsGrayscaleEffect - renders the item in shades of gray \o QGraphicsColorizeEffect - renders the item in shades of any given color \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size \o QGraphicsBlurEffect - blurs the item by a given radius \o QGraphicsDropShadowEffect - renders a dropshadow behind the item \o QGraphicsOpacityEffect - renders the item with an opacity - \o QGrahicsShaderEffect - renders the item with a pixel shader fragment + \o QGraphicsShaderEffect - renders the item with a pixel shader fragment \endlist -- cgit v0.12 From 6682b9915d80238ce97594909074aef974a74279 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 26 Aug 2009 14:50:18 +0200 Subject: Improved QPainter API for allowing native painting in GL / VG. Previously we were using QPaintEngine::syncState() which is not ideal naming-wise, since it actually prepares for native painting instead of syncing the painter's state to native state. Reviewed-by: Trond --- dist/changes-4.6.0 | 11 ++-- examples/opengl/hellogl_es2/glwidget.cpp | 4 +- examples/openvg/star/starwidget.cpp | 4 +- src/gui/painting/qpaintengineex_p.h | 3 ++ src/gui/painting/qpainter.cpp | 39 ++++++++++++++ src/gui/painting/qpainter.h | 3 ++ .../gl2paintengineex/qpaintengineex_opengl2.cpp | 8 ++- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 4 +- src/opengl/qglpixmapfilter.cpp | 1 - src/openvg/qpaintengine_vg.cpp | 63 +++++++++++----------- src/openvg/qpaintengine_vg_p.h | 3 +- 11 files changed, 100 insertions(+), 43 deletions(-) diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0 index 8c2c2c8..194d670 100644 --- a/dist/changes-4.6.0 +++ b/dist/changes-4.6.0 @@ -49,10 +49,13 @@ information about a particular change. this is that Nokia focuses on OpenGL for desktop hardware accelerated rendering. - - When mixing OpenGL and QPainter calls you need to first call syncState() - on the paint engine, for example "painter->paintEngine()->syncState()". - This is to ensure that the engine flushes any pending drawing and sets up - the GL modelview/projection matrices properly. + - When mixing OpenGL and QPainter calls you need to surround your custom + OpenGL calls with QPainter::beginNativePainting() and + QPainter::endNativePainting(). + This is to ensure that the paint engine flushes any pending drawing and sets + up the GL modelview/projection matrices properly before you can issue custom + OpenGL calls, and to let the paint engine synchronize to the painter state + before resuming regular QPainter based drawing. - Graphics View has undergone heavy optimization work, and as a result of this work, the following behavior changes were introduced. diff --git a/examples/opengl/hellogl_es2/glwidget.cpp b/examples/opengl/hellogl_es2/glwidget.cpp index 9a2a83e..50a7797 100644 --- a/examples/opengl/hellogl_es2/glwidget.cpp +++ b/examples/opengl/hellogl_es2/glwidget.cpp @@ -266,7 +266,7 @@ void GLWidget::paintGL() QPainter painter; painter.begin(this); - painter.paintEngine()->syncState(); + painter.beginNativePainting(); glClearColor(0.1f, 0.1f, 0.2f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -302,6 +302,8 @@ void GLWidget::paintGL() glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); + painter.endNativePainting(); + if (m_showBubbles) foreach (Bubble *bubble, bubbles) { bubble->drawBubble(&painter); diff --git a/examples/openvg/star/starwidget.cpp b/examples/openvg/star/starwidget.cpp index 1a64fc9..ab11bdb 100644 --- a/examples/openvg/star/starwidget.cpp +++ b/examples/openvg/star/starwidget.cpp @@ -91,7 +91,7 @@ void StarWidget::paintEvent(QPaintEvent *) // Flush the state changes to the OpenVG implementation // and prepare to perform raw OpenVG calls. - painter.paintEngine()->syncState(); + painter.beginNativePainting(); // Cache the path if we haven't already. if (path == VG_INVALID_HANDLE) { @@ -109,7 +109,7 @@ void StarWidget::paintEvent(QPaintEvent *) vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH); // Restore normal QPainter operations. - painter.paintEngine()->syncState(); + painter.endNativePainting(); painter.end(); } diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index cf3aad7..1ba2153 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -204,6 +204,9 @@ public: virtual void sync() {} + virtual void beginNativePainting() {} + virtual void endNativePainting() {} + virtual QPixmapFilter *createPixmapFilter(int /*type*/) const { return 0; } protected: diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index e1a6e80..cba4ad9 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1889,6 +1889,45 @@ QPaintEngine *QPainter::paintEngine() const return d->engine; } +/*! + Flushes the painting pipeline and prepares for the user issuing + native painting commands. Must be followed by a call to + endNativePainting(). + + \sa endNativePainting() +*/ +void QPainter::beginNativePainting() +{ + Q_D(QPainter); + if (!d->engine) { + qWarning("QPainter::beginNativePainting: Painter not active"); + return; + } + + if (d->extended) + d->extended->beginNativePainting(); +} + +/*! + Restores the painter after manually issuing native painting commands. + Lets the painter restore any native state that it relies on before + calling any other painter commands. + + \sa beginNativePainting() +*/ +void QPainter::endNativePainting() +{ + Q_D(const QPainter); + if (!d->engine) { + qWarning("QPainter::beginNativePainting: Painter not active"); + return; + } + + if (d->extended) + d->extended->endNativePainting(); + else + d->engine->syncState(); +} /*! Returns the font metrics for the painter if the painter is diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h index 14d1cf8..1bb97c6 100644 --- a/src/gui/painting/qpainter.h +++ b/src/gui/painting/qpainter.h @@ -423,6 +423,9 @@ public: static QPaintDevice *redirected(const QPaintDevice *device, QPoint *offset = 0); static void restoreRedirected(const QPaintDevice *device); + void beginNativePainting(); + void endNativePainting(); + #ifdef QT3_SUPPORT inline QT3_SUPPORT void setBackgroundColor(const QColor &color) { setBackground(color); } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 136a078..ca33101 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -675,7 +675,7 @@ void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& s glDrawArrays(GL_TRIANGLE_FAN, 0, 4); } -void QGL2PaintEngineEx::sync() +void QGL2PaintEngineEx::beginNativePainting() { Q_D(QGL2PaintEngineEx); ensureActive(); @@ -721,6 +721,12 @@ void QGL2PaintEngineEx::sync() d->needsSync = true; } +void QGL2PaintEngineEx::endNativePainting() +{ + Q_D(QGL2PaintEngineEx); + d->needsSync = true; +} + const QGLContext *QGL2PaintEngineEx::context() { Q_D(QGL2PaintEngineEx); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 7b734e3..2eec4d5 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -133,7 +133,9 @@ public: inline const QOpenGL2PaintEngineState *state() const { return static_cast(QPaintEngineEx::state()); } - virtual void sync(); + + void beginNativePainting(); + void endNativePainting(); const QGLContext* context(); diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index df7811e..83fddd1 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -338,7 +338,6 @@ bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QGL2PaintEngineEx *engine = static_cast(painter->paintEngine()); - engine->syncState(); painter->save(); // ensure GL_LINEAR filtering is used diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index d2c7b8b..09eb646 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -3072,43 +3072,42 @@ void QVGPaintEngine::setState(QPainterState *s) } } -// Called from QPaintEngine::syncState() to force a state flush. -// This should be called before and after raw VG operations. -void QVGPaintEngine::updateState(const QPaintEngineState &state) +void QVGPaintEngine::beginNativePainting() { - Q_UNUSED(state); Q_D(QVGPaintEngine); - if (!(d->rawVG)) { - // About to enter raw VG mode: flush pending changes and make - // sure that all matrices are set to the current transformation. - QVGPainterState *s = this->state(); - d->ensurePen(s->pen); - d->ensureBrush(s->brush); - d->ensurePathTransform(); - d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, d->imageTransform); + // About to enter raw VG mode: flush pending changes and make + // sure that all matrices are set to the current transformation. + QVGPainterState *s = this->state(); + d->ensurePen(s->pen); + d->ensureBrush(s->brush); + d->ensurePathTransform(); + d->setTransform(VG_MATRIX_IMAGE_USER_TO_SURFACE, d->imageTransform); #if !defined(QVG_NO_DRAW_GLYPHS) - d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, d->pathTransform); + d->setTransform(VG_MATRIX_GLYPH_USER_TO_SURFACE, d->pathTransform); #endif - d->rawVG = true; - } else { - // Exiting raw VG mode: force all state values to be - // explicitly set on the VG engine to undo any changes - // that were made by the raw VG function calls. - QPaintEngine::DirtyFlags dirty = d->dirty; - d->clearModes(); - d->forcePenChange = true; - d->forceBrushChange = true; - d->penType = (VGPaintType)0; - d->brushType = (VGPaintType)0; - d->clearColor = QColor(); - d->fillPaint = d->brushPaint; - restoreState(QPaintEngine::AllDirty); - d->dirty = dirty; - d->rawVG = false; - vgSetPaint(d->penPaint, VG_STROKE_PATH); - vgSetPaint(d->brushPaint, VG_FILL_PATH); - } + d->rawVG = true; +} + +void QVGPaintEngine::endNativePainting() +{ + Q_D(QVGPaintEngine); + // Exiting raw VG mode: force all state values to be + // explicitly set on the VG engine to undo any changes + // that were made by the raw VG function calls. + QPaintEngine::DirtyFlags dirty = d->dirty; + d->clearModes(); + d->forcePenChange = true; + d->forceBrushChange = true; + d->penType = (VGPaintType)0; + d->brushType = (VGPaintType)0; + d->clearColor = QColor(); + d->fillPaint = d->brushPaint; + restoreState(QPaintEngine::AllDirty); + d->dirty = dirty; + d->rawVG = false; + vgSetPaint(d->penPaint, VG_STROKE_PATH); + vgSetPaint(d->brushPaint, VG_FILL_PATH); } QPixmapFilter *QVGPaintEngine::createPixmapFilter(int type) const diff --git a/src/openvg/qpaintengine_vg_p.h b/src/openvg/qpaintengine_vg_p.h index 469ec9e..f0a7838 100644 --- a/src/openvg/qpaintengine_vg_p.h +++ b/src/openvg/qpaintengine_vg_p.h @@ -140,7 +140,8 @@ public: QVGPainterState *state() { return static_cast(QPaintEngineEx::state()); } const QVGPainterState *state() const { return static_cast(QPaintEngineEx::state()); } - void updateState(const QPaintEngineState &state); + void beginNativePainting(); + void endNativePainting(); QPixmapFilter *createPixmapFilter(int type) const; -- cgit v0.12 From 629e464f2774fc1893760888e676d8e073da5d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 26 Aug 2009 15:20:47 +0200 Subject: Improved GLSL precision specifiers in GL 2 engine. The recommended specifiers are lowp for colors / normal vectors, mediump for texture coordinates when a limited range is sufficient, and highp for generic texture coordinates and vertex coordinates / transformation matrices. We used to use mediump for texture coordinate in some places, but since we don't control the texturing scenarios we need to handle the worst case, which is zooming in on part of a large texture (2048x2048) with bilinear filtering. To properly handle this case without color banding mediump is probably not sufficient, so we'll use highp for texture coordinates. Reviewed-by: Tom --- .../gl2paintengineex/qglengineshadersource_p.h | 48 +++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index a8e2e72..cd3cf57 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -73,8 +73,8 @@ static const char* const qglslMainVertexShader = "\ }"; static const char* const qglslMainWithTexCoordsVertexShader = "\ - attribute mediump vec2 textureCoordArray; \ - varying mediump vec2 textureCoords; \ + attribute highp vec2 textureCoordArray; \ + varying highp vec2 textureCoords; \ uniform highp float depth;\ void setPosition();\ void main(void) \ @@ -105,9 +105,9 @@ static const char* const qglslPositionWithPatternBrushVertexShader = "\ attribute highp vec4 vertexCoordsArray; \ uniform highp mat4 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ - uniform mediump vec2 invertedTextureSize; \ - uniform mediump mat3 brushTransform; \ - varying mediump vec2 patternTexCoords; \ + uniform highp vec2 invertedTextureSize; \ + uniform highp mat3 brushTransform; \ + varying highp vec2 patternTexCoords; \ void setPosition(void) { \ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ @@ -124,9 +124,9 @@ static const char* const qglslAffinePositionWithPatternBrushVertexShader = qglslPositionWithPatternBrushVertexShader; static const char* const qglslPatternBrushSrcFragmentShader = "\ - uniform sampler2D brushTexture;\ + uniform lowp sampler2D brushTexture;\ uniform lowp vec4 patternColor; \ - varying mediump vec2 patternTexCoords;\ + varying highp vec2 patternTexCoords;\ lowp vec4 srcPixel() { \ return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \ }\n"; @@ -139,7 +139,7 @@ static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\ uniform mediump vec2 halfViewportSize; \ uniform highp vec3 linearData; \ uniform highp mat3 brushTransform; \ - varying mediump float index ; \ + varying mediump float index; \ void setPosition() { \ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ @@ -155,7 +155,7 @@ static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader = qglslPositionWithLinearGradientBrushVertexShader; static const char* const qglslLinearGradientBrushSrcFragmentShader = "\ - uniform sampler2D brushTexture; \ + uniform lowp sampler2D brushTexture; \ varying mediump float index; \ lowp vec4 srcPixel() { \ mediump vec2 val = vec2(index, 0.5); \ @@ -187,7 +187,7 @@ static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\ #define INVERSE_2PI 0.1591549430918953358 \n\ - uniform sampler2D brushTexture; \n\ + uniform lowp sampler2D brushTexture; \n\ uniform mediump float angle; \ varying highp vec2 A; \ lowp vec4 srcPixel() { \ @@ -226,7 +226,7 @@ static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader = qglslPositionWithRadialGradientBrushVertexShader; static const char* const qglslRadialGradientBrushSrcFragmentShader = "\ - uniform sampler2D brushTexture; \ + uniform lowp sampler2D brushTexture; \ uniform highp float fmp2_m_radius2; \ uniform highp float inverse_2_fmp2_m_radius2; \ varying highp float b; \ @@ -243,9 +243,9 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\ attribute highp vec4 vertexCoordsArray; \ uniform highp mat4 pmvMatrix; \ uniform mediump vec2 halfViewportSize; \ - uniform mediump vec2 invertedTextureSize; \ - uniform mediump mat3 brushTransform; \ - varying mediump vec2 brushTextureCoords; \ + uniform highp vec2 invertedTextureSize; \ + uniform highp mat3 brushTransform; \ + varying highp vec2 brushTextureCoords; \ void setPosition(void) { \ gl_Position = pmvMatrix * vertexCoordsArray;\ gl_Position.xy = gl_Position.xy / gl_Position.w; \ @@ -262,16 +262,16 @@ static const char* const qglslAffinePositionWithTextureBrushVertexShader = qglslPositionWithTextureBrushVertexShader; static const char* const qglslTextureBrushSrcFragmentShader = "\ - varying mediump vec2 brushTextureCoords; \ - uniform sampler2D brushTexture; \ + varying highp vec2 brushTextureCoords; \ + uniform lowp sampler2D brushTexture; \ lowp vec4 srcPixel() { \ return texture2D(brushTexture, brushTextureCoords); \ }"; static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\ - varying mediump vec2 brushTextureCoords; \ + varying highp vec2 brushTextureCoords; \ uniform lowp vec4 patternColor; \ - uniform sampler2D brushTexture; \ + uniform lowp sampler2D brushTexture; \ lowp vec4 srcPixel() { \ return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \ }"; @@ -284,15 +284,15 @@ static const char* const qglslSolidBrushSrcFragmentShader = "\ }"; static const char* const qglslImageSrcFragmentShader = "\ - varying mediump vec2 textureCoords; \ - uniform sampler2D imageTexture; \ + varying highp vec2 textureCoords; \ + uniform lowp sampler2D imageTexture; \ lowp vec4 srcPixel() { \ return texture2D(imageTexture, textureCoords); \ }"; static const char* const qglslCustomSrcFragmentShader = "\ varying highp vec2 textureCoords; \ - uniform sampler2D imageTexture; \ + uniform lowp sampler2D imageTexture; \ lowp vec4 customShader(lowp sampler2D texture, highp vec2 coords); \ lowp vec4 srcPixel() { \ return customShader(imageTexture, textureCoords); \ @@ -301,14 +301,14 @@ static const char* const qglslCustomSrcFragmentShader = "\ static const char* const qglslImageSrcWithPatternFragmentShader = "\ varying highp vec2 textureCoords; \ uniform lowp vec4 patternColor; \ - uniform sampler2D imageTexture; \ + uniform lowp sampler2D imageTexture; \ lowp vec4 srcPixel() { \ return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \ }\n"; static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\ varying highp vec2 textureCoords; \ - uniform sampler2D imageTexture; \ + uniform lowp sampler2D imageTexture; \ lowp vec4 srcPixel() { \ lowp vec4 sample = texture2D(imageTexture, textureCoords); \ sample.rgb = sample.rgb * sample.a; \ @@ -383,7 +383,7 @@ static const char* const qglslMainFragmentShader = "\ static const char* const qglslMaskFragmentShader = "\ varying highp vec2 textureCoords;\ - uniform sampler2D maskTexture;\ + uniform lowp sampler2D maskTexture;\ lowp vec4 applyMask(lowp vec4 src) \ {\ lowp vec4 mask = texture2D(maskTexture, textureCoords); \ -- cgit v0.12 From 4337df117dfa429776f2236141b570c4957e4a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 26 Aug 2009 17:07:21 +0200 Subject: Made brush textures in GL2 engine use correct filtering. Only use bilinear filtering when SmoothPixmapTransform render hint is used. Reviewed-by: Kim --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ca33101..95199fa 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -376,6 +376,7 @@ void QGL2PaintEngineExPrivate::useSimpleShader() void QGL2PaintEngineExPrivate::updateBrushTexture() { + Q_Q(QGL2PaintEngineEx); // qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()"); Qt::BrushStyle style = currentBrush->style(); @@ -385,7 +386,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, true); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true); + updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); } else if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) { // Gradiant brush: All the gradiants use the same texture @@ -400,11 +401,11 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() glBindTexture(GL_TEXTURE_2D, texId); if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient) - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true); + updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); else if (g->spread() == QGradient::ReflectSpread) - updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT_IBM, true); + updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT_IBM, q->state()->renderHints & QPainter::SmoothPixmapTransform); else - updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, true); + updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, q->state()->renderHints & QPainter::SmoothPixmapTransform); } else if (style == Qt::TexturePattern) { const QPixmap& texPixmap = currentBrush->texture(); @@ -412,7 +413,7 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); // TODO: Support y-inverted pixmaps as brushes ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, true); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true); + updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); } brushTextureDirty = false; } @@ -1080,6 +1081,7 @@ void QGL2PaintEngineEx::renderHintsChanged() Q_D(QGL2PaintEngineEx); d->lastTexture = GLuint(-1); + d->brushTextureDirty = true; // qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!"); } @@ -1107,7 +1109,7 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel(); - d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, + d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap); } @@ -1124,7 +1126,7 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); GLuint id = texture->id; - d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, + d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, id); d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); } @@ -1139,7 +1141,7 @@ void QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); glBindTexture(GL_TEXTURE_2D, textureId); - d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, + d->updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, state()->renderHints & QPainter::SmoothPixmapTransform, textureId); d->drawTexture(dest, src, size, false); } -- cgit v0.12 From a6f19188282b427272f075063a306c7ef98e8a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Wed, 26 Aug 2009 17:29:28 +0200 Subject: Made GL 2 engine reset various GL state to their defaults in end(). This makes mixing GL and QPainter code safer. We need to be able to assume default GL state in begin(), and set back whatever we change to the default state in end() in the GL 2 paint engine. Reviewed-by: Trond --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 12 +++++++++--- src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 95199fa..2f565cf 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -710,16 +710,20 @@ void QGL2PaintEngineEx::beginNativePainting() #endif d->lastTexture = GLuint(-1); + d->resetGLState(); + d->needsSync = true; +} + +void QGL2PaintEngineExPrivate::resetGLState() +{ glDisable(GL_BLEND); glActiveTexture(GL_TEXTURE0); - glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); glDepthFunc(GL_LESS); glDepthMask(true); glClearDepth(1); - - d->needsSync = true; } void QGL2PaintEngineEx::endNativePainting() @@ -1364,6 +1368,8 @@ bool QGL2PaintEngineEx::end() d->drawable.doneCurrent(); d->ctx->d_ptr->active_engine = 0; + d->resetGLState(); + return false; } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 2eec4d5..66e7a51 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -170,6 +170,7 @@ public: void setBrush(const QBrush* brush); void transferMode(EngineMode newMode); + void resetGLState(); // fill, drawOutline, drawTexture & drawCachedGlyphs are the rendering entry points: void fill(const QVectorPath &path); -- cgit v0.12 From 9385eebd22e005ff6027594ea643a8f46ed2e3e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Wed, 26 Aug 2009 17:33:21 +0200 Subject: Made the opengl/overpainting example work with the GL 2 engine. Since the GL 2 engine can't set/unset every single GL state that a user might possibly change, we have to make a rule that if something is changed from its default state, it needs to be reset before the GL 2 engine can draw correctly. Reviewed-by: Samuel --- doc/src/examples/overpainting.qdoc | 7 ++++--- examples/opengl/overpainting/glwidget.cpp | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/src/examples/overpainting.qdoc b/doc/src/examples/overpainting.qdoc index 91100c0..b19b503 100644 --- a/doc/src/examples/overpainting.qdoc +++ b/doc/src/examples/overpainting.qdoc @@ -159,9 +159,10 @@ \snippet examples/opengl/overpainting/glwidget.cpp 7 - Once the list containing the object has been executed, the matrix stack - needs to be restored to its original state at the start of this function - before we can begin overpainting: + Once the list containing the object has been executed, the GL + states we changed and the matrix stack needs to be restored to its + original state at the start of this function before we can begin + overpainting: \snippet examples/opengl/overpainting/glwidget.cpp 8 diff --git a/examples/opengl/overpainting/glwidget.cpp b/examples/opengl/overpainting/glwidget.cpp index a6e6195..cad591f 100644 --- a/examples/opengl/overpainting/glwidget.cpp +++ b/examples/opengl/overpainting/glwidget.cpp @@ -166,6 +166,11 @@ void GLWidget::paintEvent(QPaintEvent *event) //! [7] //! [8] + glShadeModel(GL_FLAT); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glMatrixMode(GL_MODELVIEW); glPopMatrix(); //! [8] -- cgit v0.12 From 2b7aaf18660fb6639a97b0421563696648384948 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 26 Aug 2009 17:49:25 +0200 Subject: Doc: Corrected incorrect snippets and info in inherits() documentation. Task-number: 201882 Reviewed-by: Trust Me --- doc/src/snippets/code/src_corelib_kernel_qobject.cpp | 6 +++--- src/corelib/kernel/qobject.cpp | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/doc/src/snippets/code/src_corelib_kernel_qobject.cpp b/doc/src/snippets/code/src_corelib_kernel_qobject.cpp index 5c0f80c..a02d4e9 100644 --- a/doc/src/snippets/code/src_corelib_kernel_qobject.cpp +++ b/doc/src/snippets/code/src_corelib_kernel_qobject.cpp @@ -39,10 +39,10 @@ timer->inherits("QTimer"); // returns true timer->inherits("QObject"); // returns true timer->inherits("QAbstractButton"); // returns false -// QLayout inherits QObject and QLayoutItem -QLayout *layout = new QLayout; +// QVBoxLayout inherits QObject and QLayoutItem +QVBoxLayout *layout = new QVBoxLayout; layout->inherits("QObject"); // returns true -layout->inherits("QLayoutItem"); // returns false +layout->inherits("QLayoutItem"); // returns true (even though QLayoutItem is not a QObject) //! [4] diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index ddfc44f..1f35c73 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1089,10 +1089,9 @@ QObjectPrivate::Connection::~Connection() \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 4 - (\l QLayoutItem is not a QObject.) - - Consider using qobject_cast(object) instead. The method - is both faster and safer. + If you need to determine whether an object is an instance of a particular + class for the purpose of casting it, consider using qobject_cast(object) + instead. \sa metaObject(), qobject_cast() */ -- cgit v0.12 From b2835ef710b79e88a1163f653de686a79e810155 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?= Date: Wed, 26 Aug 2009 17:50:58 +0200 Subject: Fixed the bubbles.svg file after fixing some bugs in the SVG renderer. Reviewed-by: Kim --- examples/opengl/framebufferobject/bubbles.svg | 28 +++++++++++++-------------- examples/opengl/pbuffers2/bubbles.svg | 28 +++++++++++++-------------- examples/painting/svgviewer/files/bubbles.svg | 2 +- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/examples/opengl/framebufferobject/bubbles.svg b/examples/opengl/framebufferobject/bubbles.svg index 65867da..5173012 100644 --- a/examples/opengl/framebufferobject/bubbles.svg +++ b/examples/opengl/framebufferobject/bubbles.svg @@ -72,7 +72,7 @@ - + @@ -91,56 +91,56 @@ - - - - - - - - @@ -148,28 +148,28 @@ - - - - @@ -186,7 +186,7 @@ - diff --git a/examples/opengl/pbuffers2/bubbles.svg b/examples/opengl/pbuffers2/bubbles.svg index 65867da..5173012 100644 --- a/examples/opengl/pbuffers2/bubbles.svg +++ b/examples/opengl/pbuffers2/bubbles.svg @@ -72,7 +72,7 @@ - + @@ -91,56 +91,56 @@ - - - - - - - - @@ -148,28 +148,28 @@ - - - - @@ -186,7 +186,7 @@ - diff --git a/examples/painting/svgviewer/files/bubbles.svg b/examples/painting/svgviewer/files/bubbles.svg index 9fae8cc..5173012 100644 --- a/examples/painting/svgviewer/files/bubbles.svg +++ b/examples/painting/svgviewer/files/bubbles.svg @@ -72,7 +72,7 @@ - + -- cgit v0.12 From b920f268e8f03e4857485df9dcdbf001409c8c40 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 26 Aug 2009 14:27:31 +0200 Subject: reverting the definition of WINVER and _WIN32_WINNT in qglobal.h This just caused too much problems and must be solved another way. In qfsfileengine_win.cpp we define FSCTL_GET_REPARSE_POINT and all of the other stuff that's needed for NTFS symlink support, if its not defined. This is the case if _WIN32_WINNT is less than 0x0500. All other changes in this commit are just reversions of commits that were done for the infamous qglobal.h change. Discussed with prasanth, tested by pulse. --- src/corelib/global/qglobal.h | 9 --------- src/corelib/io/qfsfileengine_win.cpp | 3 +++ src/corelib/thread/qthread_win.cpp | 4 ++++ src/gui/util/qsystemtrayicon_win.cpp | 9 +++++---- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index d22a863..93cc30f 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -265,15 +265,6 @@ namespace QT_NAMESPACE {} # define Q_OS_WIN #endif -#if defined(Q_OS_WIN32) -# ifndef WINVER -# define WINVER 0x0500 -# endif -# ifndef _WIN32_WINNT -# define _WIN32_WINNT 0x0500 -# endif -#endif - #if defined(Q_OS_DARWIN) # define Q_OS_MAC /* Q_OS_MAC is mostly for compatibility, but also more clear */ # define Q_OS_MACX /* Q_OS_MACX is only for compatibility.*/ diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index e1fc804..4e142a9 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -123,6 +123,9 @@ typedef struct _REPARSE_DATA_BUFFER { # ifndef IO_REPARSE_TAG_SYMLINK # define IO_REPARSE_TAG_SYMLINK (0xA000000CL) # endif +# ifndef FSCTL_GET_REPARSE_POINT +# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS) +# endif #endif QT_BEGIN_NAMESPACE diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp index 82b462e..12ee413 100644 --- a/src/corelib/thread/qthread_win.cpp +++ b/src/corelib/thread/qthread_win.cpp @@ -39,6 +39,10 @@ ** ****************************************************************************/ +//#define WINVER 0x0500 +#define _WIN32_WINNT 0x0400 + + #include "qthread.h" #include "qthread_p.h" #include "qthreadstorage.h" diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp index 465c1d8..ea7fbde 100644 --- a/src/gui/util/qsystemtrayicon_win.cpp +++ b/src/gui/util/qsystemtrayicon_win.cpp @@ -132,11 +132,12 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *object) : hIcon(0), q(object), ignoreNextMouseRelease(false) { - notifyIconSize = sizeof(NOTIFYICONDATA); -#ifdef Q_OS_WINCE - maxTipLength = 64; -#else +#ifndef Q_OS_WINCE + notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, guidItem); // NOTIFYICONDATAW_V2_SIZE; maxTipLength = 128; +#else + notifyIconSize = FIELD_OFFSET(NOTIFYICONDATA, szTip[64]); // NOTIFYICONDATAW_V1_SIZE; + maxTipLength = 64; #endif // For restoring the tray icon after explorer crashes -- cgit v0.12 From b22e24db7e70a6b85055f4692301ddd523956db5 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Wed, 26 Aug 2009 17:56:41 +0200 Subject: Missing ducumentation in QAbstractItemModel --- src/corelib/kernel/qabstractitemmodel.cpp | 34 +++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index fb0afcc..1c9104a 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -1483,6 +1483,7 @@ QAbstractItemModel::~QAbstractItemModel() /*! \fn void QAbstractItemModel::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) + \since 4.6 This signal is emitted after rows have been moved within the model. The items between \a sourceStart and \a sourceEnd @@ -1498,6 +1499,7 @@ QAbstractItemModel::~QAbstractItemModel() /*! \fn void QAbstractItemModel::rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow) + \since 4.6 This signal is emitted just before rows are moved within the model. The items that will be moved are those between \a sourceStart and \a sourceEnd @@ -1512,6 +1514,38 @@ QAbstractItemModel::~QAbstractItemModel() */ /*! + \fn void QAbstractItemModel::columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) + \since 4.6 + + This signal is emitted after columns have been moved within the + model. The items between \a sourceStart and \a sourceEnd + inclusive, under the given \a sourceParent item have been moved to \a destinationParent + starting at the column \a destinationColumn. + + \bold{Note:} Components connected to this signal use it to adapt to changes + in the model's dimensions. It can only be emitted by the QAbstractItemModel + implementation, and cannot be explicitly emitted in subclass code. + + \sa beginMoveRows() +*/ + +/*! + \fn void QAbstractItemModel::columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn) + \since 4.6 + + This signal is emitted just before columns are moved within the + model. The items that will be moved are those between \a sourceStart and \a sourceEnd + inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent + starting at the column \a destinationColumn. + + \bold{Note:} Components connected to this signal use it to adapt to changes + in the model's dimensions. It can only be emitted by the QAbstractItemModel + implementation, and cannot be explicitly emitted in subclass code. + + \sa beginMoveRows() +*/ + +/*! \fn void QAbstractItemModel::columnsInserted(const QModelIndex &parent, int start, int end) This signal is emitted after columns have been inserted into the model. The -- cgit v0.12 From 5e8b3fc4b913b1a1ac1a97cc633e33f3aa7fbd86 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 26 Aug 2009 08:12:06 -0700 Subject: Use QScopedPointer instead of homegrown smartptr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since QScopedPointer can take a custom cleanup handler we can use this instead of the original QDirectFBPointer. Reviewed-by: Jørgen Lind --- .../gfxdrivers/directfb/qdirectfbpixmap.cpp | 59 +++++++++++----------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 70a6e02..146a920 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -209,66 +209,60 @@ bool QDirectFBPixmapData::fromData(const uchar *buffer, uint len, const char *fo return QPixmapData::fromData(buffer, len, format, flags); } -template class QDirectFBPointer +template struct QDirectFBInterfaceCleanupHandler { -public: - QDirectFBPointer(T *tt = 0) : t(tt) {} - ~QDirectFBPointer() { if (t) t->Release(t); } - - inline T* operator->() { return t; } - inline operator T*() { return t; } - - inline T** operator&() { return &t; } - inline bool operator!() const { return !t; } - inline T *data() { return t; } - inline const T *data() const { return t; } + static void cleanup(T *t) { if (t) t->Release(t); } +}; - T *t; +template +class QDirectFBPointer : public QScopedPointer > +{ +public: + QDirectFBPointer(T *t = 0) + : QScopedPointer >(t) + {} }; bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription) { IDirectFB *dfb = screen->dfb(); Q_ASSERT(dfb); - QDirectFBPointer dataBuffer; DFBResult result = DFB_OK; - if ((result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, &dataBuffer)) != DFB_OK) { + IDirectFBDataBuffer *dataBufferPtr; + if ((result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, &dataBufferPtr)) != DFB_OK) { DirectFBError("QDirectFBPixmapData::fromDataBufferDescription()", result); return false; } + QDirectFBPointer dataBuffer(dataBufferPtr); -#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE - IDirectFBImageProvider *provider = 0; -#else - QDirectFBPointer provider; -#endif - if ((result = dataBuffer->CreateImageProvider(dataBuffer, &provider)) != DFB_OK) { + IDirectFBImageProvider *providerPtr; + if ((result = dataBuffer->CreateImageProvider(dataBuffer.data(), &providerPtr)) != DFB_OK) { DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't create image provider", result); return false; } -#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE - screen->setDirectFBImageProvider(provider); -#endif + QDirectFBPointer provider(providerPtr); + DFBSurfaceDescription surfaceDescription; - if ((result = provider->GetSurfaceDescription(provider, &surfaceDescription)) != DFB_OK) { + if ((result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription)) != DFB_OK) { DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't get surface description", result); return false; } - QDirectFBPointer surfaceFromDescription = screen->createDFBSurface(surfaceDescription, QDirectFBScreen::DontTrackSurface, &result); + QDirectFBPointer surfaceFromDescription; + surfaceFromDescription.reset(screen->createDFBSurface(surfaceDescription, QDirectFBScreen::DontTrackSurface, &result)); if (!surfaceFromDescription) { DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't create surface", result); return false; } - result = provider->RenderTo(provider, surfaceFromDescription, 0); + result = provider->RenderTo(provider.data(), surfaceFromDescription.data(), 0); if (result != DFB_OK) { DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't render to surface", result); return false; } DFBImageDescription imageDescription; - result = provider->GetImageDescription(provider, &imageDescription); + result = provider->GetImageDescription(provider.data(), &imageDescription); if (result != DFB_OK) { DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't get image description", result); return false; @@ -285,7 +279,7 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX; if (imageDescription.caps & DICAPS_COLORKEY) { blittingFlags |= DSBLIT_SRC_COLORKEY; - result = surfaceFromDescription->SetSrcColorKey(surfaceFromDescription, + result = surfaceFromDescription->SetSrcColorKey(surfaceFromDescription.data(), imageDescription.colorkey_r, imageDescription.colorkey_g, imageDescription.colorkey_b); @@ -305,7 +299,7 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti return false; } - result = dfbSurface->Blit(dfbSurface, surfaceFromDescription, 0, 0, 0); + result = dfbSurface->Blit(dfbSurface, surfaceFromDescription.data(), 0, 0, 0); if (result != DFB_OK) { DirectFBError("QDirectFBPixmapData::fromSurfaceDescription: Can't blit to surface", result); invalidate(); // release dfbSurface @@ -324,6 +318,11 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti #if (Q_DIRECTFB_VERSION >= 0x010000) dfbSurface->ReleaseSource(dfbSurface); #endif +#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE + screen->setDirectFBImageProvider(providerPtr); + provider.take(); +#endif + return true; } -- cgit v0.12 From f7709332d5ed16107e1bd8cbf07ab778e8f77217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 26 Aug 2009 18:25:17 +0200 Subject: doc: Add Graphics Effect images. --- doc/src/images/graphicseffect-blur.png | Bin 0 -> 41433 bytes doc/src/images/graphicseffect-colorize.png | Bin 0 -> 35062 bytes doc/src/images/graphicseffect-drop-shadow.png | Bin 0 -> 38770 bytes doc/src/images/graphicseffect-effects.png | Bin 0 -> 112462 bytes doc/src/images/graphicseffect-grayscale.png | Bin 0 -> 35056 bytes doc/src/images/graphicseffect-opacity.png | Bin 0 -> 33879 bytes doc/src/images/graphicseffect-pixelize.png | Bin 0 -> 23577 bytes doc/src/images/graphicseffect-widget.png | Bin 0 -> 16693 bytes src/gui/effects/qgraphicseffect.cpp | 20 +++++++++++++++++--- 9 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 doc/src/images/graphicseffect-blur.png create mode 100644 doc/src/images/graphicseffect-colorize.png create mode 100644 doc/src/images/graphicseffect-drop-shadow.png create mode 100644 doc/src/images/graphicseffect-effects.png create mode 100644 doc/src/images/graphicseffect-grayscale.png create mode 100644 doc/src/images/graphicseffect-opacity.png create mode 100644 doc/src/images/graphicseffect-pixelize.png create mode 100644 doc/src/images/graphicseffect-widget.png diff --git a/doc/src/images/graphicseffect-blur.png b/doc/src/images/graphicseffect-blur.png new file mode 100644 index 0000000..3fa403b Binary files /dev/null and b/doc/src/images/graphicseffect-blur.png differ diff --git a/doc/src/images/graphicseffect-colorize.png b/doc/src/images/graphicseffect-colorize.png new file mode 100644 index 0000000..96fbfe4 Binary files /dev/null and b/doc/src/images/graphicseffect-colorize.png differ diff --git a/doc/src/images/graphicseffect-drop-shadow.png b/doc/src/images/graphicseffect-drop-shadow.png new file mode 100644 index 0000000..c02415a Binary files /dev/null and b/doc/src/images/graphicseffect-drop-shadow.png differ diff --git a/doc/src/images/graphicseffect-effects.png b/doc/src/images/graphicseffect-effects.png new file mode 100644 index 0000000..422ae19 Binary files /dev/null and b/doc/src/images/graphicseffect-effects.png differ diff --git a/doc/src/images/graphicseffect-grayscale.png b/doc/src/images/graphicseffect-grayscale.png new file mode 100644 index 0000000..2bd0c93 Binary files /dev/null and b/doc/src/images/graphicseffect-grayscale.png differ diff --git a/doc/src/images/graphicseffect-opacity.png b/doc/src/images/graphicseffect-opacity.png new file mode 100644 index 0000000..de15859 Binary files /dev/null and b/doc/src/images/graphicseffect-opacity.png differ diff --git a/doc/src/images/graphicseffect-pixelize.png b/doc/src/images/graphicseffect-pixelize.png new file mode 100644 index 0000000..047c452 Binary files /dev/null and b/doc/src/images/graphicseffect-pixelize.png differ diff --git a/doc/src/images/graphicseffect-widget.png b/doc/src/images/graphicseffect-widget.png new file mode 100644 index 0000000..27245d1 Binary files /dev/null and b/doc/src/images/graphicseffect-widget.png differ diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index f620878..5f64698 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -61,15 +61,17 @@ Qt provides the following standard effects: \list - \o QGraphicsGrayscaleEffect - renders the item in shades of gray - \o QGraphicsColorizeEffect - renders the item in shades of any given color - \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size \o QGraphicsBlurEffect - blurs the item by a given radius \o QGraphicsDropShadowEffect - renders a dropshadow behind the item + \o QGraphicsColorizeEffect - renders the item in shades of any given color \o QGraphicsOpacityEffect - renders the item with an opacity + \o QGraphicsPixelizeEffect - pixelizes the item with any pixel size + \o QGraphicsGrayscaleEffect - renders the item in shades of gray \o QGraphicsShaderEffect - renders the item with a pixel shader fragment \endlist + \img graphicseffect-effects.png + \img graphicseffect-widget.png For more information on how to use each effect, refer to the specific effect's documentation. @@ -425,6 +427,8 @@ void QGraphicsEffect::sourceChanged(ChangeFlags flags) A grayscale effect renders the source in shades of gray. + \img graphicseffect-grayscale.png + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ @@ -478,6 +482,8 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so By default, the color is light blue (QColor(0, 0, 192)). + \img graphicseffect-colorize.png + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsOpacityEffect */ @@ -560,6 +566,8 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou By default, the pixel size is 3. + \img graphicseffect-pixelize.png + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ @@ -678,6 +686,8 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou By default, the blur radius is 5 pixels. + \img graphicseffect-blur.png + \sa QGraphicsDropShadowEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ @@ -782,6 +792,8 @@ void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) (QColor(63, 63, 63, 180)) shadow, blurred with a radius of 1 at an offset of 8 pixels towards the lower right. + \img graphicseffect-drop-shadow.png + \sa QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect, QGraphicsOpacityEffect */ @@ -948,6 +960,8 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s By default, the opacity is 0.7. + \img graphicseffect-opacity.png + \sa QGraphicsDropShadowEffect, QGraphicsBlurEffect, QGraphicsPixelizeEffect, QGraphicsGrayscaleEffect, QGraphicsColorizeEffect */ -- cgit v0.12 From a3ceb3627c0270274caa5818d34689b7bd81e2e3 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 26 Aug 2009 16:46:10 +0200 Subject: warn if QScriptValue::setScriptClass() is called on incompatible object --- src/script/api/qscriptvalue.cpp | 7 ++++++- tests/auto/qscriptvalue/tst_qscriptvalue.cpp | 29 ++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 7fd1efe..d5aaed7 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -2421,8 +2421,13 @@ QScriptClass *QScriptValue::scriptClass() const void QScriptValue::setScriptClass(QScriptClass *scriptClass) { Q_D(QScriptValue); - if (!d || !d->isJSC() || !d->jscValue.isObject(&QScriptObject::info)) + if (!d || !d->isObject()) return; + if (!d->jscValue.isObject(&QScriptObject::info)) { + qWarning("QScriptValue::setScriptClass() failed: " + "cannot change class of non-QScriptObject"); + return; + } QScriptObject *scriptObject = static_cast(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) { diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index b125965..f9ce79f 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -2220,13 +2220,30 @@ void tst_QScriptValue::getSetScriptClass() QCOMPARE(inv.scriptClass(), (QScriptClass*)0); QScriptValue num(123); QCOMPARE(num.scriptClass(), (QScriptClass*)0); - QScriptValue obj = eng.newObject(); - QCOMPARE(obj.scriptClass(), (QScriptClass*)0); + TestScriptClass testClass(&eng); - obj.setScriptClass(&testClass); - QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass); - obj.setScriptClass(0); - QCOMPARE(obj.scriptClass(), (QScriptClass*)0); + // object created in C++ (newObject()) + { + QScriptValue obj = eng.newObject(); + QCOMPARE(obj.scriptClass(), (QScriptClass*)0); + obj.setScriptClass(&testClass); + QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass); + obj.setScriptClass(0); + QCOMPARE(obj.scriptClass(), (QScriptClass*)0); + } + // object created in JS + { + QScriptValue obj = eng.evaluate("new Object"); + QVERIFY(!eng.hasUncaughtException()); + QVERIFY(obj.isObject()); + QCOMPARE(obj.scriptClass(), (QScriptClass*)0); + QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setScriptClass() failed: cannot change class of non-QScriptObject"); + obj.setScriptClass(&testClass); + QEXPECT_FAIL("", "With JSC back-end, the class of a plain object created in JS can't be changed", Continue); + QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass); + obj.setScriptClass(0); + QCOMPARE(obj.scriptClass(), (QScriptClass*)0); + } } static QScriptValue getArg(QScriptContext *ctx, QScriptEngine *) -- cgit v0.12 From ea3955ca80ab6e067c58aa9def4055a53020cd90 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 26 Aug 2009 16:49:54 +0200 Subject: make JIT construct objects of type QScriptObject, not JSC::JSObject Commit 25e76959da84fe4c40f98cf32b7b8c69e5087681 changed it for the interpreter, this commit makes it work with the JIT enabled as well. --- src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp b/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp index 40d2182..2563848 100644 --- a/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp +++ b/src/3rdparty/webkit/JavaScriptCore/jit/JITStubs.cpp @@ -58,6 +58,10 @@ #include "SamplingTool.h" #include +#ifdef QT_BUILD_SCRIPT_LIB +#include "bridge/qscriptobject_p.h" +#endif + using namespace std; namespace JSC { @@ -1470,7 +1474,11 @@ DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct) structure = asObject(stackFrame.args[3].jsValue())->inheritorID(); else structure = constructor->scope().node()->globalObject()->emptyObjectStructure(); +#ifdef QT_BUILD_SCRIPT_LIB + return new (stackFrame.globalData) QScriptObject(structure); +#else return new (stackFrame.globalData) JSObject(structure); +#endif } DEFINE_STUB_FUNCTION(EncodedJSValue, op_construct_NotJSConstruct) -- cgit v0.12 From 52f5e632da1bd5ef413b3108564b9b47850ce441 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 26 Aug 2009 19:03:21 +0200 Subject: ignore warning in autotest --- tests/auto/qscriptclass/tst_qscriptclass.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/auto/qscriptclass/tst_qscriptclass.cpp b/tests/auto/qscriptclass/tst_qscriptclass.cpp index 11c7f56..33c2c35 100644 --- a/tests/auto/qscriptclass/tst_qscriptclass.cpp +++ b/tests/auto/qscriptclass/tst_qscriptclass.cpp @@ -606,6 +606,7 @@ void tst_QScriptClass::newInstance() QScriptValue arr = eng.newArray(); QVERIFY(arr.isArray()); QCOMPARE(arr.scriptClass(), (QScriptClass*)0); + QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setScriptClass() failed: cannot change class of non-QScriptObject"); arr.setScriptClass(&cls); QEXPECT_FAIL("", "Changing class of arbitrary script object is not allowed (it's OK)", Continue); QCOMPARE(arr.scriptClass(), (QScriptClass*)&cls); -- cgit v0.12 From bf6a3925109ea55b57633d02fc752344d55a9fae Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 26 Aug 2009 00:12:25 -0700 Subject: Implement QDirectFBScreen::surfaceForWidget Allow applications to get a pointer to the surface of the window surface for a given widget or a subsurface of the widget. This function ignores whether or not the widget is fully or partially obscured. Reviewed-by: Donald Carr --- .../gfxdrivers/directfb/qdirectfbscreen.cpp | 31 ++++++++++++++++++++++ src/plugins/gfxdrivers/directfb/qdirectfbscreen.h | 3 +++ .../gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 21 +++++++++++++++ .../gfxdrivers/directfb/qdirectfbwindowsurface.h | 1 + 4 files changed, 56 insertions(+) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index dbe8926..1bf74d4 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -1557,5 +1557,36 @@ void QDirectFBScreen::setDirectFBImageProvider(IDirectFBImageProvider *provider) } #endif +IDirectFBSurface * QDirectFBScreen::surfaceForWidget(const QWidget *widget, QRect *rect) const +{ + Q_ASSERT(widget); + if (!widget->isVisible() || widget->size().isNull()) + return 0; + + const QWSWindowSurface *surface = static_cast(widget->windowSurface()); + if (surface && surface->key() == QLatin1String("directfb")) { + return static_cast(surface)->surfaceForWidget(widget, rect); + } + return 0; +} +IDirectFBSurface *QDirectFBScreen::subSurfaceForWidget(const QWidget *widget, const QRect &area) const +{ + Q_ASSERT(widget); + QRect rect; + IDirectFBSurface *surface = surfaceForWidget(widget, &rect); + IDirectFBSurface *subSurface = 0; + if (surface) { + if (!area.isNull()) + rect &= area.translated(widget->mapTo(widget->window(), QPoint(0, 0))); + if (!rect.isNull()) { + const DFBRectangle subRect = {rect.x(), rect.y(), rect.width(), rect.height() }; + const DFBResult result = surface->GetSubSurface(surface, &subRect, &subSurface); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreen::subSurface(): Can't get sub surface", result); + } + } + } + return subSurface; +} diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 8ec91c7..8af4e0f 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -152,6 +152,9 @@ public: return static_cast(inst); } + IDirectFBSurface *surfaceForWidget(const QWidget *widget, QRect *rect) const; + IDirectFBSurface *subSurfaceForWidget(const QWidget *widget, const QRect &area = QRect()) const; + IDirectFB *dfb(); #ifdef QT_NO_DIRECTFB_WM IDirectFBSurface *primarySurface(); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 2f240fb..aa98a13 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -466,6 +466,27 @@ QImage *QDirectFBWindowSurface::buffer(const QWidget *widget) return img; } +IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget, QRect *rect) const +{ + Q_ASSERT(widget); + if (!dfbSurface) { + if (sibling && (!sibling->sibling || sibling->dfbSurface)) + return sibling->surfaceForWidget(widget, rect); + return 0; + } + QWidget *win = window(); + Q_ASSERT(win); + if (rect) { + if (win == widget) { + *rect = widget->rect(); + } else { + *rect = QRect(widget->mapTo(win, QPoint(0, 0)), widget->size()); + } + } + Q_ASSERT(win == widget || widget->isAncestorOf(win)); + return dfbSurface; +} + void QDirectFBWindowSurface::updateFormat() { imageFormat = dfbSurface ? QDirectFBScreen::getImageFormat(dfbSurface) : QImage::Format_Invalid; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 0da3a98..707561b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -89,6 +89,7 @@ public: void endPaint(const QRegion &); QImage *buffer(const QWidget *widget); + IDirectFBSurface *surfaceForWidget(const QWidget *widget, QRect *rect) const; private: void updateFormat(); #ifdef QT_DIRECTFB_WM -- cgit v0.12 From 900c3368404f418c444a9781ed52f7b681ab7076 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 26 Aug 2009 12:19:04 -0700 Subject: Remove bufferImage stuff from dfbwindowsurface Neither grabWidget nor buffer is ever called from Qt and they're not public API Reviewed-by: Donald Carr --- .../gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 39 ---------------------- .../gfxdrivers/directfb/qdirectfbwindowsurface.h | 2 -- 2 files changed, 41 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index aa98a13..60211a6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -48,8 +48,6 @@ #include #include -//#define QT_DIRECTFB_DEBUG_SURFACES 1 - QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) : QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM @@ -418,7 +416,6 @@ void QDirectFBWindowSurface::flush(QWidget *, const QRegion ®ion, #endif } - void QDirectFBWindowSurface::beginPaint(const QRegion &) { if (!engine) @@ -427,45 +424,9 @@ void QDirectFBWindowSurface::beginPaint(const QRegion &) void QDirectFBWindowSurface::endPaint(const QRegion &) { -#ifdef QT_DIRECTFB_DEBUG_SURFACES - if (bufferImages.count()) { - qDebug("QDirectFBWindowSurface::endPaint() this=%p", this); - - foreach(QImage* bufferImg, bufferImages) - qDebug(" Deleting buffer image %p", bufferImg); - } -#endif - - qDeleteAll(bufferImages); - bufferImages.clear(); unlockDirectFB(); } - -QImage *QDirectFBWindowSurface::buffer(const QWidget *widget) -{ - if (!lockedImage) - return 0; - - const QRect rect = QRect(offset(widget), widget->size()) - & lockedImage->rect(); - if (rect.isEmpty()) - return 0; - - QImage *img = new QImage(lockedImage->scanLine(rect.y()) - + rect.x() * (lockedImage->depth() / 8), - rect.width(), rect.height(), - lockedImage->bytesPerLine(), - lockedImage->format()); - bufferImages.append(img); - -#ifdef QT_DIRECTFB_DEBUG_SURFACES - qDebug("QDirectFBWindowSurface::buffer() Created & returned %p", img); -#endif - - return img; -} - IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget, QRect *rect) const { Q_ASSERT(widget); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 707561b..dafc478 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -88,7 +88,6 @@ public: void beginPaint(const QRegion &); void endPaint(const QRegion &); - QImage *buffer(const QWidget *widget); IDirectFBSurface *surfaceForWidget(const QWidget *widget, QRect *rect) const; private: void updateFormat(); @@ -105,7 +104,6 @@ private: } mode; #endif - QList bufferImages; DFBSurfaceFlipFlags flipFlags; bool boundingRectFlip; #ifdef QT_DIRECTFB_TIMING -- cgit v0.12 From e201ff0ff3a8223b14a72954c898674e606f147e Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 26 Aug 2009 12:50:28 -0700 Subject: Optimize permanentState/setPermanentState No need to use a QDataStream here. Reviewed-by: Donald Carr --- .../gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 60211a6..9de1ca5 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -243,22 +243,19 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) QByteArray QDirectFBWindowSurface::permanentState() const { - QByteArray state; #ifdef QT_DIRECTFB_WM - QDataStream ds(&state, QIODevice::WriteOnly); - ds << reinterpret_cast(this); -#endif + QByteArray state(sizeof(this), 0); + *reinterpret_cast(state.data()) = this; return state; +#endif + return QByteArray(); } void QDirectFBWindowSurface::setPermanentState(const QByteArray &state) { #ifdef QT_DIRECTFB_WM - if (state.size() == sizeof(quintptr)) { - QDataStream ds(state); - quintptr ptr; - ds >> ptr; - sibling = reinterpret_cast(ptr); + if (state.size() == sizeof(this)) { + sibling = *reinterpret_cast(state.constData()); } #else Q_UNUSED(state); -- cgit v0.12 From 40856f6e2e3b5115e8730ea86c97ed7211d4e5a3 Mon Sep 17 00:00:00 2001 From: Bill King Date: Thu, 27 Aug 2009 10:31:37 +1000 Subject: Fixes invalid use of statics Multiple database connections could have differing ideas on the return value for defaultCase. The cost of the call is so minimal that caching is unnecessary, and static caching is very very wrong. Reviewed-by: Justin McPherson --- src/sql/drivers/odbc/qsql_odbc.cpp | 54 ++++++++++++++------------------ tests/auto/qsqldriver/tst_qsqldriver.cpp | 14 ++++++--- 2 files changed, 33 insertions(+), 35 deletions(-) diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 6a8609e..06ee3e1 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -743,37 +743,31 @@ void QODBCDriverPrivate::splitTableQualifier(const QString & qualifier, QString QODBCDriverPrivate::DefaultCase QODBCDriverPrivate::defaultCase() const { - static bool isInitialized = false; - static DefaultCase ret; - - if (!isInitialized) { - SQLUSMALLINT casing; - int r = SQLGetInfo(hDbc, - SQL_IDENTIFIER_CASE, - &casing, - sizeof(casing), - NULL); - if ( r != SQL_SUCCESS) - ret = Lower;//arbitrary case if driver cannot be queried - else { - switch (casing) { - case (SQL_IC_UPPER): - ret = Upper; - break; - case (SQL_IC_LOWER): - ret = Lower; - break; - case (SQL_IC_SENSITIVE): - ret = Sensitive; - break; - case (SQL_IC_MIXED): - ret = Mixed; - break; - default: - ret = Upper; - } + DefaultCase ret; + SQLUSMALLINT casing; + int r = SQLGetInfo(hDbc, + SQL_IDENTIFIER_CASE, + &casing, + sizeof(casing), + NULL); + if ( r != SQL_SUCCESS) + ret = Mixed;//arbitrary case if driver cannot be queried + else { + switch (casing) { + case (SQL_IC_UPPER): + ret = Upper; + break; + case (SQL_IC_LOWER): + ret = Lower; + break; + case (SQL_IC_SENSITIVE): + ret = Sensitive; + break; + case (SQL_IC_MIXED): + default: + ret = Mixed; + break; } - isInitialized = true; } return ret; } diff --git a/tests/auto/qsqldriver/tst_qsqldriver.cpp b/tests/auto/qsqldriver/tst_qsqldriver.cpp index 5af56c7..4857295 100644 --- a/tests/auto/qsqldriver/tst_qsqldriver.cpp +++ b/tests/auto/qsqldriver/tst_qsqldriver.cpp @@ -144,9 +144,11 @@ void tst_QSqlDriver::record() else if (db.driverName().startsWith("QPSQL")) tablename = tablename.toLower(); - //check we can get records using a properly quoted table name - rec = db.driver()->record(db.driver()->escapeIdentifier(tablename,QSqlDriver::TableName)); - QCOMPARE(rec.count(), 4); + if(!db.driverName().startsWith("QODBC") && !db.databaseName().contains("PostgreSql")) { + //check we can get records using a properly quoted table name + rec = db.driver()->record(db.driver()->escapeIdentifier(tablename,QSqlDriver::TableName)); + QCOMPARE(rec.count(), 4); + } for (int i = 0; i < fields.count(); ++i) QCOMPARE(rec.fieldName(i), fields[i]); @@ -188,8 +190,10 @@ void tst_QSqlDriver::primaryIndex() else if (db.driverName().startsWith("QPSQL")) tablename = tablename.toLower(); - index = db.driver()->primaryIndex(db.driver()->escapeIdentifier(tablename, QSqlDriver::TableName)); - QCOMPARE(index.count(), 1); + if(!db.driverName().startsWith("QODBC") && !db.databaseName().contains("PostgreSql")) { + index = db.driver()->primaryIndex(db.driver()->escapeIdentifier(tablename, QSqlDriver::TableName)); + QCOMPARE(index.count(), 1); + } if( db.driverName().startsWith("QIBASE") || db.driverName().startsWith("QOCI") || db.driverName().startsWith("QDB2")) QCOMPARE(index.fieldName(0), QString::fromLatin1("ID")); else -- cgit v0.12 From 741bbc1be204adb4ceb6f9ae2aa35772c63d989c Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Thu, 27 Aug 2009 10:54:14 +1000 Subject: API improvements for creating shaders from files It used to be possible to derive the shader type from the file extension, but this isn't very extensible and doesn't capture the usual extensions. Change it so that the shader type must be supplied explicitly. Also add the addShaderFromFile() function to QGLShaderProgram to provide a convenient short-cut for file-based shader creation. Reviewed-by: Sarah Smith --- src/opengl/qglshaderprogram.cpp | 77 +++++++++++++++-------------------------- src/opengl/qglshaderprogram.h | 3 +- 2 files changed, 28 insertions(+), 52 deletions(-) diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index f8bffd3..83578b3 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -348,31 +348,6 @@ QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent) } /*! - Constructs a new QGLShader object from the source code in \a fileName - and attaches it to \a parent. If the filename ends in \c{.fsh}, - it is assumed to be a fragment shader, otherwise it is assumed to - be a vertex shader (normally the extension is \c{.vsh} for vertex shaders). - If the shader could not be loaded, then isCompiled() will return false. - - The shader will be associated with the current QGLContext. - - \sa isCompiled() -*/ -QGLShader::QGLShader(const QString& fileName, QObject *parent) - : QObject(parent) -{ - if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive)) - d = new QGLShaderPrivate(QGLShader::FragmentShader, QGLContext::currentContext()); - else - d = new QGLShaderPrivate(QGLShader::VertexShader, QGLContext::currentContext()); - if (d->create() && !compileFile(fileName)) { - if (d->shader) - glDeleteShader(d->shader); - d->shader = 0; - } -} - -/*! Constructs a new QGLShader object of the specified \a type from the source code in \a fileName and attaches it to \a parent. If the shader could not be loaded, then isCompiled() will return false. @@ -413,31 +388,6 @@ QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObj } /*! - Constructs a new QGLShader object from the source code in \a fileName - and attaches it to \a parent. If the filename ends in \c{.fsh}, - it is assumed to be a fragment shader, otherwise it is assumed to - be a vertex shader (normally the extension is \c{.vsh} for vertex shaders). - If the shader could not be loaded, then isCompiled() will return false. - - The shader will be associated with \a context. - - \sa isCompiled() -*/ -QGLShader::QGLShader(const QString& fileName, const QGLContext *context, QObject *parent) - : QObject(parent) -{ - if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive)) - d = new QGLShaderPrivate(QGLShader::FragmentShader, context); - else - d = new QGLShaderPrivate(QGLShader::VertexShader, context); - if (d->create() && !compileFile(fileName)) { - if (d->shader) - glDeleteShader(d->shader); - d->shader = 0; - } -} - -/*! Constructs a new QGLShader object of the specified \a type from the source code in \a fileName and attaches it to \a parent. If the shader could not be loaded, then isCompiled() will return false. @@ -917,6 +867,33 @@ bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QString& sour } /*! + Compiles the contents of \a fileName as a shader of the specified + \a type and adds it to this shader program. Returns true if + compilation was successful, false otherwise. The compilation errors + and warnings will be made available via log(). + + This function is intended to be a short-cut for quickly + adding vertex and fragment shaders to a shader program without + creating an instance of QGLShader first. + + \sa addShader() +*/ +bool QGLShaderProgram::addShaderFromFile + (QGLShader::ShaderType type, const QString& fileName) +{ + if (!init()) + return false; + QGLShader *shader = new QGLShader(type, this); + if (!shader->compileFile(fileName)) { + d->log = shader->log(); + delete shader; + return false; + } + d->anonShaders.append(shader); + return addShader(shader); +} + +/*! Removes \a shader from this shader program. The object is not deleted. \sa addShader(), link(), removeAllShaders() diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h index c5295eb..5499f8a 100644 --- a/src/opengl/qglshaderprogram.h +++ b/src/opengl/qglshaderprogram.h @@ -72,10 +72,8 @@ public: }; explicit QGLShader(QGLShader::ShaderType type, QObject *parent = 0); - explicit QGLShader(const QString& fileName, QObject *parent = 0); QGLShader(const QString& fileName, QGLShader::ShaderType type, QObject *parent = 0); QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0); - QGLShader(const QString& fileName, const QGLContext *context, QObject *parent = 0); QGLShader(const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0); virtual ~QGLShader(); @@ -123,6 +121,7 @@ public: bool addShader(QGLShader::ShaderType type, const char *source); bool addShader(QGLShader::ShaderType type, const QByteArray& source); bool addShader(QGLShader::ShaderType type, const QString& source); + bool addShaderFromFile(QGLShader::ShaderType type, const QString& fileName); void removeAllShaders(); -- cgit v0.12 From c52061e7980fcde5d59a7657a254ce00d117b611 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Wed, 26 Aug 2009 08:54:04 +0200 Subject: Make QGLShader::ShaderType slightly more future proof by making it into a bitmask. I'll add GeometryShader in the future Reviewed-by: Rhys Weatherley --- src/opengl/qglshaderprogram.cpp | 9 ++++++--- src/opengl/qglshaderprogram.h | 17 ++++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 83578b3..8ce50cf 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -104,7 +104,7 @@ QT_BEGIN_NAMESPACE on desktop systems. The programmer should restrict themselves to just features that are present in GLSL/ES, and avoid standard variable names that only work on the desktop. - + \section1 Simple shader example \code @@ -199,8 +199,11 @@ QT_BEGIN_NAMESPACE \value VertexShader Vertex shader written in the OpenGL Shading Language (GLSL). \value FragmentShader Fragment shader written in the OpenGL Shading Language (GLSL). + \value PartialVertexShader Partial vertex shader that will be concatenated with all other partial vertex shaders at link time. \value PartialFragmentShader Partial fragment shader that will be concatenated with all other partial fragment shaders at link time. + + \omitvalue PartialShader */ #ifndef GL_FRAGMENT_SHADER @@ -251,8 +254,7 @@ public: , shader(0) , shaderType(type) , compiled(false) - , isPartial(type == QGLShader::PartialVertexShader || - type == QGLShader::PartialFragmentShader) + , isPartial((type & QGLShader::PartialShader) != 0) , hasPartialSource(false) { } @@ -2960,6 +2962,7 @@ bool QGLShaderProgram::hasShaderPrograms(const QGLContext *context) #endif } + #endif QT_END_NAMESPACE diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h index 5499f8a..4f95ef3 100644 --- a/src/opengl/qglshaderprogram.h +++ b/src/opengl/qglshaderprogram.h @@ -63,13 +63,17 @@ class Q_OPENGL_EXPORT QGLShader : public QObject { Q_OBJECT public: - enum ShaderType + enum ShaderTypeBits { - VertexShader, - FragmentShader, - PartialVertexShader, - PartialFragmentShader + VertexShader = 0x0001, + FragmentShader = 0x0002, + + PartialShader = 0x1000, + + PartialVertexShader = PartialShader | VertexShader, + PartialFragmentShader = PartialShader | FragmentShader }; + Q_DECLARE_FLAGS(ShaderType, ShaderTypeBits); explicit QGLShader(QGLShader::ShaderType type, QObject *parent = 0); QGLShader(const QString& fileName, QGLShader::ShaderType type, QObject *parent = 0); @@ -104,6 +108,9 @@ private: Q_DISABLE_COPY(QGLShader) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QGLShader::ShaderType); + + class QGLShaderProgramPrivate; class Q_OPENGL_EXPORT QGLShaderProgram : public QObject -- cgit v0.12