diff options
245 files changed, 5476 insertions, 2336 deletions
@@ -1166,6 +1166,8 @@ while [ "$#" -gt 0 ]; do else if [ "$VAL" = "opengl" ]; then CFG_GRAPHICS_SYSTEM="opengl" + elif [ "$VAL" = "openvg" ]; then + CFG_GRAPHICS_SYSTEM="openvg" elif [ "$VAL" = "raster" ]; then CFG_GRAPHICS_SYSTEM="raster" else @@ -3769,7 +3771,7 @@ elif [ "$Edition" = "OpenSource" ]; then read acceptance fi echo - if [ "$acceptance" = "yes" ]; then + if [ "$acceptance" = "yes" ] || [ "$acceptance" = "y" ]; then break elif [ "$acceptance" = "no" ]; then echo "You are not licensed to use this software." @@ -5612,6 +5614,12 @@ if [ "$CFG_OPENVG" != "no" ]; then fi fi +# if openvg is disabled and the user specified graphicssystem vg, disable it... +if [ "$CFG_GRAPHICS_SYSTEM" = "openvg" ] && [ "$CFG_OPENVG" = "no" ]; then + echo "OpenVG Graphics System is disabled due to missing OpenVG support..." + CFG_GRAPHICS_SYSTEM=default +fi + if [ "$CFG_PTMALLOC" != "no" ]; then # build ptmalloc, copy .a file to lib/ echo "Building ptmalloc. Please wait..." @@ -6057,6 +6065,7 @@ fi # canBuildQtXmlPatterns="yes" canBuildWebKit="$HAVE_STL" +canBuildQtConcurrent="yes" # WebKit requires stdint.h "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stdint "Stdint" $L_FLAGS $I_FLAGS $l_FLAGS @@ -6088,9 +6097,9 @@ case "$XPLATFORM" in case "$(${QMAKE_CONF_COMPILER} -dumpversion)" in 4*|3.4*) ;; - 3.3*) - canBuildWebKit="no" - ;; + 3.3*) + canBuildWebKit="no" + ;; *) canBuildWebKit="no" canBuildQtXmlPatterns="no" @@ -6098,30 +6107,72 @@ case "$XPLATFORM" in esac ;; solaris-cc*) - # Check the compiler version - case `${QMAKE_CONF_COMPILER} -V 2>&1 | awk '{print $4}'` in - *) - canBuildWebKit="no" - canBuildQtXmlPatterns="no" - ;; - esac - ;; + # Check the compiler version + case `${QMAKE_CONF_COMPILER} -V 2>&1 | awk '{print $4}'` in + 5.[012345678]) + canBuildWebKit="no" + canBuildQtXmlPatterns="no" + canBuildQtConcurrent="no" + ;; + 5.9) + canBuildWebKit="no" + ;; + esac + ;; hpux-acc*) canBuildWebKit="no" canBuildQtXmlPatterns="no" + canBuildQtConcurrent="no" ;; hpuxi-acc*) canBuildWebKit="no" ;; aix-xlc*) - canBuildWebKit="no" - canBuildQtXmlPatterns="no" - ;; + # Get the xlC version + cat > xlcver.c <<EOF +#include <stdio.h> +int main() +{ + printf("%d.%d\n", __xlC__ >> 8, __xlC__ & 0xFF); + return 0; +} +EOF + xlcver= + if ${QMAKE_CONF_COMPILER} -o xlcver xlcver.c >/dev/null 2>/dev/null; then + xlcver=`./xlcver 2>/dev/null` + rm -f ./xlcver + fi + if [ "$OPT_VERBOSE" = "yes" ]; then + if [ -n "$xlcver" ]; then + echo Found IBM xlC version: $xlcver. + else + echo Could not determine IBM xlC version, assuming oldest supported. + fi + fi + + case "$xlcver" in + [123456].*) + canBuildWebKit="no" + canBuildQtXmlPatterns="no" + canBuildQtConcurrent="no" + ;; + *) + canBuildWebKit="no" + ;; + esac + ;; irix-cc*) canBuildWebKit="no" + canBuildQtConcurrent="no" ;; esac +CFG_CONCURRENT="yes" +if [ "$canBuildQtConcurrent" = "no" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_CONCURRENT" + CFG_CONCURRENT="no" +fi + if [ "$CFG_XMLPATTERNS" = "yes" -a "$CFG_EXCEPTIONS" = "no" ]; then echo "QtXmlPatterns was requested, but it can't be built due to exceptions being disabled." exit 1 @@ -6638,6 +6689,7 @@ QMakeVar set sql-plugins "$SQL_PLUGINS" if [ "$PLATFORM_QWS" != "yes" ]; then [ "$CFG_GRAPHICS_SYSTEM" = "raster" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_GRAPHICSSYSTEM_RASTER" [ "$CFG_GRAPHICS_SYSTEM" = "opengl" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_GRAPHICSSYSTEM_OPENGL" + [ "$CFG_GRAPHICS_SYSTEM" = "openvg" ] && QCONFIG_FLAGS="$QCONFIG_FLAGS QT_GRAPHICSSYSTEM_OPENVG" fi # X11/Unix/Mac only configs @@ -7030,6 +7082,7 @@ echo "Qt 3 compatibility .. $CFG_QT3SUPPORT" [ "$CFG_DBUS" = "no" ] && echo "QtDBus module ....... no" [ "$CFG_DBUS" = "yes" ] && echo "QtDBus module ....... yes (run-time)" [ "$CFG_DBUS" = "linked" ] && echo "QtDBus module ....... yes (linked)" +echo "QtConcurrent code.... $CFG_CONCURRENT" echo "QtScriptTools module $CFG_SCRIPTTOOLS" echo "QtXmlPatterns module $CFG_XMLPATTERNS" echo "Phonon module ....... $CFG_PHONON" diff --git a/configure.exe b/configure.exe Binary files differindex b4b7c50..5c5c199 100644 --- a/configure.exe +++ b/configure.exe diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0 index bef2923..6c7e450 100644 --- a/dist/changes-4.6.0 +++ b/dist/changes-4.6.0 @@ -72,5 +72,18 @@ information about a particular change. QGraphicsWidget and QGraphicsProxyWidget). - QDesktopWidget on X11 no longer emits the resized(int) signal when screens - are added or removed. This was not done on other platforms. Use the + are added or removed. This was not done on other platforms. Use the screenCountChanged signal instead + +- QUrl's parser is more strict when for hostnames in URLs. QUrl now + enforces STD 3 rules: + + * each individual hostname section (between dots) must be at most + 63 ASCII characters in length; + + * only letters, digits, and the hyphen character are allowed in the + ASCII range; letters outside the ASCII range follow the normal + IDN rules + + That means QUrl no longer accepts some URLs that were invalid + before, but weren't interpreted as such. diff --git a/doc/src/classes.qdoc b/doc/src/classes.qdoc index dddc96f..9a5d3ec 100644 --- a/doc/src/classes.qdoc +++ b/doc/src/classes.qdoc @@ -44,13 +44,15 @@ \title Qt's Classes \ingroup classlists - This is a list of all Qt classes excluding the \l{Qt 3 - compatibility classes}. For a shorter list that only includes the - most frequently used classes, see \l{Qt's Main Classes}. + This is a list of all Qt classes. For a shorter list of the most + frequently used Qt classes, see \l{Qt's Main Classes}. For a list + of the classes provided for compatibility with Qt3, see \l{Qt 3 + compatibility classes}. For classes that have been deprecated, see + the \l{Obsolete Classes} list. \generatelist classes - \sa {Qt 3 Compatibility Classes}, {Qt's Modules} + \sa {Qt 3 Compatibility Classes}, {Qt's Modules}, {Obsolete Classes} */ /*! diff --git a/doc/src/diagrams/programs/easingcurve/main.cpp b/doc/src/diagrams/programs/easingcurve/main.cpp index 8a2d53b..f249dbc 100644 --- a/doc/src/diagrams/programs/easingcurve/main.cpp +++ b/doc/src/diagrams/programs/easingcurve/main.cpp @@ -85,32 +85,37 @@ void createCurveIcons() qreal curveScale = iconSize.height()/2; - painter.drawLine(yAxis - 2, xAxis - curveScale, yAxis + 2, xAxis - curveScale); // hor + painter.drawLine(yAxis - 2, xAxis - curveScale, yAxis + 2, xAxis - curveScale); // hor painter.drawLine(yAxis + curveScale, xAxis + 2, yAxis + curveScale, xAxis - 2); // ver painter.drawText(yAxis + curveScale - 8, xAxis - curveScale - 4, QLatin1String("(1,1)")); - + painter.drawText(yAxis + 42, xAxis + 10, QLatin1String("progress")); - painter.drawText(15, xAxis - curveScale - 10, QLatin1String("ease")); - - painter.setPen(QPen(Qt::red, 1, Qt::DotLine)); + painter.drawText(15, xAxis - curveScale - 10, QLatin1String("value")); + + painter.setPen(QPen(Qt::red, 1, Qt::DotLine)); painter.drawLine(yAxis, xAxis - curveScale, yAxis + curveScale, xAxis - curveScale); // hor painter.drawLine(yAxis + curveScale, xAxis, yAxis + curveScale, xAxis - curveScale); // ver - - QPoint currentPos(yAxis, xAxis); - + + QPoint start(yAxis, xAxis - curveScale * curve.valueForProgress(0)); + painter.setPen(Qt::black); QFont font = oldFont; font.setPixelSize(oldFont.pixelSize() + 15); painter.setFont(font); painter.drawText(0, iconSize.height() - 20, iconSize.width(), 20, Qt::AlignHCenter, name); - - for (qreal t = 0; t < 1.0; t+=1.0/curveScale) { + + QPainterPath curvePath; + curvePath.moveTo(start); + for (qreal t = 0; t <= 1.0; t+=1.0/curveScale) { QPoint to; to.setX(yAxis + curveScale * t); to.setY(xAxis - curveScale * curve.valueForProgress(t)); - painter.drawLine(currentPos, to); - currentPos = to; + curvePath.lineTo(to); } + painter.setRenderHint(QPainter::Antialiasing, true); + painter.strokePath(curvePath, QColor(32, 32, 32)); + painter.setRenderHint(QPainter::Antialiasing, false); + QString fileName(QString::fromAscii("qeasingcurve-%1.png").arg(name.toLower())); printf("%s\n", qPrintable(fileName)); pix.save(QString::fromAscii("%1/%2").arg(output).arg(fileName), "PNG"); diff --git a/doc/src/graphicsview.qdoc b/doc/src/graphicsview.qdoc index 4c408cd..f42c0d4 100644 --- a/doc/src/graphicsview.qdoc +++ b/doc/src/graphicsview.qdoc @@ -201,6 +201,9 @@ using an untransformed view, one unit on the scene is represented by one pixel on the screen. + \note The inverted Y-axis coordinate system (where \c y grows upwards) + is unsupported as Graphics Views uses Qt's coordinate system. + There are three effective coordinate systems in play in Graphics View: Item coordinates, scene coordinates, and view coordinates. To simplify your implementation, Graphics View provides convenience functions that diff --git a/doc/src/images/qeasingcurve-cosinecurve.png b/doc/src/images/qeasingcurve-cosinecurve.png Binary files differindex b27e763..8cee978 100644 --- a/doc/src/images/qeasingcurve-cosinecurve.png +++ b/doc/src/images/qeasingcurve-cosinecurve.png diff --git a/doc/src/images/qeasingcurve-inback.png b/doc/src/images/qeasingcurve-inback.png Binary files differindex 8506c0f..0064cb3 100644 --- a/doc/src/images/qeasingcurve-inback.png +++ b/doc/src/images/qeasingcurve-inback.png diff --git a/doc/src/images/qeasingcurve-inbounce.png b/doc/src/images/qeasingcurve-inbounce.png Binary files differindex 275b38c..eaa64f8 100644 --- a/doc/src/images/qeasingcurve-inbounce.png +++ b/doc/src/images/qeasingcurve-inbounce.png diff --git a/doc/src/images/qeasingcurve-incirc.png b/doc/src/images/qeasingcurve-incirc.png Binary files differindex b985e9c..7bd0f09 100644 --- a/doc/src/images/qeasingcurve-incirc.png +++ b/doc/src/images/qeasingcurve-incirc.png diff --git a/doc/src/images/qeasingcurve-incubic.png b/doc/src/images/qeasingcurve-incubic.png Binary files differindex e417ee1..1ac9eaf 100644 --- a/doc/src/images/qeasingcurve-incubic.png +++ b/doc/src/images/qeasingcurve-incubic.png diff --git a/doc/src/images/qeasingcurve-incurve.png b/doc/src/images/qeasingcurve-incurve.png Binary files differindex d9a9340..578259e 100644 --- a/doc/src/images/qeasingcurve-incurve.png +++ b/doc/src/images/qeasingcurve-incurve.png diff --git a/doc/src/images/qeasingcurve-inelastic.png b/doc/src/images/qeasingcurve-inelastic.png Binary files differindex b242fd3..f976b5a 100644 --- a/doc/src/images/qeasingcurve-inelastic.png +++ b/doc/src/images/qeasingcurve-inelastic.png diff --git a/doc/src/images/qeasingcurve-inexpo.png b/doc/src/images/qeasingcurve-inexpo.png Binary files differindex f06316c..1af3652 100644 --- a/doc/src/images/qeasingcurve-inexpo.png +++ b/doc/src/images/qeasingcurve-inexpo.png diff --git a/doc/src/images/qeasingcurve-inoutback.png b/doc/src/images/qeasingcurve-inoutback.png Binary files differindex 9fd1446..480bc05 100644 --- a/doc/src/images/qeasingcurve-inoutback.png +++ b/doc/src/images/qeasingcurve-inoutback.png diff --git a/doc/src/images/qeasingcurve-inoutbounce.png b/doc/src/images/qeasingcurve-inoutbounce.png Binary files differindex fb65f31..de62309 100644 --- a/doc/src/images/qeasingcurve-inoutbounce.png +++ b/doc/src/images/qeasingcurve-inoutbounce.png diff --git a/doc/src/images/qeasingcurve-inoutcirc.png b/doc/src/images/qeasingcurve-inoutcirc.png Binary files differindex 123cc54..b4be8ac 100644 --- a/doc/src/images/qeasingcurve-inoutcirc.png +++ b/doc/src/images/qeasingcurve-inoutcirc.png diff --git a/doc/src/images/qeasingcurve-inoutcubic.png b/doc/src/images/qeasingcurve-inoutcubic.png Binary files differindex b07695c..49dfbef 100644 --- a/doc/src/images/qeasingcurve-inoutcubic.png +++ b/doc/src/images/qeasingcurve-inoutcubic.png diff --git a/doc/src/images/qeasingcurve-inoutelastic.png b/doc/src/images/qeasingcurve-inoutelastic.png Binary files differindex 65851e1..5b0e54a 100644 --- a/doc/src/images/qeasingcurve-inoutelastic.png +++ b/doc/src/images/qeasingcurve-inoutelastic.png diff --git a/doc/src/images/qeasingcurve-inoutexpo.png b/doc/src/images/qeasingcurve-inoutexpo.png Binary files differindex 7cbfb13..776984a 100644 --- a/doc/src/images/qeasingcurve-inoutexpo.png +++ b/doc/src/images/qeasingcurve-inoutexpo.png diff --git a/doc/src/images/qeasingcurve-inoutquad.png b/doc/src/images/qeasingcurve-inoutquad.png Binary files differindex c5eed06..2643330 100644 --- a/doc/src/images/qeasingcurve-inoutquad.png +++ b/doc/src/images/qeasingcurve-inoutquad.png diff --git a/doc/src/images/qeasingcurve-inoutquart.png b/doc/src/images/qeasingcurve-inoutquart.png Binary files differindex 3b66c0d..31fc0c8 100644 --- a/doc/src/images/qeasingcurve-inoutquart.png +++ b/doc/src/images/qeasingcurve-inoutquart.png diff --git a/doc/src/images/qeasingcurve-inoutquint.png b/doc/src/images/qeasingcurve-inoutquint.png Binary files differindex c74efe9..4d7a745 100644 --- a/doc/src/images/qeasingcurve-inoutquint.png +++ b/doc/src/images/qeasingcurve-inoutquint.png diff --git a/doc/src/images/qeasingcurve-inoutsine.png b/doc/src/images/qeasingcurve-inoutsine.png Binary files differindex 5964f31..012ff75 100644 --- a/doc/src/images/qeasingcurve-inoutsine.png +++ b/doc/src/images/qeasingcurve-inoutsine.png diff --git a/doc/src/images/qeasingcurve-inquad.png b/doc/src/images/qeasingcurve-inquad.png Binary files differindex 3373310..e697c20 100644 --- a/doc/src/images/qeasingcurve-inquad.png +++ b/doc/src/images/qeasingcurve-inquad.png diff --git a/doc/src/images/qeasingcurve-inquart.png b/doc/src/images/qeasingcurve-inquart.png Binary files differindex 28086d8..6d65175 100644 --- a/doc/src/images/qeasingcurve-inquart.png +++ b/doc/src/images/qeasingcurve-inquart.png diff --git a/doc/src/images/qeasingcurve-inquint.png b/doc/src/images/qeasingcurve-inquint.png Binary files differindex 330aa85..faaaea7 100644 --- a/doc/src/images/qeasingcurve-inquint.png +++ b/doc/src/images/qeasingcurve-inquint.png diff --git a/doc/src/images/qeasingcurve-insine.png b/doc/src/images/qeasingcurve-insine.png Binary files differindex 63d9238..0944903 100644 --- a/doc/src/images/qeasingcurve-insine.png +++ b/doc/src/images/qeasingcurve-insine.png diff --git a/doc/src/images/qeasingcurve-linear.png b/doc/src/images/qeasingcurve-linear.png Binary files differindex 2a05885..fb3aaf3 100644 --- a/doc/src/images/qeasingcurve-linear.png +++ b/doc/src/images/qeasingcurve-linear.png diff --git a/doc/src/images/qeasingcurve-outback.png b/doc/src/images/qeasingcurve-outback.png Binary files differindex 7cb34c6..83b3fa2 100644 --- a/doc/src/images/qeasingcurve-outback.png +++ b/doc/src/images/qeasingcurve-outback.png diff --git a/doc/src/images/qeasingcurve-outbounce.png b/doc/src/images/qeasingcurve-outbounce.png Binary files differindex 932fc16..27ac979 100644 --- a/doc/src/images/qeasingcurve-outbounce.png +++ b/doc/src/images/qeasingcurve-outbounce.png diff --git a/doc/src/images/qeasingcurve-outcirc.png b/doc/src/images/qeasingcurve-outcirc.png Binary files differindex a1a6cb6..0019370 100644 --- a/doc/src/images/qeasingcurve-outcirc.png +++ b/doc/src/images/qeasingcurve-outcirc.png diff --git a/doc/src/images/qeasingcurve-outcubic.png b/doc/src/images/qeasingcurve-outcubic.png Binary files differindex aa1d604..45477c0 100644 --- a/doc/src/images/qeasingcurve-outcubic.png +++ b/doc/src/images/qeasingcurve-outcubic.png diff --git a/doc/src/images/qeasingcurve-outcurve.png b/doc/src/images/qeasingcurve-outcurve.png Binary files differindex a949ae4..295b471 100644 --- a/doc/src/images/qeasingcurve-outcurve.png +++ b/doc/src/images/qeasingcurve-outcurve.png diff --git a/doc/src/images/qeasingcurve-outelastic.png b/doc/src/images/qeasingcurve-outelastic.png Binary files differindex 2a9ba39..1d407ed 100644 --- a/doc/src/images/qeasingcurve-outelastic.png +++ b/doc/src/images/qeasingcurve-outelastic.png diff --git a/doc/src/images/qeasingcurve-outexpo.png b/doc/src/images/qeasingcurve-outexpo.png Binary files differindex e771c2e..5685155 100644 --- a/doc/src/images/qeasingcurve-outexpo.png +++ b/doc/src/images/qeasingcurve-outexpo.png diff --git a/doc/src/images/qeasingcurve-outinback.png b/doc/src/images/qeasingcurve-outinback.png Binary files differindex 7523727..4700ab0 100644 --- a/doc/src/images/qeasingcurve-outinback.png +++ b/doc/src/images/qeasingcurve-outinback.png diff --git a/doc/src/images/qeasingcurve-outinbounce.png b/doc/src/images/qeasingcurve-outinbounce.png Binary files differindex ab73d02..12cc1a8 100644 --- a/doc/src/images/qeasingcurve-outinbounce.png +++ b/doc/src/images/qeasingcurve-outinbounce.png diff --git a/doc/src/images/qeasingcurve-outincirc.png b/doc/src/images/qeasingcurve-outincirc.png Binary files differindex ec4b8d3..c8a5c86 100644 --- a/doc/src/images/qeasingcurve-outincirc.png +++ b/doc/src/images/qeasingcurve-outincirc.png diff --git a/doc/src/images/qeasingcurve-outincubic.png b/doc/src/images/qeasingcurve-outincubic.png Binary files differindex 8b8ae68..42af870 100644 --- a/doc/src/images/qeasingcurve-outincubic.png +++ b/doc/src/images/qeasingcurve-outincubic.png diff --git a/doc/src/images/qeasingcurve-outinelastic.png b/doc/src/images/qeasingcurve-outinelastic.png Binary files differindex 89dde2c..308be57 100644 --- a/doc/src/images/qeasingcurve-outinelastic.png +++ b/doc/src/images/qeasingcurve-outinelastic.png diff --git a/doc/src/images/qeasingcurve-outinexpo.png b/doc/src/images/qeasingcurve-outinexpo.png Binary files differindex 5909901..0692baa 100644 --- a/doc/src/images/qeasingcurve-outinexpo.png +++ b/doc/src/images/qeasingcurve-outinexpo.png diff --git a/doc/src/images/qeasingcurve-outinquad.png b/doc/src/images/qeasingcurve-outinquad.png Binary files differindex 7ddefee..9e3cd83 100644 --- a/doc/src/images/qeasingcurve-outinquad.png +++ b/doc/src/images/qeasingcurve-outinquad.png diff --git a/doc/src/images/qeasingcurve-outinquart.png b/doc/src/images/qeasingcurve-outinquart.png Binary files differindex 00ef597..9a3c16f 100644 --- a/doc/src/images/qeasingcurve-outinquart.png +++ b/doc/src/images/qeasingcurve-outinquart.png diff --git a/doc/src/images/qeasingcurve-outinquint.png b/doc/src/images/qeasingcurve-outinquint.png Binary files differindex 361bfaa4..add9feb 100644 --- a/doc/src/images/qeasingcurve-outinquint.png +++ b/doc/src/images/qeasingcurve-outinquint.png diff --git a/doc/src/images/qeasingcurve-outinsine.png b/doc/src/images/qeasingcurve-outinsine.png Binary files differindex 1737041..4bc2aaf 100644 --- a/doc/src/images/qeasingcurve-outinsine.png +++ b/doc/src/images/qeasingcurve-outinsine.png diff --git a/doc/src/images/qeasingcurve-outquad.png b/doc/src/images/qeasingcurve-outquad.png Binary files differindex 6f27cbd..c505ff9 100644 --- a/doc/src/images/qeasingcurve-outquad.png +++ b/doc/src/images/qeasingcurve-outquad.png diff --git a/doc/src/images/qeasingcurve-outquart.png b/doc/src/images/qeasingcurve-outquart.png Binary files differindex d45a0b8..6eac058 100644 --- a/doc/src/images/qeasingcurve-outquart.png +++ b/doc/src/images/qeasingcurve-outquart.png diff --git a/doc/src/images/qeasingcurve-outquint.png b/doc/src/images/qeasingcurve-outquint.png Binary files differindex 6e7df0e..77a9ad4 100644 --- a/doc/src/images/qeasingcurve-outquint.png +++ b/doc/src/images/qeasingcurve-outquint.png diff --git a/doc/src/images/qeasingcurve-outsine.png b/doc/src/images/qeasingcurve-outsine.png Binary files differindex 7546a0d..d135b2f 100644 --- a/doc/src/images/qeasingcurve-outsine.png +++ b/doc/src/images/qeasingcurve-outsine.png diff --git a/doc/src/images/qeasingcurve-sinecurve.png b/doc/src/images/qeasingcurve-sinecurve.png Binary files differindex ca67d44..6134a01 100644 --- a/doc/src/images/qeasingcurve-sinecurve.png +++ b/doc/src/images/qeasingcurve-sinecurve.png diff --git a/examples/animation/stickman/editor/mainwindow.cpp b/doc/src/obsoleteclasses.qdoc index e1d08cc..3658dfc 100644 --- a/examples/animation/stickman/editor/mainwindow.cpp +++ b/doc/src/obsoleteclasses.qdoc @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtCore module of the Qt Toolkit. +** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -39,38 +39,21 @@ ** ****************************************************************************/ -#include "mainwindow.h" -#include "animationdialog.h" -#include "stickman.h" +/*! + \page obsoleteclasses.html + \group obsolete + \title Obsolete Classes + \ingroup classlists + \ingroup groups -#include <QMenuBar> -#include <QApplication> + \brief Qt classes that are obsolete (deprecated). -MainWindow::MainWindow(StickMan *stickMan) -{ - initActions(stickMan); -} + This is a list of Qt classes that are obsolete (deprecated). These + classes are provided to keep old source code working but they are + no longer maintained. We strongly advise against using these + classes in new code. -MainWindow::~MainWindow() -{ -} + \generatelist obsoleteclasses -void MainWindow::initActions(StickMan *stickMan) -{ - AnimationDialog *dialog = new AnimationDialog(stickMan, this); - dialog->show(); - - QMenu *fileMenu = menuBar()->addMenu("&File"); - QAction *loadAction = fileMenu->addAction("&Open"); - QAction *saveAction = fileMenu->addAction("&Save"); - QAction *exitAction = fileMenu->addAction("E&xit"); - - QMenu *animationMenu = menuBar()->addMenu("&Animation"); - QAction *newAnimationAction = animationMenu->addAction("&New animation"); - - connect(loadAction, SIGNAL(triggered()), dialog, SLOT(loadAnimation())); - connect(saveAction, SIGNAL(triggered()), dialog, SLOT(saveAnimation())); - connect(exitAction, SIGNAL(triggered()), QApplication::instance(), SLOT(quit())); - connect(newAnimationAction, SIGNAL(triggered()), dialog, SLOT(newAnimation())); - -} + \sa {Qt's Classes}, {Qt's Modules} +*/ diff --git a/doc/src/snippets/code/src_network_access_qnetworkreply.cpp b/doc/src/snippets/code/src_network_access_qnetworkreply.cpp new file mode 100644 index 0000000..78b388b --- /dev/null +++ b/doc/src/snippets/code/src_network_access_qnetworkreply.cpp @@ -0,0 +1,10 @@ +//! [0] +QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem")); +QSslError error(QSslError::SelfSignedCertificate, cert.at(0)); +QList<QSslError> expectedSslErrors; +expectedSslErrors.append(error); + +QNetworkReply *reply = manager.get(QNetworkRequest(QUrl("https://server.tld/index.html"))); +reply->ignoreSslErrors(expectedSslErrors); +// here connect signals etc. +//! [0] diff --git a/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp b/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp index afffbab..7845e9b 100644 --- a/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp +++ b/doc/src/snippets/code/src_network_ssl_qsslsocket.cpp @@ -54,3 +54,14 @@ socket->connectToHostEncrypted("imap", 993); if (socket->waitForEncrypted(1000)) qDebug("Encrypted!"); //! [5] + +//! [6] +QList<QSslCertificate> cert = QSslCertificate::fromPath(QLatin1String("server-certificate.pem")); +QSslError error(QSslError::SelfSignedCertificate, cert.at(0)); +QList<QSslError> expectedSslErrors; +expectedSslErrors.append(error); + +QSslSocket socket; +socket.ignoreSslErrors(expectedSslErrors); +socket.connectToHostEncrypted("server.tld", 443); +//! [6] diff --git a/examples/animation/appchooser/main.cpp b/examples/animation/appchooser/main.cpp index fe4be1f..97751b2 100644 --- a/examples/animation/appchooser/main.cpp +++ b/examples/animation/appchooser/main.cpp @@ -134,7 +134,7 @@ int main(int argc, char **argv) QStateMachine machine; machine.setGlobalRestorePolicy(QStateMachine::RestoreProperties); - QState *group = new QState(machine.rootState()); + QState *group = new QState(&machine); group->setObjectName("group"); QRect selectedRect(86, 86, 128, 128); diff --git a/examples/animation/moveblocks/main.cpp b/examples/animation/moveblocks/main.cpp index c43e841..97d3f81 100644 --- a/examples/animation/moveblocks/main.cpp +++ b/examples/animation/moveblocks/main.cpp @@ -108,8 +108,7 @@ class StateSwitcher : public QState Q_OBJECT public: StateSwitcher(QStateMachine *machine) - : QState(machine->rootState()), m_machine(machine), - m_stateCount(0), m_lastIndex(0) + : QState(machine), m_stateCount(0), m_lastIndex(0) { } //![10] @@ -120,7 +119,7 @@ public: while ((n = (qrand() % m_stateCount + 1)) == m_lastIndex) { } m_lastIndex = n; - m_machine->postEvent(new StateSwitchEvent(n)); + machine()->postEvent(new StateSwitchEvent(n)); } virtual void onExit(QEvent *) {} //![11] @@ -135,7 +134,6 @@ public: //![12] private: - QStateMachine *m_machine; int m_stateCount; int m_lastIndex; }; diff --git a/examples/animation/states/main.cpp b/examples/animation/states/main.cpp index b3c28f2..99e04c3 100644 --- a/examples/animation/states/main.cpp +++ b/examples/animation/states/main.cpp @@ -124,10 +124,9 @@ int main(int argc, char *argv[]) scene.addItem(p6); QStateMachine machine; - QState *root = machine.rootState(); - QState *state1 = new QState(root); - QState *state2 = new QState(root); - QState *state3 = new QState(root); + QState *state1 = new QState(&machine); + QState *state2 = new QState(&machine); + QState *state3 = new QState(&machine); machine.setInitialState(state1); // State 1 diff --git a/examples/animation/stickman/editor/animationdialog.cpp b/examples/animation/stickman/editor/animationdialog.cpp deleted file mode 100644 index 853046d..0000000 --- a/examples/animation/stickman/editor/animationdialog.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the either Technology Preview License Agreement or the -** Beta Release License Agreement. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain -** additional rights. These rights are described in the Nokia Qt LGPL -** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this -** package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "animationdialog.h" -#include "stickman.h" -#include "animation.h" -#include "node.h" - -#include <QHBoxLayout> -#include <QStackedWidget> -#include <QSpinBox> -#include <QPushButton> -#include <QLabel> -#include <QLineEdit> -#include <QMessageBox> -#include <QFileDialog> - -AnimationDialog::AnimationDialog(StickMan *stickman, QWidget *parent) - : QDialog(parent), m_animation(0), m_stickman(stickman) -{ - initUi(); -} - -AnimationDialog::~AnimationDialog() -{ - delete m_animation; -} - -void AnimationDialog::initUi() -{ - setWindowTitle("Animation"); - setEnabled(false); - - // Second page - m_currentFrame = new QSpinBox(); - m_totalFrames = new QSpinBox(); - m_name = new QLineEdit(); - - connect(m_currentFrame, SIGNAL(valueChanged(int)), this, SLOT(currentFrameChanged(int))); - connect(m_totalFrames, SIGNAL(valueChanged(int)), this, SLOT(totalFramesChanged(int))); - connect(m_name, SIGNAL(textChanged(QString)), this, SLOT(setCurrentAnimationName(QString))); - - QGridLayout *gridLayout = new QGridLayout(this); - gridLayout->addWidget(new QLabel("Name:"), 0, 0, 1, 2); - gridLayout->addWidget(m_name, 0, 2, 1, 2); - gridLayout->addWidget(new QLabel("Frame:"), 1, 0); - gridLayout->addWidget(m_currentFrame, 1, 1); - gridLayout->addWidget(new QLabel("of total # of frames: "), 1, 2); - gridLayout->addWidget(m_totalFrames, 1, 3); -} - -void AnimationDialog::initFromAnimation() -{ - m_currentFrame->setRange(0, m_animation->totalFrames()-1); - m_currentFrame->setValue(m_animation->currentFrame()); - - m_totalFrames->setRange(1, 1000); - m_totalFrames->setValue(m_animation->totalFrames()); - - m_name->setText(m_animation->name()); -} - -void AnimationDialog::saveAnimation() -{ - saveCurrentFrame(); - - QString fileName = QFileDialog::getSaveFileName(this, "Save animation"); - - QFile file(fileName); - if (file.open(QIODevice::WriteOnly)) - m_animation->save(&file); -} - -void AnimationDialog::loadAnimation() -{ - if (maybeSave() != QMessageBox::Cancel) { - QString fileName = QFileDialog::getOpenFileName(this, "Open animation"); - - QFile file(fileName); - if (file.open(QIODevice::ReadOnly)) { - if (m_animation == 0) - newAnimation(); - - m_animation->load(&file); - stickManFromCurrentFrame(); - initFromAnimation(); - } - } -} - -QMessageBox::StandardButton AnimationDialog::maybeSave() -{ - if (m_animation == 0) - return QMessageBox::No; - - QMessageBox::StandardButton button = QMessageBox::question(this, "Save?", "Do you want to save your changes?", - QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); - if (button == QMessageBox::Save) - saveAnimation(); - - return button; -} - -void AnimationDialog::newAnimation() -{ - if (maybeSave() != QMessageBox::Cancel) { - setEnabled(true); - delete m_animation; - m_animation = new Animation(); - initFromAnimation(); - } -} - -// Gets the data from the stickman and stores it in current frame -void AnimationDialog::saveCurrentFrame() -{ - int count = m_stickman->nodeCount(); - m_animation->setNodeCount(count); - for (int i=0; i<count; ++i) { - QGraphicsItem *node = m_stickman->node(i); - m_animation->setNodePos(i, node->pos()); - } -} - -// Gets the data from the current frame and sets the stickman -void AnimationDialog::stickManFromCurrentFrame() -{ - int count = m_animation->nodeCount(); - for (int i=0;i<count;++i) { - QGraphicsItem *node = m_stickman->node(i); - node->setPos(m_animation->nodePos(i)); - } -} - -void AnimationDialog::currentFrameChanged(int currentFrame) -{ - saveCurrentFrame(); - qDebug("currentFrame: %d", currentFrame); - m_animation->setCurrentFrame(currentFrame); - stickManFromCurrentFrame(); - initFromAnimation(); -} - -void AnimationDialog::totalFramesChanged(int totalFrames) -{ - m_animation->setTotalFrames(totalFrames); - stickManFromCurrentFrame(); - initFromAnimation(); -} - -void AnimationDialog::setCurrentAnimationName(const QString &name) -{ - m_animation->setName(name); -} diff --git a/examples/animation/stickman/editor/editor.pri b/examples/animation/stickman/editor/editor.pri deleted file mode 100644 index 7ad9edb..0000000 --- a/examples/animation/stickman/editor/editor.pri +++ /dev/null @@ -1,2 +0,0 @@ -SOURCES += $$PWD/animationdialog.cpp $$PWD/mainwindow.cpp -HEADERS += $$PWD/animationdialog.h $$PWD/mainwindow.h diff --git a/examples/animation/stickman/graphicsview.cpp b/examples/animation/stickman/graphicsview.cpp index 760c31b..89f2430 100644 --- a/examples/animation/stickman/graphicsview.cpp +++ b/examples/animation/stickman/graphicsview.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include "graphicsview.h" -#include "editor/mainwindow.h" #include "stickman.h" #include <QtGui/QKeyEvent> @@ -53,28 +52,6 @@ void GraphicsView::keyPressEvent(QKeyEvent *e) { if (e->key() == Qt::Key_Escape) close(); - -#if 0 - if (e->key() == Qt::Key_F1) { - if (m_editor == 0) { - QGraphicsScene *scene = new QGraphicsScene; - StickMan *stickMan = new StickMan; - stickMan->setDrawSticks(true); - scene->addItem(stickMan); - - QGraphicsView *view = new QGraphicsView; - view->setBackgroundBrush(Qt::black); - view->setRenderHints(QPainter::Antialiasing); - view->setScene(scene); - - m_editor = new MainWindow(stickMan); - m_editor->setCentralWidget(view); - } - - m_editor->showMaximized(); - } -#endif - emit keyPressed(Qt::Key(e->key())); } diff --git a/examples/animation/stickman/lifecycle.cpp b/examples/animation/stickman/lifecycle.cpp index 2a54c82..c761d87 100644 --- a/examples/animation/stickman/lifecycle.cpp +++ b/examples/animation/stickman/lifecycle.cpp @@ -108,11 +108,11 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) m_machine->addDefaultAnimation(m_animationGroup); //! [3] - m_alive = new QState(m_machine->rootState()); + m_alive = new QState(m_machine); m_alive->setObjectName("alive"); // Make it blink when lightning strikes before entering dead animation - QState *lightningBlink = new QState(m_machine->rootState()); + QState *lightningBlink = new QState(m_machine); lightningBlink->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::white); lightningBlink->assignProperty(m_stickMan, "penColor", Qt::black); lightningBlink->assignProperty(m_stickMan, "fillColor", Qt::white); @@ -126,7 +126,7 @@ LifeCycle::LifeCycle(StickMan *stickMan, GraphicsView *keyReceiver) QObject::connect(lightningBlink, SIGNAL(exited()), timer, SLOT(stop())); //! [5] - m_dead = new QState(m_machine->rootState()); + m_dead = new QState(m_machine); m_dead->assignProperty(m_stickMan->scene(), "backgroundBrush", Qt::black); m_dead->assignProperty(m_stickMan, "penColor", Qt::white); m_dead->assignProperty(m_stickMan, "fillColor", Qt::black); diff --git a/examples/animation/stickman/stickman.pro b/examples/animation/stickman/stickman.pro index 1dbbce9..7f8be33 100644 --- a/examples/animation/stickman/stickman.pro +++ b/examples/animation/stickman/stickman.pro @@ -12,8 +12,6 @@ SOURCES += main.cpp \ INCLUDEPATH += $$PWD -include(editor/editor.pri) - # install target.path = $$[QT_INSTALL_EXAMPLES]/animation/stickman sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS stickman.pro diff --git a/examples/animation/sub-attaq/boat.cpp b/examples/animation/sub-attaq/boat.cpp index d286be5..68e646e 100644 --- a/examples/animation/sub-attaq/boat.cpp +++ b/examples/animation/sub-attaq/boat.cpp @@ -142,14 +142,14 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) //We setup the state machien of the boat machine = new QStateMachine(this); - QState *moving = new QState(machine->rootState()); + QState *moving = new QState(machine); StopState *stopState = new StopState(this, moving); machine->setInitialState(moving); moving->setInitialState(stopState); MoveStateRight *moveStateRight = new MoveStateRight(this, moving); MoveStateLeft *moveStateLeft = new MoveStateLeft(this, moving); - LaunchStateRight *launchStateRight = new LaunchStateRight(this, machine->rootState()); - LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this, machine->rootState()); + LaunchStateRight *launchStateRight = new LaunchStateRight(this, machine); + LaunchStateLeft *launchStateLeft = new LaunchStateLeft(this, machine); //then setup the transitions for the rightMove state KeyStopTransition *leftStopRight = new KeyStopTransition(this, QEvent::KeyPress, Qt::Key_Left); @@ -216,10 +216,10 @@ Boat::Boat(QGraphicsItem * parent, Qt::WindowFlags wFlags) launchStateLeft->addTransition(historyState); launchStateRight->addTransition(historyState); - QFinalState *final = new QFinalState(machine->rootState()); + QFinalState *final = new QFinalState(machine); //This state play the destroyed animation - QAnimationState *destroyedState = new QAnimationState(machine->rootState()); + QAnimationState *destroyedState = new QAnimationState(machine); destroyedState->setAnimation(destroyAnimation); //Play a nice animation when the boat is destroyed diff --git a/examples/animation/sub-attaq/bomb.cpp b/examples/animation/sub-attaq/bomb.cpp index 454970a..e92a723 100644 --- a/examples/animation/sub-attaq/bomb.cpp +++ b/examples/animation/sub-attaq/bomb.cpp @@ -85,11 +85,11 @@ void Bomb::launch(Bomb::Direction direction) QStateMachine *machine = new QStateMachine(this); //This state is when the launch animation is playing - QAnimationState *launched = new QAnimationState(machine->rootState()); + QAnimationState *launched = new QAnimationState(machine); launched->setAnimation(launchAnimation); //End - QFinalState *final = new QFinalState(machine->rootState()); + QFinalState *final = new QFinalState(machine); machine->setInitialState(launched); diff --git a/examples/animation/sub-attaq/graphicsscene.cpp b/examples/animation/sub-attaq/graphicsscene.cpp index bd37ce2..fcbc1b3 100644 --- a/examples/animation/sub-attaq/graphicsscene.cpp +++ b/examples/animation/sub-attaq/graphicsscene.cpp @@ -230,17 +230,17 @@ void GraphicsScene::setupScene(const QList<QAction *> &actions) QStateMachine *machine = new QStateMachine(this); //This state is when the player is playing - PlayState *gameState = new PlayState(this,machine->rootState()); + PlayState *gameState = new PlayState(this,machine); //Final state - QFinalState *final = new QFinalState(machine->rootState()); + QFinalState *final = new QFinalState(machine); //Animation when the player enter in the game - QAnimationState *lettersMovingState = new QAnimationState(machine->rootState()); + QAnimationState *lettersMovingState = new QAnimationState(machine); lettersMovingState->setAnimation(lettersGroupMoving); //Animation when the welcome screen disappear - QAnimationState *lettersFadingState = new QAnimationState(machine->rootState()); + QAnimationState *lettersFadingState = new QAnimationState(machine); lettersFadingState->setAnimation(lettersGroupFading); //if new game then we fade out the welcome screen and start playing diff --git a/examples/animation/sub-attaq/states.cpp b/examples/animation/sub-attaq/states.cpp index 81fd2de..d63737f 100644 --- a/examples/animation/sub-attaq/states.cpp +++ b/examples/animation/sub-attaq/states.cpp @@ -83,7 +83,7 @@ void PlayState::onEntry(QEvent *) machine = new QStateMachine(this); //This state is when player is playing - LevelState *levelState = new LevelState(scene, this, machine->rootState()); + LevelState *levelState = new LevelState(scene, this, machine); //This state is when the player is actually playing but the game is not paused QState *playingState = new QState(levelState); @@ -105,10 +105,10 @@ void PlayState::onEntry(QEvent *) pauseState->addTransition(pressPpause); //This state is when player have lost - LostState *lostState = new LostState(scene, this, machine->rootState()); + LostState *lostState = new LostState(scene, this, machine); //This state is when player have won - WinState *winState = new WinState(scene, this, machine->rootState()); + WinState *winState = new WinState(scene, this, machine); //The boat has been destroyed then the game is finished levelState->addTransition(scene->boat, SIGNAL(boatExecutionFinished()),lostState); @@ -136,7 +136,7 @@ void PlayState::onEntry(QEvent *) machine->setInitialState(levelState); //Final state - QFinalState *final = new QFinalState(machine->rootState()); + QFinalState *final = new QFinalState(machine); //This transition is triggered when the player press space after completing a level CustomSpaceTransition *spaceTransition = new CustomSpaceTransition(scene->views().at(0), this, QEvent::KeyPress, Qt::Key_Space); diff --git a/examples/animation/sub-attaq/submarine.cpp b/examples/animation/sub-attaq/submarine.cpp index 04b7916..78a9539 100644 --- a/examples/animation/sub-attaq/submarine.cpp +++ b/examples/animation/sub-attaq/submarine.cpp @@ -115,7 +115,7 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * QStateMachine *machine = new QStateMachine(this); //This state is when the boat is moving/rotating - QState *moving = new QState(machine->rootState()); + QState *moving = new QState(machine); //This state is when the boat is moving from left to right MovementState *movement = new MovementState(this, moving); @@ -132,7 +132,7 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * machine->setInitialState(moving); //End - QFinalState *final = new QFinalState(machine->rootState()); + QFinalState *final = new QFinalState(machine); //If the moving animation is finished we move to the return state movement->addTransition(movement, SIGNAL(animationFinished()), rotation); @@ -141,7 +141,7 @@ SubMarine::SubMarine(int type, const QString &name, int points, QGraphicsItem * rotation->addTransition(rotation, SIGNAL(animationFinished()), movement); //This state play the destroyed animation - QAnimationState *destroyedState = new QAnimationState(machine->rootState()); + QAnimationState *destroyedState = new QAnimationState(machine); destroyedState->setAnimation(setupDestroyAnimation(this)); //Play a nice animation when the submarine is destroyed diff --git a/examples/animation/sub-attaq/torpedo.cpp b/examples/animation/sub-attaq/torpedo.cpp index 5ef237a..fe79488 100644 --- a/examples/animation/sub-attaq/torpedo.cpp +++ b/examples/animation/sub-attaq/torpedo.cpp @@ -74,11 +74,11 @@ void Torpedo::launch() QStateMachine *machine = new QStateMachine(this); //This state is when the launch animation is playing - QAnimationState *launched = new QAnimationState(machine->rootState()); + QAnimationState *launched = new QAnimationState(machine); launched->setAnimation(launchAnimation); //End - QFinalState *final = new QFinalState(machine->rootState()); + QFinalState *final = new QFinalState(machine); machine->setInitialState(launched); diff --git a/examples/graphicsview/customshader/blureffect.cpp b/examples/graphicsview/customshader/blureffect.cpp new file mode 100644 index 0000000..43791c6 --- /dev/null +++ b/examples/graphicsview/customshader/blureffect.cpp @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blureffect.h" + +#include <QDebug> + +BlurEffect::BlurEffect(QGraphicsItem *item) + : QGraphicsBlurEffect() + , m_baseLine(200), item(item) +{ +} + +void BlurEffect::adjustForItem() +{ + qreal y = m_baseLine - item->pos().y(); + qreal radius = qBound(0.0, y / 32, 16.0); + setBlurRadius(radius); +} + +QRectF BlurEffect::boundingRect() const +{ + const_cast<BlurEffect *>(this)->adjustForItem(); + return QGraphicsBlurEffect::boundingRect(); +} + +void BlurEffect::draw(QPainter *painter) +{ + adjustForItem(); + QGraphicsBlurEffect::draw(painter); +} diff --git a/examples/graphicsview/customshader/blureffect.h b/examples/graphicsview/customshader/blureffect.h new file mode 100644 index 0000000..2aea8bf --- /dev/null +++ b/examples/graphicsview/customshader/blureffect.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLUREFFECT_H +#define BLUREFFECT_H + +#include <QGraphicsEffect> +#include <QGraphicsItem> + +class BlurEffect: public QGraphicsBlurEffect +{ +public: + BlurEffect(QGraphicsItem *item); + + void setBaseLine(qreal y) { m_baseLine = y; } + + QRectF boundingRect() const; + + void draw(QPainter *painter); + +private: + void adjustForItem(); + +private: + qreal m_baseLine; + QGraphicsItem *item; +}; + +#endif // BLUREFFECT_H diff --git a/examples/graphicsview/customshader/blurpicker.cpp b/examples/graphicsview/customshader/blurpicker.cpp new file mode 100644 index 0000000..de80312 --- /dev/null +++ b/examples/graphicsview/customshader/blurpicker.cpp @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "blurpicker.h" + +#include <QtGui> + +#include "blureffect.h" +#include "customshadereffect.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0) +{ + setBackgroundBrush(QPixmap(":/images/background.jpg")); + setScene(&m_scene); + + setupScene(); + updateIconPositions(); + + connect(&m_timeLine, SIGNAL(valueChanged(qreal)), SLOT(updateIconPositions())); + m_timeLine.setDuration(400); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +void BlurPicker::updateIconPositions() +{ + m_index = m_timeLine.currentFrame() / 1000.0; + + qreal baseline = 0; + for (int i = 0; i < m_icons.count(); ++i) { + QGraphicsItem *icon = m_icons[i]; + qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count(); + qreal xs = 170 * sin(a); + qreal ys = 100 * cos(a); + QPointF pos(xs, ys); + pos = QTransform().rotate(-20).map(pos); + pos -= QPointF(40, 40); + icon->setPos(pos); + baseline = qMax(baseline, ys); + if (i != 3) + static_cast<BlurEffect *>(icon->graphicsEffect())->setBaseLine(baseline); + } + + m_scene.update(); +} + +void BlurPicker::setupScene() +{ + m_scene.setSceneRect(-200, -120, 400, 240); + + QStringList names; + names << ":/images/accessories-calculator.png"; + names << ":/images/accessories-text-editor.png"; + names << ":/images/help-browser.png"; + names << ":/images/internet-group-chat.png"; + names << ":/images/internet-mail.png"; + names << ":/images/internet-web-browser.png"; + names << ":/images/office-calendar.png"; + names << ":/images/system-users.png"; + + for (int i = 0; i < names.count(); i++) { + QPixmap pixmap(names[i]); + QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap); + icon->setZValue(1); + if (i == 3) + icon->setGraphicsEffect(new CustomShaderEffect()); + else + icon->setGraphicsEffect(new BlurEffect(icon)); + m_icons << icon; + } + + QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/images/background.jpg")); + bg->setZValue(0); + bg->setPos(-200, -150); +} + +void BlurPicker::keyPressEvent(QKeyEvent *event) +{ + if (event->key() == Qt::Key_Left) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 - 1000); + m_timeLine.start(); + event->accept(); + } + } + + if (event->key() == Qt::Key_Right) { + if (m_timeLine.state() == QTimeLine::NotRunning) { + m_timeLine.setFrameRange(m_index * 1000, m_index * 1000 + 1000); + m_timeLine.start(); + event->accept(); + } + } +} diff --git a/examples/graphicsview/customshader/blurpicker.h b/examples/graphicsview/customshader/blurpicker.h new file mode 100644 index 0000000..b7ea3b4 --- /dev/null +++ b/examples/graphicsview/customshader/blurpicker.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef BLURPICKER_H +#define BLURPICKER_H + +#include <QGraphicsEffect> +#include <QGraphicsView> +#include <QTimeLine> + +#include "blureffect.h" + +class BlurPicker: public QGraphicsView +{ + Q_OBJECT + +public: + BlurPicker(QWidget *parent = 0); + +protected: + void keyPressEvent(QKeyEvent *event); + +private slots: + void updateIconPositions(); + +private: + void setupScene(); + +private: + qreal m_index; + QGraphicsScene m_scene; + QList<QGraphicsItem*> m_icons; + QTimeLine m_timeLine; +}; + +#endif // BLURPICKER_H diff --git a/examples/graphicsview/customshader/blurpicker.qrc b/examples/graphicsview/customshader/blurpicker.qrc new file mode 100644 index 0000000..e88eaca --- /dev/null +++ b/examples/graphicsview/customshader/blurpicker.qrc @@ -0,0 +1,14 @@ +<RCC> + <qresource prefix="/" > + <file>images/background.jpg</file> + <file>images/accessories-calculator.png</file> + <file>images/accessories-text-editor.png</file> + <file>images/help-browser.png</file> + <file>images/internet-group-chat.png</file> + <file>images/internet-mail.png</file> + <file>images/internet-web-browser.png</file> + <file>images/office-calendar.png</file> + <file>images/system-users.png</file> + </qresource> +</RCC> + diff --git a/examples/graphicsview/customshader/customshader.pro b/examples/graphicsview/customshader/customshader.pro new file mode 100644 index 0000000..bc07d7a --- /dev/null +++ b/examples/graphicsview/customshader/customshader.pro @@ -0,0 +1,10 @@ +SOURCES += main.cpp blurpicker.cpp blureffect.cpp customshadereffect.cpp +HEADERS += blurpicker.h blureffect.h customshadereffect.h +RESOURCES += blurpicker.qrc +QT += opengl + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS blurpicker.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/graphicsview/blurpicker +INSTALLS += target sources diff --git a/examples/graphicsview/customshader/customshadereffect.cpp b/examples/graphicsview/customshader/customshadereffect.cpp new file mode 100644 index 0000000..293123c --- /dev/null +++ b/examples/graphicsview/customshader/customshadereffect.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "customshadereffect.h" +#include <QGLShaderProgram> + +static char const colorizeShaderCode[] = + "varying highp vec2 textureCoords;\n" + "uniform sampler2D imageTexture;\n" + "uniform lowp vec4 effectColor;\n" + "lowp vec4 srcPixel() {\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" + " return vec4(colorize.rgb, src.a);\n" + "}"; + +CustomShaderEffect::CustomShaderEffect() + : QGraphicsShaderEffect(), + color(Qt::red) +{ + setPixelShaderFragment(colorizeShaderCode); +} + +void CustomShaderEffect::setEffectColor(const QColor& c) +{ + color = c; + setUniformsDirty(); +} + +void CustomShaderEffect::setUniforms(QGLShaderProgram *program) +{ + program->setUniformValue("effectColor", color); +} diff --git a/examples/graphicsview/customshader/customshadereffect.h b/examples/graphicsview/customshader/customshadereffect.h new file mode 100644 index 0000000..6482bd5 --- /dev/null +++ b/examples/graphicsview/customshader/customshadereffect.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CUSTOMSHADEREFFECT_H +#define CUSTOMSHADEREFFECT_H + +#include <QGraphicsEffect> +#include <QGraphicsShaderEffect> +#include <QGraphicsItem> + +class CustomShaderEffect: public QGraphicsShaderEffect +{ +public: + CustomShaderEffect(); + + QColor effectColor() const { return color; } + void setEffectColor(const QColor& c); + +protected: + void setUniforms(QGLShaderProgram *program); + +private: + QColor color; +}; + +#endif // CUSTOMSHADEREFFECT_H diff --git a/examples/animation/stickman/editor/mainwindow.h b/examples/graphicsview/customshader/main.cpp index ef122d9..b88a51d 100644 --- a/examples/animation/stickman/editor/mainwindow.h +++ b/examples/graphicsview/customshader/main.cpp @@ -1,9 +1,9 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Nokia Corporation (qt-info@nokia.com) +** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the QtCore module of the Qt Toolkit. +** This file is part of the examples of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -34,25 +34,22 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://www.qtsoftware.com/contact. +** contact the sales department at qt-sales@nokia.com. ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H +#include "blurpicker.h" +#include <QApplication> -#include <QMainWindow> - -class StickMan; -class MainWindow: public QMainWindow +int main(int argc, char **argv) { -public: - MainWindow(StickMan *stickMan); - ~MainWindow(); + QApplication app(argc, argv); -private: - void initActions(StickMan *stickMan); -}; + BlurPicker blurPicker; + blurPicker.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Application Picker")); + blurPicker.setFixedSize(400, 300); + blurPicker.show(); -#endif + return app.exec(); +} diff --git a/examples/graphicsview/graphicsview.pro b/examples/graphicsview/graphicsview.pro index 185c856..4dd0b13 100644 --- a/examples/graphicsview/graphicsview.pro +++ b/examples/graphicsview/graphicsview.pro @@ -12,6 +12,7 @@ SUBDIRS = \ contains(QT_CONFIG, qt3support):SUBDIRS += portedcanvas portedasteroids contains(DEFINES, QT_NO_CURSOR): SUBDIRS -= dragdroprobot +contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2):SUBDIRS += customshader # install target.path = $$[QT_INSTALL_EXAMPLES]/graphicsview diff --git a/examples/statemachine/factorial/main.cpp b/examples/statemachine/factorial/main.cpp index 18a9521..5050347 100644 --- a/examples/statemachine/factorial/main.cpp +++ b/examples/statemachine/factorial/main.cpp @@ -151,14 +151,14 @@ int main(int argc, char **argv) //! [3] //! [4] - QState *compute = new QState(machine.rootState()); + QState *compute = new QState(&machine); compute->assignProperty(&factorial, "fac", 1); compute->assignProperty(&factorial, "x", 6); compute->addTransition(new FactorialLoopTransition(&factorial)); //! [4] //! [5] - QFinalState *done = new QFinalState(machine.rootState()); + QFinalState *done = new QFinalState(&machine); FactorialDoneTransition *doneTransition = new FactorialDoneTransition(&factorial); doneTransition->setTargetState(done); compute->addTransition(doneTransition); diff --git a/examples/statemachine/tankgame/mainwindow.cpp b/examples/statemachine/tankgame/mainwindow.cpp index 68a8d68..596cdfe 100644 --- a/examples/statemachine/tankgame/mainwindow.cpp +++ b/examples/statemachine/tankgame/mainwindow.cpp @@ -160,7 +160,7 @@ void MainWindow::init() connect(quitAction, SIGNAL(triggered()), this, SLOT(close())); m_machine = new QStateMachine(this); - QState *stoppedState = new QState(m_machine->rootState()); + QState *stoppedState = new QState(m_machine); stoppedState->setObjectName("stoppedState"); stoppedState->assignProperty(runGameAction, "enabled", true); stoppedState->assignProperty(stopGameAction, "enabled", false); @@ -188,14 +188,14 @@ void MainWindow::init() stoppedState->setInitialState(hs); //! [0] - m_runningState = new QState(QState::ParallelStates, m_machine->rootState()); + m_runningState = new QState(QState::ParallelStates, m_machine); //! [0] m_runningState->setObjectName("runningState"); m_runningState->assignProperty(addTankAction, "enabled", false); m_runningState->assignProperty(runGameAction, "enabled", false); m_runningState->assignProperty(stopGameAction, "enabled", true); - QState *gameOverState = new QState(m_machine->rootState()); + QState *gameOverState = new QState(m_machine); gameOverState->setObjectName("gameOverState"); gameOverState->assignProperty(stopGameAction, "enabled", false); connect(gameOverState, SIGNAL(entered()), this, SLOT(gameOver())); diff --git a/mkspecs/features/moc.prf b/mkspecs/features/moc.prf index 299feda..c5af298 100644 --- a/mkspecs/features/moc.prf +++ b/mkspecs/features/moc.prf @@ -62,7 +62,7 @@ moc_header.output = $$MOC_DIR/$${QMAKE_H_MOD_MOC}${QMAKE_FILE_BASE}$${first(QMAK moc_header.input = HEADERS moc_header.variable_out = SOURCES moc_header.name = MOC ${QMAKE_FILE_IN} -if(!contains(TEMPLATE, "vc.*") & !contains(TEMPLATE_PREFIX, "vc")) { +if(!contains(TEMPLATE, "vc.*"):!contains(TEMPLATE_PREFIX, "vc")) { !isEmpty(INCLUDETEMP):moc_header.depends += $$INCLUDETEMP } silent:moc_header.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_header.commands @@ -76,7 +76,7 @@ moc_source.commands = ${QMAKE_FUNC_mocCmd} moc_source.output = $$MOC_DIR/$${QMAKE_CPP_MOD_MOC}${QMAKE_FILE_BASE}$${QMAKE_EXT_CPP_MOC} moc_source.input = SOURCES OBJECTIVE_SOURCES moc_source.name = MOC ${QMAKE_FILE_IN} -if(!contains(TEMPLATE, "vc.*") & !contains(TEMPLATE_PREFIX, "vc")) { +if(!contains(TEMPLATE, "vc.*"):!contains(TEMPLATE_PREFIX, "vc")) { !isEmpty(INCLUDETEMP):moc_source.depends += $$INCLUDETEMP } silent:moc_source.commands = @echo moc ${QMAKE_FILE_IN} && $$moc_source.commands diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebdatabase.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebdatabase.cpp index 7e85eaa..0d11381 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebdatabase.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebdatabase.cpp @@ -34,9 +34,20 @@ using namespace WebCore; \brief The QWebDatabase class provides access to HTML 5 databases created with JavaScript. The upcoming HTML 5 standard includes support for SQL databases that web sites can create and - access on a local computer through JavaScript. QWebDatabase is the C++ interface to these databases. + access on a local computer through JavaScript. QWebDatabase is the C++ interface to these + databases. - For more information refer to the \l{http://www.w3.org/html/wg/html5/#sql}{HTML 5 Draft Standard}. + To get access to all databases defined by a security origin, use QWebSecurityOrigin::databases(). + Each database has an internal name(), as well as a user-friendly name, provided by displayName(). + + WebKit uses SQLite to create and access the local SQL databases. The location of the database + file in the local file system is returned by fileName(). You can access the database directly + through the QtSql database module. + + For each database the web site can define an expectedSize(). The current size of the database + in bytes is returned by size(). + + For more information refer to the \l{http://dev.w3.org/html5/webdatabase/}{HTML 5 Draft Standard}. \sa QWebSecurityOrigin */ @@ -127,7 +138,7 @@ QWebDatabase::QWebDatabase(QWebDatabasePrivate* priv) \endcode \note Concurrent access to a database from multiple threads or processes - is not very efficient because Sqlite is used as WebKit's database backend. + is not very efficient because SQLite is used as WebKit's database backend. */ QString QWebDatabase::fileName() const { @@ -149,8 +160,8 @@ QWebSecurityOrigin QWebDatabase::origin() const } /*! - Removes the database \a db from its security origin. All data stored in this database - will be destroyed. + Removes the database \a db from its security origin. All data stored in the + database \a db will be destroyed. */ void QWebDatabase::removeDatabase(const QWebDatabase &db) { diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebsecurityorigin.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebsecurityorigin.cpp index da9278c..d2eaf10 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qwebsecurityorigin.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebsecurityorigin.cpp @@ -36,10 +36,9 @@ using namespace WebCore; \brief The QWebSecurityOrigin class defines a security boundary for web sites. QWebSecurityOrigin provides access to the security domains defined by web sites. - An origin consists of a host name, a scheme, and a port number. Web sites with the same - security origin can access each other's resources for client-side scripting or databases. - - ### diagram + An origin consists of a host name, a scheme, and a port number. Web sites + with the same security origin can access each other's resources for client-side + scripting or databases. For example the site \c{http://www.example.com/my/page.html} is allowed to share the same database as \c{http://www.example.com/my/overview.html}, or access each other's @@ -47,7 +46,13 @@ using namespace WebCore; \c{http://www.malicious.com/evil.html} from accessing \c{http://www.example.com/}'s resources, because they are of a different security origin. - QWebSecurity also provides access to all databases defined within a security origin. + Call QWebFrame::securityOrigin() to get the QWebSecurityOrigin for a frame in a + web page, and use host(), scheme() and port() to identify the security origin. + + Use databases() to access the databases defined within a security origin. The + disk usage of the origin's databases can be limited with setDatabaseQuota(). + databaseQuota() and databaseUsage() report the current limit as well as the + current usage. For more information refer to the \l{http://en.wikipedia.org/wiki/Same_origin_policy}{"Same origin policy" Wikipedia Article}. diff --git a/src/corelib/arch/qatomic_powerpc.h b/src/corelib/arch/qatomic_powerpc.h index ea3f458..c3b31f9 100644 --- a/src/corelib/arch/qatomic_powerpc.h +++ b/src/corelib/arch/qatomic_powerpc.h @@ -101,8 +101,6 @@ template <typename T> Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() { return false; } -QT_BEGIN_NAMESPACE - #if defined(Q_CC_GNU) #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2) \ diff --git a/src/corelib/concurrent/qfuture.h b/src/corelib/concurrent/qfuture.h index 47015ee..f2db5ac 100644 --- a/src/corelib/concurrent/qfuture.h +++ b/src/corelib/concurrent/qfuture.h @@ -210,7 +210,7 @@ public: bool operator==(const QFuture &other) const { return (d == other.d); } bool operator!=(const QFuture &other) const { return (d != other.d); } -#ifndef QT_NO_MEMBER_TEMPLATES +#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(Q_CC_XLC) template <typename T> QFuture(const QFuture<T> &other) : d(other.d) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 0ef48fa..7b16dff 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -665,7 +665,8 @@ namespace QT_NAMESPACE {} # define Q_ALIGNOF(type) __alignof__(type) # define Q_TYPEOF(expr) __typeof__(expr) # define Q_DECL_ALIGN(n) __attribute__((__aligned__(n))) -# define Q_DECL_EXPORT __attribute__((__visibility__("default"))) +// using CC 5.9: Warning: attribute visibility is unsupported and will be skipped.. +//# define Q_DECL_EXPORT __attribute__((__visibility__("default"))) # endif # if !defined(_BOOL) # define Q_NO_BOOL_TYPE @@ -2407,28 +2408,15 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_QFUTURE #endif -/* - Turn off certain features for compilers that have problems parsing - the code. -*/ -#if (defined(Q_CC_HPACC) && defined(QT_ARCH_PARISC)) \ - || defined(Q_CC_MIPS) \ - || defined(Q_CC_XLC) -// HP aCC A.03.*, MIPSpro, and xlC cannot handle -// the template function declarations for the QtConcurrent functions -# define QT_NO_QFUTURE -# define QT_NO_CONCURRENT -#endif - -// MSVC 6.0, MSVC .NET 2002, and old versions of Sun CC can`t handle the map(), etc templates, +// MSVC 6.0 and MSVC .NET 2002, can`t handle the map(), etc templates, // but the QFuture class compiles. -#if (defined(Q_CC_MSVC) && _MSC_VER <= 1300) || (defined (__SUNPRO_CC) && __SUNPRO_CC <= 0x590) +#if (defined(Q_CC_MSVC) && _MSC_VER <= 1300) # define QT_NO_CONCURRENT #endif -// Mingw uses a gcc 3 version which has problems with some of the -// map/filter overloads. So does IRIX and Solaris. -#if (defined(Q_OS_IRIX) || defined(Q_CC_MINGW) || defined (Q_OS_SOLARIS)) && (__GNUC__ < 4) +// gcc 3 version has problems with some of the +// map/filter overloads. +#if defined(Q_CC_GNU) && (__GNUC__ < 4) # define QT_NO_CONCURRENT_MAP # define QT_NO_CONCURRENT_FILTER #endif diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 93097bc..9eb3305 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -42,7 +42,7 @@ #include "qabstractfileengine.h" #include "private/qabstractfileengine_p.h" #include "qdatetime.h" -#include "qmutex.h" +#include "qreadwritelock.h" #include "qvariant.h" // built-in handlers #include "qfsfileengine.h" @@ -98,14 +98,14 @@ QT_BEGIN_NAMESPACE All application-wide handlers are stored in this list. The mutex must be acquired to ensure thread safety. */ -Q_GLOBAL_STATIC_WITH_ARGS(QMutex, fileEngineHandlerMutex, (QMutex::Recursive)) +Q_GLOBAL_STATIC_WITH_ARGS(QReadWriteLock, fileEngineHandlerMutex, (QReadWriteLock::Recursive)) static bool qt_abstractfileenginehandlerlist_shutDown = false; class QAbstractFileEngineHandlerList : public QList<QAbstractFileEngineHandler *> { public: ~QAbstractFileEngineHandlerList() { - QMutexLocker locker(fileEngineHandlerMutex()); + QWriteLocker locker(fileEngineHandlerMutex()); qt_abstractfileenginehandlerlist_shutDown = true; } }; @@ -122,7 +122,7 @@ Q_GLOBAL_STATIC(QAbstractFileEngineHandlerList, fileEngineHandlers) */ QAbstractFileEngineHandler::QAbstractFileEngineHandler() { - QMutexLocker locker(fileEngineHandlerMutex()); + QWriteLocker locker(fileEngineHandlerMutex()); fileEngineHandlers()->prepend(this); } @@ -132,7 +132,7 @@ QAbstractFileEngineHandler::QAbstractFileEngineHandler() */ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() { - QMutexLocker locker(fileEngineHandlerMutex()); + QWriteLocker locker(fileEngineHandlerMutex()); // Remove this handler from the handler list only if the list is valid. if (!qt_abstractfileenginehandlerlist_shutDown) fileEngineHandlers()->removeAll(this); @@ -166,12 +166,14 @@ QAbstractFileEngineHandler::~QAbstractFileEngineHandler() */ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName) { - QMutexLocker locker(fileEngineHandlerMutex()); + { + QReadLocker locker(fileEngineHandlerMutex()); - // check for registered handlers that can load the file - for (int i = 0; i < fileEngineHandlers()->size(); i++) { - if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName)) - return ret; + // check for registered handlers that can load the file + for (int i = 0; i < fileEngineHandlers()->size(); i++) { + if (QAbstractFileEngine *ret = fileEngineHandlers()->at(i)->create(fileName)) + return ret; + } } #ifdef QT_BUILD_CORE_LIB diff --git a/src/corelib/io/qdiriterator.cpp b/src/corelib/io/qdiriterator.cpp index c9c80bb..3bfea65 100644 --- a/src/corelib/io/qdiriterator.cpp +++ b/src/corelib/io/qdiriterator.cpp @@ -106,25 +106,29 @@ public: QDir::Filters filters, QDirIterator::IteratorFlags flags); ~QDirIteratorPrivate(); - void pushSubDirectory(const QFileInfo &fileInfo, const QStringList &nameFilters, - QDir::Filters filters); void advance(); - bool shouldFollowDirectory(const QFileInfo &); + + void pushDirectory(const QFileInfo &fileInfo); + void checkAndPushDirectory(const QFileInfo &); bool matchesFilters(const QString &fileName, const QFileInfo &fi) const; - QSet<QString> visitedLinks; - QAbstractFileEngine *engine; + QAbstractFileEngine * const engine; + + const QString path; + const QStringList nameFilters; + const QDir::Filters filters; + const QDirIterator::IteratorFlags iteratorFlags; + +#ifndef QT_NO_REGEXP + QVector<QRegExp> nameRegExps; +#endif + QStack<QAbstractFileEngineIterator *> fileEngineIterators; - QString path; - QFileInfo nextFileInfo; - //This fileinfo is the current that we will return from the public API QFileInfo currentFileInfo; - QDirIterator::IteratorFlags iteratorFlags; - QDir::Filters filters; - QStringList nameFilters; - bool followNextDir; - bool first; - bool done; + QFileInfo nextFileInfo; + + // Loop protection + QSet<QString> visitedLinks; QDirIterator *q; }; @@ -134,14 +138,24 @@ public: */ QDirIteratorPrivate::QDirIteratorPrivate(const QString &path, const QStringList &nameFilters, QDir::Filters filters, QDirIterator::IteratorFlags flags) - : engine(0), path(path), nextFileInfo(path), iteratorFlags(flags), followNextDir(false), first(true), done(false) + : engine(QAbstractFileEngine::create(path)) + , path(path) + , nameFilters(nameFilters.contains(QLatin1String("*")) ? QStringList() : nameFilters) + , filters(QDir::NoFilter == filters ? QDir::AllEntries : filters) + , iteratorFlags(flags) { - if (filters == QDir::NoFilter) - filters = QDir::AllEntries; - this->filters = filters; - this->nameFilters = nameFilters; +#ifndef QT_NO_REGEXP + nameRegExps.reserve(nameFilters.size()); + for (int i = 0; i < nameFilters.size(); ++i) + nameRegExps.append( + QRegExp(nameFilters.at(i), + (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, + QRegExp::Wildcard)); +#endif - pushSubDirectory(nextFileInfo, nameFilters, filters); + // Populate fields for hasNext() and next() + pushDirectory(QFileInfo(path)); + advance(); } /*! @@ -155,8 +169,7 @@ QDirIteratorPrivate::~QDirIteratorPrivate() /*! \internal */ -void QDirIteratorPrivate::pushSubDirectory(const QFileInfo &fileInfo, const QStringList &nameFilters, - QDir::Filters filters) +void QDirIteratorPrivate::pushDirectory(const QFileInfo &fileInfo) { QString path = fileInfo.filePath(); @@ -168,7 +181,7 @@ void QDirIteratorPrivate::pushSubDirectory(const QFileInfo &fileInfo, const QStr if (iteratorFlags & QDirIterator::FollowSymlinks) visitedLinks << fileInfo.canonicalFilePath(); - if (engine || (engine = QAbstractFileEngine::create(this->path))) { + if (engine) { engine->setFileName(path); QAbstractFileEngineIterator *it = engine->beginEntryList(filters, nameFilters); if (it) { @@ -185,71 +198,63 @@ void QDirIteratorPrivate::pushSubDirectory(const QFileInfo &fileInfo, const QStr */ void QDirIteratorPrivate::advance() { - // Advance to the next entry - if (followNextDir) { - // Start by navigating into the current directory. - QAbstractFileEngineIterator *it = fileEngineIterators.top(); - pushSubDirectory(it->currentFileInfo(), it->nameFilters(), it->filters()); - followNextDir = false; - } - while (!fileEngineIterators.isEmpty()) { - QAbstractFileEngineIterator *it = fileEngineIterators.top(); // Find the next valid iterator that matches the filters. - bool foundDirectory = false; - while (it->hasNext()) { + while (fileEngineIterators.top()->hasNext()) { + QAbstractFileEngineIterator *it = fileEngineIterators.top(); it->next(); + const QFileInfo info = it->currentFileInfo(); + checkAndPushDirectory(it->currentFileInfo()); + if (matchesFilters(it->currentFileName(), info)) { currentFileInfo = nextFileInfo; nextFileInfo = info; - // Signal that we want to follow this entry. - followNextDir = shouldFollowDirectory(nextFileInfo); + //We found a matching entry. return; - - } else if (shouldFollowDirectory(info)) { - pushSubDirectory(info, it->nameFilters(), it->filters()); - foundDirectory = true; - break; } } - if (!foundDirectory) - delete fileEngineIterators.pop(); + + delete fileEngineIterators.pop(); } + currentFileInfo = nextFileInfo; - done = true; + nextFileInfo = QFileInfo(); } /*! \internal */ -bool QDirIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo) +void QDirIteratorPrivate::checkAndPushDirectory(const QFileInfo &fileInfo) { // If we're doing flat iteration, we're done. if (!(iteratorFlags & QDirIterator::Subdirectories)) - return false; + return; // Never follow non-directory entries if (!fileInfo.isDir()) - return false; + return; + + // Follow symlinks only when asked + if (!(iteratorFlags & QDirIterator::FollowSymlinks) && fileInfo.isSymLink()) + return; // Never follow . and .. - if (fileInfo.fileName() == QLatin1String(".") || fileInfo.fileName() == QLatin1String("..")) - return false; + QString fileName = fileInfo.fileName(); + if (QLatin1String(".") == fileName || QLatin1String("..") == fileName) + return; - // Check symlinks - if (fileInfo.isSymLink() && !(iteratorFlags & QDirIterator::FollowSymlinks)) { - // Follow symlinks only if FollowSymlinks was passed - return false; - } + // No hidden directories unless requested + if (!(filters & QDir::AllDirs) && !(filters & QDir::Hidden) && fileInfo.isHidden()) + return; // Stop link loops if (visitedLinks.contains(fileInfo.canonicalFilePath())) - return false; + return; - return true; + pushDirectory(fileInfo); } /*! @@ -264,10 +269,7 @@ bool QDirIteratorPrivate::shouldFollowDirectory(const QFileInfo &fileInfo) */ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInfo &fi) const { - if (fileName.isEmpty()) { - // invalid entry - return false; - } + Q_ASSERT(!fileName.isEmpty()); // filter . and ..? const int fileNameSize = fileName.size(); @@ -278,16 +280,15 @@ bool QDirIteratorPrivate::matchesFilters(const QString &fileName, const QFileInf return false; // name filter -#ifndef QT_NO_REGEXP - const bool hasNameFilters = !nameFilters.isEmpty() && !(nameFilters.contains(QLatin1String("*"))); +#ifndef QT_NO_REGEXP // Pass all entries through name filters, except dirs if the AllDirs - if (hasNameFilters && !((filters & QDir::AllDirs) && fi.isDir())) { + if (!nameFilters.isEmpty() && !((filters & QDir::AllDirs) && fi.isDir())) { bool matched = false; - for (int i = 0; i < nameFilters.size(); ++i) { - QRegExp regexp(nameFilters.at(i), - (filters & QDir::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, - QRegExp::Wildcard); - if (regexp.exactMatch(fileName)) { + for (QVector<QRegExp>::const_iterator iter = nameRegExps.constBegin(), + end = nameRegExps.constEnd(); + iter != end; ++iter) { + + if (iter->exactMatch(fileName)) { matched = true; break; } @@ -385,7 +386,7 @@ QDirIterator::QDirIterator(const QDir &dir, IteratorFlags flags) \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorFlags flags) - : d(new QDirIteratorPrivate(path, QStringList(QLatin1String("*")), filters, flags)) + : d(new QDirIteratorPrivate(path, QStringList(), filters, flags)) { d->q = this; } @@ -403,7 +404,7 @@ QDirIterator::QDirIterator(const QString &path, QDir::Filters filters, IteratorF \sa hasNext(), next(), IteratorFlags */ QDirIterator::QDirIterator(const QString &path, IteratorFlags flags) - : d(new QDirIteratorPrivate(path, QStringList(QLatin1String("*")), QDir::NoFilter, flags)) + : d(new QDirIteratorPrivate(path, QStringList(), QDir::NoFilter, flags)) { d->q = this; } @@ -452,8 +453,6 @@ QDirIterator::~QDirIterator() */ QString QDirIterator::next() { - if (!hasNext()) - return QString(); d->advance(); return filePath(); } @@ -466,11 +465,7 @@ QString QDirIterator::next() */ bool QDirIterator::hasNext() const { - if (d->first) { - d->first = false; - d->advance(); - } - return !d->done; + return !d->fileEngineIterators.isEmpty(); } /*! diff --git a/src/corelib/io/qresource_iterator.cpp b/src/corelib/io/qresource_iterator.cpp index e97ac59..11f4acf 100644 --- a/src/corelib/io/qresource_iterator.cpp +++ b/src/corelib/io/qresource_iterator.cpp @@ -73,13 +73,11 @@ bool QResourceFileEngineIterator::hasNext() const return false; // Initialize and move to the next entry. - QResourceFileEngineIterator *that = const_cast<QResourceFileEngineIterator *>(this); - that->entries = resource.children(); - if (!that->entries.isEmpty()) - that->index = 0; + entries = resource.children(); + index = 0; } - return index <= entries.size(); + return index < entries.size(); } QString QResourceFileEngineIterator::currentFileName() const diff --git a/src/corelib/io/qresource_iterator_p.h b/src/corelib/io/qresource_iterator_p.h index b5e8382..5165157 100644 --- a/src/corelib/io/qresource_iterator_p.h +++ b/src/corelib/io/qresource_iterator_p.h @@ -71,8 +71,8 @@ public: QString currentFileName() const; private: - QStringList entries; - int index; + mutable QStringList entries; + mutable int index; }; QT_END_NAMESPACE diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 180e9ec..79cd2f0 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -2336,12 +2336,12 @@ static const NameprepCaseFoldingEntry NameprepCaseFolding[] = { { 0x1D7BB, { 0x03C3, 0x0000, 0x0000, 0x0000 } } }; -static void mapToLowerCase(QString *str) +static void mapToLowerCase(QString *str, int from) { int N = sizeof(NameprepCaseFolding) / sizeof(NameprepCaseFolding[0]); QChar *d = 0; - for (int i = 0; i < str->size(); ++i) { + for (int i = from; i < str->size(); ++i) { int uc = str->at(i).unicode(); if (uc < 0x80) { if (uc <= 'Z' && uc >= 'A') { @@ -2388,11 +2388,11 @@ static bool isMappedToNothing(const QChar &ch) } -static void stripProhibitedOutput(QString *str) +static void stripProhibitedOutput(QString *str, int from) { - ushort *out = (ushort *)str->data(); + ushort *out = (ushort *)str->data() + from; const ushort *in = out; - const ushort *end = out + str->size(); + const ushort *end = (ushort *)str->data() + str->size(); while (in < end) { ushort uc = *in; if (uc < 0x80 || @@ -2901,66 +2901,99 @@ static bool isBidirectionalL(const QChar &ch) return false; } +#ifdef QT_BUILD_INTERNAL +// export for tst_qurl.cpp +Q_AUTOTEST_EXPORT void qt_nameprep(QString *source, int from); +Q_AUTOTEST_EXPORT bool qt_check_std3rules(const QChar *uc, int len); +#else +// non-test build, keep the symbols for ourselves +static void qt_nameprep(QString *source, int from); +static bool qt_check_std3rules(const QChar *uc, int len); +#endif -Q_AUTOTEST_EXPORT QString qt_nameprep(const QString &source) +void qt_nameprep(QString *source, int from) { - QString mapped = source; - - bool simple = true; - for (int i = 0; i < mapped.size(); ++i) { - ushort uc = mapped.at(i).unicode(); + QChar *src = source->data(); // causes a detach, so we're sure the only one using it + QChar *out = src + from; + const QChar *e = src + source->size(); + + for ( ; out < e; ++out) { + register ushort uc = out->unicode(); if (uc > 0x80) { - simple = false; break; } else if (uc >= 'A' && uc <= 'Z') { - mapped[i] = QChar(uc | 0x20); + *out = QChar(uc | 0x20); } } - if (simple) - return mapped; - + if (out == e) + return; // everything was mapped easily (lowercased, actually) + int firstNonAscii = out - src; + // Characters commonly mapped to nothing are simply removed // (Table B.1) - QChar *out = mapped.data(); const QChar *in = out; - const QChar *e = in + mapped.size(); while (in < e) { if (!isMappedToNothing(*in)) *out++ = *in; ++in; } if (out != in) - mapped.truncate(out - mapped.constData()); + source->truncate(out - src); // Map to lowercase (Table B.2) - mapToLowerCase(&mapped); + mapToLowerCase(source, firstNonAscii); // Normalize to Unicode 3.2 form KC - mapped = mapped.normalized(QString::NormalizationForm_KC, QChar::Unicode_3_2); + extern void qt_string_normalize(QString *data, QString::NormalizationForm mode, + QChar::UnicodeVersion version, int from); + qt_string_normalize(source, QString::NormalizationForm_KC, QChar::Unicode_3_2, firstNonAscii); // Strip prohibited output - stripProhibitedOutput(&mapped); + stripProhibitedOutput(source, firstNonAscii); // Check for valid bidirectional characters bool containsLCat = false; bool containsRandALCat = false; - for (int j = 0; j < mapped.size() && (!containsLCat || !containsRandALCat); ++j) { - if (isBidirectionalL(mapped.at(j))) + src = source->data(); + e = src + source->size(); + for (in = src + from; in < e && (!containsLCat || !containsRandALCat); ++in) { + if (isBidirectionalL(*in)) containsLCat = true; - else if (isBidirectionalRorAL(mapped.at(j))) + else if (isBidirectionalRorAL(*in)) containsRandALCat = true; } if (containsRandALCat) { - if (containsLCat || (!isBidirectionalRorAL(mapped.at(0)) - || !isBidirectionalRorAL(mapped.at(mapped.size() - 1)))) - mapped.clear(); + if (containsLCat || (!isBidirectionalRorAL(src[from]) + || !isBidirectionalRorAL(e[-1]))) + source->resize(from); // not allowed, clear the label } +} + +bool qt_check_std3rules(const QChar *uc, int len) +{ + if (len > 63) + return false; - return mapped; + for (int i = 0; i < len; ++i) { + register ushort c = uc[i].unicode(); + if (c == '-' && (i == 0 || i == len - 1)) + return false; + + // verifying the absence of LDH is the same as verifying that + // only LDH is present + if (c == '-' || (c >= '0' && c <= '9') + || (c >= 'A' && c <= 'Z') + || (c >= 'a' && c <= 'z')) + continue; + + return false; + } + + return true; } -static inline char encodeDigit(uint digit) +static inline uint encodeDigit(uint digit) { return digit + 22 + 75 * (digit < 26); } @@ -2977,7 +3010,7 @@ static inline uint adapt(uint delta, uint numpoints, bool firsttime) return k + (((base - tmin + 1) * delta) / (delta + skew)); } -static inline void appendEncode(QByteArray* output, uint& delta, uint& bias, uint& b, uint& h) +static inline void appendEncode(QString* output, uint& delta, uint& bias, uint& b, uint& h) { uint qq; uint k; @@ -2991,17 +3024,17 @@ static inline void appendEncode(QByteArray* output, uint& delta, uint& bias, uin t = (k <= bias) ? tmin : (k >= bias + tmax) ? tmax : k - bias; if (qq < t) break; - *output += encodeDigit(t + (qq - t) % (base - t)); + *output += QChar(encodeDigit(t + (qq - t) % (base - t))); qq = (qq - t) / (base - t); } - *output += encodeDigit(qq); + *output += QChar(encodeDigit(qq)); bias = adapt(delta, h + 1, h == b); delta = 0; ++h; } -static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) +static void toPunycodeHelper(const QChar *s, int ucLength, QString *output) { uint n = initial_n; uint delta = 0; @@ -3010,7 +3043,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) int outLen = output->length(); output->resize(outLen + ucLength); - char *d = output->data() + outLen; + QChar *d = output->data() + outLen; bool skipped = false; // copy all basic code points verbatim to output. for (uint j = 0; j < (uint) ucLength; ++j) { @@ -3035,7 +3068,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) // if basic code points were copied, add the delimiter character. if (h > 0) - *output += 0x2d; + *output += QChar(0x2d); // while there are still unprocessed non-basic code points left in // the input string... @@ -3083,7 +3116,7 @@ static void toPunycodeHelper(const QChar *s, int ucLength, QByteArray *output) } // prepend ACE prefix - output->insert(outLen, "xn--"); + output->insert(outLen, QLatin1String("xn--")); return; } @@ -3144,11 +3177,15 @@ static bool qt_is_idn_enabled(const QString &domain) int idx = domain.lastIndexOf(QLatin1Char('.')); if (idx == -1) return false; - const QChar *tld = domain.constData() + idx + 1; + int len = domain.size() - idx - 1; + QString tldString(domain.constData() + idx + 1, len); + qt_nameprep(&tldString, 0); + + const QChar *tld = tldString.constData(); if (user_idn_whitelist) - return user_idn_whitelist->contains(QString(tld, len)); + return user_idn_whitelist->contains(tldString); int l = 0; int r = sizeof(idn_whitelist)/sizeof(const char *) - 1; @@ -3164,46 +3201,127 @@ static bool qt_is_idn_enabled(const QString &domain) return equal(tld, len, idn_whitelist[i]); } -static QString qt_from_ACE(const QString &domainMC) +static inline bool isDotDelimiter(ushort uc) { - QString domain = domainMC.toLower(); - int idx = domain.indexOf(QLatin1Char('.')); - if (idx != -1) { - if (!domain.contains(QLatin1String("xn--"))) { - bool simple = true; - for (int i = 0; i < domain.size(); ++i) { - ushort ch = domain.at(i).unicode(); - if (ch > 'z' || ch < '-' || ch == '/' || (ch > '9' && ch < 'A') || (ch > 'Z' && ch < 'a')) { + // IDNA / rfc3490 describes these four delimiters used for + // separating labels in unicode international domain + // names. + return uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61; +} + +static int nextDotDelimiter(const QString &domain, int from = 0) +{ + const QChar *b = domain.unicode(); + const QChar *ch = b + from; + const QChar *e = b + domain.length(); + while (ch < e) { + if (isDotDelimiter(ch->unicode())) + break; + else + ++ch; + } + return ch - b; +} + +enum AceOperation { ToAceOnly, NormalizeAce }; +static QString qt_ACE_do(const QString &domain, AceOperation op) +{ + if (domain.isEmpty()) + return domain; + + QString result; + result.reserve(domain.length()); + + const bool isIdnEnabled = op == NormalizeAce ? qt_is_idn_enabled(domain) : false; + int lastIdx = 0; + QString aceForm; // this variable is here for caching + + while (1) { + int idx = nextDotDelimiter(domain, lastIdx); + int labelLength = idx - lastIdx; + if (labelLength == 0) + return QString(); // two delimiters in a row -- empty label not allowed + + // RFC 3490 says, about the ToASCII operation: + // 3. If the UseSTD3ASCIIRules flag is set, then perform these checks: + // + // (a) Verify the absence of non-LDH ASCII code points; that is, the + // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F. + // + // (b) Verify the absence of leading and trailing hyphen-minus; that + // is, the absence of U+002D at the beginning and end of the + // sequence. + // and: + // 8. Verify that the number of code points is in the range 1 to 63 + // inclusive. + + // copy the label to the destination, which also serves as our scratch area, lowercasing it + int prevLen = result.size(); + bool simple = true; + result.resize(prevLen + labelLength); + { + QChar *out = result.data() + prevLen; + const QChar *in = domain.constData() + lastIdx; + const QChar *e = in + labelLength; + for (; in < e; ++in, ++out) { + register ushort uc = in->unicode(); + if (uc > 0x7f) simple = false; - break; - } + if (uc >= 'A' && uc <= 'Z') + *out = QChar(uc | 0x20); + else + *out = *in; } - if (simple) - return domain; } - - const bool isIdnEnabled = qt_is_idn_enabled(domain); - int lastIdx = 0; - QString result; - while (1) { - // Nameprep the host. If the labels in the hostname are Punycode - // encoded, we decode them immediately, then nameprep them. - QByteArray label; - toPunycodeHelper(domain.constData() + lastIdx, idx - lastIdx, &label); - result += qt_nameprep(isIdnEnabled ? QUrl::fromPunycode(label) : QString::fromLatin1(label)); - lastIdx = idx + 1; - if (lastIdx < domain.size() + 1) - result += QLatin1Char('.'); - else - break; - idx = domain.indexOf(QLatin1Char('.'), lastIdx); - if (idx == -1) - idx = domain.size(); + + if (simple && labelLength > 6) { + // ACE form domains contain only ASCII characters, but we can't consider them simple + // is this an ACE form? + // the shortest valid ACE domain is 6 characters long (U+0080 would be 1, but it's not allowed) + static const ushort acePrefixUtf16[] = { 'x', 'n', '-', '-' }; + if (memcmp(result.constData() + prevLen, acePrefixUtf16, sizeof acePrefixUtf16) == 0) + simple = false; } - return result; - } else { - return qt_nameprep(domain); + + if (simple) { + // fastest case: this is the common case (non IDN-domains) + // so we're done + if (!qt_check_std3rules(result.constData() + prevLen, labelLength)) + return QString(); + } else { + // Punycode encoding and decoding cannot be done in-place + // That means we need one or two temporaries + qt_nameprep(&result, prevLen); + labelLength = result.length() - prevLen; + register int toReserve = labelLength + 4 + 6; // "xn--" plus some extra bytes + if (toReserve > aceForm.capacity()) + aceForm.reserve(toReserve); + toPunycodeHelper(result.constData() + prevLen, result.size() - prevLen, &aceForm); + + // We use resize()+memcpy() here because we're overwriting the data we've copied + if (isIdnEnabled) { + QString tmp = QUrl::fromPunycode(aceForm.toLatin1()); + if (tmp.isEmpty()) + return QString(); // shouldn't happen, since we've just punycode-encoded it + result.resize(prevLen + tmp.size()); + memcpy(result.data() + prevLen, tmp.constData(), tmp.size() * sizeof(QChar)); + } else { + result.resize(prevLen + aceForm.size()); + memcpy(result.data() + prevLen, aceForm.constData(), aceForm.size() * sizeof(QChar)); + } + + if (!qt_check_std3rules(aceForm.constData(), aceForm.size())) + return QString(); + } + + + lastIdx = idx + 1; + if (lastIdx < domain.size() + 1) + result += QLatin1Char('.'); + else + break; } + return result; } @@ -3246,12 +3364,27 @@ QUrlPrivate::QUrlPrivate(const QUrlPrivate ©) QString QUrlPrivate::canonicalHost() const { - if (QURL_HASFLAG(stateFlags, HostCanonicalized)) + if (QURL_HASFLAG(stateFlags, HostCanonicalized) || host.isEmpty()) return host; QUrlPrivate *that = const_cast<QUrlPrivate *>(this); QURL_SETFLAG(that->stateFlags, HostCanonicalized); - that->host = qt_from_ACE(host); + if (host.contains(QLatin1Char(':'))) { + // This is an IP Literal, use _IPLiteral to validate + QByteArray ba = host.toLatin1(); + if (!ba.startsWith('[')) { + // surround the IP Literal with [ ] if it's not already done so + ba.reserve(ba.length() + 2); + ba.prepend('['); + ba.append(']'); + } + + const char *ptr = ba.constData(); + if (!_IPLiteral(&ptr)) + that->host.clear(); + } else { + that->host = qt_ACE_do(host, NormalizeAce); + } return that->host; } @@ -3737,7 +3870,10 @@ QByteArray QUrlPrivate::toEncoded(QUrl::FormattingOptions options) const } } - url += QUrl::toAce(host); + if (host.startsWith(QLatin1Char('['))) + url += host.toLatin1(); + else + url += QUrl::toAce(host); if (!(options & QUrl::RemovePort) && port != -1) { url += ':'; url += QString::number(port).toAscii(); @@ -4412,8 +4548,6 @@ void QUrl::setHost(const QString &host) QURL_UNSETFLAG(d->stateFlags, QUrlPrivate::Validated | QUrlPrivate::Normalized | QUrlPrivate::HostCanonicalized); d->host = host; - if (d->host.contains(QLatin1Char(':'))) - d->host = QLatin1Char('[') + d->host + QLatin1Char(']'); } /*! @@ -5425,9 +5559,9 @@ QByteArray QUrl::toPercentEncoding(const QString &input, const QByteArray &exclu */ QByteArray QUrl::toPunycode(const QString &uc) { - QByteArray output; + QString output; toPunycodeHelper(uc.constData(), uc.size(), &output); - return output; + return output.toLatin1(); } /*! @@ -5528,7 +5662,7 @@ QString QUrl::fromPunycode(const QByteArray &pc) */ QString QUrl::fromAce(const QByteArray &domain) { - return qt_from_ACE(QString::fromLatin1(domain)); + return qt_ACE_do(QString::fromLatin1(domain), NormalizeAce); } /*! @@ -5545,26 +5679,8 @@ QString QUrl::fromAce(const QByteArray &domain) */ QByteArray QUrl::toAce(const QString &domain) { - // IDNA / rfc3490 describes these four delimiters used for - // separating labels in unicode international domain - // names. - QString nameprepped = qt_nameprep(domain); - int lastIdx = 0; - QByteArray result; - for (int i = 0; i < nameprepped.size(); ++i) { - ushort uc = nameprepped.at(i).unicode(); - if (uc == 0x2e || uc == 0x3002 || uc == 0xff0e || uc == 0xff61) { - if (lastIdx) - result += '.'; - toPunycodeHelper(nameprepped.constData() + lastIdx, i - lastIdx, &result); - lastIdx = i + 1; - } - } - if (lastIdx) - result += '.'; - toPunycodeHelper(nameprepped.constData() + lastIdx, nameprepped.size() - lastIdx, &result); - - return result; + QString result = qt_ACE_do(domain, ToAceOnly); + return result.toLatin1(); } /*! diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 6d9daec..bd27ec2 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -171,6 +171,11 @@ QT_BEGIN_NAMESPACE \value QBitmap QBitmap \value QMatrix QMatrix \value QTransform QTransform + \value QMatrix4x4 QMatrix4x4 + \value QVector2D QVector2D + \value QVector3D QVector3D + \value QVector4D QVector4D + \value QQuaternion QQuaternion \value User Base value for user types @@ -272,6 +277,11 @@ static const struct { const char * typeName; int type; } types[] = { {"QTextFormat", QMetaType::QTextFormat}, {"QMatrix", QMetaType::QMatrix}, {"QTransform", QMetaType::QTransform}, + {"QMatrix4x4", QMetaType::QMatrix4x4}, + {"QVector2D", QMetaType::QVector2D}, + {"QVector3D", QMetaType::QVector3D}, + {"QVector4D", QMetaType::QVector4D}, + {"QQuaternion", QMetaType::QQuaternion}, /* All Metatype builtins */ {"void*", QMetaType::VoidStar}, @@ -670,6 +680,11 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data) case QMetaType::QTextFormat: case QMetaType::QMatrix: case QMetaType::QTransform: + case QMetaType::QMatrix4x4: + case QMetaType::QVector2D: + case QMetaType::QVector3D: + case QMetaType::QVector4D: + case QMetaType::QQuaternion: if (!qMetaTypeGuiHelper) return false; qMetaTypeGuiHelper[type - FirstGuiType].saveOp(stream, data); @@ -862,6 +877,11 @@ bool QMetaType::load(QDataStream &stream, int type, void *data) case QMetaType::QTextFormat: case QMetaType::QMatrix: case QMetaType::QTransform: + case QMetaType::QMatrix4x4: + case QMetaType::QVector2D: + case QMetaType::QVector3D: + case QMetaType::QVector4D: + case QMetaType::QQuaternion: if (!qMetaTypeGuiHelper) return false; qMetaTypeGuiHelper[type - FirstGuiType].loadOp(stream, data); diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 497c014..052312c 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -79,7 +79,9 @@ public: QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73, QCursor = 74, QSizePolicy = 75, QKeySequence = 76, QPen = 77, QTextLength = 78, QTextFormat = 79, QMatrix = 80, QTransform = 81, - LastGuiType = 81 /* QTransform */, + QMatrix4x4 = 82, QVector2D = 83, QVector3D = 84, QVector4D = 85, + QQuaternion = 86, + LastGuiType = 86 /* QQuaternion */, FirstCoreExtType = 128 /* VoidStar */, VoidStar = 128, Long = 129, Short = 130, Char = 131, ULong = 132, @@ -292,6 +294,11 @@ class QTextLength; class QTextFormat; class QMatrix; class QTransform; +class QMatrix4x4; +class QVector2D; +class QVector3D; +class QVector4D; +class QQuaternion; QT_END_NAMESPACE @@ -354,6 +361,11 @@ Q_DECLARE_BUILTIN_METATYPE(QTextLength, QTextLength) Q_DECLARE_BUILTIN_METATYPE(QTextFormat, QTextFormat) Q_DECLARE_BUILTIN_METATYPE(QMatrix, QMatrix) Q_DECLARE_BUILTIN_METATYPE(QTransform, QTransform) +Q_DECLARE_BUILTIN_METATYPE(QMatrix4x4, QMatrix4x4) +Q_DECLARE_BUILTIN_METATYPE(QVector2D, QVector2D) +Q_DECLARE_BUILTIN_METATYPE(QVector3D, QVector3D) +Q_DECLARE_BUILTIN_METATYPE(QVector4D, QVector4D) +Q_DECLARE_BUILTIN_METATYPE(QQuaternion, QQuaternion) QT_END_HEADER diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index eb1bd0b..6503ab0 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -854,7 +854,7 @@ QObject::~QObject() QObjectPrivate::Connection::~Connection() { if (argumentTypes != &DIRECT_CONNECTION_ONLY) - delete [] argumentTypes; + delete [] static_cast<int *>(argumentTypes); } diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 2ef9de4..2b5ea0a 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1264,6 +1264,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; \value Map a QVariantMap \value Matrix a QMatrix \value Transform a QTransform + \value Matrix4x4 a QMatrix4x4 \value Palette a QPalette \value Pen a QPen \value Pixmap a QPixmap @@ -1271,6 +1272,7 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; \value PointArray a QPointArray \value PointF a QPointF \value Polygon a QPolygon + \value Quaternion a QQuaternion \value Rect a QRect \value RectF a QRectF \value RegExp a QRegExp @@ -1286,6 +1288,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; \value UInt a \l uint \value ULongLong a \l qulonglong \value Url a QUrl + \value Vector2D a QVector2D + \value Vector3D a QVector3D + \value Vector4D a QVector4D \value UserType Base value for user-defined types. @@ -1677,7 +1682,7 @@ QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); } Note that return values in the ranges QVariant::Char through QVariant::RegExp and QVariant::Font through QVariant::Transform correspond to the values in the ranges QMetaType::QChar through - QMetaType::QRegExp and QMetaType::QFont through QMetaType::QTransform. + QMetaType::QRegExp and QMetaType::QFont through QMetaType::QQuaternion. Pay particular attention when working with char and QChar variants. Note that there is no QVariant constructor specifically diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index e923844..a68939d 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -154,7 +154,12 @@ class Q_CORE_EXPORT QVariant TextFormat = 79, Matrix = 80, Transform = 81, - LastGuiType = Transform, + Matrix4x4 = 82, + Vector2D = 83, + Vector3D = 84, + Vector4D = 85, + Quaternion = 86, + LastGuiType = Quaternion, UserType = 127, #ifdef QT3_SUPPORT diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp index c040c58..0004d3e 100644 --- a/src/corelib/statemachine/qabstracttransition.cpp +++ b/src/corelib/statemachine/qabstracttransition.cpp @@ -115,13 +115,10 @@ QAbstractTransitionPrivate *QAbstractTransitionPrivate::get(QAbstractTransition QStateMachine *QAbstractTransitionPrivate::machine() const { - QObject *par = parent; - while (par != 0) { - if (QStateMachine *mach = qobject_cast<QStateMachine*>(par)) - return mach; - par = par->parent(); - } - return 0; + QState *source = sourceState(); + if (!source) + return 0; + return source->machine(); } bool QAbstractTransitionPrivate::callEventTest(QEvent *e) @@ -256,10 +253,6 @@ void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets) qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null"); return; } - if (target->machine() != 0 && target->machine()->rootState() == target) { - qWarning("QAbstractTransition::setTargetStates: root state cannot be target of transition"); - return; - } } d->targetStates.clear(); @@ -330,18 +323,6 @@ QList<QAbstractAnimation*> QAbstractTransition::animations() const This function is called to determine whether the given \a event should cause this transition to trigger. Reimplement this function and return true if the event should trigger the transition, otherwise return false. - - - Note that \a event is a QWrappedEvent, which contains a clone of - the event generated by Qt. For instance, if you want to check a - key press event, do the following: - - \snippet doc/src/snippets/statemachine/eventtest.cpp 0 - - You need to check if \a event is a QWrappedEvent because Qt also - uses other events for internal reasons; you don't need to concern - yourself with these in any case. - */ /*! diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp index 83dd869..f74edc3 100644 --- a/src/corelib/statemachine/qstate.cpp +++ b/src/corelib/statemachine/qstate.cpp @@ -71,7 +71,7 @@ QT_BEGIN_NAMESPACE The assignProperty() function is used for defining property assignments that should be performed when a state is entered. - Top-level states must be passed QStateMachine::rootState() as their parent + Top-level states must be passed a QStateMachine object as their parent state, or added to a state machine using QStateMachine::addState(). \section1 States with Child States @@ -242,7 +242,7 @@ void QState::assignProperty(QObject *object, const char *name, /*! Returns this state's error state. - \sa QStateMachine::errorState(), QStateMachine::setErrorState() + \sa QStateMachine::error() */ QAbstractState *QState::errorState() const { @@ -256,19 +256,17 @@ QAbstractState *QState::errorState() const state recursively. If no error state is set for the state itself or any of its ancestors, an error will cause the machine to stop executing and an error will be printed to the console. - - \sa QStateMachine::setErrorState(), QStateMachine::errorState() */ void QState::setErrorState(QAbstractState *state) { Q_D(QState); - if (state != 0 && state->machine() != machine()) { - qWarning("QState::setErrorState: error state cannot belong " - "to a different state machine"); + if (state != 0 && qobject_cast<QStateMachine*>(state)) { + qWarning("QStateMachine::setErrorState: root state cannot be error state"); return; } - if (state != 0 && state->machine() != 0 && state->machine()->rootState() == state) { - qWarning("QStateMachine::setErrorState: root state cannot be error state"); + if (state != 0 && (!state->machine() || ((state->machine() != machine()) && !qobject_cast<QStateMachine*>(this)))) { + qWarning("QState::setErrorState: error state cannot belong " + "to a different state machine"); return; } @@ -288,12 +286,7 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition) return 0; } - // machine() will always be non-null for root state - if (machine() != 0 && machine()->rootState() == this) { - qWarning("QState::addTransition: cannot add transition from root state"); - return 0; - } - + transition->setParent(this); const QList<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates; for (int i = 0; i < targets.size(); ++i) { QAbstractState *t = targets.at(i); @@ -308,7 +301,6 @@ QAbstractTransition *QState::addTransition(QAbstractTransition *transition) return 0; } } - transition->setParent(this); if (machine() != 0 && machine()->configuration().contains(this)) QStateMachinePrivate::get(machine())->registerTransitions(this); return transition; diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index bf3ee31..5402b04 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -102,14 +102,9 @@ QT_BEGIN_NAMESPACE Framework}{overview} gives several state graphs and the code to build them. - The rootState() is the parent of all top-level states in the - machine; it is used, for instance, when the state graph is - deleted. It is created by the machine. - - Use the addState() function to add a state to the state machine. - All top-level states are added to the root state. States are - removed with the removeState() function. Removing states while the - machine is running is discouraged. + Use the addState() function to add a top-level state to the state machine. + States are removed with the removeState() function. Removing states while + the machine is running is discouraged. Before the machine can be started, the \l{initialState}{initial state} must be set. The initial state is the state that the @@ -179,26 +174,6 @@ This is */ /*! - \property QStateMachine::rootState - - \brief the root state of this state machine -*/ - -/*! - \property QStateMachine::initialState - - \brief the initial state of this state machine - - The initial state must be one of the rootState()'s child states. -*/ - -/*! - \property QStateMachine::errorState - - \brief the error state of this state machine -*/ - -/*! \property QStateMachine::errorString \brief the error string of this state machine @@ -235,7 +210,6 @@ QStateMachinePrivate::QStateMachinePrivate() stop = false; error = QStateMachine::NoError; globalRestorePolicy = QStateMachine::DoNotRestoreProperties; - rootState = 0; signalEventGenerator = 0; #ifndef QT_NO_ANIMATION animationsEnabled = true; @@ -255,6 +229,11 @@ QStateMachinePrivate *QStateMachinePrivate::get(QStateMachine *q) return 0; } +QState *QStateMachinePrivate::rootState() const +{ + return const_cast<QStateMachine*>(q_func()); +} + static QEvent *cloneEvent(QEvent *e) { switch (e->type()) { @@ -302,7 +281,9 @@ bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return true; } else { - QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2); + Q_ASSERT(s1->machine() != 0); + QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine()); + QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2); Q_ASSERT(lca != 0); return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } @@ -318,17 +299,19 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState } else if (isDescendantOf(s2, s1)) { return false; } else { - QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2); + Q_ASSERT(s1->machine() != 0); + QStateMachinePrivate *mach = QStateMachinePrivate::get(s1->machine()); + QState *lca = mach->findLCA(QList<QAbstractState*>() << s1 << s2); Q_ASSERT(lca != 0); return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2)); } } -QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) +QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) const { if (states.isEmpty()) return 0; - QList<QState*> ancestors = properAncestors(states.at(0), 0); + QList<QState*> ancestors = properAncestors(states.at(0), rootState()->parentState()); for (int i = 0; i < ancestors.size(); ++i) { QState *anc = ancestors.at(i); bool ok = true; @@ -376,7 +359,7 @@ QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event continue; if (isPreempted(state, enabledTransitions)) continue; - QList<QState*> lst = properAncestors(state, 0); + QList<QState*> lst = properAncestors(state, rootState()->parentState()); if (QState *grp = qobject_cast<QState*>(state)) lst.prepend(grp); bool found = false; @@ -557,11 +540,13 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QL if (isFinal(s)) { QState *parent = s->parentState(); if (parent) { - QState *grandparent = parent->parentState(); + if (parent != rootState()) { #ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": emitting finished signal for" << parent; + qDebug() << q << ": emitting finished signal for" << parent; #endif - QStatePrivate::get(parent)->emitFinished(); + QStatePrivate::get(parent)->emitFinished(); + } + QState *grandparent = parent->parentState(); if (grandparent && isParallel(grandparent)) { bool allChildStatesFinal = true; QList<QAbstractState*> childStates = QStatePrivate::get(grandparent)->childStates(); @@ -572,7 +557,7 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QL break; } } - if (allChildStatesFinal) { + if (allChildStatesFinal && (grandparent != rootState())) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": emitting finished signal for" << grandparent; #endif @@ -585,7 +570,7 @@ QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QL { QSet<QAbstractState*>::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - if (isFinal(*it) && (*it)->parentState() == rootState) { + if (isFinal(*it) && (*it)->parentState() == rootState()) { processing = false; stopProcessingReason = Finished; break; @@ -630,6 +615,11 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } } } else { + if (s == rootState()) { + // Error has already been set by exitStates(). + Q_ASSERT(error != QStateMachine::NoError); + return; + } statesToEnter.insert(s); if (isParallel(s)) { QState *grp = qobject_cast<QState*>(s); @@ -643,6 +633,7 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, QState *grp = qobject_cast<QState*>(s); QAbstractState *initial = grp->initialState(); if (initial != 0) { + Q_ASSERT(initial->machine() == q_func()); addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry); } else { setError(QStateMachine::NoInitialStateError, grp); @@ -873,20 +864,26 @@ bool QStateMachinePrivate::isParallel(const QAbstractState *s) return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates); } -bool QStateMachinePrivate::isCompound(const QAbstractState *s) +bool QStateMachinePrivate::isCompound(const QAbstractState *s) const { const QState *group = qobject_cast<const QState*>(s); if (!group) return false; + bool isMachine = (qobject_cast<const QStateMachine*>(group) != 0); + // Don't treat the machine as compound if it's a sub-state of this machine + if (isMachine && (group != rootState())) + return false; return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty()) - || (qobject_cast<QStateMachine*>(group->parent()) != 0); + || isMachine; } -bool QStateMachinePrivate::isAtomic(const QAbstractState *s) +bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const { const QState *ss = qobject_cast<const QState*>(s); return (ss && QStatePrivate::get(ss)->childStates().isEmpty()) - || isFinal(s); + || isFinal(s) + // Treat the machine as atomic if it's a sub-state of this machine + || (ss && (qobject_cast<const QStateMachine*>(ss) != 0) && (ss != rootState())); } @@ -1034,7 +1031,7 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta if (currentContext == currentErrorState) currentErrorState = 0; - Q_ASSERT(currentErrorState != rootState); + Q_ASSERT(currentErrorState != rootState()); if (currentErrorState != 0) { QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); @@ -1141,11 +1138,8 @@ void QStateMachinePrivate::_q_start() { Q_Q(QStateMachine); Q_ASSERT(state == Starting); - if (!rootState) { - state = NotRunning; - return; - } - QAbstractState *initial = rootState->initialState(); + Q_ASSERT(rootState() != 0); + QAbstractState *initial = rootState()->initialState(); configuration.clear(); qDeleteAll(internalEventQueue); internalEventQueue.clear(); @@ -1159,7 +1153,7 @@ void QStateMachinePrivate::_q_start() processingScheduled = true; // we call _q_process() below emit q->started(); - StartState *start = new StartState(rootState); + StartState *start = new StartState(rootState()); QAbstractTransition *initialTransition = new InitialTransition(initial); start->addTransition(initialTransition); QList<QAbstractTransition*> transitions; @@ -1371,15 +1365,22 @@ void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transit void QStateMachinePrivate::unregisterAllTransitions() { + Q_Q(QStateMachine); { - QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState); - for (int i = 0; i < transitions.size(); ++i) - unregisterSignalTransition(transitions.at(i)); + QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState()); + for (int i = 0; i < transitions.size(); ++i) { + QSignalTransition *t = transitions.at(i); + if (t->machine() == q) + unregisterSignalTransition(t); + } } { - QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState); - for (int i = 0; i < transitions.size(); ++i) - unregisterEventTransition(transitions.at(i)); + QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState()); + for (int i = 0; i < transitions.size(); ++i) { + QEventTransition *t = transitions.at(i); + if (t->machine() == q) + unregisterEventTransition(t); + } } } @@ -1457,16 +1458,20 @@ void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int sig Constructs a new state machine with the given \a parent. */ QStateMachine::QStateMachine(QObject *parent) - : QObject(*new QStateMachinePrivate, parent) + : QState(*new QStateMachinePrivate, /*parentState=*/0) { + // Can't pass the parent to the QState constructor, as it expects a QState + // But this works as expected regardless of whether parent is a QState or not + setParent(parent); } /*! \internal */ QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent) - : QObject(dd, parent) + : QState(dd, /*parentState=*/0) { + setParent(parent); } /*! @@ -1476,69 +1481,6 @@ QStateMachine::~QStateMachine() { } -namespace { - -class RootState : public QState -{ -public: - RootState(QState *parent) - : QState(parent) - { - } - - void onEntry(QEvent *) {} - void onExit(QEvent *) {} -}; - -} // namespace - -/*! - Returns this state machine's root state. -*/ -QState *QStateMachine::rootState() const -{ - Q_D(const QStateMachine); - if (!d->rootState) { - const_cast<QStateMachinePrivate*>(d)->rootState = new RootState(0); - d->rootState->setParent(const_cast<QStateMachine*>(this)); - } - return d->rootState; -} - -/*! - Returns the error state of the state machine's root state. - - \sa QState::errorState() -*/ -QAbstractState *QStateMachine::errorState() const -{ - return rootState()->errorState(); -} - -/*! - Sets the error state of this state machine's root state to be \a state. When a running state - machine encounters an error which puts it in an undefined state, it will enter an error state - based on the context of the error that occurred. It will enter this state regardless of what - is currently in the event queue. - - If the erroneous state has an error state set, this will be entered by the machine. If no error - state has been set, the state machine will search the parent hierarchy recursively for an - error state. The error state of the root state can thus be seen as a global error state that - applies for all states for which a more specific error state has not been set. - - Before entering the error state, the state machine will set the error code returned by error() and - error message returned by errorString(). - - If there is no error state available for the erroneous state, the state machine will print a - warning message on the console and stop executing. - - \sa QState::setErrorState(), rootState() -*/ -void QStateMachine::setErrorState(QAbstractState *state) -{ - rootState()->setErrorState(state); -} - /*! \enum QStateMachine::Error This enum type defines errors that can occur in the state machine at run time. When the state @@ -1640,39 +1582,13 @@ void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restoreP } /*! - Returns this state machine's initial state, or 0 if no initial state has - been set. -*/ -QAbstractState *QStateMachine::initialState() const -{ - Q_D(const QStateMachine); - if (!d->rootState) - return 0; - return d->rootState->initialState(); -} - -/*! - Sets this state machine's initial \a state. -*/ -void QStateMachine::setInitialState(QAbstractState *state) -{ - Q_D(QStateMachine); - if (!d->rootState) { - if (!state) - return; - rootState()->setInitialState(state); - } - d->rootState->setInitialState(state); -} - -/*! Adds the given \a state to this state machine. The state becomes a top-level - state (i.e. a child of the rootState()). + state. If the state is already in a different machine, it will first be removed from its old machine, and then added to this machine. - \sa removeState(), rootState(), setInitialState() + \sa removeState(), setInitialState() */ void QStateMachine::addState(QAbstractState *state) { @@ -1684,7 +1600,7 @@ void QStateMachine::addState(QAbstractState *state) qWarning("QStateMachine::addState: state has already been added to this machine"); return; } - state->setParent(rootState()); + state->setParent(this); } /*! @@ -1730,7 +1646,7 @@ void QStateMachine::start() { Q_D(QStateMachine); - if (rootState()->initialState() == 0) { + if (initialState() == 0) { qWarning("QStateMachine::start: No initial state set for machine. Refusing to start."); return; } @@ -1821,7 +1737,7 @@ void QStateMachine::postInternalEvent(QEvent *event) Returns the maximal consistent set of states (including parallel and final states) that this state machine is currently in. If a state \c s is in the configuration, it is always the case that the parent of \c s is also in - c. Note, however, that the rootState() is not an explicit member of the + c. Note, however, that the machine itself is not an explicit member of the configuration. */ QSet<QAbstractState*> QStateMachine::configuration() const @@ -1840,15 +1756,6 @@ QSet<QAbstractState*> QStateMachine::configuration() const */ /*! - \fn QStateMachine::finished() - - This signal is emitted when the state machine has reached a top-level final - state (QFinalState). - - \sa QStateMachine::started() -*/ - -/*! \fn QStateMachine::stopped() This signal is emitted when the state machine has stopped. @@ -1872,14 +1779,6 @@ bool QStateMachine::event(QEvent *e) d->scheduleProcess(); return true; } - } else if (e->type() == QEvent::ChildAdded) { - QChildEvent *ce = static_cast<QChildEvent*>(e); - if (QAbstractState *state = qobject_cast<QAbstractState*>(ce->child())) { - if (state != rootState()) { - state->setParent(rootState()); - return true; - } - } } return QObject::event(e); } @@ -1949,6 +1848,24 @@ void QStateMachine::endMicrostep(QEvent *event) Q_UNUSED(event); } +/*! + \reimp +*/ +void QStateMachine::onEntry(QEvent *event) +{ + start(); + QState::onEntry(event); +} + +/*! + \reimp +*/ +void QStateMachine::onExit(QEvent *event) +{ + stop(); + QState::onExit(event); +} + #ifndef QT_NO_ANIMATION /*! @@ -2155,6 +2072,8 @@ QSignalEvent::~QSignalEvent() Constructs a new QWrappedEvent object with the given \a object and \a event. + + The QWrappedEvent object takes ownership of \a event. */ QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event) : QEvent(QEvent::Wrapped), m_object(object), m_event(event) @@ -2166,6 +2085,7 @@ QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event) */ QWrappedEvent::~QWrappedEvent() { + delete m_event; } /*! diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 30d0e3a..230d852 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -42,7 +42,7 @@ #ifndef QSTATEMACHINE_H #define QSTATEMACHINE_H -#include <QtCore/qabstractstate.h> +#include <QtCore/qstate.h> #include <QtCore/qlist.h> #include <QtCore/qobject.h> @@ -57,18 +57,12 @@ QT_MODULE(Core) #ifndef QT_NO_STATEMACHINE class QEvent; -class QAbstractState; -class QState; class QStateMachinePrivate; class QAbstractAnimation; -class QAbstractState; -class Q_CORE_EXPORT QStateMachine : public QObject +class Q_CORE_EXPORT QStateMachine : public QState { Q_OBJECT - Q_PROPERTY(QState* rootState READ rootState) - Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState) - Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState) Q_PROPERTY(QString errorString READ errorString) Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy) Q_ENUMS(RestorePolicy) @@ -94,14 +88,6 @@ public: void addState(QAbstractState *state); void removeState(QAbstractState *state); - QState *rootState() const; - - QAbstractState *initialState() const; - void setInitialState(QAbstractState *state); - - QAbstractState *errorState() const; - void setErrorState(QAbstractState *state); - Error error() const; QString errorString() const; void clearError(); @@ -135,9 +121,11 @@ public Q_SLOTS: Q_SIGNALS: void started(); void stopped(); - void finished(); protected: + void onEntry(QEvent *event); + void onExit(QEvent *event); + void postInternalEvent(QEvent *event); virtual void beginSelectTransitions(QEvent *event); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 1335b93..21e405d 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -53,7 +53,8 @@ // We mean it. // -#include <private/qobject_p.h> +#include "private/qstate_p.h" + #include <QtCore/qcoreevent.h> #include <QtCore/qhash.h> #include <QtCore/qlist.h> @@ -61,9 +62,6 @@ #include <QtCore/qset.h> #include <QtCore/qvector.h> -#include "qstate.h" -#include "private/qstate_p.h" - QT_BEGIN_NAMESPACE class QEvent; @@ -81,7 +79,7 @@ class QAbstractAnimation; #endif class QStateMachine; -class QStateMachinePrivate : public QObjectPrivate +class QStateMachinePrivate : public QStatePrivate { Q_DECLARE_PUBLIC(QStateMachine) public: @@ -101,7 +99,7 @@ public: static QStateMachinePrivate *get(QStateMachine *q); - static QState *findLCA(const QList<QAbstractState*> &states); + QState *findLCA(const QList<QAbstractState*> &states) const; static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2); static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2); @@ -116,6 +114,8 @@ public: void _q_animationFinished(); #endif + QState *rootState() const; + void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList); bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const; QSet<QAbstractTransition*> selectTransitions(QEvent *event) const; @@ -133,8 +133,8 @@ public: bool isInFinalState(QAbstractState *s) const; static bool isFinal(const QAbstractState *s); static bool isParallel(const QAbstractState *s); - static bool isCompound(const QAbstractState *s); - static bool isAtomic(const QAbstractState *s); + bool isCompound(const QAbstractState *s) const; + bool isAtomic(const QAbstractState *s) const; static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other); static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound); @@ -164,7 +164,6 @@ public: bool processingScheduled; bool stop; StopProcessingReason stopProcessingReason; - QState *rootState; QSet<QAbstractState*> configuration; QList<QEvent*> internalEventQueue; QList<QEvent*> externalEventQueue; diff --git a/src/corelib/thread/qreadwritelock.h b/src/corelib/thread/qreadwritelock.h index 51d42b5..4742bea 100644 --- a/src/corelib/thread/qreadwritelock.h +++ b/src/corelib/thread/qreadwritelock.h @@ -190,7 +190,8 @@ inline QWriteLocker::QWriteLocker(QReadWriteLock *areadWriteLock) class Q_CORE_EXPORT QReadWriteLock { public: - inline explicit QReadWriteLock() { } + enum RecursionMode { NonRecursive, Recursive }; + inline explicit QReadWriteLock(RecursionMode = NonRecursive) { } inline ~QReadWriteLock() { } static inline void lockForRead() { } diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp index 88053d6..458a383 100644 --- a/src/corelib/tools/qchar.cpp +++ b/src/corelib/tools/qchar.cpp @@ -1421,16 +1421,15 @@ QDataStream &operator>>(QDataStream &in, QChar &chr) // --------------------------------------------------------------------------- -static QString decomposeHelper - (const QString &str, bool canonical, QChar::UnicodeVersion version) +static void decomposeHelper(QString *str, bool canonical, QChar::UnicodeVersion version, int from) { unsigned short buffer[3]; - QString s = str; + QString &s = *str; - const unsigned short *utf16 = s.utf16(); + const unsigned short *utf16 = reinterpret_cast<unsigned short *>(s.data()); const unsigned short *uc = utf16 + s.length(); - while (uc != utf16) { + while (uc != utf16 + from) { uint ucs4 = *(--uc); if (QChar(ucs4).isLowSurrogate() && uc != utf16) { ushort high = *(uc - 1); @@ -1450,11 +1449,9 @@ static QString decomposeHelper s.replace(uc - utf16, ucs4 > 0x10000 ? 2 : 1, (const QChar *)d, length); // since the insert invalidates the pointers and we do decomposition recursive int pos = uc - utf16; - utf16 = s.utf16(); + utf16 = reinterpret_cast<unsigned short *>(s.data()); uc = utf16 + pos + length; } - - return s; } @@ -1489,21 +1486,21 @@ static ushort ligatureHelper(ushort u1, ushort u2) return 0; } -static QString composeHelper(const QString &str) +static void composeHelper(QString *str, int from) { - QString s = str; + QString &s = *str; - if (s.length() < 2) - return s; + if (s.length() - from < 2) + return; // the loop can partly ignore high Unicode as all ligatures are in the BMP int starter = 0; int lastCombining = 0; - int pos = 0; + int pos = from; while (pos < s.length()) { - uint uc = s.utf16()[pos]; + uint uc = s.at(pos).unicode(); if (QChar(uc).isHighSurrogate() && pos < s.length()-1) { - ushort low = s.utf16()[pos+1]; + ushort low = s.at(pos+1).unicode(); if (QChar(low).isLowSurrogate()) { uc = QChar::surrogateToUcs4(uc, low); ++pos; @@ -1512,7 +1509,7 @@ static QString composeHelper(const QString &str) int combining = QChar::combiningClass(uc); if (starter == pos - 1 || combining > lastCombining) { // allowed to form ligature with S - QChar ligature = ligatureHelper(s.utf16()[starter], uc); + QChar ligature = ligatureHelper(s.at(starter).unicode(), uc); if (ligature.unicode()) { s[starter] = ligature; s.remove(pos, 1); @@ -1524,16 +1521,14 @@ static QString composeHelper(const QString &str) lastCombining = combining; ++pos; } - return s; } -static QString canonicalOrderHelper - (const QString &str, QChar::UnicodeVersion version) +static void canonicalOrderHelper(QString *str, QChar::UnicodeVersion version, int from) { - QString s = str; + QString &s = *str; const int l = s.length()-1; - int pos = 0; + int pos = from; while (pos < l) { int p2 = pos+1; uint u1 = s.at(pos).unicode(); @@ -1593,7 +1588,6 @@ static QString canonicalOrderHelper ++pos; } } - return s; } int QT_FASTCALL QUnicodeTables::script(unsigned int uc) diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 7d52f1e..0020d22 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -166,8 +166,8 @@ void QContiguousCache<T>::detach_helper() T *dest = x.d->array + x.d->start; T *src = d->array + d->start; - int count = x.d->count; - while (count--) { + int oldcount = x.d->count; + while (oldcount--) { if (QTypeInfo<T>::isComplex) { new (dest) T(*src); } else { @@ -200,8 +200,8 @@ void QContiguousCache<T>::setCapacity(int asize) x.d->start = x.d->offset % x.d->alloc; T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc; T *src = d->array + (d->start + d->count-1) % d->alloc; - int count = x.d->count; - while (count--) { + int oldcount = x.d->count; + while (oldcount--) { if (QTypeInfo<T>::isComplex) { new (dest) T(*src); } else { @@ -224,10 +224,10 @@ void QContiguousCache<T>::clear() { if (d->ref == 1) { if (QTypeInfo<T>::isComplex) { - int count = d->count; + int oldcount = d->count; T * i = d->array + d->start; T * e = d->array + d->alloc; - while (count--) { + while (oldcount--) { i->~T(); i++; if (i == e) @@ -254,11 +254,11 @@ inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc) } template <typename T> -QContiguousCache<T>::QContiguousCache(int capacity) +QContiguousCache<T>::QContiguousCache(int cap) { - p = malloc(capacity); + p = malloc(cap); d->ref = 1; - d->alloc = capacity; + d->alloc = cap; d->count = d->start = d->offset = 0; d->sharable = true; } @@ -295,10 +295,10 @@ template <typename T> void QContiguousCache<T>::free(Data *x) { if (QTypeInfo<T>::isComplex) { - int count = d->count; + int oldcount = d->count; T * i = d->array + d->start; T * e = d->array + d->alloc; - while (count--) { + while (oldcount--) { i->~T(); i++; if (i == e) diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 18a252a..0828c61 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -60,8 +60,10 @@ Easing curves describe a function that controls how the speed of the interpolation between 0 and 1 should be. Easing curves allow transitions from one value to another to appear more natural than a simple constant speed would allow. - The QEasingCurve class is usually used in conjunction with the QAnimation class, - but can be used on its own. + The QEasingCurve class is usually used in conjunction with the QVariantAnimation and + QPropertyAnimation classes but can be used on its own. It is usually used to accelerate + the interpolation from zero velocity (ease in) or decelerate to zero velocity (ease out). + Ease in and ease out can also be combined in the same easing curve. To calculate the speed of the interpolation, the easing curve provides the function valueForProgress(), where the \a progress argument specifies the progress of the @@ -80,10 +82,10 @@ \endcode will print the effective progress of the interpolation between 0 and 1. - When using a QAnimation, the easing curve will be used to control the + When using a QPropertyAnimation, the associated easing curve will be used to control the progress of the interpolation between startValue and endValue: \code - QAnimation animation; + QPropertyAnimation animation; animation.setStartValue(0); animation.setEndValue(1000); animation.setDuration(1000); @@ -98,189 +100,191 @@ \value Linear \inlineimage qeasingcurve-linear.png \br - Easing equation function for a simple linear tweening, - with no easing. + Easing curve for a linear (t) function: + velocity is constant. \value InQuad \inlineimage qeasingcurve-inquad.png \br - Easing equation function for a quadratic (t^2) easing - in: accelerating from zero velocity. + Easing curve for a quadratic (t^2) function: + accelerating from zero velocity. \value OutQuad \inlineimage qeasingcurve-outquad.png \br - Easing equation function for a quadratic (t^2) easing - out: decelerating to zero velocity. + Easing curve for a quadratic (t^2) function: + decelerating to zero velocity. \value InOutQuad \inlineimage qeasingcurve-inoutquad.png \br - Easing equation function for a quadratic (t^2) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a quadratic (t^2) function: + acceleration until halfway, then deceleration. \value OutInQuad \inlineimage qeasingcurve-outinquad.png \br - Easing equation function for a quadratic (t^2) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a quadratic (t^2) function: + deceleration until halfway, then acceleration. \value InCubic \inlineimage qeasingcurve-incubic.png \br - Easing equation function for a cubic (t^3) easing - in: accelerating from zero velocity. + Easing curve for a cubic (t^3) function: + accelerating from zero velocity. \value OutCubic \inlineimage qeasingcurve-outcubic.png \br - Easing equation function for a cubic (t^3) easing - out: decelerating from zero velocity. + Easing curve for a cubic (t^3) function: + decelerating from zero velocity. \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png \br - Easing equation function for a cubic (t^3) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a cubic (t^3) function: + acceleration until halfway, then deceleration. \value OutInCubic \inlineimage qeasingcurve-outincubic.png \br - Easing equation function for a cubic (t^3) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a cubic (t^3) function: + deceleration until halfway, then acceleration. \value InQuart \inlineimage qeasingcurve-inquart.png \br - Easing equation function for a quartic (t^4) easing - in: accelerating from zero velocity. + Easing curve for a quartic (t^4) function: + accelerating from zero velocity. \value OutQuart \inlineimage qeasingcurve-outquart.png \br - Easing equation function for a quartic (t^4) easing - out: decelerating from zero velocity. + Easing curve for a cubic (t^4) function: + decelerating from zero velocity. \value InOutQuart \inlineimage qeasingcurve-inoutquart.png \br - Easing equation function for a quartic (t^4) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a cubic (t^4) function: + acceleration until halfway, then deceleration. \value OutInQuart \inlineimage qeasingcurve-outinquart.png \br - Easing equation function for a quartic (t^4) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a cubic (t^4) function: + deceleration until halfway, then acceleration. \value InQuint \inlineimage qeasingcurve-inquint.png \br - Easing equation function for a quintic (t^5) easing + Easing curve for a quintic (t^5) easing in: accelerating from zero velocity. \value OutQuint \inlineimage qeasingcurve-outquint.png \br - Easing equation function for a quintic (t^5) easing - out: decelerating from zero velocity. + Easing curve for a cubic (t^5) function: + decelerating from zero velocity. \value InOutQuint \inlineimage qeasingcurve-inoutquint.png \br - Easing equation function for a quintic (t^5) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a cubic (t^5) function: + acceleration until halfway, then deceleration. \value OutInQuint \inlineimage qeasingcurve-outinquint.png \br - Easing equation function for a quintic (t^5) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a cubic (t^5) function: + deceleration until halfway, then acceleration. \value InSine \inlineimage qeasingcurve-insine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - in: accelerating from zero velocity. + Easing curve for a sinusoidal (sin(t)) function: + accelerating from zero velocity. \value OutSine \inlineimage qeasingcurve-outsine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - out: decelerating from zero velocity. + Easing curve for a sinusoidal (sin(t)) function: + decelerating from zero velocity. \value InOutSine \inlineimage qeasingcurve-inoutsine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a sinusoidal (sin(t)) function: + acceleration until halfway, then deceleration. \value OutInSine \inlineimage qeasingcurve-outinsine.png \br - Easing equation function for a sinusoidal (sin(t)) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a sinusoidal (sin(t)) function: + deceleration until halfway, then acceleration. \value InExpo \inlineimage qeasingcurve-inexpo.png \br - Easing equation function for an exponential (2^t) easing - in: accelerating from zero velocity. + Easing curve for an exponential (2^t) function: + accelerating from zero velocity. \value OutExpo \inlineimage qeasingcurve-outexpo.png \br - Easing equation function for an exponential (2^t) easing - out: decelerating from zero velocity. + Easing curve for an exponential (2^t) function: + decelerating from zero velocity. \value InOutExpo \inlineimage qeasingcurve-inoutexpo.png \br - Easing equation function for an exponential (2^t) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for an exponential (2^t) function: + acceleration until halfway, then deceleration. \value OutInExpo \inlineimage qeasingcurve-outinexpo.png \br - Easing equation function for an exponential (2^t) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for an exponential (2^t) function: + deceleration until halfway, then acceleration. \value InCirc \inlineimage qeasingcurve-incirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - in: accelerating from zero velocity. + Easing curve for a circular (sqrt(1-t^2)) function: + accelerating from zero velocity. \value OutCirc \inlineimage qeasingcurve-outcirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - out: decelerating from zero velocity. + Easing curve for a circular (sqrt(1-t^2)) function: + decelerating from zero velocity. \value InOutCirc \inlineimage qeasingcurve-inoutcirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - in/out: acceleration until halfway, then deceleration. + Easing curve for a circular (sqrt(1-t^2)) function: + acceleration until halfway, then deceleration. \value OutInCirc \inlineimage qeasingcurve-outincirc.png \br - Easing equation function for a circular (sqrt(1-t^2)) easing - out/in: deceleration until halfway, then acceleration. + Easing curve for a circular (sqrt(1-t^2)) function: + deceleration until halfway, then acceleration. \value InElastic \inlineimage qeasingcurve-inelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing in: + Easing curve for an elastic + (exponentially decaying sine wave) function: accelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter. \value OutElastic \inlineimage qeasingcurve-outelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing out: + Easing curve for an elastic + (exponentially decaying sine wave) function: decelerating from zero velocity. The peak amplitude can be set with the \e amplitude parameter, and the period of decay by the \e period parameter. \value InOutElastic \inlineimage qeasingcurve-inoutelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing in/out: + Easing curve for an elastic + (exponentially decaying sine wave) function: acceleration until halfway, then deceleration. \value OutInElastic \inlineimage qeasingcurve-outinelastic.png \br - Easing equation function for an elastic - (exponentially decaying sine wave) easing out/in: + Easing curve for an elastic + (exponentially decaying sine wave) function: deceleration until halfway, then acceleration. \value InBack \inlineimage qeasingcurve-inback.png \br - Easing equation function for a back (overshooting - cubic easing: (s+1)*t^3 - s*t^2) easing in: + Easing curve for a back (overshooting + cubic function: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity. \value OutBack \inlineimage qeasingcurve-outback.png \br - Easing equation function for a back (overshooting - cubic easing: (s+1)*t^3 - s*t^2) easing out: - decelerating from zero velocity. + Easing curve for a back (overshooting + cubic function: (s+1)*t^3 - s*t^2) easing out: + decelerating to zero velocity. \value InOutBack \inlineimage qeasingcurve-inoutback.png \br - Easing equation function for a back (overshooting - cubic easing: (s+1)*t^3 - s*t^2) easing in/out: + Easing curve for a back (overshooting + cubic function: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration. \value OutInBack \inlineimage qeasingcurve-outinback.png \br - Easing equation function for a back (overshooting + Easing curve for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration. \value InBounce \inlineimage qeasingcurve-inbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing in: accelerating + Easing curve for a bounce (exponentially + decaying parabolic bounce) function: accelerating from zero velocity. \value OutBounce \inlineimage qeasingcurve-outbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing out: decelerating + Easing curve for a bounce (exponentially + decaying parabolic bounce) function: decelerating from zero velocity. \value InOutBounce \inlineimage qeasingcurve-inoutbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing in/out: + Easing curve for a bounce (exponentially + decaying parabolic bounce) function easing in/out: acceleration until halfway, then deceleration. \value OutInBounce \inlineimage qeasingcurve-outinbounce.png \br - Easing equation function for a bounce (exponentially - decaying parabolic bounce) easing out/in: + Easing curve for a bounce (exponentially + decaying parabolic bounce) function easing out/in: deceleration until halfway, then acceleration. \omitvalue InCurve \omitvalue OutCurve \omitvalue SineCurve \omitvalue CosineCurve - \value Custom This is returned if the user have specified a custom curve type with setCustomType(). Note that you cannot call setType() with this value, but type() can return it. + \value Custom This is returned if the user specified a custom curve type with + setCustomType(). Note that you cannot call setType() with this value, + but type() can return it. \omitvalue NCurveTypes */ diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 296d5a0..85e49c7 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -5299,7 +5299,11 @@ struct p5s_deleter { ~p5s_deleter() { - Bfree(p5s); + while (p5s) { + Bigint *next = p5s->next; + Bfree(p5s); + p5s = next; + } } }; diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b97ba45..99fbaa9 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -6028,6 +6028,7 @@ QString QString::repeated(int times) const return result; } +void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from); /*! \overload \fn QString QString::normalized(NormalizationForm mode, QChar::UnicodeVersion version) const @@ -6037,42 +6038,48 @@ QString QString::repeated(int times) const */ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersion version) const { + QString copy = *this; + qt_string_normalize(©, mode, version, 0); + return copy; +} + +void qt_string_normalize(QString *data, QString::NormalizationForm mode, QChar::UnicodeVersion version, int from) +{ bool simple = true; - for (int i = 0; i < d->size; ++i) { - if (d->data[i] >= 0x80) { + const QChar *p = data->constData(); + int len = data->length(); + for (int i = from; i < len; ++i) { + if (p[i].unicode() >= 0x80) { simple = false; break; } } if (simple) - return *this; + return; - QString s = *this; + QString &s = *data; if (version != CURRENT_VERSION) { for (int i = 0; i < NumNormalizationCorrections; ++i) { const NormalizationCorrection &n = uc_normalization_corrections[i]; if (n.version > version) { + int pos = from; if (n.ucs4 > 0xffff) { ushort ucs4High = QChar::highSurrogate(n.ucs4); ushort ucs4Low = QChar::lowSurrogate(n.ucs4); ushort oldHigh = QChar::highSurrogate(n.old_mapping); ushort oldLow = QChar::lowSurrogate(n.old_mapping); - int pos = 0; - while (pos < s.d->size - 1) { - if (s.d->data[pos] == ucs4High && s.d->data[pos + 1] == ucs4Low) { - s.detach(); - s.d->data[pos] = oldHigh; - s.d->data[pos + 1] = oldLow; + while (pos < s.length() - 1) { + if (s.at(pos).unicode() == ucs4High && s.at(pos + 1).unicode() == ucs4Low) { + s[pos] = oldHigh; + s[pos + 1] = oldLow; ++pos; } ++pos; } } else { - int pos = 0; - while (pos < s.d->size) { - if (s.d->data[pos] == n.ucs4) { - s.detach(); - s.d->data[pos] = n.old_mapping; + while (pos < s.length()) { + if (s.at(pos).unicode() == n.ucs4) { + s[pos] = n.old_mapping; } ++pos; } @@ -6080,15 +6087,14 @@ QString QString::normalized(QString::NormalizationForm mode, QChar::UnicodeVersi } } } - s = decomposeHelper(s, mode < QString::NormalizationForm_KD, version); + decomposeHelper(data, mode < QString::NormalizationForm_KD, version, from); - s = canonicalOrderHelper(s, version); + canonicalOrderHelper(data, version, from); if (mode == QString::NormalizationForm_D || mode == QString::NormalizationForm_KD) - return s; - - return composeHelper(s); + return; + composeHelper(data, from); } diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index 5a2b37a..5c550af 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -41,6 +41,7 @@ #include <qstringlist.h> #include <qset.h> +#include <qstringmatcher.h> QT_BEGIN_NAMESPACE diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 665c0d0..f36567a 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -47,7 +47,6 @@ #include <QtCore/qlist.h> #include <QtCore/qregexp.h> #include <QtCore/qstring.h> -#include <QtCore/qstringmatcher.h> #ifdef QT_INCLUDE_COMPAT #include <Qt3Support/q3valuelist.h> #endif diff --git a/src/corelib/tools/qstringmatcher.h b/src/corelib/tools/qstringmatcher.h index 2b8edc9..61b7a95 100644 --- a/src/corelib/tools/qstringmatcher.h +++ b/src/corelib/tools/qstringmatcher.h @@ -81,13 +81,14 @@ private: // explicitely allow anonymous unions for RVCT to prevent compiler warnings #pragma anon_unions #endif + struct Data { + uchar q_skiptable[256]; + const QChar *uc; + int len; + }; union { uint q_data[256]; - struct { - uchar q_skiptable[256]; - const QChar *uc; - int len; - } p; + Data p; }; }; diff --git a/src/dbus/qdbusmarshaller.cpp b/src/dbus/qdbusmarshaller.cpp index bb7fa6b..7207b4c 100644 --- a/src/dbus/qdbusmarshaller.cpp +++ b/src/dbus/qdbusmarshaller.cpp @@ -397,16 +397,6 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) case DBUS_TYPE_DOUBLE: qIterAppend(&iterator, ba, *signature, arg.constData()); return true; - - case DBUS_TYPE_STRING: - case DBUS_TYPE_OBJECT_PATH: - case DBUS_TYPE_SIGNATURE: { - const QByteArray data = - reinterpret_cast<const QString *>(arg.constData())->toUtf8(); - const char *rawData = data.constData(); - qIterAppend(&iterator, ba, *signature, &rawData); - return true; - } #else case DBUS_TYPE_BYTE: append( qvariant_cast<uchar>(arg) ); @@ -435,6 +425,8 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) case DBUS_TYPE_DOUBLE: append( arg.toDouble() ); return true; +#endif + case DBUS_TYPE_STRING: append( arg.toString() ); return true; @@ -444,7 +436,6 @@ bool QDBusMarshaller::appendVariantInternal(const QVariant &arg) case DBUS_TYPE_SIGNATURE: append( qvariant_cast<QDBusSignature>(arg) ); return true; -#endif // compound types: case DBUS_TYPE_VARIANT: diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 19080de..8dc8159 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -210,6 +210,7 @@ public: PageTabList = 0x0000003C, Clock = 0x0000003D, Splitter = 0x0000003E, + // Additional Qt roles where enum value does not map directly to MSAA: LayeredPane = 0x0000003F, UserRole = 0x0000ffff }; diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp index bfacb94..85f1a8d 100644 --- a/src/gui/accessible/qaccessible_win.cpp +++ b/src/gui/accessible/qaccessible_win.cpp @@ -1051,6 +1051,8 @@ HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT Role role = accessible->role(varID.lVal); if (role != NoRole) { + if (role == LayeredPane) + role = QAccessible::Pane; (*pvarRole).vt = VT_I4; (*pvarRole).lVal = role; } else { diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp index b7fa420..31f73b9 100644 --- a/src/gui/dialogs/qmessagebox.cpp +++ b/src/gui/dialogs/qmessagebox.cpp @@ -1362,8 +1362,10 @@ void QMessageBox::setVisible(bool visible) /*! \overload - Opens the dialog and connects its accepted() signal to the slot specified - by \a receiver and \a member. + Opens the dialog and connects its finished() or buttonClicked() signal to + the slot specified by \a receiver and \a member. If the slot in \a member + has a pointer for its first parameter the connection is to buttonClicked(), + otherwise the connection is to finished(). The signal will be disconnected from the slot when the dialog is closed. */ diff --git a/src/gui/embedded/qscreenproxy_qws.cpp b/src/gui/embedded/qscreenproxy_qws.cpp index ade16ca..3d7451b 100644 --- a/src/gui/embedded/qscreenproxy_qws.cpp +++ b/src/gui/embedded/qscreenproxy_qws.cpp @@ -537,7 +537,7 @@ int QProxyScreen::transformOrientation() const } /*! -\reimp +\internal */ int QProxyScreen::memoryNeeded(const QString &str) { @@ -548,7 +548,7 @@ int QProxyScreen::memoryNeeded(const QString &str) } /*! -\reimp +\internal */ int QProxyScreen::sharedRamSize(void *ptr) { @@ -559,7 +559,7 @@ int QProxyScreen::sharedRamSize(void *ptr) } /*! -\reimp +\internal */ void QProxyScreen::haltUpdates() { @@ -568,7 +568,7 @@ void QProxyScreen::haltUpdates() } /*! -\reimp +\internal */ void QProxyScreen::resumeUpdates() { diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index ef7341a..1f9f944 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -418,7 +418,7 @@ static QImage blurred(const QImage& image, const QRect& rect, int radius) int QGraphicsBlurEffect::blurRadius() const { Q_D(const QGraphicsBlurEffect); - return int(d->filter->blurRadius()); + return int(d->filter->radius()); } void QGraphicsBlurEffect::setBlurRadius(int radius) diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 2d4a5ee..5348ae9 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -66,8 +66,6 @@ QT_BEGIN_NAMESPACE -class QPainter; - class QGraphicsEffectSourcePrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffectSource) @@ -87,7 +85,7 @@ public: friend class QGraphicsItemPrivate; }; -class QGraphicsEffectPrivate : public QObjectPrivate +class Q_GUI_EXPORT QGraphicsEffectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffect) public: diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 223c747..5178d80 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2553,6 +2553,8 @@ void QGraphicsItem::setHandlesChildEvents(bool enabled) */ bool QGraphicsItem::hasFocus() const { + if (d_ptr->focusProxy) + return d_ptr->focusProxy->hasFocus(); return (d_ptr->scene && d_ptr->scene->focusItem() == this); } @@ -2578,12 +2580,16 @@ void QGraphicsItem::setFocus(Qt::FocusReason focusReason) { if (!d_ptr->scene || !isEnabled() || hasFocus() || !(d_ptr->flags & ItemIsFocusable)) return; - if (isVisible()) { + QGraphicsItem *item = this; + QGraphicsItem *f; + while ((f = item->d_ptr->focusProxy)) + item = f; + if (item->isVisible()) { // Visible items immediately gain focus from scene. - d_ptr->scene->setFocusItem(this, focusReason); - } else if (d_ptr->isWidget) { + d_ptr->scene->d_func()->setFocusItemHelper(item, focusReason); + } else if (item->d_ptr->isWidget) { // Just set up subfocus. - static_cast<QGraphicsWidget *>(this)->d_func()->setFocusWidget(); + static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget(); } } @@ -2606,13 +2612,73 @@ void QGraphicsItem::clearFocus() // Invisible widget items with focus must explicitly clear subfocus. static_cast<QGraphicsWidget *>(this)->d_func()->clearFocusWidget(); } - if (d_ptr->scene->focusItem() == this) { + if (hasFocus()) { // If this item has the scene's input focus, clear it. d_ptr->scene->setFocusItem(0); } } /*! + \since 4.6 + + Returns this item's focus proxy, or 0 if the item + does not have any focus proxy. + + \sa setFocusProxy() +*/ +QGraphicsItem *QGraphicsItem::focusProxy() const +{ + return d_ptr->focusProxy; +} + +/*! + \since 4.6 + + Sets the item's focus proxy to \a item. + + If an item has a focus proxy, the focus proxy will receive + input focus when the item gains input focus. The item itself + will still have focus (i.e., hasFocus() will return true), + but only the focus proxy will receive the keyboard input. + + A focus proxy can itself have a focus proxy, and so on. In + such case, keyboard input will be handled by the outermost + focus proxy. + + \sa focusProxy() +*/ +void QGraphicsItem::setFocusProxy(QGraphicsItem *item) +{ + if (item == d_ptr->focusProxy) + return; + if (item == this) { + qWarning("QGraphicsItem::setFocusProxy: cannot assign self as focus proxy"); + return; + } + if (item) { + if (item->d_ptr->scene != d_ptr->scene) { + qWarning("QGraphicsItem::setFocusProxy: focus proxy must be in same scene"); + return; + } + for (QGraphicsItem *f = item->focusProxy(); f != 0; f = f->focusProxy()) { + if (f == this) { + qWarning("QGraphicsItem::setFocusProxy: %p is already in the focus proxy chain", item); + return; + } + } + } + + QGraphicsItem *lastFocusProxy = d_ptr->focusProxy; + d_ptr->focusProxy = item; + if (d_ptr->scene) { + if (lastFocusProxy) + d_ptr->scene->d_func()->focusProxyReverseMap.remove(lastFocusProxy, this); + if (item) + d_ptr->scene->d_func()->focusProxyReverseMap.insert(item, this); + } +} + +/*! \since 4.4 Grabs the mouse input. diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 0c20829..afbaf24 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -233,6 +233,9 @@ public: void setFocus(Qt::FocusReason focusReason = Qt::OtherFocusReason); void clearFocus(); + QGraphicsItem *focusProxy() const; + void setFocusProxy(QGraphicsItem *item); + void grabMouse(); void ungrabMouse(); void grabKeyboard(); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index ff1ca09..69d8b5f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -125,6 +125,7 @@ public: index(-1), siblingIndex(-1), depth(0), + focusProxy(0), acceptedMouseButtons(0x1f), visible(1), explicitlyHidden(0), @@ -413,6 +414,7 @@ public: int index; int siblingIndex; int depth; + QGraphicsItem *focusProxy; // Packed 32 bytes quint32 acceptedMouseButtons : 5; @@ -455,7 +457,7 @@ public: quint32 acceptedTouchBeginEvent : 1; quint32 filtersDescendantEvents : 1; quint32 sceneTransformTranslateOnly : 1; - quint32 unused : 7; // feel free to use + quint32 unused : 6; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7b02883..5cd0ab2 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -492,6 +492,13 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) item->d_func()->scene = 0; + // Unregister focus proxy. + QMultiHash<QGraphicsItem *, QGraphicsItem *>::iterator it = focusProxyReverseMap.find(item); + while (it != focusProxyReverseMap.end() && it.key() == item) { + it.value()->d_ptr->focusProxy = 0; + it = focusProxyReverseMap.erase(it); + } + // Remove from parent, or unregister from toplevels. if (QGraphicsItem *parentItem = item->parentItem()) { if (parentItem->scene()) { @@ -560,6 +567,58 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) /*! \internal */ +void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, + Qt::FocusReason focusReason) +{ + Q_Q(QGraphicsScene); + if (item == focusItem) + return; + if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable) + || !item->isVisible() || !item->isEnabled())) { + item = 0; + } + + if (item) { + q->setFocus(focusReason); + if (item == focusItem) + return; + } + + if (focusItem) { + QFocusEvent event(QEvent::FocusOut, focusReason); + lastFocusItem = focusItem; + focusItem = 0; + sendEvent(lastFocusItem, &event); + + if (lastFocusItem + && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { + // Reset any visible preedit text + QInputMethodEvent imEvent; + sendEvent(lastFocusItem, &imEvent); + + // Close any external input method panel + for (int i = 0; i < views.size(); ++i) + views.at(i)->inputContext()->reset(); + } + } + + if (item) { + if (item->isWidget()) { + // Update focus child chain. + static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget(); + } + + focusItem = item; + QFocusEvent event(QEvent::FocusIn, focusReason); + sendEvent(item, &event); + } + + updateInputMethodSensitivityInViews(); +} + +/*! + \internal +*/ void QGraphicsScenePrivate::addPopup(QGraphicsWidget *widget) { Q_ASSERT(widget); @@ -1927,21 +1986,42 @@ QPainterPath QGraphicsScene::selectionArea() const } /*! + \since 4.6 + Sets the selection area to \a path. All items within this area are immediately selected, and all items outside are unselected. You can get the list of all selected items by calling selectedItems(). + \a deviceTransform is the transformation that applies to the view, and needs to + be provided if the scene contains items that ignore transformations. + For an item to be selected, it must be marked as \e selectable (QGraphicsItem::ItemIsSelectable). \sa clearSelection(), selectionArea() */ +void QGraphicsScene::setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform) +{ + setSelectionArea(path, Qt::IntersectsItemShape, deviceTransform); +} + +/*! + \obsolete + \overload + + Sets the selection area to \a path. + + This function is deprecated and leads to incorrect results if the scene + contains items that ignore transformations. Use the overload that takes + a QTransform instead. +*/ void QGraphicsScene::setSelectionArea(const QPainterPath &path) { - setSelectionArea(path, Qt::IntersectsItemShape); + setSelectionArea(path, Qt::IntersectsItemShape, QTransform()); } /*! + \obsolete \overload \since 4.3 @@ -2577,49 +2657,10 @@ QGraphicsItem *QGraphicsScene::focusItem() const void QGraphicsScene::setFocusItem(QGraphicsItem *item, Qt::FocusReason focusReason) { Q_D(QGraphicsScene); - if (item == d->focusItem) - return; - if (item && (!(item->flags() & QGraphicsItem::ItemIsFocusable) - || !item->isVisible() || !item->isEnabled())) { - item = 0; - } - - if (item) { - setFocus(focusReason); - if (item == d->focusItem) - return; - } - - if (d->focusItem) { - QFocusEvent event(QEvent::FocusOut, focusReason); - d->lastFocusItem = d->focusItem; - d->focusItem = 0; - d->sendEvent(d->lastFocusItem, &event); - - if (d->lastFocusItem - && (d->lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { - // Reset any visible preedit text - QInputMethodEvent imEvent; - d->sendEvent(d->lastFocusItem, &imEvent); - - // Close any external input method panel - for (int i = 0; i < d->views.size(); ++i) - d->views.at(i)->inputContext()->reset(); - } - } - - if (item) { - if (item->isWidget()) { - // Update focus child chain. - static_cast<QGraphicsWidget *>(item)->d_func()->setFocusWidget(); - } - - d->focusItem = item; - QFocusEvent event(QEvent::FocusIn, focusReason); - d->sendEvent(item, &event); - } - - d->updateInputMethodSensitivityInViews(); + if (item) + item->setFocus(focusReason); + else + d->setFocusItemHelper(item, focusReason); } /*! @@ -2674,15 +2715,17 @@ void QGraphicsScene::clearFocus() /*! \property QGraphicsScene::stickyFocus - \brief whether or not clicking the scene will clear focus + \brief whether clicking into the scene background will clear focus \since 4.6 - If this property is false (the default), then clicking on the scene - background or on an item that does not accept focus, will clear - focus. Otherwise, focus will remain unchanged. + In a QGraphicsScene with stickyFocus set to true, focus will remain + unchanged when the user clicks into the scene background or on an item + that does not accept focus. Otherwise, focus will be cleared. + + By default, this property is false. - The focus change happens in response to a mouse press. You can reimplement + Focus changes in response to a mouse press. You can reimplement mousePressEvent() in a subclass of QGraphicsScene to toggle this property based on where the user has clicked. diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 813e000..67a2983 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -182,8 +182,9 @@ public: QList<QGraphicsItem *> selectedItems() const; QPainterPath selectionArea() const; - void setSelectionArea(const QPainterPath &path); - void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); + void setSelectionArea(const QPainterPath &path); // ### obsolete + void setSelectionArea(const QPainterPath &path, const QTransform &deviceTransform); + void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode); // ### obsolete void setSelectionArea(const QPainterPath &path, Qt::ItemSelectionMode mode, const QTransform &deviceTransform); QGraphicsItemGroup *createItemGroup(const QList<QGraphicsItem *> &items); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index f380ced..56e6224 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -130,6 +130,8 @@ public: QGraphicsWidget *tabFocusFirst; QGraphicsWidget *activeWindow; int activationRefCount; + void setFocusItemHelper(QGraphicsItem *item, Qt::FocusReason focusReason); + QMultiHash<QGraphicsItem *, QGraphicsItem *> focusProxyReverseMap; QList<QGraphicsWidget *> popupWidgets; void addPopup(QGraphicsWidget *widget); diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index ad55dcd..7d7dde1 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -612,9 +612,6 @@ bool QImageData::checkForAlphaPixels() const \table \header \o Function \o Description \row - \o setAlphaChannel() - \o Sets the alpha channel of the image. - \row \o setDotsPerMeterX() \o Defines the aspect ratio by setting the number of pixels that fit horizontally in a physical meter. @@ -5587,7 +5584,7 @@ bool QImage::isDetached() const Note that the image will be converted to the Format_ARGB32_Premultiplied format if the function succeeds. - Use one of the composition mods in QPainter::CompositionMode instead. + Use one of the composition modes in QPainter::CompositionMode instead. \warning This function is expensive. @@ -5665,6 +5662,8 @@ void QImage::setAlphaChannel(const QImage &alphaChannel) /*! + \obsolete + Returns the alpha channel of the image as a new grayscale QImage in which each pixel's red, green, and blue values are given the alpha value of the original image. The color depth of the returned image is 8-bit. @@ -5744,7 +5743,7 @@ QImage QImage::alphaChannel() const Returns true if the image has a format that respects the alpha channel, otherwise returns false. - \sa alphaChannel(), {QImage#Image Information}{Image Information} + \sa {QImage#Image Information}{Image Information} */ bool QImage::hasAlphaChannel() const { diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 72fdec0..3e5c9b7 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1572,24 +1572,24 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) designed and optimized for showing images on screen. QBitmap is only a convenience class that inherits QPixmap, ensuring a depth of 1. The isQBitmap() function returns true if a QPixmap object is - really a bitmap, otherwise returns false. Finally, the QPicture class is a - paint device that records and replays QPainter commands. + really a bitmap, otherwise returns false. Finally, the QPicture class + is a paint device that records and replays QPainter commands. A QPixmap can easily be displayed on the screen using QLabel or one of QAbstractButton's subclasses (such as QPushButton and QToolButton). QLabel has a pixmap property, whereas - QAbstractButton has an icon property. And because QPixmap is a - QPaintDevice subclass, QPainter can be used to draw directly onto - pixmaps. + QAbstractButton has an icon property. In addition to the ordinary constructors, a QPixmap can be constructed using the static grabWidget() and grabWindow() functions which creates a QPixmap and paints the given widget, or - window, in it. + window, into it. + + QPixmap objects can be passed around by value since the QPixmap + class uses implicit data sharing. For more information, see the \l + {Implicit Data Sharing} documentation. QPixmap objects can also be + streamed. - Note that the pixel data in a pixmap is internal and is managed by - the underlying window system. Pixels can only be accessed through - QPainter functions or by converting the QPixmap to a QImage. Depending on the system, QPixmap is stored using a RGB32 or a premultiplied alpha format. If the image has an alpha channel, and if the system allows, the preferred format is premultiplied alpha. @@ -1600,6 +1600,13 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) QPixmap are stored on the client side and don't use any GDI resources). + Note that the pixel data in a pixmap is internal and is managed by + the underlying window system. Because QPixmap is a QPaintDevice + subclass, QPainter can be used to draw directly onto pixmaps. + Pixels can only be accessed through QPainter functions or by + converting the QPixmap to a QImage. However, the fill() function + is available for initializing the entire pixmap with a given color. + There are functions to convert between QImage and QPixmap. Typically, the QImage class is used to load an image file, optionally manipulating the image data, before the QImage @@ -1614,11 +1621,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) there are several functions that enables transformation of the pixmap. - QPixmap objects can be passed around by value since the QPixmap - class uses implicit data sharing. For more information, see the \l - {Implicit Data Sharing} documentation. QPixmap objects can also be - streamed. - \tableofcontents \section1 Reading and Writing Image Files @@ -1675,12 +1677,15 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) The hasAlphaChannel() returns true if the pixmap has a format that respects the alpha channel, otherwise returns false, while the hasAlpha() function returns true if the pixmap has an alpha - channel \e or a mask (otherwise false). + channel \e or a mask (otherwise false). The mask() function returns + the mask as a QBitmap object, which can be set using setMask(). - The alphaChannel() function returns the alpha channel as a new - QPixmap object, while the mask() function returns the mask as a - QBitmap object. The alpha channel and mask can be set using the - setAlphaChannel() and setMask() functions, respectively. + The createHeuristicMask() function creates and returns a 1-bpp + heuristic mask (i.e. a QBitmap) for this pixmap. It works by + selecting a color from one of the corners and then chipping away + pixels of that color, starting at all the edges. The + createMaskFromColor() function creates and returns a mask (i.e. a + QBitmap) for the pixmap based on a given color. \row \o Low-level information @@ -1718,14 +1723,7 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) \section1 Pixmap Transformations QPixmap supports a number of functions for creating a new pixmap - that is a transformed version of the original: The - createHeuristicMask() function creates and returns a 1-bpp - heuristic mask (i.e. a QBitmap) for this pixmap. It works by - selecting a color from one of the corners and then chipping away - pixels of that color, starting at all the edges. The - createMaskFromColor() function creates and returns a mask (i.e. a - QBitmap) for the pixmap based on a given color. - + that is a transformed version of the original: The scaled(), scaledToWidth() and scaledToHeight() functions return scaled copies of the pixmap, while the copy() function @@ -1740,11 +1738,6 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) function returns the actual matrix used for transforming the pixmap. - There are also functions for changing attributes of a pixmap. - in-place: The fill() function fills the entire image with the - given color, the setMask() function sets a mask bitmap, and the - setAlphaChannel() function sets the pixmap's alpha channel. - \sa QBitmap, QImage, QImageReader, QImageWriter */ @@ -1763,7 +1756,7 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode) Returns true if this pixmap has an alpha channel, \e or has a mask, otherwise returns false. - \sa hasAlphaChannel(), alphaChannel(), mask() + \sa hasAlphaChannel(), mask() */ bool QPixmap::hasAlpha() const { @@ -1774,7 +1767,7 @@ bool QPixmap::hasAlpha() const Returns true if the pixmap has a format that respects the alpha channel, otherwise returns false. - \sa alphaChannel(), hasAlpha() + \sa hasAlpha() */ bool QPixmap::hasAlphaChannel() const { @@ -1791,6 +1784,7 @@ int QPixmap::metric(PaintDeviceMetric metric) const /*! \fn void QPixmap::setAlphaChannel(const QPixmap &alphaChannel) + \obsolete Sets the alpha channel of this pixmap to the given \a alphaChannel by converting the \a alphaChannel into 32 bit and using the @@ -1828,6 +1822,8 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel) } /*! + \obsolete + Returns the alpha channel of the pixmap as a new grayscale QPixmap in which each pixel's red, green, and blue values are given the alpha value of the original pixmap. The color depth of the returned pixmap is the system depth @@ -1846,7 +1842,9 @@ void QPixmap::setAlphaChannel(const QPixmap &alphaChannel) \image alphachannelimage.png The pixmap and channelImage QPixmaps \warning This is an expensive operation. The alpha channel of the - pixmap is extracted dynamically from the pixeldata. + pixmap is extracted dynamically from the pixeldata. Most usecases of this + function are covered by QPainter and compositionModes which will normally + execute faster. \sa setAlphaChannel(), {QPixmap#Pixmap Information}{Pixmap Information} @@ -1867,7 +1865,7 @@ QPaintEngine *QPixmap::paintEngine() const /*! \fn QBitmap QPixmap::mask() const - Extracts a bitmap mask from the pixmap's alphachannel. + Extracts a bitmap mask from the pixmap's alpha channel. \warning This is potentially an expensive operation. The mask of the pixmap is extracted dynamically from the pixeldata. diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp index 82069d0..ecdcd8c 100644 --- a/src/gui/image/qpixmapcache.cpp +++ b/src/gui/image/qpixmapcache.cpp @@ -64,7 +64,8 @@ QT_BEGIN_NAMESPACE access the global pixmap cache. It creates an internal QCache object for caching the pixmaps. - The cache associates a pixmap with a string as a key or with a QPixmapCache::Key. + The cache associates a pixmap with a user-provided string as a key, + or with a QPixmapCache::Key that the cache generates. Using QPixmapCache::Key for keys is faster than using strings. The string API is very convenient for complex keys but the QPixmapCache::Key API will be very efficient and convenient for a one-to-one object-to-pixmap mapping \mdash in @@ -92,6 +93,17 @@ static int cache_limit = 10240; // 10 MB cache limit for desktop #endif /*! + \class QPixmapCache::Key + \brief The QPixmapCache::Key class can be used for efficient access + to the QPixmapCache. + \since 4.6 + + Use QPixmapCache::insert() to receive an instance of Key generated + by the pixmap cache. You can store the key in your own objects for + a very efficient one-to-one object-to-pixmap mapping. +*/ + +/*! Constructs an empty Key object. */ QPixmapCache::Key::Key() : d(0) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 2b275a3..b7b3733 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -478,6 +478,225 @@ void QPixmapConvolutionFilter::draw(QPainter *painter, const QPointF &p, const Q } } +/*! + \class QPixmapBlurFilter + \since 4.6 + \ingroup multimedia + + \brief The QPixmapBlurFilter class provides blur filtering + for pixmaps. + + QPixmapBlurFilter implements a blur pixmap filter, + which is applied when \l{QPixmapFilter::}{draw()} is called. + + The filter lets you specialize the radius of the blur as well + as the quality. + + By default, the blur effect is produced by applying an exponential + filter generated from the specified blurRadius(). Paint engines + may override this with a custom blur that is faster on the + underlying hardware. + + \sa {Pixmap Filters Example}, QPixmapConvolutionFilter, QPixmapDropShadowFilter + + \internal +*/ + +class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate +{ +public: + QPixmapBlurFilterPrivate() : radius(5), quality(Qt::FastTransformation) {} + + int radius; + Qt::TransformationMode quality; +}; + + +/*! + Constructs a pixmap blur filter. + + \internal +*/ +QPixmapBlurFilter::QPixmapBlurFilter(QObject *parent) + : QPixmapFilter(*new QPixmapBlurFilterPrivate, BlurFilter, parent) +{ +} + +/*! + Destructor of pixmap blur filter. + + \internal +*/ +QPixmapBlurFilter::~QPixmapBlurFilter() +{ +} + +/*! + Sets the radius of the blur filter. Higher radius produces increased blurriness. + + \internal +*/ +void QPixmapBlurFilter::setRadius(int radius) +{ + Q_D(QPixmapBlurFilter); + d->radius = radius; +} + +/*! + Gets the radius of the blur filter. + + \internal +*/ +int QPixmapBlurFilter::radius() const +{ + Q_D(const QPixmapBlurFilter); + return d->radius; +} + +/*! + Setting the quality to FastTransformation causes the implementation + to trade off visual quality to blur the image faster. Setting the + quality to SmoothTransformation causes the implementation to improve + visual quality at the expense of speed. The implementation is free + to ignore this value if it only has a single blur algorithm. + + \internal +*/ +void QPixmapBlurFilter::setQuality(Qt::TransformationMode quality) +{ + Q_D(QPixmapBlurFilter); + d->quality = quality; +} + +/*! + Gets the quality of the blur filter. + + \internal +*/ +Qt::TransformationMode QPixmapBlurFilter::quality() const +{ + Q_D(const QPixmapBlurFilter); + return d->quality; +} + +/*! + \reimp + + \internal +*/ +QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const +{ + return rect; +} + +// Blur the image according to the blur radius +// Based on exponential blur algorithm by Jani Huhtanen +// (maximum radius is set to 16) +static QImage blurred(const QImage& image, const QRect& rect, int radius) +{ + int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; + int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; + + QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); + int r1 = rect.top(); + int r2 = rect.bottom(); + int c1 = rect.left(); + int c2 = rect.right(); + + int bpl = result.bytesPerLine(); + int rgba[4]; + unsigned char* p; + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r1) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += bpl; + for (int j = r1; j < r2; j++, p += bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c1 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p += 4; + for (int j = c1; j < c2; j++, p += 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int col = c1; col <= c2; col++) { + p = result.scanLine(r2) + col * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= bpl; + for (int j = r1; j < r2; j++, p -= bpl) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + for (int row = r1; row <= r2; row++) { + p = result.scanLine(row) + c2 * 4; + for (int i = 0; i < 4; i++) + rgba[i] = p[i] << 4; + + p -= 4; + for (int j = c1; j < c2; j++, p -= 4) + for (int i = 0; i < 4; i++) + p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; + } + + return result; +} + +/*! + \reimp + + \internal +*/ +void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &p, const QPixmap &src, const QRectF &srcRect) const +{ + Q_D(const QPixmapBlurFilter); + if (!painter->isActive()) + return; + + if (d->radius == 0) { + painter->drawPixmap(srcRect.translated(p), src, srcRect); + return; + } + + QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? + static_cast<QPaintEngineEx *>(painter->paintEngine())->createPixmapFilter(type()) : 0; + QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(filter); + if (blurFilter) { + blurFilter->setRadius(d->radius); + blurFilter->setQuality(d->quality); + blurFilter->draw(painter, p, src, srcRect); + delete blurFilter; + return; + } + + QImage srcImage; + QImage destImage; + + if (srcRect.isNull()) { + srcImage = src.toImage(); + destImage = blurred(srcImage, srcImage.rect(), d->radius); + } else { + QRect rect = srcRect.toAlignedRect().intersected(src.rect()); + + srcImage = src.copy(rect).toImage(); + destImage = blurred(srcImage, srcImage.rect(), d->radius); + } + + painter->drawImage(p, destImage); +} + // grayscales the image to dest (could be same). If rect isn't defined // destination image size is used to determine the dimension of grayscaling // process. @@ -841,235 +1060,4 @@ void QPixmapDropShadowFilter::draw(QPainter *p, p->drawPixmap(pos, px, src); } -/*! - \class QPixmapBlurFilter - \since 4.6 - \ingroup multimedia - - \brief The QPixmapBlurFilter class is a convenience class - for drawing pixmaps with blur effects. - - By default, the blur effect is produced by applying an exponential - filter generated from the specified blurRadius(). Paint engines - may override this with a custom blur that is faster on the - underlying hardware. - - \sa QPixmapConvolutionFilter - - \internal - */ - -class QPixmapBlurFilterPrivate : public QPixmapFilterPrivate -{ -public: - QPixmapBlurFilterPrivate() - : quality(QPixmapBlurFilter::High), radius(1) {} - - QPixmapBlurFilter::BlurQuality quality; - qreal radius; -}; - -/*! - Constructs blur filter and attaches it to \a parent. - - \internal -*/ -QPixmapBlurFilter::QPixmapBlurFilter(QObject *parent) - : QPixmapFilter(*new QPixmapBlurFilterPrivate, BlurFilter, parent) -{ - Q_D(QPixmapBlurFilter); - setBlurRadius(4); -} - -/*! - Destroys blur filter. - - \internal -*/ -QPixmapBlurFilter::~QPixmapBlurFilter() -{ -} - -/*! - \enum QPixmapFilter::BlurQuality - \since 4.6 - \ingroup multimedia - This enum describes the quality of blur to apply to pixmaps. - - \value Fast Blur faster, potentially losing some quality. - \value High Produce the best high-quality blur possible, even if slower. - - \internal -*/ - -/*! - Returns the quality of the blur. The default value is High. - - \sa blurRadius() - \internal -*/ -QPixmapBlurFilter::BlurQuality QPixmapBlurFilter::blurQuality() const -{ - Q_D(const QPixmapBlurFilter); - return d->quality; -} - -/*! - Sets the quality of the blur to the \a blurQuality specified. - - Setting the quality to Faster causes the implementation to trade - off visual quality to blur the image faster. Setting the quality - to High causes the implementation to improve visual quality - at the expense of speed. The implementation is free to ignore - this value if it only has a single blur algorithm. - - \sa setBlurRadius() - \internal -*/ -void QPixmapBlurFilter::setBlurQuality(BlurQuality blurQuality) -{ - Q_D(QPixmapBlurFilter); - d->quality = blurQuality; -} - -/*! - Returns the radius in pixels of the blur. The default value is 4. - - A smaller radius results in a sharper image. - - \sa blurQuality() - \internal -*/ -qreal QPixmapBlurFilter::blurRadius() const -{ - Q_D(const QPixmapBlurFilter); - return d->radius; -} - -/*! - Sets the radius in pixels of the blur to the \a radius specified. - - Using a smaller radius results in a sharper image. - - \sa setBlurQuality() - \internal -*/ -void QPixmapBlurFilter::setBlurRadius(qreal blurRadius) -{ - Q_D(QPixmapBlurFilter); - d->radius = blurRadius; -} - -/*! - \internal - */ -QRectF QPixmapBlurFilter::boundingRectFor(const QRectF &rect) const -{ - Q_D(const QPixmapBlurFilter); - qreal delta = d->radius * 3; - QRectF blurRect(rect); - blurRect.adjust(-delta, -delta, delta, delta); - return blurRect; -} - -// Blur the image according to the blur radius -// Based on exponential blur algorithm by Jani Huhtanen -// (maximum radius is set to 16) -static QImage blurred(const QImage& image, const QRect& rect, int radius) -{ - int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 }; - int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1]; - - QImage result = image.convertToFormat(QImage::Format_ARGB32_Premultiplied); - int r1 = rect.top(); - int r2 = rect.bottom(); - int c1 = rect.left(); - int c2 = rect.right(); - - int bpl = result.bytesPerLine(); - int rgba[4]; - unsigned char* p; - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r1) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += bpl; - for (int j = r1; j < r2; j++, p += bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c1 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p += 4; - for (int j = c1; j < c2; j++, p += 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int col = c1; col <= c2; col++) { - p = result.scanLine(r2) + col * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= bpl; - for (int j = r1; j < r2; j++, p -= bpl) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - for (int row = r1; row <= r2; row++) { - p = result.scanLine(row) + c2 * 4; - for (int i = 0; i < 4; i++) - rgba[i] = p[i] << 4; - - p -= 4; - for (int j = c1; j < c2; j++, p -= 4) - for (int i = 0; i < 4; i++) - p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4; - } - - return result; -} - -/*! - \internal - */ -void QPixmapBlurFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const -{ - Q_D(const QPixmapBlurFilter); - - QPixmapFilter *filter = painter->paintEngine() && painter->paintEngine()->isExtended() ? - static_cast<QPaintEngineEx *>(painter->paintEngine())->createPixmapFilter(type()) : 0; - QPixmapBlurFilter *blurFilter = static_cast<QPixmapBlurFilter*>(filter); - if (blurFilter) { - blurFilter->setBlurQuality(d->quality); - blurFilter->setBlurRadius(d->radius); - blurFilter->draw(painter, dest, src, srcRect); - delete blurFilter; - return; - } - - QImage srcImage; - QImage destImage; - - if (srcRect.isNull()) { - srcImage = src.toImage(); - destImage = blurred(srcImage, srcImage.rect(), int(d->radius + 0.5)); - } else { - QRect rect = srcRect.toAlignedRect().intersected(src.rect()); - - srcImage = src.copy(rect).toImage(); - destImage = blurred(srcImage, srcImage.rect(), int(d->radius + 0.5)); - } - - qreal delta = d->radius * 3; - painter->drawImage(dest - QPointF(delta, delta), destImage); -} - QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index ca27cbf..ac393a1 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -118,6 +118,30 @@ private: int columns() const; }; +class QPixmapBlurFilterPrivate; + +class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPixmapBlurFilter) + +public: + QPixmapBlurFilter(QObject *parent = 0); + ~QPixmapBlurFilter(); + + void setRadius(int radius); + void setQuality(Qt::TransformationMode mode); + + int radius() const; + Qt::TransformationMode quality() const; + + QRectF boundingRectFor(const QRectF &rect) const; + void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; + +private: + friend class QGLPixmapBlurFilter; +}; + class QPixmapColorizeFilterPrivate; class Q_GUI_EXPORT QPixmapColorizeFilter : public QPixmapFilter @@ -159,33 +183,6 @@ public: inline void setOffset(qreal dx, qreal dy) { setOffset(QPointF(dx, dy)); } }; -class QPixmapBlurFilterPrivate; - -class Q_GUI_EXPORT QPixmapBlurFilter : public QPixmapFilter -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QPixmapBlurFilter) - -public: - QPixmapBlurFilter(QObject *parent = 0); - ~QPixmapBlurFilter(); - - enum BlurQuality - { - Fast, - High - }; - - BlurQuality blurQuality() const; - void setBlurQuality(BlurQuality blurQuality); - - qreal blurRadius() const; - void setBlurRadius(qreal blurRadius); - - QRectF boundingRectFor(const QRectF &rect) const; - void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; -}; - QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index b168188..3453408 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -819,6 +819,12 @@ QApplication::QApplication(Display *dpy, int &argc, char **argv, #endif // Q_WS_X11 extern void qInitDrawhelperAsm(); +extern int qRegisterGuiVariant(); +extern int qUnregisterGuiVariant(); +#ifndef QT_NO_STATEMACHINE +extern int qRegisterGuiStateMachine(); +extern int qUnregisterGuiStateMachine(); +#endif /*! \fn void QApplicationPrivate::initialize() @@ -832,11 +838,9 @@ void QApplicationPrivate::initialize() if (qt_appType != QApplication::Tty) (void) QApplication::style(); // trigger creation of application style // trigger registering of QVariant's GUI types - extern int qRegisterGuiVariant(); qRegisterGuiVariant(); #ifndef QT_NO_STATEMACHINE // trigger registering of QStateMachine's GUI types - extern int qRegisterGuiStateMachine(); qRegisterGuiStateMachine(); #endif @@ -1060,11 +1064,9 @@ QApplication::~QApplication() #ifndef QT_NO_STATEMACHINE // trigger unregistering of QStateMachine's GUI types - extern int qUnregisterGuiStateMachine(); qUnregisterGuiStateMachine(); #endif // trigger unregistering of QVariant's GUI types - extern int qUnregisterGuiVariant(); qUnregisterGuiVariant(); } diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 3692160..595f220 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -192,99 +192,54 @@ extern "C" { #endif #if defined(Q_WS_WIN) -typedef BOOL (WINAPI *qt_RegisterTouchWindowPtr)(HWND, ULONG); -typedef BOOL (WINAPI *qt_GetTouchInputInfoPtr)(HANDLE, UINT, PVOID, int); -typedef BOOL (WINAPI *qt_CloseTouchInputHandlePtr)(HANDLE); - -typedef BOOL (WINAPI *PtrGetGestureInfo)(HANDLE hGestureInfo, PVOID pGestureInfo); -typedef BOOL (WINAPI *PtrGetGestureExtraArgs)(HANDLE hGestureInfo, UINT cbExtraArgs, PBYTE pExtraArgs); -typedef BOOL (WINAPI *PtrCloseGestureInfoHandle)(HANDLE hGestureInfo); -typedef BOOL (WINAPI *PtrSetGestureConfig)(HWND hwnd, DWORD dwReserved, UINT cIDs, - PVOID pGestureConfig, - UINT cbSize); -typedef BOOL (WINAPI *PtrGetGestureConfig)(HWND hwnd, DWORD dwReserved, - DWORD dwFlags, PUINT pcIDs, - PVOID pGestureConfig, - UINT cbSize); - -typedef BOOL (WINAPI *PtrBeginPanningFeedback)(HWND hwnd); -typedef BOOL (WINAPI *PtrUpdatePanningFeedback)(HWND hwnd, LONG, LONG, BOOL); -typedef BOOL (WINAPI *PtrEndPanningFeedback)(HWND hwnd, BOOL); +typedef BOOL (WINAPI *PtrRegisterTouchWindow)(HWND, ULONG); +typedef BOOL (WINAPI *PtrGetTouchInputInfo)(HANDLE, UINT, PVOID, int); +typedef BOOL (WINAPI *PtrCloseTouchInputHandle)(HANDLE); + +typedef BOOL (WINAPI *PtrGetGestureInfo)(HANDLE, PVOID); +typedef BOOL (WINAPI *PtrGetGestureExtraArgs)(HANDLE, UINT, PBYTE); +typedef BOOL (WINAPI *PtrCloseGestureInfoHandle)(HANDLE); +typedef BOOL (WINAPI *PtrSetGestureConfig)(HWND, DWORD, UINT, PVOID, UINT); +typedef BOOL (WINAPI *PtrGetGestureConfig)(HWND, DWORD, DWORD, PUINT, PVOID, UINT); + +typedef BOOL (WINAPI *PtrBeginPanningFeedback)(HWND); +typedef BOOL (WINAPI *PtrUpdatePanningFeedback)(HWND, LONG, LONG, BOOL); +typedef BOOL (WINAPI *PtrEndPanningFeedback)(HWND, BOOL); #ifndef WM_GESTURE +# define WM_GESTURE 0x0119 + +# define GID_BEGIN 1 +# define GID_END 2 +# define GID_ZOOM 3 +# define GID_PAN 4 +# define GID_ROTATE 5 +# define GID_TWOFINGERTAP 6 +# define GID_ROLLOVER 7 -#define WM_GESTURE 0x0119 -#define WM_GESTURE_NOTIFY 0x011A - -DECLARE_HANDLE(HGESTUREINFO); - -#define GF_BEGIN 0x00000001 -#define GF_INERTIA 0x00000002 -#define GF_END 0x00000004 - -/* - * Gesture IDs - */ -#define GID_BEGIN 1 -#define GID_END 2 -#define GID_ZOOM 3 -#define GID_PAN 4 -#define GID_ROTATE 5 -#define GID_TWOFINGERTAP 6 -#define GID_ROLLOVER 7 - -typedef struct tagGESTUREINFO { - UINT cbSize; // size, in bytes, of this structure (including variable length Args field) - DWORD dwFlags; // see GF_* flags - DWORD dwID; // gesture ID, see GID_* defines - HWND hwndTarget; // handle to window targeted by this gesture - POINTS ptsLocation; // current location of this gesture - DWORD dwInstanceID; // internally used - DWORD dwSequenceID; // internally used - ULONGLONG ullArguments; // arguments for gestures whose arguments fit in 8 BYTES - UINT cbExtraArgs; // size, in bytes, of extra arguments, if any, that accompany this gesture -} GESTUREINFO, *PGESTUREINFO; -typedef GESTUREINFO const * PCGESTUREINFO; - -typedef struct tagGESTURENOTIFYSTRUCT { - UINT cbSize; // size, in bytes, of this structure - DWORD dwFlags; // unused - HWND hwndTarget; // handle to window targeted by the gesture - POINTS ptsLocation; // starting location - DWORD dwInstanceID; // internally used -} GESTURENOTIFYSTRUCT, *PGESTURENOTIFYSTRUCT; - -/* - * Gesture argument helpers - * - Angle should be a double in the range of -2pi to +2pi - * - Argument should be an unsigned 16-bit value - */ -#define GID_ROTATE_ANGLE_TO_ARGUMENT(_arg_) ((USHORT)((((_arg_) + 2.0 * 3.14159265) / (4.0 * 3.14159265)) * 65535.0)) -#define GID_ROTATE_ANGLE_FROM_ARGUMENT(_arg_) ((((double)(_arg_) / 65535.0) * 4.0 * 3.14159265) - 2.0 * 3.14159265) - -typedef struct tagGESTURECONFIG { - DWORD dwID; // gesture ID - DWORD dwWant; // settings related to gesture ID that are to be turned on - DWORD dwBlock; // settings related to gesture ID that are to be turned off -} GESTURECONFIG, *PGESTURECONFIG; - -#define GC_ALLGESTURES 0x00000001 -#define GC_ZOOM 0x00000001 -#define GC_PAN 0x00000001 -#define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY 0x00000002 -#define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY 0x00000004 -#define GC_PAN_WITH_GUTTER 0x00000008 -#define GC_PAN_WITH_INERTIA 0x00000010 -#define GC_ROTATE 0x00000001 -#define GC_TWOFINGERTAP 0x00000001 -#define GC_ROLLOVER 0x00000001 -#define GESTURECONFIGMAXCOUNT 256 // Maximum number of gestures that can be included - // in a single call to SetGestureConfig / GetGestureConfig - - - -#define GCF_INCLUDE_ANCESTORS 0x00000001 // If specified, GetGestureConfig returns consolidated configuration - // for the specified window and it's parent window chain +typedef struct tagGESTUREINFO +{ + UINT cbSize; + DWORD dwFlags; + DWORD dwID; + HWND hwndTarget; + POINTS ptsLocation; + DWORD dwInstanceID; + DWORD dwSequenceID; + ULONGLONG ullArguments; + UINT cbExtraArgs; +} GESTUREINFO; + +# define GC_PAN 0x00000001 +# define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY 0x00000002 +# define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY 0x00000004 + +typedef struct tagGESTURECONFIG +{ + DWORD dwID; + DWORD dwWant; + DWORD dwBlock; +} GESTURECONFIG; #endif // WM_GESTURE @@ -559,9 +514,9 @@ public: const QList<QTouchEvent::TouchPoint> &touchPoints); #if defined(Q_WS_WIN) - static qt_RegisterTouchWindowPtr RegisterTouchWindow; - static qt_GetTouchInputInfoPtr GetTouchInputInfo; - static qt_CloseTouchInputHandlePtr CloseTouchInputHandle; + static PtrRegisterTouchWindow RegisterTouchWindow; + static PtrGetTouchInputInfo GetTouchInputInfo; + static PtrCloseTouchInputHandle CloseTouchInputHandle; QHash<DWORD, int> touchInputIDToTouchPointID; QList<QTouchEvent::TouchPoint> appAllTouchPoints; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index cbcac9a..d5c820c 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -3727,7 +3727,7 @@ bool QETWidget::translateGestureEvent(const MSG &msg) gi.dwSequenceID = 0; QApplicationPrivate *qAppPriv = getQApplicationPrivateInternal(); - BOOL bResult = qAppPriv->GetGestureInfo((HGESTUREINFO)msg.lParam, &gi); + BOOL bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi); const QPoint widgetPos = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); QWidget *alienWidget = !internalWinId() ? this : childAt(widgetPos); @@ -3765,7 +3765,7 @@ bool QETWidget::translateGestureEvent(const MSG &msg) if (dwErr > 0) qWarning() << "translateGestureEvent: error = " << dwErr; } - qAppPriv->CloseGestureInfoHandle((HGESTUREINFO)msg.lParam); + qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam); return true; } @@ -3951,17 +3951,17 @@ void QSessionManager::cancel() #endif //QT_NO_SESSIONMANAGER -qt_RegisterTouchWindowPtr QApplicationPrivate::RegisterTouchWindow = 0; -qt_GetTouchInputInfoPtr QApplicationPrivate::GetTouchInputInfo = 0; -qt_CloseTouchInputHandlePtr QApplicationPrivate::CloseTouchInputHandle = 0; +PtrRegisterTouchWindow QApplicationPrivate::RegisterTouchWindow = 0; +PtrGetTouchInputInfo QApplicationPrivate::GetTouchInputInfo = 0; +PtrCloseTouchInputHandle QApplicationPrivate::CloseTouchInputHandle = 0; void QApplicationPrivate::initializeMultitouch_sys() { QLibrary library(QLatin1String("user32")); // MinGW (g++ 3.4.5) accepts only C casts. - RegisterTouchWindow = (qt_RegisterTouchWindowPtr)(library.resolve("RegisterTouchWindow")); - GetTouchInputInfo = (qt_GetTouchInputInfoPtr)(library.resolve("GetTouchInputInfo")); - CloseTouchInputHandle = (qt_CloseTouchInputHandlePtr)(library.resolve("CloseTouchInputHandle")); + RegisterTouchWindow = (PtrRegisterTouchWindow)(library.resolve("RegisterTouchWindow")); + GetTouchInputInfo = (PtrGetTouchInputInfo)(library.resolve("GetTouchInputInfo")); + CloseTouchInputHandle = (PtrCloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); touchInputIDToTouchPointID.clear(); } diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 76138f8..4016563 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -3246,48 +3246,43 @@ int QApplication::x11ProcessEvent(XEvent* event) #ifdef ALIEN_DEBUG //qDebug() << "QApplication::x11ProcessEvent:" << event->type; #endif - Time time = 0, userTime = 0; switch (event->type) { case ButtonPress: pressed_window = event->xbutton.window; - userTime = event->xbutton.time; + X11->userTime = event->xbutton.time; // fallthrough intended case ButtonRelease: - time = event->xbutton.time; + X11->time = event->xbutton.time; break; case MotionNotify: - time = event->xmotion.time; + X11->time = event->xmotion.time; break; case XKeyPress: - userTime = event->xkey.time; + X11->userTime = event->xkey.time; // fallthrough intended case XKeyRelease: - time = event->xkey.time; + X11->time = event->xkey.time; break; case PropertyNotify: - time = event->xproperty.time; + X11->time = event->xproperty.time; break; case EnterNotify: case LeaveNotify: - time = event->xcrossing.time; + X11->time = event->xcrossing.time; break; case SelectionClear: - time = event->xselectionclear.time; + X11->time = event->xselectionclear.time; break; default: -#ifndef QT_NO_XFIXES - if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) { - XFixesSelectionNotifyEvent *req = - reinterpret_cast<XFixesSelectionNotifyEvent *>(event); - time = req->selection_timestamp; - } -#endif break; } - if (time > X11->time) - X11->time = time; - if (userTime > X11->userTime) - X11->userTime = userTime; +#ifndef QT_NO_XFIXES + if (X11->use_xfixes && event->type == (X11->xfixes_eventbase + XFixesSelectionNotify)) { + XFixesSelectionNotifyEvent *req = + reinterpret_cast<XFixesSelectionNotifyEvent *>(event); + X11->time = req->selection_timestamp; + } +#endif QETWidget *widget = (QETWidget*)QWidget::find((WId)event->xany.window); diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp index 01df47d..ab69cdf 100644 --- a/src/gui/kernel/qguivariant.cpp +++ b/src/gui/kernel/qguivariant.cpp @@ -60,6 +60,11 @@ #include "qregion.h" #include "qsizepolicy.h" #include "qtextformat.h" +#include "qmatrix4x4.h" +#include "qvector2d.h" +#include "qvector3d.h" +#include "qvector4d.h" +#include "qquaternion.h" #include "private/qvariant_p.h" @@ -148,6 +153,31 @@ static void construct(QVariant::Private *x, const void *copy) v_construct<QColor>(x, &color); break; } +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + v_construct<QMatrix4x4>(x, copy); + break; +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + v_construct<QVector2D>(x, copy); + break; +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + v_construct<QVector3D>(x, copy); + break; +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + v_construct<QVector4D>(x, copy); + break; +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + v_construct<QQuaternion>(x, copy); + break; +#endif default: qcoreVariantHandler()->construct(x, copy); return; @@ -221,6 +251,31 @@ static void clear(QVariant::Private *d) case QVariant::Pen: v_clear<QPen>(d); break; +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + v_clear<QMatrix4x4>(d); + break; +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + v_clear<QVector2D>(d); + break; +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + v_clear<QVector3D>(d); + break; +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + v_clear<QVector4D>(d); + break; +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + v_clear<QVector4D>(d); + break; +#endif default: qcoreVariantHandler()->clear(d); return; @@ -266,7 +321,26 @@ static bool isNull(const QVariant::Private *d) case QVariant::KeySequence: #endif case QVariant::Pen: +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: +#endif break; +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + return v_cast<QVector2D>(d)->isNull(); +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + return v_cast<QVector3D>(d)->isNull(); +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + return v_cast<QVector4D>(d)->isNull(); +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + return v_cast<QQuaternion>(d)->isNull(); +#endif default: return qcoreVariantHandler()->isNull(d); } @@ -326,6 +400,26 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b) #endif case QVariant::Pen: return *v_cast<QPen>(a) == *v_cast<QPen>(b); +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + return *v_cast<QMatrix4x4>(a) == *v_cast<QMatrix4x4>(b); +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + return *v_cast<QVector2D>(a) == *v_cast<QVector2D>(b); +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + return *v_cast<QVector3D>(a) == *v_cast<QVector3D>(b); +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + return *v_cast<QVector4D>(a) == *v_cast<QVector4D>(b); +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + return *v_cast<QQuaternion>(a) == *v_cast<QQuaternion>(b); +#endif default: break; } @@ -513,6 +607,31 @@ static void streamDebug(QDebug dbg, const QVariant &v) case QVariant::Pen: dbg.nospace() << qvariant_cast<QPen>(v); break; +#ifndef QT_NO_MATRIX4X4 + case QVariant::Matrix4x4: + dbg.nospace() << qvariant_cast<QMatrix4x4>(v); + break; +#endif +#ifndef QT_NO_VECTOR2D + case QVariant::Vector2D: + dbg.nospace() << qvariant_cast<QVector2D>(v); + break; +#endif +#ifndef QT_NO_VECTOR3D + case QVariant::Vector3D: + dbg.nospace() << qvariant_cast<QVector3D>(v); + break; +#endif +#ifndef QT_NO_VECTOR4D + case QVariant::Vector4D: + dbg.nospace() << qvariant_cast<QVector4D>(v); + break; +#endif +#ifndef QT_NO_QUATERNION + case QVariant::Quaternion: + dbg.nospace() << qvariant_cast<QQuaternion>(v); + break; +#endif default: qcoreVariantHandler()->debugStream(dbg, v); break; @@ -596,6 +715,21 @@ Q_DECL_METATYPE_HELPER(QTextLength) Q_DECL_METATYPE_HELPER(QTextFormat) Q_DECL_METATYPE_HELPER(QMatrix) Q_DECL_METATYPE_HELPER(QTransform) +#ifndef QT_NO_MATRIX4X4 +Q_DECL_METATYPE_HELPER(QMatrix4x4) +#endif +#ifndef QT_NO_VECTOR2D +Q_DECL_METATYPE_HELPER(QVector2D) +#endif +#ifndef QT_NO_VECTOR3D +Q_DECL_METATYPE_HELPER(QVector3D) +#endif +#ifndef QT_NO_VECTOR4D +Q_DECL_METATYPE_HELPER(QVector4D) +#endif +#ifndef QT_NO_QUATERNION +Q_DECL_METATYPE_HELPER(QQuaternion) +#endif #ifdef QT_NO_DATASTREAM # define Q_IMPL_METATYPE_HELPER(TYPE) \ @@ -645,7 +779,32 @@ static const QMetaTypeGuiHelper qVariantGuiHelper[] = { Q_IMPL_METATYPE_HELPER(QTextLength), Q_IMPL_METATYPE_HELPER(QTextFormat), Q_IMPL_METATYPE_HELPER(QMatrix), - Q_IMPL_METATYPE_HELPER(QTransform) + Q_IMPL_METATYPE_HELPER(QTransform), +#ifndef QT_NO_MATRIX4X4 + Q_IMPL_METATYPE_HELPER(QMatrix4x4), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_VECTOR2D + Q_IMPL_METATYPE_HELPER(QVector2D), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_VECTOR3D + Q_IMPL_METATYPE_HELPER(QVector3D), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_VECTOR4D + Q_IMPL_METATYPE_HELPER(QVector4D), +#else + {0, 0, 0, 0}, +#endif +#ifndef QT_NO_QUATERNION + Q_IMPL_METATYPE_HELPER(QQuaternion) +#else + {0, 0, 0, 0} +#endif }; static const QVariant::Handler *qt_guivariant_last_handler = 0; diff --git a/src/gui/kernel/qt_cocoa_helpers_mac_p.h b/src/gui/kernel/qt_cocoa_helpers_mac_p.h index 99f058b..af3b4cb 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac_p.h +++ b/src/gui/kernel/qt_cocoa_helpers_mac_p.h @@ -105,6 +105,8 @@ #include <qpoint.h> #include "private/qt_mac_p.h" +struct HIContentBorderMetrics; + #ifdef Q_WS_MAC32 typedef struct _NSPoint NSPoint; // Just redefine here so I don't have to pull in all of Cocoa. #else @@ -122,7 +124,6 @@ bool macWindowToolbarIsVisible( void * /*OSWindowRef*/ window ); void macWindowSetHasShadow( void * /*OSWindowRef*/ window, bool hasShadow ); void macWindowFlush(void * /*OSWindowRef*/ window); void macSendToolbarChangeEvent(QWidget *widget); -struct HIContentBorderMetrics; void qt_mac_updateContentBorderMetricts(void * /*OSWindowRef */window, const ::HIContentBorderMetrics &metrics); void * /*NSImage */qt_mac_create_nsimage(const QPixmap &pm); void qt_mac_update_mouseTracking(QWidget *widget); diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 88f58c8..b4c54a0 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -1794,6 +1794,51 @@ QDebug operator<<(QDebug dbg, const QMatrix4x4 &m) #endif -#endif +#ifndef QT_NO_DATASTREAM + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QMatrix4x4 &matrix) + \relates QMatrix4x4 + + Writes the given \a matrix to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QMatrix4x4 &matrix) +{ + for (int row = 0; row < 4; ++row) + for (int col = 0; col < 4; ++col) + stream << double(matrix(row, col)); + return stream; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QMatrix4x4 &matrix) + \relates QMatrix4x4 + + Reads a 4x4 matrix from the given \a stream into the given \a matrix + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QMatrix4x4 &matrix) +{ + double x; + for (int row = 0; row < 4; ++row) { + for (int col = 0; col < 4; ++col) { + stream >> x; + matrix(row, col) = float(x); + } + } + matrix.inferSpecialType(); + return stream; +} + +#endif // QT_NO_DATASTREAM + +#endif // QT_NO_MATRIX4X4 QT_END_NAMESPACE diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index d63de70..f7246bb 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -960,6 +960,11 @@ inline float *QMatrix4x4::data() Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m); #endif +#ifndef QT_NO_DATASTREAM +Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix4x4 &); +Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix4x4 &); +#endif + template <int N, int M> QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix) { @@ -989,10 +994,6 @@ QGenericMatrix<N, M, qreal, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& QT_END_NAMESPACE -#ifndef QT_NO_MATRIX4X4 -Q_DECLARE_METATYPE(QMatrix4x4) -#endif - QT_END_HEADER #endif diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index d9d4160..841a4c0 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -571,6 +571,51 @@ QDebug operator<<(QDebug dbg, const QQuaternion &q) #endif +#ifndef QT_NO_DATASTREAM + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QQuaternion &quaternion) + \relates QQuaternion + + Writes the given \a quaternion to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QQuaternion &quaternion) +{ + stream << double(quaternion.scalar()) << double(quaternion.x()) + << double(quaternion.y()) << double(quaternion.z()); + return stream; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QQuaternion &quaternion) + \relates QQuaternion + + Reads a quaternion from the given \a stream into the given \a quaternion + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QQuaternion &quaternion) +{ + double scalar, x, y, z; + stream >> scalar; + stream >> x; + stream >> y; + stream >> z; + quaternion.setScalar(qreal(scalar)); + quaternion.setX(qreal(x)); + quaternion.setY(qreal(y)); + quaternion.setZ(qreal(z)); + return stream; +} + +#endif // QT_NO_DATASTREAM + #endif QT_END_NAMESPACE diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index 6b24a04..55c871d 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -324,14 +324,15 @@ inline QVector4D QQuaternion::toVector4D() const Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QQuaternion &q); #endif +#ifndef QT_NO_DATASTREAM +Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QQuaternion &); +Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QQuaternion &); #endif -QT_END_NAMESPACE - -#ifndef QT_NO_QUATERNION -Q_DECLARE_METATYPE(QQuaternion) #endif +QT_END_NAMESPACE + QT_END_HEADER #endif diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp index b492aa8..28f6b7a 100644 --- a/src/gui/math3d/qvector2d.cpp +++ b/src/gui/math3d/qvector2d.cpp @@ -410,6 +410,46 @@ QDebug operator<<(QDebug dbg, const QVector2D &vector) #endif -#endif +#ifndef QT_NO_DATASTREAM + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QVector2D &vector) + \relates QVector2D + + Writes the given \a vector to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QVector2D &vector) +{ + stream << double(vector.x()) << double(vector.y()); + return stream; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QVector2D &vector) + \relates QVector2D + + Reads a 2D vector from the given \a stream into the given \a vector + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QVector2D &vector) +{ + double x, y; + stream >> x; + stream >> y; + vector.setX(qreal(x)); + vector.setY(qreal(y)); + return stream; +} + +#endif // QT_NO_DATASTREAM + +#endif // QT_NO_VECTOR2D QT_END_NAMESPACE diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h index bb62afe..d473c2f 100644 --- a/src/gui/math3d/qvector2d.h +++ b/src/gui/math3d/qvector2d.h @@ -243,14 +243,15 @@ inline QPointF QVector2D::toPointF() const Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector2D &vector); #endif +#ifndef QT_NO_DATASTREAM +Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QVector2D &); +Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector2D &); #endif -QT_END_NAMESPACE - -#ifndef QT_NO_VECTOR2D -Q_DECLARE_METATYPE(QVector2D) #endif +QT_END_NAMESPACE + QT_END_HEADER #endif diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp index 95550cd..881f47c 100644 --- a/src/gui/math3d/qvector3d.cpp +++ b/src/gui/math3d/qvector3d.cpp @@ -558,6 +558,49 @@ QDebug operator<<(QDebug dbg, const QVector3D &vector) #endif -#endif +#ifndef QT_NO_DATASTREAM + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QVector3D &vector) + \relates QVector3D + + Writes the given \a vector to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QVector3D &vector) +{ + stream << double(vector.x()) << double(vector.y()) + << double(vector.z()); + return stream; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QVector3D &vector) + \relates QVector3D + + Reads a 3D vector from the given \a stream into the given \a vector + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QVector3D &vector) +{ + double x, y, z; + stream >> x; + stream >> y; + stream >> z; + vector.setX(qreal(x)); + vector.setY(qreal(y)); + vector.setZ(qreal(z)); + return stream; +} + +#endif // QT_NO_DATASTREAM + +#endif // QT_NO_VECTOR3D QT_END_NAMESPACE diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h index 873b388..7494dcf 100644 --- a/src/gui/math3d/qvector3d.h +++ b/src/gui/math3d/qvector3d.h @@ -271,14 +271,15 @@ inline QPointF QVector3D::toPointF() const Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector3D &vector); #endif +#ifndef QT_NO_DATASTREAM +Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QVector3D &); +Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector3D &); #endif -QT_END_NAMESPACE - -#ifndef QT_NO_VECTOR3D -Q_DECLARE_METATYPE(QVector3D) #endif +QT_END_NAMESPACE + QT_END_HEADER #endif diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp index 1f7d921..1a84db6 100644 --- a/src/gui/math3d/qvector4d.cpp +++ b/src/gui/math3d/qvector4d.cpp @@ -509,6 +509,51 @@ QDebug operator<<(QDebug dbg, const QVector4D &vector) #endif -#endif +#ifndef QT_NO_DATASTREAM + +/*! + \fn QDataStream &operator<<(QDataStream &stream, const QVector4D &vector) + \relates QVector4D + + Writes the given \a vector to the given \a stream and returns a + reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator<<(QDataStream &stream, const QVector4D &vector) +{ + stream << double(vector.x()) << double(vector.y()) + << double(vector.z()) << double(vector.w()); + return stream; +} + +/*! + \fn QDataStream &operator>>(QDataStream &stream, QVector4D &vector) + \relates QVector4D + + Reads a 4D vector from the given \a stream into the given \a vector + and returns a reference to the stream. + + \sa {Format of the QDataStream Operators} +*/ + +QDataStream &operator>>(QDataStream &stream, QVector4D &vector) +{ + double x, y, z, w; + stream >> x; + stream >> y; + stream >> z; + stream >> w; + vector.setX(qreal(x)); + vector.setY(qreal(y)); + vector.setZ(qreal(z)); + vector.setW(qreal(w)); + return stream; +} + +#endif // QT_NO_DATASTREAM + +#endif // QT_NO_VECTOR4D QT_END_NAMESPACE diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h index dcfd87a..cd61496 100644 --- a/src/gui/math3d/qvector4d.h +++ b/src/gui/math3d/qvector4d.h @@ -276,14 +276,15 @@ inline QPointF QVector4D::toPointF() const Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector4D &vector); #endif +#ifndef QT_NO_DATASTREAM +Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QVector4D &); +Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector4D &); #endif -QT_END_NAMESPACE - -#ifndef QT_NO_VECTOR4D -Q_DECLARE_METATYPE(QVector4D) #endif +QT_END_NAMESPACE + QT_END_HEADER #endif diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp index b618d8b..ddc66f3 100644 --- a/src/gui/painting/qgraphicssystemfactory.cpp +++ b/src/gui/painting/qgraphicssystemfactory.cpp @@ -64,6 +64,10 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key) if (system.isEmpty()) { system = QLatin1String("opengl"); } +#elif defined (QT_GRAPHICSSYSTEM_OPENVG) + if (system.isEmpty()) { + system = QLatin1String("openvg"); + } #elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) if (system.isEmpty()) { system = QLatin1String("raster"); diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index 57c9e2d..5298b6a 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -210,6 +210,7 @@ public: Direct3D, Pdf, OpenVG, + OpenGL2, User = 50, // first user type id MaxUser = 100 // last user type id diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 178d519..6735ee6 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -968,8 +968,7 @@ QPdfBaseEngine::QPdfBaseEngine(QPdfBaseEnginePrivate &dd, PaintEngineFeatures f) void QPdfBaseEngine::drawPoints (const QPointF *points, int pointCount) { - Q_D(QPdfBaseEngine); - if (!points || !d->hasPen) + if (!points) return; QPainterPath p; @@ -999,6 +998,12 @@ void QPdfBaseEngine::drawRects (const QRectF *rects, int rectCount) return; Q_D(QPdfBaseEngine); + if (d->useAlphaEngine) { + QAlphaPaintEngine::drawRects(rects, rectCount); + if (!continueCall()) + return; + } + if (d->clipEnabled && d->allClipped) return; if (!d->hasPen && !d->hasBrush) diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp index 01f19c6..8f88781 100644 --- a/src/gui/styles/qcleanlooksstyle.cpp +++ b/src/gui/styles/qcleanlooksstyle.cpp @@ -1745,10 +1745,9 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o int maxWidth = rect.width() - 4; int minWidth = 4; - qint64 progress = (qint64)qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar - double vc6_workaround = ((progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * maxWidth); - int progressBarWidth = (int(vc6_workaround) > minWidth ) ? int(vc6_workaround) : minWidth; - int width = indeterminate ? maxWidth : progressBarWidth; + qreal progress = qMax(bar->progress, bar->minimum); // workaround for bug in QProgressBar + int progressBarWidth = (progress - bar->minimum) * qreal(maxWidth) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum); + int width = indeterminate ? maxWidth : qMax(minWidth, progressBarWidth); bool reverse = (!vertical && (bar->direction == Qt::RightToLeft)) || vertical; if (inverted) diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp index b6ef4c9..660b4c3 100644 --- a/src/gui/styles/qgtkstyle.cpp +++ b/src/gui/styles/qgtkstyle.cpp @@ -2075,8 +2075,8 @@ void QGtkStyle::drawControl(ControlElement element, } if (vertical) rect = QRect(rect.left(), rect.top(), rect.height(), rect.width()); // flip width and height - const int progressIndicatorPos = static_cast<int>((bar->progress - qint64(bar->minimum)) / - qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * rect.width()); + const int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) * rect.width() / + qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum); if (progressIndicatorPos >= 0 && progressIndicatorPos <= rect.width()) leftRect = QRect(rect.left(), rect.top(), progressIndicatorPos, rect.height()); if (vertical) diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp index cd0bd0a..80c9881 100644 --- a/src/gui/styles/qplastiquestyle.cpp +++ b/src/gui/styles/qplastiquestyle.cpp @@ -2571,8 +2571,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op painter->setTransform(m, true); } - double vc6_workaround = ((bar->progress - qint64(bar->minimum)) / qMax(double(1.0), double(qint64(bar->maximum) - qint64(bar->minimum))) * rect.width()); - int progressIndicatorPos = int(vc6_workaround); + int progressIndicatorPos = (bar->progress - qreal(bar->minimum)) / qMax(qreal(1.0), qreal(bar->maximum) - bar->minimum) * rect.width(); bool flip = (!vertical && (((bar->direction == Qt::RightToLeft) && !inverted) || ((bar->direction == Qt::LeftToRight) && inverted))) || (vertical && ((!inverted && !bottomToTop) || (inverted && bottomToTop))); diff --git a/src/gui/widgets/qprogressbar.cpp b/src/gui/widgets/qprogressbar.cpp index d168028..6593cd6 100644 --- a/src/gui/widgets/qprogressbar.cpp +++ b/src/gui/widgets/qprogressbar.cpp @@ -443,11 +443,11 @@ QSize QProgressBar::minimumSizeHint() const QString QProgressBar::text() const { Q_D(const QProgressBar); - if (d->maximum == 0 || d->value < d->minimum + if ((d->maximum == 0 && d->minimum == 0) || d->value < d->minimum || (d->value == INT_MIN && d->minimum == INT_MIN)) return QString(); - qint64 totalSteps = qint64(d->maximum) - qint64(d->minimum); + qint64 totalSteps = qint64(d->maximum) - d->minimum; QString result = d->format; result.replace(QLatin1String("%m"), QString::number(totalSteps)); @@ -461,7 +461,7 @@ QString QProgressBar::text() const return result; } - int progress = int(((qreal(d->value) - qreal(d->minimum)) * 100.0) / totalSteps); + int progress = (qreal(d->value) - d->minimum) * 100.0 / totalSteps; result.replace(QLatin1String("%p"), QString::number(progress)); return result; } diff --git a/src/network/access/qhttp.cpp b/src/network/access/qhttp.cpp index 790b48a..faa2398 100644 --- a/src/network/access/qhttp.cpp +++ b/src/network/access/qhttp.cpp @@ -513,6 +513,7 @@ public: /*! \class QHttpHeader + \obsolete \brief The QHttpHeader class contains header information for HTTP. \ingroup io @@ -1007,6 +1008,7 @@ public: /*! \class QHttpResponseHeader + \obsolete \brief The QHttpResponseHeader class contains response header information for HTTP. \ingroup io @@ -1211,6 +1213,7 @@ public: /*! \class QHttpRequestHeader + \obsolete \brief The QHttpRequestHeader class contains request header information for HTTP. \ingroup io diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index afcdf17..c824fac 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -261,7 +261,12 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair) #ifndef QT_NO_NETWORKPROXY } #endif - // set the gzip header + + // If the request had a accept-encoding set, we better not mess + // with it. If it was not set, we announce that we understand gzip + // and remember this fact in request.d->autoDecompress so that + // we can later decompress the HTTP reply if it has such an + // encoding. value = request.headerField("accept-encoding"); if (value.isEmpty()) { #ifndef QT_NO_COMPRESS @@ -335,8 +340,9 @@ bool QHttpNetworkConnectionPrivate::ensureConnection(QAbstractSocket *socket) #ifndef QT_NO_OPENSSL QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); sslSocket->connectToHostEncrypted(connectHost, connectPort); - if (channels[index].ignoreSSLErrors) + if (channels[index].ignoreAllSslErrors) sslSocket->ignoreSslErrors(); + sslSocket->ignoreSslErrors(channels[index].ignoreSslErrorsList); #else emitReplyError(socket, channels[index].reply, QNetworkReply::ProtocolUnknownError); #endif @@ -1443,15 +1449,32 @@ void QHttpNetworkConnection::ignoreSslErrors(int channel) if (channel == -1) { // ignore for all channels for (int i = 0; i < d->channelCount; ++i) { static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(); - d->channels[i].ignoreSSLErrors = true; + d->channels[i].ignoreAllSslErrors = true; } } else { static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors(); - d->channels[channel].ignoreSSLErrors = true; + d->channels[channel].ignoreAllSslErrors = true; } } +void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int channel) +{ + Q_D(QHttpNetworkConnection); + if (!d->encrypt) + return; + + if (channel == -1) { // ignore for all channels + for (int i = 0; i < d->channelCount; ++i) { + static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(errors); + d->channels[i].ignoreSslErrorsList = errors; + } + + } else { + static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors(errors); + d->channels[channel].ignoreSslErrorsList = errors; + } +} #endif //QT_NO_OPENSSL diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index 842a2f4..52a73a7 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -117,6 +117,7 @@ public: #ifndef QT_NO_OPENSSL void setSslConfiguration(const QSslConfiguration &config); void ignoreSslErrors(int channel = -1); + void ignoreSslErrors(const QList<QSslError> &errors, int channel = -1); Q_SIGNALS: void sslErrors(const QList<QSslError> &errors); @@ -241,13 +242,14 @@ public: QAuthenticator authenticator; QAuthenticator proxyAuthenticator; #ifndef QT_NO_OPENSSL - bool ignoreSSLErrors; + bool ignoreAllSslErrors; + QList<QSslError> ignoreSslErrorsList; #endif Channel() : socket(0), state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false), lastStatus(0), pendingEncrypt(false), reconnectAttempts(2), authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None) #ifndef QT_NO_OPENSSL - , ignoreSSLErrors(false) + , ignoreAllSslErrors(false) #endif {} }; diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 2fe0d78..a623999 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -712,6 +712,13 @@ void QHttpNetworkReply::ignoreSslErrors() d->connection->ignoreSslErrors(); } +void QHttpNetworkReply::ignoreSslErrors(const QList<QSslError> &errors) +{ + Q_D(QHttpNetworkReply); + if (d->connection) + d->connection->ignoreSslErrors(errors); +} + #endif //QT_NO_OPENSSL diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index fbbee12..575e824 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -131,6 +131,7 @@ public: QSslConfiguration sslConfiguration() const; void setSslConfiguration(const QSslConfiguration &config); void ignoreSslErrors(); + void ignoreSslErrors(const QList<QSslError> &errors); Q_SIGNALS: void sslErrors(const QList<QSslError> &errors); diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 9e17b54..caaa38e 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -165,6 +165,12 @@ void QNetworkAccessBackend::ignoreSslErrors() // do nothing } +void QNetworkAccessBackend::ignoreSslErrors(const QList<QSslError> &errors) +{ + Q_UNUSED(errors); + // do nothing +} + void QNetworkAccessBackend::fetchSslConfiguration(QSslConfiguration &) const { // do nothing diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 553b795..27da5bc 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -118,6 +118,7 @@ public: virtual void downstreamReadyWrite(); virtual void copyFinished(QIODevice *); virtual void ignoreSslErrors(); + virtual void ignoreSslErrors(const QList<QSslError> &errors); virtual void fetchSslConfiguration(QSslConfiguration &configuration) const; virtual void setSslConfiguration(const QSslConfiguration &configuration); diff --git a/src/network/access/qnetworkaccesscachebackend.cpp b/src/network/access/qnetworkaccesscachebackend.cpp index f46a50a..8571ba3 100644 --- a/src/network/access/qnetworkaccesscachebackend.cpp +++ b/src/network/access/qnetworkaccesscachebackend.cpp @@ -86,6 +86,20 @@ bool QNetworkAccessCacheBackend::sendCacheContents() setAttribute(QNetworkRequest::HttpReasonPhraseAttribute, attributes.value(QNetworkRequest::HttpReasonPhraseAttribute)); setAttribute(QNetworkRequest::SourceIsFromCacheAttribute, true); + // set the raw headers + QNetworkCacheMetaData::RawHeaderList rawHeaders = item.rawHeaders(); + QNetworkCacheMetaData::RawHeaderList::ConstIterator it = rawHeaders.constBegin(), + end = rawHeaders.constEnd(); + for ( ; it != end; ++it) + setRawHeader(it->first, it->second); + + // handle a possible redirect + QVariant redirectionTarget = attributes.value(QNetworkRequest::RedirectionTargetAttribute); + if (redirectionTarget.isValid()) { + setAttribute(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); + redirectionRequested(redirectionTarget.toUrl()); + } + // signal we're open metaDataChanged(); diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp index 2b3c128..394e196 100644 --- a/src/network/access/qnetworkaccessdebugpipebackend.cpp +++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp @@ -280,6 +280,7 @@ void QNetworkAccessDebugPipeBackend::socketConnected() bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms) { + Q_UNUSED(ms); qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()"); return false; } diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 9c36026..5c85735 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -294,7 +294,7 @@ public: QNetworkAccessHttpBackend::QNetworkAccessHttpBackend() : QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0) #ifndef QT_NO_OPENSSL - , pendingSslConfiguration(0), pendingIgnoreSslErrors(false) + , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false) #endif { } @@ -521,8 +521,9 @@ void QNetworkAccessHttpBackend::postRequest() #ifndef QT_NO_OPENSSL if (pendingSslConfiguration) httpReply->setSslConfiguration(*pendingSslConfiguration); - if (pendingIgnoreSslErrors) + if (pendingIgnoreAllSslErrors) httpReply->ignoreSslErrors(); + httpReply->ignoreSslErrors(pendingIgnoreSslErrorsList); #endif connect(httpReply, SIGNAL(readyRead()), SLOT(replyReadyRead())); @@ -883,7 +884,18 @@ void QNetworkAccessHttpBackend::ignoreSslErrors() if (httpReply) httpReply->ignoreSslErrors(); else - pendingIgnoreSslErrors = true; + pendingIgnoreAllSslErrors = true; +} + +void QNetworkAccessHttpBackend::ignoreSslErrors(const QList<QSslError> &errors) +{ + if (httpReply) { + httpReply->ignoreSslErrors(errors); + } else { + // the pending list is set if QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors) + // is called before QNetworkAccessManager::get() (or post(), etc.) + pendingIgnoreSslErrorsList = errors; + } } void QNetworkAccessHttpBackend::fetchSslConfiguration(QSslConfiguration &config) const diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index dec69d0..968f4a5 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -85,6 +85,7 @@ public: virtual void copyFinished(QIODevice *); #ifndef QT_NO_OPENSSL virtual void ignoreSslErrors(); + virtual void ignoreSslErrors(const QList<QSslError> &errors); virtual void fetchSslConfiguration(QSslConfiguration &configuration) const; virtual void setSslConfiguration(const QSslConfiguration &configuration); @@ -112,7 +113,8 @@ private: #ifndef QT_NO_OPENSSL QSslConfiguration *pendingSslConfiguration; - bool pendingIgnoreSslErrors; + bool pendingIgnoreAllSslErrors; + QList<QSslError> pendingIgnoreSslErrorsList; #endif void disconnectFromHttp(); diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index e807d29..3abf927 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -584,6 +584,38 @@ void QNetworkReply::setSslConfiguration(const QSslConfiguration &config) qt_metacall(QMetaObject::InvokeMetaMethod, id, arr); } } + +/*! + \overload + \since 4.6 + + If this function is called, the SSL errors given in \a errors + will be ignored. + + Note that you can set the expected certificate in the SSL error: + If, for instance, you want to issue a request to a server that uses + a self-signed certificate, consider the following snippet: + + \snippet doc/src/snippets/code/src_network_access_qnetworkreply.cpp 0 + + Multiple calls to this function will replace the list of errors that + were passed in previous calls. + You can clear the list of errors you want to ignore by calling this + function with an empty list. + + \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors() +*/ +void QNetworkReply::ignoreSslErrors(const QList<QSslError> &errors) +{ + // do this cryptic trick, because we could not add a virtual method to this class later on + // since that breaks binary compatibility + int id = metaObject()->indexOfMethod("ignoreSslErrorsImplementation(QList<QSslError>)"); + if (id != -1) { + QList<QSslError> copy(errors); + void *arr[] = { 0, © }; + qt_metacall(QMetaObject::InvokeMetaMethod, id, arr); + } +} #endif /*! @@ -598,7 +630,7 @@ void QNetworkReply::setSslConfiguration(const QSslConfiguration &config) sslErrors() signal, which indicates which errors were found. - \sa sslConfiguration(), sslErrors() + \sa sslConfiguration(), sslErrors(), QSslSocket::ignoreSslErrors() */ void QNetworkReply::ignoreSslErrors() { diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 30e89f1..679ab71 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -134,6 +134,7 @@ public: #ifndef QT_NO_OPENSSL QSslConfiguration sslConfiguration() const; void setSslConfiguration(const QSslConfiguration &configuration); + void ignoreSslErrors(const QList<QSslError> &errors); #endif public Q_SLOTS: diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 44ae328..de7f8b4 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -401,7 +401,17 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data) QNetworkCacheMetaData metaData; metaData.setUrl(url); metaData = backend->fetchCacheMetaData(metaData); + + // save the redirect request also in the cache + QVariant redirectionTarget = q->attribute(QNetworkRequest::RedirectionTargetAttribute); + if (redirectionTarget.isValid()) { + QNetworkCacheMetaData::AttributesMap attributes = metaData.attributes(); + attributes.insert(QNetworkRequest::RedirectionTargetAttribute, redirectionTarget); + metaData.setAttributes(attributes); + } + cacheSaveDevice = networkCache->prepare(metaData); + if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { if (cacheSaveDevice && !cacheSaveDevice->isOpen()) qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " @@ -649,6 +659,12 @@ void QNetworkReplyImpl::ignoreSslErrors() d->backend->ignoreSslErrors(); } +void QNetworkReplyImpl::ignoreSslErrorsImplementation(const QList<QSslError> &errors) +{ + Q_D(QNetworkReplyImpl); + if (d->backend) + d->backend->ignoreSslErrors(errors); +} #endif // QT_NO_OPENSSL /*! diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index 83a8aca..fba8d34 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -89,6 +89,7 @@ public: Q_INVOKABLE QSslConfiguration sslConfigurationImplementation() const; Q_INVOKABLE void setSslConfigurationImplementation(const QSslConfiguration &configuration); virtual void ignoreSslErrors(); + Q_INVOKABLE virtual void ignoreSslErrorsImplementation(const QList<QSslError> &errors); #endif Q_DECLARE_PRIVATE(QNetworkReplyImpl) diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index fc297e4..df0afe3 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -356,7 +356,7 @@ QSslSocket::~QSslSocket() want to ignore the errors and continue connecting, you must call ignoreSslErrors(), either from inside a slot function connected to the sslErrors() signal, or prior to entering encrypted mode. If - ignoreSslErrors is not called, the connection is dropped, signal + ignoreSslErrors() is not called, the connection is dropped, signal disconnected() is emitted, and QSslSocket returns to the UnconnectedState. @@ -1592,7 +1592,33 @@ void QSslSocket::startServerEncryption() void QSslSocket::ignoreSslErrors() { Q_D(QSslSocket); - d->ignoreSslErrors = true; + d->ignoreAllSslErrors = true; +} + +/*! + \overload + \since 4.6 + + This method tells QSslSocket to ignore only the errors given in \a + errors. + + Note that you can set the expected certificate in the SSL error: + If, for instance, you want to connect to a server that uses + a self-signed certificate, consider the following snippet: + + \snippet doc/src/snippets/code/src_network_ssl_qsslsocket.cpp 6 + + Multiple calls to this function will replace the list of errors that + were passed in previous calls. + You can clear the list of errors you want to ignore by calling this + function with an empty list. + + \sa sslErrors() +*/ +void QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) +{ + Q_D(QSslSocket); + d->ignoreErrorsList = errors; } /*! @@ -1732,7 +1758,11 @@ void QSslSocketPrivate::init() mode = QSslSocket::UnencryptedMode; autoStartHandshake = false; connectionEncrypted = false; - ignoreSslErrors = false; + ignoreAllSslErrors = false; + + // we don't want to clear the ignoreErrorsList, so + // that it is possible setting it before connecting +// ignoreErrorsList.clear(); readBuffer.clear(); writeBuffer.clear(); diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index 785a083..cab0667 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -169,6 +169,7 @@ public: QList<QSslError> sslErrors() const; static bool supportsSsl(); + void ignoreSslErrors(const QList<QSslError> &errors); public Q_SLOTS: void startClientEncryption(); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index ea62a4d..130494e 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -839,7 +839,27 @@ bool QSslSocketBackendPrivate::startHandshake() if (!errors.isEmpty()) { sslErrors = errors; emit q->sslErrors(errors); - if (doVerifyPeer && !ignoreSslErrors) { + + bool doEmitSslError; + if (!ignoreErrorsList.empty()) { + // check whether the errors we got are all in the list of expected errors + // (applies only if the method QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) + // was called) + doEmitSslError = false; + for (int a = 0; a < errors.count(); a++) { + if (!ignoreErrorsList.contains(errors.at(a))) { + doEmitSslError = true; + break; + } + } + } else { + // if QSslSocket::ignoreSslErrors(const QList<QSslError> &errors) was not called and + // we get an SSL error, emit a signal unless we ignored all errors (by calling + // QSslSocket::ignoreSslErrors() ) + doEmitSslError = !ignoreAllSslErrors; + } + // check whether we need to emit an SSL handshake error + if (doVerifyPeer && doEmitSslError) { q->setErrorString(sslErrors.first().errorString()); q->setSocketError(QAbstractSocket::SslHandshakeFailedError); emit q->error(QAbstractSocket::SslHandshakeFailedError); diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index dc8e4f5..8fd2154 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -79,7 +79,8 @@ public: QSslSocket::SslMode mode; bool autoStartHandshake; bool connectionEncrypted; - bool ignoreSslErrors; + bool ignoreAllSslErrors; + QList<QSslError> ignoreErrorsList; bool* readyReadEmittedPointer; QRingBuffer readBuffer; diff --git a/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp b/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp new file mode 100644 index 0000000..a82caa0 --- /dev/null +++ b/src/opengl/gl2paintengineex/qglcustomshaderstage.cpp @@ -0,0 +1,123 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qglcustomshaderstage_p.h" +#include "qglengineshadermanager_p.h" +#include "qpaintengineex_opengl2_p.h" +#include <private/qpainter_p.h> + +class QGLCustomShaderStagePrivate +{ +public: + QGLCustomShaderStagePrivate() : + m_manager(0) {} + + QGLEngineShaderManager* m_manager; + QByteArray m_source; +}; + + + + +QGLCustomShaderStage::QGLCustomShaderStage() + : d_ptr(new QGLCustomShaderStagePrivate) +{ +} + +QGLCustomShaderStage::~QGLCustomShaderStage() +{ + Q_D(QGLCustomShaderStage); + if (d->m_manager) + d->m_manager->removeCustomStage(this); +} + +void QGLCustomShaderStage::setUniformsDirty() +{ + Q_D(QGLCustomShaderStage); + if (d->m_manager) + d->m_manager->setDirty(); // ### Probably a bit overkill! +} + +bool QGLCustomShaderStage::setOnPainter(QPainter* p) +{ + Q_D(QGLCustomShaderStage); + if (p->paintEngine()->type() != QPaintEngine::OpenGL2) { + qWarning("QGLCustomShaderStage::setOnPainter() - paint engine not OpenGL2"); + return false; + } + + // Might as well go through the paint engine to get to the context + const QGLContext* ctx = static_cast<QGL2PaintEngineEx*>(p->paintEngine())->context(); + d->m_manager = QGLEngineShaderManager::managerForContext(ctx); + Q_ASSERT(d->m_manager); + + d->m_manager->setCustomStage(this); + return true; +} + +void QGLCustomShaderStage::removeFromPainter(QPainter* p) +{ + Q_D(QGLCustomShaderStage); + if (p->paintEngine()->type() != QPaintEngine::OpenGL2) + return; + + // Might as well go through the paint engine to get to the context + const QGLContext* ctx = static_cast<QGL2PaintEngineEx*>(p->paintEngine())->context(); + d->m_manager = QGLEngineShaderManager::managerForContext(ctx); + Q_ASSERT(d->m_manager); + + // Just set the stage to null, don't call removeCustomStage(). + // This should leave the program in a compiled/linked state + // if the next custom shader stage is this one again. + d->m_manager->setCustomStage(0); +} + +const char* QGLCustomShaderStage::source() const +{ + Q_D(const QGLCustomShaderStage); + return d->m_source.constData(); +} + +void QGLCustomShaderStage::setSource(const QByteArray& s) +{ + Q_D(QGLCustomShaderStage); + d->m_source = s; +} diff --git a/examples/animation/stickman/editor/animationdialog.h b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h index 293f0d4..70e9ff0 100644 --- a/examples/animation/stickman/editor/animationdialog.h +++ b/src/opengl/gl2paintengineex/qglcustomshaderstage_p.h @@ -3,7 +3,7 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtCore module of the Qt Toolkit. +** This file is part of the QtOpenGL module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -39,46 +39,54 @@ ** ****************************************************************************/ -#ifndef ANIMATIONDIALOG_H -#define ANIMATIONDIALOG_H +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// -#include <QDialog> -#include <QMessageBox> +#ifndef QGL_CUSTOM_SHADER_STAGE_H +#define QGL_CUSTOM_SHADER_STAGE_H + +#include <QGLShaderProgram> + +QT_BEGIN_HEADER QT_BEGIN_NAMESPACE -class QSpinBox; -class QLineEdit; -QT_END_NAMESPACE -class StickMan; -class Animation; -class AnimationDialog: public QDialog + +QT_MODULE(OpenGL) + +class QGLCustomShaderStagePrivate; +class Q_OPENGL_EXPORT QGLCustomShaderStage { - Q_OBJECT + Q_DECLARE_PRIVATE(QGLCustomShaderStage); public: - AnimationDialog(StickMan *stickMan, QWidget *parent = 0); - ~AnimationDialog(); + QGLCustomShaderStage(); + virtual ~QGLCustomShaderStage(); + virtual void setUniforms(QGLShaderProgram*) = 0; + + void setUniformsDirty(); -public slots: - void currentFrameChanged(int currentFrame); - void totalFramesChanged(int totalFrames); - void setCurrentAnimationName(const QString &name); + bool setOnPainter(QPainter*); + void removeFromPainter(QPainter*); + const char* source() const; - void newAnimation(); - void saveAnimation(); - void loadAnimation(); +protected: + void setSource(const QByteArray&); private: - void saveCurrentFrame(); - void stickManFromCurrentFrame(); - void initFromAnimation(); - void initUi(); - QMessageBox::StandardButton maybeSave(); - - QSpinBox *m_currentFrame; - QSpinBox *m_totalFrames; - QLineEdit *m_name; - Animation *m_animation; - StickMan *m_stickman; + QGLCustomShaderStagePrivate* d_ptr; }; - + + +QT_END_NAMESPACE + +QT_END_HEADER + + #endif diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 27636f4..0692277 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -49,6 +49,28 @@ QT_BEGIN_NAMESPACE +static void QGLEngineShaderManager_free(void *ptr) +{ + delete reinterpret_cast<QGLEngineShaderManager *>(ptr); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_shader_managers, (QGLEngineShaderManager_free)) + +QGLEngineShaderManager *QGLEngineShaderManager::managerForContext(const QGLContext *context) +{ + QGLEngineShaderManager *p = reinterpret_cast<QGLEngineShaderManager *>(qt_shader_managers()->value(context)); + if (!p) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != context) + const_cast<QGLContext *>(context)->makeCurrent(); + p = new QGLEngineShaderManager(const_cast<QGLContext *>(context)); + qt_shader_managers()->insert(context, p); + if (oldContext && oldContext != context) + oldContext->makeCurrent(); + } + return p; +} + const char* QGLEngineShaderManager::qglEngineShaderSourceCode[] = { 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, @@ -64,6 +86,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) maskType(NoMask), useTextureCoords(false), compositionMode(QPainter::CompositionMode_SourceOver), + customSrcStage(0), blitShaderProg(0), simpleShaderProg(0), currentShaderProg(0) @@ -109,6 +132,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader; code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader; code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader; + code[CustomImageSrcFragmentShader] = ""; // Supplied by app. code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader; code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader; code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader; @@ -137,7 +161,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context) #if defined(QT_DEBUG) // Check that all the elements have been filled: for (int i = 0; i < TotalShaderCount; ++i) { - if (qglEngineShaderSourceCode[i] == 0) { + if (i != CustomImageSrcFragmentShader && qglEngineShaderSourceCode[i] == 0) { int enumIndex = staticMetaObject.indexOfEnumerator("ShaderName"); QMetaEnum m = staticMetaObject.enumerator(enumIndex); @@ -286,6 +310,44 @@ void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode) shaderProgNeedsChanging = true; //### } +void QGLEngineShaderManager::setCustomStage(QGLCustomShaderStage* stage) +{ + // If the custom shader has changed, then destroy the previous compilation. + if (customSrcStage && stage && customSrcStage != stage) + removeCustomStage(customSrcStage); + + customSrcStage = stage; + shaderProgNeedsChanging = true; +} + +void QGLEngineShaderManager::shaderDestroyed(QObject *shader) +{ + // Remove any shader programs which has this as the srcPixel shader: + for (int i = 0; i < cachedPrograms.size(); ++i) { + if (cachedPrograms.at(i).srcPixelFragShader == shader) { + delete cachedPrograms.at(i).program; + cachedPrograms.removeAt(i--); + } + } + + shaderProgNeedsChanging = true; +} + +void QGLEngineShaderManager::removeCustomStage(QGLCustomShaderStage* stage) +{ + Q_UNUSED(stage); // Currently we only support one at a time... + + QGLShader *compiledShader = compiledShaders[CustomImageSrcFragmentShader]; + + if (!compiledShader) + return; + + compiledShaders[CustomImageSrcFragmentShader] = 0; + customSrcStage = 0; + shaderProgNeedsChanging = true; +} + + QGLShaderProgram* QGLEngineShaderManager::currentProgram() { return currentShaderProg->program; @@ -310,6 +372,12 @@ bool QGLEngineShaderManager::useCorrectShaderProg() if (!shaderProgNeedsChanging) return false; + bool useCustomSrc = customSrcStage != 0; + if (useCustomSrc && srcPixelType != QGLEngineShaderManager::ImageSrc) { + useCustomSrc = false; + qWarning("QGLEngineShaderManager - Ignoring custom shader stage for non image src"); + } + QGLEngineShaderProg requiredProgram; requiredProgram.program = 0; @@ -341,7 +409,11 @@ bool QGLEngineShaderManager::useCorrectShaderProg() qCritical("QGLEngineShaderManager::useCorrectShaderProg() - I'm scared, Qt::NoBrush style is set"); break; case QGLEngineShaderManager::ImageSrc: - srcPixelFragShaderName = ImageSrcFragmentShader; + srcPixelFragShaderName = useCustomSrc ? CustomImageSrcFragmentShader : ImageSrcFragmentShader; + positionVertexShaderName = PositionOnlyVertexShader; + break; + case QGLEngineShaderManager::NonPremultipliedImageSrc: + srcPixelFragShaderName = NonPremultipliedImageSrcFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; break; case QGLEngineShaderManager::PatternSrc: @@ -353,10 +425,6 @@ bool QGLEngineShaderManager::useCorrectShaderProg() positionVertexShaderName = isAffine ? AffinePositionWithTextureBrushVertexShader : PositionWithTextureBrushVertexShader; break; - case QGLEngineShaderManager::NonPremultipliedImageSrc: - srcPixelFragShaderName = NonPremultipliedImageSrcFragmentShader; - positionVertexShaderName = PositionOnlyVertexShader; - break; case Qt::SolidPattern: srcPixelFragShaderName = SolidBrushSrcFragmentShader; positionVertexShaderName = PositionOnlyVertexShader; @@ -387,7 +455,6 @@ bool QGLEngineShaderManager::useCorrectShaderProg() requiredProgram.positionVertexShader = compiledShaders[positionVertexShaderName]; requiredProgram.srcPixelFragShader = compiledShaders[srcPixelFragShaderName]; - const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus; const bool hasMask = maskType != QGLEngineShaderManager::NoMask; @@ -476,62 +543,63 @@ bool QGLEngineShaderManager::useCorrectShaderProg() else requiredProgram.compositionFragShader = 0; - // At this point, requiredProgram is fully populated so try to find the program in the cache + bool foundProgramInCache = false; for (int i = 0; i < cachedPrograms.size(); ++i) { - QGLEngineShaderProg &prog = cachedPrograms[i]; - if ( (prog.mainVertexShader == requiredProgram.mainVertexShader) - && (prog.positionVertexShader == requiredProgram.positionVertexShader) - && (prog.mainFragShader == requiredProgram.mainFragShader) - && (prog.srcPixelFragShader == requiredProgram.srcPixelFragShader) - && (prog.compositionFragShader == requiredProgram.compositionFragShader) ) - { - currentShaderProg = &prog; - currentShaderProg->program->enable(); - shaderProgNeedsChanging = false; - return true; + if (cachedPrograms[i] == requiredProgram) { + currentShaderProg = &cachedPrograms[i]; + foundProgramInCache = true; + break; } } - // Shader program not found in cache, create it now. - requiredProgram.program = new QGLShaderProgram(ctx, this); - requiredProgram.program->addShader(requiredProgram.mainVertexShader); - requiredProgram.program->addShader(requiredProgram.positionVertexShader); - requiredProgram.program->addShader(requiredProgram.mainFragShader); - requiredProgram.program->addShader(requiredProgram.srcPixelFragShader); - requiredProgram.program->addShader(requiredProgram.maskFragShader); - requiredProgram.program->addShader(requiredProgram.compositionFragShader); - - // We have to bind the vertex attribute names before the program is linked: - requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); - if (useTextureCoords) - requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); - - requiredProgram.program->link(); - if (!requiredProgram.program->isLinked()) { - QString error; - qWarning() << "Shader program failed to link," + // If the shader program's not found in the cache, create it now. + if (!foundProgramInCache) { + requiredProgram.program = new QGLShaderProgram(ctx, this); + requiredProgram.program->addShader(requiredProgram.mainVertexShader); + requiredProgram.program->addShader(requiredProgram.positionVertexShader); + requiredProgram.program->addShader(requiredProgram.mainFragShader); + requiredProgram.program->addShader(requiredProgram.srcPixelFragShader); + requiredProgram.program->addShader(requiredProgram.maskFragShader); + requiredProgram.program->addShader(requiredProgram.compositionFragShader); + + // We have to bind the vertex attribute names before the program is linked: + requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR); + if (useTextureCoords) + requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR); + + requiredProgram.program->link(); + if (!requiredProgram.program->isLinked()) { + QString error; + qWarning() << "Shader program failed to link," #if defined(QT_DEBUG) - << '\n' - << " Shaders Used:" << '\n' - << " mainVertexShader = " << requiredProgram.mainVertexShader->objectName() << '\n' - << " positionVertexShader = " << requiredProgram.positionVertexShader->objectName() << '\n' - << " mainFragShader = " << requiredProgram.mainFragShader->objectName() << '\n' - << " srcPixelFragShader = " << requiredProgram.srcPixelFragShader->objectName() << '\n' - << " maskFragShader = " << requiredProgram.maskFragShader->objectName() << '\n' - << " compositionFragShader = "<< requiredProgram.compositionFragShader->objectName() << '\n' + << '\n' + << " Shaders Used:" << '\n' + << " mainVertexShader = " << requiredProgram.mainVertexShader->objectName() << '\n' + << " positionVertexShader = " << requiredProgram.positionVertexShader->objectName() << '\n' + << " mainFragShader = " << requiredProgram.mainFragShader->objectName() << '\n' + << " srcPixelFragShader = " << requiredProgram.srcPixelFragShader->objectName() << '\n' + << " maskFragShader = " << requiredProgram.maskFragShader->objectName() << '\n' + << " compositionFragShader = "<< requiredProgram.compositionFragShader->objectName() << '\n' #endif - << " Error Log:" << '\n' - << " " << requiredProgram.program->log(); - qWarning() << error; + << " Error Log:" << '\n' + << " " << requiredProgram.program->log(); + qWarning() << error; + delete requiredProgram.program; + } else { + cachedPrograms.append(requiredProgram); + // taking the address here is safe since + // cachePrograms isn't resized anywhere else + currentShaderProg = &cachedPrograms.last(); + } } - else { - cachedPrograms.append(requiredProgram); - // taking the address here is safe since - // cachePrograms isn't resized anywhere else - currentShaderProg = &cachedPrograms.last(); + + if (currentShaderProg) { currentShaderProg->program->enable(); + if (useCustomSrc) + customSrcStage->setUniforms(currentShaderProg->program); } + shaderProgNeedsChanging = false; return true; } @@ -541,8 +609,27 @@ void QGLEngineShaderManager::compileNamedShader(QGLEngineShaderManager::ShaderNa if (compiledShaders[name]) return; - QGLShader *newShader = new QGLShader(type, ctx, this); - newShader->compile(qglEngineShaderSourceCode[name]); + QGLShader *newShader; + + QByteArray source; + if (name == CustomImageSrcFragmentShader) { + source = customSrcStage->source(); + source += qglslCustomSrcFragmentShader; + + newShader = customShaderCache.object(source); + if (!newShader) { + newShader = new QGLShader(type, ctx, this); + newShader->compile(source); + customShaderCache.insert(source, newShader); + + connect(newShader, SIGNAL(destroyed(QObject *)), + this, SLOT(shaderDestroyed(QObject *))); + } + } else { + source = qglEngineShaderSourceCode[name]; + newShader = new QGLShader(type, ctx, this); + newShader->compile(source); + } #if defined(QT_DEBUG) // Name the shader for easier debugging diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h index 442edfe..8122a08 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h @@ -199,19 +199,23 @@ O = Global Opacity - CUSTOM SHADER CODE (idea, depricated) + CUSTOM SHADER CODE ================== The use of custom shader code is supported by the engine for drawImage and drawPixmap calls. This is implemented via hooks in the fragment pipeline. + The custom shader is passed to the engine as a partial fragment shader - (QGLCustomizedShader). The shader will implement a pre-defined method name - which Qt's fragment pipeline will call. There are two different hooks which - can be implemented as custom shader code: + (QGLCustomShaderStage). The shader will implement a pre-defined method name + which Qt's fragment pipeline will call: + + lowp vec4 customShader(sampler2d src, vec2 srcCoords) - mediump vec4 customShader(sampler2d src, vec2 srcCoords) - mediump vec4 customShaderWithDest(sampler2d dest, sampler2d src, vec2 srcCoords) + The provided src and srcCoords parameters can be used to sample from the + source image. + Transformations, clipping, opacity, and composition modes set using QPainter + will be respected when using the custom shader hook. */ #ifndef QGLENGINE_SHADER_MANAGER_H @@ -220,6 +224,8 @@ #include <QGLShader> #include <QGLShaderProgram> #include <QPainter> +#include <private/qgl_p.h> +#include <private/qglcustomshaderstage_p.h> QT_BEGIN_HEADER @@ -227,7 +233,6 @@ QT_BEGIN_NAMESPACE QT_MODULE(OpenGL) - struct QGLEngineShaderProg { QGLShader* mainVertexShader; @@ -239,6 +244,17 @@ struct QGLEngineShaderProg QGLShaderProgram* program; QVector<uint> uniformLocations; + + bool operator==(const QGLEngineShaderProg& other) { + // We don't care about the program + return ( mainVertexShader == other.mainVertexShader && + positionVertexShader == other.positionVertexShader && + mainFragShader == other.mainFragShader && + srcPixelFragShader == other.srcPixelFragShader && + maskFragShader == other.maskFragShader && + compositionFragShader == other.compositionFragShader + ); + } }; /* @@ -259,7 +275,7 @@ struct QGLEngineCachedShaderProg static const GLuint QT_VERTEX_COORDS_ATTR = 0; static const GLuint QT_TEXTURE_COORDS_ATTR = 1; -class QGLEngineShaderManager : public QObject +class Q_OPENGL_EXPORT QGLEngineShaderManager : public QObject { Q_OBJECT public: @@ -304,6 +320,8 @@ public: void setUseGlobalOpacity(bool); void setMaskType(MaskType); void setCompositionMode(QPainter::CompositionMode); + void setCustomStage(QGLCustomShaderStage* stage); + void removeCustomStage(QGLCustomShaderStage* stage); uint getUniformLocation(Uniform id); @@ -314,6 +332,8 @@ public: QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer + static QGLEngineShaderManager *managerForContext(const QGLContext *context); + enum ShaderName { MainVertexShader, MainWithTexCoordsVertexShader, @@ -341,8 +361,10 @@ public: MainFragmentShader, ImageSrcFragmentShader, + CustomSrcFragmentShader, ImageSrcWithPatternFragmentShader, NonPremultipliedImageSrcFragmentShader, + CustomImageSrcFragmentShader, SolidBrushSrcFragmentShader, TextureBrushSrcFragmentShader, TextureBrushSrcWithPatternFragmentShader, @@ -386,6 +408,8 @@ public: Q_ENUMS(ShaderName) #endif +private slots: + void shaderDestroyed(QObject *shader); private: QGLContext* ctx; @@ -398,11 +422,14 @@ private: MaskType maskType; bool useTextureCoords; QPainter::CompositionMode compositionMode; + QGLCustomShaderStage* customSrcStage; QGLShaderProgram* blitShaderProg; QGLShaderProgram* simpleShaderProg; QGLEngineShaderProg* currentShaderProg; + QCache<QByteArray, QGLShader> customShaderCache; + // TODO: Possibly convert to a LUT QList<QGLEngineShaderProg> cachedPrograms; diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index 4e32f91..e379aa3 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -290,6 +290,14 @@ static const char* const qglslImageSrcFragmentShader = "\ return texture2D(imageTexture, textureCoords); \ }"; +static const char* const qglslCustomSrcFragmentShader = "\ + varying highp vec2 textureCoords; \ + uniform sampler2D imageTexture; \ + lowp vec4 customShader(sampler2D texture, vec2 coords); \ + lowp vec4 srcPixel() { \ + return customShader(imageTexture, textureCoords); \ + }"; + static const char* const qglslImageSrcWithPatternFragmentShader = "\ varying highp vec2 textureCoords; \ uniform lowp vec4 patternColor; \ diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp index 8c6b4f0..7c54bb9 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache.cpp +++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp @@ -46,6 +46,28 @@ QT_BEGIN_NAMESPACE +static void QGL2GradientCache_free(void *ptr) +{ + delete reinterpret_cast<QGL2GradientCache *>(ptr); +} + +Q_GLOBAL_STATIC_WITH_ARGS(QGLContextResource, qt_gradient_caches, (QGL2GradientCache_free)) + +QGL2GradientCache *QGL2GradientCache::cacheForContext(const QGLContext *context) +{ + QGL2GradientCache *p = reinterpret_cast<QGL2GradientCache *>(qt_gradient_caches()->value(context)); + if (!p) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != context) + const_cast<QGLContext *>(context)->makeCurrent(); + p = new QGL2GradientCache; + qt_gradient_caches()->insert(context, p); + if (oldContext && oldContext != context) + oldContext->makeCurrent(); + } + return p; +} + void QGL2GradientCache::cleanCache() { QGLGradientColorTableHash::const_iterator it = cache.constBegin(); for (; it != cache.constEnd(); ++it) { @@ -55,13 +77,8 @@ void QGL2GradientCache::cleanCache() { cache.clear(); } -GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx) +GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity) { - if (buffer_ctx && !qgl_share_reg()->checkSharing(buffer_ctx, ctx)) - cleanCache(); - - buffer_ctx = ctx; - quint64 hash_val = 0; QGradientStops stops = gradient.stops(); diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h index 55c7b65..ba698bc 100644 --- a/src/opengl/gl2paintengineex/qglgradientcache_p.h +++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h @@ -53,12 +53,12 @@ #include <QMultiHash> #include <QObject> #include <QtOpenGL/QtOpenGL> +#include <private/qgl_p.h> QT_BEGIN_NAMESPACE -class QGL2GradientCache : public QObject +class QGL2GradientCache { - Q_OBJECT struct CacheInfo { inline CacheInfo(QGradientStops s, qreal op, QGradient::InterpolationMode mode) : @@ -73,16 +73,12 @@ class QGL2GradientCache : public QObject typedef QMultiHash<quint64, CacheInfo> QGLGradientColorTableHash; public: - QGL2GradientCache() : QObject(), buffer_ctx(0) - { -/* - connect(QGLSignalProxy::instance(), - SIGNAL(aboutToDestroyContext(const QGLContext *)), - SLOT(cleanupGLContextRefs(const QGLContext *))); -*/ - } + static QGL2GradientCache *cacheForContext(const QGLContext *context); + + QGL2GradientCache() { } + ~QGL2GradientCache() {cleanCache();} - GLuint getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx); + GLuint getBuffer(const QGradient &gradient, qreal opacity); inline int paletteSize() const { return 1024; } protected: @@ -95,15 +91,6 @@ protected: void cleanCache(); QGLGradientColorTableHash cache; - const QGLContext *buffer_ctx; - -public slots: - void cleanupGLContextRefs(const QGLContext *context) { - if (context == buffer_ctx) { - cleanCache(); - buffer_ctx = 0; - } - } }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 2bfbf4a..db306a5 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -74,6 +74,7 @@ #include <private/qpainter_p.h> #include <private/qfontengine_p.h> #include <private/qtextureglyphcache_p.h> +#include <private/qpixmapdata_gl_p.h> #include "qglgradientcache_p.h" #include "qglengineshadermanager_p.h" @@ -115,6 +116,7 @@ public Q_SLOTS: glDeleteFramebuffers(1, &m_fbo); if (m_width || m_height) glDeleteTextures(1, &m_texture); + ctx = 0; } else { // since the context holding the texture is shared, and // about to be destroyed, we have to transfer ownership @@ -151,10 +153,17 @@ QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyph QGLTextureGlyphCache::~QGLTextureGlyphCache() { - glDeleteFramebuffers(1, &m_fbo); - - if (m_width || m_height) - glDeleteTextures(1, &m_texture); + if (ctx) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != ctx) + ctx->makeCurrent(); + glDeleteFramebuffers(1, &m_fbo); + + if (m_width || m_height) + glDeleteTextures(1, &m_texture); + if (oldContext && oldContext != ctx) + oldContext->makeCurrent(); + } } void QGLTextureGlyphCache::createTextureData(int width, int height) @@ -266,10 +275,6 @@ extern QImage qt_imageForBrush(int brushStyle, bool invert); QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate() { - if (shaderManager) { - delete shaderManager; - shaderManager = 0; - } } void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id) @@ -295,6 +300,7 @@ void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMod QColor QGL2PaintEngineExPrivate::premultiplyColor(QColor c, GLfloat opacity) { qreal alpha = c.alphaF() * opacity; + c.setAlphaF(alpha); c.setRedF(c.redF() * alpha); c.setGreenF(c.greenF() * alpha); c.setBlueF(c.blueF() * alpha); @@ -338,9 +344,6 @@ void QGL2PaintEngineExPrivate::useSimpleShader() } } - -Q_GLOBAL_STATIC(QGL2GradientCache, qt_opengl_gradient_cache) - void QGL2PaintEngineExPrivate::updateBrushTexture() { // qDebug("QGL2PaintEngineExPrivate::updateBrushTexture()"); @@ -361,7 +364,10 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() // We apply global opacity in the fragment shaders, so we always pass 1.0 // for opacity to the cache. - GLuint texId = qt_opengl_gradient_cache()->getBuffer(*g, 1.0, ctx); + GLuint texId = QGL2GradientCache::cacheForContext(ctx)->getBuffer(*g, 1.0); + + glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); + glBindTexture(GL_TEXTURE_2D, texId); if (g->spread() == QGradient::RepeatSpread || g->type() == QGradient::ConicalGradient) updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true); @@ -369,9 +375,6 @@ void QGL2PaintEngineExPrivate::updateBrushTexture() updateTextureFilter(GL_TEXTURE_2D, GL_MIRRORED_REPEAT_IBM, true); else updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, true); - - glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); - glBindTexture(GL_TEXTURE_2D, texId); } else if (style == Qt::TexturePattern) { const QPixmap& texPixmap = currentBrush->texture(); @@ -687,6 +690,12 @@ void QGL2PaintEngineEx::sync() d->needsSync = true; } +const QGLContext *QGL2PaintEngineEx::context() +{ + Q_D(QGL2PaintEngineEx); + return d->ctx; +} + void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode) { if (newMode == mode) @@ -1052,14 +1061,18 @@ void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, c QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - GLuint id = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true); + QGLTexture *texture = ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true, true); + + GLfloat top = texture->yInverted ? (pixmap.height() - src.top()) : src.top(); + GLfloat bottom = texture->yInverted ? (pixmap.height() - src.bottom()) : src.bottom(); + QGLRect srcRect(src.left(), top, src.right(), bottom); bool isBitmap = pixmap.isQBitmap(); bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel(); d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, - state()->renderHints & QPainter::SmoothPixmapTransform, id); - d->drawTexture(dest, src, pixmap.size(), isOpaque, isBitmap); + state()->renderHints & QPainter::SmoothPixmapTransform, texture->id); + d->drawTexture(dest, srcRect, pixmap.size(), isOpaque, isBitmap); } void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src, @@ -1071,13 +1084,29 @@ void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QGLContext *ctx = d->ctx; glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); - GLuint id = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); + QGLTexture *texture = ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true); + GLuint id = texture->id; d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, state()->renderHints & QPainter::SmoothPixmapTransform, id); d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel()); } +void QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src) +{ + Q_D(QGL2PaintEngineEx); + ensureActive(); + d->transferMode(ImageDrawingMode); + + QGLContext *ctx = d->ctx; + glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT); + glBindTexture(GL_TEXTURE_2D, textureId); + + d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, + state()->renderHints & QPainter::SmoothPixmapTransform, textureId); + d->drawTexture(dest, src, size, false); +} + void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem) { Q_D(QGL2PaintEngineEx); @@ -1209,11 +1238,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) qt_resolve_version_2_0_functions(d->ctx); #endif - if (d->shaderManager) { - d->shaderManager->setDirty(); - } else { - d->shaderManager = new QGLEngineShaderManager(d->ctx); - } + d->shaderManager = QGLEngineShaderManager::managerForContext(d->ctx); + d->shaderManager->setDirty(); glViewport(0, 0, d->width, d->height); @@ -1288,6 +1314,14 @@ bool QGL2PaintEngineEx::end() glUseProgram(0); d->transferMode(BrushDrawingMode); d->drawable.swapBuffers(); +#if defined(Q_WS_X11) + // On some (probably all) drivers, deleting an X pixmap which has been bound to a texture + // before calling glFinish/swapBuffers renders garbage. Presumably this is because X deletes + // the pixmap behind the driver's back before it's had a chance to use it. To fix this, we + // reference all QPixmaps which have been bound to stop them being deleted and only deref + // them here, after swapBuffers, where they can be safely deleted. + ctx->d_func()->boundPixmaps.clear(); +#endif d->drawable.doneCurrent(); d->ctx->d_ptr->active_engine = 0; @@ -1617,6 +1651,14 @@ QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState() { } +QPixmapFilter *QGL2PaintEngineEx::createPixmapFilter(int type) const +{ + const QGLContext *ctx = QGLContext::currentContext(); + if (ctx) + return ctx->d_func()->createPixmapFilter(type); + return 0; +} + QT_END_NAMESPACE #include "qpaintengineex_opengl2.moc" diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index ec447a3..3ff2dca 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -88,8 +88,7 @@ public: bool canRestoreClip; }; - -class QGL2PaintEngineEx : public QPaintEngineEx +class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx { Q_DECLARE_PRIVATE(QGL2PaintEngineEx) public: @@ -116,12 +115,13 @@ public: virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); - virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags = Qt::AutoColor); + virtual void drawTexture(const QRectF &r, GLuint textureId, const QSize &size, const QRectF &sr); + virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); - Type type() const { return OpenGL; } + Type type() const { return OpenGL2; } void setState(QPainterState *s); QPainterState *createState(QPainterState *orig) const; @@ -133,10 +133,15 @@ public: } virtual void sync(); + const QGLContext* context(); + + QPixmapFilter *createPixmapFilter(int type) const; + private: Q_DISABLE_COPY(QGL2PaintEngineEx) }; + class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate { Q_DECLARE_PUBLIC(QGL2PaintEngineEx) diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index c92b8cf..b217949 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -37,6 +37,7 @@ SOURCES += qgl.cpp \ !contains(QT_CONFIG, opengles1):!contains(QT_CONFIG, opengles1cl) { HEADERS += qglshaderprogram.h \ qglpixmapfilter_p.h \ + qgraphicsshadereffect.h \ qgraphicssystem_gl_p.h \ qwindowsurface_gl_p.h \ qpixmapdata_gl_p.h \ @@ -44,17 +45,20 @@ SOURCES += qgl.cpp \ gl2paintengineex/qglengineshadermanager_p.h \ gl2paintengineex/qgl2pexvertexarray_p.h \ gl2paintengineex/qpaintengineex_opengl2_p.h \ - gl2paintengineex/qglengineshadersource_p.h + gl2paintengineex/qglengineshadersource_p.h \ + gl2paintengineex/qglcustomshaderstage_p.h SOURCES += qglshaderprogram.cpp \ qglpixmapfilter.cpp \ + qgraphicsshadereffect.cpp \ qgraphicssystem_gl.cpp \ qwindowsurface_gl.cpp \ qpixmapdata_gl.cpp \ gl2paintengineex/qglgradientcache.cpp \ gl2paintengineex/qglengineshadermanager.cpp \ gl2paintengineex/qgl2pexvertexarray.cpp \ - gl2paintengineex/qpaintengineex_opengl2.cpp + gl2paintengineex/qpaintengineex_opengl2.cpp \ + gl2paintengineex/qglcustomshaderstage.cpp } diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 0169ea2..edda6b6 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -87,7 +87,6 @@ #include <private/qglpixelbuffer_p.h> #include <private/qwindowsurface_gl_p.h> #include "qcolormap.h" -#include "qcache.h" #include "qfile.h" #include "qlibrary.h" @@ -1395,39 +1394,99 @@ int qt_next_power_of_two(int v) return v; } -class QGLTexture { -public: - QGLTexture(const QGLContext *ctx, GLuint tx_id, GLenum tx_target, bool _clean = false) - : context(ctx), id(tx_id), target(tx_target), clean(_clean) {} - ~QGLTexture() { - if (clean) { - QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext()); - QGLContext *ctx = const_cast<QGLContext *>(context); - bool switch_context = current && current != ctx && !qgl_share_reg()->checkSharing(current, ctx); - if (switch_context) - ctx->makeCurrent(); - glDeleteTextures(1, &id); - if (switch_context) - current->makeCurrent(); - } - } - - const QGLContext *context; - GLuint id; - GLenum target; - bool clean; -}; - -typedef QCache<qint64, QGLTexture> QGLTextureCache; -static int qt_tex_cache_limit = 64*1024; // cache ~64 MB worth of textures - this is not accurate though -static QGLTextureCache *qt_tex_cache = 0; - typedef void (*_qt_pixmap_cleanup_hook_64)(qint64); typedef void (*_qt_image_cleanup_hook_64)(qint64); extern Q_GUI_EXPORT _qt_pixmap_cleanup_hook_64 qt_pixmap_cleanup_hook_64; extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; +static QGLTextureCache *qt_gl_texture_cache = 0; + +QGLTextureCache::QGLTextureCache() + : m_cache(64*1024) // cache ~64 MB worth of textures - this is not accurate though +{ + Q_ASSERT(qt_gl_texture_cache == 0); + qt_gl_texture_cache = this; + qt_pixmap_cleanup_hook_64 = cleanupHook; + qt_image_cleanup_hook_64 = cleanupHook; +} + +QGLTextureCache::~QGLTextureCache() +{ + qt_gl_texture_cache = 0; + qt_pixmap_cleanup_hook_64 = 0; + qt_image_cleanup_hook_64 = 0; +} + +void QGLTextureCache::insert(QGLContext* ctx, qint64 key, QGLTexture* texture, int cost) +{ + if (m_cache.totalCost() + cost > m_cache.maxCost()) { + // the cache is full - make an attempt to remove something + const QList<qint64> keys = m_cache.keys(); + int i = 0; + while (i < m_cache.count() + && (m_cache.totalCost() + cost > m_cache.maxCost())) { + QGLTexture *tex = m_cache.object(keys.at(i)); + if (tex->context == ctx) + m_cache.remove(keys.at(i)); + ++i; + } + } + m_cache.insert(key, texture, cost); +} + +bool QGLTextureCache::remove(QGLContext* ctx, GLuint textureId) +{ + QList<qint64> keys = m_cache.keys(); + for (int i = 0; i < keys.size(); ++i) { + QGLTexture *tex = m_cache.object(keys.at(i)); + if (tex->id == textureId && tex->context == ctx) { + tex->clean = true; // forces a glDeleteTextures() call + m_cache.remove(keys.at(i)); + return true; + } + } + return false; +} + +void QGLTextureCache::removeContextTextures(QGLContext* ctx) +{ + QList<qint64> keys = m_cache.keys(); + for (int i = 0; i < keys.size(); ++i) { + const qint64 &key = keys.at(i); + if (m_cache.object(key)->context == ctx) + m_cache.remove(key); + } +} + +QGLTextureCache* QGLTextureCache::instance() +{ + if (!qt_gl_texture_cache) + qt_gl_texture_cache = new QGLTextureCache; + + return qt_gl_texture_cache; +} + +/* + a hook that removes textures from the cache when a pixmap/image + is deref'ed +*/ +void QGLTextureCache::cleanupHook(qint64 cacheKey) +{ + // ### remove when the GL texture cache becomes thread-safe + if (qApp->thread() != QThread::currentThread()) + return; + QGLTexture *texture = instance()->getTexture(cacheKey); + if (texture && texture->clean) + instance()->remove(cacheKey); +} + +void QGLTextureCache::deleteIfEmpty() +{ + if (instance()->size() == 0) + delete instance(); +} + // DDS format structure struct DDSFormat { quint32 dwSize; @@ -1556,21 +1615,8 @@ QGLContext::~QGLContext() { Q_D(QGLContext); // remove any textures cached in this context - if (qt_tex_cache) { - QList<qint64> keys = qt_tex_cache->keys(); - for (int i = 0; i < keys.size(); ++i) { - const qint64 &key = keys.at(i); - if (qt_tex_cache->object(key)->context == this) - qt_tex_cache->remove(key); - } - // ### thread safety - if (qt_tex_cache->size() == 0) { - qt_pixmap_cleanup_hook_64 = 0; - qt_image_cleanup_hook_64 = 0; - delete qt_tex_cache; - qt_tex_cache = 0; - } - } + QGLTextureCache::instance()->removeContextTextures(this); + QGLTextureCache::deleteIfEmpty(); // ### thread safety QGLSignalProxy::instance()->emitAboutToDestroyContext(this); reset(); @@ -1701,21 +1747,6 @@ GLuint QGLContext::bindTexture(const QString &fileName) return tx_id; } -/* - a hook that removes textures from the cache when a pixmap/image - is deref'ed -*/ -static void qt_gl_clean_cache(qint64 cacheKey) -{ - // ### remove when the GL texture cache becomes thread-safe - if (qApp->thread() != QThread::currentThread()) - return; - if (qt_tex_cache) { - QGLTexture *texture = qt_tex_cache->object(cacheKey); - if (texture && texture->clean) - qt_tex_cache->remove(cacheKey); - } -} static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format) { @@ -1835,7 +1866,28 @@ QImage QGLContextPrivate::convertToGLFormat(const QImage &image, bool force_prem return result; } -GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, +/*! \internal */ +QGLTexture *QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, bool clean) +{ + const qint64 key = image.cacheKey(); + QGLTexture *texture = textureCacheLookup(key, target); + if (texture) { + glBindTexture(target, texture->id); + return texture; + } + + if (!texture) + texture = bindTexture(image, target, format, key, clean); + // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null + Q_ASSERT(texture); + + if (texture->id > 0) + const_cast<QImage &>(image).data_ptr()->is_cached = true; + + return texture; +} + +QGLTexture* QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, bool clean) { Q_Q(QGLContext); @@ -1853,11 +1905,6 @@ GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint // the GL_BGRA format is only present in GL version >= 1.2 GLenum texture_format = (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_2) ? GL_BGRA : GL_RGBA; - if (!qt_tex_cache) { - qt_tex_cache = new QGLTextureCache(qt_tex_cache_limit); - qt_pixmap_cleanup_hook_64 = qt_gl_clean_cache; - qt_image_cleanup_hook_64 = qt_gl_clean_cache; - } // Scale the pixmap if needed. GL textures needs to have the // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL @@ -1930,53 +1977,26 @@ GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint // this assumes the size of a texture is always smaller than the max cache size int cost = img.width()*img.height()*4/1024; - if (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost()) { - // the cache is full - make an attempt to remove something - const QList<qint64> keys = qt_tex_cache->keys(); - int i = 0; - while (i < qt_tex_cache->count() - && (qt_tex_cache->totalCost() + cost > qt_tex_cache->maxCost())) { - QGLTexture *tex = qt_tex_cache->object(keys.at(i)); - if (tex->context == q) - qt_tex_cache->remove(keys.at(i)); - ++i; - } - } - qt_tex_cache->insert(key, new QGLTexture(q, tx_id, target, clean), cost); - return tx_id; + QGLTexture *texture = new QGLTexture(q, tx_id, target, clean, false); + QGLTextureCache::instance()->insert(q, key, texture, cost); + return texture; } -bool QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target, GLuint *id) +QGLTexture *QGLContextPrivate::textureCacheLookup(const qint64 key, GLenum target) { Q_Q(QGLContext); - if (qt_tex_cache) { - QGLTexture *texture = qt_tex_cache->object(key); - if (texture && texture->target == target - && (texture->context == q || qgl_share_reg()->checkSharing(q, texture->context))) - { - *id = texture->id; - return true; - } + QGLTexture *texture = QGLTextureCache::instance()->getTexture(key); + if (texture && texture->target == target + && (texture->context == q || qgl_share_reg()->checkSharing(q, texture->context))) + { + return texture; } - return false; + return 0; } -/*! \internal */ -GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint format, bool clean) -{ - const qint64 key = image.cacheKey(); - GLuint id; - if (textureCacheLookup(key, target, &id)) { - glBindTexture(target, id); - return id; - } - GLuint cached = bindTexture(image, target, format, key, clean); - const_cast<QImage &>(image).data_ptr()->is_cached = (cached > 0); - return cached; -} /*! \internal */ -GLuint QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean) +QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean, bool canInvert) { Q_Q(QGLContext); QPixmapData *pd = pixmap.pixmapData(); @@ -1984,20 +2004,41 @@ GLuint QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLin if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) { const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd); - if (data->isValidContext(q)) - return data->bind(); + if (data->isValidContext(q)) { + data->bind(); + return data->texture(); + } } #endif const qint64 key = pixmap.cacheKey(); - GLuint id; - if (textureCacheLookup(key, target, &id)) { - glBindTexture(target, id); - return id; + QGLTexture *texture = textureCacheLookup(key, target); + if (texture) { + glBindTexture(target, texture->id); + return texture; } - GLuint cached = bindTexture(pixmap.toImage(), target, format, key, clean); - const_cast<QPixmap &>(pixmap).data_ptr()->is_cached = (cached > 0); - return cached; + +#if defined(Q_WS_X11) + // Try to use texture_from_pixmap + if (pd->classId() == QPixmapData::X11Class) { + QPixmap *thatPixmap = const_cast<QPixmap*>(&pixmap); + texture = bindTextureFromNativePixmap(thatPixmap, key, canInvert); + if (texture) { + texture->clean = clean; + boundPixmaps.insert(thatPixmap->data_ptr(), QPixmap(pixmap)); + } + } +#endif + + if (!texture) + texture = bindTexture(pixmap.toImage(), target, format, key, clean); + // NOTE: bindTexture(const QImage&, GLenum, GLint, const qint64, bool) should never return null + Q_ASSERT(texture); + + if (texture->id > 0) + const_cast<QPixmap &>(pixmap).data_ptr()->is_cached = true; + + return texture; } /*! \internal */ @@ -2063,7 +2104,8 @@ int QGLContextPrivate::maxTextureSize() GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format) { Q_D(QGLContext); - return d->bindTexture(image, target, format, false); + QGLTexture *texture = d->bindTexture(image, target, format, false); + return texture->id; } #ifdef Q_MAC_COMPAT_GL_FUNCTIONS @@ -2071,7 +2113,8 @@ GLuint QGLContext::bindTexture(const QImage &image, GLenum target, GLint format) GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMacCompatGLint format) { Q_D(QGLContext); - return d->bindTexture(image, GLenum(target), GLint(format), false); + QGLTexture *texture = d->bindTexture(image, GLenum(target), GLint(format), false); + return texture->id; } #endif @@ -2082,7 +2125,8 @@ GLuint QGLContext::bindTexture(const QImage &image, QMacCompatGLenum target, QMa GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint format) { Q_D(QGLContext); - return d->bindTexture(pixmap, target, format, false); + QGLTexture *texture = d->bindTexture(pixmap, target, format, false, false); + return texture->id; } #ifdef Q_MAC_COMPAT_GL_FUNCTIONS @@ -2090,7 +2134,8 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, GLenum target, GLint forma GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, QMacCompatGLint format) { Q_D(QGLContext); - return d->bindTexture(pixmap, GLenum(target), GLint(format), false); + QGLTexture *texture = d->bindTexture(pixmap, GLenum(target), GLint(format), false, false); + return texture->id; } #endif @@ -2103,17 +2148,8 @@ GLuint QGLContext::bindTexture(const QPixmap &pixmap, QMacCompatGLenum target, Q */ void QGLContext::deleteTexture(GLuint id) { - if (qt_tex_cache) { - QList<qint64> keys = qt_tex_cache->keys(); - for (int i = 0; i < keys.size(); ++i) { - QGLTexture *tex = qt_tex_cache->object(keys.at(i)); - if (tex->id == id && tex->context == this) { - tex->clean = true; // forces a glDeleteTextures() call - qt_tex_cache->remove(keys.at(i)); - return; - } - } - } + if (QGLTextureCache::instance()->remove(this, id)) + return; // check the DDS cache if the texture wasn't found in the pixmap/image // cache @@ -2307,9 +2343,7 @@ void QGLContext::drawTexture(const QPointF &point, QMacCompatGLuint textureId, Q */ void QGLContext::setTextureCacheLimit(int size) { - qt_tex_cache_limit = size; - if (qt_tex_cache) - qt_tex_cache->setMaxCost(qt_tex_cache_limit); + QGLTextureCache::instance()->setMaxCost(size); } /*! @@ -2319,7 +2353,7 @@ void QGLContext::setTextureCacheLimit(int size) */ int QGLContext::textureCacheLimit() { - return qt_tex_cache_limit; + return QGLTextureCache::instance()->maxCost(); } @@ -3363,8 +3397,13 @@ bool QGLWidget::event(QEvent *e) #elif defined(Q_WS_WIN) if (e->type() == QEvent::ParentChange) { QGLContext *newContext = new QGLContext(d->glcx->requestedFormat(), this); - qgl_share_reg()->replaceShare(d->glcx, newContext); + QList<const QGLContext *> shares = qgl_share_reg()->shares(d->glcx); setContext(newContext); + for (int i = 0; i < shares.size(); ++i) { + if (newContext != shares.at(i)) + qgl_share_reg()->addShare(newContext, shares.at(i)); + } + // the overlay needs to be recreated as well delete d->olcx; if (isValid() && context()->format().hasOverlay()) { @@ -4334,6 +4373,9 @@ void QGLExtensions::init_extensions() if (extensions.contains(QLatin1String("EXT_framebuffer_blit"))) glExtensions |= FramebufferBlit; + if (extensions.contains(QLatin1String("GL_ARB_texture_non_power_of_two"))) + glExtensions |= NPOTTextures; + QGLContext cx(QGLFormat::defaultFormat()); if (glExtensions & TextureCompression) { qt_glCompressedTexImage2DARB = (pfn_glCompressedTexImage2DARB) cx.getProcAddress(QLatin1String("glCompressedTexImage2DARB")); @@ -4541,32 +4583,34 @@ QGLFormat QGLDrawable::format() const GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format) { + QGLTexture *texture; if (widget) - return widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true); + texture = widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true); else if (buffer) - return buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true); + texture = buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true); else if (fbo && QGLContext::currentContext()) - return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true); + texture = const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true); #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)) else if (wsurf) - return wsurf->context()->d_func()->bindTexture(image, target, format, true); + texture = wsurf->context()->d_func()->bindTexture(image, target, format, true); #endif - return 0; + return texture->id; } GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format) { + QGLTexture *texture; if (widget) - return widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true); + texture = widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true, true); else if (buffer) - return buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true); + texture = buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true, true); else if (fbo && QGLContext::currentContext()) - return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true); + texture = const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true, true); #if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)) else if (wsurf) - return wsurf->context()->d_func()->bindTexture(pixmap, target, format, true); + texture = wsurf->context()->d_func()->bindTexture(pixmap, target, format, true, true); #endif - return 0; + return texture->id; } QColor QGLDrawable::backgroundColor() const @@ -4612,4 +4656,156 @@ bool QGLDrawable::autoFillBackground() const return false; } + +bool QGLShareRegister::checkSharing(const QGLContext *context1, const QGLContext *context2) { + bool sharing = (context1 && context2 && context1->d_ptr->groupResources == context2->d_ptr->groupResources); + return sharing; +} + +void QGLShareRegister::addShare(const QGLContext *context, const QGLContext *share) { + Q_ASSERT(context && share); + if (context->d_ptr->groupResources == share->d_ptr->groupResources) + return; + + // Make sure 'context' is not already shared with another group of contexts. + Q_ASSERT(reg.find(context->d_ptr->groupResources) == reg.end()); + Q_ASSERT(context->d_ptr->groupResources->refs == 1); + + // Free 'context' group resources and make it use the same resources as 'share'. + delete context->d_ptr->groupResources; + context->d_ptr->groupResources = share->d_ptr->groupResources; + context->d_ptr->groupResources->refs.ref(); + + // Maintain a list of all the contexts in each group of sharing contexts. + SharingHash::iterator it = reg.find(share->d_ptr->groupResources); + if (it == reg.end()) + it = reg.insert(share->d_ptr->groupResources, ContextList() << share); + it.value() << context; +} + +QList<const QGLContext *> QGLShareRegister::shares(const QGLContext *context) { + SharingHash::const_iterator it = reg.find(context->d_ptr->groupResources); + if (it == reg.end()) + return ContextList(); + return it.value(); +} + +void QGLShareRegister::removeShare(const QGLContext *context) { + SharingHash::iterator it = reg.find(context->d_ptr->groupResources); + if (it == reg.end()) + return; + + int count = it.value().removeAll(context); + Q_ASSERT(count == 1); + + Q_ASSERT(it.value().size() != 0); + if (it.value().size() == 1) + reg.erase(it); +} + +QGLContextResource::QGLContextResource(FreeFunc f, QObject *parent) + : QObject(parent), free(f) +{ + connect(QGLSignalProxy::instance(), SIGNAL(aboutToDestroyContext(const QGLContext *)), this, SLOT(aboutToDestroyContext(const QGLContext *))); +} + +QGLContextResource::~QGLContextResource() +{ + while (!m_resources.empty()) + remove(m_resources.begin().key()); +} + +void QGLContextResource::insert(const QGLContext *key, void *value) +{ + QList<const QGLContext *> shares = qgl_share_reg()->shares(key); + if (shares.size() == 0) + shares.append(key); + void *oldValue = 0; + for (int i = 0; i < shares.size(); ++i) { + ResourceHash::iterator it = m_resources.find(shares.at(i)); + if (it != m_resources.end()) { + Q_ASSERT(oldValue == 0 || oldValue == it.value()); + oldValue = it.value(); + it.value() = value; + } else { + m_resources.insert(shares.at(i), value); + } + } + if (oldValue != 0 && oldValue != value) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != key) + const_cast<QGLContext *>(key)->makeCurrent(); + free(oldValue); + if (oldContext && oldContext != key) + oldContext->makeCurrent(); + } +} + +void *QGLContextResource::value(const QGLContext *key) +{ + ResourceHash::const_iterator it = m_resources.find(key); + // Check if there is a value associated with 'key'. + if (it != m_resources.end()) + return it.value(); + // Check if there is a value associated with sharing contexts. + QList<const QGLContext *> shares = qgl_share_reg()->shares(key); + for (int i = 0; i < shares.size() && it == m_resources.end(); ++i) + it = m_resources.find(shares.at(i)); + if (it == m_resources.end()) + return 0; // Didn't find anything. + + // Found something! Share this info with all the buddies. + for (int i = 0; i < shares.size(); ++i) + m_resources.insert(shares.at(i), it.value()); + return it.value(); +} + +void QGLContextResource::remove(const QGLContext *key) +{ + QList<const QGLContext *> shares = qgl_share_reg()->shares(key); + if (shares.size() == 0) + shares.append(key); + void *oldValue = 0; + for (int i = 0; i < shares.size(); ++i) { + ResourceHash::iterator it = m_resources.find(shares.at(i)); + if (it != m_resources.end()) { + Q_ASSERT(oldValue == 0 || oldValue == it.value()); + oldValue = it.value(); + m_resources.erase(it); + } + } + if (oldValue != 0) { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != key) + const_cast<QGLContext *>(key)->makeCurrent(); + free(oldValue); + if (oldContext && oldContext != key) + oldContext->makeCurrent(); + } +} + +void QGLContextResource::aboutToDestroyContext(const QGLContext *key) +{ + ResourceHash::iterator it = m_resources.find(key); + if (it == m_resources.end()) + return; + + QList<const QGLContext *> shares = qgl_share_reg()->shares(key); + if (shares.size() > 1) { + Q_ASSERT(key->isSharing()); + // At least one of the shared contexts must stay in the cache. + // Otherwise, the value pointer is lost. + for (int i = 0; i < 2/*shares.size()*/; ++i) + m_resources.insert(shares.at(i), it.value()); + } else { + QGLContext *oldContext = const_cast<QGLContext *>(QGLContext::currentContext()); + if (oldContext != key) + const_cast<QGLContext *>(key)->makeCurrent(); + free(it.value()); + if (oldContext && oldContext != key) + oldContext->makeCurrent(); + } + m_resources.erase(it); +} + QT_END_NAMESPACE diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h index 86555da..31b9543 100644 --- a/src/opengl/qgl.h +++ b/src/opengl/qgl.h @@ -364,6 +364,7 @@ private: friend class QGLPixmapData; friend class QGLPixmapFilterBase; friend class QGLTextureGlyphCache; + friend class QGLShareRegister; friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags(); #ifdef Q_WS_MAC public: diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index ac19d64..85dae0d 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -60,10 +60,7 @@ #include "QtCore/qthreadstorage.h" #include "QtCore/qhash.h" #include "private/qwidget_p.h" - -#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) -#include "private/qpixmapdata_gl_p.h" -#endif +#include "qcache.h" #ifndef QT_OPENGL_ES_1_CL #define q_vertexType float @@ -196,17 +193,26 @@ public: #endif }; +struct QGLContextGroupResources +{ + QGLContextGroupResources() : refs(1) { } + QGLExtensionFuncs extensionFuncs; + QAtomicInt refs; +}; + +class QGLTexture; + class QGLContextPrivate { Q_DECLARE_PUBLIC(QGLContext) public: - explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {} - ~QGLContextPrivate() {} - GLuint bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, + explicit QGLContextPrivate(QGLContext *context) : internal_context(false), q_ptr(context) {groupResources = new QGLContextGroupResources;} + ~QGLContextPrivate() {if (!groupResources->refs.deref()) delete groupResources;} + QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, bool clean); + QGLTexture *bindTexture(const QImage &image, GLenum target, GLint format, const qint64 key, bool clean = false); - GLuint bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean); - GLuint bindTexture(const QImage &image, GLenum target, GLint format, bool clean); - bool textureCacheLookup(const qint64 key, GLenum target, GLuint *id); + QGLTexture *bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean, bool canInvert = false); + QGLTexture *textureCacheLookup(const qint64 key, GLenum target); void init(QPaintDevice *dev, const QGLFormat &format); QImage convertToGLFormat(const QImage &image, bool force_premul, GLenum texture_format); int maxTextureSize(); @@ -234,6 +240,8 @@ public: void* pbuf; quint32 gpm; int screen; + QHash<QPixmapData*, QPixmap> boundPixmaps; + QGLTexture *bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool internal); #endif #if defined(Q_WS_MAC) bool update; @@ -257,14 +265,14 @@ public: QGLContext *q_ptr; QGLFormat::OpenGLVersionFlags version_flags; - QGLExtensionFuncs extensionFuncs; + QGLContextGroupResources *groupResources; GLint max_texture_size; GLuint current_fbo; QPaintEngine *active_engine; #ifdef Q_WS_WIN - static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->extensionFuncs; } + static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->groupResources->extensionFuncs; } #endif #if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) @@ -293,6 +301,7 @@ class QGLPixelBuffer; class QGLFramebufferObject; class QWSGLWindowSurface; class QGLWindowSurface; +class QGLPixmapData; class QGLDrawable { public: QGLDrawable() : widget(0), buffer(0), fbo(0) @@ -353,7 +362,8 @@ public: PackedDepthStencil = 0x00000200, NVFloatBuffer = 0x00000400, PixelBufferObject = 0x00000800, - FramebufferBlit = 0x00001000 + FramebufferBlit = 0x00001000, + NPOTTextures = 0x00002000 }; Q_DECLARE_FLAGS(Extensions, Extension) @@ -371,65 +381,89 @@ struct QGLThreadContext { }; extern QThreadStorage<QGLThreadContext *> qgl_context_storage; -typedef QMultiHash<const QGLContext *, const QGLContext *> QGLSharingHash; class QGLShareRegister { public: QGLShareRegister() {} ~QGLShareRegister() { reg.clear(); } - bool checkSharing(const QGLContext *context1, const QGLContext *context2, const QGLContext * skip=0) { - if (context1 == context2) - return true; - QList<const QGLContext *> shares = reg.values(context1); - for (int k=0; k<shares.size(); ++k) { - const QGLContext *ctx = shares.at(k); - if (ctx == skip) // avoid an indirect circular loop (infinite recursion) - continue; - if (ctx == context2) - return true; - if (checkSharing(ctx, context2, context1)) - return true; - } - return false; - } + bool checkSharing(const QGLContext *context1, const QGLContext *context2); + void addShare(const QGLContext *context, const QGLContext *share); + QList<const QGLContext *> shares(const QGLContext *context); + void removeShare(const QGLContext *context); +private: + // Use a context's 'groupResources' pointer to uniquely identify a group. + typedef QList<const QGLContext *> ContextList; + typedef QHash<const QGLContextGroupResources *, ContextList> SharingHash; + SharingHash reg; +}; - void addShare(const QGLContext *context, const QGLContext *share) { - reg.insert(context, share); // context sharing works both ways - reg.insert(share, context); - } +extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg(); - void removeShare(const QGLContext *context) { - QGLSharingHash::iterator it = reg.begin(); - while (it != reg.end()) { - if (it.key() == context || it.value() == context) - it = reg.erase(it); - else - ++it; +class QGLTexture { +public: + QGLTexture(QGLContext *ctx = 0, GLuint tx_id = 0, GLenum tx_target = GL_TEXTURE_2D, + bool _clean = false, bool _yInverted = false) + : context(ctx), id(tx_id), target(tx_target), clean(_clean), yInverted(_yInverted) +#if defined(Q_WS_X11) + , boundPixmap(0) +#endif + {} + + ~QGLTexture() { + if (clean) { + QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext()); + QGLContext *ctx = const_cast<QGLContext *>(context); + Q_ASSERT(ctx); + bool switch_context = current != ctx && !qgl_share_reg()->checkSharing(current, ctx); + if (switch_context) + ctx->makeCurrent(); +#if defined(Q_WS_X11) + // Although glXReleaseTexImage is a glX call, it must be called while there + // is a current context - the context the pixmap was bound to a texture in. + // Otherwise the release doesn't do anything and you get BadDrawable errors + // when you come to delete the context. + deleteBoundPixmap(); +#endif + glDeleteTextures(1, &id); + if (switch_context && current) + current->makeCurrent(); } - } + } - void replaceShare(const QGLContext *oldContext, const QGLContext *newContext) { - QGLSharingHash::iterator it = reg.begin(); - while (it != reg.end()) { - if (it.key() == oldContext) - reg.insert(newContext, it.value()); - else if (it.value() == oldContext) - reg.insert(it.key(), newContext); - ++it; - } - removeShare(oldContext); - } + QGLContext *context; + GLuint id; + GLenum target; + bool clean; + bool yInverted; // NOTE: Y-Inverted textures are for internal use only! +#if defined(Q_WS_X11) + Qt::HANDLE boundPixmap; + void deleteBoundPixmap(); // in qgl_x11.cpp/qgl_x11egl.cpp +#endif +}; - QList<const QGLContext *> shares(const QGLContext *context) { - return reg.values(context); - } +class QGLTextureCache { +public: + QGLTextureCache(); + ~QGLTextureCache(); + + void insert(QGLContext *ctx, qint64 key, QGLTexture *texture, int cost); + void remove(quint64 key) { m_cache.remove(key); } + bool remove(QGLContext *ctx, GLuint textureId); + void removeContextTextures(QGLContext *ctx); + int size() { return m_cache.size(); } + void setMaxCost(int newMax) { m_cache.setMaxCost(newMax); } + int maxCost() {return m_cache.maxCost(); } + QGLTexture* getTexture(quint64 key) { return m_cache.object(key); } + + static QGLTextureCache *instance(); + static void deleteIfEmpty(); + static void cleanupHook(qint64 cacheKey); private: - QGLSharingHash reg; + QCache<qint64, QGLTexture> m_cache; }; -extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg(); #ifdef Q_WS_QWS extern QPaintEngine* qt_qgl_paint_engine(); @@ -464,6 +498,29 @@ inline GLenum qt_gl_preferredTextureTarget() #endif } +// One resource per group of shared contexts. +class QGLContextResource : public QObject +{ + Q_OBJECT +public: + typedef void (*FreeFunc)(void *); + QGLContextResource(FreeFunc f, QObject *parent = 0); + ~QGLContextResource(); + // Set resource 'value' for 'key' and all its shared contexts. + void insert(const QGLContext *key, void *value); + // Return resource for 'key' or a shared context. + void *value(const QGLContext *key); + // Free resource for 'key' and all its shared contexts. + void remove(const QGLContext *key); +private slots: + // Remove entry 'key' from cache and delete resource if there are no shared contexts. + void aboutToDestroyContext(const QGLContext *key); +private: + typedef QHash<const QGLContext *, void *> ResourceHash; + ResourceHash m_resources; + FreeFunc free; +}; + QT_END_NAMESPACE #endif // QGL_P_H diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index 631625b..43bdec7 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -52,6 +52,7 @@ #include "qdebug.h" #include <private/qfontengine_ft_p.h> #include <private/qt_x11_p.h> +#include <private/qpixmap_x11_p.h> #ifdef Q_OS_HPUX // for GLXPBuffer #include <private/qglpixelbuffer_p.h> @@ -81,6 +82,25 @@ extern const QX11Info *qt_x11Info(const QPaintDevice *pd); #define GLX_SAMPLES_ARB 100001 #endif +#ifndef GLX_EXT_texture_from_pixmap +#define GLX_TEXTURE_2D_BIT_EXT 0x00000002 +#define GLX_TEXTURE_RECTANGLE_BIT_EXT 0x00000004 +#define GLX_BIND_TO_TEXTURE_RGB_EXT 0x20D0 +#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1 +#define GLX_BIND_TO_MIPMAP_TEXTURE_EXT 0x20D2 +#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3 +#define GLX_Y_INVERTED_EXT 0x20D4 +#define GLX_TEXTURE_FORMAT_EXT 0x20D5 +#define GLX_TEXTURE_TARGET_EXT 0x20D6 +#define GLX_MIPMAP_TEXTURE_EXT 0x20D7 +#define GLX_TEXTURE_FORMAT_NONE_EXT 0x20D8 +#define GLX_TEXTURE_FORMAT_RGB_EXT 0x20D9 +#define GLX_TEXTURE_FORMAT_RGBA_EXT 0x20DA +#define GLX_TEXTURE_2D_EXT 0x20DC +#define GLX_TEXTURE_RECTANGLE_EXT 0x20DD +#define GLX_FRONT_LEFT_EXT 0x20DE +#endif + /* The qt_gl_choose_cmap function is internal and used by QGLWidget::setContext() and GLX (not Windows). If the application can't find any sharable @@ -1516,4 +1536,124 @@ void QGLExtensions::init() } } + +typedef void (*qt_glXBindTexImageEXT)(Display*, GLXDrawable, int, const int*); +typedef void (*qt_glXReleaseTexImageEXT)(Display*, GLXDrawable, int); +static qt_glXBindTexImageEXT glXBindTexImageEXT = 0; +static qt_glXReleaseTexImageEXT glXReleaseTexImageEXT = 0; +static bool qt_resolved_texture_from_pixmap = false; + +QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool canInvert) +{ + Q_Q(QGLContext); + + if (pm->data_ptr()->classId() != QPixmapData::X11Class) + return 0; + QX11PixmapData *pixmapData = static_cast<QX11PixmapData*>(pm->data_ptr()); + const QX11Info *x11Info = qt_x11Info(pm); + + + // Check to see if we have NPOT texture support + // TODO: Use GLX_TEXTURE_RECTANGLE_EXT texture target on systems without npot textures + if ( !(QGLExtensions::glExtensions & QGLExtensions::NPOTTextures) && + !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)) + return 0; + + if (!qt_resolved_texture_from_pixmap) { + qt_resolved_texture_from_pixmap = true; + + QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)); + if (glxExt.contains(QLatin1String("GLX_EXT_texture_from_pixmap"))) { +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) + void *handle = dlopen(NULL, RTLD_LAZY); + if (handle) { + glXBindTexImageEXT = (qt_glXBindTexImageEXT) dlsym(handle, "glXBindTexImageEXT"); + glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) dlsym(handle, "glXReleaseTexImageEXT"); + dlclose(handle); + } + if (!glXBindTexImageEXT) +#endif + { + extern const QString qt_gl_library_name(); + QLibrary lib(qt_gl_library_name()); + glXBindTexImageEXT = (qt_glXBindTexImageEXT) lib.resolve("glXBindTexImageEXT"); + glXReleaseTexImageEXT = (qt_glXReleaseTexImageEXT) lib.resolve("glXReleaseTexImageEXT"); + } + } + } + + if (!glXBindTexImageEXT) + return 0; + +#if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX) + return 0; +#else + GLXFBConfig *configList = 0; + GLXFBConfig glxPixmapConfig; + int configCount = 0; + bool hasAlpha = pixmapData->hasAlphaChannel(); + + int configAttribs[] = { + hasAlpha ? GLX_BIND_TO_TEXTURE_RGBA_EXT : GLX_BIND_TO_TEXTURE_RGB_EXT, True, + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, + // QGLContext::bindTexture() can't return an inverted texture, but QPainter::drawPixmap() can: + GLX_Y_INVERTED_EXT, canInvert ? GLX_DONT_CARE : False, + XNone +// GLX_BIND_TO_MIPMAP_TEXTURE_EXT, False, +// GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_1D_BIT_EXT or GLX_TEXTURE_2D_BIT_EXT or GLX_TEXTURE_RECTANGLE_BIT_EXT + }; + configList = glXChooseFBConfig(x11Info->display(), x11Info->screen(), configAttribs, &configCount); + if (!configList) + return 0; + glxPixmapConfig = configList[0]; + XFree(configList); + + GLXPixmap glxPixmap; + int pixmapAttribs[] = { + GLX_TEXTURE_FORMAT_EXT, hasAlpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT, + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, + GLX_MIPMAP_TEXTURE_EXT, False, + XNone +// GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT or GLX_TEXTURE_FORMAT_RGB_EXT or GLX_TEXTURE_FORMAT_NONE_EXT, +// GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT or GLX_TEXTURE_RECTANGLE_EXT, +// GLX_MIPMAP_TEXTURE_EXT, True or False, + }; + + // Wrap the X Pixmap into a GLXPixmap: + glxPixmap = glXCreatePixmap(x11Info->display(), glxPixmapConfig, pixmapData->handle(), pixmapAttribs); + + if (!glxPixmap) + return 0; + + int yInverted; + glXGetFBConfigAttrib(x11Info->display(), glxPixmapConfig, GLX_Y_INVERTED_EXT, &yInverted); + + GLuint textureId; + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); + glXBindTexImageEXT(x11Info->display(), glxPixmap, GLX_FRONT_LEFT_EXT, 0); + + glBindTexture(GL_TEXTURE_2D, textureId); + + QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, canInvert, yInverted); + texture->boundPixmap = glxPixmap; + + // We assume the cost of bound pixmaps is zero + QGLTextureCache::instance()->insert(q, key, texture, 0); + + return texture; +#endif //!defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX) +} + +void QGLTexture::deleteBoundPixmap() +{ + if (boundPixmap) { + glXReleaseTexImageEXT(QX11Info::display(), boundPixmap, GLX_FRONT_LEFT_EXT); + glXDestroyPixmap(QX11Info::display(), boundPixmap); + boundPixmap = 0; + } +} + + QT_END_NAMESPACE diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 9db3a30..99b026d 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -469,4 +469,15 @@ void QGLWidgetPrivate::recreateEglSurface(bool force) } } +QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pm, const qint64 key, bool canInvert) +{ + // TODO + return 0; +} + +void QGLTexture::deleteBoundPixmap() +{ + //TODO +} + QT_END_NAMESPACE diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index 3bb42c8..4f15197 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -535,7 +535,7 @@ struct QGLExtensionFuncs #endif #ifndef GL_MAX_SAMPLES_EXT -#define GL_MAX_SAMPLES_EXT 0x8D5 +#define GL_MAX_SAMPLES_EXT 0x8D57 #endif #ifndef GL_DRAW_FRAMEBUFFER_EXT diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 7514743..1e72fd8 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -40,23 +40,27 @@ ****************************************************************************/ #include "private/qpixmapfilter_p.h" +#include "private/qpixmapdata_gl_p.h" +#include "private/qpaintengineex_opengl2_p.h" +#include "private/qglengineshadermanager_p.h" #include "qglpixmapfilter_p.h" #include "qgraphicssystem_gl_p.h" #include "qpaintengine_opengl_p.h" +#include "qcache.h" -#include "qglpixelbuffer.h" +#include "qglframebufferobject.h" #include "qglshaderprogram.h" #include "qgl_p.h" #include "private/qapplication_p.h" +#include "private/qmath_p.h" QT_BEGIN_NAMESPACE - void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const { - const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(src, GL_TEXTURE_2D, GL_RGBA, true); + const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(src, GL_TEXTURE_2D, GL_RGBA, true, false); } void QGLPixmapFilterBase::drawImpl(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF& source) const @@ -97,6 +101,27 @@ private: mutable int m_kernelHeight; }; +class QGLPixmapBlurFilter : public QGLCustomShaderStage, public QGLPixmapFilter<QPixmapBlurFilter> +{ +public: + QGLPixmapBlurFilter(); + ~QGLPixmapBlurFilter(); + + void setUniforms(QGLShaderProgram *program); + +protected: + bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const; + +private: + static QByteArray generateBlurShader(int radius, bool gaussianBlur); + + mutable QGLShader *m_shader; + + mutable QSize m_textureSize; + + QGLShaderProgram *m_program; +}; + extern QGLWidget *qt_gl_share_widget(); QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const @@ -105,6 +130,8 @@ QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const case QPixmapFilter::ColorizeFilter: return new QGLPixmapColorizeFilter; + case QPixmapFilter::BlurFilter: + return new QGLPixmapBlurFilter; case QPixmapFilter::ConvolutionFilter: return new QGLPixmapConvolutionFilter; @@ -281,4 +308,250 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const return true; } +QGLPixmapBlurFilter::QGLPixmapBlurFilter() +{ +} + +QGLPixmapBlurFilter::~QGLPixmapBlurFilter() +{ +} + +bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const +{ + QGLPixmapBlurFilter *filter = const_cast<QGLPixmapBlurFilter *>(this); + filter->setSource(generateBlurShader(radius(), quality() == Qt::SmoothTransformation)); + + QGLFramebufferObjectFormat format; + format.setInternalFormat(src.hasAlphaChannel() ? GL_RGBA : GL_RGB); + QGLFramebufferObject *fbo = qgl_fbo_pool()->acquire(src.size(), format); + + if (!fbo) + return false; + + glBindTexture(GL_TEXTURE_2D, fbo->texture()); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, 0); + + QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(painter->paintEngine()); + + engine->syncState(); + painter->save(); + + // ensure GL_LINEAR filtering is used + painter->setRenderHint(QPainter::SmoothPixmapTransform); + + // prepare for updateUniforms + m_textureSize = src.size(); + + // first pass, to fbo + fbo->bind(); + if (src.hasAlphaChannel()) { + glClearColor(0, 0, 0, 0); + glClear(GL_COLOR_BUFFER_BIT); + } + + filter->setOnPainter(painter); + + QTransform transform = engine->state()->matrix; + if (!transform.isIdentity()) { + engine->state()->matrix = QTransform(); + engine->transformChanged(); + } + + engine->drawPixmap(src.rect().translated(0, painter->device()->height() - fbo->height()), + src, src.rect()); + + if (!transform.isIdentity()) { + engine->state()->matrix = transform; + engine->transformChanged(); + } + + fbo->release(); + + // second pass, to widget + m_program->setUniformValue("delta", 0.0, 1.0); + engine->drawTexture(src.rect().translated(pos.x(), pos.y()), fbo->texture(), fbo->size(), src.rect().translated(0, fbo->height() - src.height())); + filter->removeFromPainter(painter); + + painter->restore(); + + qgl_fbo_pool()->release(fbo); + + return true; +} + +void QGLPixmapBlurFilter::setUniforms(QGLShaderProgram *program) +{ + program->setUniformValue("invTextureSize", 1.0 / m_textureSize.width(), 1.0 / m_textureSize.height()); + program->setUniformValue("delta", 1.0, 0.0); + + m_program = program; +} + +static inline qreal gaussian(qreal dx, qreal sigma) +{ + return exp(-dx * dx / (2 * sigma * sigma)) / (Q_2PI * sigma * sigma); +} + +QByteArray QGLPixmapBlurFilter::generateBlurShader(int radius, bool gaussianBlur) +{ + Q_ASSERT(radius >= 1); + + QByteArray source; + source.reserve(1000); + + source.append("uniform highp vec2 invTextureSize;\n"); + + bool separateXY = true; + bool clip = false; + + if (separateXY) { + source.append("uniform highp vec2 delta;\n"); + + if (clip) + source.append("uniform highp vec2 clip;\n"); + } else if (clip) { + source.append("uniform highp vec4 clip;\n"); + } + + source.append("mediump vec4 customShader(sampler2D src, vec2 srcCoords) {\n"); + + QVector<qreal> sampleOffsets; + QVector<qreal> weights; + + if (gaussianBlur) { + QVector<qreal> gaussianComponents; + + qreal sigma = radius / 1.65; + + qreal sum = 0; + for (int i = -radius; i <= radius; ++i) { + float value = gaussian(i, sigma); + gaussianComponents << value; + sum += value; + } + + // normalize + for (int i = 0; i < gaussianComponents.size(); ++i) + gaussianComponents[i] /= sum; + + for (int i = 0; i < gaussianComponents.size() - 1; i += 2) { + qreal weight = gaussianComponents.at(i) + gaussianComponents.at(i + 1); + qreal offset = i - radius + gaussianComponents.at(i + 1) / weight; + + sampleOffsets << offset; + weights << weight; + } + + // odd size ? + if (gaussianComponents.size() & 1) { + sampleOffsets << radius; + weights << gaussianComponents.last(); + } + } else { + for (int i = 0; i < radius; ++i) { + sampleOffsets << 2 * i - radius + 0.5; + weights << qreal(1); + } + sampleOffsets << radius; + weights << qreal(0.5); + } + + int currentVariable = 1; + source.append(" mediump vec4 sample = vec4(0.0);\n"); + source.append(" mediump vec2 coord;\n"); + + qreal weightSum = 0; + if (separateXY) { + source.append(" mediump float c;\n"); + for (int i = 0; i < sampleOffsets.size(); ++i) { + qreal delta = sampleOffsets.at(i); + + ++currentVariable; + + QByteArray coordinate = "srcCoords"; + if (delta != qreal(0)) { + coordinate.append(" + invTextureSize * delta * float("); + coordinate.append(QByteArray::number(delta)); + coordinate.append(")"); + } + + source.append(" coord = "); + source.append(coordinate); + source.append(";\n"); + + if (clip) { + source.append(" c = dot(coord, delta);\n"); + source.append(" if (c > clip.x && c < clip.y)\n "); + } + + source.append(" sample += texture2D(src, coord)"); + + weightSum += weights.at(i); + if (weights.at(i) != qreal(1)) { + source.append(" * float("); + source.append(QByteArray::number(weights.at(i))); + source.append(");\n"); + } else { + source.append(";\n"); + } + } + } else { + for (int y = 0; y < sampleOffsets.size(); ++y) { + for (int x = 0; x < sampleOffsets.size(); ++x) { + QByteArray coordinate = "srcCoords"; + + qreal dx = sampleOffsets.at(x); + qreal dy = sampleOffsets.at(y); + + if (dx != qreal(0) || dy != qreal(0)) { + coordinate.append(" + invTextureSize * vec2(float("); + coordinate.append(QByteArray::number(dx)); + coordinate.append("), float("); + coordinate.append(QByteArray::number(dy)); + coordinate.append("))"); + } + + source.append(" coord = "); + source.append(coordinate); + source.append(";\n"); + + if (clip) + source.append(" if (coord.x > clip.x && coord.x < clip.y && coord.y > clip.z && coord.y < clip.w)\n "); + + source.append(" sample += texture2D(src, coord)"); + + ++currentVariable; + + weightSum += weights.at(x) * weights.at(y); + if ((weights.at(x) != qreal(1) || weights.at(y) != qreal(1))) { + source.append(" * float("); + source.append(QByteArray::number(weights.at(x) * weights.at(y))); + source.append(");\n"); + } else { + source.append(";\n"); + } + } + } + } + + source.append(" return "); + if (!gaussianBlur) { + source.append("float("); + if (separateXY) + source.append(QByteArray::number(1 / weightSum)); + else + source.append(QByteArray::number(1 / weightSum)); + source.append(") * "); + } + source.append("sample;\n"); + source.append("}\n"); + + return source; +} + QT_END_NAMESPACE diff --git a/src/opengl/qgraphicsshadereffect.cpp b/src/opengl/qgraphicsshadereffect.cpp new file mode 100644 index 0000000..d4f5fa0 --- /dev/null +++ b/src/opengl/qgraphicsshadereffect.cpp @@ -0,0 +1,327 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgraphicsshadereffect.h" +#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL) +#include "qglshaderprogram.h" +#include "gl2paintengineex/qglcustomshaderstage_p.h" +#define QGL_HAVE_CUSTOM_SHADERS 1 +#endif +#include <QtGui/qpainter.h> +#include <QtGui/qgraphicsitem.h> +#include <QtGui/private/qgraphicseffect_p.h> + +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 + custom GLSL shader effects in a QGraphicsScene. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + + The specific effect is defined by a fragment of GLSL source code + supplied to setPixelShaderFragment(). This source code must define a + function called \c{srcPixel()} 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 + to construct a complete QGLShaderProgram. + + The following example shader converts the incoming pixmap to + grayscale and then applies a colorize operation using the + \c effectColor value: + + \code + static char const colorizeShaderCode[] = + "varying highp vec2 textureCoords;\n" + "uniform sampler2D imageTexture;\n" + "uniform lowp vec4 effectColor;\n" + "lowp vec4 srcPixel() {\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" + " return vec4(colorize.rgb, src.a);\n" + "}"; + \endcode + + To use this shader code, it is necessary to define a subclass + of QGraphicsShaderEffect as follows: + + \code + class ColorizeEffect : public QGraphicsShaderEffect + { + Q_OBJECT + public: + ColorizeEffect(QObject *parent = 0) + : QGraphicsShaderEffect(parent), color(Qt::black) + { + setPixelShaderFragment(colorizeShaderCode); + } + + QColor effectColor() const { return color; } + void setEffectColor(const QColor& c) + { + color = c; + setUniformsDirty(); + } + + protected: + void setUniforms(QGLShaderProgram *program) + { + program->setUniformValue("effectColor", color); + } + + private: + QColor color; + }; + \endcode + + The setUniforms() function is called when the effect is about + to be used for drawing to give the subclass the opportunity to + set effect-specific uniform variables. + + QGraphicsShaderEffect is only supported when the GL2 paint engine + is in use. When any other paint engine is in use (GL1, raster, etc), + the drawItem() method will draw its item argument directly with + no effect applied. + + \sa QGrapicsEffect +*/ + +static const char qglslDefaultImageFragmentShader[] = "\ + varying highp vec2 textureCoords; \ + uniform sampler2D imageTexture; \ + lowp vec4 srcPixel() { \ + return texture2D(imageTexture, textureCoords); \ + }\n"; + +#ifdef QGL_HAVE_CUSTOM_SHADERS + +class QGLCustomShaderEffectStage : public QGLCustomShaderStage +{ +public: + QGLCustomShaderEffectStage + (QGraphicsShaderEffect *e, const QByteArray& source) + : QGLCustomShaderStage(), + effect(e) + { + setSource(source); + } + + void setUniforms(QGLShaderProgram *program); + + QGraphicsShaderEffect *effect; +}; + +void QGLCustomShaderEffectStage::setUniforms(QGLShaderProgram *program) +{ + effect->setUniforms(program); +} + +#endif + +class QGraphicsShaderEffectPrivate : public QGraphicsEffectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsShaderEffect) +public: + QGraphicsShaderEffectPrivate() + : pixelShaderFragment(qglslDefaultImageFragmentShader) +#ifdef QGL_HAVE_CUSTOM_SHADERS + , customShaderStage(0) +#endif + { + } + + QByteArray pixelShaderFragment; +#ifdef QGL_HAVE_CUSTOM_SHADERS + QGLCustomShaderEffectStage *customShaderStage; +#endif +}; + +/*! + Constructs a shader effect and attaches it to \a parent. +*/ +QGraphicsShaderEffect::QGraphicsShaderEffect() + : QGraphicsEffect(*new QGraphicsShaderEffectPrivate()) +{ +} + +/*! + Destroys this shader effect. +*/ +QGraphicsShaderEffect::~QGraphicsShaderEffect() +{ +#ifdef QGL_HAVE_CUSTOM_SHADERS + Q_D(QGraphicsShaderEffect); + delete d->customShaderStage; +#endif +} + +/*! + Returns the source code for the pixel shader fragment for + this shader effect. The default is a shader that copies + its incoming pixmap directly to the output with no effect + applied. + + \sa setPixelShaderFragment() +*/ +QByteArray QGraphicsShaderEffect::pixelShaderFragment() const +{ + Q_D(const QGraphicsShaderEffect); + return d->pixelShaderFragment; +} + +/*! + Sets the source code for the pixel shader fragment for + this shader effect to \a code. + + The \a code must define a GLSL function called \c{srcPixel()} + 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 + varying highp vec2 textureCoords; + uniform sampler2D imageTexture; + lowp vec4 srcPixel() { + return texture2D(imageTexture, textureCoords); + } + \endcode + + \sa pixelShaderFragment(), setUniforms() +*/ +void QGraphicsShaderEffect::setPixelShaderFragment(const QByteArray& code) +{ + Q_D(QGraphicsShaderEffect); + if (d->pixelShaderFragment != code) { + d->pixelShaderFragment = code; +#ifdef QGL_HAVE_CUSTOM_SHADERS + delete d->customShaderStage; + d->customShaderStage = 0; +#endif + } +} + +/*! + \reimp +*/ +void QGraphicsShaderEffect::draw(QPainter *painter) +{ + Q_D(QGraphicsShaderEffect); + +#ifdef QGL_HAVE_CUSTOM_SHADERS + // Find the item's bounds in device coordinates. + QTransform itemToPixmapTransform(painter->worldTransform()); + QRectF deviceBounds = itemToPixmapTransform.mapRect(sourceBoundingRect()); + QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1); + if (deviceRect.isEmpty()) + return; + + if (deviceRect.x() != 0 || deviceRect.y() != 0) + itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y()); + + QPixmap pixmap(deviceRect.size()); + if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform)) + return; + + // Set the custom shader on the paint engine. The setOnPainter() + // call may fail if the paint engine is not GL2. In that case, + // we fall through to drawing the pixmap normally. + if (!d->customShaderStage) { + d->customShaderStage = new QGLCustomShaderEffectStage + (this, d->pixelShaderFragment); + } + bool usingShader = d->customShaderStage->setOnPainter(painter); + + // Draw using an untransformed painter. + QTransform restoreTransform = painter->worldTransform(); + painter->setWorldTransform(QTransform()); + painter->drawPixmap(deviceRect.topLeft(), pixmap); + painter->setWorldTransform(restoreTransform); + + // Remove the custom shader to return to normal painting operations. + if (usingShader) + d->customShaderStage->removeFromPainter(painter); +#else + drawSource(painter); +#endif +} + +/*! + Sets the custom uniform variables on this shader effect to + be dirty. The setUniforms() function will be called the next + time the shader program corresponding to this effect is used. + + This function is typically called by subclasses when an + effect-specific parameter is changed by the application. + + \sa setUniforms() +*/ +void QGraphicsShaderEffect::setUniformsDirty() +{ +#ifdef QGL_HAVE_CUSTOM_SHADERS + Q_D(QGraphicsShaderEffect); + if (d->customShaderStage) + d->customShaderStage->setUniformsDirty(); +#endif +} + +/*! + Sets custom uniform variables on the current GL context when + \a program is about to be used by the paint engine. + + This function should be overridden if the shader set with + setPixelShaderFragment() has additional parameters beyond + those that the paint engine normally sets itself. + + \sa setUniformsDirty() +*/ +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 new file mode 100644 index 0000000..032a233 --- /dev/null +++ b/src/opengl/qgraphicsshadereffect.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSHADEREFFECT_H +#define QGRAPHICSSHADEREFFECT_H + +#include <QtGui/qgraphicseffect.h> + +QT_BEGIN_HEADER + +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; + +class Q_OPENGL_EXPORT QGraphicsShaderEffect : public QGraphicsEffect +{ + Q_OBJECT +public: + QGraphicsShaderEffect(); + virtual ~QGraphicsShaderEffect(); + + QByteArray pixelShaderFragment() const; + void setPixelShaderFragment(const QByteArray& code); + +protected: + void draw(QPainter *painter); + void setUniformsDirty(); + virtual void setUniforms(QGLShaderProgram *program); + +private: + Q_DECLARE_PRIVATE(QGraphicsShaderEffect) + Q_DISABLE_COPY(QGraphicsShaderEffect) + + friend class QGLCustomShaderEffectStage; +}; + +Q_DECLARE_METATYPE(QGraphicsShaderEffect *) + +#endif // QT_NO_GRAPHICSVIEW + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSHADEREFFECT_H diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index f0c7e20..c0eed4d 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -55,6 +55,85 @@ QT_BEGIN_NAMESPACE extern QGLWidget* qt_gl_share_widget(); +/*! + \class QGLFramebufferObjectPool + \since 4.6 + + \brief The QGLFramebufferObject class provides a pool of framebuffer + objects for offscreen rendering purposes. + + When requesting an FBO of a given size and format, an FBO of the same + format and a size at least as big as the requested size will be returned. + + \internal +*/ + +static inline int areaDiff(const QSize &size, const QGLFramebufferObject *fbo) +{ + return qAbs(size.width() * size.height() - fbo->width() * fbo->height()); +} + +QGLFramebufferObject *QGLFramebufferObjectPool::acquire(const QSize &requestSize, const QGLFramebufferObjectFormat &requestFormat) +{ + QGLFramebufferObject *chosen = 0; + QGLFramebufferObject *candidate = 0; + for (int i = 0; !chosen && i < m_fbos.size(); ++i) { + QGLFramebufferObject *fbo = m_fbos.at(i); + + QGLFramebufferObjectFormat format = fbo->format(); + if (format.samples() == requestFormat.samples() + && format.attachment() == requestFormat.attachment() + && format.textureTarget() == requestFormat.textureTarget() + && format.internalFormat() == requestFormat.internalFormat()) + { + // choose the fbo with a matching format and the closest size + if (!candidate || areaDiff(requestSize, candidate) > areaDiff(requestSize, fbo)) + candidate = fbo; + } + + if (candidate) { + m_fbos.removeOne(candidate); + + const QSize fboSize = candidate->size(); + QSize sz = fboSize; + + if (sz.width() < requestSize.width()) + sz.setWidth(qMax(requestSize.width(), qRound(sz.width() * 1.5))); + if (sz.height() < requestSize.height()) + sz.setHeight(qMax(requestSize.height(), qRound(sz.height() * 1.5))); + + // wasting too much space? + if (sz.width() * sz.height() > requestSize.width() * requestSize.height() * 2.5) + sz = requestSize; + + if (sz != fboSize) { + delete candidate; + qDebug() << "Resizing fbo in pool:" << sz; + candidate = new QGLFramebufferObject(sz, requestFormat); + } + + chosen = candidate; + } + } + + if (!chosen) { + qDebug() << "Creating new fbo in pool:" << requestSize; + chosen = new QGLFramebufferObject(requestSize, requestFormat); + } + + if (!chosen->isValid()) { + delete chosen; + chosen = 0; + } + + return chosen; +} + +void QGLFramebufferObjectPool::release(QGLFramebufferObject *fbo) +{ + m_fbos << fbo; +} + class QGLShareContextScope { public: @@ -97,7 +176,6 @@ static int qt_gl_pixmap_serial = 0; QGLPixmapData::QGLPixmapData(PixelType type) : QPixmapData(type, OpenGLClass) , m_renderFbo(0) - , m_textureId(0) , m_engine(0) , m_ctx(0) , m_dirty(false) @@ -113,9 +191,9 @@ QGLPixmapData::~QGLPixmapData() if (!shareWidget) return; - if (m_textureId) { + if (m_texture.id) { QGLShareContextScope ctx(shareWidget->context()); - glDeleteTextures(1, &m_textureId); + glDeleteTextures(1, &m_texture.id); } } @@ -148,10 +226,10 @@ void QGLPixmapData::resize(int width, int height) is_null = (w <= 0 || h <= 0); d = pixelType() == QPixmapData::PixmapType ? 32 : 1; - if (m_textureId) { + if (m_texture.id) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glDeleteTextures(1, &m_textureId); - m_textureId = 0; + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; } m_source = QImage(); @@ -172,9 +250,9 @@ void QGLPixmapData::ensureCreated() const const GLenum format = qt_gl_preferredTextureFormat(); const GLenum target = GL_TEXTURE_2D; - if (!m_textureId) { - glGenTextures(1, &m_textureId); - glBindTexture(target, m_textureId); + if (!m_texture.id) { + glGenTextures(1, &m_texture.id); + glBindTexture(target, m_texture.id); GLenum format = m_hasAlpha ? GL_RGBA : GL_RGB; glTexImage2D(target, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); @@ -185,13 +263,15 @@ void QGLPixmapData::ensureCreated() const if (!m_source.isNull()) { const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format); - glBindTexture(target, m_textureId); + glBindTexture(target, m_texture.id); glTexSubImage2D(target, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, tx.bits()); if (useFramebufferObjects()) m_source = QImage(); } + + m_texture.clean = false; } QGLFramebufferObject *QGLPixmapData::fbo() const @@ -223,10 +303,10 @@ void QGLPixmapData::fromImage(const QImage &image, is_null = (w <= 0 || h <= 0); d = pixelType() == QPixmapData::PixmapType ? 32 : 1; - if (m_textureId) { + if (m_texture.id) { QGLShareContextScope ctx(qt_gl_share_widget()->context()); - glDeleteTextures(1, &m_textureId); - m_textureId = 0; + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; } } @@ -256,9 +336,9 @@ void QGLPixmapData::fill(const QColor &color) bool hasAlpha = color.alpha() != 255; if (hasAlpha && !m_hasAlpha) { - if (m_textureId) { - glDeleteTextures(1, &m_textureId); - m_textureId = 0; + if (m_texture.id) { + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; m_dirty = true; } m_hasAlpha = color.alpha() != 255; @@ -303,6 +383,8 @@ QImage QGLPixmapData::fillImage(const QColor &color) const return img; } +extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha); + QImage QGLPixmapData::toImage() const { if (!isValid()) @@ -319,8 +401,7 @@ QImage QGLPixmapData::toImage() const } QGLShareContextScope ctx(qt_gl_share_widget()->context()); - extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha); - glBindTexture(GL_TEXTURE_2D, m_textureId); + glBindTexture(GL_TEXTURE_2D, m_texture.id); return qt_gl_read_texture(QSize(w, h), true, true); } @@ -330,8 +411,11 @@ struct TextureBuffer QGL2PaintEngineEx *engine; }; -static QVector<TextureBuffer> textureBufferStack; -static int currentTextureBuffer = 0; +Q_GLOBAL_STATIC(QGLFramebufferObjectPool, _qgl_fbo_pool) +QGLFramebufferObjectPool* qgl_fbo_pool() +{ + return _qgl_fbo_pool(); +} void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const { @@ -350,7 +434,7 @@ void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->fbo); glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_2D, m_textureId, 0); + GL_TEXTURE_2D, m_texture.id, 0); const int x0 = 0; const int x1 = w; @@ -378,7 +462,8 @@ void QGLPixmapData::swapBuffers() copyBackFromRenderFbo(false); m_renderFbo->release(); - --currentTextureBuffer; + qgl_fbo_pool()->release(m_renderFbo); + delete m_engine; m_renderFbo = 0; m_engine = 0; @@ -396,19 +481,6 @@ void QGLPixmapData::doneCurrent() m_renderFbo->release(); } -static TextureBuffer createTextureBuffer(const QSize &size, QGL2PaintEngineEx *engine = 0) -{ - TextureBuffer buffer; - QGLFramebufferObjectFormat fmt; - fmt.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - fmt.setSamples(4); - - buffer.fbo = new QGLFramebufferObject(size, fmt); - buffer.engine = engine ? engine : new QGL2PaintEngineEx; - - return buffer; -} - bool QGLPixmapData::useFramebufferObjects() { return QGLFramebufferObject::hasOpenGLFramebufferObjects() @@ -431,33 +503,15 @@ QPaintEngine* QGLPixmapData::paintEngine() const qt_gl_share_widget()->makeCurrent(); QGLShareContextScope ctx(qt_gl_share_widget()->context()); - if (textureBufferStack.size() <= currentTextureBuffer) { - textureBufferStack << createTextureBuffer(size()); - } else { - QSize sz = textureBufferStack.at(currentTextureBuffer).fbo->size(); - if (sz.width() < w || sz.height() < h) { - if (sz.width() < w) - sz.setWidth(qMax(w, qRound(sz.width() * 1.5))); - if (sz.height() < h) - sz.setHeight(qMax(h, qRound(sz.height() * 1.5))); - - // wasting too much space? - if (sz.width() * sz.height() > w * h * 2.5) - sz = QSize(w, h); - - delete textureBufferStack.at(currentTextureBuffer).fbo; - textureBufferStack[currentTextureBuffer] = - createTextureBuffer(sz, textureBufferStack.at(currentTextureBuffer).engine); - qDebug() << "Creating new pixmap texture buffer:" << sz; - } - } - - if (textureBufferStack.at(currentTextureBuffer).fbo->isValid()) { - m_renderFbo = textureBufferStack.at(currentTextureBuffer).fbo; - m_engine = textureBufferStack.at(currentTextureBuffer).engine; + QGLFramebufferObjectFormat format; + format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + format.setSamples(4); + format.setInternalFormat(m_hasAlpha ? GL_RGBA : GL_RGB); - ++currentTextureBuffer; + m_renderFbo = qgl_fbo_pool()->acquire(size(), format); + if (m_renderFbo) { + m_engine = new QGL2PaintEngineEx; return m_engine; } @@ -488,7 +542,7 @@ GLuint QGLPixmapData::bind(bool copyBack) const ensureCreated(); } - GLuint id = m_textureId; + GLuint id = m_texture.id; glBindTexture(GL_TEXTURE_2D, id); return id; } @@ -496,7 +550,12 @@ GLuint QGLPixmapData::bind(bool copyBack) const GLuint QGLPixmapData::textureId() const { ensureCreated(); - return m_textureId; + return m_texture.id; +} + +QGLTexture* QGLPixmapData::texture() const +{ + return &m_texture; } extern int qt_defaultDpiX(); diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index a6aa22d..14fb072 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -53,6 +53,7 @@ // We mean it. // +#include "qgl_p.h" #include "qgl.h" #include "private/qpixmapdata_p.h" @@ -61,6 +62,19 @@ QT_BEGIN_NAMESPACE class QPaintEngine; class QGLFramebufferObject; +class QGLFramebufferObjectFormat; + +class QGLFramebufferObjectPool +{ +public: + QGLFramebufferObject *acquire(const QSize &size, const QGLFramebufferObjectFormat &format); + void release(QGLFramebufferObject *fbo); + +private: + QList<QGLFramebufferObject *> m_fbos; +}; + +QGLFramebufferObjectPool* qgl_fbo_pool(); class QGLPixmapData : public QPixmapData { @@ -80,10 +94,11 @@ public: void fill(const QColor &color); bool hasAlphaChannel() const; QImage toImage() const; - QPaintEngine* paintEngine() const; + QPaintEngine *paintEngine() const; GLuint bind(bool copyBack = true) const; GLuint textureId() const; + QGLTexture *texture() const; bool isValidContext(const QGLContext *ctx) const; @@ -116,10 +131,10 @@ private: QImage fillImage(const QColor &color) const; mutable QGLFramebufferObject *m_renderFbo; - mutable GLuint m_textureId; mutable QPaintEngine *m_engine; mutable QGLContext *m_ctx; mutable QImage m_source; + mutable QGLTexture m_texture; // the texture is not in sync with the source image mutable bool m_dirty; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp index ed59db8..b5376b1 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp @@ -78,7 +78,7 @@ private: DFBEvent event; int bytesRead; -private slots: +private Q_SLOTS: void readKeyboardData(); }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp index 694ba51..142993d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp @@ -71,7 +71,7 @@ private: DFBEvent event; uint bytesRead; -private slots: +private Q_SLOTS: void readMouseData(); }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 67cad6f..0928643 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -744,7 +744,12 @@ QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType typ return new QDirectFBPixmapData(type); } -#ifndef QT_NO_DEBUG +#ifdef QT_NO_DEBUG +struct FlagDescription; +static const FlagDescription *accelerationDescriptions = 0; +static const FlagDescription *blitDescriptions = 0; +static const FlagDescription *drawDescriptions = 0; +#else struct FlagDescription { const char *name; uint flag; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index fced673..69b09e9 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -44,6 +44,7 @@ #include <QtGui/qscreen_qws.h> #include <directfb.h> +#include <directfb_version.h> QT_BEGIN_HEADER diff --git a/src/qt3support/dialogs/q3tabdialog.cpp b/src/qt3support/dialogs/q3tabdialog.cpp index 50dbd48..a65affc 100644 --- a/src/qt3support/dialogs/q3tabdialog.cpp +++ b/src/qt3support/dialogs/q3tabdialog.cpp @@ -1038,7 +1038,7 @@ QString Q3TabDialog::tabLabel(QWidget * w) } -/*! \reimp +/*! \internal */ void Q3TabDialog::styleChange(QStyle& s) { diff --git a/src/qt3support/itemviews/q3table.cpp b/src/qt3support/itemviews/q3table.cpp index 11c70b4..6c3e90c 100644 --- a/src/qt3support/itemviews/q3table.cpp +++ b/src/qt3support/itemviews/q3table.cpp @@ -6411,7 +6411,7 @@ void Q3Table::startDrag() #endif -/*! \reimp */ +/*! \internal */ void Q3Table::windowActivationChange(bool oldActive) { if (oldActive && autoScrollTimer) diff --git a/src/qt3support/widgets/q3scrollview.cpp b/src/qt3support/widgets/q3scrollview.cpp index cea385a..95e2117 100644 --- a/src/qt3support/widgets/q3scrollview.cpp +++ b/src/qt3support/widgets/q3scrollview.cpp @@ -669,7 +669,7 @@ bool Q3ScrollView::isVerticalSliderPressed() } /*! - \reimp + \internal */ void Q3ScrollView::styleChange(QStyle& old) { @@ -679,7 +679,7 @@ void Q3ScrollView::styleChange(QStyle& old) } /*! - \reimp + \internal */ void Q3ScrollView::fontChange(const QFont &old) { diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index 5f9d1dd..5857e1c 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -644,26 +644,19 @@ static void parseBrush(QSvgNode *node, QString opacity = attributes.value(QLatin1String("fill-opacity")).toString(); QString myId = someId(attributes); - QSvgFillStyle *inherited = - static_cast<QSvgFillStyle*>(node->parent()->styleProperty( - QSvgStyleProperty::FILL)); - QSvgFillStyle *prop = new QSvgFillStyle(QColor(Qt::black)); + QSvgFillStyle *prop = new QSvgFillStyle(0); //fill-rule attribute handling - Qt::FillRule f = Qt::WindingFill; if (!fillRule.isEmpty() && fillRule != QLatin1String("inherit")) { if (fillRule == QLatin1String("evenodd")) - f = Qt::OddEvenFill; - } else if (inherited) { - f = inherited->fillRule(); + prop->setFillRule(Qt::OddEvenFill); + else if (fillRule == QLatin1String("nonzero")) + prop->setFillRule(Qt::WindingFill); } //fill-opacity atttribute handling - qreal fillOpacity = 1.0; if (!opacity.isEmpty() && opacity != QLatin1String("inherit")) { - fillOpacity = qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity))); - } else if (inherited) { - fillOpacity = inherited->fillOpacity(); + prop->setFillOpacity(qMin(qreal(1.0), qMax(qreal(0.0), toDouble(opacity)))); } //fill attribute handling @@ -685,15 +678,7 @@ static void parseBrush(QSvgNode *node, } else { prop->setBrush(QBrush(Qt::NoBrush)); } - } else if (inherited) { - if (inherited->style()) { - prop->setFillStyle(inherited->style()); - } else { - prop->setBrush(inherited->qbrush()); - } } - prop->setFillOpacity(fillOpacity); - prop->setFillRule(f); node->appendStyleProperty(prop,myId); } diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 4c8247b..c3c0a68 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -81,12 +81,25 @@ void QSvgQualityStyle::revert(QPainter *, QSvgExtraStates &) } QSvgFillStyle::QSvgFillStyle(const QBrush &brush) - : m_fill(brush), m_style(0), m_fillRuleSet(false), m_fillOpacitySet(false), m_fillRule(Qt::WindingFill), m_fillOpacity(1.0), m_gradientResolved (true) + : m_fill(brush) + , m_style(0) + , m_fillRuleSet(false) + , m_fillRule(Qt::WindingFill) + , m_fillOpacitySet(false) + , m_fillOpacity(1.0) + , m_gradientResolved(true) + , m_fillSet(true) { } QSvgFillStyle::QSvgFillStyle(QSvgStyleProperty *style) - : m_style(style), m_fillRuleSet(false), m_fillOpacitySet(false), m_fillRule(Qt::WindingFill), m_fillOpacity(1.0), m_gradientResolved (true) + : m_style(style) + , m_fillRuleSet(false) + , m_fillRule(Qt::WindingFill) + , m_fillOpacitySet(false) + , m_fillOpacity(1.0) + , m_gradientResolved(true) + , m_fillSet(style != 0) { } @@ -105,11 +118,14 @@ void QSvgFillStyle::setFillOpacity(qreal opacity) void QSvgFillStyle::setFillStyle(QSvgStyleProperty* style) { m_style = style; + m_fillSet = true; } void QSvgFillStyle::setBrush(QBrush brush) { m_fill = brush; + m_style = 0; + m_fillSet = true; } static void recursivelySetFill(QSvgNode *node, Qt::FillRule f) @@ -136,20 +152,26 @@ void QSvgFillStyle::apply(QPainter *p, const QRectF &rect, QSvgNode *node, QSvgE recursivelySetFill(node, m_fillRule); m_fillRuleSet = false;//set it only on the first run } - p->setBrush(m_fill); + if (m_fillSet) { + if (m_style) + m_style->apply(p, rect, node, states); + else + p->setBrush(m_fill); + } if (m_fillOpacitySet) states.fillOpacity = m_fillOpacity; - if (m_style) - m_style->apply(p, rect, node, states); } void QSvgFillStyle::revert(QPainter *p, QSvgExtraStates &states) { - if (m_style) - m_style->revert(p, states); - p->setBrush(m_oldFill); if (m_fillOpacitySet) states.fillOpacity = m_oldOpacity; + if (m_fillSet) { + if (m_style) + m_style->revert(p, states); + else + p->setBrush(m_oldFill); + } } QSvgViewportFillStyle::QSvgViewportFillStyle(const QBrush &brush) diff --git a/src/svg/qsvgstyle_p.h b/src/svg/qsvgstyle_p.h index ac5e109..70ecf5b 100644 --- a/src/svg/qsvgstyle_p.h +++ b/src/svg/qsvgstyle_p.h @@ -281,6 +281,7 @@ private: qreal m_oldOpacity; QString m_gradientId; bool m_gradientResolved; + bool m_fillSet; }; class QSvgViewportFillStyle : public QSvgStyleProperty diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 70c8c8d..1d0bbcf 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -937,7 +937,7 @@ static void qParseArgs(int argc, char *argv[]) " -iterations n : Sets the number of accumulation iterations.\n" " -median n : Sets the number of median iterations.\n" " -vb : Print out verbose benchmarking information.\n" -#if !defined(QT_NO_PROCESS) || !defined(QT_NO_SETTINGS) +#if !defined(QT_NO_PROCESS) && !defined(QT_NO_SETTINGS) " -chart : Create chart based on the benchmark result.\n" #endif "\n" @@ -1053,7 +1053,7 @@ static void qParseArgs(int argc, char *argv[]) } else if (strcmp(argv[i], "-vb") == 0) { QBenchmarkGlobalData::current->verboseOutput = true; -#if !defined(QT_NO_PROCESS) || !defined(QT_NO_SETTINGS) +#if !defined(QT_NO_PROCESS) && !defined(QT_NO_SETTINGS) } else if (strcmp(argv[i], "-chart") == 0) { QBenchmarkGlobalData::current->createChart = true; QTestLog::setLogMode(QTestLog::XML); @@ -1480,7 +1480,7 @@ FatalSignalHandler::~FatalSignalHandler() struct sigaction oldact; - for (int i = 0; i < 32; ++i) { + for (int i = 1; i < 32; ++i) { if (!sigismember(&handledSignals, i)) continue; sigaction(i, &act, &oldact); @@ -1627,7 +1627,7 @@ int QTest::qExec(QObject *testObject, int argc, char **argv) #endif -#if !defined(QT_NO_PROCESS) || !defined(QT_NO_SETTINGS) +#if !defined(QT_NO_PROCESS) && !defined(QT_NO_SETTINGS) if (QBenchmarkGlobalData::current->createChart) { QString chartLocation = QLibraryInfo::location(QLibraryInfo::BinariesPath); #ifdef Q_OS_WIN diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index da5733a..797595f 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -337,11 +337,10 @@ bool Moc::testFunctionAttribute(Token tok, FunctionDef *def) bool Moc::parseFunction(FunctionDef *def, bool inMacro) { def->isVirtual = false; - while (test(INLINE) || test(STATIC) || test(VIRTUAL) - || testFunctionAttribute(def)) { - if (lookup() == VIRTUAL) - def->isVirtual = true; - } + //skip modifiers and attributes + while (test(INLINE) || test(STATIC) || + (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual + || testFunctionAttribute(def)) {} bool templateFunction = (lookup() == TEMPLATE); def->type = parseType(); if (def->type.name.isEmpty()) { @@ -429,11 +428,10 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) { def->isVirtual = false; - while (test(EXPLICIT) || test(INLINE) || test(STATIC) || test(VIRTUAL) - || testFunctionAttribute(def)) { - if (lookup() == VIRTUAL) - def->isVirtual = true; - } + //skip modifiers and attributes + while (test(INLINE) || test(STATIC) || + (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual + || testFunctionAttribute(def)) {} bool tilde = test(TILDE); def->type = parseType(); if (def->type.name.isEmpty()) @@ -862,7 +860,7 @@ void Moc::parseSignals(ClassDef *def) funcDef.access = FunctionDef::Protected; parseFunction(&funcDef); if (funcDef.isVirtual) - error("Signals cannot be declared virtual"); + warning("Signals cannot be declared virtual"); if (funcDef.inlineCode) error("Not a signal declaration"); def->signalList += funcDef; diff --git a/src/xmlpatterns/api/qabstractxmlforwarditerator_p.h b/src/xmlpatterns/api/qabstractxmlforwarditerator_p.h index d3188d3..b4eefeb 100644 --- a/src/xmlpatterns/api/qabstractxmlforwarditerator_p.h +++ b/src/xmlpatterns/api/qabstractxmlforwarditerator_p.h @@ -55,7 +55,7 @@ #include <QtCore/QList> #include <QtCore/QVector> #include <QtCore/QSharedData> - +#include <QtCore/QString> QT_BEGIN_HEADER @@ -74,6 +74,19 @@ inline bool qIsForwardIteratorEnd(const T &unit) return !unit; } +/** + * @short Helper class for StringSplitter + * + * Needed by the QAbstractXmlForwardIterator sub-class. + * + * @relates StringSplitter + */ +template<> +inline bool qIsForwardIteratorEnd(const QString &unit) +{ + return unit.isNull(); +} + template<typename T> class QAbstractXmlForwardIterator; class QAbstractXmlForwardIteratorPrivate; diff --git a/src/xmlpatterns/api/qxmlschema.cpp b/src/xmlpatterns/api/qxmlschema.cpp index af4c715..e64b388 100644 --- a/src/xmlpatterns/api/qxmlschema.cpp +++ b/src/xmlpatterns/api/qxmlschema.cpp @@ -45,6 +45,8 @@ #include <QtCore/QIODevice> #include <QtCore/QUrl> +QT_BEGIN_NAMESPACE + /*! \class QXmlSchema @@ -293,3 +295,5 @@ QNetworkAccessManager *QXmlSchema::networkAccessManager() const { return d->networkAccessManager(); } + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qxmlschema_p.cpp b/src/xmlpatterns/api/qxmlschema_p.cpp index 0bcb565..2dad359 100644 --- a/src/xmlpatterns/api/qxmlschema_p.cpp +++ b/src/xmlpatterns/api/qxmlschema_p.cpp @@ -47,6 +47,8 @@ #include <QtCore/QIODevice> #include <QtCore/QUrl> +QT_BEGIN_NAMESPACE + QXmlSchemaPrivate::QXmlSchemaPrivate(const QXmlNamePool &namePool) : m_namePool(namePool) , m_userMessageHandler(0) @@ -197,3 +199,5 @@ QNetworkAccessManager *QXmlSchemaPrivate::networkAccessManager() const return m_networkAccessManager.data()->value; } + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/api/qxmlschemavalidator.cpp b/src/xmlpatterns/api/qxmlschemavalidator.cpp index 9234d83..a864d40 100644 --- a/src/xmlpatterns/api/qxmlschemavalidator.cpp +++ b/src/xmlpatterns/api/qxmlschemavalidator.cpp @@ -51,6 +51,8 @@ #include <QtCore/QIODevice> #include <QtCore/QUrl> +QT_BEGIN_NAMESPACE + /*! \class QXmlSchemaValidator @@ -338,3 +340,5 @@ QNetworkAccessManager *QXmlSchemaValidator::networkAccessManager() const return d->m_networkAccessManager.data()->value; } + +QT_END_NAMESPACE diff --git a/src/xmlpatterns/functions/qsequencegeneratingfns.cpp b/src/xmlpatterns/functions/qsequencegeneratingfns.cpp index 81724f8..e3f30c5 100644 --- a/src/xmlpatterns/functions/qsequencegeneratingfns.cpp +++ b/src/xmlpatterns/functions/qsequencegeneratingfns.cpp @@ -69,19 +69,6 @@ Item IdFN::mapToItem(const QString &id, } /** - * @short Helper class for StringSplitter - * - * Needed by the QAbstractXmlForwardIterator sub-class. - * - * @relates StringSplitter - */ -template<> -bool qIsForwardIteratorEnd(const QString &unit) -{ - return unit.isNull(); -} - -/** * @short Helper class for IdFN. * * StringSplitter takes an Iterator which delivers strings of this kind: diff --git a/src/xmlpatterns/parser/qmaintainingreader.cpp b/src/xmlpatterns/parser/qmaintainingreader.cpp index 0513555..8569f05 100644 --- a/src/xmlpatterns/parser/qmaintainingreader.cpp +++ b/src/xmlpatterns/parser/qmaintainingreader.cpp @@ -172,7 +172,7 @@ void MaintainingReader<TokenLookupClass, LookupKey>::validateElement(const Looku QStringList allowed; for(int i = 0; i < totalCount; ++i) - allowed.append(formatKeyword(toString(all.at(i)))); + allowed.append(QPatternist::formatKeyword(TokenLookupClass::toString(all.at(i)))); /* Note, we can't run toString() on attrName, because we're in this branch, * the token lookup doesn't have the string(!).*/ @@ -229,7 +229,7 @@ void MaintainingReader<TokenLookupClass, LookupKey>::validateElement(const Looku if(!requiredButMissing.isEmpty()) { error(QtXmlPatterns::tr("The attribute %1 must appear on element %2.") - .arg(formatKeyword(toString(*requiredButMissing.constBegin())), + .arg(QPatternist::formatKeyword(TokenLookupClass::toString(*requiredButMissing.constBegin())), formatKeyword(name())), ReportContext::XTSE0010); } diff --git a/src/xmlpatterns/parser/qmaintainingreader_p.h b/src/xmlpatterns/parser/qmaintainingreader_p.h index c2c991e..eb20bdb 100644 --- a/src/xmlpatterns/parser/qmaintainingreader_p.h +++ b/src/xmlpatterns/parser/qmaintainingreader_p.h @@ -59,6 +59,7 @@ #include <QXmlStreamReader> #include "qxpathhelper_p.h" +#include "qxslttokenlookup_p.h" class QUrl; diff --git a/src/xmlpatterns/type/qprimitives_p.h b/src/xmlpatterns/type/qprimitives_p.h index 78bd4ae..b77698a 100644 --- a/src/xmlpatterns/type/qprimitives_p.h +++ b/src/xmlpatterns/type/qprimitives_p.h @@ -74,17 +74,6 @@ QT_BEGIN_NAMESPACE class QString; /** - * @internal - * - * A method to allow a QHash or QSet with QUrl - * as key type. - */ -inline uint qHash(const QUrl &uri) -{ - return qHash(uri.toString()); -} - -/** * @short The namespace for the internal API of QtXmlPatterns * @internal */ @@ -92,6 +81,17 @@ namespace QPatternist { /** + * @internal + * + * A method to allow a QHash or QSet with QUrl + * as key type. + */ + inline uint qHash(const QUrl &uri) + { + return qHash(uri.toString()); + } + + /** * @defgroup Patternist_cppWXSTypes C++ Primitives for W3C XML Schema Number Types * * The implementations of W3C XML Schema's(WXS) number types, more specifically @@ -208,6 +208,8 @@ namespace QPatternist QString Q_AUTOTEST_EXPORT escape(const QString &input); } +using QPatternist::qHash; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/xmlpatterns/utils/qpatternistlocale_p.h b/src/xmlpatterns/utils/qpatternistlocale_p.h index dc287bd..d8288c7 100644 --- a/src/xmlpatterns/utils/qpatternistlocale_p.h +++ b/src/xmlpatterns/utils/qpatternistlocale_p.h @@ -93,7 +93,8 @@ namespace QPatternist Q_DISABLE_COPY(QtXmlPatterns) }; - static inline QString formatKeyword(const QString &keyword) + // don't make this function static, otherwise xlC 7 cannot find it + inline QString formatKeyword(const QString &keyword) { return QLatin1String("<span class='XQuery-keyword'>") + escape(keyword) + diff --git a/tests/auto/bic/tst_bic.cpp b/tests/auto/bic/tst_bic.cpp index cec5e76..36c35ff 100644 --- a/tests/auto/bic/tst_bic.cpp +++ b/tests/auto/bic/tst_bic.cpp @@ -43,6 +43,10 @@ #include <QtCore/QtCore> #include <QtTest/QtTest> +#ifdef QT_NO_PROCESS +QTEST_NOOP_MAIN +#else + #include "qbic.h" #include <stdlib.h> @@ -367,4 +371,4 @@ void tst_Bic::sizesAndVTables() QTEST_APPLESS_MAIN(tst_Bic) #include "tst_bic.moc" - +#endif diff --git a/tests/auto/compilerwarnings/tst_compilerwarnings.cpp b/tests/auto/compilerwarnings/tst_compilerwarnings.cpp index 57795c9..d5fef1b 100644 --- a/tests/auto/compilerwarnings/tst_compilerwarnings.cpp +++ b/tests/auto/compilerwarnings/tst_compilerwarnings.cpp @@ -47,6 +47,10 @@ #include <QtTest/QtTest> +#ifdef QT_NO_PROCESS +QTEST_NOOP_MAIN +#else + #include <stdlib.h> QT_USE_NAMESPACE @@ -248,4 +252,4 @@ void tst_CompilerWarnings::warnings() QTEST_APPLESS_MAIN(tst_CompilerWarnings) #include "tst_compilerwarnings.moc" - +#endif // QT_NO_PROCESS diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index 3a40ae0..d66791f 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -488,6 +488,7 @@ private slots: void warnOnPropertyWithoutREAD(); void constructors(); void typenameWithUnsigned(); + void warnOnVirtualSignal(); signals: void sigWithUnsignedArg(unsigned foo); @@ -510,7 +511,7 @@ private: void tst_Moc::initTestCase() { -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS) QProcess proc; proc.start("qmake", QStringList() << "-query" << "QT_INSTALL_HEADERS"); QVERIFY(proc.waitForFinished()); @@ -555,7 +556,7 @@ void tst_Moc::oldStyleCasts() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; proc.start("moc", QStringList(srcify("/oldstyle-casts.h"))); QVERIFY(proc.waitForFinished()); @@ -585,7 +586,7 @@ void tst_Moc::warnOnExtraSignalSlotQualifiaction() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; proc.start("moc", QStringList(srcify("extraqualification.h"))); QVERIFY(proc.waitForFinished()); @@ -627,7 +628,7 @@ void tst_Moc::inputFileNameWithDotsButNoExtension() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; proc.setWorkingDirectory(QString(SRCDIR) + "/task71021"); proc.start("moc", QStringList("../Header")); @@ -835,7 +836,7 @@ void tst_Moc::warnOnMultipleInheritance() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; QStringList args; args << "-I" << qtIncludePath + "/QtGui" @@ -858,7 +859,7 @@ void tst_Moc::forgottenQInterface() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; QStringList args; args << "-I" << qtIncludePath + "/QtCore" @@ -940,7 +941,7 @@ void tst_Moc::frameworkSearchPath() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_UNIX) +#if defined(Q_OS_UNIX) && !defined(QT_NO_PROCESS) QStringList args; args << "-F" << srcify(".") << srcify("interface-from-framework.h") @@ -978,7 +979,7 @@ void tst_Moc::templateGtGt() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; proc.start("moc", QStringList(srcify("template-gtgt.h"))); QVERIFY(proc.waitForFinished()); @@ -994,7 +995,7 @@ void tst_Moc::templateGtGt() void tst_Moc::defineMacroViaCmdline() { -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; QStringList args; @@ -1082,7 +1083,7 @@ void tst_Moc::warnOnPropertyWithoutREAD() #ifdef MOC_CROSS_COMPILED QSKIP("Not tested when cross-compiled", SkipAll); #endif -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) QProcess proc; proc.start("moc", QStringList(srcify("warn-on-property-without-read.h"))); QVERIFY(proc.waitForFinished()); @@ -1180,6 +1181,27 @@ void tst_Moc::typenameWithUnsigned() QVERIFY(mobj->indexOfSlot("l(unsignedQImage)") != -1); } + +void tst_Moc::warnOnVirtualSignal() +{ +#ifdef MOC_CROSS_COMPILED + QSKIP("Not tested when cross-compiled", SkipAll); +#endif +#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(QT_NO_PROCESS) + QProcess proc; + proc.start("moc", QStringList(srcify("pure-virtual-signals.h"))); + QVERIFY(proc.waitForFinished()); + QCOMPARE(proc.exitCode(), 0); + QByteArray mocOut = proc.readAllStandardOutput(); + QVERIFY(!mocOut.isEmpty()); + QString mocWarning = QString::fromLocal8Bit(proc.readAllStandardError()); + QCOMPARE(mocWarning, QString(SRCDIR) + QString("/pure-virtual-signals.h:48: Warning: Signals cannot be declared virtual\n") + + QString(SRCDIR) + QString("/pure-virtual-signals.h:50: Warning: Signals cannot be declared virtual\n")); +#else + QSKIP("Only tested on linux/gcc", SkipAll); +#endif +} + QTEST_MAIN(tst_Moc) #include "tst_moc.moc" diff --git a/tests/auto/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp index 8532723..7cb6bfa 100644 --- a/tests/auto/qapplication/tst_qapplication.cpp +++ b/tests/auto/qapplication/tst_qapplication.cpp @@ -1382,6 +1382,7 @@ void tst_QApplication::testDeleteLaterProcessEvents() */ void tst_QApplication::desktopSettingsAware() { +#ifndef QT_NO_PROCESS QProcess testProcess; #ifdef Q_OS_WINCE int argc = 0; @@ -1399,6 +1400,7 @@ void tst_QApplication::desktopSettingsAware() QVERIFY(testProcess.waitForFinished(10000)); QCOMPARE(int(testProcess.state()), int(QProcess::NotRunning)); QVERIFY(int(testProcess.error()) != int(QProcess::Crashed)); +#endif } void tst_QApplication::setActiveWindow() diff --git a/tests/auto/qbytearray/tst_qbytearray.cpp b/tests/auto/qbytearray/tst_qbytearray.cpp index 78fbf32..b7e4717 100644 --- a/tests/auto/qbytearray/tst_qbytearray.cpp +++ b/tests/auto/qbytearray/tst_qbytearray.cpp @@ -235,6 +235,8 @@ void tst_QByteArray::qUncompress() QSKIP("Corrupt data causes this tests to lock up on HP-UX / PA-RISC with gcc", SkipAll); #elif defined Q_OS_SOLARIS QSKIP("Corrupt data causes this tests to lock up on Solaris", SkipAll); +#elif defined Q_OS_QNX + QSKIP("Currupt data cuases this test to lock up on QNX", SkipAll); #endif QTEST(::qUncompress(in), "out"); diff --git a/tests/auto/qclipboard/tst_qclipboard.cpp b/tests/auto/qclipboard/tst_qclipboard.cpp index f400754..bcdf043 100644 --- a/tests/auto/qclipboard/tst_qclipboard.cpp +++ b/tests/auto/qclipboard/tst_qclipboard.cpp @@ -192,6 +192,7 @@ void tst_QClipboard::testSignals() */ void tst_QClipboard::copy_exit_paste() { +#ifndef QT_NO_PROCESS #if defined Q_WS_X11 || defined Q_WS_QWS QSKIP("This test does not make sense on X11 and embedded, copied data disappears from the clipboard when the application exits ", SkipAll); // ### It's still possible to test copy/paste - just keep the apps running @@ -205,6 +206,7 @@ void tst_QClipboard::copy_exit_paste() QTest::qWait(100); #endif QCOMPARE(QProcess::execute("paster/paster", stringArgument), 0); +#endif } void tst_QClipboard::setMimeData() diff --git a/tests/auto/qcopchannel/tst_qcopchannel.cpp b/tests/auto/qcopchannel/tst_qcopchannel.cpp index d07898a..ce97eae 100644 --- a/tests/auto/qcopchannel/tst_qcopchannel.cpp +++ b/tests/auto/qcopchannel/tst_qcopchannel.cpp @@ -42,7 +42,7 @@ #include <QtTest/QtTest> -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) && !defined(QT_NO_PROCESS) //TESTED_CLASS= //TESTED_FILES= diff --git a/tests/auto/qdir/tst_qdir.cpp b/tests/auto/qdir/tst_qdir.cpp index 1fd5e88..e5b23ab 100644 --- a/tests/auto/qdir/tst_qdir.cpp +++ b/tests/auto/qdir/tst_qdir.cpp @@ -571,10 +571,21 @@ void tst_QDir::entryList() return; } - for (int i=0; i<max; ++i) - QCOMPARE(actual[i], expected[i]); + bool doContentCheck = true; +#ifdef Q_OS_UNIX + if (qstrcmp(QTest::currentDataTag(), "QDir::AllEntries | QDir::Writable") == 0) { + // for root, everything is writeable + if (::getuid() == 0) + doContentCheck = false; + } +#endif - QCOMPARE(actual.count(), expected.count()); + if (doContentCheck) { + for (int i=0; i<max; ++i) + QCOMPARE(actual[i], expected[i]); + + QCOMPARE(actual.count(), expected.count()); + } QFile::remove(SRCDIR "entrylist/writable"); QFile::remove(SRCDIR "entrylist/linktofile"); diff --git a/tests/auto/qdirectpainter/tst_qdirectpainter.cpp b/tests/auto/qdirectpainter/tst_qdirectpainter.cpp index e300244..d5c0ef8 100644 --- a/tests/auto/qdirectpainter/tst_qdirectpainter.cpp +++ b/tests/auto/qdirectpainter/tst_qdirectpainter.cpp @@ -175,6 +175,9 @@ void tst_QDirectPainter::setGeometry() void tst_QDirectPainter::regionSynchronization() { +#ifdef QT_NO_PROCESS + QSKIP("Test requires QProcess", SkipAll); +#else QRect dpRect(10, 10, 50, 50); // Start the direct painter in a different process @@ -211,6 +214,7 @@ void tst_QDirectPainter::regionSynchronization() QVERIFY(i > 100); // sanity check proc.kill(); +#endif } class MyObject : public QObject diff --git a/tests/auto/qfile/tst_qfile.cpp b/tests/auto/qfile/tst_qfile.cpp index 8d9c2be..66f29dd 100644 --- a/tests/auto/qfile/tst_qfile.cpp +++ b/tests/auto/qfile/tst_qfile.cpp @@ -382,6 +382,12 @@ void tst_QFile::open() QFETCH( bool, ok ); +#ifdef Q_OS_UNIX + if (::getuid() == 0) + // root and Chuck Norris don't care for file permissions. Skip. + QSKIP("Running this test as root doesn't make sense", SkipAll); +#endif + #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) QEXPECT_FAIL("noreadfile", "Windows does not currently support non-readable files.", Abort); #endif @@ -2493,14 +2499,20 @@ void tst_QFile::map() file.close(); - // Change permissions on a file, just to confirm it would fail - QFile::Permissions originalPermissions = file.permissions(); - QVERIFY(file.setPermissions(QFile::ReadOther)); - QVERIFY(!file.open(QFile::ReadWrite)); - memory = file.map(offset, size); - QCOMPARE(file.error(), QFile::PermissionsError); - QVERIFY(!memory); - QVERIFY(file.setPermissions(originalPermissions)); +#ifdef Q_OS_UNIX + if (::getuid() != 0) + // root always has permissions +#endif + { + // Change permissions on a file, just to confirm it would fail + QFile::Permissions originalPermissions = file.permissions(); + QVERIFY(file.setPermissions(QFile::ReadOther)); + QVERIFY(!file.open(QFile::ReadWrite)); + memory = file.map(offset, size); + QCOMPARE(file.error(), QFile::PermissionsError); + QVERIFY(!memory); + QVERIFY(file.setPermissions(originalPermissions)); + } QVERIFY(file.remove()); } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index f58cad2..011e480 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -76,6 +76,46 @@ Q_DECLARE_METATYPE(QRectF) #define Q_CHECK_PAINTEVENTS #endif +class EventSpy : public QGraphicsWidget +{ + Q_OBJECT +public: + EventSpy(QObject *watched, QEvent::Type type) + : _count(0), spied(type) + { + watched->installEventFilter(this); + } + + EventSpy(QGraphicsScene *scene, QGraphicsItem *watched, QEvent::Type type) + : _count(0), spied(type) + { + scene->addItem(this); + watched->installSceneEventFilter(this); + } + + int count() const { return _count; } + +protected: + bool eventFilter(QObject *watched, QEvent *event) + { + Q_UNUSED(watched); + if (event->type() == spied) + ++_count; + return false; + } + + bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) + { + Q_UNUSED(watched); + if (event->type() == spied) + ++_count; + return false; + } + + int _count; + QEvent::Type spied; +}; + class EventTester : public QGraphicsItem { public: @@ -234,6 +274,7 @@ private slots: void sorting(); void itemHasNoContents(); void hitTestUntransformableItem(); + void focusProxy(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -7344,5 +7385,84 @@ void tst_QGraphicsItem::hitTestUntransformableItem() QCOMPARE(items.at(0), static_cast<QGraphicsItem*>(item3)); } +void tst_QGraphicsItem::focusProxy() +{ + QGraphicsScene scene; + QGraphicsItem *item = scene.addRect(0, 0, 10, 10); + item->setFlag(QGraphicsItem::ItemIsFocusable); + QVERIFY(!item->focusProxy()); + + QGraphicsItem *item2 = scene.addRect(0, 0, 10, 10); + item2->setFlag(QGraphicsItem::ItemIsFocusable); + item->setFocusProxy(item2); + QCOMPARE(item->focusProxy(), item2); + + item->setFocus(); + QVERIFY(item->hasFocus()); + QVERIFY(item2->hasFocus()); + + // Try to make a focus chain loop + QString err; + QTextStream stream(&err); + stream << "QGraphicsItem::setFocusProxy: " + << (void*)item << " is already in the focus proxy chain" << flush; + QTest::ignoreMessage(QtWarningMsg, err.toLatin1().constData()); + item2->setFocusProxy(item); // fails + QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2); + QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0); + + // Try to assign self as focus proxy + QTest::ignoreMessage(QtWarningMsg, "QGraphicsItem::setFocusProxy: cannot assign self as focus proxy"); + item->setFocusProxy(item); // fails + QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2); + QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0); + + // Reset the focus proxy + item->setFocusProxy(0); + QCOMPARE(item->focusProxy(), (QGraphicsItem *)0); + QVERIFY(!item->hasFocus()); + QVERIFY(item2->hasFocus()); + + // Test deletion + item->setFocusProxy(item2); + QCOMPARE(item->focusProxy(), (QGraphicsItem *)item2); + delete item2; + QCOMPARE(item->focusProxy(), (QGraphicsItem *)0); + + // Test event delivery + item2 = scene.addRect(0, 0, 10, 10); + item2->setFlag(QGraphicsItem::ItemIsFocusable); + item->setFocusProxy(item2); + item->clearFocus(); + + EventSpy focusInSpy(&scene, item, QEvent::FocusIn); + EventSpy focusOutSpy(&scene, item, QEvent::FocusOut); + EventSpy focusInSpy2(&scene, item2, QEvent::FocusIn); + EventSpy focusOutSpy2(&scene, item2, QEvent::FocusOut); + QCOMPARE(focusInSpy.count(), 0); + QCOMPARE(focusOutSpy.count(), 0); + QCOMPARE(focusInSpy2.count(), 0); + QCOMPARE(focusOutSpy2.count(), 0); + + item->setFocus(); + QCOMPARE(focusInSpy.count(), 0); + QCOMPARE(focusInSpy2.count(), 1); + item->clearFocus(); + QCOMPARE(focusOutSpy.count(), 0); + QCOMPARE(focusOutSpy2.count(), 1); + + // Test two items proxying one item. + QGraphicsItem *item3 = scene.addRect(0, 0, 10, 10); + item3->setFlag(QGraphicsItem::ItemIsFocusable); + item3->setFocusProxy(item2); // item and item3 use item2 as proxy + + QCOMPARE(item->focusProxy(), item2); + QCOMPARE(item2->focusProxy(), (QGraphicsItem *)0); + QCOMPARE(item3->focusProxy(), item2); + delete item2; + QCOMPARE(item->focusProxy(), (QGraphicsItem *)0); + QCOMPARE(item3->focusProxy(), (QGraphicsItem *)0); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index b67c727..788be1e 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -114,6 +114,7 @@ class tst_QNetworkReply: public QObject MyCookieJar *cookieJar; #ifndef QT_NO_OPENSSL QSslConfiguration storedSslConfiguration; + QList<QSslError> storedExpectedSslErrors; #endif public: @@ -126,9 +127,11 @@ public Q_SLOTS: void gotError(); void authenticationRequired(QNetworkReply*,QAuthenticator*); void proxyAuthenticationRequired(const QNetworkProxy &,QAuthenticator*); + #ifndef QT_NO_OPENSSL void sslErrors(QNetworkReply*,const QList<QSslError> &); void storeSslConfiguration(); + void ignoreSslErrorListSlot(QNetworkReply *reply, const QList<QSslError> &); #endif protected Q_SLOTS: @@ -247,6 +250,13 @@ private Q_SLOTS: void httpConnectionCount(); void httpDownloadPerformance_data(); void httpDownloadPerformance(); + +#ifndef QT_NO_OPENSSL + void ignoreSslErrorsList_data(); + void ignoreSslErrorsList(); + void ignoreSslErrorsListWithSlot_data(); + void ignoreSslErrorsListWithSlot(); +#endif }; QT_BEGIN_NAMESPACE @@ -3540,7 +3550,7 @@ void tst_QNetworkReply::httpProxyCommands_data() << QUrl("http://0.0.0.0:4443/http-request") << QByteArray("HTTP/1.0 200 OK\r\nProxy-Connection: close\r\nContent-Length: 1\r\n\r\n1") << "GET http://0.0.0.0:4443/http-request HTTP/1."; -#ifndef QT_NO_SSL +#ifndef QT_NO_OPENSSL QTest::newRow("https") << QUrl("https://0.0.0.0:4443/https-request") << QByteArray("HTTP/1.0 200 Connection Established\r\n\r\n") @@ -3832,5 +3842,81 @@ void tst_QNetworkReply::httpDownloadPerformance() delete reply; } +#ifndef QT_NO_OPENSSL +void tst_QNetworkReply::ignoreSslErrorsList_data() +{ + QTest::addColumn<QString>("url"); + QTest::addColumn<QList<QSslError> >("expectedSslErrors"); + QTest::addColumn<QNetworkReply::NetworkError>("expectedNetworkError"); + + QList<QSslError> expectedSslErrors; + // apparently, because of some weird behaviour of SRCDIR, the file name below needs to start with a slash + QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "/../qsslsocket/certs/qt-test-server-cacert.pem")); + QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0)); + QSslError wrongError(QSslError::SelfSignedCertificate); + + QTest::newRow("SSL-failure-empty-list") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError; + expectedSslErrors.append(wrongError); + QTest::newRow("SSL-failure-wrong-error") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError; + expectedSslErrors.append(rightError); + QTest::newRow("allErrorsInExpectedList1") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::NoError; + expectedSslErrors.removeAll(wrongError); + QTest::newRow("allErrorsInExpectedList2") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::NoError; + expectedSslErrors.removeAll(rightError); + QTest::newRow("SSL-failure-empty-list-again") << "https://" + QtNetworkSettings::serverName() + "/index.html" << expectedSslErrors << QNetworkReply::SslHandshakeFailedError; +} + +void tst_QNetworkReply::ignoreSslErrorsList() +{ + QFETCH(QString, url); + QNetworkRequest request(url); + QNetworkReply *reply = manager.get(request); + + QFETCH(QList<QSslError>, expectedSslErrors); + reply->ignoreSslErrors(expectedSslErrors); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QFETCH(QNetworkReply::NetworkError, expectedNetworkError); + QCOMPARE(reply->error(), expectedNetworkError); +} + +void tst_QNetworkReply::ignoreSslErrorsListWithSlot_data() +{ + ignoreSslErrorsList_data(); +} + +// this is not a test, just a slot called in the test below +void tst_QNetworkReply::ignoreSslErrorListSlot(QNetworkReply *reply, const QList<QSslError> &) +{ + reply->ignoreSslErrors(storedExpectedSslErrors); +} + +// do the same as in ignoreSslErrorsList, but ignore the errors in the slot +void tst_QNetworkReply::ignoreSslErrorsListWithSlot() +{ + QFETCH(QString, url); + QNetworkRequest request(url); + QNetworkReply *reply = manager.get(request); + + QFETCH(QList<QSslError>, expectedSslErrors); + // store the errors to ignore them later in the slot connected below + storedExpectedSslErrors = expectedSslErrors; + connect(&manager, SIGNAL(sslErrors(QNetworkReply *, const QList<QSslError> &)), + this, SLOT(ignoreSslErrorListSlot(QNetworkReply *, const QList<QSslError> &))); + + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QFETCH(QNetworkReply::NetworkError, expectedNetworkError); + QCOMPARE(reply->error(), expectedNetworkError); +} + +#endif // QT_NO_OPENSSL + QTEST_MAIN(tst_QNetworkReply) #include "tst_qnetworkreply.moc" diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 8ce7c3a..4f25af6 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -2426,11 +2426,15 @@ void tst_QObject::dynamicProperties() void tst_QObject::recursiveSignalEmission() { +#ifdef QT_NO_PROCESS + QSKIP("Test requires QProcess", SkipAll); +#else QProcess proc; proc.start("./signalbug"); QVERIFY(proc.waitForFinished()); QVERIFY(proc.exitStatus() == QProcess::NormalExit); QCOMPARE(proc.exitCode(), 0); +#endif } void tst_QObject::blockingQueuedConnection() diff --git a/tests/auto/qprocess/tst_qprocess.cpp b/tests/auto/qprocess/tst_qprocess.cpp index c19d0a5..1ae5b12 100644 --- a/tests/auto/qprocess/tst_qprocess.cpp +++ b/tests/auto/qprocess/tst_qprocess.cpp @@ -50,6 +50,10 @@ #include <QtNetwork/QHostInfo> #include <stdlib.h> +#ifdef QT_NO_PROCESS +QTEST_NOOP_MAIN +#else + #if defined(Q_OS_WIN) #include <windows.h> #endif @@ -143,6 +147,7 @@ private slots: void startFinishStartFinish(); void invalidProgramString_data(); void invalidProgramString(); + void processEventsInAReadyReadSlot(); // keep these at the end, since they use lots of processes and sometimes // caused obscure failures to occur in tests that followed them (esp. on the Mac) @@ -156,6 +161,7 @@ protected slots: void restartProcess(); void waitForReadyReadInAReadyReadSlotSlot(); void waitForBytesWrittenInABytesWrittenSlotSlot(); + void processEventsInAReadyReadSlotSlot(); private: QProcess *process; @@ -2130,5 +2136,35 @@ void tst_QProcess::invalidProgramString() QVERIFY(!QProcess::startDetached(programString)); } +//----------------------------------------------------------------------------- +void tst_QProcess::processEventsInAReadyReadSlot() +{ +#ifdef Q_OS_WINCE + QSKIP("Reading and writing to a process is not supported on Qt/CE", SkipAll); +#endif + + QProcess process; + QVERIFY(QObject::connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(processEventsInAReadyReadSlotSlot()))); + + for (int i = 0; i < 10; ++i) { + QCOMPARE(process.state(), QProcess::NotRunning); + +#ifdef Q_OS_MAC + process.start("testProcessOutput/testProcessOutput.app"); +#else + process.start("testProcessOutput/testProcessOutput"); +#endif + + QVERIFY(process.waitForFinished(10000)); + } +} + +//----------------------------------------------------------------------------- +void tst_QProcess::processEventsInAReadyReadSlotSlot() +{ + qApp->processEvents(); +} + QTEST_MAIN(tst_QProcess) #include "tst_qprocess.moc" +#endif diff --git a/tests/auto/qprogressbar/tst_qprogressbar.cpp b/tests/auto/qprogressbar/tst_qprogressbar.cpp index 403b56b..911d6b7 100644 --- a/tests/auto/qprogressbar/tst_qprogressbar.cpp +++ b/tests/auto/qprogressbar/tst_qprogressbar.cpp @@ -62,6 +62,8 @@ private slots: void format(); void setValueRepaint(); void sizeHint(); + void formatedText_data(); + void formatedText(); void task245201_testChangeStyleAndDelete_data(); void task245201_testChangeStyleAndDelete(); @@ -174,7 +176,7 @@ void tst_QProgressBar::format() bar.repainted = false; bar.setFormat("%v of %m (%p%)"); qApp->processEvents(); -#ifndef Q_WS_MAC +#ifndef Q_WS_MAC // The Mac scroll bar is animated, which means we get paint events all the time. QVERIFY(!bar.repainted); #endif @@ -225,6 +227,34 @@ void tst_QProgressBar::sizeHint() QCOMPARE(barSize.height(), size.height()); } +void tst_QProgressBar::formatedText_data() +{ + QTest::addColumn<int>("minimum"); + QTest::addColumn<int>("maximum"); + QTest::addColumn<int>("value"); + QTest::addColumn<QString>("format"); + QTest::addColumn<QString>("text"); + + QTest::newRow("1") << -100 << 100 << 0 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 50 - 0 - 200 "); + QTest::newRow("2") << -100 << 0 << -25 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 75 - -25 - 100 "); + QTest::newRow("3") << 10 << 10 << 10 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 100 - 10 - 0 "); + QTest::newRow("task152227") << INT_MIN << INT_MAX << 42 << QString::fromLatin1(" %p - %v - %m ") << QString::fromLatin1(" 50 - 42 - 4294967295 "); +} + +void tst_QProgressBar::formatedText() +{ + QFETCH(int, minimum); + QFETCH(int, maximum); + QFETCH(int, value); + QFETCH(QString, format); + QFETCH(QString, text); + QProgressBar bar; + bar.setRange(minimum, maximum); + bar.setValue(value); + bar.setFormat(format); + QCOMPARE(bar.text(), text); +} + void tst_QProgressBar::task245201_testChangeStyleAndDelete_data() { QTest::addColumn<QString>("style1_str"); diff --git a/tests/auto/qsettings/tst_qsettings.cpp b/tests/auto/qsettings/tst_qsettings.cpp index 77fef1f..5b9e9e1 100644 --- a/tests/auto/qsettings/tst_qsettings.cpp +++ b/tests/auto/qsettings/tst_qsettings.cpp @@ -716,6 +716,9 @@ void tst_QSettings::testErrorHandling() #ifdef QT_BUILD_INTERNAL #ifdef Q_OS_WIN QSKIP("Windows doesn't support most file modes, including read-only directories, so this test is moot.", SkipAll); +#elif defined(Q_OS_UNIX) + if (::getuid() == 0) + QSKIP("Running this test as root doesn't work, since file perms do not bother him", SkipAll); #else QFETCH(int, filePerms); QFETCH(int, dirPerms); @@ -724,8 +727,7 @@ void tst_QSettings::testErrorHandling() QFETCH(int, statusAfterGet); QFETCH(int, statusAfterSetAndSync); - - system(QString("chmod 700 %1 2>/dev/null").arg(settingsPath("someDir")).toLatin1()); + system(QString("chmod 700 %1 2>/dev/null").arg(settingsPath("someDir")).toLatin1()); system(QString("chmod -R u+rwx %1 2>/dev/null").arg(settingsPath("someDir")).toLatin1()); system(QString("rm -fr %1").arg(settingsPath("someDir")).toLatin1()); diff --git a/tests/auto/qsslsocket/certs/qt-test-server-cacert.pem b/tests/auto/qsslsocket/certs/qt-test-server-cacert.pem index 83adca2..25bd404 100644 --- a/tests/auto/qsslsocket/certs/qt-test-server-cacert.pem +++ b/tests/auto/qsslsocket/certs/qt-test-server-cacert.pem @@ -1,22 +1,17 @@ -----BEGIN CERTIFICATE----- -MIIDuDCCAyGgAwIBAgIJAM17QpZu2GP7MA0GCSqGSIb3DQEBBAUAMIGaMQ4wDAYD -VQQKEwVOb2tpYTEUMBIGA1UECxMLUXQgU29mdHdhcmUxIjAgBgkqhkiG9w0BCQEW -E25vYm9keUBub2RvbWFpbi5vcmcxDTALBgNVBAcTBE9zbG8xDTALBgNVBAgTBE9z -bG8xCzAJBgNVBAYTAk5PMSMwIQYDVQQDExpxdC10ZXN0LXNlcnZlci5xdC10ZXN0 -LW5ldDAeFw0wODEyMDIxNDQ3MjZaFw0xODExMzAxNDQ3MjZaMIGaMQ4wDAYDVQQK -EwVOb2tpYTEUMBIGA1UECxMLUXQgU29mdHdhcmUxIjAgBgkqhkiG9w0BCQEWE25v -Ym9keUBub2RvbWFpbi5vcmcxDTALBgNVBAcTBE9zbG8xDTALBgNVBAgTBE9zbG8x -CzAJBgNVBAYTAk5PMSMwIQYDVQQDExpxdC10ZXN0LXNlcnZlci5xdC10ZXN0LW5l -dDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAz7dQ0l6IYpwVUcvj0mQxvG80 -yzoRzYr+alh7HMmOFI6/xjBHD6zAEEmLBafY7M/xe8PGH7ds2l2BFJkz0OS+IJRX -8CdOoeFvmVyp+L84tzXk81NKnMQ3y8DiFc6aUkfnyybA0whIv/TlqNyrYeQUin+t -61dPf1vr0LAAm5HdeYECAwEAAaOCAQIwgf8wDAYDVR0TBAUwAwEB/zAdBgNVHQ4E -FgQUwhEr5xV4r0deMQd3XwFkFtwls20wgc8GA1UdIwSBxzCBxIAUwhEr5xV4r0de -MQd3XwFkFtwls22hgaCkgZ0wgZoxDjAMBgNVBAoTBU5va2lhMRQwEgYDVQQLEwtR -dCBTb2Z0d2FyZTEiMCAGCSqGSIb3DQEJARYTbm9ib2R5QG5vZG9tYWluLm9yZzEN -MAsGA1UEBxMET3NsbzENMAsGA1UECBMET3NsbzELMAkGA1UEBhMCTk8xIzAhBgNV -BAMTGnF0LXRlc3Qtc2VydmVyLnF0LXRlc3QtbmV0ggkAzXtClm7YY/swDQYJKoZI -hvcNAQEEBQADgYEAQ/8YDtHrUoEsu9j5J6GY8iuuT8jvs/W1se5vXzoITgld+vLM -RWzxz35Hwzy2n31MNmUagRyQsTNOvEtJTxPCP97eLLxxrHDAbRmY/PPcZfolfOQf -xKQYf9naBv2F9Bs0WcY9z0Dgdl27szTAN67vGddYx5HpU9UE8Or5hdFJI3I= +MIICrTCCAhYCCQCdDn5rci6VDjANBgkqhkiG9w0BAQQFADCBmjEOMAwGA1UEChMF +Tm9raWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2Jv +ZHlAbm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQsw +CQYDVQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQw +HhcNMDkwNzEwMDc0MTIzWhcNMTkwNzA4MDc0MTIzWjCBmjEOMAwGA1UEChMFTm9r +aWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2JvZHlA +bm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQswCQYD +VQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwgZ8w +DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6 +Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt +93CxGBXMIChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJr +gsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAy7YOLCZABQy2Ygkchq1I ++TUpvMn+gLwAyW8TNErM1V4lNY2+K78RawzKx3SqM97ymCy4TD45EA3A2gmi32NI +xSKBNjFyzngUqsXBdcSasALiowlZCiJrGwlGX5qCkBlxXvJeUEbuJLPYVl5FBjXZ +6o00K4cSPCqtqUez7WSmDZU= -----END CERTIFICATE----- diff --git a/tests/auto/qsslsocket/tst_qsslsocket.cpp b/tests/auto/qsslsocket/tst_qsslsocket.cpp index 066b950..23eee29 100644 --- a/tests/auto/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/qsslsocket/tst_qsslsocket.cpp @@ -173,6 +173,10 @@ private slots: void disconnectFromHostWhenConnecting(); void disconnectFromHostWhenConnected(); void resetProxy(); + void ignoreSslErrorsList_data(); + void ignoreSslErrorsList(); + void ignoreSslErrorsListWithSlot_data(); + void ignoreSslErrorsListWithSlot(); static void exitLoop() { @@ -194,9 +198,11 @@ protected slots: if (errors.size() == 1 && errors.first().error() == QSslError::CertificateUntrusted) socket->ignoreSslErrors(); } + void ignoreErrorListSlot(const QList<QSslError> &errors); private: QSslSocket *socket; + QList<QSslError> storedExpectedSslErrors; #endif // QT_NO_OPENSSL private: static int loopLevel; @@ -609,7 +615,7 @@ void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName() QSslSocketPtr socket = newSocket(); this->socket = socket; - socket->addCaCertificates(QLatin1String("certs/qt-test-server-cacert.pem")); + socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); #ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND connect(&socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(untrustedWorkaroundSlot(QList<QSslError>))); @@ -1417,9 +1423,7 @@ void tst_QSslSocket::verifyMode() QVERIFY(!socket.waitForEncrypted()); QList<QSslError> expectedErrors = QList<QSslError>() - << QSslError(QSslError::UnableToGetLocalIssuerCertificate, socket.peerCertificate()) - << QSslError(QSslError::CertificateUntrusted, socket.peerCertificate()) - << QSslError(QSslError::UnableToVerifyFirstCertificate, socket.peerCertificate()); + << QSslError(QSslError::SelfSignedCertificate, socket.peerCertificate()); QCOMPARE(socket.sslErrors(), expectedErrors); socket.abort(); @@ -1539,6 +1543,82 @@ void tst_QSslSocket::resetProxy() QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString())); } +void tst_QSslSocket::ignoreSslErrorsList_data() +{ + QTest::addColumn<QList<QSslError> >("expectedSslErrors"); + QTest::addColumn<int>("expectedSslErrorSignalCount"); + + // construct the list of errors that we will get with the SSL handshake and that we will ignore + QList<QSslError> expectedSslErrors; + // fromPath gives us a list of certs, but it actually only contains one + QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")); + QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0)); + QSslError wrongError(QSslError::SelfSignedCertificate); + + + QTest::newRow("SSL-failure-empty-list") << expectedSslErrors << 1; + expectedSslErrors.append(wrongError); + QTest::newRow("SSL-failure-wrong-error") << expectedSslErrors << 1; + expectedSslErrors.append(rightError); + QTest::newRow("allErrorsInExpectedList1") << expectedSslErrors << 0; + expectedSslErrors.removeAll(wrongError); + QTest::newRow("allErrorsInExpectedList2") << expectedSslErrors << 0; + expectedSslErrors.removeAll(rightError); + QTest::newRow("SSL-failure-empty-list-again") << expectedSslErrors << 1; +} + +void tst_QSslSocket::ignoreSslErrorsList() +{ + QSslSocket socket; + connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), + this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); + +// this->socket = &socket; + QSslCertificate cert; + + QFETCH(QList<QSslError>, expectedSslErrors); + socket.ignoreSslErrors(expectedSslErrors); + + QFETCH(int, expectedSslErrorSignalCount); + QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError))); + + socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); + + bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0); + QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess); + QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount); +} + +void tst_QSslSocket::ignoreSslErrorsListWithSlot_data() +{ + ignoreSslErrorsList_data(); +} + +// this is not a test, just a slot called in the test below +void tst_QSslSocket::ignoreErrorListSlot(const QList<QSslError> &) +{ + socket->ignoreSslErrors(storedExpectedSslErrors); +} + +void tst_QSslSocket::ignoreSslErrorsListWithSlot() +{ + QSslSocket socket; + this->socket = &socket; + + QFETCH(QList<QSslError>, expectedSslErrors); + // store the errors to ignore them later in the slot connected below + storedExpectedSslErrors = expectedSslErrors; + connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)), + this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*))); + connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), + this, SLOT(ignoreErrorListSlot(const QList<QSslError> &))); + socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443); + + QFETCH(int, expectedSslErrorSignalCount); + bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0); + QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess); +} + #endif // QT_NO_OPENSSL QTEST_MAIN(tst_QSslSocket) diff --git a/tests/auto/qstate/tst_qstate.cpp b/tests/auto/qstate/tst_qstate.cpp index ab87767..78b9853 100644 --- a/tests/auto/qstate/tst_qstate.cpp +++ b/tests/auto/qstate/tst_qstate.cpp @@ -60,10 +60,10 @@ tst_QState::~tst_QState() void tst_QState::test() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); QCOMPARE(s1->machine(), &machine); - QCOMPARE(s1->parentState(), machine.rootState()); + QCOMPARE(s1->parentState(), &machine); QCOMPARE(s1->initialState(), (QState*)0); QVERIFY(s1->childStates().isEmpty()); QVERIFY(s1->transitions().isEmpty()); @@ -218,7 +218,7 @@ void tst_QState::assignProperty() QObject *object = new QObject(); object->setProperty("fooBar", 10); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(object, "fooBar", 20); machine.setInitialState(s1); @@ -235,7 +235,7 @@ void tst_QState::assignPropertyTwice() QObject *object = new QObject(); object->setProperty("fooBar", 10); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(object, "fooBar", 20); s1->assignProperty(object, "fooBar", 30); @@ -271,9 +271,9 @@ void tst_QState::historyInitialState() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); QHistoryState *h1 = new QHistoryState(s2); s2->setInitialState(h1); diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index efcb983..7f4d9f5 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -127,6 +127,7 @@ private slots: void targetStateWithNoParent(); void targetStateDeleted(); void transitionToRootState(); + void transitionFromRootState(); void transitionEntersParent(); void defaultErrorState(); @@ -189,6 +190,8 @@ private slots: // void overrideDefaultSourceAnimationWithSpecific(); // void overrideDefaultTargetAnimationWithSpecific(); // void overrideDefaultTargetAnimationWithSource(); + + void nestedStateMachines(); }; tst_QStateMachine::tst_QStateMachine() @@ -258,13 +261,17 @@ private: void tst_QStateMachine::transitionToRootState() { QStateMachine machine; + machine.setObjectName("machine"); QState *initialState = new QState(); + initialState->setObjectName("initial"); machine.addState(initialState); machine.setInitialState(initialState); - QTest::ignoreMessage(QtWarningMsg, "QAbstractTransition::setTargetStates: root state cannot be target of transition"); - initialState->addTransition(new EventTransition(QEvent::User, machine.rootState())); + QAbstractTransition *trans = initialState->addTransition(new EventTransition(QEvent::User, &machine)); + QVERIFY(trans != 0); + QCOMPARE(trans->sourceState(), initialState); + QCOMPARE(trans->targetState(), &machine); machine.start(); QCoreApplication::processEvents(); @@ -273,10 +280,21 @@ void tst_QStateMachine::transitionToRootState() QVERIFY(machine.configuration().contains(initialState)); machine.postEvent(new QEvent(QEvent::User)); + QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: No common ancestor for targets and source of transition from state 'initial'"); QCoreApplication::processEvents(); + QVERIFY(machine.configuration().isEmpty()); + QVERIFY(!machine.isRunning()); +} - QCOMPARE(machine.configuration().count(), 1); - QVERIFY(machine.configuration().contains(initialState)); +void tst_QStateMachine::transitionFromRootState() +{ + QStateMachine machine; + QState *root = &machine; + QState *s1 = new QState(root); + EventTransition *trans = new EventTransition(QEvent::User, s1); + QCOMPARE(root->addTransition(trans), trans); + QCOMPARE(trans->sourceState(), root); + QCOMPARE(trans->targetState(), s1); } void tst_QStateMachine::transitionEntersParent() @@ -658,7 +676,7 @@ void tst_QStateMachine::errorStateIsRootState() { QStateMachine machine; QTest::ignoreMessage(QtWarningMsg, "QStateMachine::setErrorState: root state cannot be error state"); - machine.setErrorState(machine.rootState()); + machine.setErrorState(&machine); QState *initialState = new QState(); initialState->setObjectName("initialState"); @@ -759,7 +777,7 @@ void tst_QStateMachine::errorStateEntersParentFirst() void tst_QStateMachine::customErrorStateIsNull() { QStateMachine machine; - machine.rootState()->setErrorState(0); + machine.setErrorState(0); QState *initialState = new QState(); machine.addState(initialState); @@ -785,9 +803,9 @@ void tst_QStateMachine::customErrorStateIsNull() void tst_QStateMachine::clearError() { QStateMachine machine; - machine.setErrorState(new QState(machine.rootState())); // avoid warnings + machine.setErrorState(new QState(&machine)); // avoid warnings - QState *brokenState = new QState(machine.rootState()); + QState *brokenState = new QState(&machine); brokenState->setObjectName("brokenState"); machine.setInitialState(brokenState); new QState(brokenState); @@ -809,13 +827,13 @@ void tst_QStateMachine::historyStateAsInitialState() { QStateMachine machine; - QHistoryState *hs = new QHistoryState(machine.rootState()); + QHistoryState *hs = new QHistoryState(&machine); machine.setInitialState(hs); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); hs->setDefaultState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); QHistoryState *s2h = new QHistoryState(s2); s2->setInitialState(s2h); @@ -843,11 +861,11 @@ void tst_QStateMachine::historyStateHasNowhereToGo() { QStateMachine machine; - QState *initialState = new QState(machine.rootState()); + QState *initialState = new QState(&machine); machine.setInitialState(initialState); - machine.setErrorState(new QState(machine.rootState())); // avoid warnings + machine.setErrorState(new QState(&machine)); // avoid warnings - QState *brokenState = new QState(machine.rootState()); + QState *brokenState = new QState(&machine); brokenState->setObjectName("brokenState"); brokenState->setInitialState(new QState(brokenState)); @@ -877,14 +895,14 @@ void tst_QStateMachine::brokenStateIsNeverEntered() entryController->setProperty("childStateEntered", false); entryController->setProperty("errorStateEntered", false); - QState *initialState = new QState(machine.rootState()); + QState *initialState = new QState(&machine); machine.setInitialState(initialState); - QState *errorState = new QState(machine.rootState()); + QState *errorState = new QState(&machine); errorState->assignProperty(entryController, "errorStateEntered", true); machine.setErrorState(errorState); - QState *brokenState = new QState(machine.rootState()); + QState *brokenState = new QState(&machine); brokenState->assignProperty(entryController, "brokenStateEntered", true); brokenState->setObjectName("brokenState"); @@ -908,7 +926,7 @@ void tst_QStateMachine::transitionToStateNotInGraph() { QStateMachine machine; - QState *initialState = new QState(machine.rootState()); + QState *initialState = new QState(&machine); initialState->setObjectName("initialState"); machine.setInitialState(initialState); @@ -933,7 +951,7 @@ void tst_QStateMachine::customErrorStateNotInGraph() machine.setErrorState(&errorState); QCOMPARE(machine.errorState(), reinterpret_cast<QAbstractState *>(0)); - QState *initialBrokenState = new QState(machine.rootState()); + QState *initialBrokenState = new QState(&machine); initialBrokenState->setObjectName("initialBrokenState"); machine.setInitialState(initialBrokenState); new QState(initialBrokenState); @@ -999,25 +1017,22 @@ void tst_QStateMachine::restoreProperties() void tst_QStateMachine::rootState() { QStateMachine machine; - QVERIFY(machine.rootState() != 0); - QVERIFY(qobject_cast<QState*>(machine.rootState()) != 0); - QCOMPARE(qobject_cast<QState*>(machine.rootState())->parentState(), (QState*)0); - QCOMPARE(machine.rootState()->parent(), (QObject*)&machine); - QCOMPARE(machine.rootState()->machine(), &machine); + QCOMPARE(qobject_cast<QState*>(machine.parentState()), (QState*)0); + QCOMPARE(machine.machine(), (QStateMachine*)0); - QState *s1 = new QState(machine.rootState()); - QCOMPARE(s1->parentState(), machine.rootState()); + QState *s1 = new QState(&machine); + QCOMPARE(s1->parentState(), &machine); QState *s2 = new QState(); s2->setParent(&machine); - QCOMPARE(s2->parentState(), machine.rootState()); + QCOMPARE(s2->parentState(), &machine); } void tst_QStateMachine::addAndRemoveState() { #ifdef QT_BUILD_INTERNAL QStateMachine machine; - QStatePrivate *root_d = QStatePrivate::get(machine.rootState()); + QStatePrivate *root_d = QStatePrivate::get(&machine); QCOMPARE(root_d->childStates().size(), 0); QTest::ignoreMessage(QtWarningMsg, "QStateMachine::addState: cannot add null state"); @@ -1028,7 +1043,7 @@ void tst_QStateMachine::addAndRemoveState() QCOMPARE(s1->machine(), (QStateMachine*)0); machine.addState(s1); QCOMPARE(s1->machine(), &machine); - QCOMPARE(s1->parentState(), machine.rootState()); + QCOMPARE(s1->parentState(), &machine); QCOMPARE(root_d->childStates().size(), 1); QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s1); @@ -1038,7 +1053,7 @@ void tst_QStateMachine::addAndRemoveState() QState *s2 = new QState(); QCOMPARE(s2->parentState(), (QState*)0); machine.addState(s2); - QCOMPARE(s2->parentState(), machine.rootState()); + QCOMPARE(s2->parentState(), &machine); QCOMPARE(root_d->childStates().size(), 2); QCOMPARE(root_d->childStates().at(0), (QAbstractState*)s1); QCOMPARE(root_d->childStates().at(1), (QAbstractState*)s2); @@ -1063,13 +1078,13 @@ void tst_QStateMachine::addAndRemoveState() { QString warning; warning.sprintf("QStateMachine::removeState: state %p's machine (%p) is different from this machine (%p)", - machine2.rootState(), &machine2, &machine); + &machine2, (void*)0, &machine); QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); - machine.removeState(machine2.rootState()); + machine.removeState(&machine2); } // ### check this behavior - machine.addState(machine2.rootState()); - QCOMPARE(machine2.rootState()->parent(), (QObject*)machine.rootState()); + machine.addState(&machine2); + QCOMPARE(machine2.parent(), (QObject*)&machine); } delete s1; @@ -1085,7 +1100,7 @@ void tst_QStateMachine::stateEntryAndExit() { QStateMachine machine; - TestState *s1 = new TestState(machine.rootState()); + TestState *s1 = new TestState(&machine); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state"); s1->addTransition((QAbstractState*)0); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add null transition"); @@ -1093,8 +1108,8 @@ void tst_QStateMachine::stateEntryAndExit() QTest::ignoreMessage(QtWarningMsg, "QState::removeTransition: cannot remove null transition"); s1->removeTransition((QAbstractTransition*)0); - TestState *s2 = new TestState(machine.rootState()); - QFinalState *s3 = new QFinalState(machine.rootState()); + TestState *s2 = new TestState(&machine); + QFinalState *s3 = new QFinalState(&machine); TestTransition *t = new TestTransition(s2); QCOMPARE(t->machine(), (QStateMachine*)0); @@ -1143,9 +1158,9 @@ void tst_QStateMachine::stateEntryAndExit() QCOMPARE(machine.initialState(), (QAbstractState*)s1); { QString warning; - warning.sprintf("QState::setInitialState: state %p is not a child of this state (%p)", machine.rootState(), machine.rootState()); + warning.sprintf("QState::setInitialState: state %p is not a child of this state (%p)", &machine, &machine); QTest::ignoreMessage(QtWarningMsg, qPrintable(warning)); - machine.setInitialState(machine.rootState()); + machine.setInitialState(&machine); QCOMPARE(machine.initialState(), (QAbstractState*)s1); } QVERIFY(machine.configuration().isEmpty()); @@ -1192,11 +1207,11 @@ void tst_QStateMachine::stateEntryAndExit() { QStateMachine machine; - TestState *s1 = new TestState(machine.rootState()); + TestState *s1 = new TestState(&machine); TestState *s11 = new TestState(s1); TestState *s12 = new TestState(s1); - TestState *s2 = new TestState(machine.rootState()); - QFinalState *s3 = new QFinalState(machine.rootState()); + TestState *s2 = new TestState(&machine); + QFinalState *s3 = new QFinalState(&machine); s1->setInitialState(s11); TestTransition *t1 = new TestTransition(s12); s11->addTransition(t1); @@ -1255,13 +1270,13 @@ void tst_QStateMachine::stateEntryAndExit() void tst_QStateMachine::assignProperty() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); QTest::ignoreMessage(QtWarningMsg, "QState::assignProperty: cannot assign property 'foo' of null object"); s1->assignProperty(0, "foo", QVariant()); s1->assignProperty(s1, "objectName", "s1"); - QFinalState *s2 = new QFinalState(machine.rootState()); + QFinalState *s2 = new QFinalState(&machine); s1->addTransition(s2); machine.setInitialState(s1); machine.start(); @@ -1307,9 +1322,9 @@ void tst_QStateMachine::assignPropertyWithAnimation() QObject obj; obj.setProperty("foo", 321); obj.setProperty("bar", 654); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(&obj, "foo", 123); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(&obj, "foo", 456); s2->assignProperty(&obj, "bar", 789); QAbstractTransition *trans = s1->addTransition(s2); @@ -1329,7 +1344,7 @@ void tst_QStateMachine::assignPropertyWithAnimation() trans->addAnimation(&anim); QCOMPARE(trans->animations().size(), 1); QCOMPARE(trans->animations().at(0), (QAbstractAnimation*)&anim); - QFinalState *s3 = new QFinalState(machine.rootState()); + QFinalState *s3 = new QFinalState(&machine); s2->addTransition(s2, SIGNAL(polished()), s3); machine.setInitialState(s1); @@ -1345,9 +1360,9 @@ void tst_QStateMachine::assignPropertyWithAnimation() QObject obj; obj.setProperty("foo", 321); obj.setProperty("bar", 654); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(&obj, "foo", 123); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(&obj, "foo", 456); s2->assignProperty(&obj, "bar", 789); QAbstractTransition *trans = s1->addTransition(s2); @@ -1357,7 +1372,7 @@ void tst_QStateMachine::assignPropertyWithAnimation() QPropertyAnimation anim2(&obj, "bar"); anim2.setDuration(150); trans->addAnimation(&anim2); - QFinalState *s3 = new QFinalState(machine.rootState()); + QFinalState *s3 = new QFinalState(&machine); s2->addTransition(s2, SIGNAL(polished()), s3); machine.setInitialState(s1); @@ -1373,10 +1388,10 @@ void tst_QStateMachine::assignPropertyWithAnimation() QObject obj; obj.setProperty("foo", 321); obj.setProperty("bar", 654); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(&obj, "foo", 123); s1->assignProperty(&obj, "bar", 321); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(&obj, "foo", 456); s2->assignProperty(&obj, "bar", 654); s2->assignProperty(&obj, "baz", 789); @@ -1385,7 +1400,7 @@ void tst_QStateMachine::assignPropertyWithAnimation() group.addAnimation(new QPropertyAnimation(&obj, "foo")); group.addAnimation(new QPropertyAnimation(&obj, "bar")); trans->addAnimation(&group); - QFinalState *s3 = new QFinalState(machine.rootState()); + QFinalState *s3 = new QFinalState(&machine); s2->addTransition(s2, SIGNAL(polished()), s3); machine.setInitialState(s1); @@ -1402,7 +1417,7 @@ void tst_QStateMachine::assignPropertyWithAnimation() QObject obj; obj.setProperty("foo", 321); obj.setProperty("bar", 654); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); QCOMPARE(s1->childMode(), QState::ExclusiveStates); s1->setChildMode(QState::ParallelStates); QCOMPARE(s1->childMode(), QState::ParallelStates); @@ -1412,7 +1427,7 @@ void tst_QStateMachine::assignPropertyWithAnimation() s1->setObjectName("s1"); s1->assignProperty(&obj, "foo", 123); s1->assignProperty(&obj, "bar", 456); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->setObjectName("s2"); s2->assignProperty(&obj, "foo", 321); QState *s21 = new QState(s2); @@ -1434,7 +1449,7 @@ void tst_QStateMachine::assignPropertyWithAnimation() s21->addTransition(s21, SIGNAL(polished()), s22); - QFinalState *s3 = new QFinalState(machine.rootState()); + QFinalState *s3 = new QFinalState(&machine); s22->addTransition(s2, SIGNAL(polished()), s3); machine.setInitialState(s1); @@ -1451,7 +1466,7 @@ void tst_QStateMachine::assignPropertyWithAnimation() QObject obj; obj.setProperty("foo", 321); obj.setProperty("bar", 654); - QState *group = new QState(machine.rootState()); + QState *group = new QState(&machine); QState *s1 = new QState(group); group->setInitialState(s1); s1->assignProperty(&obj, "foo", 123); @@ -1577,12 +1592,12 @@ void tst_QStateMachine::postEvent() void tst_QStateMachine::stateFinished() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); QState *s1_1 = new QState(s1); QFinalState *s1_2 = new QFinalState(s1); s1_1->addTransition(s1_2); s1->setInitialState(s1_1); - QFinalState *s2 = new QFinalState(machine.rootState()); + QFinalState *s2 = new QFinalState(&machine); s1->addTransition(s1, SIGNAL(finished()), s2); machine.setInitialState(s1); QSignalSpy finishedSpy(&machine, SIGNAL(finished())); @@ -1632,7 +1647,7 @@ void tst_QStateMachine::parallelStates() void tst_QStateMachine::parallelRootState() { QStateMachine machine; - QState *root = machine.rootState(); + QState *root = &machine; QCOMPARE(root->childMode(), QState::ExclusiveStates); root->setChildMode(QState::ParallelStates); QCOMPARE(root->childMode(), QState::ParallelStates); @@ -1655,7 +1670,7 @@ void tst_QStateMachine::parallelRootState() void tst_QStateMachine::allSourceToTargetConfigurations() { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); + QState *s0 = new QState(&machine); s0->setObjectName("s0"); QState *s1 = new QState(s0); s1->setObjectName("s1"); @@ -1667,7 +1682,7 @@ void tst_QStateMachine::allSourceToTargetConfigurations() s21->setObjectName("s21"); QState *s211 = new QState(s21); s211->setObjectName("s211"); - QFinalState *f = new QFinalState(machine.rootState()); + QFinalState *f = new QFinalState(&machine); f->setObjectName("f"); s0->setInitialState(s1); @@ -1741,7 +1756,7 @@ void tst_QStateMachine::signalTransitions() { { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); + QState *s0 = new QState(&machine); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: sender cannot be null"); QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QSignalTransition*)0); @@ -1752,7 +1767,7 @@ void tst_QStateMachine::signalTransitions() QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state"); QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QSignalTransition*)0); - QFinalState *s1 = new QFinalState(machine.rootState()); + QFinalState *s1 = new QFinalState(&machine); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: no such signal SignalEmitter::noSuchSignal()"); QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QSignalTransition*)0); @@ -1803,8 +1818,8 @@ void tst_QStateMachine::signalTransitions() } { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); SignalEmitter emitter; QSignalTransition *trans = s0->addTransition(&emitter, "signalWithNoArg()", s1); QVERIFY(trans != 0); @@ -1831,8 +1846,8 @@ void tst_QStateMachine::signalTransitions() } { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); SignalEmitter emitter; TestSignalTransition *trans = new TestSignalTransition(&emitter, SIGNAL(signalWithIntArg(int)), s1); s0->addTransition(trans); @@ -1850,8 +1865,8 @@ void tst_QStateMachine::signalTransitions() } { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); SignalEmitter emitter; TestSignalTransition *trans = new TestSignalTransition(&emitter, SIGNAL(signalWithStringArg(QString)), s1); s0->addTransition(trans); @@ -1870,8 +1885,8 @@ void tst_QStateMachine::signalTransitions() } { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); TestSignalTransition *trans = new TestSignalTransition(); QCOMPARE(trans->senderObject(), (QObject*)0); @@ -1898,8 +1913,8 @@ void tst_QStateMachine::signalTransitions() { QStateMachine machine; SignalEmitter emitter; - QState *s0 = new QState(machine.rootState()); - QState *s1 = new QState(machine.rootState()); + QState *s0 = new QState(&machine); + QState *s1 = new QState(&machine); QSignalTransition *t0 = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1); QSignalTransition *t1 = s1->addTransition(&emitter, SIGNAL(signalWithNoArg()), s0); @@ -1943,12 +1958,12 @@ void tst_QStateMachine::signalTransitions() { QStateMachine machine; SignalEmitter emitter; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1); - QFinalState *s2 = new QFinalState(machine.rootState()); + QFinalState *s2 = new QFinalState(&machine); s0->addTransition(&emitter, SIGNAL(signalWithIntArg(int)), s2); - QFinalState *s3 = new QFinalState(machine.rootState()); + QFinalState *s3 = new QFinalState(&machine); s0->addTransition(&emitter, SIGNAL(signalWithStringArg(QString)), s3); QSignalSpy startedSpy(&machine, SIGNAL(started())); @@ -1980,8 +1995,8 @@ void tst_QStateMachine::signalTransitions() { QStateMachine machine; SignalEmitter emitter; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); QSignalTransition *t0 = s0->addTransition(&emitter, SIGNAL( signalWithNoArg( ) ), s1); QVERIFY(t0 != 0); QCOMPARE(t0->signal(), QByteArray(SIGNAL( signalWithNoArg( ) ))); @@ -2008,8 +2023,8 @@ void tst_QStateMachine::eventTransitions() QPushButton button; for (int x = 0; x < 2; ++x) { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); QMouseEventTransition *trans; if (x == 0) { @@ -2057,8 +2072,8 @@ void tst_QStateMachine::eventTransitions() } for (int x = 0; x < 3; ++x) { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); QEventTransition *trans; if (x == 0) { @@ -2092,8 +2107,8 @@ void tst_QStateMachine::eventTransitions() } { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); QMouseEventTransition *trans = new QMouseEventTransition(); QCOMPARE(trans->eventObject(), (QObject*)0); @@ -2118,8 +2133,8 @@ void tst_QStateMachine::eventTransitions() { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); QKeyEventTransition *trans = new QKeyEventTransition(&button, QEvent::KeyPress, Qt::Key_A); QCOMPARE(trans->eventType(), QEvent::KeyPress); @@ -2139,8 +2154,8 @@ void tst_QStateMachine::eventTransitions() } { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); QKeyEventTransition *trans = new QKeyEventTransition(); QCOMPARE(trans->eventObject(), (QObject*)0); @@ -2165,8 +2180,8 @@ void tst_QStateMachine::eventTransitions() // Multiple transitions for same (object,event) { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QState *s1 = new QState(machine.rootState()); + QState *s0 = new QState(&machine); + QState *s1 = new QState(&machine); QEventTransition *t0 = new QEventTransition(&button, QEvent::MouseButtonPress); t0->setTargetState(s1); s0->addTransition(t0); @@ -2213,9 +2228,9 @@ void tst_QStateMachine::eventTransitions() // multiple event transitions from same source { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); - QFinalState *s2 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); + QFinalState *s2 = new QFinalState(&machine); QEventTransition *t0 = new QEventTransition(&button, QEvent::MouseButtonPress); t0->setTargetState(s1); s0->addTransition(t0); @@ -2244,8 +2259,8 @@ void tst_QStateMachine::eventTransitions() // custom event { QStateMachine machine; - QState *s0 = new QState(machine.rootState()); - QFinalState *s1 = new QFinalState(machine.rootState()); + QState *s0 = new QState(&machine); + QFinalState *s1 = new QFinalState(&machine); QEventTransition *trans = new QEventTransition(&button, QEvent::Type(QEvent::User+1)); trans->setTargetState(s1); @@ -2263,7 +2278,7 @@ void tst_QStateMachine::historyStates() { for (int x = 0; x < 2; ++x) { QStateMachine machine; - QState *root = machine.rootState(); + QState *root = &machine; QState *s0 = new QState(root); QState *s00 = new QState(s0); QState *s01 = new QState(s0); @@ -2347,7 +2362,7 @@ void tst_QStateMachine::startAndStop() QCOMPARE(stoppedSpy.count(), 0); QCOMPARE(finishedSpy.count(), 0); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); machine.start(); QTRY_COMPARE(machine.isRunning(), true); @@ -2378,7 +2393,7 @@ void tst_QStateMachine::startAndStop() void tst_QStateMachine::targetStateWithNoParent() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->setObjectName("s1"); QState s2; s1->addTransition(&s2); @@ -2398,9 +2413,9 @@ void tst_QStateMachine::targetStateWithNoParent() void tst_QStateMachine::targetStateDeleted() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->setObjectName("s1"); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); QAbstractTransition *trans = s1->addTransition(s2); delete s2; QCOMPARE(trans->targetState(), (QAbstractState*)0); @@ -2415,13 +2430,13 @@ void tst_QStateMachine::defaultGlobalRestorePolicy() propertyHolder->setProperty("a", 1); propertyHolder->setProperty("b", 2); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(propertyHolder, "a", 3); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(propertyHolder, "b", 4); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); s1->addTransition(new EventTransition(QEvent::User, s2)); s2->addTransition(new EventTransition(QEvent::User, s3)); @@ -2450,11 +2465,12 @@ void tst_QStateMachine::noInitialStateForInitialState() { QStateMachine machine; - QState *initialState = new QState(machine.rootState()); + QState *initialState = new QState(&machine); initialState->setObjectName("initialState"); machine.setInitialState(initialState); QState *childState = new QState(initialState); + (void)childState; QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: " "Missing initial state in compound state 'initialState'"); @@ -2474,7 +2490,7 @@ void tst_QStateMachine::restorePolicyNotInherited() propertyHolder->setProperty("a", 1); propertyHolder->setProperty("b", 2); - QState *parentState = new QState(machine.rootState()); + QState *parentState = new QState(&machine); parentState->setObjectName("parentState"); parentState->setRestorePolicy(QState::RestoreProperties); @@ -2523,13 +2539,13 @@ void tst_QStateMachine::globalRestorePolicySetToDoNotRestore() propertyHolder->setProperty("a", 1); propertyHolder->setProperty("b", 2); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(propertyHolder, "a", 3); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(propertyHolder, "b", 4); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); s1->addTransition(new EventTransition(QEvent::User, s2)); s2->addTransition(new EventTransition(QEvent::User, s3)); @@ -2633,7 +2649,7 @@ void tst_QStateMachine::restorePolicyOnChildState() propertyHolder->setProperty("a", 1); propertyHolder->setProperty("b", 2); - QState *parentState = new QState(machine.rootState()); + QState *parentState = new QState(&machine); parentState->setObjectName("parentState"); QState *s1 = new QState(parentState); @@ -2684,13 +2700,13 @@ void tst_QStateMachine::globalRestorePolicySetToRestore() propertyHolder->setProperty("a", 1); propertyHolder->setProperty("b", 2); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->assignProperty(propertyHolder, "a", 3); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(propertyHolder, "b", 4); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); s1->addTransition(new EventTransition(QEvent::User, s2)); s2->addTransition(new EventTransition(QEvent::User, s3)); @@ -2723,19 +2739,19 @@ void tst_QStateMachine::mixedRestoreProperties() QObject *propertyHolder = new QObject(); propertyHolder->setProperty("a", 1); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); s1->setRestorePolicy(QState::RestoreProperties); s1->assignProperty(propertyHolder, "a", 3); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(propertyHolder, "a", 4); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); - QState *s4 = new QState(machine.rootState()); + QState *s4 = new QState(&machine); s4->assignProperty(propertyHolder, "a", 5); - QState *s5 = new QState(machine.rootState()); + QState *s5 = new QState(&machine); s5->setRestorePolicy(QState::RestoreProperties); s5->assignProperty(propertyHolder, "a", 6); @@ -2787,8 +2803,8 @@ void tst_QStateMachine::mixedRestoreProperties() void tst_QStateMachine::transitionWithParent() { QStateMachine machine; - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); + QState *s2 = new QState(&machine); EventTransition *trans = new EventTransition(QEvent::User, s2, s1); QCOMPARE(trans->sourceState(), s1); QCOMPARE(trans->targetState(), (QAbstractState*)s2); @@ -2803,8 +2819,8 @@ void tst_QStateMachine::simpleAnimation() QObject *object = new QObject(&machine); object->setProperty("fooBar", 1.0); - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); + QState *s2 = new QState(&machine); s2->assignProperty(object, "fooBar", 2.0); EventTransition *et = new EventTransition(QEvent::User, s2); @@ -2812,7 +2828,7 @@ void tst_QStateMachine::simpleAnimation() et->addAnimation(animation); s1->addTransition(et); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); s2->addTransition(animation, SIGNAL(finished()), s3); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); @@ -2847,8 +2863,8 @@ void tst_QStateMachine::twoAnimations() object->setProperty("foo", 1.0); object->setProperty("bar", 3.0); - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); s2->assignProperty(object, "bar", 10.0); @@ -2865,7 +2881,7 @@ void tst_QStateMachine::twoAnimations() et->addAnimation(animationBar); s1->addTransition(et); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(s2, SIGNAL(polished()), s3); @@ -2890,23 +2906,23 @@ void tst_QStateMachine::twoAnimatedTransitions() QObject *object = new QObject(&machine); object->setProperty("foo", 1.0); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 5.0); QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2); s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(fooAnimation, SIGNAL(finished()), s3); - QState *s4 = new QState(machine.rootState()); + QState *s4 = new QState(&machine); s4->assignProperty(object, "foo", 2.0); QPropertyAnimation *fooAnimation2 = new QPropertyAnimation(object, "foo", s4); s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation2); - QState *s5 = new QState(machine.rootState()); + QState *s5 = new QState(&machine); QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit())); s4->addTransition(fooAnimation2, SIGNAL(finished()), s5); @@ -2934,22 +2950,22 @@ void tst_QStateMachine::playAnimationTwice() QObject *object = new QObject(&machine); object->setProperty("foo", 1.0); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 5.0); QPropertyAnimation *fooAnimation = new QPropertyAnimation(object, "foo", s2); s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(fooAnimation); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(fooAnimation, SIGNAL(finished()), s3); - QState *s4 = new QState(machine.rootState()); + QState *s4 = new QState(&machine); s4->assignProperty(object, "foo", 2.0); s3->addTransition(new EventTransition(QEvent::User, s4))->addAnimation(fooAnimation); - QState *s5 = new QState(machine.rootState()); + QState *s5 = new QState(&machine); QObject::connect(s5, SIGNAL(entered()), QApplication::instance(), SLOT(quit())); s4->addTransition(fooAnimation, SIGNAL(finished()), s5); @@ -2980,8 +2996,8 @@ void tst_QStateMachine::nestedTargetStateForAnimation() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); @@ -3008,7 +3024,7 @@ void tst_QStateMachine::nestedTargetStateForAnimation() connect(animation, SIGNAL(finished()), &counter, SLOT(slot())); at->addAnimation(animation); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); s2->addTransition(s2Child, SIGNAL(polished()), s3); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); @@ -3036,13 +3052,13 @@ void tst_QStateMachine::animatedGlobalRestoreProperty() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); - QState *s2 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); - QState *s4 = new QState(machine.rootState()); + QState *s4 = new QState(&machine); QObject::connect(s4, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3080,16 +3096,16 @@ void tst_QStateMachine::specificTargetValueOfAnimation() QObject *object = new QObject(&machine); object->setProperty("foo", 1.0); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); QPropertyAnimation *anim = new QPropertyAnimation(object, "foo"); anim->setEndValue(10.0); s1->addTransition(new EventTransition(QEvent::User, s2))->addAnimation(anim); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s2->addTransition(anim, SIGNAL(finished()), s3); @@ -3103,6 +3119,8 @@ void tst_QStateMachine::specificTargetValueOfAnimation() QVERIFY(machine.configuration().contains(s3)); QCOMPARE(object->property("foo").toDouble(), 2.0); QCOMPARE(anim->endValue().toDouble(), 10.0); + + delete anim; } void tst_QStateMachine::addDefaultAnimation() @@ -3112,12 +3130,12 @@ void tst_QStateMachine::addDefaultAnimation() QObject *object = new QObject(); object->setProperty("foo", 1.0); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3135,6 +3153,8 @@ void tst_QStateMachine::addDefaultAnimation() QVERIFY(machine.configuration().contains(s3)); QCOMPARE(object->property("foo").toDouble(), 2.0); + + delete object; } void tst_QStateMachine::addDefaultAnimationWithUnusedAnimation() @@ -3147,12 +3167,12 @@ void tst_QStateMachine::addDefaultAnimationWithUnusedAnimation() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3214,6 +3234,9 @@ void tst_QStateMachine::removeDefaultAnimation() machine.removeDefaultAnimation(anim2); QCOMPARE(machine.defaultAnimations().size(), 0); + + delete anim; + delete anim2; } void tst_QStateMachine::overrideDefaultAnimationWithSpecific() @@ -3225,13 +3248,13 @@ void tst_QStateMachine::overrideDefaultAnimationWithSpecific() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3254,6 +3277,9 @@ void tst_QStateMachine::overrideDefaultAnimationWithSpecific() QVERIFY(machine.configuration().contains(s3)); QCOMPARE(counter.counter, 2); // specific animation started and stopped + + delete defaultAnimation; + delete moreSpecificAnimation; } /* @@ -3264,12 +3290,12 @@ void tst_QStateMachine::addDefaultAnimationForSource() QObject *object = new QObject(); object->setProperty("foo", 1.0); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3296,12 +3322,12 @@ void tst_QStateMachine::addDefaultAnimationForTarget() QObject *object = new QObject(); object->setProperty("foo", 1.0); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3325,88 +3351,88 @@ void tst_QStateMachine::removeDefaultAnimationForSource() { QStateMachine machine; - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0); QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); - machine.addDefaultAnimationForSourceState(machine.rootState(), anim); + machine.addDefaultAnimationForSourceState(&machine, anim); QCOMPARE(machine.defaultAnimations().size(), 0); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); - QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim)); - machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + machine.removeDefaultAnimationForTargetState(&machine, anim); QCOMPARE(machine.defaultAnimations().size(), 0); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); - QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim)); - machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + machine.removeDefaultAnimationForSourceState(&machine, anim); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0); - machine.addDefaultAnimationForSourceState(machine.rootState(), anim); + machine.addDefaultAnimationForSourceState(&machine, anim); QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); - machine.addDefaultAnimationForSourceState(machine.rootState(), anim2); + machine.addDefaultAnimationForSourceState(&machine, anim2); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 2); - QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim)); - QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim2)); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 2); + QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim)); + QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim2)); - machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + machine.removeDefaultAnimationForSourceState(&machine, anim); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 1); - QVERIFY(machine.defaultAnimationsForSourceState(machine.rootState()).contains(anim2)); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 1); + QVERIFY(machine.defaultAnimationsForSourceState(&machine).contains(anim2)); - machine.removeDefaultAnimationForSourceState(machine.rootState(), anim2); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); + machine.removeDefaultAnimationForSourceState(&machine, anim2); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0); } void tst_QStateMachine::removeDefaultAnimationForTarget() { QStateMachine machine; - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0); QPropertyAnimation *anim = new QPropertyAnimation(this, "foo"); - machine.addDefaultAnimationForTargetState(machine.rootState(), anim); + machine.addDefaultAnimationForTargetState(&machine, anim); QCOMPARE(machine.defaultAnimations().size(), 0); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); - QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim)); - machine.removeDefaultAnimationForSourceState(machine.rootState(), anim); + machine.removeDefaultAnimationForSourceState(&machine, anim); QCOMPARE(machine.defaultAnimations().size(), 0); - QCOMPARE(machine.defaultAnimationsForSourceState(machine.rootState()).size(), 0); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); - QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); + QCOMPARE(machine.defaultAnimationsForSourceState(&machine).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim)); - machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + machine.removeDefaultAnimationForTargetState(&machine, anim); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0); - machine.addDefaultAnimationForTargetState(machine.rootState(), anim); + machine.addDefaultAnimationForTargetState(&machine, anim); QPropertyAnimation *anim2 = new QPropertyAnimation(this, "foo"); - machine.addDefaultAnimationForTargetState(machine.rootState(), anim2); + machine.addDefaultAnimationForTargetState(&machine, anim2); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 2); - QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim)); - QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim2)); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 2); + QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim)); + QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim2)); - machine.removeDefaultAnimationForTargetState(machine.rootState(), anim); + machine.removeDefaultAnimationForTargetState(&machine, anim); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 1); - QVERIFY(machine.defaultAnimationsForTargetState(machine.rootState()).contains(anim2)); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 1); + QVERIFY(machine.defaultAnimationsForTargetState(&machine).contains(anim2)); - machine.removeDefaultAnimationForTargetState(machine.rootState(), anim2); - QCOMPARE(machine.defaultAnimationsForTargetState(machine.rootState()).size(), 0); + machine.removeDefaultAnimationForTargetState(&machine, anim2); + QCOMPARE(machine.defaultAnimationsForTargetState(&machine).size(), 0); } void tst_QStateMachine::overrideDefaultAnimationWithSource() @@ -3418,13 +3444,13 @@ void tst_QStateMachine::overrideDefaultAnimationWithSource() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3458,13 +3484,13 @@ void tst_QStateMachine::overrideDefaultAnimationWithTarget() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3499,13 +3525,13 @@ void tst_QStateMachine::overrideDefaultSourceAnimationWithSpecific() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3539,13 +3565,13 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSpecific() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); QAbstractTransition *at = s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3579,13 +3605,13 @@ void tst_QStateMachine::overrideDefaultTargetAnimationWithSource() SlotCalledCounter counter; - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(object, "foo", 2.0); - QState *s3 = new QState(machine.rootState()); + QState *s3 = new QState(&machine); QObject::connect(s3, SIGNAL(entered()), QCoreApplication::instance(), SLOT(quit())); s1->addTransition(new EventTransition(QEvent::User, s2)); @@ -3621,10 +3647,10 @@ void tst_QStateMachine::parallelStateAssignmentsDone() propertyHolder->setProperty("bar", 456); propertyHolder->setProperty("zoot", 789); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); + QState *parallelState = new QState(QState::ParallelStates, &machine); parallelState->assignProperty(propertyHolder, "foo", 321); QState *s2 = new QState(parallelState); @@ -3653,10 +3679,10 @@ void tst_QStateMachine::transitionsFromParallelStateWithNoChildren() { QStateMachine machine; - QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); + QState *parallelState = new QState(QState::ParallelStates, &machine); machine.setInitialState(parallelState); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); parallelState->addTransition(new EventTransition(QEvent::User, s1)); machine.start(); @@ -3677,7 +3703,7 @@ void tst_QStateMachine::parallelStateTransition() { QStateMachine machine; - QState *parallelState = new QState(QState::ParallelStates, machine.rootState()); + QState *parallelState = new QState(QState::ParallelStates, &machine); machine.setInitialState(parallelState); QState *s1 = new QState(parallelState); @@ -3726,10 +3752,10 @@ void tst_QStateMachine::nestedRestoreProperties() propertyHolder->setProperty("foo", 1); propertyHolder->setProperty("bar", 2); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(propertyHolder, "foo", 3); QState *s21 = new QState(s2); @@ -3778,10 +3804,10 @@ void tst_QStateMachine::nestedRestoreProperties2() propertyHolder->setProperty("foo", 1); propertyHolder->setProperty("bar", 2); - QState *s1 = new QState(machine.rootState()); + QState *s1 = new QState(&machine); machine.setInitialState(s1); - QState *s2 = new QState(machine.rootState()); + QState *s2 = new QState(&machine); s2->assignProperty(propertyHolder, "foo", 3); QState *s21 = new QState(s2); @@ -3833,6 +3859,46 @@ void tst_QStateMachine::nestedRestoreProperties2() } +void tst_QStateMachine::nestedStateMachines() +{ + QStateMachine machine; + QState *group = new QState(&machine); + group->setChildMode(QState::ParallelStates); + QStateMachine *subMachines[3]; + for (int i = 0; i < 3; ++i) { + QState *subGroup = new QState(group); + QStateMachine *subMachine = new QStateMachine(subGroup); + { + QState *initial = new QState(subMachine); + QFinalState *done = new QFinalState(subMachine); + initial->addTransition(new EventTransition(QEvent::User, done)); + subMachine->setInitialState(initial); + } + QFinalState *subMachineDone = new QFinalState(subGroup); + subMachine->addTransition(subMachine, SIGNAL(finished()), subMachineDone); + subGroup->setInitialState(subMachine); + subMachines[i] = subMachine; + } + QFinalState *final = new QFinalState(&machine); + group->addTransition(group, SIGNAL(finished()), final); + machine.setInitialState(group); + + QSignalSpy startedSpy(&machine, SIGNAL(started())); + QSignalSpy finishedSpy(&machine, SIGNAL(finished())); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 1); + QTRY_COMPARE(machine.configuration().count(), 1+2*3); + QVERIFY(machine.configuration().contains(group)); + for (int i = 0; i < 3; ++i) + QVERIFY(machine.configuration().contains(subMachines[i])); + + QCoreApplication::processEvents(); // starts the submachines + + for (int i = 0; i < 3; ++i) + subMachines[i]->postEvent(new QEvent(QEvent::User)); + + QTRY_COMPARE(finishedSpy.count(), 1); +} QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" diff --git a/tests/auto/qtextcodec/tst_qtextcodec.cpp b/tests/auto/qtextcodec/tst_qtextcodec.cpp index f2da1ec..9f51805 100644 --- a/tests/auto/qtextcodec/tst_qtextcodec.cpp +++ b/tests/auto/qtextcodec/tst_qtextcodec.cpp @@ -1875,6 +1875,9 @@ void tst_QTextCodec::codecForUtfText() #ifdef Q_OS_UNIX void tst_QTextCodec::toLocal8Bit() { +#ifdef QT_NO_PROCESS + QSKIP("This test requires QProcess", SkipAll); +#else QProcess process; process.start("echo/echo"); QString string(QChar(0x410)); @@ -1884,6 +1887,7 @@ void tst_QTextCodec::toLocal8Bit() process.waitForFinished(); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); +#endif } #endif diff --git a/tests/auto/qtoolbar/tst_qtoolbar.cpp b/tests/auto/qtoolbar/tst_qtoolbar.cpp index 002ea04..856a935 100644 --- a/tests/auto/qtoolbar/tst_qtoolbar.cpp +++ b/tests/auto/qtoolbar/tst_qtoolbar.cpp @@ -797,8 +797,8 @@ void tst_QToolBar::toolButtonStyle() QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonTextUnderIcon); QCOMPARE(spy.count(), 0); - tb.setToolButtonStyle(Qt::ToolButtonSystemDefault); - QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonSystemDefault); + tb.setToolButtonStyle(Qt::ToolButtonFollowStyle); + QCOMPARE(tb.toolButtonStyle(), Qt::ToolButtonFollowStyle); QCOMPARE(spy.count(), 1); } diff --git a/tests/auto/qurl/tst_qurl.cpp b/tests/auto/qurl/tst_qurl.cpp index 723f882..78ea146 100644 --- a/tests/auto/qurl/tst_qurl.cpp +++ b/tests/auto/qurl/tst_qurl.cpp @@ -162,6 +162,8 @@ private slots: void nameprep_testsuite(); void ace_testsuite_data(); void ace_testsuite(); + void std3violations_data(); + void std3violations(); void tldRestrictions_data(); void tldRestrictions(); void emptyQueryOrFragment(); @@ -3059,7 +3061,8 @@ void tst_QUrl::nameprep_testsuite_data() #ifdef QT_BUILD_INTERNAL QT_BEGIN_NAMESPACE -extern QString qt_nameprep(const QString &source); +extern void qt_nameprep(QString *source, int from); +extern bool qt_check_std3rules(const QChar *, int); QT_END_NAMESPACE #endif @@ -3084,7 +3087,8 @@ void tst_QUrl::nameprep_testsuite() "Investigate further", Continue); QEXPECT_FAIL("Larger test (expanding)", "Investigate further", Continue); - QCOMPARE(qt_nameprep(in), out); + qt_nameprep(&in, 0); + QCOMPARE(in, out); #endif } @@ -3100,6 +3104,11 @@ void tst_QUrl::ace_testsuite_data() QTest::newRow("ascii-upper") << "FLUKE" << "fluke" << "fluke" << "fluke"; QTest::newRow("asciifolded") << QString::fromLatin1("stra\337e") << "strasse" << "." << "strasse"; + QTest::newRow("asciifolded-dotcom") << QString::fromLatin1("stra\337e.example.com") << "strasse.example.com" << "." << "strasse.example.com"; + QTest::newRow("greek-mu") << QString::fromLatin1("\265V") + <<"xn--v-lmb" + << "." + << QString::fromUtf8("\316\274v"); QTest::newRow("non-ascii-lower") << QString::fromLatin1("alqualond\353") << "xn--alqualond-34a" @@ -3132,6 +3141,9 @@ void tst_QUrl::ace_testsuite_data() QTest::newRow("idn-upper") << "XN--ALQUALOND-34A" << "xn--alqualond-34a" << QString::fromLatin1("alqualond\353") << QString::fromLatin1("alqualond\353"); + + QTest::newRow("separator-3002") << QString::fromUtf8("example\343\200\202com") + << "example.com" << "." << "example.com"; } void tst_QUrl::ace_testsuite() @@ -3142,23 +3154,83 @@ void tst_QUrl::ace_testsuite() QFETCH(QString, fromace); QFETCH(QString, unicode); - QString domain = in + canonsuffix; - QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + canonsuffix); + const char *suffix = canonsuffix; + if (toace.contains('.')) + suffix = 0; + + QString domain = in + suffix; + QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + suffix); if (fromace != ".") - QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + canonsuffix); - QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + canonsuffix); + QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + suffix); + QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + suffix); - domain = in + ".troll.No"; - QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + canonsuffix); + domain = in + (suffix ? ".troll.No" : ""); + QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + suffix); if (fromace != ".") - QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + canonsuffix); - QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + canonsuffix); + QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + suffix); + QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + suffix); - domain = in + ".troll.NO"; - QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + canonsuffix); + domain = in + (suffix ? ".troll.NO" : ""); + QCOMPARE(QString::fromLatin1(QUrl::toAce(domain)), toace + suffix); if (fromace != ".") - QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + canonsuffix); - QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + canonsuffix); + QCOMPARE(QUrl::fromAce(domain.toLatin1()), fromace + suffix); + QCOMPARE(QUrl::fromAce(QUrl::toAce(domain)), unicode + suffix); +} + +void tst_QUrl::std3violations_data() +{ + QTest::addColumn<QString>("source"); + QTest::addColumn<bool>("validUrl"); + + QTest::newRow("too-long") << "this-domain-is-far-too-long-for-its-own-good-and-should-have-been-limited-to-63-chars" << false; + QTest::newRow("dash-begin") << "-x-foo" << false; + QTest::newRow("dash-end") << "x-foo-" << false; + QTest::newRow("dash-begin-end") << "-foo-" << false; + + QTest::newRow("control") << "\033foo" << false; + QTest::newRow("bang") << "foo!" << false; + QTest::newRow("plus") << "foo+bar" << false; + QTest::newRow("dot") << "foo.bar"; + QTest::newRow("slash") << "foo/bar" << true; + QTest::newRow("colon") << "foo:80" << true; + QTest::newRow("question") << "foo?bar" << true; + QTest::newRow("at") << "foo@bar" << true; + QTest::newRow("backslash") << "foo\\bar" << false; + QTest::newRow("underline") << "foo_bar" << false; + + // these characters are transformed by NFKC to non-LDH characters + QTest::newRow("dot-like") << QString::fromUtf8("foo\342\200\244bar") << false; // U+2024 ONE DOT LEADER + QTest::newRow("slash-like") << QString::fromUtf8("foo\357\274\217bar") << false; // U+FF0F FULLWIDTH SOLIDUS + + // The following should be invalid but isn't + // the DIVISON SLASH doesn't case-fold to a slash + // is this a problem with RFC 3490? + //QTest::newRow("slash-like2") << QString::fromUtf8("foo\342\210\225bar") << false; // U+2215 DIVISION SLASH +} + +void tst_QUrl::std3violations() +{ + QFETCH(QString, source); + + { + QString prepped = source; + qt_nameprep(&prepped, 0); + QVERIFY(!qt_check_std3rules(prepped.constData(), prepped.length())); + } + + if (source.contains('.')) + return; // this test ends here + + QUrl url; + url.setHost(source); + QVERIFY(url.host().isEmpty()); + + QFETCH(bool, validUrl); + if (validUrl) + return; // test ends here for these cases + + url = QUrl("http://" + source + "/some/path"); + QVERIFY(!url.isValid()); } void tst_QUrl::tldRestrictions_data() diff --git a/tests/auto/test.pl b/tests/auto/test.pl index 9fd5c9d..a9e3da8 100755 --- a/tests/auto/test.pl +++ b/tests/auto/test.pl @@ -1,4 +1,4 @@ -#!/usr/bin/perl +#!/usr/bin/env perl use strict; use Cwd; diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index a899adb..61daca8 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -3109,6 +3109,7 @@ void Configure::buildQmake() void Configure::buildHostTools() { + dictionary[ "DONE" ] = "yes"; if (!dictionary.contains("XQMAKESPEC")) return; @@ -3332,7 +3333,6 @@ void Configure::generateMakefiles() } else { cout << "Processing of project files have been disabled." << endl; cout << "Only use this option if you really know what you're doing." << endl << endl; - dictionary[ "DONE" ] = "yes"; return; } } diff --git a/tools/configure/main.cpp b/tools/configure/main.cpp index 0e13c7a..e5c04cc 100644 --- a/tools/configure/main.cpp +++ b/tools/configure/main.cpp @@ -95,7 +95,7 @@ int runConfigure( int argc, char** argv ) #endif if( !app.isDone() ) app.generateMakefiles(); - if( !app.isDone() && app.isOk() ) + if( !app.isDone() ) app.buildHostTools(); if( !app.isDone() ) app.showSummary(); diff --git a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp index fb1a5bb..ca55b15 100644 --- a/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp +++ b/tools/designer/src/components/propertyeditor/designerpropertymanager.cpp @@ -254,8 +254,11 @@ void TextEditor::resourceActionActivated() { QString oldPath = m_editor->text(); if (oldPath.startsWith(QLatin1String("qrc:"))) - oldPath = oldPath.mid(4); - const QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); + oldPath.remove(0, 4); + // returns ':/file' + QString newPath = IconSelector::choosePixmapResource(m_core, m_core->resourceModel(), oldPath, this); + if (newPath.startsWith(QLatin1Char(':'))) + newPath.remove(0, 1); if (newPath.isEmpty() || newPath == oldPath) return; const QString newText = QLatin1String("qrc:") + newPath; diff --git a/tools/linguist/shared/profileevaluator.cpp b/tools/linguist/shared/profileevaluator.cpp index 9a27eb0..5a9095a 100644 --- a/tools/linguist/shared/profileevaluator.cpp +++ b/tools/linguist/shared/profileevaluator.cpp @@ -256,7 +256,7 @@ public: ProFile *m_prevProFile; // See m_prevLineNo }; -#if !defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) +#if (!defined(__GNUC__) || __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3)) && !defined(__SUNPRO_CC) Q_DECLARE_TYPEINFO(ProFileEvaluator::Private::State, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(ProFileEvaluator::Private::ProLoop, Q_MOVABLE_TYPE); #endif diff --git a/tools/linguist/shared/profileevaluator.h b/tools/linguist/shared/profileevaluator.h index 88b7590..f3498c1 100644 --- a/tools/linguist/shared/profileevaluator.h +++ b/tools/linguist/shared/profileevaluator.h @@ -96,7 +96,7 @@ private: class Private; Private *d; - // This doesn't help gcc 3.3 ... + // This doesn't help gcc 3.3 and sunpro ... template<typename T> friend class QTypeInfo; }; diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index c007b9b..e31f6cf 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -294,6 +294,7 @@ void HtmlGenerator::generateTree(const Tree *tree, CodeMarker *marker) nonCompatClasses.clear(); mainClasses.clear(); compatClasses.clear(); + obsoleteClasses.clear(); moduleClassMap.clear(); moduleNamespaceMap.clear(); funcIndex.clear(); @@ -381,7 +382,7 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::AutoLink: if (!inLink && !inContents && !inSectionHeading) { const Node *node = 0; - QString link = getLink(atom, relative, marker, node); + QString link = getLink(atom, relative, marker, &node); if (!link.isEmpty()) { beginLink(link, node, relative, marker); generateLink(atom, relative, marker); @@ -567,6 +568,9 @@ int HtmlGenerator::generateAtom(const Atom *atom, else if (atom->string() == "compatclasses") { generateCompactList(relative, marker, compatClasses); } + else if (atom->string() == "obsoleteclasses") { + generateCompactList(relative, marker, obsoleteClasses); + } else if (atom->string() == "functionindex") { generateFunctionIndex(relative, marker); } @@ -648,11 +652,12 @@ int HtmlGenerator::generateAtom(const Atom *atom, case Atom::Link: { const Node *node = 0; - QString myLink = getLink(atom, relative, marker, node); - if (myLink.isEmpty()) + QString myLink = getLink(atom, relative, marker, &node); + if (myLink.isEmpty()) { relative->doc().location().warning(tr("Cannot link to '%1' in %2") .arg(atom->string()) .arg(marker->plainFullName(relative))); + } beginLink(myLink, node, relative, marker); skipAhead = 1; } @@ -3261,6 +3266,9 @@ void HtmlGenerator::findAllClasses(const InnerNode *node) if ((*c)->status() == Node::Compat) { compatClasses.insert(className, *c); } + else if ((*c)->status() == Node::Obsolete) { + obsoleteClasses.insert(className, *c); + } else { nonCompatClasses.insert(className, *c); if ((*c)->status() == Node::Main) @@ -3457,10 +3465,10 @@ const QPair<QString,QString> HtmlGenerator::anchorForNode(const Node *node) QString HtmlGenerator::getLink(const Atom *atom, const Node *relative, CodeMarker *marker, - const Node *node) + const Node** node) { QString link; - node = 0; + *node = 0; if (atom->string().contains(":") && (atom->string().startsWith("file:") @@ -3484,40 +3492,74 @@ QString HtmlGenerator::getLink(const Atom *atom, QString first = path.first().trimmed(); if (first.isEmpty()) { - node = relative; + *node = relative; } else if (first.endsWith(".html")) { - node = tre->root()->findNode(first, Node::Fake); + *node = tre->root()->findNode(first, Node::Fake); } else { - node = marker->resolveTarget(first, tre, relative); - if (!node) - node = tre->findFakeNodeByTitle(first); - if (!node) - node = tre->findUnambiguousTarget(first, targetAtom); + *node = marker->resolveTarget(first, tre, relative); + if (!*node) + *node = tre->findFakeNodeByTitle(first); + if (!*node) + *node = tre->findUnambiguousTarget(first, targetAtom); } - if (node) { - if (!node->url().isEmpty()) - return node->url(); + if (*node) { + if (!(*node)->url().isEmpty()) + return (*node)->url(); else path.removeFirst(); } else { - node = relative; + *node = relative; + } + + if (*node) { + if ((*node)->status() == Node::Obsolete) { + if (relative) { + if (relative->parent() != *node) { + if (relative->status() != Node::Obsolete) { + relative->doc().location().warning(tr("Link to obsolete item '%1' in %2") + .arg(atom->string()) + .arg(marker->plainFullName(relative))); +#if 0 + qDebug() << "Link to Obsolete entity" + << (*node)->name(); + qDebug() << " relative entity" + << relative->name(); +#endif + } + } + } + else { + qDebug() << "Link to Obsolete entity" + << (*node)->name() << "no relative"; + } + } +#if 0 + else if ((*node)->status() == Node::Deprecated) { + qDebug() << "Link to Deprecated entity"; + } + else if ((*node)->status() == Node::Internal) { + qDebug() << "Link to Internal entity"; + } + //else + //qDebug() << "Node Status:" << (*node)->status(); +#endif } while (!path.isEmpty()) { - targetAtom = tre->findTarget(path.first(), node); + targetAtom = tre->findTarget(path.first(), *node); if (targetAtom == 0) break; path.removeFirst(); } if (path.isEmpty()) { - link = linkForNode(node, relative); + link = linkForNode(*node, relative); if (targetAtom) - link += "#" + refForAtom(targetAtom, node); + link += "#" + refForAtom(targetAtom, *node); } } return link; diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h index dc5e5cf..a7f4009 100644 --- a/tools/qdoc3/htmlgenerator.h +++ b/tools/qdoc3/htmlgenerator.h @@ -202,7 +202,7 @@ class HtmlGenerator : public PageGenerator virtual QString getLink(const Atom *atom, const Node *relative, CodeMarker *marker, - const Node *node = 0); + const Node** node); virtual void generateDcf(const QString &fileBase, const QString &startPage, const QString &title, DcfSection &dcfRoot); @@ -256,6 +256,7 @@ class HtmlGenerator : public PageGenerator QMap<QString, const Node *> nonCompatClasses; QMap<QString, const Node *> mainClasses; QMap<QString, const Node *> compatClasses; + QMap<QString, const Node *> obsoleteClasses; QMap<QString, const Node *> namespaceIndex; QMap<QString, const Node *> serviceClasses; #ifdef QDOC_QML diff --git a/tools/qdoc3/qdoc3.pro b/tools/qdoc3/qdoc3.pro index 1291272..49a16e6 100644 --- a/tools/qdoc3/qdoc3.pro +++ b/tools/qdoc3/qdoc3.pro @@ -7,10 +7,11 @@ DEFINES += QT_NO_CAST_TO_ASCII QT = core xml CONFIG += console CONFIG -= debug_and_release_target -CONFIG += debug +#CONFIG += debug build_all:!build_pass { CONFIG -= build_all - CONFIG += debug + CONFIG += release +# CONFIG += debug } mac:CONFIG -= app_bundle HEADERS += apigenerator.h \ diff --git a/tools/qtestlib/wince/cetest/bootstrapped.pri b/tools/qtestlib/wince/cetest/bootstrapped.pri index 39f24c2..a31374e 100644 --- a/tools/qtestlib/wince/cetest/bootstrapped.pri +++ b/tools/qtestlib/wince/cetest/bootstrapped.pri @@ -35,4 +35,5 @@ SOURCES += \ $$QT_SOURCE_TREE/src/corelib/tools/qmap.cpp \ $$QT_SOURCE_TREE/src/corelib/tools/qbitarray.cpp \ $$QT_SOURCE_TREE/src/corelib/kernel/qmetatype.cpp \ - $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp + $$QT_SOURCE_TREE/src/corelib/kernel/qvariant.cpp \ + $$QT_SOURCE_TREE/src/corelib/codecs/qutfcodec.cpp |