summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexis Menard <alexis.menard@nokia.com>2009-06-11 11:33:54 +0200
committerAlexis Menard <alexis.menard@nokia.com>2009-06-11 11:34:05 +0200
commitc6f2229bcecbbea2d1f3df149d1a397cd26b43c7 (patch)
treebb14b976cddccdb196a68bed6f9b94d10273f857
parentbc3abd32ed1c5a872d7a7817c1af0a13f442d536 (diff)
parent0989cbe2b164560eef14334a540fcbcb2e2ec8cb (diff)
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into qt-main/qgraphicssceneindex
Painfull merge due to recent changes in QGV framework. Conflicts: src/gui/graphicsview/qgraphicsitem.cpp src/gui/graphicsview/qgraphicsscene.cpp src/gui/graphicsview/qgraphicsscene.h src/gui/graphicsview/qgraphicsscene_p.h src/gui/graphicsview/qgraphicsview.cpp
-rw-r--r--demos/embeddeddialogs/main.cpp1
-rw-r--r--dist/changes-4.6.033
-rw-r--r--doc/src/diagrams/programs/easingcurve/main.cpp36
-rw-r--r--doc/src/index.qdoc20
-rw-r--r--doc/src/qmake-manual.qdoc4
-rw-r--r--examples/graphicsview/elasticnodes/node.cpp1
-rw-r--r--examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp5
-rw-r--r--qmake/generators/makefile.cpp1
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp8
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp22
-rw-r--r--src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc3
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp33
-rw-r--r--src/corelib/io/io.pri1
-rw-r--r--src/corelib/io/qdir.cpp69
-rw-r--r--src/corelib/io/qfileinfo.cpp65
-rw-r--r--src/corelib/io/qfileinfo_p.h126
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp31
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h1
-rw-r--r--src/corelib/kernel/qobject.cpp89
-rw-r--r--src/corelib/kernel/qobject.h3
-rw-r--r--src/corelib/kernel/qobject_p.h5
-rw-r--r--src/corelib/kernel/qtimer.cpp2
-rw-r--r--src/corelib/kernel/qvariant.cpp18
-rw-r--r--src/corelib/tools/qstringbuilder.cpp12
-rw-r--r--src/corelib/tools/qstringbuilder.h12
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp1158
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h4
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h245
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp941
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h5
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h39
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp19
-rw-r--r--src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h17
-rw-r--r--src/gui/graphicsview/qgraphicssceneindex.cpp10
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp360
-rw-r--r--src/gui/graphicsview/qgraphicsview.h5
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h10
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp3
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp2
-rw-r--r--src/gui/image/qpicture_p.h2
-rw-r--r--src/gui/itemviews/qabstractitemview.cpp16
-rw-r--r--src/gui/itemviews/qcolumnview.cpp38
-rw-r--r--src/gui/itemviews/qheaderview.cpp10
-rw-r--r--src/gui/itemviews/qlistview.cpp10
-rw-r--r--src/gui/itemviews/qlistwidget.cpp5
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp7
-rw-r--r--src/gui/itemviews/qstandarditemmodel.cpp4
-rw-r--r--src/gui/itemviews/qtableview.cpp6
-rw-r--r--src/gui/itemviews/qtablewidget.cpp20
-rw-r--r--src/gui/itemviews/qtablewidget_p.h1
-rw-r--r--src/gui/itemviews/qtreeview.cpp60
-rw-r--r--src/gui/itemviews/qtreewidget.cpp25
-rw-r--r--src/gui/itemviews/qtreewidget_p.h1
-rw-r--r--src/gui/kernel/qaction.cpp25
-rw-r--r--src/gui/kernel/qapplication_x11.cpp87
-rw-r--r--src/gui/kernel/qt_x11_p.h6
-rw-r--r--src/gui/kernel/qwidget.cpp4
-rw-r--r--src/gui/kernel/qwidget_p.h8
-rw-r--r--src/gui/kernel/qwidget_x11.cpp28
-rw-r--r--src/gui/kernel/qwidgetaction.cpp4
-rw-r--r--src/gui/math3d/qgenericmatrix.cpp2
-rw-r--r--src/gui/math3d/qgenericmatrix.h2
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp2
-rw-r--r--src/gui/math3d/qmatrix4x4.h2
-rw-r--r--src/gui/math3d/qquaternion.cpp2
-rw-r--r--src/gui/math3d/qquaternion.h2
-rw-r--r--src/gui/math3d/qvector2d.cpp2
-rw-r--r--src/gui/math3d/qvector2d.h2
-rw-r--r--src/gui/math3d/qvector3d.cpp2
-rw-r--r--src/gui/math3d/qvector3d.h2
-rw-r--r--src/gui/math3d/qvector4d.cpp2
-rw-r--r--src/gui/math3d/qvector4d.h2
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp12
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp11
-rw-r--r--src/gui/painting/qpaintengineex.cpp91
-rw-r--r--src/gui/painting/qpaintengineex_p.h32
-rw-r--r--src/gui/painting/qpainter.cpp47
-rw-r--r--src/gui/painting/qpainter.h1
-rw-r--r--src/gui/painting/qpainter_p.h2
-rw-r--r--src/gui/painting/qprinter.cpp3
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h2
-rw-r--r--src/gui/painting/qvectorpath_p.h2
-rw-r--r--src/gui/styles/qcleanlooksstyle.cpp3
-rw-r--r--src/gui/styles/qgtkstyle.cpp2
-rw-r--r--src/gui/styles/qplastiquestyle.cpp3
-rw-r--r--src/gui/text/qcssparser.cpp42
-rw-r--r--src/gui/text/qcssparser_p.h1
-rw-r--r--src/gui/text/qfontengine.cpp6
-rw-r--r--src/gui/text/qfontengine_p.h1
-rw-r--r--src/gui/text/qfontengineglyphcache_p.h4
-rw-r--r--src/gui/text/qtextcontrol.cpp2
-rw-r--r--src/gui/text/qtexthtmlparser.cpp2
-rw-r--r--src/gui/util/qdesktopservices_win.cpp3
-rw-r--r--src/gui/widgets/qabstractbutton.cpp20
-rw-r--r--src/gui/widgets/qdockarealayout.cpp8
-rw-r--r--src/gui/widgets/qdockwidget.cpp7
-rw-r--r--src/gui/widgets/qmdiarea.cpp32
-rw-r--r--src/gui/widgets/qmdisubwindow.cpp24
-rw-r--r--src/gui/widgets/qmdisubwindow_p.h2
-rw-r--r--src/gui/widgets/qmenubar.cpp6
-rw-r--r--src/gui/widgets/qtoolbarlayout.cpp2
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp3
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h14
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp420
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h26
-rw-r--r--src/opengl/qglextensions.cpp3
-rw-r--r--src/opengl/qpixmapdata_gl.cpp5
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp3
-rw-r--r--src/plugins/imageformats/tiff/qtiffhandler.cpp342
-rw-r--r--tests/auto/bic/bic.pro6
-rw-r--r--tests/auto/bic/tst_bic.cpp33
-rw-r--r--tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp2
-rw-r--r--tests/auto/math3d/qquaternion/tst_qquaternion.cpp2
-rw-r--r--tests/auto/math3d/qvectornd/tst_qvectornd.cpp2
-rw-r--r--tests/auto/math3d/shared/math3dincludes.h2
-rw-r--r--tests/auto/qcssparser/tst_cssparser.cpp45
-rw-r--r--tests/auto/qfileinfo/tst_qfileinfo.cpp56
-rw-r--r--tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp506
-rw-r--r--tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp2
-rw-r--r--tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp8
-rw-r--r--tests/auto/qgraphicsview/tst_qgraphicsview.cpp59
-rw-r--r--tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp36
-rw-r--r--tests/auto/qimagereader/qimagereader.qrc2
-rw-r--r--tests/auto/qimagereader/tst_qimagereader.cpp26
-rw-r--r--tests/auto/qimagewriter/tst_qimagewriter.cpp26
-rw-r--r--tests/auto/qlistwidget/tst_qlistwidget.cpp39
-rw-r--r--tests/auto/qpixmap/tst_qpixmap.cpp2
-rw-r--r--tests/auto/qvariant/tst_qvariant.cpp14
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp94
-rw-r--r--tools/qdoc3/htmlgenerator.cpp55
-rw-r--r--tools/qdoc3/test/classic.css103
131 files changed, 3791 insertions, 2328 deletions
diff --git a/demos/embeddeddialogs/main.cpp b/demos/embeddeddialogs/main.cpp
index cfb31c471a..c9b6ee1bba 100644
--- a/demos/embeddeddialogs/main.cpp
+++ b/demos/embeddeddialogs/main.cpp
@@ -76,7 +76,6 @@ int main(int argc, char *argv[])
view.scale(0.5, 0.5);
view.setRenderHints(view.renderHints() | QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
view.setBackgroundBrush(QPixmap(":/No-Ones-Laughing-3.jpg"));
- view.setCacheMode(QGraphicsView::CacheBackground);
view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate);
view.show();
view.setWindowTitle("Embedded Dialogs Demo");
diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0
index bedf58af8a..ba58bcf299 100644
--- a/dist/changes-4.6.0
+++ b/dist/changes-4.6.0
@@ -40,17 +40,30 @@ information about a particular change.
reasons for this is that Qt Software focuses on OpenGL for desktop
hardware accelerated rendering.
- - QStyleOptionGraphicsItem::exposedRect and QStyleOptionGraphicsItem::matrix
- does no longer contain fine-grained values when passed in drawItems()/paint()
- unless the QGraphicsItem::ItemUsesExtendedStyleOptions flag is enabled.
- By default, exposedRect is initialized to the item's bounding rect
- and the matrix is untransformed.
-
- - QStyleOptionGraphicsItem::levelOfDetails is obsoleted and its value
- is always initialized to 1. For a more fine-grained value use
- QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &).
-
- When mixing OpenGL and QPainter calls you need to first call syncState()
on the paint engine, for example "painter->paintEngine()->syncState()".
This is to ensure that the engine flushes any pending drawing and sets up
the GL modelview/projection matrices properly.
+
+ - Graphics View has undergone heavy optimization work, and as a result of
+ this work, the following behavior changes were introduced.
+
+ a) QStyleOptionGraphicsItem::exposedRect now contains the item's bounding
+ rectangle, and QStyleOptionGraphicsItem::matrix is uninitialized by
+ default. You can enable an exact exposed rectangle and a correct matrix
+ by enabling the flag QGraphicsItem::ItemUsesExtendedStyleOptions.
+
+ b) QStyleOptionGraphicsItem::levelOfDetails is obsoleted and its value is
+ always initialized to 1. Instead you can call
+ QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &)
+ to determine the level of detail.
+
+ c) QGraphicsView no longer calls QGraphicsView::drawItems(), and in turn
+ QGraphicsScene::drawItems(), by default. You can get the old behavior
+ back by enabling QGraphicsView::IndirectPainting.
+
+ d) QGraphicsItem no longer calls itemChange() for position and
+ transformation changes. If you want to receive notifications for changes
+ to the item's position and transformation, you can set the flag
+ QGraphicsItem::ItemSendsGeometryChanges (which is enabled by default by
+ QGraphicsWidget and QGraphicsProxyWidget).
diff --git a/doc/src/diagrams/programs/easingcurve/main.cpp b/doc/src/diagrams/programs/easingcurve/main.cpp
index 98e9d37e32..8d399a30ff 100644
--- a/doc/src/diagrams/programs/easingcurve/main.cpp
+++ b/doc/src/diagrams/programs/easingcurve/main.cpp
@@ -1,11 +1,41 @@
/****************************************************************************
**
-** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
-** $TROLLTECH_DUAL_LICENSE$
+** $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$
**
****************************************************************************/
diff --git a/doc/src/index.qdoc b/doc/src/index.qdoc
index 23e86233de..b18a50d2e8 100644
--- a/doc/src/index.qdoc
+++ b/doc/src/index.qdoc
@@ -86,15 +86,15 @@
\endif
\raw HTML
- <table cellpadding="2" cellspacing="1" border="0" width="100%" bgcolor="#e5e5e5">
+ <table cellpadding="2" cellspacing="1" border="0" width="100%" class="indextable">
<tr>
- <th bgcolor="#66b036" width="33%">
+ <th class="titleheader" width="33%">
Getting Started
</th>
- <th bgcolor="#66b036" width="33%">
+ <th class="titleheader" width="33%">
General
</th>
- <th bgcolor="#66b036" width="33%">
+ <th class="titleheader" width="33%">
Developer Resources
</th>
</tr>
@@ -128,13 +128,13 @@
</td>
</tr>
<tr>
- <th bgcolor="#66b036">
+ <th class="titleheader">
API Reference
</th>
- <th bgcolor="#66b036">
+ <th class="titleheader">
Core Features
</th>
- <th bgcolor="#66b036">
+ <th class="titleheader">
Key Technologies
</th>
</tr>
@@ -194,13 +194,13 @@
</td>
</tr>
<tr>
- <th bgcolor="#66b036">
+ <th class="titleheader">
Add-ons &amp; Services
</th>
- <th bgcolor="#66b036">
+ <th class="titleheader">
Tools
</th>
- <th bgcolor="#66b036">
+ <th class="titleheader">
Licenses &amp; Credits
</th>
</tr>
diff --git a/doc/src/qmake-manual.qdoc b/doc/src/qmake-manual.qdoc
index 172bc60e0b..9714a4403a 100644
--- a/doc/src/qmake-manual.qdoc
+++ b/doc/src/qmake-manual.qdoc
@@ -3303,10 +3303,6 @@
\o output_function
\o Specifies a custom qmake function that is used to specify the filename to be created.
\row
- \o variables
- \o Indicates that the variables specified here are replaced with $(QMAKE_COMP_VARNAME) when refered to
- in the pro file as $(VARNAME).
- \row
\o variable_out
\o The variable that the files created from the output should be added to.
\endtable
diff --git a/examples/graphicsview/elasticnodes/node.cpp b/examples/graphicsview/elasticnodes/node.cpp
index 6942fa007d..53fe994350 100644
--- a/examples/graphicsview/elasticnodes/node.cpp
+++ b/examples/graphicsview/elasticnodes/node.cpp
@@ -52,6 +52,7 @@ Node::Node(GraphWidget *graphWidget)
: graph(graphWidget)
{
setFlag(ItemIsMovable);
+ setFlag(ItemSendsGeometryChanges);
setCacheMode(DeviceCoordinateCache);
setZValue(1);
}
diff --git a/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp
index d360de9453..2368608ebf 100644
--- a/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp
+++ b/examples/statemachine/tankgameplugins/random_ai/random_ai_plugin.cpp
@@ -42,13 +42,12 @@
#include "random_ai_plugin.h"
#include <QState>
+#include <QTime>
#include <QtPlugin>
-#include <time.h>
-
QState *RandomAiPlugin::create(QState *parentState, QObject *tank)
{
- qsrand(uint(time(NULL)));
+ qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
QState *topLevel = new QState(parentState);
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 2d4658e261..a385748f67 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -1910,6 +1910,7 @@ MakefileGenerator::writeExtraCompilerTargets(QTextStream &t)
deps += replaceExtraCompilerVariables(pre_deps.at(i), (*input), out);
}
QString cmd = replaceExtraCompilerVariables(tmp_cmd, (*input), out);
+ // NOTE: The var -> QMAKE_COMP_var replace feature is unsupported, do not use!
for(QStringList::ConstIterator it3 = vars.constBegin(); it3 != vars.constEnd(); ++it3)
cmd.replace("$(" + (*it3) + ")", "$(QMAKE_COMP_" + (*it3)+")");
if(!tmp_dep_cmd.isEmpty() && doDepends()) {
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
index 01b68eb891..77add54789 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
@@ -1986,10 +1986,12 @@ bool QWebPage::isContentEditable() const
/*!
\property QWebPage::forwardUnsupportedContent
- \brief whether QWebPage should forward unsupported content through the
- unsupportedContent signal
+ \brief whether QWebPage should forward unsupported content
- If disabled the download of such content is aborted immediately.
+ If enabled, the unsupportedContent() signal is emitted with a network reply that
+ can be used to read the content.
+
+ If disabled, the download of such content is aborted immediately.
By default unsupported content is not forwarded.
*/
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp
index 1ad23f64d7..b5162637f4 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp
@@ -213,17 +213,25 @@ QWebSettings *QWebSettings::globalSettings()
Each QWebPage object has its own QWebSettings object, which configures the
settings for that page. If a setting is not configured, then it is looked
up in the global settings object, which can be accessed using
- QWebSettings::globalSettings().
+ globalSettings().
- QWebSettings allows configuring font properties such as font size and font
- family, the location of a custom stylesheet, and generic attributes like java
- script, plugins, etc. The \l{QWebSettings::WebAttribute}{WebAttribute}
- enum further describes this.
+ QWebSettings allows configuration of browser properties, such as font sizes and
+ families, the location of a custom style sheet, and generic attributes like
+ JavaScript and plugins. Individual attributes are set using the setAttribute()
+ function. The \l{QWebSettings::WebAttribute}{WebAttribute} enum further describes
+ each attribute.
- QWebSettings also configures global properties such as the web page memory
- cache and the web page icon database, local database storage and offline
+ QWebSettings also configures global properties such as the Web page memory
+ cache and the Web page icon database, local database storage and offline
applications storage.
+ \section1 Enabling Plugins
+
+ Support for browser plugins can enabled by setting the
+ \l{QWebSettings::PluginsEnabled}{PluginsEnabled} attribute. For many applications,
+ this attribute is enabled for all pages by setting it on the
+ \l{globalSettings()}{global settings object}.
+
\section1 Web Application Support
WebKit provides support for features specified in \l{HTML 5} that improve the
diff --git a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc
index 06305e04b5..119c126516 100644
--- a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc
+++ b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc
@@ -96,7 +96,8 @@
Since WebKit supports the Netscape Plugin API, Qt applications can display
Web pages that embed common plugins, as long as the user has the appropriate
- binary files for those plugins installed.
+ binary files for those plugins installed and the \l{QWebSettings::PluginsEnabled}
+ attribute is set for the application.
The following locations are searched for plugins:
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
index c148cb5da4..6ec467945c 100644
--- a/src/corelib/animation/qparallelanimationgroup.cpp
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -135,13 +135,14 @@ void QParallelAnimationGroup::updateCurrentTime(int)
// simulate completion of the loop
int dura = duration();
if (dura > 0) {
- foreach (QAbstractAnimation *animation, d->animations) {
- animation->setCurrentTime(dura); // will stop
+ for (int i = 0; i < d->animations.size(); ++i) {
+ d->animations.at(i)->setCurrentTime(dura); // will stop
}
}
} else if (d->currentLoop < d->lastLoop) {
// simulate completion of the loop seeking backwards
- foreach (QAbstractAnimation *animation, d->animations) {
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
animation->setCurrentTime(0);
animation->stop();
}
@@ -154,7 +155,8 @@ void QParallelAnimationGroup::updateCurrentTime(int)
__LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state());
#endif
// finally move into the actual time of the current loop
- foreach (QAbstractAnimation *animation, d->animations) {
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
const int dura = animation->totalDuration();
if (dura == -1 && d->isUncontrolledAnimationFinished(animation))
continue;
@@ -200,17 +202,18 @@ void QParallelAnimationGroup::updateState(QAbstractAnimation::State oldState,
switch (newState) {
case Stopped:
- foreach (QAbstractAnimation *animation, d->animations)
- animation->stop();
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->stop();
d->disconnectUncontrolledAnimations();
break;
case Paused:
- foreach (QAbstractAnimation *animation, d->animations)
- animation->pause();
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->pause();
break;
case Running:
d->connectUncontrolledAnimations();
- foreach (QAbstractAnimation *animation, d->animations) {
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
animation->stop();
animation->setDirection(d->direction);
animation->start();
@@ -243,8 +246,8 @@ void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
return;
int maxDuration = 0;
- foreach (QAbstractAnimation *a, animations)
- maxDuration = qMax(maxDuration, a->totalDuration());
+ for (int i = 0; i < animations.size(); ++i)
+ maxDuration = qMax(maxDuration, animations.at(i)->totalDuration());
if (currentTime >= maxDuration)
q->stop();
@@ -267,7 +270,8 @@ void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
{
Q_Q(QParallelAnimationGroup);
- foreach (QAbstractAnimation *animation, animations) {
+ for (int i = 0; i < animations.size(); ++i) {
+ QAbstractAnimation *animation = animations.at(i);
if (animation->duration() == -1 || animation->loopCount() < 0) {
uncontrolledFinishTime[animation] = -1;
QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
@@ -288,8 +292,9 @@ void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction dire
Q_D(QParallelAnimationGroup);
//we need to update the direction of the current animation
if (state() != Stopped) {
- foreach(QAbstractAnimation *anim, d->animations) {
- anim->setDirection(direction);
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ animation->setDirection(direction);
}
} else {
if (direction == Forward) {
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 8f37e255bf..5033b21a7b 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -10,6 +10,7 @@ HEADERS += \
io/qdiriterator.h \
io/qfile.h \
io/qfileinfo.h \
+ io/qfileinfo_p.h \
io/qiodevice.h \
io/qiodevice_p.h \
io/qnoncontiguousbytedevice_p.h \
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 7d330e64d1..302d9b56e9 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -45,6 +45,7 @@
#ifndef QT_NO_DEBUG_STREAM
#include "qdebug.h"
#endif
+#include "qdiriterator.h"
#include "qfsfileengine.h"
#include "qdatetime.h"
#include "qstring.h"
@@ -92,7 +93,7 @@ protected:
QString initFileEngine(const QString &file);
void updateFileLists() const;
- void sortFileList(QDir::SortFlags, QStringList &, QStringList *, QFileInfoList *) const;
+ void sortFileList(QDir::SortFlags, QFileInfoList &, QStringList *, QFileInfoList *) const;
private:
#ifdef QT3_SUPPORT
@@ -268,39 +269,50 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt
return r < 0;
}
-inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QStringList &l,
+inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QFileInfoList &l,
QStringList *names, QFileInfoList *infos) const
{
if(names)
names->clear();
if(infos)
infos->clear();
- if(!l.isEmpty()) {
- QDirSortItem *si= new QDirSortItem[l.count()];
- int i;
- for (i = 0; i < l.size(); ++i) {
- QString path = data->path;
- if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
- path += QLatin1Char('/');
- si[i].item = QFileInfo(path + l.at(i));
- }
- if ((sort & QDir::SortByMask) != QDir::Unsorted)
- qStableSort(si, si+i, QDirSortItemComparator(sort));
- // put them back in the list(s)
- for (int j = 0; j<i; j++) {
+ int n = l.size();
+ if(n > 0) {
+ if (n == 1 || (sort & QDir::SortByMask) == QDir::Unsorted) {
if(infos)
- infos->append(si[j].item);
- if(names)
- names->append(si[j].item.fileName());
+ *infos = l;
+ if(names) {
+ for (int i = 0; i < n; ++i)
+ names->append(l.at(i).fileName());
+ }
+ } else {
+ QDirSortItem *si = new QDirSortItem[n];
+ for (int i = 0; i < n; ++i)
+ si[i].item = l.at(i);
+ qStableSort(si, si + n, QDirSortItemComparator(sort));
+ // put them back in the list(s)
+ if(infos) {
+ for (int i = 0; i < n; ++i)
+ infos->append(si[i].item);
+ }
+ if(names) {
+ for (int i = 0; i < n; ++i)
+ names->append(si[i].item.fileName());
+ }
+ delete [] si;
}
- delete [] si;
}
}
inline void QDirPrivate::updateFileLists() const
{
if(data->listsDirty) {
- QStringList l = data->fileEngine->entryList(data->filters, data->nameFilters);
+ QFileInfoList l;
+ QDirIterator it(data->path, data->nameFilters, data->filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
sortFileList(data->sort, l, &data->files, &data->fileInfos);
data->listsDirty = 0;
}
@@ -1346,10 +1358,12 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
d->updateFileLists();
return d->data->files;
}
- QStringList l = d->data->fileEngine->entryList(filters, nameFilters);
- if ((sort & QDir::SortByMask) == QDir::Unsorted)
- return l;
-
+ QFileInfoList l;
+ QDirIterator it(d->data->path, nameFilters, filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
QStringList ret;
d->sortFileList(sort, l, &ret, 0);
return ret;
@@ -1389,8 +1403,13 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter
d->updateFileLists();
return d->data->fileInfos;
}
+ QFileInfoList l;
+ QDirIterator it(d->data->path, nameFilters, filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
QFileInfoList ret;
- QStringList l = d->data->fileEngine->entryList(filters, nameFilters);
d->sortFileList(sort, l, 0, &ret);
return ret;
}
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 36b1ed8d09..4f1b9433fa 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -48,73 +48,10 @@
#include "qatomic.h"
#include "qhash.h"
#include "qdir.h"
+#include "qfileinfo_p.h"
QT_BEGIN_NAMESPACE
-class QFileInfoPrivate
-{
-public:
- QFileInfoPrivate(const QFileInfo *copy=0);
- ~QFileInfoPrivate();
-
- void initFileEngine(const QString &);
-
- enum Access {
- ReadAccess,
- WriteAccess,
- ExecuteAccess
- };
- bool hasAccess(Access access) const;
-
- uint getFileFlags(QAbstractFileEngine::FileFlags) const;
- QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
- QString getFileName(QAbstractFileEngine::FileName) const;
-
- enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
- CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
- CachedSize =0x08 };
- struct Data {
- inline Data()
- : ref(1), fileEngine(0), cache_enabled(1)
- { clear(); }
- inline Data(const Data &copy)
- : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)),
- fileName(copy.fileName), cache_enabled(copy.cache_enabled)
- { clear(); }
- inline ~Data() { delete fileEngine; }
- inline void clearFlags() {
- fileFlags = 0;
- cachedFlags = 0;
- if (fileEngine)
- (void)fileEngine->fileFlags(QFSFileEngine::Refresh);
- }
- inline void clear() {
- fileNames.clear();
- clearFlags();
- }
- mutable QAtomicInt ref;
-
- QAbstractFileEngine *fileEngine;
- mutable QString fileName;
- mutable QHash<int, QString> fileNames;
-
- mutable uint cachedFlags : 31;
- mutable uint cache_enabled : 1;
- mutable uint fileFlags;
- mutable qint64 fileSize;
- mutable QDateTime fileTimes[3];
- inline bool getCachedFlag(uint c) const
- { return cache_enabled ? (cachedFlags & c) : 0; }
- inline void setCachedFlag(uint c)
- { if (cache_enabled) cachedFlags |= c; }
- } *data;
- inline void reset() {
- detach();
- data->clear();
- }
- void detach();
-};
-
QFileInfoPrivate::QFileInfoPrivate(const QFileInfo *copy)
{
if(copy) {
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
new file mode 100644
index 0000000000..8155bcb950
--- /dev/null
+++ b/src/corelib/io/qfileinfo_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFILEINFO_P_H
+#define QFILEINFO_P_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 "qfileinfo.h"
+
+QT_BEGIN_NAMESPACE
+
+class QFileInfoPrivate
+{
+public:
+ QFileInfoPrivate(const QFileInfo *copy=0);
+ ~QFileInfoPrivate();
+
+ void initFileEngine(const QString &);
+
+ enum Access {
+ ReadAccess,
+ WriteAccess,
+ ExecuteAccess
+ };
+ bool hasAccess(Access access) const;
+
+ uint getFileFlags(QAbstractFileEngine::FileFlags) const;
+ QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
+ QString getFileName(QAbstractFileEngine::FileName) const;
+
+ enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
+ CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
+ CachedSize =0x08 };
+ struct Data {
+ inline Data()
+ : ref(1), fileEngine(0), cache_enabled(1)
+ { clear(); }
+ inline Data(const Data &copy)
+ : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)),
+ fileName(copy.fileName), cache_enabled(copy.cache_enabled)
+ { clear(); }
+ inline ~Data() { delete fileEngine; }
+ inline void clearFlags() {
+ fileFlags = 0;
+ cachedFlags = 0;
+ if (fileEngine)
+ (void)fileEngine->fileFlags(QFSFileEngine::Refresh);
+ }
+ inline void clear() {
+ fileNames.clear();
+ clearFlags();
+ }
+ mutable QAtomicInt ref;
+
+ QAbstractFileEngine *fileEngine;
+ mutable QString fileName;
+ mutable QHash<int, QString> fileNames;
+
+ mutable uint cachedFlags : 31;
+ mutable uint cache_enabled : 1;
+ mutable uint fileFlags;
+ mutable qint64 fileSize;
+ mutable QDateTime fileTimes[3];
+ inline bool getCachedFlag(uint c) const
+ { return cache_enabled ? (cachedFlags & c) : 0; }
+ inline void setCachedFlag(uint c)
+ { if (cache_enabled) cachedFlags |= c; }
+ } *data;
+ inline void reset() {
+ detach();
+ data->clear();
+ }
+ void detach();
+};
+
+QT_END_NAMESPACE
+
+#endif // QFILEINFO_P_H
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index 935c0aa47a..6d6caf5421 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -467,6 +467,37 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
return qEmptyModel();
}
+/*!
+ \internal
+ return true if \a value contains a numerical type
+
+ This function is used by our Q{Tree,Widget,Table}WidgetModel classes to sort.
+ We cannot rely on QVariant::canConvert because this would take strings as double
+ and then not sort strings correctly
+*/
+bool QAbstractItemModelPrivate::canConvertToDouble(const QVariant &value)
+{
+ switch (value.userType()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Double:
+ case QVariant::Char:
+ case QMetaType::Float:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
{
if (data->index.isValid()) {
diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h
index 27f1b2824f..70c35cba05 100644
--- a/src/corelib/kernel/qabstractitemmodel_p.h
+++ b/src/corelib/kernel/qabstractitemmodel_p.h
@@ -89,6 +89,7 @@ public:
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
void columnsRemoved(const QModelIndex &parent, int first, int last);
static QAbstractItemModel *staticEmptyModel();
+ static bool canConvertToDouble(const QVariant &value);
inline QModelIndex createIndex(int row, int column, void *data = 0) const {
return q_func()->createIndex(row, column, data);
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 5e33a71f37..55d70c1176 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -123,7 +123,7 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
}
QObjectPrivate::QObjectPrivate(int version)
- : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0)
+ : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0), senders(0)
{
if (version != QObjectPrivateVersion)
qFatal("Cannot mix incompatible Qt libraries");
@@ -143,6 +143,7 @@ QObjectPrivate::QObjectPrivate(int version)
inEventHandler = false;
inThreadChangeEvent = false;
deleteWatch = 0;
+ hasGuards = false;
}
QObjectPrivate::~QObjectPrivate()
@@ -287,8 +288,8 @@ QObjectList QObjectPrivate::senderList() const
{
QObjectList returnValue;
QMutexLocker locker(signalSlotLock(q_func()));
- for (int i = 0; i < senders.count(); ++i)
- returnValue << senders.at(i)->sender;
+ for (Connection *c = senders; c; c = c->next)
+ returnValue << c->sender;
return returnValue;
}
@@ -359,6 +360,7 @@ void QMetaObject::addGuard(QObject **ptr)
return;
}
QMutexLocker locker(guardHashLock());
+ QObjectPrivate::get(*ptr)->hasGuards = true;
hash->insert(*ptr, ptr);
}
@@ -374,12 +376,17 @@ void QMetaObject::removeGuard(QObject **ptr)
QMutexLocker locker(guardHashLock());
GuardHash::iterator it = hash->find(*ptr);
const GuardHash::iterator end = hash->end();
+ bool more = false; //if the QObject has more pointer attached to it.
for (; it.key() == *ptr && it != end; ++it) {
if (it.value() == ptr) {
- (void) hash->erase(it);
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
break;
}
+ more = true;
}
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
}
/*!\internal
@@ -393,24 +400,33 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o)
}
QMutexLocker locker(guardHashLock());
if (*ptr) {
+ bool more = false; //if the QObject has more pointer attached to it.
GuardHash::iterator it = hash->find(*ptr);
const GuardHash::iterator end = hash->end();
for (; it.key() == *ptr && it != end; ++it) {
if (it.value() == ptr) {
- (void) hash->erase(it);
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
break;
}
+ more = true;
}
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
}
*ptr = o;
- if (*ptr)
+ if (*ptr) {
hash->insert(*ptr, ptr);
+ QObjectPrivate::get(*ptr)->hasGuards = true;
+ }
}
/*! \internal
*/
void QObjectPrivate::clearGuards(QObject *object)
{
+ if (!QObjectPrivate::get(object)->hasGuards)
+ return;
GuardHash *hash = guardHash();
if (hash) {
QMutexLocker locker(guardHashLock());
@@ -756,8 +772,10 @@ QObject::~QObject()
QMutex *m = signalSlotLock(c->receiver);
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
c = connectionList[i];
- if (c->receiver)
- c->receiver->d_func()->senders.removeOne(c);
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
+ }
if (needToUnlock)
m->unlock();
@@ -774,29 +792,25 @@ QObject::~QObject()
}
// disconnect all senders
- for (int i = 0; i < d->senders.count(); ) {
- QObjectPrivate::Connection *s = d->senders[i];
-
- QMutex *m = signalSlotLock(s->sender);
+ QObjectPrivate::Connection *node = d->senders;
+ while (node) {
+ QMutex *m = signalSlotLock(node->sender);
+ node->prev = &node;
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
- if (m < locker.mutex()) {
- if (i >= d->senders.count() || s != d->senders[i]) {
- if (needToUnlock)
- m->unlock();
- continue;
- }
+ //the node has maybe been removed while the mutex was unlocked in relock?
+ if (!node || signalSlotLock(node->sender) != m) {
+ m->unlock();
+ continue;
}
- s->receiver = 0;
- QObjectConnectionListVector *senderLists = s->sender->d_func()->connectionLists;
+ node->receiver = 0;
+ QObjectConnectionListVector *senderLists = node->sender->d_func()->connectionLists;
if (senderLists)
senderLists->dirty = true;
if (needToUnlock)
m->unlock();
- ++i;
+ node = node->next;
}
-
- d->senders.clear();
}
if (d->pendTimer) {
@@ -2281,8 +2295,8 @@ QObject *QObject::sender() const
// Return 0 if d->currentSender isn't in d->senders
bool found = false;
- for (int i = 0; !found && i < d->senders.count(); ++i)
- found = (d->senders.at(i)->sender == d->currentSender->sender);
+ for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next)
+ found = (c->sender == d->currentSender->sender);
if (!found)
return 0;
return d->currentSender->sender;
@@ -2799,9 +2813,13 @@ bool QMetaObject::connect(const QObject *sender, int signal_index,
c->method = method_index;
c->connectionType = type;
c->argumentTypes = types;
+ c->prev = &r->d_func()->senders;
+ c->next = *c->prev;
+ *c->prev = c;
+ if (c->next)
+ c->next->prev = &c->next;
s->d_func()->addConnection(signal_index, c);
- r->d_func()->senders.append(c);
if (signal_index < 0)
sender->d_func()->connectedSignals = ~0u;
@@ -2851,8 +2869,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
c = connectionList[i];
}
- if (c->receiver)
- c->receiver->d_func()->senders.removeOne(c);
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
+ }
if (needToUnlock)
m->unlock();
@@ -2878,8 +2898,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
c = connectionList[i];
}
- if (c->receiver)
- c->receiver->d_func()->senders.removeOne(c);
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
+ }
if (needToUnlock)
m->unlock();
@@ -3417,9 +3439,8 @@ void QObject::dumpObjectInfo()
// now look for connections where this object is the receiver
qDebug(" SIGNALS IN");
- if (!d->senders.isEmpty()) {
- for (int i = 0; i < d->senders.count(); ++i) {
- const QObjectPrivate::Connection *s = d->senders.at(i);
+ if (d->senders) {
+ for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
const QMetaMethod slot = metaObject()->method(s->method);
qDebug(" <-- %s::%s %s",
s->sender->metaObject()->className(),
@@ -3427,7 +3448,7 @@ void QObject::dumpObjectInfo()
slot.signature());
}
} else {
- qDebug(" <None>");
+ qDebug(" <None>");
}
#endif
}
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index dbec0a6b1a..b1f41ad647 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -106,7 +106,8 @@ public:
uint receiveChildEvents : 1;
uint inEventHandler : 1;
uint inThreadChangeEvent : 1;
- uint unused : 23;
+ uint hasGuards : 1; //true iff there is one or more QPointer attached to this object
+ uint unused : 22;
int postedEvents;
};
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 96d79afec0..d699061d12 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -152,6 +152,9 @@ public:
int method;
uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
QBasicAtomicPointer<int> argumentTypes;
+ //senders linked list
+ Connection *next;
+ Connection **prev;
~Connection();
};
typedef QList<Connection *> ConnectionList;
@@ -160,7 +163,7 @@ public:
void addConnection(int signal, Connection *c);
void cleanConnectionLists();
- ConnectionList senders;
+ Connection *senders; //linked list;
static Sender *setCurrentSender(QObject *receiver,
Sender *sender);
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 8ca53b9034..29bdf7eaf9 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -251,7 +251,7 @@ void QTimer::stop()
/*!
- \reimp
+ \reimp
*/
void QTimer::timerEvent(QTimerEvent *e)
{
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 2ff9818b44..a3434a40e3 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -591,6 +591,15 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
ok = &dummy;
switch (uint(t)) {
+ case QVariant::Url:
+ switch (d->type) {
+ case QVariant::String:
+ *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
+ break;
+ default:
+ return false;
+ }
+ break;
case QVariant::String: {
QString *str = static_cast<QString *>(result);
switch (d->type) {
@@ -640,6 +649,8 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
if (v_cast<QStringList>(d)->count() == 1)
*str = v_cast<QStringList>(d)->at(0);
break;
+ case QVariant::Url:
+ *str = v_cast<QUrl>(d)->toString();
default:
return false;
}
@@ -1823,7 +1834,7 @@ QVariant::Type QVariant::nameToType(const char *name)
#ifndef QT_NO_DATASTREAM
enum { MapFromThreeCount = 35 };
-static const uint map_from_three[MapFromThreeCount] =
+static const ushort map_from_three[MapFromThreeCount] =
{
QVariant::Invalid,
QVariant::Map,
@@ -2484,7 +2495,8 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
/*QString*/ 1 << QVariant::StringList | 1 << QVariant::ByteArray | 1 << QVariant::Int
| 1 << QVariant::UInt | 1 << QVariant::Bool | 1 << QVariant::Double
| 1 << QVariant::Date | 1 << QVariant::Time | 1 << QVariant::DateTime
- | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char,
+ | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char
+ | 1 << QVariant::Url,
/*QStringList*/ 1 << QVariant::List | 1 << QVariant::String,
@@ -2499,7 +2511,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
/*QDateTime*/ 1 << QVariant::String | 1 << QVariant::Date,
-/*QUrl*/ 0,
+/*QUrl*/ 1 << QVariant::String,
/*QLocale*/ 0,
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
index 03d81606b3..740deb4ff6 100644
--- a/src/corelib/tools/qstringbuilder.cpp
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -3,14 +3,14 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** Commercial Usage
-** Licensees holding valid Qt Commercial licenses may use this file in
-** accordance with the Qt Commercial License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Nokia.
+** 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
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 2c31476322..30a7c6771f 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -3,14 +3,14 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** Commercial Usage
-** Licensees holding valid Qt Commercial licenses may use this file in
-** accordance with the Qt Commercial License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Nokia.
+** 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
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index ee32724420..58a2286ba1 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -133,12 +133,8 @@
\section1 Transformation
QGraphicsItem supports affine transformations in addition to its base
- position, pos(). To change the item's transformation, you can either pass
- a transformation matrix to setTransform(), or set the different transformation
- properties (transformOrigin, x/y/zRotation, x/yScale, horizontal/verticalShear).
- Note that setting the transformation matrix conflicts with using the properties.
- Setting the properties will overwrite the transformation set with setTransform,
- and using setTransform will reset the properties.
+ position, pos(). To change the item's transformation, you can pass
+ a transformation matrix to setTransform()
Item transformations accumulate from parent to child, so if both a parent and child
item are rotated 90 degrees, the child's total transformation will be 180 degrees.
@@ -152,19 +148,18 @@
and scenePos(), which returns its position in scene coordinates. To reset
an item's matrix, call resetTransform().
+ Another way to apply transformation to an item is to use the , or set the
+ different transformation properties (transformOrigin, x/y/zRotation, x/yScale,
+ horizontal/verticalShear). Those properties come in addition to the base transformation
+
The order you set the transformation properties does not affect the resulting transformation
The resulting transformation is always computed in the following order
\code
- [Origin] [RotateX] [RotateY] [RotateZ] [Shear] [Scale] [-Origin]
+ [Origin] [Base] [RotateX] [RotateY] [RotateZ] [Shear] [Scale] [-Origin]
\endcode
- So the transformation is equivalent to the following code
-
- \code
- QTransform().translate(xOrigin, yOrigin).rotate(xRotation, Qt::XAxis).rotate(yRotation, Qt::YAxis).rotate(zRotation, Qt::ZAxis)
- .shear(horizontalShear, verticalShear).scale(xScale, yScale).translate(-xOrigin, -yOrigin);
- \endcode
+ Where [Base] is the stransformation set by setTransform
\section1 Painting
@@ -309,6 +304,18 @@
and is always initialized to 1.
Use QStyleOptionGraphicsItem::levelOfDetailFromTransform for a more
fine-grained value.
+
+ \value ItemHasNoContents The item does not paint anything (i.e., calling
+ paint() on the item has no effect). You should set this flag on items that
+ do not need to be painted to ensure that Graphics View avoids unnecessary
+ painting preparations. This flag was introduced in Qt 4.6.
+
+ \value ItemSendsGeometryChanges The item enables itemChange()
+ notifications for ItemPositionChange, ItemPositionHasChanged,
+ ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For
+ performance reasons, these notifications are disabled by default. You must
+ enable this flag to receive notifications for position and transform
+ changes. This flag was introduced in Qt 4.6.
*/
/*!
@@ -347,33 +354,36 @@
changing. This value is obsolete; you can use ItemTransformChange instead.
\value ItemPositionChange The item's position changes. This notification
- is only sent when the item's local position changes, relative to its
- parent, has changed (i.e., as a result of calling setPos() or
- moveBy()). The value argument is the new position (i.e., a QPointF). You
- can call pos() to get the original position. Do not call setPos() or
- moveBy() in itemChange() as this notification is delivered; instead, you
- can return the new, adjusted position from itemChange(). After this
- notification, QGraphicsItem immediately sends the ItemPositionHasChanged
- notification if the position changed.
+ is sent if the ItemSendsGeometryChanges flag is enabled, and when the
+ item's local position changes, relative to its parent (i.e., as a result
+ of calling setPos() or moveBy()). The value argument is the new position
+ (i.e., a QPointF). You can call pos() to get the original position. Do
+ not call setPos() or moveBy() in itemChange() as this notification is
+ delivered; instead, you can return the new, adjusted position from
+ itemChange(). After this notification, QGraphicsItem immediately sends the
+ ItemPositionHasChanged notification if the position changed.
\value ItemPositionHasChanged The item's position has changed. This
- notification is only sent after the item's local position, relative to its
- parent, has changed. The value argument is the new position (the same as
- pos()), and QGraphicsItem ignores the return value for this notification
- (i.e., a read-only notification).
+ notification is sent if the ItemSendsGeometryChanges flag is enabled, and
+ after the item's local position, relative to its parent, has changed. The
+ value argument is the new position (the same as pos()), and QGraphicsItem
+ ignores the return value for this notification (i.e., a read-only
+ notification).
\value ItemTransformChange The item's transformation matrix changes. This
- notification is only sent when the item's local transformation matrix
- changes (i.e., as a result of calling setTransform(). The value
- argument is the new matrix (i.e., a QTransform); to get the old matrix,
- call transform(). Do not call setTransform() or set any of the transformation
- properties in itemChange() as this notification is delivered;
- instead, you can return the new matrix from itemChange().
- This notification is not sent if you change the transformation properties.
+ notification is send if the ItemSendsGeometryChanges flag is enabled, and
+ when the item's local transformation matrix changes (i.e., as a result of
+ calling setTransform(). The value argument is the new matrix (i.e., a
+ QTransform); to get the old matrix, call transform(). Do not call
+ setTransform() or set any of the transformation properties in itemChange()
+ as this notification is delivered; instead, you can return the new matrix
+ from itemChange(). This notification is not sent if you change the
+ transformation properties.
\value ItemTransformHasChanged The item's transformation matrix has
- changed either because setTransform is called, or one of the transformation
- properties is changed. This notification is only sent after the item's local
+ changed either because setTransform is called, or one of the
+ transformation properties is changed. This notification is sent if the
+ ItemSendsGeometryChanges flag is enabled, and after the item's local
transformation matrix has changed. The value argument is the new matrix
(same as transform()), and QGraphicsItem ignores the return value for this
notification (i.e., a read-only notification).
@@ -762,12 +772,43 @@ QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos,
/*!
\internal
- Returns true if this item or any of its ancestors are untransformable.
+ Combines this item's position and transform onto \a transform.
+
+ If you need to change this function (e.g., adding more transformation
+ modes / options), make sure to change all places marked with COMBINE.
*/
-bool QGraphicsItemPrivate::itemIsUntransformable() const
+void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const
{
- return (flags & QGraphicsItem::ItemIgnoresTransformations)
- || (ancestorFlags & AncestorIgnoresTransformations);
+ // COMBINE
+ if (itemIsUntransformable() && viewTransform) {
+ *x = q_ptr->deviceTransform(*viewTransform);
+ } else {
+ if (transformData)
+ *x *= transformData->computedFullTransform();
+ if (!pos.isNull())
+ *x *= QTransform::fromTranslate(pos.x(), pos.y());
+ }
+}
+
+/*!
+ \internal
+
+ Combines this item's position and transform onto \a transform.
+
+ If you need to change this function (e.g., adding more transformation
+ modes / options), make sure to change QGraphicsItem::deviceTransform() as
+ well.
+*/
+void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const
+{
+ // COMBINE
+ if (itemIsUntransformable() && viewTransform) {
+ *x = q_ptr->deviceTransform(*viewTransform);
+ } else {
+ x->translate(pos.x(), pos.y());
+ if (transformData)
+ *x = transformData->computedFullTransform() * *x;
+ }
}
/*!
@@ -789,11 +830,11 @@ QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query
/*!
\internal
- If \a deleting is true, then this item is being deleted, and \a parent is
- null. Make sure not to trigger any pure virtual function calls (e.g.,
- prepareGeometryChange).
+ Make sure not to trigger any pure virtual function calls (e.g.,
+ prepareGeometryChange) if the item is in its destructor, i.e.
+ inDestructor is 1.
*/
-void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool deleting)
+void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
{
Q_Q(QGraphicsItem);
if (newParent == q) {
@@ -820,7 +861,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de
// We anticipate geometry changes. If the item is deleted, it will be
// removed from the index at a later stage, and the whole scene will be
// updated.
- if (!deleting)
+ if (!inDestructor)
q_ptr->prepareGeometryChange();
const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(q));
@@ -832,7 +873,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de
// Update toplevelitem list. If this item is being deleted, its parent
// will be 0 but we don't want to register/unregister it in the TLI list.
- if (scene && !deleting) {
+ if (scene && !inDestructor) {
if (parent && !newParent) {
scene->d_func()->registerTopLevelItem(q);
} else if (!parent && newParent) {
@@ -853,8 +894,11 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de
parent->d_ptr->addChild(q);
parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
- if (!implicitUpdate)
- updateHelper(QRectF(), false, true);
+ if (!implicitUpdate && scene) {
+ scene->d_func()->markDirty(q_ptr, QRect(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/true);
+ }
// Inherit ancestor flags from the new parent.
updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
@@ -877,7 +921,7 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de
updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
- if (!deleting) {
+ if (!inDestructor) {
// Update item visible / enabled.
if (!visible && !explicitlyHidden)
setVisibleHelper(true, /* explicit = */ false);
@@ -885,18 +929,17 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de
setEnabledHelper(true, /* explicit = */ false);
// If the item is being deleted, the whole scene will be updated.
- updateHelper(QRectF(), false, true);
+ if (scene) {
+ scene->d_func()->markDirty(q_ptr, QRect(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/true);
+ }
}
}
- // Resolve opacity.
- updateEffectiveOpacity();
-
// Resolve depth.
resolveDepth(parent ? parent->d_ptr->depth : -1);
-
- // Invalidate transform cache.
- invalidateSceneTransformCache();
+ dirtySceneTransform = 1;
// Deliver post-change notification
q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
@@ -914,20 +957,18 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, bool de
*/
void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect)
{
+ if (!dirtyChildrenBoundingRect) {
+ *rect |= x->mapRect(childrenBoundingRect);
+ return;
+ }
+
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *child = children.at(i);
QGraphicsItemPrivate *childd = child->d_ptr;
- bool hasX = childd->hasTransform;
bool hasPos = !childd->pos.isNull();
- if (hasPos || hasX) {
- QTransform matrix;
- if (hasX)
- matrix = child->transform();
- if (hasPos) {
- const QPointF &p = childd->pos;
- matrix *= QTransform::fromTranslate(p.x(), p.y());
- }
- matrix *= *x;
+ if (hasPos || childd->transformData) {
+ // COMBINE
+ QTransform matrix = childd->transformToParent() * *x;
*rect |= matrix.mapRect(child->boundingRect());
if (!childd->children.isEmpty())
childd->childrenBoundingRectHelper(&matrix, rect);
@@ -937,6 +978,9 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec
childd->childrenBoundingRectHelper(x, rect);
}
}
+
+ childrenBoundingRect = *rect;
+ dirtyChildrenBoundingRect = 0;
}
void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
@@ -968,14 +1012,12 @@ void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, con
return;
// Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect).
-
- const QTransform itemToViewportTransform = q->deviceTransform(worldTransform);
- option->matrix = itemToViewportTransform.toAffine(); //### discards perspective
+ option->matrix = worldTransform.toAffine(); //### discards perspective
if (!allItems) {
// Determine the item's exposed area
option->exposedRect = QRectF();
- const QTransform reverseMap = itemToViewportTransform.inverted();
+ const QTransform reverseMap = worldTransform.inverted();
const QVector<QRect> exposedRects(exposedRegion.rects());
for (int i = 0; i < exposedRects.size(); ++i) {
option->exposedRect |= reverseMap.mapRect(exposedRects.at(i));
@@ -1062,20 +1104,22 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent,
*/
QGraphicsItem::~QGraphicsItem()
{
- if (d_ptr->scene && !d_ptr->parent)
- d_ptr->scene->d_func()->unregisterTopLevelItem(this);
+ d_ptr->inDestructor = 1;
+ d_ptr->removeExtraItemCache();
clearFocus();
+ if (!d_ptr->children.isEmpty()) {
+ QList<QGraphicsItem *> oldChildren = d_ptr->children;
+ qDeleteAll(oldChildren);
+ Q_ASSERT(d_ptr->children.isEmpty());
+ }
- d_ptr->removeExtraItemCache();
- QList<QGraphicsItem *> oldChildren = d_ptr->children;
- qDeleteAll(oldChildren);
- Q_ASSERT(d_ptr->children.isEmpty());
-
- d_ptr->setParentItemHelper(0, /* deleting = */ true);
if (d_ptr->scene)
- d_ptr->scene->d_func()->_q_removeItemLater(this);
+ d_ptr->scene->d_func()->removeItemHelper(this);
+ else
+ d_ptr->setParentItemHelper(0);
+ delete d_ptr->transformData;
delete d_ptr;
qt_dataStore()->data.remove(this);
@@ -1217,7 +1261,7 @@ QGraphicsWidget *QGraphicsItem::window() const
*/
void QGraphicsItem::setParentItem(QGraphicsItem *parent)
{
- d_ptr->setParentItemHelper(parent, /* deleting = */ false);
+ d_ptr->setParentItemHelper(parent);
}
/*!
@@ -1322,7 +1366,9 @@ static void _q_qgraphicsItemSetFlag(QGraphicsItem *item, QGraphicsItem::Graphics
item was selected, and \a flags does not enabled ItemIsSelectable, the
item is automatically unselected.
- By default, no flags are enabled.
+ By default, no flags are enabled. (QGraphicsWidget enables the
+ ItemSendsGeometryChanges flag by default in order to track position
+ changes.)
\sa flags(), setFlag()
*/
@@ -1339,7 +1385,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);
bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
if (fullUpdate)
- d_ptr->fullUpdateHelper(false, true);
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
// Keep the old flags to compare the diff.
GraphicsItemFlags oldFlags = this->flags();
@@ -1347,11 +1393,6 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
// Update flags.
d_ptr->flags = flags;
- // Reresolve effective opacity if the opacity flags change.
- static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren;
- if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask))
- d_ptr->updateEffectiveOpacity();
-
if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
// Clear focus on the item if it has focus when the focusable flag
// is unset.
@@ -1379,8 +1420,19 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
}
- // ### Why updateHelper?
- d_ptr->updateHelper(QRectF(), false, true);
+ if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
+ // Ensure child item sorting is up to date when toggling this flag.
+ if (d_ptr->parent)
+ d_ptr->parent->d_ptr->needSortChildren = 1;
+ else if (d_ptr->scene)
+ d_ptr->scene->d_func()->needSortTopLevelItems = 1;
+ }
+
+ if (d_ptr->scene) {
+ d_ptr->scene->d_func()->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath*/true);
+ }
// Notify change.
itemChange(ItemFlagsHaveChanged, quint32(flags));
@@ -1646,7 +1698,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
if (c)
c->purge();
- updateHelper(QRectF(), /* force = */ true);
+ if (scene) {
+ scene->d_func()->markDirty(q_ptr, QRectF(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/false,
+ /*force=*/true);
+ }
}
// Certain properties are dropped as an item becomes invisible.
@@ -1809,8 +1866,8 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo
enabled = newEnabledVariant.toBool();
// Schedule redraw.
- if (update)
- updateHelper();
+ if (update && scene)
+ scene->d_func()->markDirty(q_ptr);
foreach (QGraphicsItem *child, children) {
if (!newEnabled || !child->d_ptr->explicitlyDisabled)
@@ -1911,9 +1968,8 @@ void QGraphicsItem::setSelected(bool selected)
return;
d_ptr->selected = newSelected;
- d_ptr->updateHelper();
-
if (d_ptr->scene) {
+ d_ptr->scene->d_func()->markDirty(this);
QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
if (selected) {
sceneD->selectedItems << this;
@@ -1949,12 +2005,7 @@ void QGraphicsItem::setSelected(bool selected)
*/
qreal QGraphicsItem::opacity() const
{
- if (d_ptr->hasOpacity) {
- QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity);
- if (!o.isNull())
- return o.toDouble();
- }
- return qreal(1.0);
+ return d_ptr->opacity;
}
/*!
@@ -1970,11 +2021,7 @@ qreal QGraphicsItem::opacity() const
*/
qreal QGraphicsItem::effectiveOpacity() const
{
- if (!d_ptr->hasEffectiveOpacity)
- return qreal(1.0);
-
- QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity);
- return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble());
+ return d_ptr->effectiveOpacity();
}
/*!
@@ -2009,30 +2056,21 @@ void QGraphicsItem::setOpacity(qreal opacity)
newOpacity = qBound<qreal>(0.0, newOpacity, 1.0);
// No change? Done.
- if (qFuzzyIsNull(newOpacity - this->opacity()))
+ if (newOpacity == d_ptr->opacity)
return;
- // Assign local opacity.
- if (qFuzzyIsNull(newOpacity - 1)) {
- // Opaque, unset opacity.
- d_ptr->hasOpacity = 0;
- d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity);
- } else {
- d_ptr->hasOpacity = 1;
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity));
- }
-
- // Resolve effective opacity.
- if (QGraphicsItem *p = d_ptr->parent)
- d_ptr->resolveEffectiveOpacity(p->effectiveOpacity());
- else
- d_ptr->resolveEffectiveOpacity(1.0);
+ d_ptr->opacity = newOpacity;
// Notify change.
- itemChange(ItemOpacityHasChanged, newOpacity);
+ itemChange(ItemOpacityHasChanged, newOpacityVariant);
// Update.
- d_ptr->fullUpdateHelper(/*childrenOnly=*/false, /*maybeDirtyClipPath=*/false, /*ignoreOpacity=*/true);
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath=*/false,
+ /*force=*/false,
+ /*ignoreOpacity=*/true);
}
/*!
@@ -2463,38 +2501,33 @@ QPointF QGraphicsItem::scenePos() const
/*!
\internal
- Sets the position \a pos and notifies the change. If \a update is true,
- the item is also updated; otherwise it is not updated before and after the
- change.
+ Sets the position \a pos.
*/
void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
{
Q_Q(QGraphicsItem);
- if (this->pos == pos)
- return;
-
- // Notify the item that the position is changing.
- const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos));
- QPointF newPos = newPosVariant.toPointF();
- if (newPos == this->pos)
- return;
-
- // Update and repositition.
inSetPosHelper = 1;
- updateCachedClipPathFromSetPosHelper(newPos);
- if (scene) {
- fullUpdateHelper(true);
+ updateCachedClipPathFromSetPosHelper(pos);
+ if (scene)
q->prepareGeometryChange();
- }
- this->pos = newPos;
- invalidateSceneTransformCache();
-
- // Send post-notification.
- q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
+ this->pos = pos;
+ dirtySceneTransform = 1;
inSetPosHelper = 0;
}
/*!
+ \internal
+
+ Sets the transform \a transform.
+*/
+void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform)
+{
+ q_ptr->prepareGeometryChange();
+ transformData->transform = transform;
+ dirtySceneTransform = 1;
+}
+
+/*!
Sets the position of the item to \a pos, which is in parent
coordinates. For items with no parent, \a pos is in scene
coordinates.
@@ -2506,7 +2539,26 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
*/
void QGraphicsItem::setPos(const QPointF &pos)
{
- d_ptr->setPosHelper(pos);
+ if (d_ptr->pos == pos)
+ return;
+
+ // Update and repositition.
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setPosHelper(pos);
+ return;
+ }
+
+ // Notify the item that the position is changing.
+ const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos)));
+ QPointF newPos = newPosVariant.toPointF();
+ if (newPos == d_ptr->pos)
+ return;
+
+ // Update and repositition.
+ d_ptr->setPosHelper(newPos);
+
+ // Send post-notification.
+ itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
}
/*!
@@ -2591,19 +2643,9 @@ QMatrix QGraphicsItem::matrix() const
*/
QTransform QGraphicsItem::transform() const
{
- if (!d_ptr->hasTransform)
+ if (!d_ptr->transformData)
return QTransform();
- if (d_ptr->hasDecomposedTransform && d_ptr->dirtyTransform) {
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- QTransform x;
- decomposed->generateTransform(&x);
- QVariant v(x);
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, v);
- d_ptr->dirtyTransform = 0;
- const_cast<QGraphicsItem *>(this)->itemChange(ItemTransformHasChanged, v);
- return x;
- }
- return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform));
+ return d_ptr->transformData->transform;
}
/*!
@@ -2613,14 +2655,15 @@ QTransform QGraphicsItem::transform() const
The default is 0
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
\sa setXRotation(), {Transformations}
*/
qreal QGraphicsItem::xRotation() const
{
- return d_ptr->decomposedTransform()->xRotation;
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->xRotation;
}
/*!
@@ -2628,23 +2671,17 @@ qreal QGraphicsItem::xRotation() const
Sets the rotation around the X axis to \a angle degrees.
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
- \sa xRotation(), {Transformations}
+ \sa xRotation(), setTransformOrigin(), {Transformations}
*/
void QGraphicsItem::setXRotation(qreal angle)
{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->xRotation = angle;
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xRotation = angle;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2654,14 +2691,15 @@ void QGraphicsItem::setXRotation(qreal angle)
The default is 0
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
\sa setYRotation(), {Transformations}
*/
qreal QGraphicsItem::yRotation() const
{
- return d_ptr->decomposedTransform()->yRotation;
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->yRotation;
}
/*!
@@ -2669,23 +2707,17 @@ qreal QGraphicsItem::yRotation() const
Sets the rotation around the Y axis to \a angle degrees.
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
- \sa yRotation(), {Transformations}
+ \sa yRotation(), setTransformOrigin() {Transformations}
*/
void QGraphicsItem::setYRotation(qreal angle)
{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->yRotation = angle;
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->yRotation = angle;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2695,14 +2727,15 @@ void QGraphicsItem::setYRotation(qreal angle)
The default is 0
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
\sa setZRotation(), {Transformations}
*/
qreal QGraphicsItem::zRotation() const
{
- return d_ptr->decomposedTransform()->zRotation;
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->zRotation;
}
/*!
@@ -2710,23 +2743,17 @@ qreal QGraphicsItem::zRotation() const
Sets the rotation around the Z axis to \a angle degrees.
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
- \sa zRotation(), {Transformations}
+ \sa zRotation(), setTransformOrigin(), {Transformations}
*/
void QGraphicsItem::setZRotation(qreal angle)
{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->zRotation = angle;
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->zRotation = angle;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2735,13 +2762,17 @@ void QGraphicsItem::setZRotation(qreal angle)
This convenience function set the rotation angles around the 3 axes
to \a x, \a y and \a z.
- \sa setXRotation(), setYRotation(), setZRotation()
+ \sa setXRotation(), setYRotation(), setZRotation(), {Transformations}
*/
void QGraphicsItem::setRotation(qreal x, qreal y, qreal z)
{
- setXRotation(x);
- setYRotation(y);
- setZRotation(z);
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xRotation = x;
+ d_ptr->transformData->yRotation = y;
+ d_ptr->transformData->zRotation = z;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2751,14 +2782,15 @@ void QGraphicsItem::setRotation(qreal x, qreal y, qreal z)
The default is 1
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
\sa setXScale(), {Transformations}
*/
qreal QGraphicsItem::xScale() const
{
- return d_ptr->decomposedTransform()->xScale;
+ if (!d_ptr->transformData)
+ return 1;
+ return d_ptr->transformData->xScale;
}
/*!
@@ -2766,23 +2798,17 @@ qreal QGraphicsItem::xScale() const
Sets the scale factor on the X axis to \a factor.
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
- \sa xScale(), {Transformations}
+ \sa xScale(), setTransformOrigin(), {Transformations}
*/
void QGraphicsItem::setXScale(qreal factor)
{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->xScale = factor;
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xScale = factor;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2792,14 +2818,15 @@ void QGraphicsItem::setXScale(qreal factor)
The default is 1
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
\sa setYScale(), {Transformations}
*/
qreal QGraphicsItem::yScale() const
{
- return d_ptr->decomposedTransform()->yScale;
+ if (!d_ptr->transformData)
+ return 1;
+ return d_ptr->transformData->yScale;
}
/*!
@@ -2807,23 +2834,17 @@ qreal QGraphicsItem::yScale() const
Sets the scale factor on the Y axis to \a factor.
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
- \sa yScale(), {Transformations}
+ \sa yScale(), setTransformOrigin(), {Transformations}
*/
void QGraphicsItem::setYScale(qreal factor)
{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->yScale = factor;
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->yScale = factor;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2831,12 +2852,18 @@ void QGraphicsItem::setYScale(qreal factor)
This convenience function set the scaling factors on X and Y axis to \a sx and \a sy.
- \sa setXScale(), setYScale()
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
+
+ \sa setXScale(), setYScale(), {Transformations}
*/
void QGraphicsItem::setScale(qreal sx, qreal sy)
{
- setXScale(sx);
- setYScale(sy);
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xScale = sx;
+ d_ptr->transformData->yScale = sy;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2846,14 +2873,15 @@ void QGraphicsItem::setScale(qreal sx, qreal sy)
The default is 0
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
\sa setHorizontalShear(), {Transformations}
*/
qreal QGraphicsItem::horizontalShear() const
{
- return d_ptr->decomposedTransform()->horizontalShear;
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->horizontalShear;
}
/*!
@@ -2861,23 +2889,17 @@ qreal QGraphicsItem::horizontalShear() const
Sets the horizontal shear to \a shear.
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
\sa horizontalShear(), {Transformations}
*/
void QGraphicsItem::setHorizontalShear(qreal shear)
{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->horizontalShear = shear;
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->horizontalShear = shear;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2887,14 +2909,15 @@ void QGraphicsItem::setHorizontalShear(qreal shear)
The default is 0
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
\sa setHorizontalShear(), {Transformations}
*/
qreal QGraphicsItem::verticalShear() const
{
- return d_ptr->decomposedTransform()->verticalShear;
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->verticalShear;
}
/*!
@@ -2902,23 +2925,17 @@ qreal QGraphicsItem::verticalShear() const
Sets the vertical shear to \a shear.
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
\sa verticalShear(), {Transformations}
*/
void QGraphicsItem::setVerticalShear(qreal shear)
{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->verticalShear = shear;
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->verticalShear = shear;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
@@ -2926,69 +2943,62 @@ void QGraphicsItem::setVerticalShear(qreal shear)
This convenience function sets the horizontal shear to \a sh and the vertical shear to \a sv.
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
+
\sa setHorizontalShear(), setVerticalShear()
*/
void QGraphicsItem::setShear(qreal sh, qreal sv)
{
- setHorizontalShear(sh);
- setVerticalShear(sv);
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->horizontalShear = sh;
+ d_ptr->transformData->verticalShear = sv;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
\since 4.6
- Returns the transformation origin for the transformation properties.
+ Returns the origin point using for transformation in item coordinate.
The default is QPointF(0,0).
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, this function return the default value.
-
\sa setTransformOrigin(), {Transformations}
*/
QPointF QGraphicsItem::transformOrigin() const
{
- const QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- return QPointF(decomposed->xOrigin, decomposed->yOrigin);
+ if (!d_ptr->transformData)
+ return QPointF(0,0);
+ return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin);
}
/*!
- \fn inline void setTransformOrigin(qreal x, qreal y)
-
\since 4.6
- This is an overloaded member function, provided for convenience.
- Sets the transformation origin for the transformation
- properties to the point(\a x, \a y).
+ Sets the origin for transformation in item coordinate
- \sa setTransformOrigin(), {Transformations}
+ \sa transformOrigin(), {Transformations}
*/
+void QGraphicsItem::setTransformOrigin(const QPointF &origin)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xOrigin = origin.x();
+ d_ptr->transformData->yOrigin = origin.y();
+ d_ptr->dirtySceneTransform = 1;
+}
/*!
- \since 4.6
-
- Sets the transformation origin for the transformation properties to \a origin.
- This does not apply to the transformation set by setTransform.
+ \fn inline void setTransformOrigin(qreal x, qreal y)
- \warning setting this property is conflicting with calling setTransform.
- If a transform has been set, it will be overwritten.
+ \since 4.6
+ \overload
- \sa transformOrigin(), {Transformations}
+ \sa setTransformOrigin(), {Transformations}
*/
-void QGraphicsItem::setTransformOrigin(const QPointF &origin)
-{
- if (!d_ptr->dirtyTransform) {
- d_ptr->fullUpdateHelper(true);
- prepareGeometryChange();
- }
- QGraphicsItemPrivate::DecomposedTransform *decomposed = d_ptr->decomposedTransform();
- decomposed->xOrigin = origin.x();
- decomposed->yOrigin = origin.y();
- if (!d_ptr->dirtyTransform)
- d_ptr->invalidateSceneTransformCache();
- d_ptr->dirtyTransform = 1;
- d_ptr->hasTransform = 1;
-}
+
/*!
\obsolete
@@ -3016,51 +3026,23 @@ QMatrix QGraphicsItem::sceneMatrix() const
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 4
Unlike transform(), which returns only an item's local transformation, this
- function includes the item's (and any parents') position.
+ function includes the item's (and any parents') position, and all the transfomation properties.
- \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}
+ \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations}
*/
QTransform QGraphicsItem::sceneTransform() const
{
- // Check if there's any entry in the transform cache.
- QGraphicsScenePrivate *sd = d_ptr->scene ? d_ptr->scene->d_func() : 0;
- int index = d_ptr->sceneTransformIndex;
- if (sd && index != -1 && sd->validTransforms.testBit(index))
- return sd->sceneTransformCache[index];
-
- // Calculate local transform.
- QTransform m;
- if (d_ptr->hasTransform) {
- m = transform();
- if (!d_ptr->pos.isNull())
- m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- } else if (!d_ptr->pos.isNull()) {
- m = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- }
-
- // Combine with parent and add to cache.
- if (d_ptr->parent) {
- m *= d_ptr->parent->sceneTransform();
- // Don't cache toplevels
- if (sd) {
- if (index == -1) {
- if (!sd->freeSceneTransformSlots.isEmpty()) {
- index = sd->freeSceneTransformSlots.last();
- sd->freeSceneTransformSlots.pop_back();
- } else {
- index = sd->sceneTransformCache.size();
- }
- d_ptr->sceneTransformIndex = index;
- if (index >= sd->validTransforms.size()) {
- sd->validTransforms.resize(index + 1);
- sd->sceneTransformCache.resize(index + 1);
- }
- }
- sd->validTransforms.setBit(index, 1);
- sd->sceneTransformCache[index] = m;
- }
+ if (d_ptr->dirtySceneTransform) {
+ // This item and all its descendants have dirty scene transforms.
+ // We're about to validate this item's scene transform, so we have to
+ // invalidate all the children; otherwise there's no way for the descendants
+ // to detect that the ancestor has changed.
+ d_ptr->invalidateChildrenSceneTransform();
}
- return m;
+
+ QGraphicsItem *that = const_cast<QGraphicsItem *>(this);
+ d_ptr->ensureSceneTransformRecursive(&that);
+ return d_ptr->sceneTransform;
}
/*!
@@ -3110,17 +3092,17 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c
// First translate the base untransformable item.
QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0));
+
+ // COMBINE
QTransform matrix;
matrix.translate(mappedPoint.x(), mappedPoint.y());
- matrix = untransformedAncestor->transform() * matrix;
+ if (untransformedAncestor->d_ptr->transformData)
+ matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform() * matrix;
// Then transform and translate all children.
for (int i = 0; i < parents.size(); ++i) {
const QGraphicsItem *parent = parents.at(i);
- QPointF pos = parent->pos();
- QTransform moveMatrix;
- moveMatrix.translate(pos.x(), pos.y());
- matrix = (parent->transform() * moveMatrix) * matrix;
+ parent->d_ptr->combineTransformFromParent(&matrix);
}
return matrix;
@@ -3163,51 +3145,40 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
if (parent == other) {
if (ok)
*ok = true;
- const QPointF &itemPos = d_ptr->pos;
- if (itemPos.isNull())
- return d_ptr->hasTransform ? transform() : QTransform();
- if (d_ptr->hasTransform)
- return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y());
- return QTransform::fromTranslate(itemPos.x(), itemPos.y());
+ QTransform x;
+ d_ptr->combineTransformFromParent(&x);
+ return x;
}
// This is other's parent
if (otherParent == this) {
const QPointF &otherPos = other->d_ptr->pos;
- if (other->d_ptr->hasTransform) {
- QTransform otherToParent = other->transform();
- if (!otherPos.isNull())
- otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y());
+ if (other->d_ptr->transformData) {
+ QTransform otherToParent;
+ other->d_ptr->combineTransformFromParent(&otherToParent);
return otherToParent.inverted(ok);
- } else {
- if (ok)
- *ok = true;
- return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
}
+ if (ok)
+ *ok = true;
+ return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
}
// Siblings
if (parent == otherParent) {
- bool hasTr = d_ptr->hasTransform;
- bool otherHasTr = other->d_ptr->hasTransform;
+ // COMBINE
const QPointF &itemPos = d_ptr->pos;
const QPointF &otherPos = other->d_ptr->pos;
-
- if (!hasTr && !otherHasTr) {
+ if (!d_ptr->transformData && !other->d_ptr->transformData) {
QPointF delta = itemPos - otherPos;
if (ok)
*ok = true;
return QTransform::fromTranslate(delta.x(), delta.y());
}
- QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y());
- if (hasTr)
- itemToParent = itemPos.isNull() ? transform() : transform() * itemToParent;
-
- QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y());
- if (otherHasTr)
- otherToParent = otherPos.isNull() ? other->transform() : other->transform() * otherToParent;
-
+ QTransform itemToParent;
+ d_ptr->combineTransformFromParent(&itemToParent);
+ QTransform otherToParent;
+ other->d_ptr->combineTransformFromParent(&otherToParent);
return itemToParent * otherToParent.inverted(ok);
}
@@ -3243,11 +3214,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
QTransform x;
const QGraphicsItem *p = child;
do {
- const QGraphicsItemPrivate *pd = p->d_ptr;
- if (pd->hasTransform)
- x *= p->transform();
- if (!pd->pos.isNull())
- x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y());
+ p->d_ptr->combineTransformToParent(&x);
} while ((p = p->d_ptr->parent) && p != root);
if (parentOfOther)
return x.inverted(ok);
@@ -3269,35 +3236,30 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
*/
void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
- QTransform newTransform;
- if (!combine)
- newTransform = QTransform(matrix);
- else
- newTransform = QTransform(matrix) * oldTransform;
- if (oldTransform == newTransform)
- return;
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- // Notify the item that the matrix is changing.
- QVariant newTransformVariant(itemChange(ItemMatrixChange,
- qVariantFromValue<QMatrix>(newTransform.toAffine())));
- newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant));
- if (oldTransform == newTransform)
+ QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix));
+ if (d_ptr->transformData->transform == newTransform)
return;
// Update and set the new transformation.
- d_ptr->fullUpdateHelper(true, true);
- prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
- d_ptr->dirtyTransformComponents = 1;
- d_ptr->dirtyTransform = 0;
- d_ptr->invalidateSceneTransformCache();
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setTransformHelper(newTransform);
+ return;
+ }
+ // Notify the item that the transformation matrix is changing.
+ const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine());
+ newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant)));
+ if (d_ptr->transformData->transform == newTransform)
+ return;
+
+ // Update and set the new transformation.
+ d_ptr->setTransformHelper(newTransform);
+
// Send post-notification.
- // NB! We have to change the value from QMatrix to QTransform.
- qVariantSetValue<QTransform>(newTransformVariant, newTransform);
- itemChange(ItemTransformHasChanged, newTransformVariant);
+ itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform));
}
/*!
@@ -3315,37 +3277,34 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
to map an item coordiate to a scene coordinate, or mapFromScene() to map
from scene coordinates to item coordinates.
- \warning using this function conflicts with using the transformation properties.
- If you set a transformation, getting the properties will return default values.
+ \warning using this function doesnt affect the value of the transformation properties
- \sa transform(), setRotation(), setScale(), setShear(), setTransformOrigin() {The Graphics View Coordinate System}
+ \sa transform(), setRotation(), setScale(), setShear(), setTransformOrigin(), {The Graphics View Coordinate System}, {Transformations}
*/
void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
- QTransform newTransform;
- if (!combine)
- newTransform = matrix;
- else
- newTransform = matrix * oldTransform;
- if (oldTransform == newTransform)
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+
+ QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix);
+ if (d_ptr->transformData->transform == newTransform)
+ return;
+
+ // Update and set the new transformation.
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setTransformHelper(newTransform);
return;
+ }
// Notify the item that the transformation matrix is changing.
const QVariant newTransformVariant(itemChange(ItemTransformChange,
qVariantFromValue<QTransform>(newTransform)));
newTransform = qVariantValue<QTransform>(newTransformVariant);
- if (oldTransform == newTransform)
+ if (d_ptr->transformData->transform == newTransform)
return;
// Update and set the new transformation.
- d_ptr->fullUpdateHelper(true, true);
- prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
- d_ptr->dirtyTransformComponents = 1;
- d_ptr->dirtyTransform = 0;
- d_ptr->invalidateSceneTransformCache();
+ d_ptr->setTransformHelper(newTransform);
// Send post-notification.
itemChange(ItemTransformHasChanged, newTransformVariant);
@@ -3387,8 +3346,7 @@ void QGraphicsItem::resetTransform()
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 6
- \warning using this function conflicts with using the transformation properties.
- Getting those properties after using this function will return default values.
+ \warning using this functionhas no effect on the zRotation value
\sa setTransform(), transform(), scale(), shear(), translate()
*/
@@ -3409,8 +3367,7 @@ void QGraphicsItem::rotate(qreal angle)
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7
- \warning using this function conflicts with using the transformation properties.
- Getting those properties after using this function will return default values.
+ \warning using this function has no effect on the xScale or yScale value
\sa setTransform(), transform()
*/
@@ -3425,8 +3382,7 @@ void QGraphicsItem::scale(qreal sx, qreal sy)
Shears the current item transformation by (\a sh, \a sv).
- \warning using this function conflicts with using the transformation properties.
- Getting those properties after using this function will return default values.
+ \warning using this function has no effect on the horizontalShear or verticalShear value
\sa setTransform(), transform()
*/
@@ -3445,9 +3401,6 @@ void QGraphicsItem::shear(qreal sh, qreal sv)
setPos() instead; this function changes the item's translation,
which is conceptually separate from its position.
- \warning using this function conflicts with using the transformation properties.
- Getting those properties after using this function will return default values.
-
\sa setTransform(), transform()
*/
void QGraphicsItem::translate(qreal dx, qreal dy)
@@ -3526,11 +3479,16 @@ void QGraphicsItem::setZValue(qreal z)
if (newZ == d_ptr->z)
return;
d_ptr->z = newZ;
- d_ptr->fullUpdateHelper();
+ if (d_ptr->parent)
+ d_ptr->parent->d_ptr->needSortChildren = 1;
+ else if (d_ptr->scene)
+ d_ptr->scene->d_func()->needSortTopLevelItems = 1;
- //Z Value has changed, we have to notify the index.
- if (d_ptr->scene)
+ if (d_ptr->scene) {
+ d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
+ //Z Value has changed, we have to notify the index.
d_ptr->scene->d_func()->index->itemChanged(this, ItemZValueChange, z);
+ }
itemChange(ItemZValueHasChanged, newZVariant);
}
@@ -3554,6 +3512,9 @@ void QGraphicsItem::setZValue(qreal z)
*/
QRectF QGraphicsItem::childrenBoundingRect() const
{
+ if (!d_ptr->dirtyChildrenBoundingRect)
+ return d_ptr->childrenBoundingRect;
+
QRectF childRect;
QTransform x;
d_ptr->childrenBoundingRectHelper(&x, &childRect);
@@ -3602,12 +3563,13 @@ QRectF QGraphicsItem::childrenBoundingRect() const
QRectF QGraphicsItem::sceneBoundingRect() const
{
// Find translate-only offset
+ // COMBINE
QPointF offset;
const QGraphicsItem *parentItem = this;
const QGraphicsItemPrivate *itemd;
do {
itemd = parentItem->d_ptr;
- if (itemd->hasTransform)
+ if (itemd->transformData)
break;
offset += itemd->pos;
} while ((parentItem = itemd->parent));
@@ -4184,7 +4146,7 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore
// No scene, or if the scene is updating everything, means we have nothing
// to do. The only exception is if the scene tracks the growing scene rect.
return (!visible && !ignoreVisibleBit)
- || (dirty && !ignoreDirtyBit)
+ || (!ignoreDirtyBit && fullUpdatePending)
|| !scene
|| (scene->d_func()->updateAll && scene->d_func()->hasSceneRect)
|| (!ignoreClipping && (childrenClippedToShape() && isClippedAway()))
@@ -4194,141 +4156,6 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore
/*!
\internal
- Asks the scene to mark this item's scene rect as dirty, requesting a
- redraw. This does not invalidate any cache.
-
- The \a force argument is for the update call in setVisible(), which is the
- only case where the item's background should be marked as dirty even when
- the item isn't visible.
-*/
-void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool maybeDirtyClipPath)
-{
- // No scene, or if the scene is updating everything, means we have nothing
- // to do. The only exception is if the scene tracks the growing scene rect.
- if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force))
- return;
-
- if (rect.isNull())
- dirty = 1;
- scene->itemUpdated(q_ptr, rect);
-}
-
-/*!
- \internal
-
- Propagates updates to \a item and all its children.
-*/
-void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath, bool ignoreOpacity)
-{
- if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/false,
- /*ignoreDirtyBit=*/true, ignoreOpacity)) {
- return;
- }
-
- if (!childrenOnly && !dirty) {
- // Effectively the same as updateHelper(QRectF(), false, maybeDirtyClipPath).
- dirty = 1;
- scene->itemUpdated(q_ptr, QRectF());
- }
-
- if (dirtyChildren || childrenClippedToShape()) {
- // Unnecessary to update children as well.
- return;
- }
-
- if (ancestorFlags & AncestorClipsChildren) {
- Q_Q(QGraphicsItem);
- // Check if we can avoid updating all children.
- QGraphicsItem *p = parent;
- QRectF br = q->boundingRect();
- while (p) {
- if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
- bool ok;
- QTransform x = q->itemTransform(p, &ok);
- if (!ok)
- break;
- if (x.mapRect(br).contains(p->boundingRect()))
- return;
- }
- p = p->d_ptr->parent;
- if (!p || !(p->d_ptr->ancestorFlags & AncestorClipsChildren))
- break;
- // ### check one level only
- break;
- }
- }
- foreach (QGraphicsItem *child, children)
- child->d_ptr->fullUpdateHelper(false, maybeDirtyClipPath);
- dirtyChildren = 1;
-}
-
-static inline bool allChildrenCombineOpacityHelper(QGraphicsItem *parent)
-{
- Q_ASSERT(parent);
- if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
- return false;
-
- const QList<QGraphicsItem *> children(parent->childItems());
- for (int i = 0; i < children.size(); ++i) {
- if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity)
- return false;
- }
- return true;
-}
-
-void QGraphicsItemPrivate::updateEffectiveOpacity()
-{
- Q_Q(QGraphicsItem);
- if (parent) {
- resolveEffectiveOpacity(parent->effectiveOpacity());
- parent->d_ptr->allChildrenCombineOpacity = allChildrenCombineOpacityHelper(parent);
- } else {
- resolveEffectiveOpacity(1.0);
- }
- allChildrenCombineOpacity = allChildrenCombineOpacityHelper(q);
-}
-
-/*!
- \internal
-
- Resolves and propagates this item's effective opacity to its children.
-*/
-void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity)
-{
- Q_Q(QGraphicsItem);
- QGraphicsItem::GraphicsItemFlags myFlags = q->flags();
- QGraphicsItem::GraphicsItemFlags parentFlags = parent ? parent->flags() : QGraphicsItem::GraphicsItemFlags(0);
-
- // My local opacity is always part of my effective opacity.
- qreal myEffectiveOpacity = q->opacity();
-
- // If I have a parent, and I don't ignore my parent's opacity, and my
- // parent propagates to me, then combine my local opacity with my parent's
- // effective opacity into my effective opacity.
- if (parent
- && !(myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
- && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
- myEffectiveOpacity *= parentEffectiveOpacity;
- }
-
- // Set this item's resolved opacity.
- if (qFuzzyIsNull(myEffectiveOpacity - 1)) {
- // Opaque, unset effective opacity.
- hasEffectiveOpacity = 0;
- unsetExtra(ExtraEffectiveOpacity);
- } else {
- hasEffectiveOpacity = 1;
- setExtra(ExtraEffectiveOpacity, myEffectiveOpacity);
- }
-
- // Resolve children always.
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->resolveEffectiveOpacity(myEffectiveOpacity);
-}
-
-/*!
- \internal
-
Resolves the stacking depth of this object and all its children.
*/
void QGraphicsItemPrivate::resolveDepth(int parentDepth)
@@ -4341,22 +4168,9 @@ void QGraphicsItemPrivate::resolveDepth(int parentDepth)
/*!
\internal
*/
-void QGraphicsItemPrivate::invalidateSceneTransformCache()
-{
- if (!scene || (parent && sceneTransformIndex == -1))
- return;
- if (sceneTransformIndex != -1)
- scene->d_func()->validTransforms.setBit(sceneTransformIndex, 0);
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->invalidateSceneTransformCache();
-}
-
-/*!
- \internal
-*/
void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
{
- child->d_ptr->siblingIndex = children.size();
+ needSortChildren = 1;
children.append(child);
}
@@ -4365,14 +4179,7 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
*/
void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
{
- int idx = child->d_ptr->siblingIndex;
- int size = children.size();
- for (int i = idx; i < size - 1; ++i) {
- QGraphicsItem *p = children[i + 1];
- children[i] = p;
- p->d_ptr->siblingIndex = i;
- }
- children.removeLast();
+ children.removeOne(child);
}
/*!
@@ -4461,17 +4268,11 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
// Find closest clip ancestor and transform.
Q_Q(QGraphicsItem);
- QTransform thisToParentTransform = hasTransform
- ? q->transform() * QTransform::fromTranslate(newPos.x(), newPos.y())
- : QTransform::fromTranslate(newPos.x(), newPos.y());
+ // COMBINE
+ QTransform thisToParentTransform = transformToParent();
QGraphicsItem *clipParent = parent;
while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) {
- if (clipParent->d_ptr->hasTransform)
- thisToParentTransform *= clipParent->transform();
- if (!clipParent->d_ptr->pos.isNull()) {
- thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(),
- clipParent->d_ptr->pos.y());
- }
+ thisToParentTransform *= clipParent->d_ptr->transformToParent();
clipParent = clipParent->d_ptr->parent;
}
@@ -4513,6 +4314,35 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
}
}
+// Traverses all the ancestors up to the top-level and updates the pointer to
+// always point to the top-most item that has a dirty scene transform.
+// It then backtracks to the top-most dirty item and start calculating the
+// scene transform by combining the item's transform (+pos) with the parent's
+// cached scene transform (which we at this point know for sure is valid).
+void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem)
+{
+ Q_ASSERT(topMostDirtyItem);
+
+ if (dirtySceneTransform)
+ *topMostDirtyItem = q_ptr;
+
+ if (parent)
+ parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem);
+
+ if (*topMostDirtyItem == q_ptr) {
+ if (!dirtySceneTransform)
+ return; // OK, neither my ancestors nor I have dirty scene transforms.
+ *topMostDirtyItem = 0;
+ } else if (*topMostDirtyItem) {
+ return; // Continue backtrack.
+ }
+
+ // COMBINE my transform with the parent's scene transform.
+ sceneTransform = parent ? parent->d_ptr->sceneTransform : QTransform();
+ combineTransformFromParent(&sceneTransform);
+ dirtySceneTransform = 0;
+}
+
/*!
\internal
@@ -4564,16 +4394,12 @@ void QGraphicsItem::update(const QRectF &rect)
}
}
// Only invalidate cache; item is already dirty.
- if (d_ptr->dirty)
+ if (d_ptr->fullUpdatePending)
return;
- } else if (d_ptr->discardUpdateRequest()) {
- return;
}
- // Effectively the same as updateHelper(rect);
- if (rect.isNull())
- d_ptr->dirty = 1;
- d_ptr->scene->itemUpdated(this, rect);
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this, rect);
}
/*!
@@ -4671,7 +4497,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
exposed -= r.translated(dx, dy);
foreach (QRect rect, exposed.rects())
update(rect);
- d_ptr->updateHelper();
+ d->scene->d_func()->markDirty(this);
} else {
update(rect);
}
@@ -4700,13 +4526,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
static const QLineF left(0, 0, -1, 0);
static const QLineF right(0, 0, 1, 0);
- QTransform deviceTr;
- if (d->itemIsUntransformable()) {
- deviceTr = deviceTransform(view->viewportTransform());
- } else {
- deviceTr = sceneTransform() * view->viewportTransform();
- }
-
+ QTransform deviceTr = deviceTransform(view->viewportTransform());
QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect();
QLineF v1 = deviceTr.map(right);
QLineF v2 = deviceTr.map(down);
@@ -4838,9 +4658,10 @@ QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point
*/
QPointF QGraphicsItem::mapToParent(const QPointF &point) const
{
- if (!d_ptr->hasTransform)
+ // COMBINE
+ if (!d_ptr->transformData)
return point + d_ptr->pos;
- return transform().map(point) + d_ptr->pos;
+ return d_ptr->transformToParent().map(point);
}
/*!
@@ -4905,9 +4726,10 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect
*/
QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const
{
- if (!d_ptr->hasTransform)
+ // COMBINE
+ if (!d_ptr->transformData)
return rect.translated(d_ptr->pos);
- return transform().map(rect).translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(rect);
}
/*!
@@ -4974,8 +4796,10 @@ QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rec
*/
QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const
{
- QRectF r = !d_ptr->hasTransform ? rect : transform().mapRect(rect);
- return r.translated(d_ptr->pos);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(d_ptr->pos);
+ return d_ptr->transformToParent().mapRect(rect);
}
/*!
@@ -5046,8 +4870,10 @@ QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &r
*/
QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const
{
- QRectF r = rect.translated(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().mapRect(r) : r;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().mapRect(rect);
}
/*!
@@ -5106,9 +4932,10 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &p
*/
QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
{
- if (!d_ptr->hasTransform)
+ // COMBINE
+ if (!d_ptr->transformData)
return polygon.translated(d_ptr->pos);
- return transform().map(polygon).translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(polygon);
}
/*!
@@ -5150,9 +4977,10 @@ QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterP
*/
QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const
{
- if (!d_ptr->hasTransform)
+ // COMBINE
+ if (!d_ptr->transformData)
return path.translated(d_ptr->pos);
- return transform().map(path).translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(path);
}
/*!
@@ -5201,8 +5029,9 @@ QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &poi
*/
QPointF QGraphicsItem::mapFromParent(const QPointF &point) const
{
- if (d_ptr->hasTransform)
- return transform().inverted().map(point - d_ptr->pos);
+ // COMBINE
+ if (d_ptr->transformData)
+ return d_ptr->transformToParent().inverted().map(point);
return point - d_ptr->pos;
}
@@ -5269,8 +5098,10 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &re
*/
QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const
{
- QRectF r = rect.translated(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().map(r) : r;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(rect);
}
/*!
@@ -5325,9 +5156,10 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPolygonF
*/
QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const
{
- QPolygonF p = polygon;
- p.translate(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().map(p) : p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return polygon.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(polygon);
}
/*!
@@ -5367,9 +5199,10 @@ QPainterPath QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPainte
*/
QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const
{
- QPainterPath p(path);
- p.translate(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().map(p) : p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return path.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(path);
}
/*!
@@ -5887,7 +5720,8 @@ void QGraphicsItem::focusOutEvent(QFocusEvent *event)
void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
- d_ptr->updateHelper();
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this);
}
/*!
@@ -5915,7 +5749,8 @@ void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
- d_ptr->updateHelper();
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this);
}
/*!
@@ -6345,7 +6180,6 @@ void QGraphicsItem::addToIndex()
}
if (d_ptr->scene)
d_ptr->scene->d_func()->index->addItem(this);
- d_ptr->updateHelper();
}
/*!
@@ -6357,7 +6191,10 @@ void QGraphicsItem::addToIndex()
*/
void QGraphicsItem::removeFromIndex()
{
- d_ptr->updateHelper();
+ if (d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
+ // ### remove from child index only if applicable
+ return;
+ }
if (d_ptr->scene)
d_ptr->scene->d_func()->index->removeItem(this);
}
@@ -6378,11 +6215,29 @@ void QGraphicsItem::removeFromIndex()
void QGraphicsItem::prepareGeometryChange()
{
if (d_ptr->scene) {
- d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
+ d_ptr->geometryChanged = 1;
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
+
QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
scenePrivate->index->prepareBoundingRectChange(this);
+ scenePrivate->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
+
+ // For compatibility reasons, we have to update the item's old geometry
+ // if someone is connected to the changed signal or the scene has no views.
+ // Note that this has to be done *after* markDirty to ensure that
+ // _q_processDirtyItems is called before _q_emitUpdated.
+ if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask)
+ || scenePrivate->views.isEmpty()) {
+ d_ptr->scene->update(sceneTransform().mapRect(boundingRect()));
+ }
}
+ QGraphicsItem *parent = this;
+ while ((parent = parent->d_ptr->parent))
+ parent->d_ptr->dirtyChildrenBoundingRect = 1;
+
if (d_ptr->inSetPosHelper)
return;
@@ -8043,7 +7898,6 @@ void QGraphicsPixmapItem::setTransformationMode(Qt::TransformationMode mode)
{
Q_D(QGraphicsPixmapItem);
if (mode != d->transformationMode) {
- d_ptr->updateHelper();
d->transformationMode = mode;
update();
}
@@ -9425,6 +9279,8 @@ void QGraphicsItemGroup::addToGroup(QGraphicsItem *item)
return;
}
+ // COMBINE
+ // ### Use itemTransform() instead.
QTransform oldSceneMatrix = item->sceneTransform();
item->setPos(mapFromItem(item, 0, 0));
item->setParentItem(this);
@@ -9666,6 +9522,12 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemUsesExtendedStyleOption:
str = "ItemUsesExtendedStyleOption";
break;
+ case QGraphicsItem::ItemHasNoContents:
+ str = "ItemHasNoContents";
+ break;
+ case QGraphicsItem::ItemSendsGeometryChanges:
+ str = "ItemSendsGeometryChanges";
+ break;
}
debug << str;
return debug;
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 78740336f8..3b1e4038b2 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -95,7 +95,9 @@ public:
ItemIgnoresParentOpacity = 0x40,
ItemDoesntPropagateOpacityToChildren = 0x80,
ItemStacksBehindParent = 0x100,
- ItemUsesExtendedStyleOption = 0x200
+ ItemUsesExtendedStyleOption = 0x200,
+ ItemHasNoContents = 0x400,
+ ItemSendsGeometryChanges = 0x800
// NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index bd81fe5804..562686777c 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -95,25 +95,12 @@ class Q_AUTOTEST_EXPORT QGraphicsItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsItem)
public:
- struct TransformData
- {
- TransformData() : rotationX(0),rotationY(0),rotationZ(0),scaleX(1),scaleY(1), dirty(true) {}
- QTransform baseTransform;
- QTransform transform;
- QPointF transformCenter;
- qreal rotationX,rotationY,rotationZ,scaleX,scaleY;
- bool dirty;
- };
enum Extra {
- ExtraTransform,
ExtraToolTip,
ExtraCursor,
ExtraCacheData,
ExtraMaxDeviceCoordCacheSize,
- ExtraBoundingRegionGranularity,
- ExtraOpacity,
- ExtraEffectiveOpacity,
- ExtraDecomposedTransform
+ ExtraBoundingRegionGranularity
};
enum AncestorFlag {
@@ -125,9 +112,10 @@ public:
inline QGraphicsItemPrivate()
: z(0),
+ opacity(1.),
scene(0),
parent(0),
- siblingIndex(-1),
+ transformData(0),
index(-1),
depth(0),
acceptedMouseButtons(0x1f),
@@ -141,13 +129,10 @@ public:
isMemberOfGroup(0),
handlesChildEvents(0),
itemDiscovered(0),
- hasTransform(0),
hasCursor(0),
ancestorFlags(0),
cacheMode(0),
hasBoundingRegionGranularity(0),
- hasOpacity(0),
- hasEffectiveOpacity(0),
isWidget(0),
dirty(0),
dirtyChildren(0),
@@ -155,13 +140,16 @@ public:
dirtyClipPath(1),
emptyClipPath(0),
inSetPosHelper(0),
+ needSortChildren(1),
+ allChildrenDirty(0),
+ fullUpdatePending(0),
flags(0),
- allChildrenCombineOpacity(1),
- hasDecomposedTransform(0),
- dirtyTransform(0),
- dirtyTransformComponents(0),
+ dirtyChildrenBoundingRect(1),
+ paintedViewBoundingRectsNeedRepaint(0),
+ dirtySceneTransform(1),
+ geometryChanged(0),
+ inDestructor(0),
globalStackingOrder(-1),
- sceneTransformIndex(-1),
q_ptr(0)
{
}
@@ -174,26 +162,29 @@ public:
void setIsMemberOfGroup(bool enabled);
void remapItemPos(QEvent *event, QGraphicsItem *item);
QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const;
- bool itemIsUntransformable() const;
+ inline bool itemIsUntransformable() const
+ {
+ return (flags & QGraphicsItem::ItemIgnoresTransformations)
+ || (ancestorFlags & AncestorIgnoresTransformations);
+ }
+ void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
+ void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
+
// ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4.
virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const;
static bool movableAncestorIsSelected(const QGraphicsItem *item);
void setPosHelper(const QPointF &pos);
+ void setTransformHelper(const QTransform &transform);
void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false,
bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
- void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false);
- void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false, bool ignoreOpacity = false);
- void updateEffectiveOpacity();
- void resolveEffectiveOpacity(qreal effectiveParentOpacity);
void resolveDepth(int parentDepth);
- void invalidateSceneTransformCache();
void addChild(QGraphicsItem *child);
void removeChild(QGraphicsItem *child);
- void setParentItemHelper(QGraphicsItem *parent, bool deleting);
+ void setParentItemHelper(QGraphicsItem *parent);
void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
const QRegion &exposedRegion, bool allItems = false) const;
@@ -287,12 +278,67 @@ public:
void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF());
void updateCachedClipPathFromSetPosHelper(const QPointF &newPos);
+ void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem);
+
+ inline void invalidateChildrenSceneTransform()
+ {
+ for (int i = 0; i < children.size(); ++i)
+ children.at(i)->d_ptr->dirtySceneTransform = 1;
+ }
+
+ inline qreal calcEffectiveOpacity() const
+ {
+ qreal o = opacity;
+ QGraphicsItem *p = parent;
+ int myFlags = flags;
+ while (p) {
+ int parentFlags = p->d_ptr->flags;
+
+ // If I have a parent, and I don't ignore my parent's opacity, and my
+ // parent propagates to me, then combine my local opacity with my parent's
+ // effective opacity into my effective opacity.
+ if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
+ || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
+ break;
+ }
+
+ o *= p->d_ptr->opacity;
+ p = p->d_ptr->parent;
+ myFlags = parentFlags;
+ }
+ return o;
+ }
inline bool isFullyTransparent() const
- { return hasEffectiveOpacity && qFuzzyIsNull(q_func()->effectiveOpacity()); }
+ {
+ if (opacity < 0.001)
+ return true;
+ if (!parent)
+ return false;
+
+ return calcEffectiveOpacity() < 0.001;
+ }
+
+ inline qreal effectiveOpacity() const {
+ if (!parent || !opacity)
+ return opacity;
+
+ return calcEffectiveOpacity();
+ }
inline bool childrenCombineOpacity() const
- { return allChildrenCombineOpacity || children.isEmpty(); }
+ {
+ if (!children.size())
+ return true;
+ if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
+ return false;
+
+ for (int i = 0; i < children.size(); ++i) {
+ if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)
+ return false;
+ }
+ return true;
+ }
inline bool isClippedAway() const
{ return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); }
@@ -307,13 +353,21 @@ public:
|| (childrenCombineOpacity() && isFullyTransparent());
}
+ inline QTransform transformToParent() const;
+
QPainterPath cachedClipPath;
+ QRectF childrenBoundingRect;
+ QRectF needsRepaint;
+ QMap<QWidget *, QRect> paintedViewBoundingRects;
QPointF pos;
qreal z;
+ qreal opacity;
QGraphicsScene *scene;
QGraphicsItem *parent;
QList<QGraphicsItem *> children;
- int siblingIndex;
+ struct TransformData;
+ TransformData *transformData;
+ QTransform sceneTransform;
int index;
int depth;
@@ -329,13 +383,10 @@ public:
quint32 isMemberOfGroup : 1;
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
- quint32 hasTransform : 1;
quint32 hasCursor : 1;
quint32 ancestorFlags : 3;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
- quint32 hasOpacity : 1;
- quint32 hasEffectiveOpacity : 1;
quint32 isWidget : 1;
quint32 dirty : 1;
quint32 dirtyChildren : 1;
@@ -343,89 +394,67 @@ public:
quint32 dirtyClipPath : 1;
quint32 emptyClipPath : 1;
quint32 inSetPosHelper : 1;
+ quint32 needSortChildren : 1;
+ quint32 allChildrenDirty : 1;
+ quint32 fullUpdatePending : 1;
// New 32 bits
- quint32 flags : 10;
- quint32 allChildrenCombineOpacity : 1;
- quint32 hasDecomposedTransform : 1;
- quint32 dirtyTransform : 1;
- quint32 dirtyTransformComponents : 1;
- quint32 padding : 18; // feel free to use
+ quint32 flags : 12;
+ quint32 dirtyChildrenBoundingRect : 1;
+ quint32 paintedViewBoundingRectsNeedRepaint : 1;
+ quint32 dirtySceneTransform : 1;
+ quint32 geometryChanged : 1;
+ quint32 inDestructor : 1;
+ quint32 unused : 15; // feel free to use
// Optional stacking order
int globalStackingOrder;
- int sceneTransformIndex;
+ QGraphicsItem *q_ptr;
+};
- struct DecomposedTransform;
- DecomposedTransform *decomposedTransform() const
+struct QGraphicsItemPrivate::TransformData {
+ QTransform transform;
+ qreal xScale;
+ qreal yScale;
+ qreal xRotation;
+ qreal yRotation;
+ qreal zRotation;
+ qreal horizontalShear;
+ qreal verticalShear;
+ qreal xOrigin;
+ qreal yOrigin;
+
+ TransformData() :
+ xScale(1.0), yScale(1.0), xRotation(0.0), yRotation(0.0), zRotation(0.0),
+ horizontalShear(0.0), verticalShear(0.0), xOrigin(0.0), yOrigin(0.0)
+ {}
+
+ QTransform computedFullTransform() const
{
- QGraphicsItemPrivate *that = const_cast<QGraphicsItemPrivate *>(this);
- DecomposedTransform *decomposed;
- if (hasDecomposedTransform) {
- decomposed = qVariantValue<DecomposedTransform *>(extra(ExtraDecomposedTransform));
- } else {
- decomposed = new DecomposedTransform;
- that->setExtra(ExtraDecomposedTransform, qVariantFromValue<DecomposedTransform *>(decomposed));
- that->hasDecomposedTransform = 1;
- if (!dirtyTransformComponents)
- decomposed->reset();
- }
- if (dirtyTransformComponents) {
- decomposed->initFrom(q_ptr->transform());
- that->dirtyTransformComponents = 0;
- }
- return decomposed;
+ QTransform x;
+ x.translate(xOrigin, yOrigin);
+ x = transform * x;
+ x.rotate(xRotation, Qt::XAxis);
+ x.rotate(yRotation, Qt::YAxis);
+ x.rotate(zRotation, Qt::ZAxis);
+ x.shear(horizontalShear, verticalShear);
+ x.scale(xScale, yScale);
+ x.translate(-xOrigin, -yOrigin);
+ return x;
}
-
- struct DecomposedTransform {
- qreal xScale;
- qreal yScale;
- qreal xRotation;
- qreal yRotation;
- qreal zRotation;
- qreal horizontalShear;
- qreal verticalShear;
- qreal xOrigin;
- qreal yOrigin;
-
- inline void reset()
- {
- xScale = 1.0;
- yScale = 1.0;
- xRotation = 0.0;
- yRotation = 0.0;
- zRotation = 0.0;
- horizontalShear = 0.0;
- verticalShear = 0.0;
- xOrigin = 0.0;
- yOrigin = 0.0;
- }
-
- inline void initFrom(const QTransform &x)
- {
- reset();
- // ### decompose transform
- Q_UNUSED(x);
- }
-
- inline void generateTransform(QTransform *x) const
- {
- x->translate(xOrigin, yOrigin);
- x->rotate(xRotation, Qt::XAxis);
- x->rotate(yRotation, Qt::YAxis);
- x->rotate(zRotation, Qt::ZAxis);
- x->shear(horizontalShear, verticalShear);
- x->scale(xScale, yScale);
- x->translate(-xOrigin, -yOrigin);
- }
- };
-
- QGraphicsItem *q_ptr;
};
-QT_END_NAMESPACE
+/*
+ return the full transform of the item to the parent. This include the position and all the transform data
+*/
+inline QTransform QGraphicsItemPrivate::transformToParent() const
+{
+ QTransform matrix;
+ combineTransformToParent(&matrix);
+ return matrix;
+}
-Q_DECLARE_METATYPE(QGraphicsItemPrivate::DecomposedTransform *)
+QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index cf851c0901..33232afa5a 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -275,8 +275,9 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
hasSceneRect(false),
updateAll(false),
calledEmitUpdated(false),
+ processDirtyItemsEmitted(false),
selectionChanging(0),
- dirtyItemResetPending(false),
+ needSortTopLevelItems(true),
stickyFocus(false),
hasFocus(false),
focusItem(0),
@@ -311,9 +312,6 @@ void QGraphicsScenePrivate::init()
q->update();
}
-/*!
- \internal
-*/
void QGraphicsScenePrivate::_q_emitUpdated()
{
Q_Q(QGraphicsScene);
@@ -323,7 +321,7 @@ void QGraphicsScenePrivate::_q_emitUpdated()
// the optimization that items send updates directly to the views, but it
// needs to happen in order to keep compatibility with the behavior from
// Qt 4.4 and backward.
- if (!views.isEmpty() && (connectedSignals & changedSignalMask)) {
+ if (connectedSignals & changedSignalMask) {
for (int i = 0; i < views.size(); ++i) {
QGraphicsView *view = views.at(i);
if (!view->d_func()->connectedToScene) {
@@ -332,13 +330,13 @@ void QGraphicsScenePrivate::_q_emitUpdated()
views.at(i), SLOT(updateScene(QList<QRectF>)));
}
}
+ } else {
+ updateAll = false;
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->processPendingUpdates();
+ return;
}
- // Ensure all dirty items's current positions are recorded in the list of
- // updated rects.
- for (int i = 0; i < dirtyItems.size(); ++i)
- updatedRects += dirtyItems.at(i)->sceneBoundingRect();
-
// Notify the changes to anybody interested.
QList<QRectF> oldUpdatedRects;
oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects;
@@ -352,7 +350,7 @@ void QGraphicsScenePrivate::_q_emitUpdated()
*/
void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
{
- item->d_ptr->siblingIndex = topLevelItems.size();
+ needSortTopLevelItems = true;
topLevelItems.append(item);
}
@@ -361,14 +359,7 @@ void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
*/
void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
{
- int idx = item->d_ptr->siblingIndex;
- int size = topLevelItems.size();
- for (int i = idx; i < size - 1; ++i) {
- QGraphicsItem *p = topLevelItems[i + 1];
- topLevelItems[i] = p;
- p->d_ptr->siblingIndex = i;
- }
- topLevelItems.removeLast();
+ topLevelItems.removeOne(item);
}
/*!
@@ -403,59 +394,86 @@ void QGraphicsScenePrivate::_q_polishItems()
unpolishedItems.clear();
}
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::_q_resetDirtyItems()
+void QGraphicsScenePrivate::_q_processDirtyItems()
{
- for (int i = 0; i < dirtyItems.size(); ++i) {
- QGraphicsItem *item = dirtyItems.at(i);
- item->d_ptr->dirty = 0;
- item->d_ptr->dirtyChildren = 0;
- }
- dirtyItems.clear();
- dirtyItemResetPending = false;
-}
+ processDirtyItemsEmitted = false;
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::resetDirtyItemsLater()
-{
- Q_Q(QGraphicsScene);
- if (dirtyItemResetPending)
+ const bool wasPendingSceneUpdate = calledEmitUpdated;
+ const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
+ processDirtyItemsRecursive(0);
+ if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
+ emit q_func()->sceneRectChanged(growingItemsBoundingRect);
+
+ if (wasPendingSceneUpdate)
return;
- // dirtyItems.reserve(indexedItems.size() + unindexedItems.size());
- dirtyItemResetPending = true;
- QMetaObject::invokeMethod(q, "_q_resetDirtyItems", Qt::QueuedConnection);
+
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->processPendingUpdates();
+
+ if (calledEmitUpdated) {
+ // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
+ // and we cannot wait for the control to reach the eventloop before the
+ // changed signal is emitted, so we emit it now.
+ _q_emitUpdated();
+ }
+
+ // Immediately dispatch all pending update requests on the views.
+ for (int i = 0; i < views.size(); ++i) {
+ QWidget *viewport = views.at(i)->d_func()->viewport;
+ if (qt_widget_private(viewport)->paintOnScreen())
+ QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
+ else
+ QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
+ }
}
/*!
\internal
Schedules an item for removal. This function leaves some stale indexes
- around in the BSP tree; these will be cleaned up the next time someone
- triggers purgeRemovedItems().
+ around in the BSP tree if called from the item's destructor; these will
+ be cleaned up the next time someone triggers purgeRemovedItems().
- Note: This function is called from QGraphicsItem's destructor. \a item is
+ Note: This function might get called from QGraphicsItem's destructor. \a item is
being destroyed, so we cannot call any pure virtual functions on it (such
as boundingRect()). Also, it is unnecessary to update the item's own state
in any way.
-
- ### Refactoring: This function shares much functionality with removeItem()
*/
-void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
+void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
{
Q_Q(QGraphicsScene);
- // Clear focus on the item to remove any reference in the focusWidget
- // chain.
+ // Clear focus on the item to remove any reference in the focusWidget chain.
item->clearFocus();
- // Note: This will access item's sceneBoundingRect(), which (as this is
- // C++) is why we cannot call removeItem() from QGraphicsItem's
- // destructor.
- this->index->deleteItem(item);
+ markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true);
+
+ if (item->d_ptr->inDestructor) {
+ // Can potentially call item->boundingRect() (virtual function), that's why
+ // we only can call this function if the item is not in its destructor.
+ index->deleteItem(item);
+ } else {
+ // Remove it from the index properly
+ index->removeItem(item);
+ }
+
+ if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
+ }
+
+ item->d_func()->scene = 0;
+
+ // Remove from parent, or unregister from toplevels.
+ if (QGraphicsItem *parentItem = item->parentItem()) {
+ if (parentItem->scene()) {
+ Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
+ "Parent item's scene is different from this item's scene");
+ item->d_ptr->setParentItemHelper(0);
+ }
+ } else {
+ unregisterTopLevelItem(item);
+ }
// Reset the mouse grabber and focus item data.
if (item == focusItem)
@@ -474,10 +492,10 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
// Update selected & hovered item bookkeeping
selectedItems.remove(item);
hoverItems.removeAll(item);
- pendingUpdateItems.removeAll(item);
cachedItemsUnderMouse.removeAll(item);
unpolishedItems.removeAll(item);
- dirtyItems.removeAll(item);
+ pendingUpdateItems.removeAll(item);
+ resetDirtyItem(item);
//We remove all references of item from the sceneEventFilter arrays
QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
@@ -488,20 +506,19 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
++iterator;
}
- // Remove from scene transform cache
- int transformIndex = item->d_func()->sceneTransformIndex;
- if (transformIndex != -1) {
- validTransforms.setBit(transformIndex, 0);
- freeSceneTransformSlots.append(transformIndex);
+ if (!item->d_ptr->inDestructor) {
+ // Remove all children recursively
+ for (int i = 0; i < item->d_ptr->children.size(); ++i)
+ q->removeItem(item->d_ptr->children.at(i));
}
- // Reset the mouse grabber
+ // Reset the mouse grabber and focus item data.
if (mouseGrabberItems.contains(item))
- ungrabMouse(item, /* item is dying */ true);
+ ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
// Reset the keyboard grabber
if (keyboardGrabberItems.contains(item))
- ungrabKeyboard(item, /* item is dying */ true);
+ ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);
// Reset the last mouse grabber item
if (item == lastMouseGrabberItem)
@@ -1072,6 +1089,110 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item)
return 0;
}
+void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect,
+ QList<QGraphicsItem *> *items,
+ const QTransform &parentTransform,
+ const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ qreal parentOpacity) const
+{
+ // Calculate opacity.
+ qreal opacity;
+ if (item) {
+ if (!item->d_ptr->visible)
+ return;
+ QGraphicsItem *p = item->d_ptr->parent;
+ bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity;
+ bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren));
+ if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) {
+ opacity = parentOpacity * item->opacity();
+ } else {
+ opacity = item->d_ptr->opacity;
+ }
+ if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren))
+ return;
+ } else {
+ opacity = parentOpacity;
+ }
+
+ // Calculate the full transform for this item.
+ QTransform transform = parentTransform;
+ bool keep = false;
+ if (item) {
+ item->d_ptr->combineTransformFromParent(&transform, &viewTransform);
+
+ // ### This does not take the clip into account.
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ keep = true;
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = rect.contains(transform.mapRect(brect)) && rect != brect;
+ else
+ keep = rect.intersects(transform.mapRect(brect));
+
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath rectPath;
+ rectPath.addRect(rect);
+ keep = itemCollidesWithPath(item, transform.inverted().map(rectPath), mode);
+ }
+ }
+
+ bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape));
+ bool dontProcessItem = !item || !keep;
+ bool dontProcessChildren = item && dontProcessItem && childClip;
+
+ // Find and sort children.
+ QList<QGraphicsItem *> &children = item ? item->d_ptr->children : const_cast<QGraphicsScenePrivate *>(this)->topLevelItems;
+ if (!dontProcessChildren) {
+ if (item && item->d_ptr->needSortChildren) {
+ item->d_ptr->needSortChildren = 0;
+ qStableSort(children.begin(), children.end(), qt_notclosestLeaf);
+ } else if (!item && needSortTopLevelItems) {
+ const_cast<QGraphicsScenePrivate *>(this)->needSortTopLevelItems = false;
+ qStableSort(children.begin(), children.end(), qt_notclosestLeaf);
+ }
+ }
+
+ childClip &= !dontProcessChildren & !children.isEmpty();
+
+ // Clip.
+ if (childClip)
+ rect &= transform.map(item->shape()).controlPointRect();
+
+ // Process children behind
+ int i = 0;
+ if (!dontProcessChildren) {
+ for (i = 0; i < children.size(); ++i) {
+ QGraphicsItem *child = children.at(i);
+ if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ recursive_items_helper(child, rect, items, transform, viewTransform,
+ mode, order, opacity);
+ }
+ }
+
+ // Process item
+ if (!dontProcessItem)
+ items->append(item);
+
+ // Process children in front
+ if (!dontProcessChildren) {
+ for (; i < children.size(); ++i)
+ recursive_items_helper(children.at(i), rect, items, transform, viewTransform,
+ mode, order, opacity);
+ }
+
+ if (!item && order == Qt::AscendingOrder) {
+ int n = items->size();
+ for (int i = 0; i < n / 2; ++i) {
+ QGraphicsItem *tmp = (*items)[n - i - 1];
+ (*items)[n - i - 1] = (*items)[i];
+ (*items)[i] = tmp;
+ }
+ }
+}
+
/*!
\internal
@@ -1597,7 +1718,6 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
return d->index->items(pos, Qt::IntersectsItemShape, Qt::AscendingOrder);
}
-
/*!
\fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
@@ -1614,7 +1734,10 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const
{
Q_D(const QGraphicsScene);
- return d->index->items(rect, mode, Qt::AscendingOrder);
+ QList<QGraphicsItem *> itemList;
+ //###d->index->items(rect, mode, Qt::AscendingOrder);
+ d->recursive_items_helper(0, rect, &itemList, QTransform(), QTransform(), mode, Qt::AscendingOrder);
+ return itemList;
}
/*!
@@ -1916,16 +2039,17 @@ void QGraphicsScene::clearSelection()
void QGraphicsScene::clear()
{
Q_D(QGraphicsScene);
- QList<QGraphicsItem *> items;
+ QList<QGraphicsItem *> items = d->index->items();
+ QList<QGraphicsItem *> toDelete;
// Recursive descent delete
- for (int i = 0; i < d->index->items().size(); ++i) {
- if (QGraphicsItem *item = d->index->items().at(i)) {
+ for (int i = 0; i < items.size(); ++i) {
+ if (QGraphicsItem *item = items.at(i)) {
if (!item->parentItem())
- items << item;
+ toDelete << item;
}
}
//We delete all top level items
- qDeleteAll(items);
+ qDeleteAll(toDelete);
d->lastItemCount = 0;
d->index->clear();
d->largestUntransformableItem = QRectF();
@@ -2409,97 +2533,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
return;
}
- // If the item has focus, remove it (and any focusWidget reference).
- item->clearFocus();
-
- // Clear its background
- item->update();
-
- // Remove it from the index properly
- d->index->removeItem(item);
-
- if (item == d->tabFocusFirst) {
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
- widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
- }
- // Set the item's scene ptr to 0.
- item->d_func()->scene = 0;
-
- // Remove from parent, or unregister from toplevels.
- if (QGraphicsItem *parentItem = item->parentItem()) {
- if (parentItem->scene()) {
- Q_ASSERT_X(parentItem->scene() == this, "QGraphicsScene::removeItem",
- "Parent item's scene is different from this item's scene");
- item->setParentItem(0);
- }
- } else {
- d->unregisterTopLevelItem(item);
- }
-
- // Remove from scene transform cache
- int transformIndex = item->d_func()->sceneTransformIndex;
- if (transformIndex != -1) {
- d->validTransforms.setBit(transformIndex, 0);
- d->freeSceneTransformSlots.append(transformIndex);
- item->d_func()->sceneTransformIndex = -1;
- }
-
- if (item == d->focusItem)
- d->focusItem = 0;
- if (item == d->lastFocusItem)
- d->lastFocusItem = 0;
- if (item == d->activeWindow) {
- // ### deactivate...
- d->activeWindow = 0;
- }
-
- // Disable selectionChanged() for individual items
- ++d->selectionChanging;
- int oldSelectedItemsSize = d->selectedItems.size();
-
- // Update selected & hovered item bookkeeping
- d->selectedItems.remove(item);
- d->hoverItems.removeAll(item);
- d->pendingUpdateItems.removeAll(item);
- d->cachedItemsUnderMouse.removeAll(item);
- d->unpolishedItems.removeAll(item);
- d->dirtyItems.removeAll(item);
-
- //We remove all references of item from the sceneEventFilter arrays
- QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = d->sceneEventFilters.begin();
- while (iterator != d->sceneEventFilters.end()) {
- if (iterator.value() == item || iterator.key() == item)
- iterator = d->sceneEventFilters.erase(iterator);
- else
- ++iterator;
- }
-
-
- //Ensure dirty flag have the correct default value so the next time it will be added it will receive updates
- item->d_func()->dirty = 0;
- item->d_func()->dirtyChildren = 0;
-
- // Remove all children recursively
- foreach (QGraphicsItem *child, item->children())
- removeItem(child);
-
- // Reset the mouse grabber and focus item data.
- if (d->mouseGrabberItems.contains(item))
- d->ungrabMouse(item);
-
- // Reset the keyboard grabber
- if (d->keyboardGrabberItems.contains(item))
- item->ungrabKeyboard();
-
- // Reset the last mouse grabber item
- if (item == d->lastMouseGrabberItem)
- d->lastMouseGrabberItem = 0;
-
- // Reenable selectionChanged() for individual items
- --d->selectionChanging;
-
- if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemsSize)
- emit selectionChanged();
+ d->removeItemHelper(item);
// Deliver post-change notification
item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
@@ -2802,7 +2836,7 @@ void QGraphicsScene::update(const QRectF &rect)
}
}
- if (!directUpdates && !d->calledEmitUpdated) {
+ if (!d->calledEmitUpdated) {
d->calledEmitUpdated = true;
QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
}
@@ -2918,6 +2952,8 @@ bool QGraphicsScene::event(QEvent *event)
// items from inside event handlers, this list can quickly end up
// having stale pointers in it. We need to clear it before dispatching
// events that use it.
+ // ### this should only be cleared if we received a new mouse move event,
+ // which relies on us fixing the replay mechanism in QGraphicsView.
d->cachedItemsUnderMouse.clear();
default:
break;
@@ -3941,7 +3977,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Generate the item's exposedRect and map its list of expose
// rects to device coordinates.
- QStyleOptionGraphicsItem cacheOption = *option;
+ styleOptionTmp = *option;
QRegion pixmapExposed;
QRectF exposedRect;
if (!itemCache->allExposed) {
@@ -3953,11 +3989,11 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
} else {
exposedRect = brect;
}
- cacheOption.exposedRect = exposedRect;
+ styleOptionTmp.exposedRect = exposedRect;
// Render.
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &cacheOption, painterStateProtection);
+ &styleOptionTmp, painterStateProtection);
// insert this pixmap into the cache.
itemCache->key = QPixmapCache::insert(pix);
@@ -4118,12 +4154,12 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
foreach (QRect r, scrollExposure.rects())
br |= pixmapToItem.mapRect(r);
}
- QStyleOptionGraphicsItem cacheOption = *option;
- cacheOption.exposedRect = br.adjusted(-1, -1, 1, 1);
+ styleOptionTmp = *option;
+ styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
// Render the exposed areas.
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &cacheOption, painterStateProtection);
+ &styleOptionTmp, painterStateProtection);
// Reset expose data.
pixModified = true;
@@ -4152,6 +4188,392 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
}
+void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
+ const QTransform &viewTransform,
+ QRegion *exposedRegion, QWidget *widget,
+ QList<QGraphicsItem *> *topLevelItems,
+ qreal parentOpacity)
+{
+ // Calculate opacity.
+ qreal opacity;
+ bool invisibleButChildIgnoresParentOpacity = false;
+ if (item) {
+ if (!item->d_ptr->visible)
+ return;
+ QGraphicsItem *p = item->d_ptr->parent;
+ bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity;
+ bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren));
+ if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) {
+ opacity = parentOpacity * item->opacity();
+ } else {
+ opacity = item->d_ptr->opacity;
+ }
+ if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
+ invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity();
+ if (!invisibleButChildIgnoresParentOpacity)
+ return;
+ }
+ } else {
+ opacity = parentOpacity;
+ }
+
+ // Calculate the full transform for this item.
+ QRect viewBoundingRect;
+ bool wasDirtyParentSceneTransform = false;
+ QTransform transform;
+ if (item) {
+ if (item->d_ptr->itemIsUntransformable()) {
+ transform = item->deviceTransform(viewTransform);
+ } else {
+ if (item->d_ptr->dirtySceneTransform) {
+ item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
+ : QTransform();
+ item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
+ item->d_ptr->dirtySceneTransform = 0;
+ wasDirtyParentSceneTransform = true;
+ }
+ transform = item->d_ptr->sceneTransform;
+ transform *= viewTransform;
+ }
+
+ QRectF brect = item->boundingRect();
+ // ### This does not take the clip into account.
+ _q_adjustRect(&brect);
+ viewBoundingRect = transform.mapRect(brect).toRect();
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ viewBoundingRect.adjust(-1, -1, 1, 1);
+ if (exposedRegion)
+ viewBoundingRect &= exposedRegion->boundingRect();
+ }
+
+ // Find and sort children.
+ QList<QGraphicsItem *> tmp;
+ QList<QGraphicsItem *> *children = 0;
+ if (item) {
+ children = &item->d_ptr->children;
+ } else if (topLevelItems) {
+ children = topLevelItems;
+ } else if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) {
+ children = &this->topLevelItems;
+ } else {
+ QRectF sceneRect = viewTransform.inverted().mapRect(QRectF(exposedRegion->boundingRect().adjusted(-1, -1, 1, 1)));
+ if (!largestUntransformableItem.isEmpty()) {
+ // ### Nuke this when we move the indexing code into a separate
+ // class. All the largestUntransformableItem code should then go
+ // away, and the estimate function should return untransformable
+ // items as well.
+ QRectF untr = largestUntransformableItem;
+ QRectF ltri = viewTransform.inverted().mapRect(untr);
+ ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
+ sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
+ }
+ tmp = index->estimateItems(sceneRect, Qt::DescendingOrder, viewTransform);
+
+ QList<QGraphicsItem *> tli;
+ for (int i = 0; i < tmp.size(); ++i)
+ tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1;
+
+ // Sort if the toplevel list is unsorted.
+ if (needSortTopLevelItems) {
+ needSortTopLevelItems = false;
+ qStableSort(this->topLevelItems.begin(),
+ this->topLevelItems.end(), qt_notclosestLeaf);
+ }
+
+ for (int i = 0; i < this->topLevelItems.size(); ++i) {
+ // ### Investigate smarter ways. Looping through all top level
+ // items is not optimal. If the BSP tree is to have maximum
+ // effect, it should be possible to sort the subset of items
+ // quickly. We must use this approach for now, as it's the only
+ // current way to keep the stable sorting order (insertion order).
+ QGraphicsItem *item = this->topLevelItems.at(i);
+ if (item->d_ptr->itemDiscovered) {
+ item->d_ptr->itemDiscovered = 0;
+ tli << item;
+ }
+ }
+
+ tmp = tli;
+ children = &tmp;
+ }
+
+ bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape));
+ bool dontDrawItem = !item || viewBoundingRect.isEmpty();
+ bool dontDrawChildren = item && dontDrawItem && childClip;
+ childClip &= !dontDrawChildren && !children->isEmpty();
+ if (item && ((item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) || invisibleButChildIgnoresParentOpacity))
+ dontDrawItem = true;
+
+ // Clip children.
+ if (childClip) {
+ painter->save();
+ painter->setWorldTransform(transform);
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ }
+
+ if (!dontDrawChildren) {
+ if (item && item->d_ptr->needSortChildren) {
+ item->d_ptr->needSortChildren = 0;
+ qStableSort(children->begin(), children->end(), qt_notclosestLeaf);
+ } else if (!item && needSortTopLevelItems && children != &tmp) {
+ needSortTopLevelItems = false;
+ qStableSort(children->begin(), children->end(), qt_notclosestLeaf);
+ }
+ }
+
+ // Draw children behind
+ int i = 0;
+ if (!dontDrawChildren) {
+ // ### Don't visit children that don't ignore parent opacity if this
+ // item is invisible.
+ for (i = 0; i < children->size(); ++i) {
+ QGraphicsItem *child = children->at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget,
+ 0, opacity);
+ }
+ }
+
+ // Draw item
+ if (!dontDrawItem) {
+ item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0);
+
+ bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape);
+ bool savePainter = clipsToShape || painterStateProtection;
+ if (savePainter)
+ painter->save();
+ if (!childClip)
+ painter->setWorldTransform(transform);
+ if (clipsToShape)
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ painter->setOpacity(opacity);
+ drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
+
+ if (savePainter)
+ painter->restore();
+ }
+
+ // Draw children in front
+ if (!dontDrawChildren) {
+ // ### Don't visit children that don't ignore parent opacity if this
+ // item is invisible.
+ for (; i < children->size(); ++i) {
+ QGraphicsItem *child = children->at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion,
+ widget, 0, opacity);
+ }
+ } else if (wasDirtyParentSceneTransform) {
+ item->d_ptr->invalidateChildrenSceneTransform();
+ }
+
+ // Restore child clip
+ if (childClip)
+ painter->restore();
+}
+
+void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
+ bool maybeDirtyClipPath, bool force, bool ignoreOpacity,
+ bool removingItemFromScene)
+{
+ Q_ASSERT(item);
+ if (updateAll)
+ return;
+
+ if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath,
+ /*ignoreVisibleBit=*/force,
+ /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
+ /*ignoreOpacity=*/ignoreOpacity)) {
+ return;
+ }
+
+ const bool fullItemUpdate = rect.isNull();
+ if (!fullItemUpdate && rect.isEmpty())
+ return;
+
+ if (!processDirtyItemsEmitted) {
+ QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
+ processDirtyItemsEmitted = true;
+ }
+
+ if (removingItemFromScene) {
+ // Note that this function can be called from the item's destructor, so
+ // do NOT call any virtual functions on it within this block.
+ if ((connectedSignals & changedSignalMask) || views.isEmpty()) {
+ // This block of code is kept for compatibility. Since 4.5, by default
+ // QGraphicsView does not connect the signal and we use the below
+ // method of delivering updates.
+ q_func()->update();
+ return;
+ }
+
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func();
+ viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport));
+ }
+ return;
+ }
+
+ item->d_ptr->dirty = 1;
+ if (fullItemUpdate)
+ item->d_ptr->fullUpdatePending = 1;
+ else if (!item->d_ptr->fullUpdatePending)
+ item->d_ptr->needsRepaint |= rect;
+
+ if (invalidateChildren) {
+ item->d_ptr->allChildrenDirty = 1;
+ item->d_ptr->dirtyChildren = 1;
+ }
+
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p && !p->d_ptr->dirtyChildren) {
+ p->d_ptr->dirtyChildren = 1;
+ p = p->d_ptr->parent;
+ }
+}
+
+void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren)
+{
+ Q_Q(QGraphicsScene);
+
+ // Calculate the full scene transform for this item.
+ bool wasDirtyParentSceneTransform = false;
+ if (item && item->d_ptr->dirtySceneTransform && !item->d_ptr->itemIsUntransformable()) {
+ item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
+ : QTransform();
+ item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
+ item->d_ptr->dirtySceneTransform = 0;
+ wasDirtyParentSceneTransform = true;
+ }
+
+ // Process item.
+ bool wasDirtyParentViewBoundingRects = false;
+ if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) {
+ const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask);
+ const bool untransformableItem = item->d_ptr->itemIsUntransformable();
+ const QRectF itemBoundingRect = item->boundingRect();
+
+ if (item->d_ptr->geometryChanged) {
+ // Update growingItemsBoundingRect.
+ if (!hasSceneRect) {
+ QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
+ _q_adjustRect(&itemSceneBoundingRect);
+ growingItemsBoundingRect |= itemSceneBoundingRect;
+ }
+ item->d_ptr->geometryChanged = 0;
+ }
+
+ if (useCompatUpdate && !untransformableItem && qFuzzyIsNull(item->boundingRegionGranularity())) {
+ // This block of code is kept for compatibility. Since 4.5, by default
+ // QGraphicsView does not connect the signal and we use the below
+ // method of delivering updates.
+ q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect));
+ } else {
+ QRectF dirtyRect;
+ bool uninitializedDirtyRect = true;
+
+ for (int j = 0; j < views.size(); ++j) {
+ QGraphicsView *view = views.at(j);
+ QGraphicsViewPrivate *viewPrivate = view->d_func();
+ if (viewPrivate->fullUpdatePending)
+ continue;
+ switch (viewPrivate->viewportUpdateMode) {
+ case QGraphicsView::NoViewportUpdate:
+ continue;
+ case QGraphicsView::FullViewportUpdate:
+ view->viewport()->update();
+ viewPrivate->fullUpdatePending = 1;
+ continue;
+ default:
+ break;
+ }
+
+ if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
+ wasDirtyParentViewBoundingRects = true;
+ viewPrivate->updateRect(item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport));
+ }
+
+ if (!item->d_ptr->dirty)
+ continue;
+
+ if (uninitializedDirtyRect) {
+ dirtyRect = itemBoundingRect;
+ _q_adjustRect(&dirtyRect);
+ if (!item->d_ptr->fullUpdatePending) {
+ _q_adjustRect(&item->d_ptr->needsRepaint);
+ dirtyRect &= item->d_ptr->needsRepaint;
+ }
+ uninitializedDirtyRect = false;
+ }
+
+ if (dirtyRect.isEmpty())
+ continue; // Discard updates outside the bounding rect.
+
+ QTransform deviceTransform = item->d_ptr->sceneTransform;
+ if (view->isTransformed()) {
+ if (!untransformableItem)
+ deviceTransform *= view->viewportTransform();
+ else
+ deviceTransform = item->deviceTransform(view->viewportTransform());
+ }
+ if (item->d_ptr->hasBoundingRegionGranularity)
+ viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect())));
+ else
+ viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect());
+ }
+ }
+ }
+
+ // Process root items / children.
+ if (!item || item->d_ptr->dirtyChildren) {
+ QList<QGraphicsItem *> *children = item ? &item->d_ptr->children : &topLevelItems;
+ const bool allChildrenDirty = item && item->d_ptr->allChildrenDirty;
+ if (!dirtyAncestorContainsChildren) {
+ dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending
+ && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ }
+ for (int i = 0; i < children->size(); ++i) {
+ QGraphicsItem *child = children->at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (wasDirtyParentViewBoundingRects)
+ child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
+
+ if (allChildrenDirty) {
+ child->d_ptr->dirty = 1;
+ child->d_ptr->fullUpdatePending = 1;
+ child->d_ptr->dirtyChildren = 1;
+ child->d_ptr->allChildrenDirty = 1;
+ } else if (!child->d_ptr->dirty && !child->d_ptr->dirtyChildren) {
+ resetDirtyItem(child);
+ continue;
+ }
+
+ if (dirtyAncestorContainsChildren || updateAll) {
+ // No need to process this child's dirty rect, hence reset the dirty state.
+ // However, we have to continue the recursion because it might have a dirty
+ // view bounding rect that needs repaint. We also have to reset the dirty
+ // state of its descendants.
+ child->d_ptr->dirty = 0;
+ child->d_ptr->fullUpdatePending = 0;
+ if (updateAll)
+ child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
+ }
+
+ processDirtyItemsRecursive(child, dirtyAncestorContainsChildren);
+ }
+ } else if (wasDirtyParentSceneTransform) {
+ item->d_ptr->invalidateChildrenSceneTransform();
+ }
+
+ if (item)
+ resetDirtyItem(item);
+}
+
/*!
Paints the given \a items using the provided \a painter, after the
background has been drawn, and before the foreground has been
@@ -4183,111 +4605,29 @@ void QGraphicsScene::drawItems(QPainter *painter,
const QStyleOptionGraphicsItem options[], QWidget *widget)
{
Q_D(QGraphicsScene);
-
- // Detect if painter state protection is disabled.
QTransform viewTransform = painter->worldTransform();
- QVarLengthArray<QGraphicsItem *, 16> childClippers;
-
- for (int i = 0; i < numItems; ++i) {
- QGraphicsItem *item = items[i];
- if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
- if (!childClippers.isEmpty()) {
- // Item is not clipped to any ancestor: pop all current clippers.
- for (int i = 0; i < childClippers.size(); ++i)
- painter->restore();
- childClippers.clear();
- }
- } else {
- // Item is clipped to an ancestor, which may or may not be in our
- // child clipper list. Let's start by finding the item's closest
- // clipping ancestor.
- QGraphicsItem *clipParent = item->parentItem();
- while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape))
- clipParent = clipParent->parentItem();
-
- // Pop any in-between clippers. If the clipper is unknown, pop
- // them all. ### QVarLengthArray::lastIndexOf().
- int index = -1;
- for (int n = childClippers.size() - 1; n >= 0; --n) {
- if (childClippers[n] == clipParent) {
- index = n;
- break;
- }
- }
- if (index != -1) {
- int toPop = childClippers.size() - index - 1;
- if (toPop > 0) {
- for (int i = 0; i < toPop; ++i)
- painter->restore();
- childClippers.resize(index + 1);
- }
- }
-
- // Sanity check
- if (!childClippers.isEmpty())
- Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
-
- // If the clipper list is empty at this point, but we're still
- // clipped to an ancestor, then we need to build the clip chain
- // ourselves. There is only one case that can produce this issue:
- // This item is stacked behind an ancestor:
- // ItemStacksBehindParent.
- if (childClippers.isEmpty()) {
- Q_ASSERT(clipParent != 0);
- // Build a stack of clippers.
- QVarLengthArray<QGraphicsItem *, 16> clippers;
- QGraphicsItem *p = clipParent;
- do {
- if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
- clippers.append(p);
- } while ((p = p->parentItem()) && (p->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
-
- // ### This code path can also use the itemTransform
- // optimization, but it's hit very rarely.
- for (int i = clippers.size() - 1; i >= 0; --i) {
- QGraphicsItem *clipper = clippers[i];
- painter->setWorldTransform(clipper->deviceTransform(viewTransform), false);
-
- childClippers.append(clipper);
- painter->save();
- painter->setClipPath(clipper->shape(), Qt::IntersectClip);
- }
- Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
- }
- }
-
- // Set up the painter transform
- painter->setWorldTransform(item->deviceTransform(viewTransform), false);
-
- // Save painter
- bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape));
- if (saveState)
- painter->save();
+ Q_UNUSED(options);
- // Set local clip
- if (item->flags() & QGraphicsItem::ItemClipsToShape)
- painter->setClipPath(item->shape(), Qt::IntersectClip);
-
- // Setup opacity
- painter->setOpacity(item->effectiveOpacity());
-
- // Draw the item
- d->drawItemHelper(item, painter, &options[i], widget, d->painterStateProtection);
-
- if (saveState)
- painter->restore();
+ // Determine view, expose and flags.
+ QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
+ QRegion *expose = 0;
+ if (view)
+ expose = &view->d_func()->exposedRegion;
- if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape) {
- // Clip descendents to this item's shape, and keep the painter
- // saved.
- childClippers.append(item);
- painter->save();
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ // Find all toplevels, they are already sorted.
+ QList<QGraphicsItem *> topLevelItems;
+ for (int i = 0; i < numItems; ++i) {
+ QGraphicsItem *item = items[i]->topLevelItem();
+ if (!item->d_ptr->itemDiscovered) {
+ topLevelItems << item;
+ item->d_ptr->itemDiscovered = 1;
+ d->drawSubtreeRecursive(item, painter, viewTransform, expose, widget);
}
}
- for (int i = 0; i < childClippers.size(); ++i)
- painter->restore();
+ // Reset discovery bits.
+ for (int i = 0; i < topLevelItems.size(); ++i)
+ topLevelItems.at(i)->d_ptr->itemDiscovered = 0;
painter->setWorldTransform(viewTransform);
}
@@ -4399,73 +4739,6 @@ bool QGraphicsScene::focusNextPrevChild(bool next)
*/
/*!
- \internal
-
- This private function is called by QGraphicsItem, which is a friend of
- QGraphicsScene. It is used by QGraphicsScene to record the rectangles that
- need updating. It also launches a single-shot timer to ensure that
- updated() will be emitted later.
-
- The \a item parameter is the item that changed, and \a rect is the
- area of the item that changed given in item coordinates.
-*/
-void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
-{
- Q_D(QGraphicsScene);
- // Deliver the actual update.
- if (!d->updateAll) {
- if (d->views.isEmpty() || ((d->connectedSignals & d->changedSignalMask) && !item->d_ptr->itemIsUntransformable()
- && qFuzzyIsNull(item->boundingRegionGranularity()))) {
- // This block of code is kept for compatibility. Since 4.5, by default
- // QGraphicsView does not connect the signal and we use the below
- // method of delivering updates.
- update(item->sceneBoundingRect());
- } else {
- // ### Remove _q_adjustedRects().
- QRectF boundingRect(adjustedItemBoundingRect(item));
- if (!rect.isNull()) {
- QRectF adjustedRect(rect);
- _q_adjustRect(&adjustedRect);
- boundingRect &= adjustedRect;
- }
-
- // Update each view directly.
- for (int i = 0; i < d->views.size(); ++i)
- d->views.at(i)->d_func()->itemUpdated(item, boundingRect);
- }
- }
- if (item->d_ptr->dirty) {
- d->dirtyItems << item;
- d->resetDirtyItemsLater();
- }
-
- if (!item->isVisible())
- return; // Hiding an item won't effect the largestUntransformableItem/sceneRect.
-
- // Update d->largestUntransformableItem by mapping this item's bounding
- // rect back to the topmost untransformable item's untransformed
- // coordinate system (which sort of equals the 1:1 coordinate system of an
- // untransformed view).
- if (item->d_ptr->itemIsUntransformable()) {
- QGraphicsItem *parent = item;
- while (parent && (parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations))
- parent = parent->parentItem();
- d->largestUntransformableItem |= item->mapToItem(parent, item->boundingRect()).boundingRect();
- }
-
- // Only track the automatically growing scene rect if the scene has no
- // defined scene rect.
- if (!d->hasSceneRect) {
- QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect;
- QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect());
- _q_adjustRect(&adjustedItemSceneBoundingRect);
- d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect;
- if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect)
- emit sceneRectChanged(d->growingItemsBoundingRect);
- }
-}
-
-/*!
\since 4.4
Returns the scene's style, or the same as QApplication::style() if the
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index 702813cf4b..2e840254a7 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -282,15 +282,12 @@ Q_SIGNALS:
void selectionChanged();
private:
- void itemUpdated(QGraphicsItem *item, const QRectF &rect);
-
Q_DECLARE_PRIVATE(QGraphicsScene)
Q_DISABLE_COPY(QGraphicsScene)
Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated())
- Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item))
Q_PRIVATE_SLOT(d_func(), void _q_updateLater())
Q_PRIVATE_SLOT(d_func(), void _q_polishItems())
- Q_PRIVATE_SLOT(d_func(), void _q_resetDirtyItems())
+ Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems())
friend class QGraphicsItem;
friend class QGraphicsItemPrivate;
friend class QGraphicsView;
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index d2a5cdbbc9..afdba7ef86 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -60,6 +60,7 @@
#include "qgraphicsscenebsptreeindex_p.h"
#include "qgraphicsscenelinearindex_p.h"
#include "qgraphicssceneindex.h"
+#include "qgraphicsview.h"
#include "qgraphicsitem_p.h"
#include <private/qobject_p.h>
@@ -70,6 +71,7 @@
#include <QtGui/qfont.h>
#include <QtGui/qpalette.h>
#include <QtGui/qstyle.h>
+#include <QtGui/qstyleoption.h>
QT_BEGIN_NAMESPACE
@@ -101,25 +103,24 @@ public:
QList<QRectF> updatedRects;
bool updateAll;
bool calledEmitUpdated;
+ bool processDirtyItemsEmitted;
QPainterPath selectionArea;
int selectionChanging;
QSet<QGraphicsItem *> selectedItems;
- QList<QGraphicsItem *> dirtyItems;
QList<QGraphicsItem *> pendingUpdateItems;
QList<QGraphicsItem *> unpolishedItems;
QList<QGraphicsItem *> topLevelItems;
+ bool needSortTopLevelItems;
QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions;
void registerTopLevelItem(QGraphicsItem *item);
void unregisterTopLevelItem(QGraphicsItem *item);
void _q_updateLater();
void _q_polishItems();
- void _q_resetDirtyItems();
- void resetDirtyItemsLater();
- bool dirtyItemResetPending;
+ void _q_processDirtyItems();
- void _q_removeItemLater(QGraphicsItem *item);
+ void removeItemHelper(QGraphicsItem *item);
QBrush backgroundBrush;
QBrush foregroundBrush;
@@ -188,10 +189,34 @@ public:
void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
+ void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList<QGraphicsItem *> *items,
+ const QTransform &parentTransform, const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
+
void drawItemHelper(QGraphicsItem *item, QPainter *painter,
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection);
+ void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform,
+ QRegion *exposedRegion, QWidget *widget,
+ QList<QGraphicsItem *> *topLevelItems = 0, qreal parentOpacity = qreal(1.0));
+ void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
+ bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false,
+ bool removingItemFromScene = false);
+ void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false);
+
+ inline void resetDirtyItem(QGraphicsItem *item)
+ {
+ Q_ASSERT(item);
+ item->d_ptr->dirty = 0;
+ item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
+ item->d_ptr->geometryChanged = 0;
+ item->d_ptr->dirtyChildren = 0;
+ item->d_ptr->needsRepaint = QRectF();
+ item->d_ptr->allChildrenDirty = 0;
+ item->d_ptr->fullUpdatePending = 0;
+ }
+
QStyle *style;
QFont font;
void setFont_helper(const QFont &font);
@@ -202,9 +227,7 @@ public:
void resolvePalette();
void updatePalette(const QPalette &palette);
- mutable QVector<QTransform> sceneTransformCache;
- mutable QBitArray validTransforms;
- mutable QVector<int> freeSceneTransformSlots;
+ QStyleOptionGraphicsItem styleOptionTmp;
};
static inline bool QRectF_intersects(const QRectF &s, const QRectF &r)
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp
index 19aa9d57f4..97d0500ddf 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p.cpp
@@ -40,8 +40,6 @@
****************************************************************************/
-static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
-
#include "qgraphicsscenebsptreeindex_p.h"
#ifndef QT_NO_GRAPHICSVIEW
@@ -182,7 +180,7 @@ void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems()
return;
// Remove stale items from the BSP tree.
- bsp.removeItems(removedItems.toSet());
+ bsp.removeItems(removedItems);
// Purge this list.
removedItems.clear();
freeItemIndexes.clear();
@@ -191,9 +189,6 @@ void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems()
freeItemIndexes << i;
}
purgePending = false;
-
- // No locality info for the items; update the whole scene.
- q->scene()->update();
}
/*!
@@ -201,13 +196,13 @@ void QGraphicsSceneBspTreeIndexPrivate::purgeRemovedItems()
Starts or restarts the timer used for reindexing unindexed items.
*/
-void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer()
+void QGraphicsSceneBspTreeIndexPrivate::startIndexTimer(int interval)
{
Q_Q(QGraphicsSceneBspTreeIndex);
if (indexTimerId) {
restartIndexTimer = true;
} else {
- indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
+ indexTimerId = q->startTimer(interval);
}
}
@@ -407,7 +402,7 @@ void QGraphicsSceneBspTreeIndex::addItem(QGraphicsItem *item)
// a temporary list and schedule an indexing for later.
d->unindexedItems << item;
item->d_func()->index = -1;
- d->startIndexTimer();
+ d->startIndexTimer(0);
}
/*!
@@ -557,8 +552,10 @@ QList<QGraphicsItem *> QGraphicsSceneBspTreeIndex::items(Qt::SortOrder order) co
itemList << item;
}
}
- //We sort descending order
- d->sortItems(&itemList, order, d->sortCacheEnabled);
+ if (order != -1) {
+ //We sort descending order
+ d->sortItems(&itemList, order, d->sortCacheEnabled);
+ }
return itemList;
}
diff --git a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h
index 2df5fbc8cd..098b278957 100644
--- a/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h
+++ b/src/gui/graphicsview/qgraphicsscenebsptreeindex_p_p.h
@@ -62,6 +62,8 @@
QT_BEGIN_NAMESPACE
+static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
+
class QGraphicsScene;
class QGraphicsSceneBspTreeIndexPrivate : public QObjectPrivate
@@ -84,11 +86,11 @@ public:
QList<int> freeItemIndexes;
bool purgePending;
- QList<QGraphicsItem *> removedItems;
+ QSet<QGraphicsItem *> removedItems;
void purgeRemovedItems();
void _q_updateIndex();
- void startIndexTimer();
+ void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
void resetIndex();
void addToIndex(QGraphicsItem *item);
@@ -129,9 +131,18 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item
if (f1 != f2) return f2;
qreal z1 = d1->z;
qreal z2 = d2->z;
- return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex;
+ return z1 > z2;
+}
+
+/*!
+ \internal
+*/
+static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ return qt_closestLeaf(item2, item1);
}
+
QT_END_NAMESPACE
#endif // QGRAPHICSSCENEBSPTREEINDEX_P_P_H
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
index eeee74e178..6895911ecf 100644
--- a/src/gui/graphicsview/qgraphicssceneindex.cpp
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -71,7 +71,7 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList<QGraphicsItem *> *items
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items and all their children.
@@ -111,7 +111,7 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList<QGraphicsItem *> *items
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items and all their children.
@@ -147,7 +147,7 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList<QGraphicsItem *> *items
if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
// Recurse into children.
- if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) {
+ if (!item->d_ptr->transformData || item->d_ptr->transformData->computedFullTransform().type() <= QTransform::TxScale) {
// Rect
childItems_helper(items, item, item->mapRectFromParent(rect), mode);
} else {
@@ -177,7 +177,7 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList<QGraphicsItem *> *items
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items.
@@ -236,7 +236,7 @@ void QGraphicsSceneIndexPrivate::childItems_helper(QList<QGraphicsItem *> *items
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items.
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index e8330a9117..e3e5723103 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -39,8 +39,6 @@
**
****************************************************************************/
-//#define QGRAPHICSVIEW_DEBUG
-
static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50;
static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < 2^9
@@ -329,8 +327,6 @@ QGraphicsViewPrivate::QGraphicsViewPrivate()
#endif
lastDragDropEvent(0),
fullUpdatePending(true),
- dirtyRectCount(0),
- updatingLater(false),
updateSceneSlotReimplementedChecked(false)
{
styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS);
@@ -391,7 +387,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
int left = q_round_bound(viewRect.left());
int right = q_round_bound(viewRect.right() - width);
if (left >= right) {
- q->horizontalScrollBar()->setRange(0, 0);
+ hbar->setRange(0, 0);
switch (alignment & Qt::AlignHorizontal_Mask) {
case Qt::AlignLeft:
@@ -406,9 +402,9 @@ void QGraphicsViewPrivate::recalculateContentSize()
break;
}
} else {
- q->horizontalScrollBar()->setRange(left, right);
- q->horizontalScrollBar()->setPageStep(width);
- q->horizontalScrollBar()->setSingleStep(width / 20);
+ hbar->setRange(left, right);
+ hbar->setPageStep(width);
+ hbar->setSingleStep(width / 20);
leftIndent = 0;
}
@@ -417,7 +413,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
int top = q_round_bound(viewRect.top());
int bottom = q_round_bound(viewRect.bottom() - height);
if (top >= bottom) {
- q->verticalScrollBar()->setRange(0, 0);
+ vbar->setRange(0, 0);
switch (alignment & Qt::AlignVertical_Mask) {
case Qt::AlignTop:
@@ -432,9 +428,9 @@ void QGraphicsViewPrivate::recalculateContentSize()
break;
}
} else {
- q->verticalScrollBar()->setRange(top, bottom);
- q->verticalScrollBar()->setPageStep(height);
- q->verticalScrollBar()->setSingleStep(height / 20);
+ vbar->setRange(top, bottom);
+ vbar->setPageStep(height);
+ vbar->setSingleStep(height / 20);
topIndent = 0;
}
@@ -446,7 +442,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
// scroll instead.
if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
dirtyScroll = true;
- q->viewport()->update();
+ viewport->update();
} else if (q->isRightToLeft() && !leftIndent) {
// In reverse mode, the horizontal scroll always changes after the content
// size has changed, as the scroll is calculated by summing the min and
@@ -472,7 +468,7 @@ void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
if (q->underMouse()) {
// Last scene pos: lastMouseMoveScenePoint
// Current mouse pos:
- QPointF transformationDiff = q->mapToScene(q->viewport()->rect().center())
+ QPointF transformationDiff = q->mapToScene(viewport->rect().center())
- q->mapToScene(q->mapFromGlobal(QCursor::pos()));
q->centerOn(lastMouseMoveScenePoint + transformationDiff);;
} else {
@@ -494,7 +490,7 @@ void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
void QGraphicsViewPrivate::updateLastCenterPoint()
{
Q_Q(QGraphicsView);
- lastCenterPoint = q->mapToScene(q->viewport()->rect().center());
+ lastCenterPoint = q->mapToScene(viewport->rect().center());
}
/*!
@@ -532,15 +528,15 @@ void QGraphicsViewPrivate::updateScroll()
scrollX = qint64(-leftIndent);
if (q->isRightToLeft()) {
if (!leftIndent) {
- scrollX += q->horizontalScrollBar()->minimum();
- scrollX += q->horizontalScrollBar()->maximum();
- scrollX -= q->horizontalScrollBar()->value();
+ scrollX += hbar->minimum();
+ scrollX += hbar->maximum();
+ scrollX -= hbar->value();
}
} else {
- scrollX += q->horizontalScrollBar()->value();
+ scrollX += hbar->value();
}
- scrollY = qint64(q->verticalScrollBar()->value() - topIndent);
+ scrollY = qint64(vbar->value() - topIndent);
dirtyScroll = false;
}
@@ -580,7 +576,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
return;
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
- mouseEvent.setWidget(q->viewport());
+ mouseEvent.setWidget(viewport);
mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
mouseEvent.setScenePos(q->mapToScene(event->pos()));
@@ -627,7 +623,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
if (hasStoredOriginalCursor) {
// Restore the original viewport cursor.
hasStoredOriginalCursor = false;
- q->viewport()->setCursor(originalCursor);
+ viewport->setCursor(originalCursor);
}
#endif
}
@@ -659,8 +655,6 @@ QRegion QGraphicsViewPrivate::rubberBandRegion(const QWidget *widget, const QRec
#ifndef QT_NO_CURSOR
void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor)
{
- Q_Q(QGraphicsView);
- QWidget *viewport = q->viewport();
if (!hasStoredOriginalCursor) {
hasStoredOriginalCursor = true;
originalCursor = viewport->cursor();
@@ -686,9 +680,9 @@ void QGraphicsViewPrivate::_q_unsetViewportCursor()
// Restore the original viewport cursor.
hasStoredOriginalCursor = false;
if (dragMode == QGraphicsView::ScrollHandDrag)
- q->viewport()->setCursor(Qt::OpenHandCursor);
+ viewport->setCursor(Qt::OpenHandCursor);
else
- q->viewport()->setCursor(originalCursor);
+ viewport->setCursor(originalCursor);
}
#endif
@@ -727,7 +721,7 @@ void QGraphicsViewPrivate::populateSceneDragDropEvent(QGraphicsSceneDragDropEven
dest->setProposedAction(source->proposedAction());
dest->setDropAction(source->dropAction());
dest->setMimeData(source->mimeData());
- dest->setWidget(q->viewport());
+ dest->setWidget(viewport);
dest->setSource(source->source());
#else
Q_UNUSED(dest)
@@ -750,12 +744,13 @@ QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRect
}
// Translate-only
+ // COMBINE
QPointF offset;
const QGraphicsItem *parentItem = item;
const QGraphicsItemPrivate *itemd;
do {
itemd = parentItem->d_ptr;
- if (itemd->hasTransform)
+ if (itemd->transformData)
break;
offset += itemd->pos;
} while ((parentItem = itemd->parent));
@@ -787,223 +782,103 @@ QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const Q
const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
// Accurate bounding region
- QTransform itv = item->sceneTransform() * q->viewportTransform();
+ QTransform itv = item->deviceTransform(q->viewportTransform());
return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
}
/*!
\internal
*/
-void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect)
-{
- if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate)
- return;
- if (item->d_ptr->dirty)
- updateLater();
-
- QRectF updateRect = rect;
- if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) {
- updateRect &= adjustedItemBoundingRect(item);
- if (updateRect.isEmpty())
- return;
- }
-
- QGraphicsItem *clipItem = item;
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
- // Minimize unnecessary redraw.
- QGraphicsItem *parent = item;
- while ((parent = parent->d_ptr->parent)) {
- if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
- // Map update rect to the current parent and itersect with its bounding rect.
- updateRect = clipItem->itemTransform(parent).mapRect(updateRect)
- & adjustedItemBoundingRect(parent);
- if (updateRect.isEmpty())
- return;
- clipItem = parent;
- }
-
- if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
- break;
- }
- }
-
- // Map update rect from clipItem coordinates to view coordinates.
- Q_ASSERT(clipItem);
- if (!item->d_ptr->hasBoundingRegionGranularity)
- this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect());
- else
- updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect());
-}
-
-void QGraphicsViewPrivate::updateLater()
+void QGraphicsViewPrivate::processPendingUpdates()
{
- Q_Q(QGraphicsView);
- if (updatingLater)
- return;
- updatingLater = true;
- QMetaObject::invokeMethod(q, "_q_updateLaterSlot", Qt::QueuedConnection);
-}
-
-void QGraphicsViewPrivate::_q_updateLaterSlot()
-{
- Q_Q(QGraphicsView);
if (!scene)
return;
- QRect vr = viewport->rect();
- QTransform viewTransform = q->viewportTransform();
- const QList<QGraphicsItem *> &dirtyItems = scene->d_func()->dirtyItems;
- for (int i = 0; i < dirtyItems.size(); ++i) {
- const QGraphicsItem *item = dirtyItems.at(i);
- if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false,
- /*ignoreVisibleBit=*/false,
- /*ignoreDirtyBit=*/true)) {
- continue;
- }
- QTransform x = item->sceneTransform() * viewTransform;
- updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr);
+ if (fullUpdatePending) { // We have already called viewport->update()
+ dirtyBoundingRect = QRect();
+ dirtyRegion = QRegion();
+ return;
}
- dirtyRectCount += dirtyRects.size();
-
- bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate;
- if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) {
- if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate
- || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate
- && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) {
- if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
- viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
- } else {
- viewport->update(dirtyBoundingRect);
- }
- } else {
- // ### Improve this block, which is very slow for complex regions. We
- // need to strike the balance between having an accurate update
- // region, and running fast. The below approach is the simplest way to
- // create a region from a bunch of rects, but we might want to use
- // other approaches; e.g., a grid of a fixed size representing
- // quadrants of the viewport, which we mark as dirty depending on the
- // rectangles in the list. Perhaps this should go into a
- // QRegion::fromRects(rects, how) function.
- QRegion region;
- if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
- for (int i = 0; i < dirtyRegions.size(); ++i) {
- QVector<QRect> rects = dirtyRegions.at(i).rects();
- for (int j = 0; j < rects.size(); ++j)
- region += rects.at(j).adjusted(-2, -2, 2, 2);
- }
- for (int i = 0; i < dirtyRects.size(); ++i)
- region += dirtyRects.at(i).adjusted(-2, -2, 2, 2);
- } else {
- for (int i = 0; i < dirtyRegions.size(); ++i)
- region += dirtyRegions.at(i);
- for (int i = 0; i < dirtyRects.size(); ++i)
- region += dirtyRects.at(i);
- }
-
- viewport->update(region);
- }
+ if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ viewport->update(dirtyBoundingRect);
+ else
+ viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
+ } else {
+ viewport->update(dirtyRegion); // Already adjusted in updateRect/Region.
}
- dirtyRegions.clear();
- dirtyRects.clear();
- dirtyRectCount = 0;
dirtyBoundingRect = QRect();
- updatingLater = false;
+ dirtyRegion = QRegion();
}
void QGraphicsViewPrivate::updateAll()
{
- Q_Q(QGraphicsView);
- q->viewport()->update();
+ viewport->update();
fullUpdatePending = true;
- dirtyRectCount = 0;
dirtyBoundingRect = QRect();
- updatingLater = false;
+ dirtyRegion = QRegion();
}
void QGraphicsViewPrivate::updateRegion(const QRegion &r)
{
- if (r.isEmpty())
+ if (r.isEmpty() || fullUpdatePending)
return;
- Q_Q(QGraphicsView);
-
// Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
- q->viewport()->update();
+ viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
dirtyBoundingRect |= r.boundingRect();
- if (dirtyBoundingRect == q->viewport()->rect()) {
+ if (dirtyBoundingRect.contains(viewport->rect())) {
fullUpdatePending = true;
- q->viewport()->update();
- } else {
- updateLater();
+ viewport->update();
}
break;
- case QGraphicsView::SmartViewportUpdate:
- dirtyBoundingRect |= r.boundingRect();
- if ((dirtyRectCount + r.numRects()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
- dirtyRegions << r;
- dirtyRectCount += r.numRects();
- updateLater();
- break;
+ case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
case QGraphicsView::MinimalViewportUpdate:
- dirtyRegions << r;
- dirtyRectCount += r.numRects();
- updateLater();
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing) {
+ dirtyRegion += r;
+ } else {
+ const QVector<QRect> &rects = r.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2);
+ }
break;
case QGraphicsView::NoViewportUpdate:
// Unreachable
break;
}
-
- // Compress the regions...
- if (dirtyRectCount > QGRAPHICSVIEW_REGION_RECT_THRESHOLD && dirtyRegions.size() > 1) {
- QRegion masterRegion;
- for (int i=0; i<dirtyRegions.size(); ++i) {
- masterRegion |= dirtyRegions.at(i);
- }
- dirtyRectCount = masterRegion.numRects();
- dirtyRegions.clear();
- dirtyRegions << masterRegion;
- }
}
void QGraphicsViewPrivate::updateRect(const QRect &r)
{
- if (r.isEmpty())
+ if (r.isEmpty() || fullUpdatePending)
return;
- Q_Q(QGraphicsView);
-
// Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
- q->viewport()->update();
+ viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
dirtyBoundingRect |= r;
- if (dirtyBoundingRect == q->viewport()->rect()) {
+ if (dirtyBoundingRect.contains(viewport->rect())) {
fullUpdatePending = true;
- q->viewport()->update();
- } else {
- updateLater();
+ viewport->update();
}
break;
- case QGraphicsView::SmartViewportUpdate:
- dirtyBoundingRect |= r;
- if ((dirtyRectCount + dirtyRects.size()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
- dirtyRects << r;
- updateLater();
- break;
+ case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
case QGraphicsView::MinimalViewportUpdate:
- dirtyRects << r;
- updateLater();
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ dirtyRegion += r;
+ else
+ dirtyRegion += r.adjusted(-2, -2, 2, 2);
break;
case QGraphicsView::NoViewportUpdate:
// Unreachable
@@ -2595,9 +2470,11 @@ void QGraphicsView::updateScene(const QList<QRectF> &rects)
// Extract and reset dirty scene rect info.
QVector<QRect> dirtyViewportRects;
- for (int i = 0; i < d->dirtyRegions.size(); ++i)
- dirtyViewportRects += d->dirtyRegions.at(i).rects();
- d->dirtyRegions.clear();
+ const QVector<QRect> &dirtyRects = d->dirtyRegion.rects();
+ for (int i = 0; i < dirtyRects.size(); ++i)
+ dirtyViewportRects += dirtyRects.at(i);
+ d->dirtyRegion = QRegion();
+ d->dirtyBoundingRect = QRect();
bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate)
@@ -3337,16 +3214,15 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState);
// Determine the exposed region
- QRegion exposedRegion = event->region();
+ d->exposedRegion = event->region();
if (!d->accelerateScrolling)
- exposedRegion = viewport()->rect();
+ d->exposedRegion = viewport()->rect();
else if (d->viewportUpdateMode == BoundingRectViewportUpdate)
- exposedRegion = event->rect();
- QRectF exposedSceneRect = mapToScene(exposedRegion.boundingRect()).boundingRect();
+ d->exposedRegion = event->rect();
+ QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
// Set up the painter
QPainter painter(viewport());
- QTransform original = painter.worldTransform();
#ifndef QT_NO_RUBBERBAND
if (d->rubberBanding && !d->rubberBandRect.isEmpty())
painter.save();
@@ -3357,22 +3233,9 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Set up viewport transform
const QTransform viewTransform = viewportTransform();
- painter.setTransform(viewTransform, true);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- QTime stopWatch;
- stopWatch.start();
- qDebug() << "QGraphicsView::paintEvent(" << exposedRegion << ')';
-#endif
-
- // Find all exposed items
- bool allItems = false;
- QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- int exposedTime = stopWatch.elapsed();
-#endif
+ painter.setWorldTransform(viewTransform);
+ // Draw background
if ((d->cacheMode & CacheBackground)
#ifdef Q_WS_X11
&& X11->use_xrender
@@ -3402,10 +3265,9 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
}
// Blit the background from the background pixmap
- QTransform oldMatrix = painter.worldTransform();
- painter.setWorldTransform(original);
+ painter.setWorldTransform(QTransform());
painter.drawPixmap(QPoint(), d->backgroundPixmap);
- painter.setWorldTransform(oldMatrix);
+ painter.setWorldTransform(viewTransform);
} else {
if (!(d->optimizationFlags & DontSavePainterState))
painter.save();
@@ -3414,33 +3276,31 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.restore();
}
-#ifdef QGRAPHICSVIEW_DEBUG
- int backgroundTime = stopWatch.elapsed() - exposedTime;
-#endif
-
- if (!itemList.isEmpty()) {
- // Generate the style options.
- const int numItems = itemList.size();
- QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
- QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
- for (int i = 0; i < numItems; ++i)
- itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, exposedRegion, allItems);
- // Draw the items.
- drawItems(&painter, numItems, itemArray, styleOptionArray);
- d->freeStyleOptionsArray(styleOptionArray);
+ // Items
+ if (!(d->optimizationFlags & IndirectPainting)) {
+ d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion,
+ viewport(), 0);
+ } else {
+ // Find all exposed items
+ bool allItems = false;
+ QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems);
+
+ if (!itemList.isEmpty()) {
+ // Generate the style options.
+ const int numItems = itemList.size();
+ QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
+ QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems);
+ // Draw the items.
+ drawItems(&painter, numItems, itemArray, styleOptionArray);
+ d->freeStyleOptionsArray(styleOptionArray);
+ }
}
-#ifdef QGRAPHICSVIEW_DEBUG
- int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime;
-#endif
-
// Foreground
drawForeground(&painter, exposedSceneRect);
-#ifdef QGRAPHICSVIEW_DEBUG
- int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;
-#endif
-
#ifndef QT_NO_RUBBERBAND
// Rubberband
if (d->rubberBanding && !d->rubberBandRect.isEmpty()) {
@@ -3462,17 +3322,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.end();
-#ifdef QGRAPHICSVIEW_DEBUG
- qDebug() << "\tItem discovery....... " << exposedTime << "msecs (" << itemList.size() << "items,"
- << (exposedTime > 0 ? (itemList.size() * 1000.0 / exposedTime) : -1) << "/ sec )";
- qDebug() << "\tDrawing background... " << backgroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
- qDebug() << "\tDrawing items........ " << itemsTime << "msecs ("
- << (itemsTime > 0 ? (itemList.size() * 1000.0 / itemsTime) : -1) << "/ sec )";
- qDebug() << "\tDrawing foreground... " << foregroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
- qDebug() << "\tTotal rendering time: " << stopWatch.elapsed() << "msecs ("
- << (stopWatch.elapsed() > 0 ? (1000.0 / stopWatch.elapsed()) : -1.0) << "fps )";
-#endif
-
// Restore painter state protection.
d->scene->d_func()->painterStateProtection = true;
}
@@ -3519,10 +3368,7 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) {
- for (int i = 0; i < d->dirtyRects.size(); ++i)
- d->dirtyRects[i].translate(dx, dy);
- for (int i = 0; i < d->dirtyRegions.size(); ++i)
- d->dirtyRegions[i].translate(dx, dy);
+ d->dirtyRegion.translate(dx, dy);
if (d->accelerateScrolling) {
#ifndef QT_NO_RUBBERBAND
// Update new and old rubberband regions
@@ -3656,8 +3502,10 @@ void QGraphicsView::drawItems(QPainter *painter, int numItems,
const QStyleOptionGraphicsItem options[])
{
Q_D(QGraphicsView);
- if (d->scene)
- d->scene->drawItems(painter, numItems, items, options, viewport());
+ if (d->scene) {
+ QWidget *widget = painter->device() == viewport() ? viewport() : 0;
+ d->scene->drawItems(painter, numItems, items, options, widget);
+ }
}
/*!
@@ -3686,6 +3534,18 @@ QTransform QGraphicsView::viewportTransform() const
}
/*!
+ Returns true if the view is transformed (i.e., a non-identity transform
+ has been assigned, or the scrollbars are adjusted).
+
+ \sa setTransform(), horizontalScrollBar(), verticalScrollBar()
+*/
+bool QGraphicsView::isTransformed() const
+{
+ Q_D(const QGraphicsView);
+ return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
+}
+
+/*!
Sets the view's current transformation matrix to \a matrix.
If \a combine is true, then \a matrix is combined with the current matrix;
diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h
index c3ea6e5b9f..387fa018dc 100644
--- a/src/gui/graphicsview/qgraphicsview.h
+++ b/src/gui/graphicsview/qgraphicsview.h
@@ -112,7 +112,8 @@ public:
enum OptimizationFlag {
DontClipPainter = 0x1, // obsolete
DontSavePainterState = 0x2,
- DontAdjustForAntialiasing = 0x4
+ DontAdjustForAntialiasing = 0x4,
+ IndirectPainting = 0x8
};
Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag)
@@ -169,6 +170,7 @@ public:
void resetMatrix();
QTransform transform() const;
QTransform viewportTransform() const;
+ bool isTransformed() const;
void setTransform(const QTransform &matrix, bool combine = false);
void resetTransform();
void rotate(qreal angle);
@@ -273,7 +275,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_setViewportCursor(const QCursor &))
Q_PRIVATE_SLOT(d_func(), void _q_unsetViewportCursor())
#endif
- Q_PRIVATE_SLOT(d_func(), void _q_updateLaterSlot())
friend class QGraphicsSceneWidget;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index c18f85daef..814e476592 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -159,19 +159,15 @@ public:
QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const;
QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const;
- void itemUpdated(QGraphicsItem *item, const QRectF &rect);
bool fullUpdatePending;
- QList<QRect> dirtyRects;
- QList<QRegion> dirtyRegions;
- int dirtyRectCount;
+ QRegion dirtyRegion;
QRect dirtyBoundingRect;
- void updateLater();
- bool updatingLater;
- void _q_updateLaterSlot();
+ void processPendingUpdates();
void updateAll();
void updateRect(const QRect &rect);
void updateRegion(const QRegion &region);
bool updateSceneSlotReimplementedChecked;
+ QRegion exposedRegion;
QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const;
};
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 3296aee4b7..731416745c 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -1057,6 +1057,9 @@ void QGraphicsWidget::updateGeometry()
ItemParentChange both to deliver \l ParentChange events, and for managing
the focus chain.
+ QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in
+ order to track position changes.
+
\sa propertyChange()
*/
QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value)
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index a435758612..557b88339d 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -77,7 +77,9 @@ void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFl
resolveLayoutDirection();
q->unsetWindowFrameMargins();
q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+ q->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
}
+
qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{
Q_Q(const QGraphicsWidget);
diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h
index a3fd34f0bc..3e8391ff67 100644
--- a/src/gui/image/qpicture_p.h
+++ b/src/gui/image/qpicture_p.h
@@ -69,7 +69,7 @@ class QPaintEngine;
extern const char *qt_mfhdr_tag;
-class Q_GUI_EXPORT QPicturePrivate
+class QPicturePrivate
{
Q_DECLARE_PUBLIC(QPicture)
friend class QPicturePaintEngine;
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp
index c90216b210..7890e1fa87 100644
--- a/src/gui/itemviews/qabstractitemview.cpp
+++ b/src/gui/itemviews/qabstractitemview.cpp
@@ -108,16 +108,16 @@ void QAbstractItemViewPrivate::init()
Q_Q(QAbstractItemView);
q->setItemDelegate(new QStyledItemDelegate(q));
- q->verticalScrollBar()->setRange(0, 0);
- q->horizontalScrollBar()->setRange(0, 0);
+ vbar->setRange(0, 0);
+ hbar->setRange(0, 0);
- QObject::connect(q->verticalScrollBar(), SIGNAL(actionTriggered(int)),
+ QObject::connect(vbar, SIGNAL(actionTriggered(int)),
q, SLOT(verticalScrollbarAction(int)));
- QObject::connect(q->horizontalScrollBar(), SIGNAL(actionTriggered(int)),
+ QObject::connect(hbar, SIGNAL(actionTriggered(int)),
q, SLOT(horizontalScrollbarAction(int)));
- QObject::connect(q->verticalScrollBar(), SIGNAL(valueChanged(int)),
+ QObject::connect(vbar, SIGNAL(valueChanged(int)),
q, SLOT(verticalScrollbarValueChanged(int)));
- QObject::connect(q->horizontalScrollBar(), SIGNAL(valueChanged(int)),
+ QObject::connect(hbar, SIGNAL(valueChanged(int)),
q, SLOT(horizontalScrollbarValueChanged(int)));
viewport->setBackgroundRole(QPalette::Base);
@@ -2398,8 +2398,8 @@ void QAbstractItemView::updateEditorGeometries()
//we release the editor outside of the loop because it might change the focus and try
//to change the d->editors list.
- foreach(QWidget *editor, editorsToRelease) {
- d->releaseEditor(editor);
+ for (int i = 0; i < editorsToRelease.count(); ++i) {
+ d->releaseEditor(editorsToRelease.at(i));
}
}
diff --git a/src/gui/itemviews/qcolumnview.cpp b/src/gui/itemviews/qcolumnview.cpp
index 4fb08bb36a..1f88f7cac0 100644
--- a/src/gui/itemviews/qcolumnview.cpp
+++ b/src/gui/itemviews/qcolumnview.cpp
@@ -108,9 +108,9 @@ void QColumnViewPrivate::initialize()
{
Q_Q(QColumnView);
q->setTextElideMode(Qt::ElideMiddle);
- q->connect(&currentAnimation, SIGNAL(frameChanged(int)),
- q->horizontalScrollBar(), SLOT(setValue(int)));
- q->connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
+ QObject::connect(&currentAnimation, SIGNAL(frameChanged(int)),
+ hbar, SLOT(setValue(int)));
+ QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
delete itemDelegate;
q->setItemDelegate(new QColumnViewDelegate(q));
}
@@ -421,23 +421,23 @@ void QColumnViewPrivate::updateScrollbars()
horizontalLength = (columns.first()->x() + columns.first()->width()) - columns.last()->x();
}
- QSize viewportSize = q->viewport()->size();
- if (horizontalLength < viewportSize.width() && q->horizontalScrollBar()->value() == 0) {
- q->horizontalScrollBar()->setRange(0, 0);
+ QSize viewportSize = viewport->size();
+ if (horizontalLength < viewportSize.width() && hbar->value() == 0) {
+ hbar->setRange(0, 0);
} else {
int visibleLength = qMin(horizontalLength + q->horizontalOffset(), viewportSize.width());
int hiddenLength = horizontalLength - visibleLength;
- if (hiddenLength != q->horizontalScrollBar()->maximum())
- q->horizontalScrollBar()->setRange(0, hiddenLength);
+ if (hiddenLength != hbar->maximum())
+ hbar->setRange(0, hiddenLength);
}
if (!columns.isEmpty()) {
int pageStepSize = columns.at(0)->width();
- if (pageStepSize != q->horizontalScrollBar()->pageStep())
- q->horizontalScrollBar()->setPageStep(pageStepSize);
+ if (pageStepSize != hbar->pageStep())
+ hbar->setPageStep(pageStepSize);
}
- bool visible = (q->horizontalScrollBar()->maximum() > 0);
- if (visible != q->horizontalScrollBar()->isVisible())
- q->horizontalScrollBar()->setVisible(visible);
+ bool visible = (hbar->maximum() > 0);
+ if (visible != hbar->isVisible())
+ hbar->setVisible(visible);
}
/*!
@@ -696,7 +696,7 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
q, SIGNAL(pressed(const QModelIndex &)));
view->setFocusPolicy(Qt::NoFocus);
- view->setParent(q->viewport());
+ view->setParent(viewport);
Q_ASSERT(view);
// Setup corner grip
@@ -707,13 +707,13 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
}
if (columnSizes.count() > columns.count()) {
- view->setGeometry(0, 0, columnSizes.at(columns.count()), q->viewport()->height());
+ view->setGeometry(0, 0, columnSizes.at(columns.count()), viewport->height());
} else {
int initialWidth = view->sizeHint().width();
if (q->isRightToLeft())
- view->setGeometry(q->viewport()->width() - initialWidth, 0, initialWidth, q->viewport()->height());
+ view->setGeometry(viewport->width() - initialWidth, 0, initialWidth, viewport->height());
else
- view->setGeometry(0, 0, initialWidth, q->viewport()->height());
+ view->setGeometry(0, 0, initialWidth, viewport->height());
columnSizes.resize(qMax(columnSizes.count(), columns.count() + 1));
columnSizes[columns.count()] = initialWidth;
}
@@ -1056,11 +1056,11 @@ void QColumnViewPrivate::doLayout()
if (!model || columns.isEmpty())
return;
- int viewportHeight = q->viewport()->height();
+ int viewportHeight = viewport->height();
int x = columns.at(0)->x();
if (q->isRightToLeft()) {
- x = q->viewport()->width() + q->horizontalOffset();
+ x = viewport->width() + q->horizontalOffset();
for (int i = 0; i < columns.size(); ++i) {
QAbstractItemView *view = columns.at(i);
x -= view->width();
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index d28c08adab..d0321d8628 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -1153,7 +1153,8 @@ void QHeaderView::setResizeMode(ResizeMode mode)
\overload
Sets the constraints on how the section specified by \a logicalIndex in
- the header can be resized to those described by the given \a mode.
+ the header can be resized to those described by the given \a mode. The logical
+ index should exist at the time this function is called.
\note This setting will be ignored for the last section if the stretchLastSection
property is set to true. This is the default for the horizontal headers provided
@@ -3473,11 +3474,10 @@ void QHeaderViewPrivate::setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode)
int QHeaderViewPrivate::viewSectionSizeHint(int logical) const
{
- Q_Q(const QHeaderView);
- if (QAbstractItemView *parent = qobject_cast<QAbstractItemView*>(q->parent())) {
+ if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent)) {
return (orientation == Qt::Horizontal
- ? parent->sizeHintForColumn(logical)
- : parent->sizeHintForRow(logical));
+ ? view->sizeHintForColumn(logical)
+ : view->sizeHintForRow(logical));
}
return 0;
}
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index 03ba641909..fe7916c7c8 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -610,7 +610,7 @@ int QListViewPrivate::horizontalScrollToValue(const QModelIndex &index, const QR
const bool rightOf = q->isRightToLeft()
? rect.right() > area.right()
: (rect.right() > area.right()) && (rect.left() > area.left());
- int horizontalValue = q->horizontalScrollBar()->value();
+ int horizontalValue = hbar->value();
// ScrollPerItem
if (q->horizontalScrollMode() == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
@@ -652,10 +652,10 @@ int QListViewPrivate::verticalScrollToValue(const QModelIndex &index, const QRec
const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top());
const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom());
- int verticalValue = q->verticalScrollBar()->value();
+ int verticalValue = vbar->value();
// ScrollPerItem
- if (q->verticalScrollMode() == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
+ if (verticalScrollMode == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
const QListViewItem item = indexToListViewItem(index);
const QRect rect = q->visualRect(index);
verticalValue = staticListView->verticalPerItemValue(itemIndex(item),
@@ -1972,10 +1972,10 @@ void QListViewPrivate::prepareItemsLayout()
// Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
// is Qt::ScrollBarAsNeeded
int verticalMargin = vbarpolicy==Qt::ScrollBarAsNeeded
- ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->verticalScrollBar()) + frameAroundContents
+ ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, vbar) + frameAroundContents
: 0;
int horizontalMargin = hbarpolicy==Qt::ScrollBarAsNeeded
- ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->horizontalScrollBar()) + frameAroundContents
+ ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, hbar) + frameAroundContents
: 0;
layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin);
diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp
index e1e509dd51..504908fbb1 100644
--- a/src/gui/itemviews/qlistwidget.cpp
+++ b/src/gui/itemviews/qlistwidget.cpp
@@ -687,7 +687,10 @@ QVariant QListWidgetItem::data(int role) const
*/
bool QListWidgetItem::operator<(const QListWidgetItem &other) const
{
- return text() < other.text();
+ const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
+ if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2))
+ return v1.toDouble() < v2.toDouble();
+ return v1.toString() < v2.toString();
}
#ifndef QT_NO_DATASTREAM
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index 96eb6f02e7..4021c8356f 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -884,8 +884,8 @@ void QSortFilterProxyModelPrivate::proxy_item_range(
{
proxy_low = INT_MAX;
proxy_high = INT_MIN;
- foreach (int source_item, source_items) {
- int proxy_item = source_to_proxy.at(source_item);
+ for (int i = 0; i < source_items.count(); ++i) {
+ int proxy_item = source_to_proxy.at(source_items.at(i));
Q_ASSERT(proxy_item != -1);
if (proxy_item < proxy_low)
proxy_low = proxy_item;
@@ -985,7 +985,8 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
Q_Q(QSortFilterProxyModel);
// Figure out which mapped items to remove
QVector<int> source_items_remove;
- foreach (int source_item, proxy_to_source) {
+ for (int i = 0; i < proxy_to_source.count(); ++i) {
+ const int source_item = proxy_to_source.at(i);
if ((orient == Qt::Vertical)
? !q->filterAcceptsRow(source_item, source_parent)
: !q->filterAcceptsColumn(source_item, source_parent)) {
diff --git a/src/gui/itemviews/qstandarditemmodel.cpp b/src/gui/itemviews/qstandarditemmodel.cpp
index d8adbd22ba..9d0f796c98 100644
--- a/src/gui/itemviews/qstandarditemmodel.cpp
+++ b/src/gui/itemviews/qstandarditemmodel.cpp
@@ -2907,8 +2907,8 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
QStack<QStandardItem*> stack;
itemsSet.reserve(indexes.count());
stack.reserve(indexes.count());
- foreach (const QModelIndex &index, indexes) {
- QStandardItem *item = itemFromIndex(index);
+ for (int i = 0; i < indexes.count(); ++i) {
+ QStandardItem *item = itemFromIndex(indexes.at(i));
itemsSet << item;
stack.push(item);
}
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index 0bded54607..454b1f54cc 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -1844,14 +1844,14 @@ void QTableView::setSortingEnabled(bool enable)
disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)),
this, SLOT(selectColumn(int)));
connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(sortByColumn(int)));
+ this, SLOT(sortByColumn(int)), Qt::UniqueConnection);
sortByColumn(horizontalHeader()->sortIndicatorSection(),
horizontalHeader()->sortIndicatorOrder());
} else {
connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
- this, SLOT(_q_selectColumn(int)));
+ this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection);
connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
- this, SLOT(selectColumn(int)));
+ this, SLOT(selectColumn(int)), Qt::UniqueConnection);
disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
this, SLOT(sortByColumn(int)));
}
diff --git a/src/gui/itemviews/qtablewidget.cpp b/src/gui/itemviews/qtablewidget.cpp
index 8cb2e55214..072e435a9a 100644
--- a/src/gui/itemviews/qtablewidget.cpp
+++ b/src/gui/itemviews/qtablewidget.cpp
@@ -530,24 +530,6 @@ void QTableModel::sort(int column, Qt::SortOrder order)
emit layoutChanged();
}
-bool QTableModel::canConvertToDouble(const QVariant &value)
-{
- switch (value.type()) {
- case QVariant::Bool:
- case QVariant::Int:
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- case QVariant::Double:
- case QVariant::Char:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-
/*
\internal
@@ -1410,7 +1392,7 @@ QVariant QTableWidgetItem::data(int role) const
bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const
{
const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
- if (QTableModel::canConvertToDouble(v1) && QTableModel::canConvertToDouble(v2))
+ if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2))
return v1.toDouble() < v2.toDouble();
return v1.toString() < v2.toString();
}
diff --git a/src/gui/itemviews/qtablewidget_p.h b/src/gui/itemviews/qtablewidget_p.h
index 2e1dab64c0..d8bfcc5e84 100644
--- a/src/gui/itemviews/qtablewidget_p.h
+++ b/src/gui/itemviews/qtablewidget_p.h
@@ -144,7 +144,6 @@ public:
const QPair<QTableWidgetItem*,int> &right);
static bool itemGreaterThan(const QPair<QTableWidgetItem*,int> &left,
const QPair<QTableWidgetItem*,int> &right);
- static bool canConvertToDouble(const QVariant &value);
void ensureSorted(int column, Qt::SortOrder order, int start, int end);
QVector<QTableWidgetItem*> columnItems(int column) const;
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index 7837700773..53fa17078a 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -238,11 +238,6 @@ void QTreeView::setModel(QAbstractItemModel *model)
connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(rowsRemoved(QModelIndex,int,int)));
- connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
-
connect(d->model, SIGNAL(modelAboutToBeReset()), SLOT(_q_modelAboutToBeReset()));
if (d->sortingEnabled)
@@ -1324,7 +1319,7 @@ bool QTreeViewPrivate::expandOrCollapseItemAtPos(const QPoint &pos)
expand(i, true);
if (!isAnimating()) {
q->updateGeometries();
- q->viewport()->update();
+ viewport->update();
}
return true;
}
@@ -2072,7 +2067,8 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
const bool useTopIndex = (cursorAction == MoveUp || cursorAction == MovePrevious);
int index = useTopIndex ? INT_MAX : INT_MIN;
const QItemSelection selection = d->selectionModel->selection();
- foreach (const QItemSelectionRange &range, selection) {
+ for (int i = 0; i < selection.count(); ++i) {
+ const QItemSelectionRange &range = selection.at(i);
int candidate = d->viewIndex(useTopIndex ? range.topLeft() : range.bottomRight());
if (candidate >= 0)
index = useTopIndex ? qMin(index, candidate) : qMax(index, candidate);
@@ -3071,16 +3067,16 @@ void QTreeViewPrivate::_q_modelAboutToBeReset()
void QTreeViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
- Q_UNUSED(parent);
if (start <= 0 && 0 <= end)
viewItems.clear();
+ QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(parent, start, end);
}
void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, int end)
{
- Q_UNUSED(parent);
if (start <= 0 && 0 <= end)
doDelayedItemsLayout();
+ QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end);
}
void QTreeViewPrivate::layout(int i)
@@ -3205,19 +3201,18 @@ int QTreeViewPrivate::itemHeight(int item) const
*/
int QTreeViewPrivate::coordinateForItem(int item) const
{
- Q_Q(const QTreeView);
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights)
- return (item * defaultItemHeight) - q->verticalScrollBar()->value();
+ return (item * defaultItemHeight) - vbar->value();
// ### optimize (spans or caching)
int y = 0;
for (int i = 0; i < viewItems.count(); ++i) {
if (i == item)
- return y - q->verticalScrollBar()->value();
+ return y - vbar->value();
y += itemHeight(i);
}
} else { // ScrollPerItem
- int topViewItemIndex = q->verticalScrollBar()->value();
+ int topViewItemIndex = vbar->value();
if (uniformRowHeights)
return defaultItemHeight * (item - topViewItemIndex);
if (item >= topViewItemIndex) {
@@ -3257,7 +3252,6 @@ int QTreeViewPrivate::coordinateForItem(int item) const
*/
int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
{
- Q_Q(const QTreeView);
const int itemCount = viewItems.count();
if (itemCount == 0)
return -1;
@@ -3265,19 +3259,19 @@ int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
return -1;
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights) {
- const int viewItemIndex = (coordinate + q->verticalScrollBar()->value()) / defaultItemHeight;
+ const int viewItemIndex = (coordinate + vbar->value()) / defaultItemHeight;
return ((viewItemIndex >= itemCount || viewItemIndex < 0) ? -1 : viewItemIndex);
}
// ### optimize
int viewItemCoordinate = 0;
- const int contentsCoordinate = coordinate + q->verticalScrollBar()->value();
+ const int contentsCoordinate = coordinate + vbar->value();
for (int viewItemIndex = 0; viewItemIndex < viewItems.count(); ++viewItemIndex) {
viewItemCoordinate += itemHeight(viewItemIndex);
if (viewItemCoordinate >= contentsCoordinate)
return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
}
} else { // ScrollPerItem
- int topViewItemIndex = q->verticalScrollBar()->value();
+ int topViewItemIndex = vbar->value();
if (uniformRowHeights) {
if (coordinate < 0)
coordinate -= defaultItemHeight - 1;
@@ -3369,8 +3363,7 @@ QModelIndex QTreeViewPrivate::modelIndex(int i, int column) const
int QTreeViewPrivate::firstVisibleItem(int *offset) const
{
- Q_Q(const QTreeView);
- const int value = q->verticalScrollBar()->value();
+ const int value = vbar->value();
if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
if (offset)
*offset = 0;
@@ -3447,9 +3440,9 @@ void QTreeViewPrivate::updateScrollBars()
if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
if (!viewItems.isEmpty())
itemsInViewport = qMax(1, itemsInViewport);
- q->verticalScrollBar()->setRange(0, viewItems.count() - itemsInViewport);
- q->verticalScrollBar()->setPageStep(itemsInViewport);
- q->verticalScrollBar()->setSingleStep(1);
+ vbar->setRange(0, viewItems.count() - itemsInViewport);
+ vbar->setPageStep(itemsInViewport);
+ vbar->setSingleStep(1);
} else { // scroll per pixel
int contentsHeight = 0;
if (uniformRowHeights) {
@@ -3458,9 +3451,9 @@ void QTreeViewPrivate::updateScrollBars()
for (int i = 0; i < viewItems.count(); ++i)
contentsHeight += itemHeight(i);
}
- q->verticalScrollBar()->setRange(0, contentsHeight - viewportSize.height());
- q->verticalScrollBar()->setPageStep(viewportSize.height());
- q->verticalScrollBar()->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
+ vbar->setRange(0, contentsHeight - viewportSize.height());
+ vbar->setPageStep(viewportSize.height());
+ vbar->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
}
const int columnCount = header->count();
@@ -3476,17 +3469,17 @@ void QTreeViewPrivate::updateScrollBars()
if (columnCount > 0)
columnsInViewport = qMax(1, columnsInViewport);
if (horizontalScrollMode == QAbstractItemView::ScrollPerItem) {
- q->horizontalScrollBar()->setRange(0, columnCount - columnsInViewport);
- q->horizontalScrollBar()->setPageStep(columnsInViewport);
- q->horizontalScrollBar()->setSingleStep(1);
+ hbar->setRange(0, columnCount - columnsInViewport);
+ hbar->setPageStep(columnsInViewport);
+ hbar->setSingleStep(1);
} else { // scroll per pixel
const int horizontalLength = header->length();
const QSize maxSize = q->maximumViewportSize();
- if (maxSize.width() >= horizontalLength && q->verticalScrollBar()->maximum() <= 0)
+ if (maxSize.width() >= horizontalLength && vbar->maximum() <= 0)
viewportSize = maxSize;
- q->horizontalScrollBar()->setPageStep(viewportSize.width());
- q->horizontalScrollBar()->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
- q->horizontalScrollBar()->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
+ hbar->setPageStep(viewportSize.width());
+ hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
+ hbar->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
}
}
@@ -3558,7 +3551,8 @@ QList<QPair<int, int> > QTreeViewPrivate::columnRanges(const QModelIndex &topInd
QPair<int, int> current;
current.first = -2; // -1 is not enough because -1+1 = 0
current.second = -2;
- foreach (int logicalColumn, logicalIndexes) {
+ for(int i = 0; i < logicalIndexes.count(); ++i) {
+ const int logicalColumn = logicalIndexes.at(i);
if (current.second + 1 != logicalColumn) {
if (current.first != -2) {
//let's save the current one
diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp
index 1c8758050f..5604f8de86 100644
--- a/src/gui/itemviews/qtreewidget.cpp
+++ b/src/gui/itemviews/qtreewidget.cpp
@@ -695,29 +695,6 @@ bool QTreeModel::itemGreaterThan(const QPair<QTreeWidgetItem*,int> &left,
}
/*!
- \internal
-
- Returns true if the type of the variant \a value
- can be casted as double.
-*/
-bool QTreeModel::canConvertToDouble(const QVariant &value)
-{
- switch (value.type()) {
- case QVariant::Bool:
- case QVariant::Int:
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- case QVariant::Double:
- case QVariant::Char:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-/*!
\internal
*/
QList<QTreeWidgetItem*>::iterator QTreeModel::sortedInsertionIterator(
@@ -1812,7 +1789,7 @@ bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const
int column = view ? view->sortColumn() : 0;
const QVariant v1 = data(column, Qt::DisplayRole);
const QVariant v2 = other.data(column, Qt::DisplayRole);
- if (QTreeModel::canConvertToDouble(v1) && QTreeModel::canConvertToDouble(v2))
+ if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2))
return v1.toDouble() < v2.toDouble();
return v1.toString() < v2.toString();
}
diff --git a/src/gui/itemviews/qtreewidget_p.h b/src/gui/itemviews/qtreewidget_p.h
index 96f734de16..a089cf5e93 100644
--- a/src/gui/itemviews/qtreewidget_p.h
+++ b/src/gui/itemviews/qtreewidget_p.h
@@ -116,7 +116,6 @@ public:
const QPair<QTreeWidgetItem*,int> &right);
static bool itemGreaterThan(const QPair<QTreeWidgetItem*,int> &left,
const QPair<QTreeWidgetItem*,int> &right);
- static bool canConvertToDouble(const QVariant &value);
static QList<QTreeWidgetItem*>::iterator sortedInsertionIterator(
const QList<QTreeWidgetItem*>::iterator &begin,
const QList<QTreeWidgetItem*>::iterator &end,
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index 051b6a65a1..f44d207202 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -136,25 +136,31 @@ void QActionPrivate::redoGrab(QShortcutMap &map)
void QActionPrivate::redoGrabAlternate(QShortcutMap &map)
{
Q_Q(QAction);
- foreach (int id, alternateShortcutIds)
- if (id)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
map.removeShortcut(id, q);
+ }
alternateShortcutIds.clear();
if (alternateShortcuts.isEmpty())
return;
- foreach (const QKeySequence& alternate, alternateShortcuts) {
+ for(int i = 0; i < alternateShortcuts.count(); ++i) {
+ const QKeySequence& alternate = alternateShortcuts.at(i);
if (!alternate.isEmpty())
alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext));
else
alternateShortcutIds.append(0);
}
if (!enabled) {
- foreach (int id, alternateShortcutIds)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
map.setShortcutEnabled(false, id, q);
+ }
}
if (!autorepeat) {
- foreach (int id, alternateShortcutIds)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
map.setShortcutAutoRepeat(false, id, q);
+ }
}
}
@@ -163,9 +169,10 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
Q_Q(QAction);
if (shortcutId)
map.setShortcutEnabled(enable, shortcutId, q);
- foreach (int id, alternateShortcutIds)
- if (id)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
map.setShortcutEnabled(enable, id, q);
+ }
}
#endif // QT_NO_SHORTCUT
@@ -615,8 +622,10 @@ QAction::~QAction()
#ifndef QT_NO_SHORTCUT
if (d->shortcutId && qApp) {
qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this);
- foreach (int id, d->alternateShortcutIds)
+ for(int i = 0; i < d->alternateShortcutIds.count(); ++i) {
+ const int id = d->alternateShortcutIds.at(i);
qApp->d_func()->shortcutMap.removeShortcut(id, this);
+ }
}
#endif
}
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 1473421e4b..8ebea19d50 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -157,6 +157,8 @@ static const char * x11_atomnames = {
"WM_TAKE_FOCUS\0"
"_NET_WM_PING\0"
"_NET_WM_CONTEXT_HELP\0"
+ "_NET_WM_SYNC_REQUEST\0"
+ "_NET_WM_SYNC_REQUEST_COUNTER\0"
// ICCCM window state
"WM_STATE\0"
@@ -508,6 +510,7 @@ static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg)
class QETWidget : public QWidget // event translator widget
{
public:
+ QWidgetPrivate* d_func() { return QWidget::d_func(); }
bool translateMouseEvent(const XEvent *);
void translatePaintEvent(const XEvent *);
bool translateConfigEvent(const XEvent *);
@@ -718,6 +721,44 @@ static int qt_xio_errhandler(Display *)
}
#endif
+#ifndef QT_NO_XSYNC
+struct qt_sync_request_event_data
+{
+ WId window;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg)
+{
+ qt_sync_request_event_data *data =
+ reinterpret_cast<qt_sync_request_event_data*>(arg);
+ if (event->type == ClientMessage &&
+ event->xany.window == data->window &&
+ event->xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) {
+ QWidget *w = QWidget::find(event->xany.window);
+ if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+#endif // QT_NO_XSYNC
static void qt_x11_create_intern_atoms()
{
@@ -2090,6 +2131,13 @@ void qt_init(QApplicationPrivate *priv, int,
#endif // QT_RUNTIME_XCURSOR
#endif // QT_NO_XCURSOR
+#ifndef QT_NO_XSYNC
+ int xsync_evbase, xsync_errbase;
+ int major, minor;
+ if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase))
+ XSyncInitialize(X11->display, &major, &minor);
+#endif // QT_NO_XSYNC
+
#ifndef QT_NO_XINERAMA
#ifdef QT_RUNTIME_XINERAMA
X11->ptrXineramaQueryExtension = 0;
@@ -3116,6 +3164,19 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
XSendEvent(event->xclient.display, event->xclient.window,
False, SubstructureNotifyMask|SubstructureRedirectMask, event);
}
+#ifndef QT_NO_XSYNC
+ } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (QTLWExtra *tlw = w->d_func()->maybeTopData()) {
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+#endif
}
} else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
widget->translateScrollDoneEvent(event);
@@ -4144,7 +4205,9 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
|| ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify)
&& qt_button_down == this)
|| (nextEvent.type == ClientMessage
- && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) {
+ && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) ||
+ (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) {
qApp->x11ProcessEvent(&nextEvent);
continue;
} else if (nextEvent.type != MotionNotify ||
@@ -5200,6 +5263,14 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
otherEvent.xconfigure.border_width;
}
}
+#ifndef QT_NO_XSYNC
+ qt_sync_request_event_data sync_event;
+ sync_event.window = internalWinId();
+ for (XEvent ev;;) {
+ if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event))
+ break;
+ }
+#endif // QT_NO_XSYNC
}
QRect cr (geometry());
@@ -5285,6 +5356,20 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
if (d->extra && d->extra->topextra)
d->extra->topextra->inTopLevelResize = false;
}
+#ifndef QT_NO_XSYNC
+ if (QTLWExtra *tlwExtra = d->maybeTopData()) {
+ if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) {
+ XSyncValue value;
+ XSyncIntsToValue(&value,
+ tlwExtra->newCounterValueLo,
+ tlwExtra->newCounterValueHi);
+
+ XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value);
+ tlwExtra->newCounterValueHi = 0;
+ tlwExtra->newCounterValueLo = 0;
+ }
+ }
+#endif
return true;
}
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index b9ace9d961..21bb5509fa 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -154,6 +154,10 @@ extern "C" {
# include <X11/extensions/Xrender.h>
#endif // QT_NO_XRENDER
+#ifndef QT_NO_XSYNC
+# include "X11/extensions/sync.h"
+#endif
+
// #define QT_NO_XKB
#ifndef QT_NO_XKB
# include <X11/XKBlib.h>
@@ -514,6 +518,8 @@ struct QX11Data
WM_TAKE_FOCUS,
_NET_WM_PING,
_NET_WM_CONTEXT_HELP,
+ _NET_WM_SYNC_REQUEST,
+ _NET_WM_SYNC_REQUEST_COUNTER,
// ICCCM window state
WM_STATE,
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 60268214b3..61d8f2070e 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1067,7 +1067,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
q->data = &data;
#ifndef QT_NO_THREAD
- if (!q->parent()) {
+ if (!parent) {
Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
"Widgets must be created in the GUI thread.");
}
@@ -4993,7 +4993,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QPoint scrollAreaOffset;
#ifndef QT_NO_SCROLLAREA
- QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent());
+ QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
if (scrollArea && scrollArea->viewport() == q) {
QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr;
QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index bf4f091c6c..ff194f76a9 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -131,6 +131,10 @@ struct QTLWExtra {
uint embedded : 1;
// *************************** Platform specific values (bit fields first) **********
+#ifndef QT_NO_XSYNC
+ int newCounterValueHi : 32;
+ uint newCounterValueLo : 32;
+#endif
#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
uint spont_unmapped: 1; // window was spontaneously unmapped
uint dnd : 1; // DND properties installed
@@ -156,6 +160,10 @@ struct QTLWExtra {
QWSManager *qwsManager;
#endif
#endif
+#ifndef QT_NO_XSYNC
+ WId syncUpdateCounter;
+ ulong syncRequestTimestamp;
+#endif
};
struct QWExtra {
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 4e340450c9..8159f8e383 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -754,11 +754,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
qBound(1, data.crect.width(), XCOORD_MAX),
qBound(1, data.crect.height(), XCOORD_MAX));
XStoreName(dpy, id, appName.data());
- Atom protocols[4];
+ Atom protocols[5];
int n = 0;
protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol
protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol
protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol
+#ifndef QT_NO_XSYNC
+ protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
+#endif // QT_NO_XSYNC
if (flags & Qt::WindowContextHelpButtonHint)
protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
XSetWMProtocols(dpy, id, protocols, n);
@@ -1877,6 +1880,23 @@ void QWidgetPrivate::show_sys()
if (setUserTime)
qt_net_update_user_time(q, userTime);
+#ifndef QT_NO_XSYNC
+ if (!topData()->syncUpdateCounter) {
+ XSyncValue value;
+ XSyncIntToValue(&value, 0);
+ topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
+
+ XChangeProperty(X11->display, q->internalWinId(),
+ ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
+ XA_CARDINAL,
+ 32, PropModeReplace,
+ (uchar *) &topData()->syncUpdateCounter, 1);
+
+ topData()->newCounterValueHi = 0;
+ topData()->newCounterValueLo = 0;
+ }
+#endif
+
if (!topData()->embedded
&& (topData()->validWMState || topData()->waitingForMapNotify)
&& !q->isMinimized()) {
@@ -2687,6 +2707,12 @@ void QWidgetPrivate::createTLSysExtra()
extra->topextra->waitingForMapNotify = 0;
extra->topextra->parentWinId = 0;
extra->topextra->userTimeWindow = 0;
+#ifndef QT_NO_XSYNC
+ extra->topextra->syncUpdateCounter = 0;
+ extra->topextra->syncRequestTimestamp = 0;
+ extra->topextra->newCounterValueHi = 0;
+ extra->topextra->newCounterValueLo = 0;
+#endif
}
void QWidgetPrivate::deleteTLSysExtra()
diff --git a/src/gui/kernel/qwidgetaction.cpp b/src/gui/kernel/qwidgetaction.cpp
index efdde5e1e6..cd1202967e 100644
--- a/src/gui/kernel/qwidgetaction.cpp
+++ b/src/gui/kernel/qwidgetaction.cpp
@@ -228,8 +228,8 @@ bool QWidgetAction::event(QEvent *event)
if (event->type() == QEvent::ActionChanged) {
if (d->defaultWidget)
d->defaultWidget->setEnabled(isEnabled());
- foreach (QWidget *w, d->createdWidgets)
- w->setEnabled(isEnabled());
+ for (int i = 0; i < d->createdWidgets.count(); ++i)
+ d->createdWidgets.at(i)->setEnabled(isEnabled());
}
return QAction::event(event);
}
diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp
index 6ecd878df3..19a0f6ebc8 100644
--- a/src/gui/math3d/qgenericmatrix.cpp
+++ b/src/gui/math3d/qgenericmatrix.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
index b4d37073e6..330ded20c8 100644
--- a/src/gui/math3d/qgenericmatrix.h
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 8ef4da3a8a..a69b9df04f 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
index ba7f67f6f5..da1bcba0fb 100644
--- a/src/gui/math3d/qmatrix4x4.h
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
index 96659eafa0..03f626a587 100644
--- a/src/gui/math3d/qquaternion.cpp
+++ b/src/gui/math3d/qquaternion.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
index c05c6413b9..b17cf73856 100644
--- a/src/gui/math3d/qquaternion.h
+++ b/src/gui/math3d/qquaternion.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp
index c3aaa42747..df2519dabf 100644
--- a/src/gui/math3d/qvector2d.cpp
+++ b/src/gui/math3d/qvector2d.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
index b027df456e..2be0a11c64 100644
--- a/src/gui/math3d/qvector2d.h
+++ b/src/gui/math3d/qvector2d.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp
index c83cd6093f..a5f5c5b160 100644
--- a/src/gui/math3d/qvector3d.cpp
+++ b/src/gui/math3d/qvector3d.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
index 02873f2fa9..480667aa99 100644
--- a/src/gui/math3d/qvector3d.h
+++ b/src/gui/math3d/qvector3d.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp
index 010fa534a5..c5124e2f0f 100644
--- a/src/gui/math3d/qvector4d.cpp
+++ b/src/gui/math3d/qvector4d.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
index 8e673f31fa..e38f4e5b8b 100644
--- a/src/gui/math3d/qvector4d.h
+++ b/src/gui/math3d/qvector4d.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index 175f1ab7a5..5ce1136610 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -99,9 +99,9 @@ void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
QBrush copy = brush;
QTransform mat = copy.transform();
- QRealRect r = path.controlPointRect();
- mat.translate(r.x1, r.y1);
- mat.scale(r.x2 - r.x1, r.y2 - r.y1);
+ QRectF r = path.controlPointRect();
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
copy.setTransform(mat);
real_engine->fill(path, copy);
return;
@@ -139,9 +139,9 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
return;
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
QTransform mat = brush.transform();
- QRealRect r = path.controlPointRect();
- mat.translate(r.x1, r.y1);
- mat.scale(r.x2 - r.x1, r.y2 - r.y1);
+ QRectF r = path.controlPointRect();
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
brush.setTransform(mat);
copy.setBrush(brush);
real_engine->stroke(path, copy);
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 0810bb9cb9..471145529f 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -1852,8 +1852,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
}
// ### Optimize for non transformed ellipses and rectangles...
- QRealRect r = path.controlPointRect();
- QRectF cpRect(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1);
+ QRectF cpRect = path.controlPointRect();
const QRect deviceRect = s->matrix.mapRect(cpRect).toRect();
ProcessSpans blend = d->getBrushFunc(deviceRect, &s->brushData);
@@ -4311,7 +4310,7 @@ QClipData::QClipData(int height)
clipSpanHeight = height;
m_clipLines = 0;
- allocated = height;
+ allocated = 0;
m_spans = 0;
xmin = xmax = ymin = ymax = 0;
count = 0;
@@ -4333,7 +4332,9 @@ void QClipData::initialize()
if (m_spans)
return;
- m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
+ if (!m_clipLines)
+ m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
+
m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
allocated = clipSpanHeight;
@@ -4479,7 +4480,7 @@ void QClipData::fixup()
*/
void QClipData::setClipRect(const QRect &rect)
{
- if (rect == clipRect)
+ if (hasRectClip && rect == clipRect)
return;
// qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect;
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 28f92207e6..67a3fa9f0b 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -56,15 +56,15 @@ QT_BEGIN_NAMESPACE
*
*/
-const QRealRect &QVectorPath::controlPointRect() const
+QRectF QVectorPath::controlPointRect() const
{
if (m_hints & ControlPointRect)
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
if (m_count == 0) {
m_cp_rect.x1 = m_cp_rect.x2 = m_cp_rect.y1 = m_cp_rect.y2 = 0;
m_hints |= ControlPointRect;
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
}
Q_ASSERT(m_points && m_count > 0);
@@ -88,7 +88,7 @@ const QRealRect &QVectorPath::controlPointRect() const
}
m_hints |= ControlPointRect;
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
}
const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
@@ -100,9 +100,7 @@ const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
#ifndef QT_NO_DEBUG_STREAM
QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path)
{
- QRealRect vectorPathBounds = path.controlPointRect();
- QRectF rf(vectorPathBounds.x1, vectorPathBounds.y1,
- vectorPathBounds.x2 - vectorPathBounds.x1, vectorPathBounds.y2 - vectorPathBounds.y1);
+ QRectF rf = path.controlPointRect();
s << "QVectorPath(size:" << path.elementCount()
<< " hints:" << hex << path.hints()
<< rf << ')';
@@ -138,6 +136,75 @@ QPaintEngineExPrivate::~QPaintEngineExPrivate()
}
+void QPaintEngineExPrivate::replayClipOperations()
+{
+ Q_Q(QPaintEngineEx);
+
+ QPainter *p = q->painter();
+ if (!p || !p->d_ptr)
+ return;
+
+ QPainterPrivate *pp = p->d_ptr;
+ QList<QPainterClipInfo> clipInfo = pp->state->clipInfo;
+
+ QTransform transform = q->state()->matrix;
+
+ const QTransform &redirection = q->state()->redirectionMatrix;
+
+ for (int i = 0; i < clipInfo.size(); ++i) {
+ const QPainterClipInfo &info = clipInfo.at(i);
+
+ QTransform combined = info.matrix * redirection;
+
+ if (combined != q->state()->matrix) {
+ q->state()->matrix = combined;
+ q->transformChanged();
+ }
+
+ switch (info.clipType) {
+ case QPainterClipInfo::RegionClip:
+ q->clip(info.region, info.operation);
+ break;
+ case QPainterClipInfo::PathClip:
+ q->clip(info.path, info.operation);
+ break;
+ case QPainterClipInfo::RectClip:
+ q->clip(info.rect, info.operation);
+ break;
+ case QPainterClipInfo::RectFClip: {
+ qreal right = info.rectf.x() + info.rectf.width();
+ qreal bottom = info.rectf.y() + info.rectf.height();
+ qreal pts[] = { info.rectf.x(), info.rectf.y(),
+ right, info.rectf.y(),
+ right, bottom,
+ info.rectf.x(), bottom };
+ QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
+ q->clip(vp, info.operation);
+ break;
+ }
+ }
+ }
+
+ if (transform != q->state()->matrix) {
+ q->state()->matrix = transform;
+ q->transformChanged();
+ }
+}
+
+
+bool QPaintEngineExPrivate::hasClipOperations() const
+{
+ Q_Q(const QPaintEngineEx);
+
+ QPainter *p = q->painter();
+ if (!p || !p->d_ptr)
+ return false;
+
+ QPainterPrivate *pp = p->d_ptr;
+ QList<QPainterClipInfo> clipInfo = pp->state->clipInfo;
+
+ return !clipInfo.isEmpty();
+}
/*******************************************************************************
*
@@ -244,13 +311,18 @@ static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, q
((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement);
}
+QPaintEngineEx::QPaintEngineEx()
+ : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures)
+{
+ extended = true;
+}
+
QPaintEngineEx::QPaintEngineEx(QPaintEngineExPrivate &data)
: QPaintEngine(data, AllFeatures)
{
extended = true;
}
-
QPainterState *QPaintEngineEx::createState(QPainterState *orig) const
{
if (!orig)
@@ -483,6 +555,9 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op)
void QPaintEngineEx::clip(const QRegion &region, Qt::ClipOperation op)
{
+ if (region.numRects() == 1)
+ clip(region.boundingRect(), op);
+
QVector<QRect> rects = region.rects();
if (rects.size() <= 32) {
qreal pts[2*32*4];
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index 1c55242e49..3f64260416 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -139,27 +139,13 @@ public:
QDebug Q_GUI_EXPORT &operator<<(QDebug &, const QVectorPath &path);
#endif
-class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate
-{
-public:
- QPaintEngineExPrivate();
- ~QPaintEngineExPrivate();
-
- QStroker stroker;
- QDashStroker dasher;
- StrokeHandler *strokeHandler;
- QStrokerOps *activeStroker;
- QPen strokerPen;
-};
-
class QPixmapFilter;
class Q_GUI_EXPORT QPaintEngineEx : public QPaintEngine
{
Q_DECLARE_PRIVATE(QPaintEngineEx)
public:
- inline QPaintEngineEx()
- : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) { extended = true; }
+ QPaintEngineEx();
virtual QPainterState *createState(QPainterState *orig) const;
@@ -224,6 +210,22 @@ protected:
QPaintEngineEx(QPaintEngineExPrivate &data);
};
+class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QPaintEngineEx)
+public:
+ QPaintEngineExPrivate();
+ ~QPaintEngineExPrivate();
+
+ void replayClipOperations();
+ bool hasClipOperations() const;
+
+ QStroker stroker;
+ QDashStroker dasher;
+ StrokeHandler *strokeHandler;
+ QStrokerOps *activeStroker;
+ QPen strokerPen;
+};
inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) {
switch (mode) {
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 4744f14cb0..0ece4989cc 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -281,10 +281,14 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
// Update matrix.
- if (q->d_ptr->state->WxF)
- q->d_ptr->state->worldMatrix.translate(-offset.x(), -offset.y());
- else
- q->d_ptr->state->redirection_offset = offset;
+ if (q->d_ptr->state->WxF) {
+ q->d_ptr->state->redirectionMatrix *= q->d_ptr->state->worldMatrix;
+ q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
+ q->d_ptr->state->worldMatrix = QTransform();
+ q->d_ptr->state->WxF = false;
+ } else {
+ q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
+ }
q->d_ptr->updateMatrix();
QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
@@ -410,7 +414,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio
bool old_txinv = txinv;
QTransform old_invMatrix = invMatrix;
txinv = true;
- invMatrix = QTransform().translate(-state->redirection_offset.x(), -state->redirection_offset.y());
+ invMatrix = state->redirectionMatrix;
QPainterPath clipPath = q->clipPath();
QRectF r = clipPath.boundingRect().intersected(absPathRect);
absPathRect = r.toAlignedRect();
@@ -634,20 +638,7 @@ void QPainterPrivate::updateMatrix()
state->matrix *= viewTransform();
txinv = false; // no inverted matrix
- if (!state->redirection_offset.isNull()) {
- // We want to translate in dev space so we do the adding of the redirection
- // offset manually.
- if (state->matrix.isAffine()) {
- state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(),
- state->matrix.m21(), state->matrix.m22(),
- state->matrix.dx()-state->redirection_offset.x(),
- state->matrix.dy()-state->redirection_offset.y());
- } else {
- QTransform temp;
- temp.translate(-state->redirection_offset.x(), -state->redirection_offset.y());
- state->matrix *= temp;
- }
- }
+ state->matrix *= state->redirectionMatrix;
if (extended)
extended->transformChanged();
else
@@ -1572,10 +1563,8 @@ void QPainter::restore()
// replay the list of clip states,
for (int i=0; i<d->state->clipInfo.size(); ++i) {
const QPainterClipInfo &info = d->state->clipInfo.at(i);
- tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m13(),
- info.matrix.m21(), info.matrix.m22(), info.matrix.m23(),
- info.matrix.dx() - d->state->redirection_offset.x(),
- info.matrix.dy() - d->state->redirection_offset.y(), info.matrix.m33());
+ tmp->matrix = info.matrix;
+ tmp->matrix *= d->state->redirectionMatrix;
tmp->clipOperation = info.operation;
if (info.clipType == QPainterClipInfo::RectClip) {
tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
@@ -1689,7 +1678,7 @@ bool QPainter::begin(QPaintDevice *pd)
d->state->painter = this;
d->states.push_back(d->state);
- d->state->redirection_offset = redirectionOffset;
+ d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
d->state->brushOrigin = QPointF();
if (!d->engine) {
@@ -1723,7 +1712,8 @@ bool QPainter::begin(QPaintDevice *pd)
// Adjust offset for alien widgets painting outside the paint event.
if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
&& widget->testAttribute(Qt::WA_WState_Created)) {
- d->state->redirection_offset -= widget->mapTo(widget->nativeParentWidget(), QPoint());
+ const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
+ d->state->redirectionMatrix.translate(offset.x(), offset.y());
}
break;
}
@@ -1805,11 +1795,12 @@ bool QPainter::begin(QPaintDevice *pd)
d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
}
- d->state->redirection_offset += d->engine->coordinateOffset();
+ const QPoint coordinateOffset = d->engine->coordinateOffset();
+ d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
Q_ASSERT(d->engine->isActive());
- if (!d->state->redirection_offset.isNull())
+ if (!d->state->redirectionMatrix.isIdentity())
d->updateMatrix();
Q_ASSERT(d->engine->isActive());
@@ -7704,7 +7695,7 @@ QPainterState::QPainterState(const QPainterState *s)
clipRegion(s->clipRegion), clipPath(s->clipPath),
clipOperation(s->clipOperation),
renderHints(s->renderHints), clipInfo(s->clipInfo),
- worldMatrix(s->worldMatrix), matrix(s->matrix), redirection_offset(s->redirection_offset),
+ worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index f3df7a31bc..78cd713384 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -507,6 +507,7 @@ private:
friend class QFontEngineXLFD;
friend class QWSManager;
friend class QPaintEngine;
+ friend class QPaintEngineExPrivate;
friend class QOpenGLPaintEngine;
friend class QX11PaintEngine;
friend class QX11PaintEnginePrivate;
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 6c8821addf..8d4e6c5df8 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -158,7 +158,7 @@ public:
QList<QPainterClipInfo> clipInfo; // ### Make me smaller and faster to copy around...
QTransform worldMatrix; // World transformation matrix, not window and viewport
QTransform matrix; // Complete transformation matrix,
- QPoint redirection_offset;
+ QTransform redirectionMatrix;
int wx, wy, ww, wh; // window rectangle
int vx, vy, vw, vh; // viewport rectangle
qreal opacity;
diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp
index ba208fd6da..ce3389369b 100644
--- a/src/gui/painting/qprinter.cpp
+++ b/src/gui/painting/qprinter.cpp
@@ -1308,6 +1308,9 @@ void QPrinter::setNumCopies(int numCopies)
Returns true if collation is turned on when multiple copies is selected.
Returns false if it is turned off when multiple copies is selected.
+ When collating is turned off the printing of each individual page will be repeated
+ the numCopies() amount before the next page is started. With collating turned on
+ all pages are printed before the next copy of those pages is started.
\sa setCollateCopies()
*/
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index cb5be75b0a..689c091f3e 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -121,7 +121,7 @@ protected:
};
-class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache
+class QImageTextureGlyphCache : public QTextureGlyphCache
{
public:
QImageTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index 2602a3d1de..b073f8c80c 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -112,7 +112,7 @@ public:
{
}
- const QRealRect &controlPointRect() const;
+ QRectF controlPointRect() const;
inline Hint shape() const { return (Hint) (m_hints & ShapeHintMask); }
diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp
index b33dfc11e3..805cd05aba 100644
--- a/src/gui/styles/qcleanlooksstyle.cpp
+++ b/src/gui/styles/qcleanlooksstyle.cpp
@@ -3305,7 +3305,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
}
// Draw the focus rect
- if ((focus && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) {
+ if (focus && !comboBox->editable
+ && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) {
QStyleOptionFocusRect focus;
focus.rect = subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget)
.adjusted(0, 2, option->direction == Qt::RightToLeft ? 1 : -1, -2);
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index 1fe462704e..ab81d97a8c 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -1426,7 +1426,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QGtk::gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL);
int xt = interiorFocus ? gtkToggleButton->style->xthickness : 0;
int yt = interiorFocus ? gtkToggleButton->style->ythickness : 0;
- if ((focus && (option->state & State_KeyboardFocusChange)))
+ if (focus && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget)))
gtkCachedPainter.paintFocus(gtkToggleButton, "button",
option->rect.adjusted(xt, yt, -xt, -yt),
option->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index 01c0e44035..0a562135df 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -4568,7 +4568,8 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
// Draw the focus rect
- if (((option->state & State_HasFocus) && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) {
+ if ((option->state & State_HasFocus) && !comboBox->editable
+ && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) {
QStyleOptionFocusRect focus;
focus.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget)
.adjusted(-2, 0, 2, 0);
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 0494b72acd..a05e5a1696 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -57,46 +57,6 @@ QT_BEGIN_NAMESPACE
using namespace QCss;
-const char *Scanner::tokenName(QCss::TokenType t)
-{
- switch (t) {
- case NONE: return "NONE";
- case S: return "S";
- case CDO: return "CDO";
- case CDC: return "CDC";
- case INCLUDES: return "INCLUDES";
- case DASHMATCH: return "DASHMATCH";
- case LBRACE: return "LBRACE";
- case PLUS: return "PLUS";
- case GREATER: return "GREATER";
- case COMMA: return "COMMA";
- case STRING: return "STRING";
- case INVALID: return "INVALID";
- case IDENT: return "IDENT";
- case HASH: return "HASH";
- case ATKEYWORD_SYM: return "ATKEYWORD_SYM";
- case EXCLAMATION_SYM: return "EXCLAMATION_SYM";
- case LENGTH: return "LENGTH";
- case PERCENTAGE: return "PERCENTAGE";
- case NUMBER: return "NUMBER";
- case FUNCTION: return "FUNCTION";
- case COLON: return "COLON";
- case SEMICOLON: return "SEMICOLON";
- case RBRACE: return "RBRACE";
- case SLASH: return "SLASH";
- case MINUS: return "MINUS";
- case DOT: return "DOT";
- case STAR: return "STAR";
- case LBRACKET: return "LBRACKET";
- case RBRACKET: return "RBRACKET";
- case EQUAL: return "EQUAL";
- case LPAREN: return "LPAREN";
- case RPAREN: return "RPAREN";
- case OR: return "OR";
- }
- return "";
-}
-
struct QCssKnownValue
{
const char *name;
@@ -279,7 +239,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
};
//Map id to strings as they appears in the 'values' array above
-static const int indexOfId[NumKnownValues] = { 0, 40, 47, 41, 48, 53, 34, 26, 68, 69, 25, 42, 5, 62, 46,
+static const short indexOfId[NumKnownValues] = { 0, 40, 47, 41, 48, 53, 34, 26, 68, 69, 25, 42, 5, 62, 46,
29, 57, 58, 27, 50, 60, 6, 10, 38, 55, 19, 13, 17, 18, 20, 21, 49, 24, 45, 65, 36, 3, 2, 39, 61, 16,
11, 56, 14, 32, 63, 54, 64, 33, 67, 8, 28, 37, 12, 35, 59, 7, 9, 4, 66, 52, 22, 23, 30, 31, 1, 15, 0,
51, 44, 43 };
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index 72bd637572..81f306d3c5 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -731,7 +731,6 @@ class Q_AUTOTEST_EXPORT Scanner
public:
static QString preprocess(const QString &input, bool *hasEscapeSequences = 0);
static void scan(const QString &preprocessedInput, QVector<Symbol> *symbols);
- static const char *tokenName(TokenType t);
};
class Q_GUI_EXPORT Parser
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 6e8adcf263..79e341afee 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -70,12 +70,6 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
}
}
-
-
-QFontEngineGlyphCache::~QFontEngineGlyphCache()
-{
-}
-
// Harfbuzz helper functions
static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 0f8d81ced1..3ef9d5fcc8 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -93,7 +93,6 @@ struct QGlyphLayout;
class Q_GUI_EXPORT QFontEngine : public QObject
{
- Q_OBJECT
public:
enum Type {
Box,
diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h
index 8589cc68de..ca67e3ff4f 100644
--- a/src/gui/text/qfontengineglyphcache_p.h
+++ b/src/gui/text/qfontengineglyphcache_p.h
@@ -72,7 +72,7 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QFontEngineGlyphCache
+class QFontEngineGlyphCache
{
public:
QFontEngineGlyphCache(const QTransform &matrix) : m_transform(matrix) { }
@@ -83,7 +83,7 @@ public:
Raster_Mono
};
- virtual ~QFontEngineGlyphCache();
+ virtual ~QFontEngineGlyphCache() { }
QTransform m_transform;
};
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 0958b52142..780891be28 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -394,7 +394,7 @@ void QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QText
Q_Q(QTextControl);
setContent(format, text, document);
- QWidget *parentWidget = qobject_cast<QWidget*>(q->parent());
+ QWidget *parentWidget = qobject_cast<QWidget*>(parent);
if (parentWidget) {
QTextOption opt = doc->defaultTextOption();
opt.setTextDirection(parentWidget->layoutDirection());
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index ee743dc7ec..76c59c3fe5 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -343,7 +343,7 @@ static QChar resolveEntity(const QString &entity)
return e->code;
}
-static const uint windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
+static const ushort windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
0x20ac, // 0x80
0x0081, // 0x81 direct mapping
0x201a, // 0x82
diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp
index 9f8efb4008..a8aa11cb03 100644
--- a/src/gui/util/qdesktopservices_win.cpp
+++ b/src/gui/util/qdesktopservices_win.cpp
@@ -165,6 +165,9 @@ static bool launchWebBrowser(const QUrl &url)
if (!url.isValid())
return false;
+ if (url.scheme().isEmpty())
+ return openDocument(url);
+
quintptr returnValue;
returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *) QString::fromUtf8(url.toEncoded().constData()).utf16(),
0, 0, SW_SHOWNORMAL);
diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp
index 1900016bc7..f28288e71a 100644
--- a/src/gui/widgets/qabstractbutton.cpp
+++ b/src/gui/widgets/qabstractbutton.cpp
@@ -319,20 +319,16 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
return group->d_func()->buttonList;
#endif
- Q_Q(const QAbstractButton);
- QList<QAbstractButton*>candidates;
- if (q->parentWidget()) {
- candidates = qFindChildren<QAbstractButton *>(q->parentWidget());
- if (autoExclusive) {
- for (int i = candidates.count() - 1; i >= 0; --i) {
- QAbstractButton *candidate = candidates.at(i);
- if (!candidate->autoExclusive()
+ QList<QAbstractButton*>candidates = qFindChildren<QAbstractButton *>(parent);
+ if (autoExclusive) {
+ for (int i = candidates.count() - 1; i >= 0; --i) {
+ QAbstractButton *candidate = candidates.at(i);
+ if (!candidate->autoExclusive()
#ifndef QT_NO_BUTTONGROUP
- || candidate->group()
+ || candidate->group()
#endif
- )
- candidates.removeAt(i);
- }
+ )
+ candidates.removeAt(i);
}
}
return candidates;
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index 4f0ec1e2ec..58e8f9c259 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -2202,8 +2202,8 @@ QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- foreach (QWidget *sepWidget, separatorWidgets)
- result << sepWidget;
+ for (int i = 0; i < separatorWidgets.count(); ++i)
+ result << separatorWidgets.at(i);
for (int i = 0; i < item_list.count(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
@@ -3244,8 +3244,8 @@ QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- foreach (QWidget *sepWidget, separatorWidgets)
- result << sepWidget;
+ for (int i = 0; i < separatorWidgets.count(); ++i)
+ result << separatorWidgets.at(i);
for (int i = 0; i < QInternal::DockCount; ++i) {
const QDockAreaLayoutInfo &dock = docks[i];
result += dock.usedSeparatorWidgets();
diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp
index d573b8b1ba..6a0c8798f2 100644
--- a/src/gui/widgets/qdockwidget.cpp
+++ b/src/gui/widgets/qdockwidget.cpp
@@ -221,7 +221,8 @@ void QDockWidgetLayout::addItem(QLayoutItem*)
QLayoutItem *QDockWidgetLayout::itemAt(int index) const
{
int cnt = 0;
- foreach (QLayoutItem *item, item_list) {
+ for (int i = 0; i < item_list.count(); ++i) {
+ QLayoutItem *item = item_list.at(i);
if (item == 0)
continue;
if (index == cnt++)
@@ -250,8 +251,8 @@ QLayoutItem *QDockWidgetLayout::takeAt(int index)
int QDockWidgetLayout::count() const
{
int result = 0;
- foreach (QLayoutItem *item, item_list) {
- if (item != 0)
+ for (int i = 0; i < item_list.count(); ++i) {
+ if (item_list.at(i))
++result;
}
return result;
diff --git a/src/gui/widgets/qmdiarea.cpp b/src/gui/widgets/qmdiarea.cpp
index 6acd9771f3..0235c04458 100644
--- a/src/gui/widgets/qmdiarea.cpp
+++ b/src/gui/widgets/qmdiarea.cpp
@@ -800,12 +800,12 @@ void QMdiAreaPrivate::appendChild(QMdiSubWindow *child)
Q_Q(QMdiArea);
Q_ASSERT(child && childWindows.indexOf(child) == -1);
- if (child->parent() != q->viewport())
- child->setParent(q->viewport(), child->windowFlags());
+ if (child->parent() != viewport)
+ child->setParent(viewport, child->windowFlags());
childWindows.append(QPointer<QMdiSubWindow>(child));
if (!child->testAttribute(Qt::WA_Resized) && q->isVisible()) {
- QSize newSize(child->sizeHint().boundedTo(q->viewport()->size()));
+ QSize newSize(child->sizeHint().boundedTo(viewport->size()));
child->resize(newSize.expandedTo(qSmartMinSize(child)));
}
@@ -931,7 +931,7 @@ void QMdiAreaPrivate::rearrange(Rearranger *rearranger)
widgets.move(indexToActive, 0);
}
- QRect domain = q->viewport()->rect();
+ QRect domain = viewport->rect();
if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty())
domain = resizeToMinimumTileSize(minSubWindowSize, widgets.count());
@@ -1236,7 +1236,7 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
{
Q_Q(QMdiArea);
if (!minSubWindowSize.isValid() || subWindowCount <= 0)
- return q->viewport()->rect();
+ return viewport->rect();
// Calculate minimum size.
const int columns = qMax(qCeil(qSqrt(qreal(subWindowCount))), 1);
@@ -1255,10 +1255,10 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
// We don't want sub-subwindows to be placed at the edge, thus add 2 pixels.
int minAreaWidth = minWidth + left + right + 2;
int minAreaHeight = minHeight + top + bottom + 2;
- if (q->horizontalScrollBar()->isVisible())
- minAreaHeight += q->horizontalScrollBar()->height();
- if (q->verticalScrollBar()->isVisible())
- minAreaWidth += q->verticalScrollBar()->width();
+ if (hbar->isVisible())
+ minAreaHeight += hbar->height();
+ if (vbar->isVisible())
+ minAreaWidth += vbar->width();
if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q)) {
const int frame = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, q);
minAreaWidth += 2 * frame;
@@ -1268,23 +1268,23 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
topLevel->resize(topLevel->size() + diff);
}
- QRect domain = q->viewport()->rect();
+ QRect domain = viewport->rect();
// Adjust domain width and provide horizontal scroll bar.
if (domain.width() < minWidth) {
domain.setWidth(minWidth);
- if (q->horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
+ if (hbarpolicy == Qt::ScrollBarAlwaysOff)
q->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- else if (q->horizontalScrollBar()->value() != 0)
- q->horizontalScrollBar()->setValue(0);
+ else
+ hbar->setValue(0);
}
// Adjust domain height and provide vertical scroll bar.
if (domain.height() < minHeight) {
domain.setHeight(minHeight);
- if (q->verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
+ if (vbarpolicy == Qt::ScrollBarAlwaysOff)
q->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- else if (q->verticalScrollBar()->value() != 0)
- q->verticalScrollBar()->setValue(0);
+ else
+ vbar->setValue(0);
}
return domain;
}
diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp
index 56df8ea758..b366c28371 100644
--- a/src/gui/widgets/qmdisubwindow.cpp
+++ b/src/gui/widgets/qmdisubwindow.cpp
@@ -1115,7 +1115,7 @@ void QMdiSubWindowPrivate::updateDirtyRegions()
void QMdiSubWindowPrivate::updateGeometryConstraints()
{
Q_Q(QMdiSubWindow);
- if (!q->parent())
+ if (!parent)
return;
internalMinimumSize = (!q->isMinimized() && !q->minimumSize().isNull())
@@ -1145,7 +1145,7 @@ void QMdiSubWindowPrivate::updateMask()
if (!q->mask().isEmpty())
q->clearMask();
- if (!q->parent())
+ if (!parent)
return;
if ((q->isMaximized() && !drawTitleBarWhenMaximized())
@@ -1168,7 +1168,7 @@ void QMdiSubWindowPrivate::setNewGeometry(const QPoint &pos)
{
Q_Q(QMdiSubWindow);
Q_ASSERT(currentOperation != None);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
uint cflags = operationMap.find(currentOperation).value().changeFlags;
int posX = pos.x();
@@ -1235,7 +1235,7 @@ void QMdiSubWindowPrivate::setNewGeometry(const QPoint &pos)
void QMdiSubWindowPrivate::setMinimizeMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
ensureWindowState(Qt::WindowMinimized);
isShadeRequestFromMinimizeMode = true;
@@ -1263,7 +1263,7 @@ void QMdiSubWindowPrivate::setMinimizeMode()
void QMdiSubWindowPrivate::setNormalMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
isShadeMode = false;
isMaximizeMode = false;
@@ -1334,7 +1334,7 @@ void QMdiSubWindowPrivate::setNormalMode()
void QMdiSubWindowPrivate::setMaximizeMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
ensureWindowState(Qt::WindowMaximized);
isShadeMode = false;
@@ -1423,7 +1423,7 @@ void QMdiSubWindowPrivate::setMaximizeMode()
void QMdiSubWindowPrivate::setActive(bool activate, bool changeFocus)
{
Q_Q(QMdiSubWindow);
- if (!q->parent() || !activationEnabled)
+ if (!parent || !activationEnabled)
return;
if (activate && !isActive && q->isEnabled()) {
@@ -1711,7 +1711,7 @@ void QMdiSubWindowPrivate::ensureWindowState(Qt::WindowState state)
int QMdiSubWindowPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint
|| (q->isMaximized() && !drawTitleBarWhenMaximized())) {
return 0;
}
@@ -1734,7 +1734,7 @@ void QMdiSubWindowPrivate::sizeParameters(int *margin, int *minWidth) const
{
Q_Q(const QMdiSubWindow);
Qt::WindowFlags flags = q->windowFlags();
- if (!q->parent() || flags & Qt::FramelessWindowHint) {
+ if (!parent || flags & Qt::FramelessWindowHint) {
*margin = 0;
*minWidth = 0;
return;
@@ -1893,7 +1893,7 @@ void QMdiSubWindowPrivate::enterRubberBandMode()
if (q->isMaximized())
return;
Q_ASSERT(oldGeometry.isValid());
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
if (!rubberBand) {
rubberBand = new QRubberBand(QRubberBand::Rectangle, q->parentWidget());
// For accessibility to identify this special widget.
@@ -2079,7 +2079,7 @@ void QMdiSubWindowPrivate::restoreFocus()
void QMdiSubWindowPrivate::setWindowFlags(Qt::WindowFlags windowFlags)
{
Q_Q(QMdiSubWindow);
- if (!q->parent()) {
+ if (!parent) {
q->setWindowFlags(windowFlags);
return;
}
@@ -2164,7 +2164,7 @@ void QMdiSubWindowPrivate::addToSystemMenu(WindowStateAction action, const QStri
QSize QMdiSubWindowPrivate::iconSize() const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint)
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint)
return QSize(-1, -1);
return QSize(q->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, 0, q), titleBarHeight());
}
diff --git a/src/gui/widgets/qmdisubwindow_p.h b/src/gui/widgets/qmdisubwindow_p.h
index 2e672d6a1e..394f11c6a8 100644
--- a/src/gui/widgets/qmdisubwindow_p.h
+++ b/src/gui/widgets/qmdisubwindow_p.h
@@ -287,7 +287,7 @@ public:
inline int titleBarHeight() const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint
|| (q->isMaximized() && !drawTitleBarWhenMaximized())) {
return 0;
}
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index cffc3d5eff..fc7e901864 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -220,7 +220,8 @@ void QMenuBarPrivate::updateGeometries()
//we try to see if the actions will fit there
bool hasHiddenActions = false;
- foreach(QAction *action, actionList) {
+ for (int i = 0; i < actionList.count(); ++i) {
+ QAction *action = actionList.at(i);
if (!menuRect.contains(actionRect(action))) {
hasHiddenActions = true;
break;
@@ -230,7 +231,8 @@ void QMenuBarPrivate::updateGeometries()
//...and if not, determine the ones that fit on the menu with the extension visible
if (hasHiddenActions) {
menuRect = this->menuRect(true);
- foreach(QAction *action, actionList) {
+ for (int i = 0; i < actionList.count(); ++i) {
+ QAction *action = actionList.at(i);
if (!menuRect.contains(actionRect(action))) {
hiddenActions.append(action);
}
diff --git a/src/gui/widgets/qtoolbarlayout.cpp b/src/gui/widgets/qtoolbarlayout.cpp
index 0bfa493746..0af2b6592a 100644
--- a/src/gui/widgets/qtoolbarlayout.cpp
+++ b/src/gui/widgets/qtoolbarlayout.cpp
@@ -128,7 +128,7 @@ void QToolBarLayout::setUsePopupMenu(bool set)
invalidate();
if (!set) {
QObject::connect(extension, SIGNAL(clicked(bool)),
- this, SLOT(setExpanded(bool)));
+ this, SLOT(setExpanded(bool)), Qt::UniqueConnection);
extension->setPopupMode(QToolButton::DelayedPopup);
extension->setMenu(0);
delete popupMenu;
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
index ea57fdfb4b..5c541d0da5 100644
--- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -157,6 +157,7 @@ QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
simpleShaderProg->addShader(compiledShaders[PositionOnlyVertexShader]);
simpleShaderProg->addShader(compiledShaders[MainFragmentShader]);
simpleShaderProg->addShader(compiledShaders[ShockingPinkSrcFragmentShader]);
+ simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
simpleShaderProg->link();
if (!simpleShaderProg->isLinked()) {
qCritical() << "Errors linking simple shader:"
@@ -444,7 +445,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg()
requiredProgram.program->addShader(requiredProgram.compositionFragShader);
// We have to bind the vertex attribute names before the program is linked:
- requiredProgram.program->bindAttributeLocation("inputVertex", QT_VERTEX_COORDS_ATTR);
+ requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
if (useTextureCoords)
requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
index 920d0bcc1a..70cc67efc4 100644
--- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -84,16 +84,20 @@ static const char* const qglslMainWithTexCoordsVertexShader = "\
static const char* const qglslPositionOnlyVertexShader = "\
attribute highp vec4 vertexCoordsArray;\
uniform highp mat4 pmvMatrix;\
+ uniform highp float depth;\
void setPosition(void)\
{\
gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.z = depth;\
}";
static const char* const qglslUntransformedPositionVertexShader = "\
attribute highp vec4 vertexCoordsArray;\
+ uniform highp float depth;\
void setPosition(void)\
{\
gl_Position = vertexCoordsArray;\
+ gl_Position.z = depth;\
}";
// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
@@ -104,9 +108,11 @@ static const char* const qglslPositionWithPatternBrushVertexShader = "\
uniform mediump vec2 invertedTextureSize; \
uniform mediump mat3 brushTransform; \
varying mediump vec2 patternTexCoords; \
+ uniform highp float depth;\
void setPosition(void) { \
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth;\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -136,9 +142,11 @@ static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\
uniform highp vec3 linearData; \
uniform highp mat3 brushTransform; \
varying mediump float index ; \
+ uniform highp float depth;\
void setPosition() { \
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth;\
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -166,10 +174,12 @@ static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\
uniform mediump vec2 halfViewportSize; \
uniform highp mat3 brushTransform; \
varying highp vec2 A; \
+ uniform highp float depth;\
void setPosition(void)\
{\
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth; \
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -205,10 +215,12 @@ static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\
uniform highp vec2 fmp; \
varying highp float b; \
varying highp vec2 A; \
+ uniform highp float depth;\
void setPosition(void) \
{\
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth; \
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
@@ -242,9 +254,11 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\
uniform mediump vec2 invertedTextureSize; \
uniform mediump mat3 brushTransform; \
varying mediump vec2 brushTextureCoords; \
+ uniform highp float depth;\
void setPosition(void) { \
gl_Position = pmvMatrix * vertexCoordsArray;\
gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth; \
mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 868adcf525..bdea187021 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -183,8 +183,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
pex->transferMode(BrushDrawingMode);
- glDisable(GL_SCISSOR_TEST);
glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, oldWidth, oldHeight);
@@ -217,7 +217,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
glViewport(0, 0, pex->width, pex->height);
- pex->updateDepthClip();
+ pex->updateDepthScissorTest();
}
void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
@@ -297,6 +297,11 @@ void QGL2PaintEngineExPrivate::useSimpleShader()
shaderManager->simpleProgram()->setUniformValue("pmvMatrix", pmvMatrix);
simpleShaderMatrixUniformDirty = false;
}
+
+ if (simpleShaderDepthUniformDirty) {
+ shaderManager->simpleProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth);
+ simpleShaderDepthUniformDirty = false;
+ }
}
@@ -709,6 +714,7 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
if (path.shape() == QVectorPath::RectangleHint) {
QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y());
prepareForDraw(currentBrush->isOpaque());
+
composite(rect);
}
else if (path.shape() == QVectorPath::EllipseHint) {
@@ -726,12 +732,14 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
// Stencil the brush onto the dest buffer
glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
glEnable(GL_STENCIL_TEST);
prepareForDraw(currentBrush->isOpaque());
composite(vertexCoordinateArray.boundingRect());
glDisable(GL_STENCIL_TEST);
- cleanStencilBuffer(vertexCoordinateArray.boundingRect());
+ glStencilMask(0);
}
}
@@ -739,17 +747,17 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill)
{
// qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()");
- if (stencilBuferDirty) {
+ glStencilMask(0xFFFF); // Enable stencil writes
+
+ if (stencilBufferDirty) {
// Clear the stencil buffer to zeros
glDisable(GL_STENCIL_TEST);
- glStencilMask(0xFFFF); // Enable writing to stencil buffer, otherwise glClear wont do anything.
glClearStencil(0); // Clear to zero
glClear(GL_STENCIL_BUFFER_BIT);
- stencilBuferDirty = false;
+ stencilBufferDirty = false;
}
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
- glStencilMask(0xFFFF); // Enable stencil writes
glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test
// Setup the stencil op:
@@ -759,7 +767,7 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve
} else
glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
- // No point in using a fancy gradiant shader for writing into the stencil buffer!
+ // No point in using a fancy gradient shader for writing into the stencil buffer!
useSimpleShader();
glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d
@@ -770,41 +778,6 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve
// Enable color writes & disable stencil writes
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilMask(0);
-}
-
-void QGL2PaintEngineExPrivate::cleanStencilBuffer(const QGLRect& area)
-{
-// qDebug("QGL2PaintEngineExPrivate::cleanStencilBuffer()");
- useSimpleShader();
-
- GLfloat rectVerts[] = {
- area.left, area.top,
- area.left, area.bottom,
- area.right, area.bottom,
- area.right, area.top
- };
-
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, rectVerts);
-
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
- glStencilMask(0xFFFF); // Enable writing to stencil buffer
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // Write 0's to stencil buffer
-
- glDisable(GL_BLEND);
-
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
-
- // Enable color writes & disable stencil writes
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilMask(0);
- glDisable(GL_STENCIL_TEST);
}
void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
@@ -843,6 +816,7 @@ void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
// The shader program has changed so mark all uniforms as dirty:
brushUniformsDirty = true;
shaderMatrixUniformDirty = true;
+ depthUniformDirty = true;
}
if (brushUniformsDirty && mode != ImageDrawingMode)
@@ -853,6 +827,11 @@ void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
shaderMatrixUniformDirty = false;
}
+ if (depthUniformDirty) {
+ shaderManager->currentProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth);
+ depthUniformDirty = false;
+ }
+
if (useGlobalOpacityUniform)
shaderManager->currentProgram()->setUniformValue("globalOpacity", (GLfloat)q->state()->opacity);
}
@@ -1062,7 +1041,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte
matrix.translate(p.x(), p.y());
ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-
QFontEngineGlyphCache::Type glyphType = ti.fontEngine->glyphFormat >= 0
? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat)
: QFontEngineGlyphCache::Raster_A8;
@@ -1146,6 +1124,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
}
d->ctx->d_ptr->active_engine = this;
+ d->last_created_state = 0;
d->drawable.makeCurrent();
QSize sz = d->drawable.size();
@@ -1172,12 +1151,16 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->brushUniformsDirty = true;
d->matrixDirty = true;
d->compositionModeDirty = true;
- d->stencilBuferDirty = true;
+ d->stencilBufferDirty = true;
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
d->use_system_clip = !systemClip().isEmpty();
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glDepthMask(false);
QGLPixmapData *source = d->drawable.copyOnBegin();
if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) {
@@ -1201,7 +1184,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->drawTexture(QRectF(rect), QRectF(rect), rect.size(), true);
}
- updateClipRegion(QRegion(), Qt::NoClip);
+ d->systemStateChanged();
return true;
}
@@ -1245,260 +1228,297 @@ void QGL2PaintEngineEx::ensureActive()
ctx->d_ptr->active_engine = this;
glDisable(GL_DEPTH_TEST);
- glDisable(GL_SCISSOR_TEST);
glViewport(0, 0, d->width, d->height);
+
setState(state());
- d->updateDepthClip();
}
}
+void QGL2PaintEngineExPrivate::updateDepthScissorTest()
+{
+ Q_Q(QGL2PaintEngineEx);
+ if (q->state()->depthTestEnabled)
+ glEnable(GL_DEPTH_TEST);
+ else
+ glDisable(GL_DEPTH_TEST);
-/////////////////////////////////// State/Clipping stolen from QOpenGLPaintEngine //////////////////////////////////////////
+ if (q->state()->scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+ else
+ glDisable(GL_SCISSOR_TEST);
+}
void QGL2PaintEngineEx::clipEnabledChanged()
{
Q_D(QGL2PaintEngineEx);
- d->updateDepthClip();
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
+
+ if (painter()->hasClipping()) {
+ d->regenerateDepthClip();
+ } else {
+ if (d->use_system_clip) {
+ state()->currentDepth = -0.5f;
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ state()->depthTestEnabled = false;
+ }
+ }
}
-void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
+void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, float depth)
{
-// qDebug("QGL2PaintEngineEx::clip()");
- const qreal *points = path.points();
- const QPainterPath::ElementType *types = path.elements();
- if (!types && path.shape() == QVectorPath::RectangleHint) {
- QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
- updateClipRegion(QRegion(r.toRect()), op);
- return;
- }
+ transferMode(BrushDrawingMode);
- QPainterPath p;
- if (types) {
- int id = 0;
- for (int i=0; i<path.elementCount(); ++i) {
- switch(types[i]) {
- case QPainterPath::MoveToElement:
- p.moveTo(QPointF(points[id], points[id+1]));
- id+=2;
- break;
- case QPainterPath::LineToElement:
- p.lineTo(QPointF(points[id], points[id+1]));
- id+=2;
- break;
- case QPainterPath::CurveToElement: {
- QPointF p1(points[id], points[id+1]);
- QPointF p2(points[id+2], points[id+3]);
- QPointF p3(points[id+4], points[id+5]);
- p.cubicTo(p1, p2, p3);
- id+=6;
- break;
- }
- case QPainterPath::CurveToDataElement:
- ;
- break;
- }
- }
- } else if (!path.isEmpty()) {
- p.moveTo(QPointF(points[0], points[1]));
- int id = 2;
- for (int i=1; i<path.elementCount(); ++i) {
- p.lineTo(QPointF(points[id], points[id+1]));
- id+=2;
- }
+ if (matrixDirty)
+ updateMatrix();
+
+ if (q->state()->needsDepthBufferClear) {
+ glDepthMask(true);
+ glClearDepth(0.5);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ q->state()->needsDepthBufferClear = false;
+ glDepthMask(false);
}
- if (path.hints() & QVectorPath::WindingFill)
- p.setFillRule(Qt::WindingFill);
- updateClipRegion(QRegion(p.toFillPolygon().toPolygon(), p.fillRule()), op);
- return;
+ if (path.isEmpty())
+ return;
+
+ glDisable(GL_BLEND);
+ glDepthMask(false);
+
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
+
+ glDepthMask(GL_FALSE);
+ fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
+
+ // Stencil the clip onto the clip buffer
+ glColorMask(false, false, false, false);
+ glDepthMask(true);
+
+ shaderManager->simpleProgram()->setUniformValue("depth", depth);
+ simpleShaderDepthUniformDirty = true;
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+
+ glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+ glEnable(GL_STENCIL_TEST);
+ composite(vertexCoordinateArray.boundingRect());
+ glDisable(GL_STENCIL_TEST);
+
+ glStencilMask(0);
+
+ glColorMask(true, true, true, true);
+ glDepthMask(false);
}
-void QGL2PaintEngineEx::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op)
+void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
{
-// qDebug("QGL2PaintEngineEx::updateClipRegion()");
+// qDebug("QGL2PaintEngineEx::clip()");
Q_D(QGL2PaintEngineEx);
- QRegion sysClip = systemClip();
- if (op == Qt::NoClip && !d->use_system_clip) {
- state()->hasClipping = false;
- state()->clipRegion = QRegion();
- d->updateDepthClip();
- return;
- }
+ if (op == Qt::ReplaceClip && !d->hasClipOperations())
+ op = Qt::IntersectClip;
- bool isScreenClip = false;
- if (!d->use_system_clip) {
- QVector<QRect> untransformedRects = clipRegion.rects();
+ if (!path.isEmpty() && op == Qt::IntersectClip && (path.hints() & QVectorPath::RectangleHint)) {
+ const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
+ QRectF rect(points[0], points[2]);
- if (untransformedRects.size() == 1) {
- QPainterPath path;
- path.addRect(untransformedRects[0]);
- //path = d->matrix.map(path);
- path = state()->matrix.map(path);
-
-// if (path.contains(QRectF(QPointF(), d->drawable.size())))
-// isScreenClip = true;
- if (path.contains(QRectF(0.0, 0.0, d->width, d->height)))
- isScreenClip = true;
+ if (state()->matrix.type() <= QTransform::TxScale) {
+ rect = state()->matrix.mapRect(rect);
+
+ if (d->use_system_clip && rect.contains(d->systemClip.boundingRect())
+ || rect.contains(QRect(0, 0, d->width, d->height)))
+ return;
}
}
-// QRegion region = isScreenClip ? QRegion() : clipRegion * d->matrix;
- QRegion region = isScreenClip ? QRegion() : clipRegion * state()->matrix;
switch (op) {
case Qt::NoClip:
- if (!d->use_system_clip)
- break;
- state()->clipRegion = sysClip;
+ if (d->use_system_clip) {
+ glEnable(GL_DEPTH_TEST);
+ state()->depthTestEnabled = true;
+ state()->currentDepth = -0.5;
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ state()->depthTestEnabled = false;
+ }
+ state()->canRestoreClip = false;
break;
case Qt::IntersectClip:
- if (isScreenClip)
- return;
- if (state()->hasClipping) {
- state()->clipRegion &= region;
- break;
- }
- // fall through
+ state()->maxDepth = (1.0f + state()->maxDepth) * 0.5;
+ d->writeClip(path, state()->maxDepth);
+ state()->currentDepth = 1.5 * state()->maxDepth - 0.5f;
+ state()->depthTestEnabled = true;
+ break;
case Qt::ReplaceClip:
- if (d->use_system_clip && !sysClip.isEmpty())
- state()->clipRegion = region & sysClip;
- else
- state()->clipRegion = region;
+ d->systemStateChanged();
+ state()->maxDepth = 0.5f;
+ glDepthFunc(GL_ALWAYS);
+ d->writeClip(path, state()->maxDepth);
+ state()->currentDepth = 0.25f;
+ state()->canRestoreClip = false;
+ state()->depthTestEnabled = true;
break;
case Qt::UniteClip:
- state()->clipRegion |= region;
- if (d->use_system_clip && !sysClip.isEmpty())
- state()->clipRegion &= sysClip;
- break;
- default:
+ glDepthFunc(GL_ALWAYS);
+ d->writeClip(path, state()->maxDepth);
+ state()->canRestoreClip = false;
+ state()->depthTestEnabled = true;
break;
}
- if (isScreenClip) {
- state()->hasClipping = false;
- state()->clipRegion = QRegion();
- } else {
- state()->hasClipping = op != Qt::NoClip || d->use_system_clip;
+ glDepthFunc(GL_LEQUAL);
+ if (state()->depthTestEnabled) {
+ glEnable(GL_DEPTH_TEST);
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
}
-
- d->updateDepthClip();
}
-void QGL2PaintEngineExPrivate::systemStateChanged()
+void QGL2PaintEngineExPrivate::regenerateDepthClip()
{
- Q_Q(QGL2PaintEngineEx);
- use_system_clip = !systemClip.isEmpty();
-
- if (q->painter()->hasClipping())
- q->updateClipRegion(q->painter()->clipRegion(), Qt::ReplaceClip);
- else
- q->updateClipRegion(QRegion(), Qt::NoClip);
+ systemStateChanged();
+ replayClipOperations();
}
-void QGL2PaintEngineExPrivate::updateDepthClip()
+void QGL2PaintEngineExPrivate::systemStateChanged()
{
-// qDebug("QGL2PaintEngineExPrivate::updateDepthClip()");
-
Q_Q(QGL2PaintEngineEx);
+ use_system_clip = !systemClip.isEmpty();
- q->ensureActive();
glDisable(GL_DEPTH_TEST);
+ q->state()->depthTestEnabled = false;
+ q->state()->scissorTestEnabled = false;
+ q->state()->needsDepthBufferClear = true;
+
glDisable(GL_SCISSOR_TEST);
- if (!q->state()->hasClipping)
- return;
+ q->state()->currentDepth = -0.5f;
+ q->state()->maxDepth = 0.5f;
- const QVector<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects();
- if (rects.size() == 1) {
- QRect fastClip = rects.at(0);
+ if (use_system_clip) {
+ QRect bounds = systemClip.boundingRect();
+ if (systemClip.numRects() == 1
+ && bounds == QRect(0, 0, width, height))
+ {
+ q->state()->needsDepthBufferClear = true;
+ } else {
+ glEnable(GL_SCISSOR_TEST);
- glEnable(GL_SCISSOR_TEST);
+ const int left = bounds.left();
+ const int width = bounds.width();
+ const int bottom = height - (bounds.top() + bounds.height());
+ const int height = bounds.height();
- const int left = fastClip.left();
- const int width = fastClip.width();
- const int bottom = height - (fastClip.bottom() + 1);
- const int height = fastClip.height();
+ glScissor(left, bottom, width, height);
- glScissor(left, bottom, width, height);
- return;
- }
+ QTransform transform = q->state()->matrix;
+ q->state()->matrix = QTransform();
+ q->transformChanged();
- glClearDepth(0x0);
- glDepthMask(true);
- glClear(GL_DEPTH_BUFFER_BIT);
- glClearDepth(0x1);
+ q->state()->needsDepthBufferClear = false;
- glEnable(GL_SCISSOR_TEST);
- for (int i = 0; i < rects.size(); ++i) {
- QRect rect = rects.at(i);
+ glDepthMask(true);
- const int left = rect.left();
- const int width = rect.width();
- const int bottom = height - (rect.bottom() + 1);
- const int height = rect.height();
+ glClearDepth(0);
+ glClear(GL_DEPTH_BUFFER_BIT);
- glScissor(left, bottom, width, height);
+ QPainterPath path;
+ path.addRegion(systemClip);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- glDisable(GL_SCISSOR_TEST);
+ glDepthFunc(GL_ALWAYS);
+ writeClip(qtVectorPathForPath(path), 0.0f);
+ glDepthFunc(GL_LEQUAL);
- glDepthMask(false);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_DEPTH_TEST);
-}
+ glEnable(GL_DEPTH_TEST);
+ q->state()->depthTestEnabled = true;
+ q->state()->scissorTestEnabled = true;
+ q->state()->matrix = transform;
+ q->transformChanged();
+ }
+ q->state()->currentDepth = -0.5f;
+ simpleShaderDepthUniformDirty = true;
+ depthUniformDirty = true;
+ }
+}
void QGL2PaintEngineEx::setState(QPainterState *new_state)
{
-// qDebug("QGL2PaintEngineEx::setState()");
+ // qDebug("QGL2PaintEngineEx::setState()");
Q_D(QGL2PaintEngineEx);
QOpenGL2PaintEngineState *s = static_cast<QOpenGL2PaintEngineState *>(new_state);
-
QOpenGL2PaintEngineState *old_state = state();
- const bool needsDepthClipUpdate = !old_state
- || s->clipEnabled != old_state->clipEnabled
- || (s->clipEnabled && s->clipRegion != old_state->clipRegion);
QPaintEngineEx::setState(s);
- if (needsDepthClipUpdate)
- d->updateDepthClip();
+ if (s == d->last_created_state) {
+ d->last_created_state = 0;
+ return;
+ }
d->matrixDirty = true;
d->compositionModeDirty = true;
d->brushTextureDirty = true;
d->brushUniformsDirty = true;
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
d->simpleShaderMatrixUniformDirty = true;
d->shaderMatrixUniformDirty = true;
+
+ if (old_state && old_state != s && old_state->canRestoreClip) {
+ d->updateDepthScissorTest();
+ glDepthMask(false);
+ glDepthFunc(GL_LEQUAL);
+ s->maxDepth = old_state->maxDepth;
+ } else {
+ d->regenerateDepthClip();
+ }
}
QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
{
+ Q_D(const QGL2PaintEngineEx);
+
QOpenGL2PaintEngineState *s;
if (!orig)
s = new QOpenGL2PaintEngineState();
else
s = new QOpenGL2PaintEngineState(*static_cast<QOpenGL2PaintEngineState *>(orig));
+ d->last_created_state = s;
return s;
}
QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other)
: QPainterState(other)
{
- clipRegion = other.clipRegion;
- hasClipping = other.hasClipping;
+ needsDepthBufferClear = other.needsDepthBufferClear;
+ depthTestEnabled = other.depthTestEnabled;
+ scissorTestEnabled = other.scissorTestEnabled;
+ currentDepth = other.currentDepth;
+ maxDepth = other.maxDepth;
+ canRestoreClip = other.canRestoreClip;
}
QOpenGL2PaintEngineState::QOpenGL2PaintEngineState()
{
- hasClipping = false;
+ needsDepthBufferClear = true;
+ depthTestEnabled = false;
+ scissorTestEnabled = false;
+ currentDepth = -0.5f;
+ maxDepth = 0.5f;
+ canRestoreClip = true;
}
QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState()
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 7213474a01..db39ced087 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -77,8 +77,15 @@ public:
QOpenGL2PaintEngineState();
~QOpenGL2PaintEngineState();
- QRegion clipRegion;
- bool hasClipping;
+ bool needsDepthBufferClear;
+ qreal depthBufferClearValue;
+
+ bool depthTestEnabled;
+ bool scissorTestEnabled;
+ qreal currentDepth;
+ qreal maxDepth;
+
+ bool canRestoreClip;
};
@@ -116,7 +123,6 @@ public:
Type type() const { return OpenGL; }
- // State stuff is just for clipping and ripped off from QGLPaintEngine
void setState(QPainterState *s);
QPainterState *createState(QPainterState *orig) const;
inline QOpenGL2PaintEngineState *state() {
@@ -125,7 +131,6 @@ public:
inline const QOpenGL2PaintEngineState *state() const {
return static_cast<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
- void updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op);
virtual void sync();
private:
@@ -169,7 +174,6 @@ public:
// ^ Composites the bounding rect onto dest buffer
void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill);
// ^ Calls drawVertexArrays to render into stencil buffer
- void cleanStencilBuffer(const QGLRect& area);
void prepareForDraw(bool srcPixelsAreOpaque);
@@ -180,9 +184,10 @@ public:
QGLDrawable drawable;
int width, height;
QGLContext *ctx;
-
EngineMode mode;
+ mutable QOpenGL2PaintEngineState *last_created_state;
+
// Dirty flags
bool matrixDirty; // Implies matrix uniforms are also dirty
bool compositionModeDirty;
@@ -190,7 +195,9 @@ public:
bool brushUniformsDirty;
bool simpleShaderMatrixUniformDirty;
bool shaderMatrixUniformDirty;
- bool stencilBuferDirty;
+ bool stencilBufferDirty;
+ bool depthUniformDirty;
+ bool simpleShaderDepthUniformDirty;
const QBrush* currentBrush; // May not be the state's brush!
@@ -206,8 +213,9 @@ public:
QGLEngineShaderManager* shaderManager;
- // Clipping & state stuff stolen from QOpenGLPaintEngine:
- void updateDepthClip();
+ void writeClip(const QVectorPath &path, float depth);
+ void updateDepthScissorTest();
+ void regenerateDepthClip();
void systemStateChanged();
uint use_system_clip : 1;
};
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 3c198fbdab..10ca613ded 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -337,6 +337,9 @@ bool qt_resolve_version_2_0_functions(QGLContext *ctx)
if (!qt_resolve_version_1_3_functions(ctx))
gl2supported = false;
+ if (!qt_resolve_framebufferobject_extensions(ctx))
+ gl2supported = false;
+
if (glStencilOpSeparate)
return gl2supported;
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index 8d94c8bff5..98c406b0a8 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -389,6 +389,11 @@ QPaintEngine* QGLPixmapData::paintEngine() const
sz.setWidth(qMax(m_width, qRound(sz.width() * 1.5)));
if (sz.height() < m_height)
sz.setHeight(qMax(m_height, qRound(sz.height() * 1.5)));
+
+ // wasting too much space?
+ if (sz.width() * sz.height() > m_width * m_height * 2.5)
+ sz = QSize(m_width, m_height);
+
delete textureBufferStack.at(currentTextureBuffer).fbo;
textureBufferStack[currentTextureBuffer] =
createTextureBuffer(sz, textureBufferStack.at(currentTextureBuffer).engine);
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index 6d0bc1f15a..088ef97eca 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -781,7 +781,8 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage,
#ifndef QT_NO_IMAGE_SMOOTHSCALE
// If high quality not required, shrink image during decompression
- if (scaledSize.isValid() && quality < HIGH_QUALITY_THRESHOLD && !params.contains(QLatin1String("GetHeaderInformation")) ) {
+ if (scaledSize.isValid() && !scaledSize.isEmpty() && quality < HIGH_QUALITY_THRESHOLD
+ && !params.contains(QLatin1String("GetHeaderInformation")) ) {
cinfo.scale_denom = qMin(cinfo.image_width / scaledSize.width(),
cinfo.image_width / scaledSize.height());
if (cinfo.scale_denom < 2) {
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp
index 77dfeb3868..791aeaa474 100644
--- a/src/plugins/imageformats/tiff/qtiffhandler.cpp
+++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp
@@ -131,58 +131,138 @@ bool QTiffHandler::read(QImage *image)
if (!canRead())
return false;
- TIFF *tiff = TIFFClientOpen("foo",
- "r",
- this,
- qtiffReadProc,
- qtiffWriteProc,
- qtiffSeekProc,
- qtiffCloseProc,
- qtiffSizeProc,
- qtiffMapProc,
- qtiffUnmapProc);
-
- if (tiff) {
- uint32 width = 0;
- uint32 height = 0;
- TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);
- TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);
- if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32)
- *image = QImage(width, height, QImage::Format_ARGB32);
+ TIFF *const tiff = TIFFClientOpen("foo",
+ "r",
+ this,
+ qtiffReadProc,
+ qtiffWriteProc,
+ qtiffSeekProc,
+ qtiffCloseProc,
+ qtiffSizeProc,
+ qtiffMapProc,
+ qtiffUnmapProc);
+
+ if (!tiff) {
+ return false;
+ }
+ uint32 width;
+ uint32 height;
+ uint16 photometric;
+ if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width)
+ || !TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height)
+ || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) {
+ if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono)
+ *image = QImage(width, height, QImage::Format_Mono);
+ QVector<QRgb> colortable(2);
+ if (photometric == PHOTOMETRIC_MINISBLACK) {
+ colortable[0] = 0xff000000;
+ colortable[1] = 0xffffffff;
+ } else {
+ colortable[0] = 0xffffffff;
+ colortable[1] = 0xff000000;
+ }
+ image->setColorTable(colortable);
+
if (!image->isNull()) {
- if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, 0)) {
- uint16 resUnit = RESUNIT_NONE;
- float resX = 0;
- float resY = 0;
- TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit);
- TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX);
- TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY);
- switch(resUnit) {
- case RESUNIT_CENTIMETER:
- image->setDotsPerMeterX(qRound(resX * 100));
- image->setDotsPerMeterY(qRound(resY * 100));
- break;
- case RESUNIT_INCH:
- image->setDotsPerMeterX(qRound(resX * (100 / 2.54)));
- image->setDotsPerMeterY(qRound(resY * (100 / 2.54)));
- break;
- default:
- // do nothing as defaults have already
- // been set within the QImage class
- break;
+ for (uint32 y=0; y<height; ++y) {
+ if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
+ TIFFClose(tiff);
+ return false;
+ }
+ }
+ }
+ } else {
+ uint16 bitPerSample;
+ if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) {
+ TIFFClose(tiff);
+ return false;
+ }
+ if (photometric == PHOTOMETRIC_PALETTE && bitPerSample == 8) {
+ if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8)
+ *image = QImage(width, height, QImage::Format_Indexed8);
+ if (!image->isNull()) {
+ // create the color table
+ const uint16 tableSize = 256;
+ uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
+ uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
+ uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
+ if (!redTable || !greenTable || !blueTable) {
+ TIFFClose(tiff);
+ return false;
+ }
+ if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ QVector<QRgb> qtColorTable(tableSize);
+ for (int i = 0; i<tableSize ;++i) {
+ const int red = redTable[i] / 257;
+ const int green = greenTable[i] / 257;
+ const int blue = blueTable[i] / 257;
+ qtColorTable[i] = qRgb(red, green, blue);
+
+ }
+
+ image->setColorTable(qtColorTable);
+ for (uint32 y=0; y<height; ++y) {
+ if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
+ TIFFClose(tiff);
+ return false;
+ }
+ }
+
+ // free redTable, greenTable and greenTable done by libtiff
+ }
+ } else {
+ if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32)
+ *image = QImage(width, height, QImage::Format_ARGB32);
+ if (!image->isNull()) {
+ if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, 0)) {
+ for (uint32 y=0; y<height; ++y)
+ convert32BitOrder(image->scanLine(y), width);
+ } else {
+ TIFFClose(tiff);
+ return false;
}
- for (uint32 y=0; y<height; ++y)
- convert32BitOrder(image->scanLine(y), width);
- } else {
- *image = QImage();
}
}
- TIFFClose(tiff);
}
- if (image->isNull())
+ if (image->isNull()) {
+ TIFFClose(tiff);
return false;
+ }
+
+ float resX = 0;
+ float resY = 0;
+ uint16 resUnit = RESUNIT_NONE;
+ if (TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit)
+ && TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX)
+ && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) {
+
+ switch(resUnit) {
+ case RESUNIT_CENTIMETER:
+ image->setDotsPerMeterX(qRound(resX * 100));
+ image->setDotsPerMeterY(qRound(resY * 100));
+ break;
+ case RESUNIT_INCH:
+ image->setDotsPerMeterX(qRound(resX * (100 / 2.54)));
+ image->setDotsPerMeterY(qRound(resY * (100 / 2.54)));
+ break;
+ default:
+ // do nothing as defaults have already
+ // been set within the QImage class
+ break;
+ }
+ }
+ TIFFClose(tiff);
return true;
}
@@ -191,48 +271,145 @@ bool QTiffHandler::write(const QImage &image)
if (!device()->isWritable())
return false;
- TIFF *tiff = TIFFClientOpen("foo",
- "w",
- this,
- qtiffReadProc,
- qtiffWriteProc,
- qtiffSeekProc,
- qtiffCloseProc,
- qtiffSizeProc,
- qtiffMapProc,
- qtiffUnmapProc);
-
- if (tiff) {
- int width = image.width();
- int height = image.height();
- int depth = 32;
-
- if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width)
- || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height)
- || !TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
- || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
- || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, depth/8)
- || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
- || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
+ TIFF *const tiff = TIFFClientOpen("foo",
+ "w",
+ this,
+ qtiffReadProc,
+ qtiffWriteProc,
+ qtiffSeekProc,
+ qtiffCloseProc,
+ qtiffSizeProc,
+ qtiffMapProc,
+ qtiffUnmapProc);
+ if (!tiff)
+ return false;
+
+ const int width = image.width();
+ const int height = image.height();
+
+ if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width)
+ || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height)
+ || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ // set the resolution
+ bool resolutionSet = false;
+ const int dotPerMeterX = image.dotsPerMeterX();
+ const int dotPerMeterY = image.dotsPerMeterY();
+ if ((dotPerMeterX % 100) == 0
+ && (dotPerMeterY % 100) == 0) {
+ resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER)
+ && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0)
+ && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0);
+ } else {
+ resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)
+ && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast<float>(image.logicalDpiX()))
+ && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast<float>(image.logicalDpiY()));
+ }
+ if (!resolutionSet) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ // configure image depth
+ const QImage::Format format = image.format();
+ if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) {
+ uint16 photometric = PHOTOMETRIC_MINISBLACK;
+ if (image.colorTable().at(0) == 0xffffffff)
+ photometric = PHOTOMETRIC_MINISWHITE;
+ if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
+ || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)) {
TIFFClose(tiff);
return false;
}
- // set the resolution
- bool resolutionSet = false;
- const int dotPerMeterX = image.dotsPerMeterX();
- const int dotPerMeterY = image.dotsPerMeterY();
- if ((dotPerMeterX % 100) == 0
- && (dotPerMeterY % 100) == 0) {
- resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER)
- && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0)
- && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0);
- } else {
- resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)
- && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast<float>(image.logicalDpiX()))
- && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast<float>(image.logicalDpiY()));
+ // try to do the conversion in chunks no greater than 16 MB
+ int chunks = (width * height / (1024 * 1024 * 16)) + 1;
+ int chunkHeight = qMax(height / chunks, 1);
+
+ int y = 0;
+ while (y < height) {
+ QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_Mono);
+
+ int chunkStart = y;
+ int chunkEnd = y + chunk.height();
+ while (y < chunkEnd) {
+ if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
+ TIFFClose(tiff);
+ return false;
+ }
+ ++y;
+ }
+ }
+ TIFFClose(tiff);
+ } else if (format == QImage::Format_Indexed8) {
+ if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE)
+ || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
+ || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
+ TIFFClose(tiff);
+ return false;
+ }
+ //// write the color table
+ // allocate the color tables
+ uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
+ uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
+ uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
+ if (!redTable || !greenTable || !blueTable) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ // set the color table
+ const QVector<QRgb> colorTable = image.colorTable();
+
+ const int tableSize = colorTable.size();
+ Q_ASSERT(tableSize <= 256);
+ for (int i = 0; i<tableSize; ++i) {
+ const QRgb color = colorTable.at(i);
+ redTable[i] = qRed(color) * 257;
+ greenTable[i] = qGreen(color) * 257;
+ blueTable[i] = qBlue(color) * 257;
+ }
+
+ const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable);
+
+ qFree(redTable);
+ qFree(greenTable);
+ qFree(blueTable);
+
+ if (!setColorTableSuccess) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ //// write the data
+ // try to do the conversion in chunks no greater than 16 MB
+ int chunks = (width * height/ (1024 * 1024 * 16)) + 1;
+ int chunkHeight = qMax(height / chunks, 1);
+
+ int y = 0;
+ while (y < height) {
+ QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y));
+
+ int chunkStart = y;
+ int chunkEnd = y + chunk.height();
+ while (y < chunkEnd) {
+ if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
+ TIFFClose(tiff);
+ return false;
+ }
+ ++y;
+ }
}
- if (!resolutionSet) {
+ TIFFClose(tiff);
+
+ } else {
+ if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
+ || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
+ || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
+ || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
TIFFClose(tiff);
return false;
}
@@ -260,9 +437,8 @@ bool QTiffHandler::write(const QImage &image)
}
}
TIFFClose(tiff);
- } else {
- return false;
}
+
return true;
}
diff --git a/tests/auto/bic/bic.pro b/tests/auto/bic/bic.pro
index a168d77954..82711c9dfa 100644
--- a/tests/auto/bic/bic.pro
+++ b/tests/auto/bic/bic.pro
@@ -2,3 +2,9 @@ load(qttest_p4)
SOURCES += tst_bic.cpp qbic.cpp
QT = core
+wince*:{
+ DEFINES += SRCDIR=\\\"\\\"
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
diff --git a/tests/auto/bic/tst_bic.cpp b/tests/auto/bic/tst_bic.cpp
index 181c27587e..8bc8d4fd96 100644
--- a/tests/auto/bic/tst_bic.cpp
+++ b/tests/auto/bic/tst_bic.cpp
@@ -165,30 +165,30 @@ void tst_Bic::sizesAndVTables_data()
#if defined Q_OS_LINUX && defined Q_WS_X11
# if defined(__powerpc__) && !defined(__powerpc64__)
- archFileName400 = "data/%1.4.0.0.linux-gcc-ppc32.txt";
- archFileName410 = "data/%1.4.1.0.linux-gcc-ppc32.txt";
- archFileName420 = "data/%1.4.2.0.linux-gcc-ppc32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-ppc32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.linux-gcc-ppc32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.linux-gcc-ppc32.txt";
# elif defined(__amd64__)
- archFileName400 = "data/%1.4.0.0.linux-gcc-amd64.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-amd64.txt";
# elif defined(__i386__)
- archFileName400 = "data/%1.4.0.0.linux-gcc-ia32.txt";
- archFileName410 = "data/%1.4.1.0.linux-gcc-ia32.txt";
- archFileName420 = "data/%1.4.2.0.linux-gcc-ia32.txt";
- archFileName430 = "data/%1.4.3.0.linux-gcc-ia32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.linux-gcc-ia32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.linux-gcc-ia32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.linux-gcc-ia32.txt";
+ archFileName430 = SRCDIR "data/%1.4.3.0.linux-gcc-ia32.txt";
# endif
#elif defined Q_OS_AIX
if (sizeof(void*) == 4)
- archFileName400 = "data/%1.4.0.0.aix-gcc-power32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.aix-gcc-power32.txt";
#elif defined Q_OS_MAC && defined(__powerpc__)
- archFileName400 = "data/%1.4.0.0.macx-gcc-ppc32.txt";
- archFileName410 = "data/%1.4.1.0.macx-gcc-ppc32.txt";
- archFileName420 = "data/%1.4.2.0.macx-gcc-ppc32.txt";
+ archFileName400 = SRCDIR "data/%1.4.0.0.macx-gcc-ppc32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.macx-gcc-ppc32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.macx-gcc-ppc32.txt";
#elif defined Q_OS_MAC && defined(__i386__)
- archFileName410 = "data/%1.4.1.0.macx-gcc-ia32.txt";
- archFileName420 = "data/%1.4.2.0.macx-gcc-ia32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.macx-gcc-ia32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.macx-gcc-ia32.txt";
#elif defined Q_OS_WIN && defined Q_CC_GNU
- archFileName410 = "data/%1.4.1.0.win32-gcc-ia32.txt";
- archFileName420 = "data/%1.4.2.0.win32-gcc-ia32.txt";
+ archFileName410 = SRCDIR "data/%1.4.1.0.win32-gcc-ia32.txt";
+ archFileName420 = SRCDIR "data/%1.4.2.0.win32-gcc-ia32.txt";
#endif
if (archFileName400.isEmpty() && archFileName410.isEmpty()
@@ -293,6 +293,7 @@ void tst_Bic::sizesAndVTables()
bool isFailed = false;
+ qDebug() << oldLib.arg(libName);
if (oldLib.isEmpty() || !QFile::exists(oldLib.arg(libName)))
QSKIP("No platform spec found for this platform/version.", SkipSingle);
diff --git a/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
index 4d51e894e8..dd3e396a3e 100644
--- a/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
+++ b/tests/auto/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/tests/auto/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp
index f25f85892c..5d70e4d61d 100644
--- a/tests/auto/math3d/qquaternion/tst_qquaternion.cpp
+++ b/tests/auto/math3d/qquaternion/tst_qquaternion.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/tests/auto/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp
index a092fb0ed6..f7d241157a 100644
--- a/tests/auto/math3d/qvectornd/tst_qvectornd.cpp
+++ b/tests/auto/math3d/qvectornd/tst_qvectornd.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/tests/auto/math3d/shared/math3dincludes.h b/tests/auto/math3d/shared/math3dincludes.h
index 1ac0c0810c..a77090baf5 100644
--- a/tests/auto/math3d/shared/math3dincludes.h
+++ b/tests/auto/math3d/shared/math3dincludes.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the $MODULE$ of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
diff --git a/tests/auto/qcssparser/tst_cssparser.cpp b/tests/auto/qcssparser/tst_cssparser.cpp
index b41a7451ed..27258b72e6 100644
--- a/tests/auto/qcssparser/tst_cssparser.cpp
+++ b/tests/auto/qcssparser/tst_cssparser.cpp
@@ -114,11 +114,52 @@ void tst_CssParser::scanner_data()
}
}
+
+static char *tokenName(QCss::TokenType t)
+{
+ switch (t) {
+ case QCss::NONE: return "NONE";
+ case QCss::S: return "S";
+ case QCss::CDO: return "CDO";
+ case QCss::CDC: return "CDC";
+ case QCss::INCLUDES: return "INCLUDES";
+ case QCss::DASHMATCH: return "DASHMATCH";
+ case QCss::LBRACE: return "LBRACE";
+ case QCss::PLUS: return "PLUS";
+ case QCss::GREATER: return "GREATER";
+ case QCss::COMMA: return "COMMA";
+ case QCss::STRING: return "STRING";
+ case QCss::INVALID: return "INVALID";
+ case QCss::IDENT: return "IDENT";
+ case QCss::HASH: return "HASH";
+ case QCss::ATKEYWORD_SYM: return "ATKEYWORD_SYM";
+ case QCss::EXCLAMATION_SYM: return "EXCLAMATION_SYM";
+ case QCss::LENGTH: return "LENGTH";
+ case QCss::PERCENTAGE: return "PERCENTAGE";
+ case QCss::NUMBER: return "NUMBER";
+ case QCss::FUNCTION: return "FUNCTION";
+ case QCss::COLON: return "COLON";
+ case QCss::SEMICOLON: return "SEMICOLON";
+ case QCss::RBRACE: return "RBRACE";
+ case QCss::SLASH: return "SLASH";
+ case QCss::MINUS: return "MINUS";
+ case QCss::DOT: return "DOT";
+ case QCss::STAR: return "STAR";
+ case QCss::LBRACKET: return "LBRACKET";
+ case QCss::RBRACKET: return "RBRACKET";
+ case QCss::EQUAL: return "EQUAL";
+ case QCss::LPAREN: return "LPAREN";
+ case QCss::RPAREN: return "RPAREN";
+ case QCss::OR: return "OR";
+ }
+ return "";
+}
+
static void debug(const QVector<QCss::Symbol> &symbols, int index = -1)
{
qDebug() << "all symbols:";
for (int i = 0; i < symbols.count(); ++i)
- qDebug() << "(" << i << "); Token:" << QCss::Scanner::tokenName(symbols.at(i).token) << "; Lexem:" << symbols.at(i).lexem();
+ qDebug() << "(" << i << "); Token:" << tokenName(symbols.at(i).token) << "; Lexem:" << symbols.at(i).lexem();
if (index != -1)
qDebug() << "failure at index" << index;
}
@@ -160,7 +201,7 @@ void tst_CssParser::scanner()
QCOMPARE(l.count(), 2);
const QString expectedToken = l.at(0);
const QString expectedLexem = l.at(1);
- QString actualToken = QString::fromLatin1(QCss::Scanner::tokenName(symbols.at(i).token));
+ QString actualToken = QString::fromLatin1(tokenName(symbols.at(i).token));
if (actualToken != expectedToken) {
debug(symbols, i);
QCOMPARE(actualToken, expectedToken);
diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp
index 3d7e6f85d1..cccdd64c19 100644
--- a/tests/auto/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp
@@ -61,6 +61,7 @@
#include <qdebug.h>
#include "../network-settings.h"
+#include <private/qfileinfo_p.h>
//TESTED_CLASS=
//TESTED_FILES=
@@ -75,6 +76,9 @@ public:
private slots:
void getSetCheck();
+
+ void copy();
+
void isFile_data();
void isFile();
@@ -178,6 +182,58 @@ void tst_QFileInfo::getSetCheck()
QCOMPARE(true, obj1.caching());
}
+static QFileInfoPrivate* getPrivate(QFileInfo &info)
+{
+ return (*reinterpret_cast<QFileInfoPrivate**>(&info));
+}
+
+void tst_QFileInfo::copy()
+{
+ QTemporaryFile *t;
+ t = new QTemporaryFile;
+ t->open();
+ QFileInfo info(t->fileName());
+ QVERIFY(info.exists());
+
+ //copy constructor
+ QFileInfo info2(info);
+ QFileInfoPrivate *privateInfo = getPrivate(info);
+ QFileInfoPrivate *privateInfo2 = getPrivate(info2);
+ QCOMPARE(privateInfo->data, privateInfo2->data);
+
+ //operator =
+ QFileInfo info3 = info;
+ QFileInfoPrivate *privateInfo3 = getPrivate(info3);
+ QCOMPARE(privateInfo->data, privateInfo3->data);
+ QCOMPARE(privateInfo2->data, privateInfo3->data);
+
+ //refreshing info3 will detach it
+ QFile file(info.absoluteFilePath());
+ QVERIFY(file.open(QFile::WriteOnly));
+ QCOMPARE(file.write("JAJAJAA"), qint64(7));
+ file.flush();
+
+ QTest::qWait(250);
+#if defined(Q_OS_WIN) || defined(Q_OS_WINCE)
+ if (QSysInfo::windowsVersion() & QSysInfo::WV_VISTA ||
+ QSysInfo::windowsVersion() & QSysInfo::WV_CE_based)
+ file.close();
+#endif
+#if defined(Q_OS_WINCE)
+ // On Windows CE we need to close the file.
+ // Otherwise the content will be cached and not
+ // flushed to the storage, although we flushed it
+ // manually!!! CE has interim cache, we cannot influence.
+ QTest::qWait(5000);
+#endif
+ info3.refresh();
+ QVERIFY(privateInfo->data != privateInfo3->data);
+ QVERIFY(privateInfo2->data != privateInfo3->data);
+ QCOMPARE(privateInfo->data, privateInfo2->data);
+
+
+}
+
tst_QFileInfo::tst_QFileInfo()
{
}
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index c83134f777..cfd2b1549c 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -44,6 +44,7 @@
#include <private/qtextcontrol_p.h>
#include <private/qgraphicsitem_p.h>
+#include <QStyleOptionGraphicsItem>
#include <QAbstractTextDocumentLayout>
#include <QBitmap>
#include <QCursor>
@@ -219,8 +220,14 @@ private slots:
void updateCachedItemAfterMove();
void deviceTransform_data();
void deviceTransform();
+ void update();
void setTransformProperties_data();
void setTransformProperties();
+ void itemUsesExtendedStyleOption();
+ void itemSendsGeometryChanges();
+ void moveItem();
+ void sorting_data();
+ void sorting();
// task specific tests below me
void task141694_textItemEnsureVisible();
@@ -231,6 +238,9 @@ private slots:
void task240400_clickOnTextItem();
void task243707_addChildBeforeParent();
void task197802_childrenVisibility();
+
+private:
+ QList<QGraphicsItem *> paintedItems;
};
void tst_QGraphicsItem::init()
@@ -1790,15 +1800,15 @@ void tst_QGraphicsItem::setMatrix()
QCOMPARE(rlist.at(2), unrotatedRect); // From post-update (update current state)
}
-static QList<QGraphicsItem *> paintedItems;
+static QList<QGraphicsItem *> _paintedItems;
class PainterItem : public QGraphicsItem
{
protected:
QRectF boundingRect() const
{ return QRectF(-10, -10, 20, 20); }
- void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *)
- { paintedItems << this; }
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
+ { _paintedItems << this; painter->fillRect(boundingRect(), Qt::red); }
};
void tst_QGraphicsItem::zValue()
@@ -1830,10 +1840,10 @@ void tst_QGraphicsItem::zValue()
QApplication::sendPostedEvents(); //glib workaround
#endif
- QVERIFY(!paintedItems.isEmpty());
- QVERIFY((paintedItems.size() % 4) == 0);
+ QVERIFY(!_paintedItems.isEmpty());
+ QVERIFY((_paintedItems.size() % 4) == 0);
for (int i = 0; i < 3; ++i)
- QVERIFY(paintedItems.at(i)->zValue() < paintedItems.at(i + 1)->zValue());
+ QVERIFY(_paintedItems.at(i)->zValue() < _paintedItems.at(i + 1)->zValue());
}
void tst_QGraphicsItem::shape()
@@ -3726,8 +3736,20 @@ void tst_QGraphicsItem::defaultItemTest_QGraphicsEllipseItem()
class ItemChangeTester : public QGraphicsRectItem
{
public:
- ItemChangeTester(){}
- ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent) {}
+ ItemChangeTester()
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+ ItemChangeTester(QGraphicsItem *parent) : QGraphicsRectItem(parent)
+ { setFlag(ItemSendsGeometryChanges); clear(); }
+
+ void clear()
+ {
+ itemChangeReturnValue = QVariant();
+ itemSceneChangeTargetScene = 0;
+ changes.clear();
+ values.clear();
+ oldValues.clear();
+ }
+
QVariant itemChangeReturnValue;
QGraphicsScene *itemSceneChangeTargetScene;
@@ -3928,7 +3950,8 @@ void tst_QGraphicsItem::itemChange()
QCOMPARE(tester.changes.size(), changeCount);
QCOMPARE(tester.changes.at(tester.changes.size() - 2), QGraphicsItem::ItemFlagsChange);
QCOMPARE(tester.changes.at(tester.changes.size() - 1), QGraphicsItem::ItemFlagsHaveChanged);
- QCOMPARE(tester.values.at(tester.values.size() - 2), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
+ QVariant expectedFlags = qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges);
+ QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags);
QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue<quint32>(QGraphicsItem::ItemIsSelectable));
}
{
@@ -5780,19 +5803,36 @@ void tst_QGraphicsItem::opacity2()
QCOMPARE(grandChild->repaints, 0);
}
+class StacksBehindParentHelper : public QGraphicsRectItem
+{
+public:
+ StacksBehindParentHelper(QList<QGraphicsItem *> *paintedItems, const QRectF &rect, QGraphicsItem *parent = 0)
+ : QGraphicsRectItem(rect, parent), paintedItems(paintedItems)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ paintedItems->append(this);
+ }
+
+private:
+ QList<QGraphicsItem *> *paintedItems;
+};
+
void tst_QGraphicsItem::itemStacksBehindParent()
{
- QGraphicsRectItem *parent1 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
- QGraphicsRectItem *child11 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent1);
- QGraphicsRectItem *grandChild111 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child11);
- QGraphicsRectItem *child12 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent1);
- QGraphicsRectItem *grandChild121 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child12);
+ StacksBehindParentHelper *parent1 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child11 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild111 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child11);
+ StacksBehindParentHelper *child12 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent1);
+ StacksBehindParentHelper *grandChild121 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child12);
- QGraphicsRectItem *parent2 = new QGraphicsRectItem(QRectF(0, 0, 100, 50));
- QGraphicsRectItem *child21 = new QGraphicsRectItem(QRectF(-10, 10, 50, 50), parent2);
- QGraphicsRectItem *grandChild211 = new QGraphicsRectItem(QRectF(-20, 20, 50, 50), child21);
- QGraphicsRectItem *child22 = new QGraphicsRectItem(QRectF(60, 10, 50, 50), parent2);
- QGraphicsRectItem *grandChild221 = new QGraphicsRectItem(QRectF(70, 20, 50, 50), child22);
+ StacksBehindParentHelper *parent2 = new StacksBehindParentHelper(&paintedItems, QRectF(0, 0, 100, 50));
+ StacksBehindParentHelper *child21 = new StacksBehindParentHelper(&paintedItems, QRectF(-10, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild211 = new StacksBehindParentHelper(&paintedItems, QRectF(-20, 20, 50, 50), child21);
+ StacksBehindParentHelper *child22 = new StacksBehindParentHelper(&paintedItems, QRectF(60, 10, 50, 50), parent2);
+ StacksBehindParentHelper *grandChild221 = new StacksBehindParentHelper(&paintedItems, QRectF(70, 20, 50, 50), child22);
parent1->setData(0, "parent1");
child11->setData(0, "child11");
@@ -5814,25 +5854,57 @@ void tst_QGraphicsItem::itemStacksBehindParent()
scene.addItem(parent1);
scene.addItem(parent2);
+ paintedItems.clear();
+
+ QGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(250);
+
QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< grandChild111 << child11
<< grandChild121 << child12 << parent1
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << parent1 << child12 << grandChild121
+ << child11 << grandChild111);
child11->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ scene.update();
+ paintedItems.clear();
+ QTest::qWait(250);
+
QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< grandChild121 << child12 << parent1
<< grandChild111 << child11
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child11 << grandChild111
+ << parent1 << child12 << grandChild121);
child12->setFlag(QGraphicsItem::ItemStacksBehindParent);
+ paintedItems.clear();
+ scene.update();
+ QTest::qWait(250);
+
QCOMPARE(scene.items(0, 0, 100, 100), (QList<QGraphicsItem *>()
<< parent1 << grandChild111 << child11
<< grandChild121 << child12
<< grandChild211 << child21
<< grandChild221 << child22 << parent2));
+ QCOMPARE(paintedItems, QList<QGraphicsItem *>()
+ << parent2 << child22 << grandChild221
+ << child21 << grandChild211
+ << child12 << grandChild121
+ << child11 << grandChild111 << parent1);
}
class ClippingAndTransformsScene : public QGraphicsScene
@@ -5881,6 +5953,7 @@ void tst_QGraphicsItem::nestedClipping()
l3->setData(0, "l3");
QGraphicsView view(&scene);
+ view.setOptimizationFlag(QGraphicsView::IndirectPainting);
view.show();
#ifdef Q_WS_X11
qt_x11_wait_for_window_manager(&view);
@@ -6433,6 +6506,71 @@ void tst_QGraphicsItem::deviceTransform()
QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
}
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ int repaints;
+ QRegion paintedRegion;
+ MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ ++repaints;
+ QGraphicsView::paintEvent(e);
+ }
+ void reset() { repaints = 0; paintedRegion = QRegion(); }
+};
+
+void tst_QGraphicsItem::update()
+{
+ QGraphicsScene scene;
+ MyGraphicsView view(&scene);
+
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *item = new EventTester;
+ scene.addItem(item);
+ QTest::qWait(100); // Make sure all pending updates are processed.
+ item->repaints = 0;
+
+ item->update(); // Item marked as dirty
+ scene.update(); // Entire scene marked as dirty
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+
+ // Make sure the dirty state from the previous update is reset so that
+ // the item don't think it is already dirty and discards this update.
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 2);
+
+ // Make sure a partial update doesn't cause a full update to be discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(QRectF(0, 0, 5, 5));
+ item->update();
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRect itemDeviceBoundingRect = item->deviceTransform(view.viewportTransform())
+ .mapRect(item->boundingRect()).toRect();
+ const QRegion expectedRegion = itemDeviceBoundingRect.adjusted(-2, -2, 2, 2);
+ // The entire item's bounding rect (adjusted for antialiasing) should have been painted.
+ QCOMPARE(view.paintedRegion, expectedRegion);
+
+ // Make sure update requests outside the bounding rect are discarded.
+ view.reset();
+ item->repaints = 0;
+ item->update(-15, -15, 5, 5); // Item's brect: (-10, -10, 20, 20)
+ qApp->processEvents();
+ QCOMPARE(item->repaints, 0);
+ QCOMPARE(view.repaints, 0);
+}
+
void tst_QGraphicsItem::setTransformProperties_data()
{
QTest::addColumn<QPointF>("origin");
@@ -6445,26 +6583,26 @@ void tst_QGraphicsItem::setTransformProperties_data()
QTest::addColumn<qreal>("shearY");
QTest::newRow("nothing") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
- << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0);
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
QTest::newRow("rotationZ") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(42.2)
- << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0);
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
QTest::newRow("rotationXY") << QPointF() << qreal(12.5) << qreal(53.6) << qreal(0.0)
- << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0);
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
QTest::newRow("rotationXYZ") << QPointF() << qreal(-25) << qreal(12) << qreal(556)
- << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0);
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
QTest::newRow("rotationXYZ dicentred") << QPointF(-53, 25.2)
<< qreal(-2578.2) << qreal(4565.2) << qreal(56)
- << qreal(1) << qreal(1) << qreal(0.0) << qreal(0.0);
+ << qreal(1.0) << qreal(1.0) << qreal(0.0) << qreal(0.0);
QTest::newRow("Scale") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
<< qreal(6) << qreal(0.5) << qreal(0.0) << qreal(0.0);
QTest::newRow("Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
- << qreal(1) << qreal(1) << qreal(2.2) << qreal(0.5);
+ << qreal(1.0) << qreal(1.0) << qreal(2.2) << qreal(0.5);
QTest::newRow("Scale and Shear") << QPointF() << qreal(0.0) << qreal(0.0) << qreal(0.0)
<< qreal(5.2) << qreal(2.1) << qreal(5.2) << qreal(5.5);
@@ -6476,6 +6614,11 @@ void tst_QGraphicsItem::setTransformProperties_data()
<< qreal(4) << qreal(2) << qreal(2.56) << qreal(0.8);
}
+/**
+ * the normal QCOMPARE doesn't work because it doesn't use qFuzzyCompare
+ */
+#define QCOMPARE_TRANSFORM(X1, X2) QVERIFY(((X1)*(X2).inverted()).isIdentity())
+
void tst_QGraphicsItem::setTransformProperties()
{
QFETCH(QPointF,origin);
@@ -6499,7 +6642,6 @@ void tst_QGraphicsItem::setTransformProperties()
QGraphicsScene scene;
QGraphicsRectItem *item = new QGraphicsRectItem(QRectF(0, 0, 100, 100));
scene.addItem(item);
- item->setPos(100, 100);
item->setRotation(rotationX, rotationY, rotationZ);
item->setScale(scaleX, scaleY);
@@ -6515,7 +6657,8 @@ void tst_QGraphicsItem::setTransformProperties()
QCOMPARE(item->verticalShear(), shearY);
QCOMPARE(item->transformOrigin(), origin);
- QCOMPARE(result, item->transform());
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result, item->sceneTransform());
//-----------------------------------------------------------------
//Change the rotation Z
@@ -6538,24 +6681,311 @@ void tst_QGraphicsItem::setTransformProperties()
QCOMPARE(item->verticalShear(), shearY);
QCOMPARE(item->transformOrigin(), origin);
- QCOMPARE(result2, item->transform());
+ QCOMPARE(QTransform(), item->transform());
+ QCOMPARE(result2, item->sceneTransform());
//-----------------------------------------------------------------
- // calling setTransform() should reset the properties to their default
+ // calling setTransform() and setPos shoukld change the sceneTransform
item->setTransform(result);
+ item->setPos(100, -150.5);
- QCOMPARE(item->xRotation(), 0.0);
- QCOMPARE(item->yRotation(), 0.0);
- QCOMPARE(item->zRotation(), 0.0);
- QCOMPARE(item->xScale(), 1.0);
- QCOMPARE(item->yScale(), 1.0);
- QCOMPARE(item->horizontalShear(), 0.0);
- QCOMPARE(item->verticalShear(), 0.0);
- QCOMPARE(item->transformOrigin(), QPointF(0,0));
-
+ QCOMPARE(item->xRotation(), rotationX);
+ QCOMPARE(item->yRotation(), rotationY);
+ QCOMPARE(item->zRotation(), 45.0);
+ QCOMPARE(item->xScale(), scaleX);
+ QCOMPARE(item->yScale(), scaleY);
+ QCOMPARE(item->horizontalShear(), shearX);
+ QCOMPARE(item->verticalShear(), shearY);
+ QCOMPARE(item->transformOrigin(), origin);
QCOMPARE(result, item->transform());
+
+ QTransform result3;
+
+ result3.translate(origin.x(), origin.y());
+ result3 = result * result3;
+ result3.rotate(rotationX, Qt::XAxis);
+ result3.rotate(rotationY, Qt::YAxis);
+ result3.rotate(45, Qt::ZAxis);
+ result3.shear(shearX, shearY);
+ result3.scale(scaleX, scaleY);
+ result3.translate(-origin.x(), -origin.y());
+
+ result3 *= QTransform::fromTranslate(100, -150.5); //the pos;
+
+ QCOMPARE(result3, item->sceneTransform());
+
+ //-----------------------------------------------------
+ // setting the propertiees should be the same as setting a transform
+ {//with center origin on the matrix
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item1);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item2);
+
+ item1->setPos(12.3, -5);
+ item2->setPos(12.3, -5);
+ item1->setRotation(rotationX, rotationY, rotationZ);
+ item1->setScale(scaleX, scaleY);
+ item1->setShear(shearX, shearY);
+ item1->setTransformOrigin(origin);
+
+ item2->setTransform(result);
+
+ QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
+
+ QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
+ QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
+ }
+
+ {//with center origin on the item
+ QGraphicsRectItem *item1 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item1);
+ QGraphicsRectItem *item2 = new QGraphicsRectItem(QRectF(50.2, -150, 230.5, 119));
+ scene.addItem(item2);
+
+ item1->setPos(12.3, -5);
+ item2->setPos(12.3, -5);
+ item1->setTransformOrigin(origin);
+ item2->setTransformOrigin(origin);
+
+ item1->setRotation(rotationX, rotationY, rotationZ);
+ item1->setScale(scaleX, scaleY);
+ item1->setShear(shearX, shearY);
+
+ QTransform tr;
+ tr.rotate(rotationX, Qt::XAxis);
+ tr.rotate(rotationY, Qt::YAxis);
+ tr.rotate(rotationZ, Qt::ZAxis);
+ tr.shear(shearX, shearY);
+ tr.scale(scaleX, scaleY);
+
+ item2->setTransform(tr);
+
+ QCOMPARE_TRANSFORM(item1->sceneTransform(), item2->sceneTransform());
+
+ QCOMPARE_TRANSFORM(item1->itemTransform(item2), QTransform());
+ QCOMPARE_TRANSFORM(item2->itemTransform(item1), QTransform());
+ }
+}
+
+class MyStyleOptionTester : public QGraphicsRectItem
+{
+public:
+ MyStyleOptionTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), startTrack(false)
+ {}
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0)
+ {
+ if (startTrack) {
+ //Doesn't use the extended style option so the exposed rect is the boundingRect
+ if (!(flags() & QGraphicsItem::ItemUsesExtendedStyleOption)) {
+ QCOMPARE(option->exposedRect, boundingRect());
+ } else {
+ QVERIFY(option->exposedRect != QRect());
+ QVERIFY(option->exposedRect != boundingRect());
+ }
+ }
+ QGraphicsRectItem::paint(painter, option, widget);
+ }
+ bool startTrack;
+};
+
+void tst_QGraphicsItem::itemUsesExtendedStyleOption()
+{
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsPixmapItem item;
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QCOMPARE(item.flags(), QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemUsesExtendedStyleOption));
+ item.setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, false);
+ QCOMPARE(item.flags(), 0);
+
+ //We now test the content of the style option
+ MyStyleOptionTester *rect = new MyStyleOptionTester(QRect(0, 0, 100, 100));
+ scene.addItem(rect);
+ rect->setPos(200, 200);
+ QGraphicsView view(&scene);
+ QTest::qWait(500);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(125);
+ rect->startTrack = false;
+ rect->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
+ QVERIFY((rect->flags() & QGraphicsItem::ItemUsesExtendedStyleOption));
+ QTest::qWait(125);
+ rect->startTrack = true;
+ rect->update(10, 10, 10, 10);
+ QTest::qWait(125);
+}
+
+void tst_QGraphicsItem::itemSendsGeometryChanges()
+{
+ ItemChangeTester item;
+ item.setFlags(0);
+ item.clear();
+
+ QTransform x = QTransform().rotate(45);
+ QPointF pos(10, 10);
+ qreal o(0.5);
+ item.setTransform(x);
+ item.setPos(pos);
+ QCOMPARE(item.transform(), x);
+ QCOMPARE(item.pos(), pos);
+ QCOMPARE(item.changes.size(), 0);
+
+ item.setOpacity(o);
+ QCOMPARE(item.changes.size(), 2); // opacity
+
+ item.setFlag(QGraphicsItem::ItemSendsGeometryChanges);
+ QCOMPARE(item.changes.size(), 4); // flags
+ item.setTransform(QTransform());
+ item.setPos(QPointF());
+ QCOMPARE(item.changes.size(), 8); // transform + pos
+ QCOMPARE(item.transform(), QTransform());
+ QCOMPARE(item.pos(), QPointF());
+ QCOMPARE(item.opacity(), o);
+
+ QCOMPARE(item.changes, QList<QGraphicsItem::GraphicsItemChange>()
+ << QGraphicsItem::ItemOpacityChange
+ << QGraphicsItem::ItemOpacityHasChanged
+ << QGraphicsItem::ItemFlagsChange
+ << QGraphicsItem::ItemFlagsHaveChanged
+ << QGraphicsItem::ItemTransformChange
+ << QGraphicsItem::ItemTransformHasChanged
+ << QGraphicsItem::ItemPositionChange
+ << QGraphicsItem::ItemPositionHasChanged);
+}
+
+// Make sure we update moved items correctly.
+void tst_QGraphicsItem::moveItem()
+{
+ QGraphicsScene scene;
+ scene.setSceneRect(-50, -50, 200, 200);
+
+ MyGraphicsView view(&scene);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ EventTester *parent = new EventTester;
+ EventTester *child = new EventTester(parent);
+ EventTester *grandChild = new EventTester(child);
+
+#define RESET_COUNTERS \
+ parent->repaints = 0; \
+ child->repaints = 0; \
+ grandChild->repaints = 0; \
+ view.reset();
+
+ scene.addItem(parent);
+ QTest::qWait(100);
+
+ RESET_COUNTERS
+
+ // Item's boundingRect: (-10, -10, 20, 20).
+ QRect parentDeviceBoundingRect = parent->deviceTransform(view.viewportTransform())
+ .mapRect(parent->boundingRect()).toRect()
+ .adjusted(-2, -2, 2, 2); // Adjusted for antialiasing.
+
+ parent->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ QRegion expectedParentRegion = parentDeviceBoundingRect; // old position
+ parentDeviceBoundingRect.translate(20, 20);
+ expectedParentRegion += parentDeviceBoundingRect; // new position
+ QCOMPARE(view.paintedRegion, expectedParentRegion);
+
+ RESET_COUNTERS
+
+ child->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedChildRegion = expectedParentRegion.translated(20, 20);
+ QCOMPARE(view.paintedRegion, expectedChildRegion);
+
+ RESET_COUNTERS
+
+ grandChild->setPos(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ const QRegion expectedGrandChildRegion = expectedParentRegion.translated(40, 40);
+ QCOMPARE(view.paintedRegion, expectedGrandChildRegion);
+
+ RESET_COUNTERS
+
+ parent->translate(20, 20);
+ qApp->processEvents();
+ QCOMPARE(parent->repaints, 1);
+ QCOMPARE(child->repaints, 1);
+ QCOMPARE(grandChild->repaints, 1);
+ QCOMPARE(view.repaints, 1);
+ expectedParentRegion.translate(20, 20);
+ expectedParentRegion += expectedChildRegion.translated(20, 20);
+ expectedParentRegion += expectedGrandChildRegion.translated(20, 20);
+ QCOMPARE(view.paintedRegion, expectedParentRegion);
}
+void tst_QGraphicsItem::sorting_data()
+{
+ QTest::addColumn<int>("index");
+
+ QTest::newRow("NoIndex") << int(QGraphicsScene::NoIndex);
+ QTest::newRow("BspTreeIndex") << int(QGraphicsScene::BspTreeIndex);
+}
+
+void tst_QGraphicsItem::sorting()
+{
+ _paintedItems.clear();
+
+ QGraphicsScene scene;
+ QGraphicsItem *grid[100][100];
+ for (int x = 0; x < 100; ++x) {
+ for (int y = 0; y < 100; ++y) {
+ PainterItem *item = new PainterItem;
+ item->setPos(x * 25, y * 25);
+ item->setData(0, QString("%1x%2").arg(x).arg(y));
+ grid[x][y] = item;
+ scene.addItem(item);
+ }
+ }
+
+ PainterItem *item1 = new PainterItem;
+ PainterItem *item2 = new PainterItem;
+ item1->setData(0, "item1");
+ item2->setData(0, "item2");
+ scene.addItem(item1);
+ scene.addItem(item2);
+
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::NoAnchor);
+ view.setTransformationAnchor(QGraphicsView::NoAnchor);
+ view.resize(100, 100);
+ view.setFrameStyle(0);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(100);
+
+ _paintedItems.clear();
+
+ view.viewport()->repaint();
+
+ QCOMPARE(_paintedItems, QList<QGraphicsItem *>()
+ << grid[0][0] << grid[0][1] << grid[0][2] << grid[0][3]
+ << grid[1][0] << grid[1][1] << grid[1][2] << grid[1][3]
+ << grid[2][0] << grid[2][1] << grid[2][2] << grid[2][3]
+ << grid[3][0] << grid[3][1] << grid[3][2] << grid[3][3]
+ << item1 << item2);
+}
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"
diff --git a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index d856024787..fa0e03571e 100644
--- a/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -1487,7 +1487,7 @@ void tst_QGraphicsProxyWidget::scrollUpdate()
QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
QCOMPARE(widget->npaints, 2);
QCOMPARE(widget->paintEventRegion.rects(),
- QVector<QRect>() << QRect(0, 0, 200, 13) << QRect(0, 13, 103, 10));
+ QVector<QRect>() << QRect(0, 0, 200, 12) << QRect(0, 12, 102, 10));
}
void tst_QGraphicsProxyWidget::setWidget_simple()
diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp
index dd997c74db..4d786c7ad7 100644
--- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp
+++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp
@@ -274,7 +274,9 @@ void tst_QGraphicsScene::sceneRect()
QCOMPARE(scene.sceneRect(), QRectF());
QGraphicsItem *item = scene.addRect(QRectF(0, 0, 10, 10));
+ qApp->processEvents();
item->setPos(-5, -5);
+ qApp->processEvents();
QCOMPARE(scene.itemAt(0, 0), item);
QCOMPARE(scene.itemAt(10, 10), (QGraphicsItem *)0);
@@ -1319,8 +1321,9 @@ void tst_QGraphicsScene::removeItem()
scene.removeItem(hoverItem);
hoverItem->setAcceptsHoverEvents(false);
scene.addItem(hoverItem);
- qApp->processEvents(); // update
- qApp->processEvents(); // draw
+ qApp->processEvents(); // <- delayed update is called
+ qApp->processEvents(); // <- scene schedules pending update
+ qApp->processEvents(); // <- pending update is sent to view
QVERIFY(!hoverItem->isHovered);
}
@@ -2714,6 +2717,7 @@ void tst_QGraphicsScene::update()
QGraphicsRectItem *rect = new QGraphicsRectItem(0, 0, 100, 100);
scene.addItem(rect);
+ qApp->processEvents();
rect->setPos(-100, -100);
// This function forces indexing
diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
index 696a42d81a..6b0d8b7942 100644
--- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
@@ -191,6 +191,7 @@ private slots:
void centerOnDirtyItem();
void mouseTracking();
void mouseTracking2();
+ void render();
// task specific tests below me
void task172231_untransformableItems();
@@ -2525,6 +2526,8 @@ void tst_QGraphicsView::acceptMousePressEvent()
scene.addRect(0, 0, 2000, 2000)->setFlag(QGraphicsItem::ItemIsMovable);
+ qApp->processEvents(); // ensure scene rect is updated
+
QApplication::sendEvent(view.viewport(), &event);
QVERIFY(view.accepted);
}
@@ -3201,6 +3204,62 @@ void tst_QGraphicsView::mouseTracking2()
QCOMPARE(spy.count(), 1);
}
+class RenderTester : public QGraphicsRectItem
+{
+public:
+ RenderTester(const QRectF &rect)
+ : QGraphicsRectItem(rect), paints(0)
+ { }
+
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
+ QWidget *widget)
+ {
+ QGraphicsRectItem::paint(painter, option, widget);
+ ++paints;
+ }
+
+ int paints;
+};
+
+void tst_QGraphicsView::render()
+{
+ // ### This test can be much more thorough - see QGraphicsScene::render.
+ QGraphicsScene scene;
+ RenderTester *r1 = new RenderTester(QRectF(0, 0, 50, 50));
+ RenderTester *r2 = new RenderTester(QRectF(50, 50, 50, 50));
+ RenderTester *r3 = new RenderTester(QRectF(0, 50, 50, 50));
+ RenderTester *r4 = new RenderTester(QRectF(50, 0, 50, 50));
+ scene.addItem(r1);
+ scene.addItem(r2);
+ scene.addItem(r3);
+ scene.addItem(r4);
+
+ QGraphicsView view(&scene);
+ view.setFrameStyle(0);
+ view.resize(200, 200);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(200);
+
+ QCOMPARE(r1->paints, 1);
+ QCOMPARE(r2->paints, 1);
+ QCOMPARE(r3->paints, 1);
+ QCOMPARE(r4->paints, 1);
+
+ QPixmap pix(200, 200);
+ pix.fill(Qt::transparent);
+ QPainter painter(&pix);
+ view.render(&painter);
+ painter.end();
+
+ QCOMPARE(r1->paints, 2);
+ QCOMPARE(r2->paints, 2);
+ QCOMPARE(r3->paints, 2);
+ QCOMPARE(r4->paints, 2);
+}
+
void tst_QGraphicsView::task253415_reconnectUpdateSceneOnSceneChanged()
{
QGraphicsView view;
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index 56d42c3e2d..00f3155560 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -155,6 +155,7 @@ private slots:
void windowFlags_data();
void windowFlags();
void shortcutsDeletion();
+ void painterStateProtectionOnWindowFrame();
// Task fixes
void task236127_bspTreeIndexFails();
@@ -2282,6 +2283,41 @@ void tst_QGraphicsWidget::shortcutsDeletion()
delete widget;
}
+class MessUpPainterWidget : public QGraphicsWidget
+{
+public:
+ MessUpPainterWidget(QGraphicsItem * parent = 0, Qt::WindowFlags wFlags = 0)
+ : QGraphicsWidget(parent, wFlags)
+ {}
+
+ void paintWindowFrame(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->setOpacity(0.0);
+ QGraphicsWidget::paintWindowFrame(painter, option, widget);
+ }
+ void paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+ {
+ QCOMPARE(painter->opacity(), 1.0);
+ painter->drawRect(0, 0, 100, 100);
+ QGraphicsWidget::paint(painter, option, widget);
+ }
+
+};
+
+void tst_QGraphicsWidget::painterStateProtectionOnWindowFrame()
+{
+ MessUpPainterWidget *widget = new MessUpPainterWidget(0, Qt::Window);
+ QGraphicsScene scene(0, 0, 300, 300);
+ QGraphicsView view(&scene);
+ scene.addItem(widget);
+ view.show();
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&view);
+#endif
+ QTest::qWait(500);
+}
+
class ProxyStyle : public QCommonStyle
{
public:
diff --git a/tests/auto/qimagereader/qimagereader.qrc b/tests/auto/qimagereader/qimagereader.qrc
index 3c674ad224..c6b963b032 100644
--- a/tests/auto/qimagereader/qimagereader.qrc
+++ b/tests/auto/qimagereader/qimagereader.qrc
@@ -30,7 +30,7 @@
<file>images/image.pgm</file>
<file>images/image.png</file>
<file>images/image.ppm</file>
- <file>images/image.tif</file>
+ <file>images/image_100dpi.tif</file>
<file>images/kollada.png</file>
<file>images/marble.xpm</file>
<file>images/namedcolors.xpm</file>
diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp
index f5313eb356..0b32f0a5c3 100644
--- a/tests/auto/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/qimagereader/tst_qimagereader.cpp
@@ -156,6 +156,9 @@ private slots:
void pixelCompareWithBaseline_data();
void pixelCompareWithBaseline();
+
+ void task255627_setNullScaledSize_data();
+ void task255627_setNullScaledSize();
};
static const QLatin1String prefix(SRCDIR "/images/");
@@ -333,6 +336,29 @@ void tst_QImageReader::setScaledSize()
QCOMPARE(image.size(), newSize);
}
+void tst_QImageReader::task255627_setNullScaledSize_data()
+{
+ setScaledSize_data();
+}
+
+void tst_QImageReader::task255627_setNullScaledSize()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QByteArray, format);
+
+ if (!format.isEmpty() && !QImageReader::supportedImageFormats().contains(format))
+ QSKIP("Qt does not support reading the \"" + format + "\" format", SkipSingle);
+
+ QImageReader reader(prefix + fileName);
+
+ // set a null size
+ reader.setScaledSize(QSize(0, 0));
+ reader.setQuality(0);
+ QImage image = reader.read();
+ QVERIFY(image.isNull());
+ QCOMPARE(image.size(), QSize(0, 0));
+}
+
void tst_QImageReader::setClipRect_data()
{
QTest::addColumn<QString>("fileName");
diff --git a/tests/auto/qimagewriter/tst_qimagewriter.cpp b/tests/auto/qimagewriter/tst_qimagewriter.cpp
index 349afa5150..3ceb2c2953 100644
--- a/tests/auto/qimagewriter/tst_qimagewriter.cpp
+++ b/tests/auto/qimagewriter/tst_qimagewriter.cpp
@@ -59,6 +59,7 @@ Q_DECLARE_METATYPE(QStringMap)
Q_DECLARE_METATYPE(QIntList)
Q_DECLARE_METATYPE(QImageWriter::ImageWriterError)
Q_DECLARE_METATYPE(QIODevice *)
+Q_DECLARE_METATYPE(QImage::Format)
//TESTED_FILES=
@@ -82,6 +83,9 @@ private slots:
void writeImage2();
void supportedFormats();
+ void readWriteNonDestructive_data();
+ void readWriteNonDestructive();
+
#if defined QTEST_HAVE_TIFF
void largeTiff();
#endif
@@ -376,6 +380,28 @@ void tst_QImageWriter::supportedFormats()
QCOMPARE(formatSet.size(), formats.size());
}
+void tst_QImageWriter::readWriteNonDestructive_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<QImage::Format>("expectedFormat");
+ QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono;
+ QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8;
+ QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32;
+}
+
+void tst_QImageWriter::readWriteNonDestructive()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(QImage::Format, expectedFormat);
+ QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format);
+ QVERIFY(image.save(prefix + "gen-readWriteNonDestructive.tiff"));
+
+ QImage image2 = QImage(prefix + "gen-readWriteNonDestructive.tiff");
+ QImage::Format readFormat = image2.format();
+ QCOMPARE(readFormat, expectedFormat);
+ QCOMPARE(image, image2);
+}
+
void tst_QImageWriter::setDescription_data()
{
QTest::addColumn<QString>("fileName");
diff --git a/tests/auto/qlistwidget/tst_qlistwidget.cpp b/tests/auto/qlistwidget/tst_qlistwidget.cpp
index 8d15aa4374..8468cf31c9 100644
--- a/tests/auto/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/qlistwidget/tst_qlistwidget.cpp
@@ -883,31 +883,46 @@ void tst_QListWidget::itemStreaming()
void tst_QListWidget::sortItems_data()
{
QTest::addColumn<int>("order");
- QTest::addColumn<QStringList>("initialList");
- QTest::addColumn<QStringList>("expectedList");
+ QTest::addColumn<QVariantList>("initialList");
+ QTest::addColumn<QVariantList>("expectedList");
QTest::addColumn<IntList>("expectedRows");
- QTest::newRow("ascending order")
+ QTest::newRow("ascending strings")
<< static_cast<int>(Qt::AscendingOrder)
- << (QStringList() << "c" << "d" << "a" << "b")
- << (QStringList() << "a" << "b" << "c" << "d")
+ << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b"))
+ << (QVariantList() << QString("a") << QString("b") << QString("c") << QString("d"))
<< (IntList() << 2 << 3 << 0 << 1);
- QTest::newRow("descending order")
+ QTest::newRow("descending strings")
<< static_cast<int>(Qt::DescendingOrder)
- << (QStringList() << "c" << "d" << "a" << "b")
- << (QStringList() << "d" << "c" << "b" << "a")
+ << (QVariantList() << QString("c") << QString("d") << QString("a") << QString("b"))
+ << (QVariantList() << QString("d") << QString("c") << QString("b") << QString("a"))
<< (IntList() << 1 << 0 << 3 << 2);
+
+ QTest::newRow("ascending numbers")
+ << static_cast<int>(Qt::AscendingOrder)
+ << (QVariantList() << 1 << 11 << 2 << 22)
+ << (QVariantList() << 1 << 2 << 11 << 22)
+ << (IntList() << 0 << 2 << 1 << 3);
+
+ QTest::newRow("descending numbers")
+ << static_cast<int>(Qt::DescendingOrder)
+ << (QVariantList() << 1 << 11 << 2 << 22)
+ << (QVariantList() << 22 << 11 << 2 << 1)
+ << (IntList() << 3 << 1 << 2 << 0);
}
void tst_QListWidget::sortItems()
{
QFETCH(int, order);
- QFETCH(QStringList, initialList);
- QFETCH(QStringList, expectedList);
+ QFETCH(QVariantList, initialList);
+ QFETCH(QVariantList, expectedList);
QFETCH(IntList, expectedRows);
- testWidget->addItems(initialList);
+ foreach (const QVariant &data, initialList) {
+ QListWidgetItem *item = new QListWidgetItem(testWidget);
+ item->setData(Qt::DisplayRole, data);
+ }
QAbstractItemModel *model = testWidget->model();
QList<QPersistentModelIndex> persistent;
@@ -918,7 +933,7 @@ void tst_QListWidget::sortItems()
QCOMPARE(testWidget->count(), expectedList.count());
for (int i = 0; i < testWidget->count(); ++i)
- QCOMPARE(testWidget->item(i)->text(), expectedList.at(i));
+ QCOMPARE(testWidget->item(i)->text(), expectedList.at(i).toString());
for (int k = 0; k < testWidget->count(); ++k)
QCOMPARE(persistent.at(k).row(), expectedRows.at(k));
diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp
index 8a6b63bb01..058c3c6156 100644
--- a/tests/auto/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/qpixmap/tst_qpixmap.cpp
@@ -376,7 +376,7 @@ void tst_QPixmap::scroll()
QFETCH(QRegion, exposed);
QFETCH(bool, newPix);
- QPixmap pixmap(input);
+ QPixmap pixmap = QPixmap::fromImage(input);
QRegion exp;
qint64 oldKey = pixmap.cacheKey();
pixmap.scroll(dx, dy, rect, &exp);
diff --git a/tests/auto/qvariant/tst_qvariant.cpp b/tests/auto/qvariant/tst_qvariant.cpp
index 0ede920a43..2d269144dc 100644
--- a/tests/auto/qvariant/tst_qvariant.cpp
+++ b/tests/auto/qvariant/tst_qvariant.cpp
@@ -2449,14 +2449,22 @@ void tst_QVariant::saveLoadCustomTypes()
void tst_QVariant::url()
{
- QUrl url("http://www.trolltech.com");
+ QString str("http://www.trolltech.com");
+ QUrl url(str);
- QVariant v(url);
+ QVariant v(url); //built with a QUrl
QVariant v2 = v;
- QVERIFY(v2.toUrl() == url);
+ QVariant v3(str); //built with a QString
+ QCOMPARE(v2.toUrl(), url);
+ QVERIFY(qVariantCanConvert<QUrl>(v3));
+ QCOMPARE(v2.toUrl(), v3.toUrl());
+
+ QVERIFY(qVariantCanConvert<QString>(v2));
+ QCOMPARE(v2.toString(), str);
+ QCOMPARE(v3.toString(), str);
}
void tst_QVariant::globalColor()
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index 041aa7ab0b..85d7de1e7a 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -288,6 +288,7 @@ private slots:
void render_systemClip3_data();
void render_systemClip3();
void render_task252837();
+ void render_worldTransform();
void setContentsMargins();
@@ -7151,6 +7152,99 @@ void tst_QWidget::render_task252837()
// Please do not crash.
widget.render(&painter);
}
+
+void tst_QWidget::render_worldTransform()
+{
+ class MyWidget : public QWidget
+ { public:
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter painter(this);
+ // Make sure world transform is identity.
+ QCOMPARE(painter.worldTransform(), QTransform());
+
+ // Make sure device transform is correct.
+ const QPoint widgetOffset = geometry().topLeft();
+ QTransform expectedDeviceTransform = QTransform::fromTranslate(105, 5);
+ expectedDeviceTransform.rotate(90);
+ expectedDeviceTransform.translate(widgetOffset.x(), widgetOffset.y());
+ QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
+
+ // Set new world transform.
+ QTransform newWorldTransform = QTransform::fromTranslate(10, 10);
+ newWorldTransform.rotate(90);
+ painter.setWorldTransform(newWorldTransform);
+ QCOMPARE(painter.worldTransform(), newWorldTransform);
+
+ // Again, check device transform.
+ expectedDeviceTransform.translate(10, 10);
+ expectedDeviceTransform.rotate(90);
+ QCOMPARE(painter.deviceTransform(), expectedDeviceTransform);
+
+ painter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ }
+ };
+
+ MyWidget widget;
+ widget.setFixedSize(100, 100);
+ widget.setPalette(Qt::red);
+ widget.setAutoFillBackground(true);
+
+ MyWidget child;
+ child.setParent(&widget);
+ child.move(50, 50);
+ child.setFixedSize(50, 50);
+ child.setPalette(Qt::blue);
+ child.setAutoFillBackground(true);
+
+ QImage image(QSize(110, 110), QImage::Format_RGB32);
+ image.fill(QColor(Qt::black).rgb());
+
+ QPainter painter(&image);
+ painter.translate(105, 5);
+ painter.rotate(90);
+
+ const QTransform worldTransform = painter.worldTransform();
+ const QTransform deviceTransform = painter.deviceTransform();
+
+ // Render widgets onto image.
+ widget.render(&painter);
+#ifdef RENDER_DEBUG
+ image.save("render_worldTransform_image.png");
+#endif
+
+ // Ensure the transforms are unchanged after render.
+ QCOMPARE(painter.worldTransform(), painter.worldTransform());
+ QCOMPARE(painter.deviceTransform(), painter.deviceTransform());
+ painter.end();
+
+ // Paint expected image.
+ QImage expected(QSize(110, 110), QImage::Format_RGB32);
+ expected.fill(QColor(Qt::black).rgb());
+
+ QPainter expectedPainter(&expected);
+ expectedPainter.translate(105, 5);
+ expectedPainter.rotate(90);
+ expectedPainter.save();
+ expectedPainter.fillRect(widget.rect(),Qt::red);
+ expectedPainter.translate(10, 10);
+ expectedPainter.rotate(90);
+ expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ expectedPainter.restore();
+ expectedPainter.translate(50, 50);
+ expectedPainter.fillRect(child.rect(),Qt::blue);
+ expectedPainter.translate(10, 10);
+ expectedPainter.rotate(90);
+ expectedPainter.fillRect(QRect(0, 0, 20, 10), Qt::green);
+ expectedPainter.end();
+
+#ifdef RENDER_DEBUG
+ expected.save("render_worldTransform_expected.png");
+#endif
+
+ QCOMPARE(image, expected);
+}
+
void tst_QWidget::setContentsMargins()
{
QLabel label("why does it always rain on me?");
diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp
index 0c21534b57..44401ed24c 100644
--- a/tools/qdoc3/htmlgenerator.cpp
+++ b/tools/qdoc3/htmlgenerator.cpp
@@ -678,13 +678,17 @@ int HtmlGenerator::generateAtom(const Atom *atom,
else if (atom->string() == ATOM_LIST_VALUE) {
threeColumnEnumValueTable = isThreeColumnEnumValueTable(atom);
if (threeColumnEnumValueTable) {
- out() << "<p><table border=\"1\" cellpadding=\"2\" cellspacing=\"1\" width=\"100%\">\n"
- "<tr><th width=\"25%\">Constant</th><th width=\"15%\">Value</th>"
- "<th width=\"60%\">Description</th></tr>\n";
+ out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
+ << "cellspacing=\"1\" width=\"100%\">\n"
+ << "<tr><th width=\"25%\">Constant</th>"
+ << "<th width=\"15%\">Value</th>"
+ << "<th width=\"60%\">Description</th></tr>\n";
}
else {
- out() << "<p><table border=\"1\" cellpadding=\"2\" cellspacing=\"1\" width=\"40%\">\n"
- << "<tr><th width=\"60%\">Constant</th><th width=\"40%\">Value</th></tr>\n";
+ out() << "<p><table class=\"valuelist\" border=\"1\" cellpadding=\"2\" "
+ << "cellspacing=\"1\" width=\"40%\">\n"
+ << "<tr><th width=\"60%\">Constant</th><th "
+ << "width=\"40%\">Value</th></tr>\n";
}
}
else {
@@ -858,14 +862,17 @@ int HtmlGenerator::generateAtom(const Atom *atom,
}
if (!atom->string().isEmpty()) {
if (atom->string().contains("%"))
- out() << "<p><table width=\"" << atom->string() << "\" "
+ out() << "<p><table class=\"generic\" width=\"" << atom->string() << "\" "
<< "align=\"center\" cellpadding=\"2\" "
<< "cellspacing=\"1\" border=\"0\">\n";
- else
- out() << "<p><table align=\"center\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
+ else {
+ out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
+ << "cellspacing=\"1\" border=\"0\">\n";
+ }
}
else {
- out() << "<p><table align=\"center\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
+ out() << "<p><table class=\"generic\" align=\"center\" cellpadding=\"2\" "
+ << "cellspacing=\"1\" border=\"0\">\n";
}
numTableRows = 0;
break;
@@ -1577,7 +1584,8 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
QString tdTag;
if (numColumns > 1) {
tdTag = "<td width=\"" + QString::number((100 + numColumns - 1) / numColumns) + "%\">";
- out() << "<p><table width=\"100%\">\n<tr valign=\"top\">" << tdTag << "\n";
+ out() << "<p><table class=\"toc\" width=\"100%\">\n<tr valign=\"top\">"
+ << tdTag << "\n";
}
// disable nested links in table of contents
@@ -1596,7 +1604,8 @@ void HtmlGenerator::generateTableOfContents(const Node *node,
out() << "<ul>";
sectionNumber.append("1");
} while (sectionNumber.size() < nextLevel);
- } else {
+ }
+ else {
while (sectionNumber.size() > nextLevel) {
out() << "</ul>\n";
sectionNumber.removeLast();
@@ -1804,10 +1813,13 @@ void HtmlGenerator::generateClassHierarchy(const Node *relative,
}
}
-void HtmlGenerator::generateAnnotatedList(const Node *relative, CodeMarker *marker,
- const QMap<QString, const Node *> &nodeMap)
+void
+HtmlGenerator::generateAnnotatedList(const Node *relative,
+ CodeMarker *marker,
+ const QMap<QString,const Node *>&nodeMap)
{
- out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" cellspacing=\"1\" border=\"0\">\n";
+ out() << "<p><table width=\"100%\" class=\"annotated\" cellpadding=\"2\" "
+ << "cellspacing=\"1\" border=\"0\">\n";
int row = 0;
foreach (const QString &name, nodeMap.keys()) {
@@ -1960,7 +1972,7 @@ void HtmlGenerator::generateCompactList(const Node *relative, CodeMarker *marker
}
firstOffset[NumColumns] = classMap.count();
- out() << "<p><table width=\"100%\">\n";
+ out() << "<p><table class=\"generic\" width=\"100%\">\n";
for (k = 0; k < numRows; k++) {
out() << "<tr>\n";
for (i = 0; i < NumColumns; i++) {
@@ -2213,12 +2225,12 @@ void HtmlGenerator::generateSectionList(const Section& section,
name_alignment = false;
}
if (name_alignment) {
- out() << "<table border=\"0\" cellpadding=\"0\" "
+ out() << "<table class=\"alignedsummary\" border=\"0\" cellpadding=\"0\" "
<< "cellspacing=\"0\" width=\"100%\">\n";
}
else {
if (twoColumn)
- out() << "<p><table width=\"100%\" "
+ out() << "<p><table class=\"propsummary\" width=\"100%\" "
<< "border=\"0\" cellpadding=\"0\""
<< " cellspacing=\"0\">\n"
<< "<tr><td width=\"45%\" valign=\"top\">";
@@ -2349,8 +2361,6 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode,
// replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*(</@link>)"
static const QString linkTag("link");
- if (src.contains("setAcceptDrops"))
- qDebug() << "SRC:" << src;
bool done = false;
for (int i = 0, n = src.size(); i < n;) {
if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') {
@@ -2515,12 +2525,13 @@ void HtmlGenerator::generateSectionList(const Section& section,
bool twoColumn = false;
if (style == CodeMarker::SeparateList) {
twoColumn = (section.members.count() >= 16);
- } else if (section.members.first()->type() == Node::Property) {
+ }
+ else if (section.members.first()->type() == Node::Property) {
twoColumn = (section.members.count() >= 5);
}
if (twoColumn)
- out() << "<p><table width=\"100%\" border=\"0\" cellpadding=\"0\""
- " cellspacing=\"0\">\n"
+ out() << "<p><table class=\"generic\" width=\"100%\" border=\"0\" "
+ << "cellpadding=\"0\" cellspacing=\"0\">\n"
<< "<tr><td width=\"45%\" valign=\"top\">";
out() << "<ul>\n";
diff --git a/tools/qdoc3/test/classic.css b/tools/qdoc3/test/classic.css
index 85bb3484d9..7f228618db 100644
--- a/tools/qdoc3/test/classic.css
+++ b/tools/qdoc3/test/classic.css
@@ -14,12 +14,64 @@ H3 {
h3.fn,span.fn
{
- background-color: #e0eff6;
+ background-color: #eee;
border-width: 1px;
border-style: solid;
- border-color: #3388be #3388be #e9f8ff #3388be;
+ border-color: #ddd;
font-weight: bold;
padding: 6px 0px 6px 10px;
+ margin: 42px 0px 0px 0px;
+}
+
+hr {
+ border: 0;
+ color: #a0a0a0;
+ background-color: #ccc;
+ height: 1px;
+ width: 100%;
+ text-align: left;
+ margin: 34px 0px 34px 0px;
+}
+
+table.valuelist {
+ border-width: 1px 1px 1px 1px;
+ border-style: solid;
+ border-color: #dddddd;
+ border-collapse: collapse;
+ background-color: #f0f0f0;
+}
+
+table.indextable {
+ border-width: 1px 1px 1px 1px;
+ border-collapse: collapse;
+ background-color: #f0f0f0;
+ border-color:#555;
+}
+
+
+table.valuelist th {
+ border-width: 1px 1px 1px 2px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #666;
+ color:white;
+ background-color:#666;
+}
+
+th.titleheader {
+ border-width: 1px 0px 1px 0px;
+ padding: 4px;
+ border-style: solid;
+ border-color: #444;
+ color:white;
+ background-color:#555555;
+}
+
+p {
+
+ margin-left: 4px;
+ margin-top: 8px;
+ margin-bottom: 8px;
}
a:link
@@ -64,42 +116,31 @@ body
color: black
}
+table.generic, table.annotated
+{
+ border-width: 1px;
+ border-color:#bbb;
+ border-style:solid;
+ border-collapse:collapse;
+}
+
table td.memItemLeft {
- width: 200px;
- padding: 1px 0px 0px 8px;
+ width: 160px;
+ padding: 2px 0px 0px 8px;
margin: 4px;
- border-top-width: 1px;
- border-right-width: 1px;
- border-bottom-width: 1px;
- border-left-width: 1px;
- border-top-color: #E0E0E0;
- border-right-color: #E0E0E0;
- border-bottom-color: #E0E0E0;
- border-left-color: #E0E0E0;
- border-top-style: solid;
- border-right-style: none;
- border-bottom-style: none;
- border-left-style: none;
- background-color: #FAFAFA;
+ border-width: 1px;
+ border-color: #E0E0E0;
+ border-style: none;
font-size: 100%;
white-space: nowrap
}
+
table td.memItemRight {
- padding: 1px 8px 0px 8px;
+ padding: 2px 8px 0px 8px;
margin: 4px;
- border-top-width: 1px;
- border-right-width: 1px;
- border-bottom-width: 1px;
- border-left-width: 1px;
- border-top-color: #E0E0E0;
- border-right-color: #E0E0E0;
- border-bottom-color: #E0E0E0;
- border-left-color: #E0E0E0;
- border-top-style: solid;
- border-right-style: none;
- border-bottom-style: none;
- border-left-style: none;
- background-color: #FAFAFA;
+ border-width: 1px;
+ border-color: #E0E0E0;
+ border-style: none;
font-size: 100%;
}