diff options
79 files changed, 2550 insertions, 474 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/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/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. */ diff --git a/doc/src/images/graphicseffect-blur.png b/doc/src/images/graphicseffect-blur.png Binary files differnew file mode 100644 index 0000000..3fa403b --- /dev/null +++ b/doc/src/images/graphicseffect-blur.png diff --git a/doc/src/images/graphicseffect-colorize.png b/doc/src/images/graphicseffect-colorize.png Binary files differnew file mode 100644 index 0000000..96fbfe4 --- /dev/null +++ b/doc/src/images/graphicseffect-colorize.png diff --git a/doc/src/images/graphicseffect-drop-shadow.png b/doc/src/images/graphicseffect-drop-shadow.png Binary files differnew file mode 100644 index 0000000..c02415a --- /dev/null +++ b/doc/src/images/graphicseffect-drop-shadow.png diff --git a/doc/src/images/graphicseffect-effects.png b/doc/src/images/graphicseffect-effects.png Binary files differnew file mode 100644 index 0000000..422ae19 --- /dev/null +++ b/doc/src/images/graphicseffect-effects.png diff --git a/doc/src/images/graphicseffect-grayscale.png b/doc/src/images/graphicseffect-grayscale.png Binary files differnew file mode 100644 index 0000000..2bd0c93 --- /dev/null +++ b/doc/src/images/graphicseffect-grayscale.png diff --git a/doc/src/images/graphicseffect-opacity.png b/doc/src/images/graphicseffect-opacity.png Binary files differnew file mode 100644 index 0000000..de15859 --- /dev/null +++ b/doc/src/images/graphicseffect-opacity.png diff --git a/doc/src/images/graphicseffect-pixelize.png b/doc/src/images/graphicseffect-pixelize.png Binary files differnew file mode 100644 index 0000000..047c452 --- /dev/null +++ b/doc/src/images/graphicseffect-pixelize.png diff --git a/doc/src/images/graphicseffect-widget.png b/doc/src/images/graphicseffect-widget.png Binary files differnew file mode 100644 index 0000000..27245d1 --- /dev/null +++ b/doc/src/images/graphicseffect-widget.png 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/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/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 @@ <radialGradient id="shadowGrad" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="100" fx="-50" fy="50"> <stop offset="0%" stop-color="black" stop-opacity="1.0" /> - <stop offset="100%" stop-color="white" stop-opacity="0.0" /> + <stop offset="100%" stop-color="black" stop-opacity="0.0" /> </radialGradient> <!-- Define a shadow for each sphere. --> @@ -91,56 +91,56 @@ <g transform="translate(200,700)"> <use xlink:href="#bubble" fill="url(#blueBubble)" /> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="1s" dur="10s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(315,700)"> <g transform="scale(0.5,0.5)"> <use xlink:href="#bubble" fill="url(#redBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="3s" dur="7s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(80,700)"> <g transform="scale(0.65,0.65)"> <use xlink:href="#bubble" fill="url(#greenBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="5s" dur="9s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(255,700)"> <g transform="scale(0.3,0.3)"> <use xlink:href="#bubble" fill="url(#yellowBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="2s" dur="6s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(565,700)"> <g transform="scale(0.4,0.4)"> <use xlink:href="#bubble" fill="url(#blueBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="4s" dur="8s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(715,700)"> <g transform="scale(0.6,0.6)"> <use xlink:href="#bubble" fill="url(#redBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="1s" dur="4s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(645,700)"> <g transform="scale(0.375,0.375)"> <use xlink:href="#bubble" fill="url(#greenBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="0s" dur="11s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(555,700)"> <g transform="scale(0.9,0.9)"> <use xlink:href="#bubble" fill="url(#yellowBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="3s" dur="7.5s" fill="freeze" repeatCount="indefinite" /> </g> @@ -148,28 +148,28 @@ <g transform="scale(0.5,0.5)"> <use xlink:href="#bubble" fill="url(#blueBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="3s" dur="6s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(215,700)"> <g transform="scale(0.45,0.45)"> <use xlink:href="#bubble" fill="url(#redBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="5.5s" dur="7s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(420,700)"> <g transform="scale(0.75,0.75)"> <use xlink:href="#bubble" fill="url(#greenBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="1s" dur="9s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(815,700)"> <g transform="scale(0.6,0.6)"> <use xlink:href="#bubble" fill="url(#yellowBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="2s" dur="9.5s" fill="freeze" repeatCount="indefinite" /> </g> @@ -186,7 +186,7 @@ <circle fill="#a6ce39" cx="0" cy="0" r="33" /> <path fill="black" d="M 37,50 L 50,37 L 12,-1 L 22,-11 L 10,-24 L -24,10 L -11,22 L -1,12 Z" /> - <animateTransform attributeName="transform" type="rotate" values="0; 360" + <animateTransform attributeName="transform" type="rotate" additive="sum" values="0; 360" begin="0s" dur="10s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(200,375)"> 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/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] 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 @@ <radialGradient id="shadowGrad" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="100" fx="-50" fy="50"> <stop offset="0%" stop-color="black" stop-opacity="1.0" /> - <stop offset="100%" stop-color="white" stop-opacity="0.0" /> + <stop offset="100%" stop-color="black" stop-opacity="0.0" /> </radialGradient> <!-- Define a shadow for each sphere. --> @@ -91,56 +91,56 @@ <g transform="translate(200,700)"> <use xlink:href="#bubble" fill="url(#blueBubble)" /> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="1s" dur="10s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(315,700)"> <g transform="scale(0.5,0.5)"> <use xlink:href="#bubble" fill="url(#redBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="3s" dur="7s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(80,700)"> <g transform="scale(0.65,0.65)"> <use xlink:href="#bubble" fill="url(#greenBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="5s" dur="9s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(255,700)"> <g transform="scale(0.3,0.3)"> <use xlink:href="#bubble" fill="url(#yellowBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="2s" dur="6s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(565,700)"> <g transform="scale(0.4,0.4)"> <use xlink:href="#bubble" fill="url(#blueBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="4s" dur="8s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(715,700)"> <g transform="scale(0.6,0.6)"> <use xlink:href="#bubble" fill="url(#redBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="1s" dur="4s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(645,700)"> <g transform="scale(0.375,0.375)"> <use xlink:href="#bubble" fill="url(#greenBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="0s" dur="11s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(555,700)"> <g transform="scale(0.9,0.9)"> <use xlink:href="#bubble" fill="url(#yellowBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="3s" dur="7.5s" fill="freeze" repeatCount="indefinite" /> </g> @@ -148,28 +148,28 @@ <g transform="scale(0.5,0.5)"> <use xlink:href="#bubble" fill="url(#blueBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="3s" dur="6s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(215,700)"> <g transform="scale(0.45,0.45)"> <use xlink:href="#bubble" fill="url(#redBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="5.5s" dur="7s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(420,700)"> <g transform="scale(0.75,0.75)"> <use xlink:href="#bubble" fill="url(#greenBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="1s" dur="9s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(815,700)"> <g transform="scale(0.6,0.6)"> <use xlink:href="#bubble" fill="url(#yellowBubble)" /> </g> - <animateTransform attributeName="transform" type="translate" + <animateTransform attributeName="transform" type="translate" additive="sum" values="0,0; 0,-800" begin="2s" dur="9.5s" fill="freeze" repeatCount="indefinite" /> </g> @@ -186,7 +186,7 @@ <circle fill="#a6ce39" cx="0" cy="0" r="33" /> <path fill="black" d="M 37,50 L 50,37 L 12,-1 L 22,-11 L 10,-24 L -24,10 L -11,22 L -1,12 Z" /> - <animateTransform attributeName="transform" type="rotate" values="0; 360" + <animateTransform attributeName="transform" type="rotate" additive="sum" values="0; 360" begin="0s" dur="10s" fill="freeze" repeatCount="indefinite" /> </g> <g transform="translate(200,375)"> 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/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 @@ <radialGradient id="shadowGrad" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="100" fx="-50" fy="50"> <stop offset="0%" stop-color="black" stop-opacity="1.0" /> - <stop offset="100%" stop-color="white" stop-opacity="0.0" /> + <stop offset="100%" stop-color="black" stop-opacity="0.0" /> </radialGradient> <!-- Define a shadow for each sphere. --> 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 <http://www.gnu.org/licenses/>. #include <QtCore/QTime> #include <QtCore/QLibrary> -#ifndef Q_CC_MSVC #include <dshow.h> -#endif //Q_CC_MSVC #include <objbase.h> #include <initguid.h> #include <qnetwork.h> 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(); } 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 <stdio.h> +#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) 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/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 <windows.h> #ifdef _WIN32_WCE 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/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. diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 3b7059b..1c9104a 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<QPersistentModelIndexData *> persistent_moved_explicitly; + QVector<QPersistentModelIndexData *> persistent_moved_in_source; + QVector<QPersistentModelIndexData *> persistent_moved_in_destination; + + QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it; + const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator begin = persistent.indexes.constBegin(); + const QHash<QModelIndex, QPersistentModelIndexData *>::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<QPersistentModelIndexData *> indexes, int change, const QModelIndex &parent, Qt::Orientation orientation) +{ + QVector<QPersistentModelIndexData *>::const_iterator it; + const QVector<QPersistentModelIndexData *>::const_iterator begin = indexes.constBegin(); + const QVector<QPersistentModelIndexData *>::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<QPersistentModelIndexData *> moved_in_destination = persistent.moved.pop(); + QVector<QPersistentModelIndexData *> moved_in_source = persistent.moved.pop(); + QVector<QPersistentModelIndexData *> 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,70 @@ 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 + 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) + \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 + 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::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 @@ -2284,6 +2460,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 +2692,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<QPersistentModelIndexData *> 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<Change> changes; 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<Type *>(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<Type *>(object) + instead. \sa metaObject(), qobject_cast() */ 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/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 9ed01df..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 QGrahicsShaderEffect - renders the item with a pixel shader fragment + \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. @@ -108,7 +110,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 +121,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 +176,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 +208,6 @@ const QStyleOption *QGraphicsEffectSource::styleOption() const \sa QGraphicsEffect::draw() */ - void QGraphicsEffectSource::draw(QPainter *painter) { d_func()->draw(painter); @@ -312,8 +320,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 +343,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() */ @@ -420,18 +427,31 @@ 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 */ + +/*! + 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 +474,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 @@ -462,34 +482,40 @@ 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 */ + +/*! + 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 +530,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 +557,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 @@ -536,22 +566,36 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou By default, the pixel size is 3. + \img graphicseffect-pixelize.png + \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. + + 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. - \sa setPixelSize(), pixelSizeChanged() + By default, the pixel size is 3. */ int QGraphicsPixelizeEffect::pixelSize() const { @@ -559,14 +603,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 +617,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 +641,9 @@ static inline void pixelize(QImage *image, int pixelSize) } } +/*! + \reimp +*/ void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsPixelizeEffect); @@ -636,7 +676,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, @@ -646,22 +686,36 @@ 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 */ + +/*! + 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. - \sa setBlurRadius(), blurRadiusChanged() + Using a smaller radius results in a sharper appearance, whereas a bigger + radius results in a more blurred appearance. + + By default, the blur radius is 5 pixels. */ int QGraphicsBlurEffect::blurRadius() const { @@ -669,14 +723,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 +738,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); @@ -739,22 +792,35 @@ 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 */ + +/*! + 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. + + By default, the offset is 8 pixels towards the lower right. - \sa setOffset(), blurRadius(), color(), offsetChanged() + \sa blurRadius(), color() */ QPointF QGraphicsDropShadowEffect::offset() const { @@ -762,11 +828,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 +843,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 +863,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 +878,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 +896,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 +910,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); @@ -894,22 +960,36 @@ void QGraphicsDropShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *s By default, the opacity is 0.7. + \img graphicseffect-opacity.png + \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 +997,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 +1013,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/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(); } 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/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<QAction*> &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/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); 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/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(); 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 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<QToolBarItem*> items; 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..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,16 +284,16 @@ 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; \ - lowp vec4 customShader(sampler2D texture, vec2 coords); \ + 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); \ diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index fb0cd99..cc9b014 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, QGLContext::InternalBindOption); - 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,18 +401,18 @@ 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(); glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); - updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true); + updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform); } brushTextureDirty = false; } @@ -674,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(); @@ -708,15 +709,25 @@ void QGL2PaintEngineEx::sync() #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); +} +void QGL2PaintEngineEx::endNativePainting() +{ + Q_D(QGL2PaintEngineEx); d->needsSync = true; } @@ -1073,6 +1084,7 @@ void QGL2PaintEngineEx::renderHintsChanged() Q_D(QGL2PaintEngineEx); d->lastTexture = GLuint(-1); + d->brushTextureDirty = true; // qDebug("QGL2PaintEngineEx::renderHintsChanged() not implemented!"); } @@ -1101,7 +1113,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); } @@ -1115,11 +1127,10 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true, - QGLContext::InternalBindOption); + QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, QGLContext::InternalBindOption); 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()); } @@ -1134,7 +1145,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); } @@ -1357,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 7b734e3..66e7a51 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<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state()); } - virtual void sync(); + + void beginNativePainting(); + void endNativePainting(); const QGLContext* context(); @@ -168,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); diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 9ea602d..0913606 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<QGL2PaintEngineEx *>(painter->paintEngine()); - engine->syncState(); painter->save(); // ensure GL_LINEAR filtering is used @@ -418,7 +417,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<qreal> sampleOffsets; QVector<qreal> weights; diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index f8bffd3..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) { } @@ -348,31 +350,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 +390,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 +869,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() @@ -2983,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 c5295eb..4f95ef3 100644 --- a/src/opengl/qglshaderprogram.h +++ b/src/opengl/qglshaderprogram.h @@ -63,19 +63,21 @@ 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); - 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(); @@ -106,6 +108,9 @@ private: Q_DISABLE_COPY(QGLShader) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QGLShader::ShaderType); + + class QGLShaderProgramPrivate; class Q_OPENGL_EXPORT QGLShaderProgram : public QObject @@ -123,6 +128,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(); diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp index d3f52f6..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 @@ -64,7 +62,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 +75,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" @@ -126,11 +124,11 @@ QT_BEGIN_NAMESPACE the drawItem() method will draw its item argument directly with no effect applied. - \sa QGrapicsEffect + \sa QGraphicsEffect */ 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 +213,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 @@ -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 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<QVGPainterState *>(QPaintEngineEx::state()); } const QVGPainterState *state() const { return static_cast<const QVGPainterState *>(QPaintEngineEx::state()); } - void updateState(const QPaintEngineState &state); + void beginNativePainting(); + void endNativePainting(); QPixmapFilter *createPixmapFilter(int type) const; 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 <typename T> class QDirectFBPointer +template <typename T> 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 <typename T> +class QDirectFBPointer : public QScopedPointer<T, QDirectFBInterfaceCleanupHandler<T> > +{ +public: + QDirectFBPointer(T *t = 0) + : QScopedPointer<T, QDirectFBInterfaceCleanupHandler<T> >(t) + {} }; bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription) { IDirectFB *dfb = screen->dfb(); Q_ASSERT(dfb); - QDirectFBPointer<IDirectFBDataBuffer> 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<IDirectFBDataBuffer> dataBuffer(dataBufferPtr); -#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE - IDirectFBImageProvider *provider = 0; -#else - QDirectFBPointer<IDirectFBImageProvider> 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<IDirectFBImageProvider> 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<IDirectFBSurface> surfaceFromDescription = screen->createDFBSurface(surfaceDescription, QDirectFBScreen::DontTrackSurface, &result); + QDirectFBPointer<IDirectFBSurface> 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; } 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<const QWSWindowSurface*>(widget->windowSurface()); + if (surface && surface->key() == QLatin1String("directfb")) { + return static_cast<const QDirectFBWindowSurface*>(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<QDirectFBScreen*>(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..9de1ca5 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -48,8 +48,6 @@ #include <qpaintdevice.h> #include <qvarlengtharray.h> -//#define QT_DIRECTFB_DEBUG_SURFACES 1 - QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) : QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM @@ -245,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<quintptr>(this); -#endif + QByteArray state(sizeof(this), 0); + *reinterpret_cast<const QDirectFBWindowSurface**>(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<QDirectFBWindowSurface*>(ptr); + if (state.size() == sizeof(this)) { + sibling = *reinterpret_cast<QDirectFBWindowSurface *const*>(state.constData()); } #else Q_UNUSED(state); @@ -418,7 +413,6 @@ void QDirectFBWindowSurface::flush(QWidget *, const QRegion ®ion, #endif } - void QDirectFBWindowSurface::beginPaint(const QRegion &) { if (!engine) @@ -427,43 +421,28 @@ 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) +IDirectFBSurface *QDirectFBWindowSurface::surfaceForWidget(const QWidget *widget, QRect *rect) const { - if (!lockedImage) + Q_ASSERT(widget); + if (!dfbSurface) { + if (sibling && (!sibling->sibling || sibling->dfbSurface)) + return sibling->surfaceForWidget(widget, rect); 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; + } + 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() diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 0da3a98..dafc478 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -88,7 +88,7 @@ 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(); #ifdef QT_DIRECTFB_WM @@ -104,7 +104,6 @@ private: } mode; #endif - QList<QImage*> bufferImages; DFBSurfaceFlipFlags flipFlags; bool boundingRectFlip; #ifdef QT_DIRECTFB_TIMING diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 1d08676..d5aaed7 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<JSC::JSObject*>(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<JSC::JSObject*>(object)); @@ -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)); @@ -753,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); } @@ -767,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); } @@ -781,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); } @@ -795,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); } @@ -810,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()); } @@ -829,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())) { @@ -859,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); @@ -871,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())) { @@ -903,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: " @@ -1662,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); @@ -1687,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); } @@ -1709,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); } @@ -1730,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: " @@ -1780,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); } @@ -1803,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); } @@ -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->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()) + if (!d || !d->isObject() || !name.isValid()) 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); - 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); } /*! @@ -2263,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(); } /*! @@ -2310,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; } /*! @@ -2337,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<QScriptObject*>(JSC::asObject(d->jscValue)); @@ -2359,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)) { @@ -2413,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<QScriptObject*>(JSC::asObject(d->jscValue)); QScriptObjectDelegate *delegate = scriptObject->delegate(); if (!delegate || (delegate->type() != QScriptObjectDelegate::ClassObject)) { diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h index 3e952af..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); @@ -104,6 +105,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(); @@ -142,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/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/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/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 <steveire@gmail.com> + + 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 <QHash> +#include <QList> +#include <QTimer> + +#include <QDebug> + +#include <kdebug.h> + +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<QList<qint64> > childIdColumns = m_childItems.value(parent.internalId()); + + + if (childIdColumns.size() == 0) + return QModelIndex(); + + if (column >= childIdColumns.size()) + return QModelIndex(); + + QList<qint64> rowIds = childIdColumns.at(column); + + if ( row >= rowIds.size()) + return QModelIndex(); + + qint64 id = rowIds.at(row); + + return createIndex(row, column, reinterpret_cast<void *>(id)); + +} + +qint64 DynamicTreeModel::findParentId(qint64 searchId) const +{ + if (searchId <= 0) + return -1; + + QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems); + while (i.hasNext()) + { + i.next(); + QListIterator<QList<qint64> > j(i.value()); + while (j.hasNext()) + { + QList<qint64> 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<qint64> childList = m_childItems.value(grandParentId).at(column); + + int row = childList.indexOf(parentId); + + return createIndex(row, column, reinterpret_cast<void *>(parentId)); + +} + +int DynamicTreeModel::rowCount(const QModelIndex &index ) const +{ + QList<QList<qint64> > 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<int> rows) +{ + const int col = 0; + QModelIndex parent = QModelIndex(); + QListIterator<int> 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<qint64>()); + } +// 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<qint64> 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 <steveire@gmail.com> + + 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 <QAbstractItemModel> + +#include <QHash> +#include <QList> + +#include <QDebug> + +#include <kdebug.h> + +template<typename T> 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<qint64, QString> m_items; + QHash<qint64, QList<QList<qint64> > > 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<int> rowNumbers) { m_rowNumbers = rowNumbers; } + + QModelIndex findIndex(QList<int> 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<int> m_rowNumbers; + int m_numCols; + int m_startRow; + int m_endRow; + +}; + +typedef QList<ModelChangeCommand*> 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<int> rows ) { m_destRowNumbers = rows; } + + void setDestRow(int row) { m_destRow = row; } + +protected: + QList<int> 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<int>() << 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<int>("startRow"); + QTest::addColumn<int>("endRow"); + QTest::addColumn<int>("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<QPersistentModelIndex> 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>(), QModelIndex()); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex()); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value<QModelIndex>(), 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<int>("startRow"); + QTest::addColumn<int>("endRow"); + QTest::addColumn<int>("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<QPersistentModelIndex> 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>(), QModelIndex()); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex()); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value<QModelIndex>(), 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<int>("startRow"); + QTest::addColumn<int>("endRow"); + QTest::addColumn<int>("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<QPersistentModelIndex> 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<int>() << 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<QModelIndex>(), sourceIndex); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value<QModelIndex>(), 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<int>("startRow"); + QTest::addColumn<int>("endRow"); + QTest::addColumn<int>("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<QPersistentModelIndex> 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<int>() << 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<QModelIndex>(), sourceIndex); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value<QModelIndex>(), 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<int>("startRow"); + QTest::addColumn<int>("endRow"); + QTest::addColumn<int>("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<int>() << 9); + insertCommand->setNumCols(4); + insertCommand->setStartRow(0); + insertCommand->setEndRow(9); + insertCommand->doCommand(); + + QFETCH( int, startRow); + QFETCH( int, endRow); + QFETCH( int, destRow); + + QList<QPersistentModelIndex> 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<int>() << 9); + moveCommand->setNumCols(4); + moveCommand->setStartRow(startRow); + moveCommand->setEndRow(endRow); + moveCommand->setDestAncestors(QList<int>() << 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<QModelIndex>(), sourceIndex); + QCOMPARE(beforeSignal.at(1).toInt(), startRow); + QCOMPARE(beforeSignal.at(2).toInt(), endRow); + QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex); + QCOMPARE(beforeSignal.at(4).toInt(), destRow); + + QCOMPARE(afterSignal.size(), 5); + QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex); + QCOMPARE(afterSignal.at(1).toInt(), startRow); + QCOMPARE(afterSignal.at(2).toInt(), endRow); + QCOMPARE(afterSignal.at(3).value<QModelIndex>(), 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<int> 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<QPersistentModelIndex> 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<int> 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<int>("startRow"); + QTest::addColumn<int>("endRow"); + QTest::addColumn<int>("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" 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<QByteArray>("rawdata"); + QTest::addColumn<QByteArray>("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]; 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) diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index a08f620..b20c0e0 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<Foo::Bleh *>()), + QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bleh *>()), QByteArray(Bleh_iid)); - QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bar *>()), + QCOMPARE(QByteArray(qobject_interface_iid<Foo::Bar *>()), QByteArray("com.qtest.foobar")); - QCOMPARE(QByteArray(qobject_interface_iid<FooObject *>()), + QCOMPARE(QByteArray(qobject_interface_iid<FooObject *>()), 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); + 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" 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); 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() diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index 3f231f2..f9ce79f 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() @@ -2219,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 *) @@ -3277,6 +3295,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() 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 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" 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" |