diff options
40 files changed, 465 insertions, 249 deletions
diff --git a/demos/declarative/declarative.pro b/demos/declarative/declarative.pro index aa60db0..2963386 100644 --- a/demos/declarative/declarative.pro +++ b/demos/declarative/declarative.pro @@ -12,7 +12,9 @@ sources.files = \ samegame \ snake \ twitter \ + rssnews \ webbrowser + sources.path = $$[QT_INSTALL_DEMOS]/declarative INSTALLS += sources diff --git a/dist/changes-4.6.3 b/dist/changes-4.6.3 index d8e9fb4..08db0bb 100644 --- a/dist/changes-4.6.3 +++ b/dist/changes-4.6.3 @@ -40,14 +40,85 @@ Optimizations QtCore ------ - - foo - * bar + - QStateMachine + * [QTBUG-8842] Ensure history configuration is cleared when a state + machine is restarted + - QXmlStreamReader + * [QTBUG-9196] fixed crash when parsing QtGui ----- - - foo - * bar + - QPainter + * [QTBUG-10421] Fixed WebKit-specific justification bug for text containing + more than one script. + + - QRegion + * [QTBUG-7699] Prevented crash on large x-coordinates. + + - QTextEdit + * [QTBUG-9599] Fixed crash when copying the current text cursor as a result + of deleting a character. + + - QTextEngine + * [QTBUG-9374] Fixed possible crash in QTextEngine::boundingBox() when using + multiscripted text. + + - QTextLayout + * [QTBUG-9074] Fixed performance regression that was introduced in Qt 4.6.0. + + - QTransform + * [QTBUG-8557] Fixed bug in QTransform::type() potentially occuring + after using operator/ or operator* or their overloads. + + - Improved scrolling horizontally with a mouse wheel over sliders. + - [QTBUG-7451] Gestures respect panels on QGraphicsView. + + - QCUPSSupport + * [QTBUG-10512] Fixed a potential crash with misconfigured CUPS printers. + * [QTBUG-6419] Make QCUPSSupport::printerHasPPD() release temporary file + handles. + + - QPDFBaseEngine + * [QTBUG-8451] Fixed line and point drawing in the PS and PDF generators. + + - QTextDocument + * [QTBUG-10301] Fixed a leak in QTextDocument::print(). + + - QFontEngine + * [QTBUG-3976] Fixed a leak for QFont objects used in threads. + + - QPSPrintEngine + * [QTBUG-10121] Fixed incorrect version setting for EPS files. + * [QTBUG-10140] Fixed generation of the %%BoundingBox operator to output + integer values instead of floating point values. + + - QWin32PrintEngine + * [QTBUG-9938] Fixed a crash on Windows 7 systems with invalid PrinterPorts + registry entries. + + - QTriangulatingStroker + * [QTBUG-9548] Fixed possible data corruption when certain paths were triangulated. + + - QRasterPaintEngine + * [QTBUG-9036] Fixed ClearType text rendering on translucent surfaces under Windows. + + - QPixmap + * [QTBUG-8606] Fixed QPixmap::load() to not modify referenced copies. + + - QPainter + * [QTBUG-8140] Speed up custom bitmap bruses under X11 without Xrender support. + * [QTBUG-8032] Fixed drawing pixmaps onto bitmaps on X11 without Xrender support. + + - QImageReader + * [QTBUG-7980] Fixed QImageReader::setAutoDetectImageFormat() to work with plugins. + + - QGifHandler + * [QTBUG-7037] Fixed QGifHandler::loopCount(). + * [QTBUG-6696] Cache the sizes of images in an animated GIF. + + - qDrawPixmaps() + * [QTBUG-8455] Fixed qDrawPixmaps() to draw on integer coordinates under Mac OS X. QtDBus ------ @@ -64,14 +135,47 @@ QtNetwork QtOpenGL -------- - - foo - * bar + - QOpenGLPaintEngine + * [QTBUG-10529] Fixed an issue where bound pixmaps were not released correctly + in the GL 1 engine. + + - QGL2PaintEngineEx + * [QTBUG-8681] Fixed an application exit crash that could occur in + the GL2 engine under X11. + + - QGLWidget + * [QTBUG-7545] Fixed QGLWidget::grabFrameBuffer() to honor the 'withAlpha' flag. + * [QTBUG-8054] Fixed drawing QPixmaps onto QGLWidgets on different X11 screens. + * [QTBUG-7865] Fixed bug where GL widgets were not fully updated on + Windows Vista/7 with Aero disabled. + * [QTBUG-8753] Worked around driver bug causing clipping errors on the N900. + * [QTBUG-10510] Workaround ATI driver bug when using QGraphicsEffect with GL. + + - QGLContext + * [QTBUG-5732] Fixed a GLX warning that occured with some Intel chipsets under X11. + + - QGLPixelBuffer + * [QTBUG-8047] Fixed usage of QGLPixelBuffer with share widgets on other X11 screens. QtScript -------- - - foo - * bar + - [QTBUG-7066] Fixed regression introduced in 4.6.0 that made it not + possible to change the prototype of the global object + - [QTBUG-8366] Fixed regression introduced in 4.6.0 that caused the + instanceof operator to throw an error when the right-hand-side is + generated by QScriptEngine::newQMetaObject() + - [QTBUG-8400] Fixed memory leak when lazily binding QScriptValue to an + engine + - [QTBUG-9775] Fixed regression introduced in 4.6.0 that caused the + qsTr() function not to resolve the translation context correctly when + invoked in the global scope + - QScriptClass + * [QTBUG-8364] Fixed regression introduced in 4.6.0 that could cause + the Callable extension to crash + - QScriptEngine + * [QTBUG-6437] Fixed regression introduced in 4.6.0 that made + installTranslatorFunctions() not work with custom global object QtSql ----- @@ -82,8 +186,13 @@ QtSql QtXml ----- - - foo - * bar + - [QTBUG-8398] QDom: prevent infinite loop when cloning a DTD + +QtXmlPatterns +------------- +- [QTBUG-8920] fixed crash with anonymous types in XsdSchemaChecker +- [QTBUG-8394] include/import/redefine schemas only once +- QXmlSchema: fix crash with referencing elements Qt Plugins ---------- @@ -106,17 +215,21 @@ Third party components Qt for Unix (X11 and Mac OS X) ------------------------------ - - + - Qt for Linux/X11 ---------------- - - + - [MR 458] Improved handling of Shift-Tab with VNC on X11. + - [QTBUG-7063] Changed key bindings (XF86XK_MyComputer, Qt::Key_Launch0, + Key_Calculator) on X11 back to how it was in Qt 4.5 before MR 1742 + accidentally changed it. Qt for Windows -------------- - - + - [QTBUG-6007] On Windows we query if there is a touch screen and do not try + to enable gestures otherwise. Qt for Mac OS X --------------- diff --git a/dist/changes-4.7.0 b/dist/changes-4.7.0 index a57575e..dff20dd 100644 --- a/dist/changes-4.7.0 +++ b/dist/changes-4.7.0 @@ -232,7 +232,6 @@ Qt for Windows * Pipe handle leak fixed, when closing a QLocalSocket that still has unwritten data. (QTBUG-7815) * Fixed closing state for local sockets with unwritten data. (QTBUG-9681) - * Detection of Windows mobile 6.5 fixed. (QTBUG-8418) * Improved performance of writing to QLocalSocket. @@ -260,6 +259,7 @@ Qt for Windows CE * Huge performance penalty for QTabWidget fixed for Windows mobile 6.5. (QTBUG-8419) * QTabBar scroll button size has been fixed. (QTBUG-8757) + * Detection of Windows mobile 6.5 fixed. (QTBUG-8418) diff --git a/doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp b/doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp index 4f27661..81099a7 100644 --- a/doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp +++ b/doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp @@ -271,3 +271,9 @@ class QGraphicsPathItem : public QAbstractGraphicsShapeItem }; //! [18] +//! [19] +QTransform xform = item->deviceTransform(view->viewportTransform()); +QRect deviceRect = xform.mapRect(rect).toAlignedRect(); +view->viewport()->scroll(dx, dy, deviceRect); +//! [19] + diff --git a/examples/declarative/README b/examples/declarative/README new file mode 100644 index 0000000..9e0f4c4 --- /dev/null +++ b/examples/declarative/README @@ -0,0 +1,41 @@ +The Qt Declarative module provides the ability to specify and implement +your UI declaratively, using the Qt Meta-Object Language(QML). This +language is very expressive and human readable, and can be used by +designers to actually implement their UI vision. QML UIs can integrate +with C++ code in many ways, including being loaded as a part of a C++ UI +and loading data models from C++ and interacting with them. + +The example launcher provided with Qt can be used to explore each of the +examples in this directory. But most can also be viewed directly with the +QML viewer utility, without requiring compilation. + +Documentation for these examples can be found via the Tutorial and Examples +link in the main Qt documentation. + + +Finding the Qt Examples and Demos launcher +========================================== + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Qt Examples and Demos" entry in the submenu containing +the Qt tools. + +On Mac OS X: + +For the binary distribution, the qtdemo executable is installed in the +/Developer/Applications/Qt directory. For the source distribution, it is +installed alongside the other Qt tools on the path specified when Qt is +configured. + +On Unix/Linux: + +The qtdemo executable is installed alongside the other Qt tools on the path +specified when Qt is configured. + +On all platforms: + +The source code for the launcher can be found in the demos/qtdemo directory +in the Qt package. This example is built at the same time as the Qt libraries, +tools, examples, and demonstrations. diff --git a/examples/declarative/toys/README b/examples/declarative/toys/README new file mode 100644 index 0000000..7fd7eb0 --- /dev/null +++ b/examples/declarative/toys/README @@ -0,0 +1,37 @@ +These pure QML examples create complete components to demonstrate +some of what can be easily done using just a few QML files. + +The example launcher provided with Qt can be used to explore each of the +examples in this directory. They can also be viewed directly with the +QML viewer utility, without requiring compilation. + +Documentation for these examples can be found via the Tutorial and Examples +link in the main Qt documentation. + + +Finding the Qt Examples and Demos launcher +========================================== + +On Windows: + +The launcher can be accessed via the Windows Start menu. Select the menu +entry entitled "Qt Examples and Demos" entry in the submenu containing +the Qt tools. + +On Mac OS X: + +For the binary distribution, the qtdemo executable is installed in the +/Developer/Applications/Qt directory. For the source distribution, it is +installed alongside the other Qt tools on the path specified when Qt is +configured. + +On Unix/Linux: + +The qtdemo executable is installed alongside the other Qt tools on the path +specified when Qt is configured. + +On all platforms: + +The source code for the launcher can be found in the demos/qtdemo directory +in the Qt package. This example is built at the same time as the Qt libraries, +tools, examples, and demonstrations. diff --git a/examples/declarative/toys/dial/content/Dial.qml b/examples/declarative/toys/dial-example/content/Dial.qml index 6f24801..6f24801 100644 --- a/examples/declarative/toys/dial/content/Dial.qml +++ b/examples/declarative/toys/dial-example/content/Dial.qml diff --git a/examples/declarative/toys/dial/content/background.png b/examples/declarative/toys/dial-example/content/background.png Binary files differindex 75d555d..75d555d 100644 --- a/examples/declarative/toys/dial/content/background.png +++ b/examples/declarative/toys/dial-example/content/background.png diff --git a/examples/declarative/toys/dial/content/needle.png b/examples/declarative/toys/dial-example/content/needle.png Binary files differindex 2d19f75..2d19f75 100644 --- a/examples/declarative/toys/dial/content/needle.png +++ b/examples/declarative/toys/dial-example/content/needle.png diff --git a/examples/declarative/toys/dial/content/needle_shadow.png b/examples/declarative/toys/dial-example/content/needle_shadow.png Binary files differindex 8d8a928..8d8a928 100644 --- a/examples/declarative/toys/dial/content/needle_shadow.png +++ b/examples/declarative/toys/dial-example/content/needle_shadow.png diff --git a/examples/declarative/toys/dial/content/overlay.png b/examples/declarative/toys/dial-example/content/overlay.png Binary files differindex 3860a7b..3860a7b 100644 --- a/examples/declarative/toys/dial/content/overlay.png +++ b/examples/declarative/toys/dial-example/content/overlay.png diff --git a/examples/declarative/toys/dial/dial-example.qml b/examples/declarative/toys/dial-example/dial-example.qml index 900954f..900954f 100644 --- a/examples/declarative/toys/dial/dial-example.qml +++ b/examples/declarative/toys/dial-example/dial-example.qml diff --git a/examples/declarative/toys/dial/dial.qmlproject b/examples/declarative/toys/dial-example/dial.qmlproject index d4909f8..d4909f8 100644 --- a/examples/declarative/toys/dial/dial.qmlproject +++ b/examples/declarative/toys/dial-example/dial.qmlproject diff --git a/examples/declarative/toys/dynamicscene/dynamicscene.qml b/examples/declarative/toys/dynamicscene/dynamicscene.qml index 52c7c1e..2aa15e5 100644 --- a/examples/declarative/toys/dynamicscene/dynamicscene.qml +++ b/examples/declarative/toys/dynamicscene/dynamicscene.qml @@ -8,7 +8,8 @@ Item { property int activeSuns: 0 //This is a desktop-sized example - width: 1024; height: 512 + width: 800; height: 480 + //This is the message box that pops up when there's an error Rectangle { @@ -79,7 +80,7 @@ Item { Rectangle { id: toolbox - width: 480 + width: 380 color: activePalette.window anchors { right: parent.right; top: parent.top; bottom: parent.bottom } @@ -132,7 +133,7 @@ Item { Text { text: "Arbitrary QML:" } Rectangle { - width: 460; height: 240 + width: 360; height: 240 TextEdit { id: qmlText @@ -140,8 +141,9 @@ Item { readOnly: false focusOnPress: true font.pixelSize: 14 + wrapMode: TextEdit.WordWrap - text: "import Qt 4.7\nImage {\n id: smile\n x: 500 * Math.random()\n y: 200 * Math.random() \n source: 'images/face-smile.png'\n\n NumberAnimation on opacity { \n to: 0; duration: 1500\n }\n\n Component.onCompleted: smile.destroy(1500);\n}" + text: "import Qt 4.7\nImage {\n id: smile\n x: 360 * Math.random()\n y: 180 * Math.random() \n source: 'images/face-smile.png'\n NumberAnimation on opacity { \n to: 0; duration: 1500\n }\n Component.onCompleted: smile.destroy(1500);\n}" } } diff --git a/examples/declarative/toys/dynamicscene/qml/GenericSceneItem.qml b/examples/declarative/toys/dynamicscene/qml/GenericSceneItem.qml new file mode 100644 index 0000000..de096ad --- /dev/null +++ b/examples/declarative/toys/dynamicscene/qml/GenericSceneItem.qml @@ -0,0 +1,9 @@ +import Qt 4.7 + +Image { + property bool created: false + property string image + + source: image + +} diff --git a/examples/declarative/toys/dynamicscene/qml/itemCreation.js b/examples/declarative/toys/dynamicscene/qml/itemCreation.js index f92dd15..e74f7b0 100644 --- a/examples/declarative/toys/dynamicscene/qml/itemCreation.js +++ b/examples/declarative/toys/dynamicscene/qml/itemCreation.js @@ -5,7 +5,7 @@ var posnInWindow; function startDrag(mouse) { - posnInWindow = paletteItem.mapToItem(null, 0, 0); + posnInWindow = paletteItem.mapToItem(window, 0, 0); startingMouse = { x: mouse.x, y: mouse.y } loadComponent(); } @@ -36,7 +36,7 @@ function createItem() { } else if (itemComponent.status == Component.Error) { draggedItem = null; console.log("error creating component"); - console.log(component.errorString()); + console.log(itemComponent.errorString()); } } diff --git a/mkspecs/features/default_pre.prf b/mkspecs/features/default_pre.prf index 6442594..2e82f03 100644 --- a/mkspecs/features/default_pre.prf +++ b/mkspecs/features/default_pre.prf @@ -1,2 +1,3 @@ load(exclusive_builds) +### Qt 5: remove "uic" and "resources" - or add "qt" CONFIG = lex yacc warn_on debug uic resources $$CONFIG diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 62cce62..e8946de 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -31,6 +31,9 @@ plugin { #Qt plugins } } +#handle modules +for(mod,$$list($$files($$[QMAKE_MKSPECS]/modules/qt_*.pri))):include($$mod) + #handle includes INCLUDEPATH = $$QMAKE_INCDIR_QT $$INCLUDEPATH #prepending prevents us from picking up "stale" includes win32:INCLUDEPATH += $$QMAKE_INCDIR_QT/ActiveQt diff --git a/mkspecs/features/resources.prf b/mkspecs/features/resources.prf index 5d00a4d..a305a4f 100644 --- a/mkspecs/features/resources.prf +++ b/mkspecs/features/resources.prf @@ -1,3 +1,4 @@ +defined(qtPrepareTool)|load(qt_functions) ### Qt 5: see default_pre.prf qtPrepareTool(QMAKE_RCC, rcc) isEmpty(RCC_DIR):RCC_DIR = . diff --git a/mkspecs/features/symbian/qt.prf b/mkspecs/features/symbian/qt.prf index 9fc9814..b5d3d98 100644 --- a/mkspecs/features/symbian/qt.prf +++ b/mkspecs/features/symbian/qt.prf @@ -31,9 +31,16 @@ contains(CONFIG, qt):!contains(TARGET.UID3, 0x2001E61C):!contains(TARGET.UID3, 0 # Projects linking to webkit need dependency to webkit contains(QT, webkit): { + # these can be overridden by mkspecs/modules/qt_webkit.pri + isEmpty(QT_WEBKIT_MAJOR_VERSION) { + QT_WEBKIT_MAJOR_VERSION = $${QT_MAJOR_VERSION} + QT_WEBKIT_MINOR_VERSION = $${QT_MINOR_VERSION} + QT_WEBKIT_PATCH_VERSION = $${QT_PATCH_VERSION} + } + pkg_depends_webkit += \ "; Dependency to Qt Webkit" \ - "(0x200267C2), $${QT_MAJOR_VERSION}, $${QT_MINOR_VERSION}, $${QT_PATCH_VERSION}, {\"QtWebKit\"}" + "(0x200267C2), $${QT_WEBKIT_MAJOR_VERSION}, $${QT_WEBKIT_MINOR_VERSION}, $${QT_WEBKIT_PATCH_VERSION}, {\"QtWebKit\"}" } else { default_deployment.pkg_prerules -= pkg_depends_webkit } diff --git a/mkspecs/features/uic.prf b/mkspecs/features/uic.prf index d108f24..c87372d 100644 --- a/mkspecs/features/uic.prf +++ b/mkspecs/features/uic.prf @@ -1,3 +1,4 @@ +defined(qtPrepareTool)|load(qt_functions) ### Qt 5: see default_pre.prf qtPrepareTool(QMAKE_UIC3, uic3) qtPrepareTool(QMAKE_UIC, uic) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 3118f8f..31f8b85 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -2425,8 +2425,6 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); #if defined(Q_OS_SYMBIAN) #ifdef SYMBIAN_BUILD_GCE -//RWsPointerCursor is fixed, so don't use low performance sprites -#define Q_SYMBIAN_FIXED_POINTER_CURSORS #define Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE #define Q_SYMBIAN_WINDOW_SIZE_CACHE #define QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER diff --git a/src/declarative/graphicsitems/qdeclarativelayoutitem.cpp b/src/declarative/graphicsitems/qdeclarativelayoutitem.cpp index 1bbdd97..c8ecbb6 100644 --- a/src/declarative/graphicsitems/qdeclarativelayoutitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativelayoutitem.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE /*! \qmlclass LayoutItem QDeclarativeLayoutItem \since 4.7 - \brief The LayoutItem element allows you to place your Fluid UI elements inside a classical Qt layout. + \brief The LayoutItem element allows you to place your declarative UI elements inside a classical Qt layout. LayoutItem is a variant of Item with a couple of additional properties. These properties provide the size hints needed for items to work in conjunction with Qt Layouts. The Qt Layout will resize the LayoutItem as appropriate, diff --git a/src/declarative/graphicsitems/qdeclarativerectangle.cpp b/src/declarative/graphicsitems/qdeclarativerectangle.cpp index ccabbde..d098aa0 100644 --- a/src/declarative/graphicsitems/qdeclarativerectangle.cpp +++ b/src/declarative/graphicsitems/qdeclarativerectangle.cpp @@ -380,7 +380,9 @@ void QDeclarativeRectangle::generateBorderedRect() key += d->pen->color().name() % QString::number(d->pen->color().alpha(), 16); if (!QPixmapCache::find(key, &d->rectImage)) { - d->rectImage = QPixmap(pw*2 + 3, pw*2 + 3); + // Adding 5 here makes qDrawBorderPixmap() paint correctly with smooth: true + // See QTBUG-7999 and QTBUG-10765 for more details. + d->rectImage = QPixmap(pw*2 + 5, pw*2 + 5); d->rectImage.fill(Qt::transparent); QPainter p(&(d->rectImage)); p.setRenderHint(QPainter::Antialiasing); diff --git a/src/declarative/qml/qdeclarativeinclude.cpp b/src/declarative/qml/qdeclarativeinclude.cpp index e37b68b..4cde54b 100644 --- a/src/declarative/qml/qdeclarativeinclude.cpp +++ b/src/declarative/qml/qdeclarativeinclude.cpp @@ -259,8 +259,6 @@ QScriptValue QDeclarativeInclude::worker_include(QScriptContext *ctxt, QScriptEn if (ctxt->argumentCount() == 0) return engine->undefinedValue(); - QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine); - QString urlString = ctxt->argument(0).toString(); QUrl url(ctxt->argument(0).toString()); if (url.isRelative()) { diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 1365cd7..de1c0cb 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -2543,7 +2543,6 @@ void QDeclarativeParentAnimation::transition(QDeclarativeStateActions &actions, QDeclarativeAction &yAction = pc->yIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; QDeclarativeAction &sAction = pc->scaleIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; QDeclarativeAction &rAction = pc->rotationIsSet() && i < actions.size()-1 ? actions[++i] : dummyAction; - bool forward = (direction == QDeclarativeAbstractAnimation::Forward); QDeclarativeItem *target = pc->object(); QDeclarativeItem *targetParent = action.reverseEvent ? pc->originalParent() : pc->parent(); diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index 9a5c9de..7518eb7 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -162,7 +162,7 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM spacing: 5 Text { text: "Attributes:" } Repeater { - dataSource: attributes + model: attributes Component { Text { text: description } } } } diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 4a374a5..cae1d3a 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -423,6 +423,7 @@ public: int highestRole; QNetworkReply *reply; QDeclarativeXmlListModel::Status status; + QString errorString; qreal progress; int queryId; QStringList keyRoleResultsCache; @@ -495,10 +496,11 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla </rss> \endcode - Then it could be used to create the following model: + A XmlListModel could create a model from this data, like this: \qml XmlListModel { + id: xmlModel source: "http://www.mysite.com/feed.xml" query: "/rss/channel/item" XmlRole { name: "title"; query: "title/string()" } @@ -511,6 +513,16 @@ void QDeclarativeXmlListModelPrivate::clear_role(QDeclarativeListProperty<QDecla model item attributes; here, each model item will have \c title and \c pubDate attributes that match the \c title and \c pubDate values of its corresponding \c <item>. + The model could be used in a ListView, like this: + + \qml + ListView { + width: 180; height: 300 + model: xmlModel + delegate: Text { title + " (" + pubDate + ")" } + } + \endqml + \section2 Using key XML roles @@ -722,7 +734,8 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati \o XmlListModel.Null - No XML data has been set for this model. \o XmlListModel.Ready - The XML data has been loaded into the model. \o XmlListModel.Loading - The model is in the process of reading and loading XML data. - \o XmlListModel.Error - An error occurred while the model was loading. + \o XmlListModel.Error - An error occurred while the model was loading. See errorString() for details + about the error. \endlist \sa progress @@ -755,6 +768,12 @@ qreal QDeclarativeXmlListModel::progress() const return d->progress; } +QString QDeclarativeXmlListModel::errorString() const +{ + Q_D(const QDeclarativeXmlListModel); + return d->errorString; +} + void QDeclarativeXmlListModel::classBegin() { Q_D(QDeclarativeXmlListModel); @@ -807,6 +826,7 @@ void QDeclarativeXmlListModel::reload() d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache); d->progress = 1.0; d->status = Loading; + d->errorString.clear(); emit progressChanged(d->progress); emit statusChanged(d->status); return; @@ -816,6 +836,7 @@ void QDeclarativeXmlListModel::reload() d->queryId = XMLLISTMODEL_CLEAR_ID; d->progress = 1.0; d->status = Loading; + d->errorString.clear(); emit progressChanged(d->progress); emit statusChanged(d->status); QTimer::singleShot(0, this, SLOT(dataCleared())); @@ -824,6 +845,7 @@ void QDeclarativeXmlListModel::reload() d->progress = 0.0; d->status = Loading; + d->errorString.clear(); emit progressChanged(d->progress); emit statusChanged(d->status); @@ -854,6 +876,7 @@ void QDeclarativeXmlListModel::requestFinished() d->redirectCount = 0; if (d->reply->error() != QNetworkReply::NoError) { + d->errorString = d->reply->errorString(); disconnect(d->reply, 0, this, 0); d->reply->deleteLater(); d->reply = 0; @@ -919,6 +942,7 @@ void QDeclarativeXmlListModel::queryCompleted(const QDeclarativeXmlQueryResult & d->data = result.data; d->keyRoleResultsCache = result.keyRoleResultsCache; d->status = Ready; + d->errorString.clear(); d->queryId = -1; bool hasKeys = false; diff --git a/src/declarative/util/qdeclarativexmllistmodel_p.h b/src/declarative/util/qdeclarativexmllistmodel_p.h index 7b85476..7101c57 100644 --- a/src/declarative/util/qdeclarativexmllistmodel_p.h +++ b/src/declarative/util/qdeclarativexmllistmodel_p.h @@ -113,6 +113,8 @@ public: Status status() const; qreal progress() const; + Q_INVOKABLE QString errorString() const; + virtual void classBegin(); virtual void componentComplete(); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index dfd58b3..db6c4c5 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5643,6 +5643,14 @@ void QGraphicsItem::update(const QRectF &rect) viewport, which does not benefit from scroll optimizations), this function is equivalent to calling update(\a rect). + \bold{Note:} Scrolling is only supported when QGraphicsItem::ItemCoordinateCache + is enabled; in all other cases calling this function is equivalent to calling + update(\a rect). If you for sure know that the item is opaque and not overlapped + by other items, you can map the \a rect to viewport coordinates and scroll the + viewport. + + \snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 19 + \sa boundingRect() */ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) @@ -5652,153 +5660,73 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) return; if (!d->scene) return; - if (d->cacheMode != NoCache) { - QGraphicsItemCache *c; - bool scrollCache = qFuzzyIsNull(dx - int(dx)) && qFuzzyIsNull(dy - int(dy)) - && (c = (QGraphicsItemCache *)qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraCacheData))) - && (d->cacheMode == ItemCoordinateCache && !c->fixedSize.isValid()); - if (scrollCache) { - QPixmap pix; - if (QPixmapCache::find(c->key, &pix)) { - // Adjust with 2 pixel margin. Notice the loss of precision - // when converting to QRect. - int adjust = 2; - QRectF scrollRect = !rect.isNull() ? rect : boundingRect(); - QRectF br = boundingRect().adjusted(-adjust, -adjust, adjust, adjust); - QRect irect = scrollRect.toRect().translated(-br.x(), -br.y()); - - pix.scroll(dx, dy, irect); - - QPixmapCache::replace(c->key, pix); - - // Translate the existing expose. - foreach (QRectF exposedRect, c->exposed) - c->exposed += exposedRect.translated(dx, dy) & scrollRect; - - // Calculate exposure. - QRegion exposed; - QRect r = scrollRect.toRect(); - exposed += r; - exposed -= r.translated(dx, dy); - foreach (QRect rect, exposed.rects()) - update(rect); - d->scene->d_func()->markDirty(this); - } else { - update(rect); - } - } else { - // ### This is very slow, and can be done much better. If the cache is - // local and matches the below criteria for rotation and scaling, we - // can easily scroll. And if the cache is in device coordinates, we - // can scroll both the viewport and the cache. - update(rect); - } + + // Accelerated scrolling means moving pixels from one location to another + // and only redraw the newly exposed area. The following requirements must + // be fulfilled in order to do that: + // + // 1) Item is opaque. + // 2) Item is not overlapped by other items. + // + // There's (yet) no way to detect whether an item is opaque or not, which means + // we cannot do accelerated scrolling unless the cache is enabled. In case of using + // DeviceCoordinate cache we also have to take the device transform into account in + // order to determine whether we can do accelerated scrolling or not. That's left out + // for simplicity here, but it is definitely something we can consider in the future + // as a performance improvement. + if (d->cacheMode != QGraphicsItem::ItemCoordinateCache + || !qFuzzyIsNull(dx - int(dx)) || !qFuzzyIsNull(dy - int(dy))) { + update(rect); return; } - QRectF scrollRect = !rect.isNull() ? rect : boundingRect(); - int couldntScroll = d->scene->views().size(); - foreach (QGraphicsView *view, d->scene->views()) { - if (view->viewport()->inherits("QGLWidget")) { - // ### Please replace with a widget attribute; any widget that - // doesn't support partial updates / doesn't support scrolling - // should be skipped in this code. Qt::WA_NoPartialUpdates or so. - continue; - } + QGraphicsItemCache *cache = d->extraItemCache(); + if (cache->allExposed || cache->fixedSize.isValid()) { + // Cache is either invalidated or item is scaled (see QGraphicsItem::setCacheMode). + update(rect); + return; + } - static const QLineF up(0, 0, 0, -1); - static const QLineF down(0, 0, 0, 1); - static const QLineF left(0, 0, -1, 0); - static const QLineF right(0, 0, 1, 0); - - QTransform deviceTr = deviceTransform(view->viewportTransform()); - QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect(); - QLineF v1 = deviceTr.map(right); - QLineF v2 = deviceTr.map(down); - QLineF u1 = v1.unitVector(); u1.translate(-v1.p1()); - QLineF u2 = v2.unitVector(); u2.translate(-v2.p1()); - bool noScroll = false; - - // Check if the delta resolves to ints in device space. - QPointF deviceDelta = deviceTr.map(QPointF(dx, dy)); - if ((deviceDelta.x() - int(deviceDelta.x())) - || (deviceDelta.y() - int(deviceDelta.y()))) { - noScroll = true; - } else { - // Check if the unit vectors have no fraction in device space. - qreal v1l = v1.length(); - if (v1l - int(v1l)) { - noScroll = true; - } else { - dx *= v1.length(); - } - qreal v2l = v2.length(); - if (v2l - int(v2l)) { - noScroll = true; - } else { - dy *= v2.length(); - } - } + QPixmap cachedPixmap; + if (!QPixmapCache::find(cache->key, &cachedPixmap)) { + update(rect); + return; + } - if (!noScroll) { - if (u1 == right) { - if (u2 == up) { - // flipped - dy = -dy; - } else if (u2 == down) { - // normal - } else { - noScroll = true; - } - } else if (u1 == left) { - if (u2 == up) { - // mirrored & flipped / rotated 180 degrees - dx = -dx; - dy = -dy; - } else if (u2 == down) { - // mirrored - dx = -dx; - } else { - noScroll = true; - } - } else if (u1 == up) { - if (u2 == left) { - // rotated -90 & mirrored - qreal tmp = dy; - dy = -dx; - dx = -tmp; - } else if (u2 == right) { - // rotated -90 - qreal tmp = dy; - dy = -dx; - dx = tmp; - } else { - noScroll = true; - } - } else if (u1 == down) { - if (u2 == left) { - // rotated 90 - qreal tmp = dy; - dy = dx; - dx = -tmp; - } else if (u2 == right) { - // rotated 90 & mirrored - qreal tmp = dy; - dy = dx; - dx = tmp; - } else { - noScroll = true; - } - } - } + QRegion exposed; + const bool scrollEntirePixmap = rect.isNull(); + if (scrollEntirePixmap) { + // Scroll entire pixmap. + cachedPixmap.scroll(dx, dy, cachedPixmap.rect(), &exposed); + } else { + if (!rect.intersects(cache->boundingRect)) + return; // Nothing to scroll. + // Scroll sub-rect of pixmap. The rect is in item coordinates + // so we have to translate it to pixmap coordinates. + QRect scrollRect = rect.toAlignedRect(); + cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed); + } - if (!noScroll) { - view->viewport()->scroll(int(dx), int(dy), deviceScrollRect); - --couldntScroll; - } + QPixmapCache::replace(cache->key, cachedPixmap); + + // Translate the existing expose. + for (int i = 0; i < cache->exposed.size(); ++i) { + QRectF &e = cache->exposed[i]; + if (!scrollEntirePixmap && !e.intersects(rect)) + continue; + e.translate(dx, dy); } - if (couldntScroll) - update(rect); + + // Append newly exposed areas. Note that the exposed region is currently + // in pixmap coordinates, so we have to translate it to item coordinates. + exposed.translate(cache->boundingRect.topLeft()); + const QVector<QRect> exposedRects = exposed.rects(); + for (int i = 0; i < exposedRects.size(); ++i) + cache->exposed += exposedRects.at(i); + + // Trigger update. This will redraw the newly exposed area and make sure + // the pixmap is re-blitted in case there are overlapping items. + d->scene->d_func()->markDirty(this, rect); } /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 4b09a7e..344df30 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4372,11 +4372,6 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte bool pixmapFound; QGraphicsItemCache *itemCache = itemd->extraItemCache(); if (cacheMode == QGraphicsItem::ItemCoordinateCache) { - if (itemCache->boundingRect != brect.toRect()) { - itemCache->boundingRect = brect.toRect(); - itemCache->allExposed = true; - itemCache->exposed.clear(); - } pixmapKey = itemCache->key; } else { pixmapKey = itemCache->deviceData.value(widget).key; @@ -4389,19 +4384,24 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte if (cacheMode == QGraphicsItem::ItemCoordinateCache) { QSize pixmapSize; bool fixedCacheSize = false; - QRectF brectAligned = brect.toAlignedRect(); + QRect br = brect.toAlignedRect(); if ((fixedCacheSize = itemCache->fixedSize.isValid())) { pixmapSize = itemCache->fixedSize; } else { - pixmapSize = brectAligned.size().toSize(); + pixmapSize = br.size(); } // Create or recreate the pixmap. int adjust = itemCache->fixedSize.isValid() ? 0 : 2; QSize adjustSize(adjust*2, adjust*2); - QRectF br = brectAligned.adjusted(-adjust, -adjust, adjust, adjust); + br.adjust(-adjust, -adjust, adjust, adjust); if (pix.isNull() || (!fixedCacheSize && (pixmapSize + adjustSize) != pix.size())) { pix = QPixmap(pixmapSize + adjustSize); + itemCache->boundingRect = br; + itemCache->exposed.clear(); + itemCache->allExposed = true; + } else if (itemCache->boundingRect != br) { + itemCache->boundingRect = br; itemCache->exposed.clear(); itemCache->allExposed = true; } @@ -4455,10 +4455,10 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte // qpixmap-image-transform-pixmap roundtrip. if (newPainterOpacity != oldPainterOpacity) { painter->setOpacity(newPainterOpacity); - painter->drawPixmap(br, pix, QRectF(QPointF(), pix.size())); + painter->drawPixmap(br.topLeft(), pix); painter->setOpacity(oldPainterOpacity); } else { - painter->drawPixmap(br, pix, QRectF(QPointF(), pix.size())); + painter->drawPixmap(br.topLeft(), pix); } return; } diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index fc99439..f848321 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -566,8 +566,6 @@ void QItemSelectionModelPrivate::initModel(QAbstractItemModel *model) q, SLOT(_q_layoutAboutToBeChanged())); QObject::connect(model, SIGNAL(layoutChanged()), q, SLOT(_q_layoutChanged())); - QObject::connect(model, SIGNAL(modelAboutToBeReset()), - q, SLOT(_q_modelAboutToBeReset())); } } @@ -898,13 +896,6 @@ void QItemSelectionModelPrivate::_q_layoutChanged() savedPersistentCurrentIndexes.clear(); } -void QItemSelectionModelPrivate::_q_modelAboutToBeReset() -{ - Q_Q(QItemSelectionModel); - q->clearSelection(); - clearCurrentIndex(); -} - /*! \class QItemSelectionModel @@ -1104,18 +1095,12 @@ void QItemSelectionModel::clear() { Q_D(QItemSelectionModel); clearSelection(); - d->clearCurrentIndex(); -} - -void QItemSelectionModelPrivate::clearCurrentIndex() -{ - Q_Q(QItemSelectionModel); - QModelIndex previous = currentIndex; - currentIndex = QModelIndex(); + QModelIndex previous = d->currentIndex; + d->currentIndex = QModelIndex(); if (previous.isValid()) { - emit q->currentChanged(currentIndex, previous); - emit q->currentRowChanged(currentIndex, previous); - emit q->currentColumnChanged(currentIndex, previous); + emit currentChanged(d->currentIndex, previous); + emit currentRowChanged(d->currentIndex, previous); + emit currentColumnChanged(d->currentIndex, previous); } } diff --git a/src/gui/itemviews/qitemselectionmodel.h b/src/gui/itemviews/qitemselectionmodel.h index 8682109..436514f 100644 --- a/src/gui/itemviews/qitemselectionmodel.h +++ b/src/gui/itemviews/qitemselectionmodel.h @@ -197,7 +197,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_rowsAboutToBeInserted(const QModelIndex&, int, int)) Q_PRIVATE_SLOT(d_func(), void _q_layoutAboutToBeChanged()) Q_PRIVATE_SLOT(d_func(), void _q_layoutChanged()) - Q_PRIVATE_SLOT(d_func(), void _q_modelAboutToBeReset()) }; Q_DECLARE_OPERATORS_FOR_FLAGS(QItemSelectionModel::SelectionFlags) diff --git a/src/gui/itemviews/qitemselectionmodel_p.h b/src/gui/itemviews/qitemselectionmodel_p.h index c2fe976..5afa90d 100644 --- a/src/gui/itemviews/qitemselectionmodel_p.h +++ b/src/gui/itemviews/qitemselectionmodel_p.h @@ -78,7 +78,6 @@ public: void _q_columnsAboutToBeInserted(const QModelIndex &parent, int start, int end); void _q_layoutAboutToBeChanged(); void _q_layoutChanged(); - void _q_modelAboutToBeReset(); inline void remove(QList<QItemSelectionRange> &r) { @@ -94,8 +93,6 @@ public: currentSelection.clear(); } - void clearCurrentIndex(); - QPointer<QAbstractItemModel> model; QItemSelection ranges; QItemSelection currentSelection; diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp index 67eb1ef..4e7b92c 100644 --- a/src/gui/styles/qwindowsmobilestyle.cpp +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -80,6 +80,8 @@ extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cp extern bool qt_wince_is_windows_mobile_65(); //defined in qguifunctions_wince.cpp #endif // Q_WS_WINCE +#include "qstylehelper_p.h" + QT_BEGIN_NAMESPACE static const int windowsItemFrame = 1; // menu item frame width diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/compiled.qml b/tests/auto/declarative/qdeclarativeecmascript/data/compiled.qml index a883e85..1655905 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/data/compiled.qml +++ b/tests/auto/declarative/qdeclarativeecmascript/data/compiled.qml @@ -31,6 +31,8 @@ QtObject { property string test21: g property string test22: h property bool test23: i + property color test24: j + property color test25: k property real a: 4.5 property real b: 11.2 @@ -41,4 +43,6 @@ QtObject { property variant g: 6.7 property variant h: "!" property variant i: true + property string j: "#112233" + property string k: "#aa112233" } diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index 4900fa2..9a8ad64 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -2090,6 +2090,8 @@ void tst_qdeclarativeecmascript::compiled() QCOMPARE(object->property("test21").toString(), QLatin1String("6.7")); QCOMPARE(object->property("test22").toString(), QLatin1String("!")); QCOMPARE(object->property("test23").toBool(), true); + QCOMPARE(qvariant_cast<QColor>(object->property("test24")), QColor(0x11,0x22,0x33)); + QCOMPARE(qvariant_cast<QColor>(object->property("test25")), QColor(0x11,0x22,0x33,0xAA)); delete object; } diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp index 4173a44..7769979 100644 --- a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp +++ b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp @@ -268,10 +268,12 @@ void tst_qdeclarativexmllistmodel::xml() QDeclarativeXmlListModel *model = qobject_cast<QDeclarativeXmlListModel*>(component.create()); QSignalSpy spy(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status))); + QVERIFY(model->errorString().isEmpty()); QCOMPARE(model->progress(), qreal(0.0)); QCOMPARE(model->status(), QDeclarativeXmlListModel::Loading); QTRY_COMPARE(spy.count(), 1); spy.clear(); QCOMPARE(model->status(), QDeclarativeXmlListModel::Ready); + QVERIFY(model->errorString().isEmpty()); QCOMPARE(model->progress(), qreal(1.0)); QCOMPARE(model->count(), 9); @@ -284,6 +286,7 @@ void tst_qdeclarativexmllistmodel::xml() QCOMPARE(model->status(), QDeclarativeXmlListModel::Loading); QTRY_COMPARE(spy.count(), 1); spy.clear(); QCOMPARE(model->status(), QDeclarativeXmlListModel::Ready); + QVERIFY(model->errorString().isEmpty()); QCOMPARE(model->count(), count); delete model; @@ -309,10 +312,12 @@ void tst_qdeclarativexmllistmodel::source() QDeclarativeXmlListModel *model = qobject_cast<QDeclarativeXmlListModel*>(component.create()); QSignalSpy spy(model, SIGNAL(statusChanged(QDeclarativeXmlListModel::Status))); + QVERIFY(model->errorString().isEmpty()); QCOMPARE(model->progress(), qreal(0.0)); QCOMPARE(model->status(), QDeclarativeXmlListModel::Loading); QTRY_COMPARE(spy.count(), 1); spy.clear(); QCOMPARE(model->status(), QDeclarativeXmlListModel::Ready); + QVERIFY(model->errorString().isEmpty()); QCOMPARE(model->progress(), qreal(1.0)); QCOMPARE(model->count(), 9); @@ -320,6 +325,7 @@ void tst_qdeclarativexmllistmodel::source() QCOMPARE(model->progress(), qreal(0.0)); QTRY_COMPARE(spy.count(), 1); spy.clear(); QCOMPARE(model->status(), QDeclarativeXmlListModel::Loading); + QVERIFY(model->errorString().isEmpty()); QEventLoop loop; QTimer timer; @@ -337,9 +343,12 @@ void tst_qdeclarativexmllistmodel::source() QCOMPARE(model->status(), status); QCOMPARE(model->count(), count); + if (status == QDeclarativeXmlListModel::Ready) QCOMPARE(model->progress(), qreal(1.0)); + QCOMPARE(model->errorString().isEmpty(), status == QDeclarativeXmlListModel::Ready); + delete model; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 5a5a821..300afc3 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -236,11 +236,12 @@ public: QRectF boundingRect() const { return br; } - void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) + void paint(QPainter *painter, const QStyleOptionGraphicsItem *o, QWidget *) { hints = painter->renderHints(); painter->setBrush(brush); painter->drawRect(boundingRect()); + lastExposedRect = o->exposedRect; ++repaints; } @@ -250,10 +251,19 @@ public: return QGraphicsItem::sceneEvent(event); } + void reset() + { + events.clear(); + hints = QPainter::RenderHints(0); + repaints = 0; + lastExposedRect = QRectF(); + } + QList<QEvent::Type> events; QPainter::RenderHints hints; int repaints; QRectF br; + QRectF lastExposedRect; QBrush brush; }; @@ -430,6 +440,7 @@ private slots: void scenePosChange(); void updateMicroFocus(); void textItem_shortcuts(); + void scroll(); // task specific tests below me void task141694_textItemEnsureVisible(); @@ -10155,6 +10166,78 @@ void tst_QGraphicsItem::textItem_shortcuts() QTRY_COMPARE(item->textCursor().selectedText(), item->toPlainText()); } +void tst_QGraphicsItem::scroll() +{ + // Create two overlapping rectangles in the scene: + // +-------+ + // | | <- item1 + // | +-------+ + // | | | + // +---| | <- item2 + // | | + // +-------+ + + EventTester *item1 = new EventTester; + item1->br = QRectF(0, 0, 200, 200); + item1->brush = Qt::red; + item1->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); + + EventTester *item2 = new EventTester; + item2->br = QRectF(0, 0, 200, 200); + item2->brush = Qt::blue; + item2->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption); + item2->setPos(100, 100); + + QGraphicsScene scene(0, 0, 300, 300); + scene.addItem(item1); + scene.addItem(item2); + + MyGraphicsView view(&scene); + view.setFrameStyle(0); + view.show(); + QTest::qWaitForWindowShown(&view); + QTRY_VERIFY(view.repaints > 0); + + view.reset(); + item1->reset(); + item2->reset(); + + const QRectF item1BoundingRect = item1->boundingRect(); + const QRectF item2BoundingRect = item2->boundingRect(); + + // Scroll item1: + // Item1 should get full exposure + // Item2 should get exposure for the part that overlaps item1. + item1->scroll(0, -10); + QTRY_VERIFY(view.repaints > 0); + QCOMPARE(item1->lastExposedRect, item1BoundingRect); + + QRectF expectedItem2Expose = item2BoundingRect; + // NB! Adjusted by 2 pixels for antialiasing + expectedItem2Expose &= item1->mapRectToItem(item2, item1BoundingRect.adjusted(-2, -2, 2, 2)); + QCOMPARE(item2->lastExposedRect, expectedItem2Expose); + + // Enable ItemCoordinateCache on item1. + view.reset(); + item1->setCacheMode(QGraphicsItem::ItemCoordinateCache); + QTRY_VERIFY(view.repaints > 0); + view.reset(); + item1->reset(); + item2->reset(); + + // Scroll item1: + // Item1 should only get expose for the newly exposed area (accelerated scroll). + // Item2 should get exposure for the part that overlaps item1. + item1->scroll(0, -10, QRectF(50, 50, 100, 100)); + QTRY_VERIFY(view.repaints > 0); + QCOMPARE(item1->lastExposedRect, QRectF(50, 140, 100, 10)); + + expectedItem2Expose = item2BoundingRect; + // NB! Adjusted by 2 pixels for antialiasing + expectedItem2Expose &= item1->mapRectToItem(item2, QRectF(50, 50, 100, 100).adjusted(-2, -2, 2, 2)); + QCOMPARE(item2->lastExposedRect, expectedItem2Expose); +} + void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor() { struct Item : public QGraphicsTextItem diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp index 9858829..3b2a716 100644 --- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -1536,43 +1536,6 @@ public: inline void reset() { QStandardItemModel::reset(); } }; -class ResetObserver : public QObject -{ - QItemSelectionModel * const m_selectionModel; - QItemSelection m_selection; - Q_OBJECT -public: - ResetObserver(QItemSelectionModel *selectionModel) - : m_selectionModel(selectionModel) - { - connect(selectionModel->model(), SIGNAL(modelAboutToBeReset()),SLOT(modelAboutToBeReset())); - connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged(QItemSelection,QItemSelection))); - connect(selectionModel->model(), SIGNAL(modelReset()),SLOT(modelReset())); - } - -private slots: - void modelAboutToBeReset() - { - m_selection = m_selectionModel->selection(); - foreach(const QItemSelectionRange &range, m_selection) - { - QVERIFY(range.isValid()); - } - } - - void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) - { - qDebug() << deselected << selected; - QCOMPARE(m_selection, deselected); - m_selection.clear(); - } - - void modelReset() - { - QVERIFY(m_selectionModel->selection().isEmpty()); - } -}; - void tst_QItemSelectionModel::resetModel() { MyStandardItemModel model(20, 20); @@ -1592,13 +1555,11 @@ void tst_QItemSelectionModel::resetModel() view.selectionModel()->select(QItemSelection(model.index(0, 0), model.index(5, 5)), QItemSelectionModel::Select); - // We get this signal three times. Twice in this test method and once because the source reset causes the current selection to - // be deselected. - QCOMPARE(spy.count(), 3); - QCOMPARE(spy.at(2).count(), 2); + QCOMPARE(spy.count(), 2); + QCOMPARE(spy.at(1).count(), 2); // make sure we don't get an "old selection" - QCOMPARE(spy.at(2).at(1).userType(), qMetaTypeId<QItemSelection>()); - QVERIFY(qvariant_cast<QItemSelection>(spy.at(2).at(1)).isEmpty()); + QCOMPARE(spy.at(1).at(1).userType(), qMetaTypeId<QItemSelection>()); + QVERIFY(qvariant_cast<QItemSelection>(spy.at(1).at(1)).isEmpty()); } void tst_QItemSelectionModel::removeRows_data() |