From e97b1187391e16208a2da0e4c7f9e6daa540aa93 Mon Sep 17 00:00:00 2001 From: Joel Nordell Date: Wed, 17 Jun 2009 12:48:53 +0200 Subject: add a state() function to QScriptEngineDebugger for determining whether the debu gger is suspended or not Merge-request: 555 Reviewed-by: Kent Hansen --- src/scripttools/debugging/qscriptdebugger.cpp | 6 ++++++ src/scripttools/debugging/qscriptdebugger_p.h | 2 ++ src/scripttools/debugging/qscriptenginedebugger.cpp | 21 +++++++++++++++++++++ src/scripttools/debugging/qscriptenginedebugger.h | 7 +++++++ 4 files changed, 36 insertions(+) diff --git a/src/scripttools/debugging/qscriptdebugger.cpp b/src/scripttools/debugging/qscriptdebugger.cpp index 9cca8ad..003121f 100644 --- a/src/scripttools/debugging/qscriptdebugger.cpp +++ b/src/scripttools/debugging/qscriptdebugger.cpp @@ -1946,6 +1946,12 @@ QToolBar *QScriptDebugger::createStandardToolBar(QWidget *widgetParent, QObject return tb; } +bool QScriptDebugger::isInteractive() const +{ + Q_D(const QScriptDebugger); + return d->interactive; +} + /*! \reimp */ diff --git a/src/scripttools/debugging/qscriptdebugger_p.h b/src/scripttools/debugging/qscriptdebugger_p.h index 9ed7e0a..ba27200 100644 --- a/src/scripttools/debugging/qscriptdebugger_p.h +++ b/src/scripttools/debugging/qscriptdebugger_p.h @@ -172,6 +172,8 @@ public: bool eventFilter(QObject *, QEvent *e); + bool isInteractive() const; + Q_SIGNALS: void stopped() const; void started() const; diff --git a/src/scripttools/debugging/qscriptenginedebugger.cpp b/src/scripttools/debugging/qscriptenginedebugger.cpp index 948a01a..ae58c89 100644 --- a/src/scripttools/debugging/qscriptenginedebugger.cpp +++ b/src/scripttools/debugging/qscriptenginedebugger.cpp @@ -226,6 +226,15 @@ public: \value GoToLineAction Shows the "Go to Line" dialog. */ +/*! + \enum QScriptEngineDebugger::DebuggerState + + This enum specifies the current state of the debugger. + + \value RunningState The debugger is running. (Script evaluation is allowed.) + \value SuspendedState The debugger has suspended script evaluation. +*/ + class QScriptEngineDebuggerPrivate : public QObjectPrivate { @@ -387,6 +396,18 @@ void QScriptEngineDebugger::detach() } /*! + Returns the current state of the debugger. + + \sa evaluationResumed() + \sa evaluationSuspended() +*/ +QScriptEngineDebugger::DebuggerState QScriptEngineDebugger::state() const +{ + Q_D(const QScriptEngineDebugger); + return (d->debugger && d->debugger->isInteractive() ? SuspendedState : RunningState); +} + +/*! Returns a pointer to the instance of the specified standard \a widget. The widgets available are defined by the DebuggerWidget diff --git a/src/scripttools/debugging/qscriptenginedebugger.h b/src/scripttools/debugging/qscriptenginedebugger.h index 0fd4963..b9061a2 100644 --- a/src/scripttools/debugging/qscriptenginedebugger.h +++ b/src/scripttools/debugging/qscriptenginedebugger.h @@ -92,6 +92,11 @@ public: GoToLineAction }; + enum DebuggerState { + RunningState, + SuspendedState + }; + QScriptEngineDebugger(QObject *parent = 0); ~QScriptEngineDebugger(); @@ -108,6 +113,8 @@ public: QWidget *widget(DebuggerWidget widget) const; QAction *action(DebuggerAction action) const; + DebuggerState state() const; + Q_SIGNALS: void evaluationSuspended(); void evaluationResumed(); -- cgit v0.12 From f136f7410a30b090646a58c1791e15adfa18de85 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 17 Jun 2009 13:17:16 +0200 Subject: fix the QScriptEngineDebugger::state() logic, add test, improve docs --- src/scripttools/debugging/qscriptenginedebugger.cpp | 7 +++++-- tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/scripttools/debugging/qscriptenginedebugger.cpp b/src/scripttools/debugging/qscriptenginedebugger.cpp index ae58c89..f2245cc 100644 --- a/src/scripttools/debugging/qscriptenginedebugger.cpp +++ b/src/scripttools/debugging/qscriptenginedebugger.cpp @@ -126,7 +126,7 @@ public: mode in which it accepts input from the user. The evaluationResumed() signal is emitted when script evaluation is resumed, i.e, when execution control is given back to the script - engine. + engine. The state() function returns the debugger's current state. When calling QScriptEngine::evaluate() it is useful to pass a descriptive script name (file name) as second argument, as this is @@ -228,6 +228,7 @@ public: /*! \enum QScriptEngineDebugger::DebuggerState + \since 4.6 This enum specifies the current state of the debugger. @@ -396,6 +397,8 @@ void QScriptEngineDebugger::detach() } /*! + \since 4.6 + Returns the current state of the debugger. \sa evaluationResumed() @@ -404,7 +407,7 @@ void QScriptEngineDebugger::detach() QScriptEngineDebugger::DebuggerState QScriptEngineDebugger::state() const { Q_D(const QScriptEngineDebugger); - return (d->debugger && d->debugger->isInteractive() ? SuspendedState : RunningState); + return !d->debugger || !d->debugger->isInteractive() ? SuspendedState : RunningState; } /*! diff --git a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp index 5d9f56f..7f3f9f3 100644 --- a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp +++ b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp @@ -111,9 +111,11 @@ void tst_QScriptEngineDebugger::attachAndDetach() { { QScriptEngineDebugger debugger; + QCOMPARE(debugger.state(), QScriptEngineDebugger::SuspendedState); debugger.attachTo(0); QScriptEngine engine; debugger.attachTo(&engine); + QCOMPARE(debugger.state(), QScriptEngineDebugger::SuspendedState); } { QScriptEngineDebugger debugger; -- cgit v0.12 From 6f2f1fb334c8fbcaa2bf0607e813628b4c9549ca Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 17 Jun 2009 13:36:47 +0200 Subject: kill some includes not needed anymore The debugger is completely abstracted from QScriptEngine, whee --- src/scripttools/debugging/qscriptdebugger.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/scripttools/debugging/qscriptdebugger.cpp b/src/scripttools/debugging/qscriptdebugger.cpp index 003121f..20de788 100644 --- a/src/scripttools/debugging/qscriptdebugger.cpp +++ b/src/scripttools/debugging/qscriptdebugger.cpp @@ -75,10 +75,6 @@ #include "qscriptdebuggerjob_p_p.h" #include "qscriptxmlparser_p.h" -#include "qscriptenginedebuggerfrontend_p.h" -#include "qscriptdebuggerbackend_p.h" -#include - #include "private/qobject_p.h" #include -- cgit v0.12 From aff5e7a05e598f8196da4fe39dd0d193426d36e8 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 17 Jun 2009 14:22:50 +0200 Subject: QIoDevice and QAbstractSocket: Clarify doc about waitForReadyRead() --- src/corelib/io/qiodevice.cpp | 4 ++-- src/network/socket/qabstractsocket.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index d3fa6a8..2977c7f 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -1454,11 +1454,11 @@ QByteArray QIODevice::peek(qint64 maxSize) } /*! - Blocks until data is available for reading and the readyRead() + Blocks until new data is available for reading and the readyRead() signal has been emitted, or until \a msecs milliseconds have passed. If msecs is -1, this function will not time out. - Returns true if data is available for reading; otherwise returns + Returns true if new data is available for reading; otherwise returns false (if the operation timed out or if an error occurred). This function can operate without an event loop. It is diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 19bfe51..d099382 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1658,13 +1658,13 @@ bool QAbstractSocket::waitForConnected(int msecs) } /*! - This function blocks until data is available for reading and the + This function blocks until new data is available for reading and the \l{QIODevice::}{readyRead()} signal has been emitted. The function will timeout after \a msecs milliseconds; the default timeout is 30000 milliseconds. The function returns true if the readyRead() signal is emitted and - there is data available for reading; otherwise it returns false + there is new data available for reading; otherwise it returns false (if an error occurred or the operation timed out). \sa waitForBytesWritten() -- cgit v0.12 From f10441ab65d6204f23735e7cffbab5ac81663e91 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 17 Jun 2009 14:38:09 +0200 Subject: Autotest: fixed compile issues on hp compiler --- tests/auto/qanimationgroup/tst_qanimationgroup.cpp | 26 +++++++++++----------- .../tst_qparallelanimationgroup.cpp | 22 +++++++++--------- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/tests/auto/qanimationgroup/tst_qanimationgroup.cpp b/tests/auto/qanimationgroup/tst_qanimationgroup.cpp index 0457f8f..0e98797 100644 --- a/tests/auto/qanimationgroup/tst_qanimationgroup.cpp +++ b/tests/auto/qanimationgroup/tst_qanimationgroup.cpp @@ -206,9 +206,9 @@ void tst_QAnimationGroup::setCurrentTime() // sequence operating on same object/property QSequentialAnimationGroup *sequence = new QSequentialAnimationGroup(); - QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); - QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); - QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); + QAbstractAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); + QAbstractAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); + QAbstractAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); a2_s_o1->setLoopCount(3); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a2_s_o1); @@ -216,25 +216,25 @@ void tst_QAnimationGroup::setCurrentTime() // sequence operating on different object/properties QAnimationGroup *sequence2 = new QSequentialAnimationGroup(); - QVariantAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value"); - QVariantAnimation *a1_s_o3 = new QPropertyAnimation(&s_o3, "value"); + QAbstractAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value"); + QAbstractAnimation *a1_s_o3 = new QPropertyAnimation(&s_o3, "value"); sequence2->addAnimation(a1_s_o2); sequence2->addAnimation(a1_s_o3); // parallel operating on different object/properties QAnimationGroup *parallel = new QParallelAnimationGroup(); - QVariantAnimation *a1_p_o1 = new QPropertyAnimation(&p_o1, "value"); - QVariantAnimation *a1_p_o2 = new QPropertyAnimation(&p_o2, "value"); - QVariantAnimation *a1_p_o3 = new QPropertyAnimation(&p_o3, "value"); + QAbstractAnimation *a1_p_o1 = new QPropertyAnimation(&p_o1, "value"); + QAbstractAnimation *a1_p_o2 = new QPropertyAnimation(&p_o2, "value"); + QAbstractAnimation *a1_p_o3 = new QPropertyAnimation(&p_o3, "value"); a1_p_o2->setLoopCount(3); parallel->addAnimation(a1_p_o1); parallel->addAnimation(a1_p_o2); parallel->addAnimation(a1_p_o3); - UncontrolledAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1, "value"); + QAbstractAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1, "value"); QCOMPARE(notTimeDriven->totalDuration(), -1); - QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value"); + QAbstractAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value"); loopsForever->setLoopCount(-1); QCOMPARE(loopsForever->totalDuration(), -1); @@ -318,7 +318,7 @@ void tst_QAnimationGroup::setParentAutoAdd() { QParallelAnimationGroup group; QVariantAnimation *animation = new QPropertyAnimation(&group); - QCOMPARE(animation->group(), &group); + QCOMPARE(animation->group(), static_cast(&group)); } void tst_QAnimationGroup::beginNestedGroup() @@ -347,8 +347,8 @@ void tst_QAnimationGroup::beginNestedGroup() void tst_QAnimationGroup::addChildTwice() { - QPropertyAnimation *subGroup; - QPropertyAnimation *subGroup2; + QAbstractAnimation *subGroup; + QAbstractAnimation *subGroup2; QAnimationGroup *parent = new QSequentialAnimationGroup(); subGroup = new QPropertyAnimation(); diff --git a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp index 9f66fe0..d7d6b88 100644 --- a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp +++ b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp @@ -253,16 +253,16 @@ void tst_QParallelAnimationGroup::setCurrentTime() void tst_QParallelAnimationGroup::clearGroup() { QParallelAnimationGroup group; + static const int animationCount = 10; - for (int i = 0; i < 10; ++i) { + for (int i = 0; i < animationCount; ++i) { new QParallelAnimationGroup(&group); } - QCOMPARE(group.animationCount(), 10); + QCOMPARE(group.animationCount(), animationCount); - int count = group.animationCount(); - QPointer *children = new QPointer[count]; - for (int i = 0; i < count; ++i) { + QPointer children[animationCount]; + for (int i = 0; i < animationCount; ++i) { QVERIFY(group.animationAt(i) != 0); children[i] = group.animationAt(i); } @@ -270,10 +270,8 @@ void tst_QParallelAnimationGroup::clearGroup() group.clearAnimations(); QCOMPARE(group.animationCount(), 0); QCOMPARE(group.currentTime(), 0); - for (int i = 0; i < count; ++i) - QCOMPARE(children[i], QPointer()); - - delete[] children; + for (int i = 0; i < animationCount; ++i) + QVERIFY(children[i].isNull()); } void tst_QParallelAnimationGroup::propagateGroupUpdateToChildren() @@ -807,15 +805,15 @@ void tst_QParallelAnimationGroup::autoAdd() QParallelAnimationGroup group; QCOMPARE(group.duration(), 0); TestAnimation2 *test = new TestAnimation2(250, &group); // 0, duration = 250; - QCOMPARE(test->group(), &group); + QCOMPARE(test->group(), static_cast(&group)); QCOMPARE(test->duration(), 250); QCOMPARE(group.duration(), 250); test = new TestAnimation2(750, &group); // 1 - QCOMPARE(test->group(), &group); + QCOMPARE(test->group(), static_cast(&group)); QCOMPARE(group.duration(), 750); test = new TestAnimation2(500, &group); // 2 - QCOMPARE(test->group(), &group); + QCOMPARE(test->group(), static_cast(&group)); QCOMPARE(group.duration(), 750); delete group.animationAt(1); // remove the one with duration = 750 -- cgit v0.12 From abc67ad77fa719db95254ac2995c0ce1a3ebaf5c Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 17 Jun 2009 14:57:23 +0200 Subject: reset debugger's state correctly when previous engine was deleted If the engine was deleted, the agent will be 0, but we still want to fall through rather than return immediately, so that the other variables are reset correctly. --- .../debugging/qscriptdebuggerbackend.cpp | 30 +++++++++++----------- .../tst_qscriptenginedebugger.cpp | 8 ++++++ 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/scripttools/debugging/qscriptdebuggerbackend.cpp b/src/scripttools/debugging/qscriptdebuggerbackend.cpp index 9eaf571..da9d50e 100644 --- a/src/scripttools/debugging/qscriptdebuggerbackend.cpp +++ b/src/scripttools/debugging/qscriptdebuggerbackend.cpp @@ -433,21 +433,21 @@ void QScriptDebuggerBackend::attachTo(QScriptEngine *engine) void QScriptDebuggerBackend::detach() { Q_D(QScriptDebuggerBackend); - if (!d->agent) - return; - QScriptEngine *eng = d->agent->engine(); - if (eng && eng->agent() == d->agent) { - eng->setAgent(0); - QScriptValue global = eng->globalObject(); - if (global.property(QString::fromLatin1("print")).strictlyEquals(traceFunction())) - global.setProperty(QString::fromLatin1("print"), QScriptValue()); -// global.setProperty(QString::fromLatin1("qAssert"), QScriptValue()); - if (global.property(QString::fromLatin1("__FILE__")).strictlyEquals(fileNameFunction())) - global.setProperty(QString::fromLatin1("__FILE__"), QScriptValue()); - if (global.property(QString::fromLatin1("__LINE__")).strictlyEquals(lineNumberFunction())) - global.setProperty(QString::fromLatin1("__LINE__"), QScriptValue()); - d->agent->nullifyBackendPointer(); - d->agent = 0; // agent is owned by engine + if (d->agent) { + QScriptEngine *eng = d->agent->engine(); + if (eng && eng->agent() == d->agent) { + eng->setAgent(0); + QScriptValue global = eng->globalObject(); + if (global.property(QString::fromLatin1("print")).strictlyEquals(traceFunction())) + global.setProperty(QString::fromLatin1("print"), QScriptValue()); +// global.setProperty(QString::fromLatin1("qAssert"), QScriptValue()); + if (global.property(QString::fromLatin1("__FILE__")).strictlyEquals(fileNameFunction())) + global.setProperty(QString::fromLatin1("__FILE__"), QScriptValue()); + if (global.property(QString::fromLatin1("__LINE__")).strictlyEquals(lineNumberFunction())) + global.setProperty(QString::fromLatin1("__LINE__"), QScriptValue()); + d->agent->nullifyBackendPointer(); + d->agent = 0; // agent is owned by engine + } } d->pendingEvaluateLineNumber = -1; diff --git a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp index 7f3f9f3..5e5b701 100644 --- a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp +++ b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp @@ -163,6 +163,14 @@ void tst_QScriptEngineDebugger::attachAndDetach() debugger2.attachTo(&engine); } #endif + { + QScriptEngine *engine = new QScriptEngine; + QScriptEngineDebugger debugger; + debugger.attachTo(engine); + delete engine; + QScriptEngine engine2; + debugger.attachTo(&engine2); + } } void tst_QScriptEngineDebugger::action() -- cgit v0.12 From 30d6ac5feeb43b32eccc72595fe9a2c89d0f5c1e Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Wed, 17 Jun 2009 15:10:39 +0200 Subject: Autotests: fix compile issues on HPUX --- .../tst_qsequentialanimationgroup.cpp | 57 +++++++++++----------- tests/auto/qstatemachine/tst_qstatemachine.cpp | 32 ++++++------ 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp b/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp index 522a900..97ff04b 100644 --- a/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp +++ b/tests/auto/qsequentialanimationgroup/tst_qsequentialanimationgroup.cpp @@ -321,15 +321,15 @@ void tst_QSequentialAnimationGroup::setCurrentTimeWithUncontrolledAnimation() // sequence operating on different object/properties QAnimationGroup *sequence = new QSequentialAnimationGroup(); - QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); - QVariantAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value"); + QAbstractAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); + QAbstractAnimation *a1_s_o2 = new QPropertyAnimation(&s_o2, "value"); sequence->addAnimation(a1_s_o1); sequence->addAnimation(a1_s_o2); - UncontrolledAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1, "value"); + QAbstractAnimation *notTimeDriven = new UncontrolledAnimation(&t_o1, "value"); QCOMPARE(notTimeDriven->totalDuration(), -1); - QVariantAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value"); + QAbstractAnimation *loopsForever = new QPropertyAnimation(&t_o2, "value"); loopsForever->setLoopCount(-1); QCOMPARE(loopsForever->totalDuration(), -1); @@ -818,7 +818,7 @@ void tst_QSequentialAnimationGroup::restart() QCOMPARE(seqCurrentAnimChangedSpy.count(), 6); for(int i=0; i(seqCurrentAnimChangedSpy.at(i).at(0))); + QCOMPARE(static_cast(anims[i%3]), qVariantValue(seqCurrentAnimChangedSpy.at(i).at(0))); group.start(); @@ -836,9 +836,9 @@ void tst_QSequentialAnimationGroup::looping() // sequence operating on same object/property QSequentialAnimationGroup *sequence = new QSequentialAnimationGroup(); - QVariantAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); - QVariantAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); - QVariantAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); + QAbstractAnimation *a1_s_o1 = new QPropertyAnimation(&s_o1, "value"); + QAbstractAnimation *a2_s_o1 = new QPropertyAnimation(&s_o1, "value"); + QAbstractAnimation *a3_s_o1 = new QPropertyAnimation(&s_o1, "value"); QSignalSpy a1Spy(a1_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); QSignalSpy a2Spy(a2_s_o1, SIGNAL(stateChanged(QAbstractAnimation::State, QAbstractAnimation::State))); @@ -951,18 +951,19 @@ void tst_QSequentialAnimationGroup::startDelay() void tst_QSequentialAnimationGroup::clearGroup() { QSequentialAnimationGroup group; + + static const int animationCount = 20; - for (int i = 0; i < 10; ++i) { + for (int i = 0; i < animationCount/2; ++i) { QSequentialAnimationGroup *subGroup = new QSequentialAnimationGroup(&group); group.addPause(100); subGroup->addPause(10); } - QCOMPARE(group.animationCount(), 20); + QCOMPARE(group.animationCount(), animationCount); - int count = group.animationCount(); - QPointer *children = new QPointer[count]; - for (int i = 0; i < count; ++i) { + QPointer children[animationCount]; + for (int i = 0; i < animationCount; ++i) { QVERIFY(group.animationAt(i) != 0); children[i] = group.animationAt(i); } @@ -970,10 +971,8 @@ void tst_QSequentialAnimationGroup::clearGroup() group.clearAnimations(); QCOMPARE(group.animationCount(), 0); QCOMPARE(group.currentTime(), 0); - for (int i = 0; i < count; ++i) - QCOMPARE(children[i], QPointer()); - - delete[] children; + for (int i = 0; i < animationCount; ++i) + QVERIFY(children[i].isNull()); } void tst_QSequentialAnimationGroup::groupWithZeroDurationAnimations() @@ -995,7 +994,7 @@ void tst_QSequentialAnimationGroup::groupWithZeroDurationAnimations() //this should just run fine and change nothing group.setCurrentTime(0); - QCOMPARE(group.currentAnimation(), a1); + QCOMPARE(group.currentAnimation(), static_cast(a1)); QVariantAnimation *a2 = new QPropertyAnimation(&o2, "myOtherProperty"); a2->setDuration(500); @@ -1457,7 +1456,7 @@ void tst_QSequentialAnimationGroup::finishWithUncontrolledAnimation() group.setCurrentTime(300); QCOMPARE(group.state(), QAnimationGroup::Stopped); QCOMPARE(notTimeDriven.currentTime(), actualDuration); - QCOMPARE(group.currentAnimation(), &anim); + QCOMPARE(group.currentAnimation(), static_cast(&anim)); //3rd case: //now let's add a perfectly defined animation at the end @@ -1474,7 +1473,7 @@ void tst_QSequentialAnimationGroup::finishWithUncontrolledAnimation() QCOMPARE(notTimeDriven.state(), QAnimationGroup::Stopped); QCOMPARE(group.state(), QAnimationGroup::Running); QCOMPARE(anim.state(), QAnimationGroup::Running); - QCOMPARE(group.currentAnimation(), &anim); + QCOMPARE(group.currentAnimation(), static_cast(&anim)); QCOMPARE(animStateChangedSpy.count(), 1); QTest::qWait(300); //wait for the end of anim @@ -1494,21 +1493,21 @@ void tst_QSequentialAnimationGroup::addRemoveAnimation() QCOMPARE(group.duration(), 0); QCOMPARE(group.currentTime(), 0); - QVariantAnimation *anim1 = new QPropertyAnimation; + QAbstractAnimation *anim1 = new QPropertyAnimation; group.addAnimation(anim1); QCOMPARE(group.duration(), 250); QCOMPARE(group.currentTime(), 0); QCOMPARE(group.currentAnimation(), anim1); //let's append an animation - QVariantAnimation *anim2 = new QPropertyAnimation; + QAbstractAnimation *anim2 = new QPropertyAnimation; group.addAnimation(anim2); QCOMPARE(group.duration(), 500); QCOMPARE(group.currentTime(), 0); QCOMPARE(group.currentAnimation(), anim1); //let's prepend an animation - QVariantAnimation *anim0 = new QPropertyAnimation; + QAbstractAnimation *anim0 = new QPropertyAnimation; group.insertAnimationAt(0, anim0); QCOMPARE(group.duration(), 750); QCOMPARE(group.currentTime(), 0); @@ -1545,7 +1544,7 @@ void tst_QSequentialAnimationGroup::currentAnimation() QPropertyAnimation anim; anim.setDuration(0); group.addAnimation(&anim); - QCOMPARE(group.currentAnimation(), &anim); + QCOMPARE(group.currentAnimation(), static_cast(&anim)); } void tst_QSequentialAnimationGroup::currentAnimationWithZeroDuration() @@ -1572,21 +1571,21 @@ void tst_QSequentialAnimationGroup::currentAnimationWithZeroDuration() group.addAnimation(&zero3); group.addAnimation(&zero4); - QCOMPARE(group.currentAnimation(), &zero1); + QCOMPARE(group.currentAnimation(), static_cast(&zero1)); group.setCurrentTime(0); - QCOMPARE(group.currentAnimation(), &anim); + QCOMPARE(group.currentAnimation(), static_cast(&anim)); group.setCurrentTime(group.duration()); - QCOMPARE(group.currentAnimation(), &zero4); + QCOMPARE(group.currentAnimation(), static_cast(&zero4)); group.setDirection(QAbstractAnimation::Backward); group.setCurrentTime(0); - QCOMPARE(group.currentAnimation(), &zero1); + QCOMPARE(group.currentAnimation(), static_cast(&zero1)); group.setCurrentTime(group.duration()); - QCOMPARE(group.currentAnimation(), &anim); + QCOMPARE(group.currentAnimation(), static_cast(&anim)); } void tst_QSequentialAnimationGroup::insertAnimation() diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index cd0c71d..6040abd 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -778,7 +778,7 @@ void tst_QStateMachine::customErrorStateIsNull() QTest::ignoreMessage(QtWarningMsg, "Unrecoverable error detected in running state machine: Missing initial state in compound state ''"); QCoreApplication::processEvents(); - QCOMPARE(machine.errorState(), reinterpret_cast(0)); + QCOMPARE(machine.errorState(), reinterpret_cast(0)); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(oldErrorState)); } @@ -1103,29 +1103,29 @@ void tst_QStateMachine::stateEntryAndExit() TestTransition *t = new TestTransition(s2); QCOMPARE(t->machine(), (QStateMachine*)0); QCOMPARE(t->sourceState(), (QState*)0); - QCOMPARE(t->targetState(), s2); + QCOMPARE(t->targetState(), (QAbstractState*)s2); QCOMPARE(t->targetStates().size(), 1); - QCOMPARE(t->targetStates().at(0), s2); + QCOMPARE(t->targetStates().at(0), (QAbstractState*)s2); t->setTargetState(0); - QCOMPARE(t->targetState(), (QState*)0); + QCOMPARE(t->targetState(), (QAbstractState*)0); QVERIFY(t->targetStates().isEmpty()); t->setTargetState(s2); - QCOMPARE(t->targetState(), s2); + QCOMPARE(t->targetState(), (QAbstractState*)s2); QTest::ignoreMessage(QtWarningMsg, "QAbstractTransition::setTargetStates: target state(s) cannot be null"); t->setTargetStates(QList() << 0); - QCOMPARE(t->targetState(), s2); + QCOMPARE(t->targetState(), (QAbstractState*)s2); t->setTargetStates(QList() << s2); - QCOMPARE(t->targetState(), s2); + QCOMPARE(t->targetState(), (QAbstractState*)s2); QCOMPARE(t->targetStates().size(), 1); - QCOMPARE(t->targetStates().at(0), s2); + QCOMPARE(t->targetStates().at(0), (QAbstractState*)s2); QCOMPARE(s1->addTransition(t), (QAbstractTransition*)t); - QCOMPARE(t->sourceState(), s1); + QCOMPARE(t->sourceState(), (QState*)s1); QCOMPARE(t->machine(), &machine); { QAbstractTransition *trans = s2->addTransition(s3); QVERIFY(trans != 0); - QCOMPARE(trans->sourceState(), (QAbstractState*)s2); + QCOMPARE(trans->sourceState(), (QState*)s2); QCOMPARE(trans->targetState(), (QAbstractState*)s3); { char warning[256]; @@ -1134,10 +1134,10 @@ void tst_QStateMachine::stateEntryAndExit() s1->removeTransition(trans); } s2->removeTransition(trans); - QCOMPARE(trans->sourceState(), (QAbstractState*)0); + QCOMPARE(trans->sourceState(), (QState*)0); QCOMPARE(trans->targetState(), (QAbstractState*)s3); QCOMPARE(s2->addTransition(trans), trans); - QCOMPARE(trans->sourceState(), (QAbstractState*)s2); + QCOMPARE(trans->sourceState(), (QState*)s2); } QSignalSpy startedSpy(&machine, SIGNAL(started())); @@ -1724,18 +1724,18 @@ void tst_QStateMachine::signalTransitions() QStateMachine machine; QState *s0 = new QState(machine.rootState()); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: sender cannot be null"); - QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QObject*)0); + QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QAbstractTransition*)0); SignalEmitter emitter; QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: signal cannot be null"); - QCOMPARE(s0->addTransition(&emitter, 0, 0), (QObject*)0); + QCOMPARE(s0->addTransition(&emitter, 0, 0), (QAbstractTransition*)0); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state"); - QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QObject*)0); + QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QAbstractTransition*)0); QFinalState *s1 = new QFinalState(machine.rootState()); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: no such signal SignalEmitter::noSuchSignal()"); - QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QObject*)0); + QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QAbstractTransition*)0); QSignalTransition *trans = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1); QVERIFY(trans != 0); -- cgit v0.12 From 5af2e06cb543bd27450c29a1fca8686413f1cceb Mon Sep 17 00:00:00 2001 From: Joel Nordell Date: Wed, 17 Jun 2009 15:26:41 +0200 Subject: fix crash when detach()ing a debugger and then evaluating script print() function Merge-request: 554 Reviewed-by: Kent Hansen --- src/scripttools/debugging/qscriptdebuggerbackend.cpp | 15 +++++++++------ src/scripttools/debugging/qscriptdebuggerbackend_p_p.h | 6 +++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/scripttools/debugging/qscriptdebuggerbackend.cpp b/src/scripttools/debugging/qscriptdebuggerbackend.cpp index da9d50e..c7577d6 100644 --- a/src/scripttools/debugging/qscriptdebuggerbackend.cpp +++ b/src/scripttools/debugging/qscriptdebuggerbackend.cpp @@ -412,11 +412,14 @@ void QScriptDebuggerBackend::attachTo(QScriptEngine *engine) detach(); d->agent = new QScriptDebuggerAgent(d, engine); QScriptValue global = engine->globalObject(); + d->origTraceFunction = global.property(QString::fromLatin1("print")); global.setProperty(QString::fromLatin1("print"), traceFunction()); // global.setProperty(QString::fromLatin1("qAssert"), assertFunction()); + d->origFileNameFunction = global.property(QString::fromLatin1("__FILE__")); global.setProperty(QString::fromLatin1("__FILE__"), fileNameFunction(), QScriptValue::PropertyGetter | QScriptValue::PropertySetter | QScriptValue::ReadOnly); + d->origLineNumberFunction = global.property(QString::fromLatin1("__LINE__")); global.setProperty(QString::fromLatin1("__LINE__"), lineNumberFunction(), QScriptValue::PropertyGetter | QScriptValue::PropertySetter | QScriptValue::ReadOnly); @@ -438,13 +441,13 @@ void QScriptDebuggerBackend::detach() if (eng && eng->agent() == d->agent) { eng->setAgent(0); QScriptValue global = eng->globalObject(); - if (global.property(QString::fromLatin1("print")).strictlyEquals(traceFunction())) - global.setProperty(QString::fromLatin1("print"), QScriptValue()); + global.setProperty(QString::fromLatin1("print"), d->origTraceFunction); + d->origTraceFunction = QScriptValue(); // global.setProperty(QString::fromLatin1("qAssert"), QScriptValue()); - if (global.property(QString::fromLatin1("__FILE__")).strictlyEquals(fileNameFunction())) - global.setProperty(QString::fromLatin1("__FILE__"), QScriptValue()); - if (global.property(QString::fromLatin1("__LINE__")).strictlyEquals(lineNumberFunction())) - global.setProperty(QString::fromLatin1("__LINE__"), QScriptValue()); + global.setProperty(QString::fromLatin1("__FILE__"), d->origFileNameFunction); + d->origFileNameFunction = QScriptValue(); + global.setProperty(QString::fromLatin1("__LINE__"), d->origLineNumberFunction); + d->origLineNumberFunction = QScriptValue(); d->agent->nullifyBackendPointer(); d->agent = 0; // agent is owned by engine } diff --git a/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h b/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h index de18304..a356762 100644 --- a/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h +++ b/src/scripttools/debugging/qscriptdebuggerbackend_p_p.h @@ -57,6 +57,7 @@ #include #include +#include #include "qscriptdebuggerbackend_p.h" @@ -66,7 +67,6 @@ class QEvent; class QString; class QScriptContext; class QScriptEngine; -class QScriptValue; class QScriptValueIterator; class QScriptObjectSnapshot; class QScriptDebuggerAgent; @@ -126,6 +126,10 @@ public: QObject *eventReceiver; QScriptDebuggerBackend *q_ptr; + + QScriptValue origTraceFunction; + QScriptValue origFileNameFunction; + QScriptValue origLineNumberFunction; }; QT_END_NAMESPACE -- cgit v0.12 From 67d40ba7225dd38ba1e21ff6317920ce9fd5ee75 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Wed, 17 Jun 2009 15:42:01 +0200 Subject: make sure __FILE__ and __LINE__ properties are restored correctly Task-number: 256184 --- src/scripttools/debugging/qscriptdebuggerbackend.cpp | 10 ++++++---- tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp | 6 ++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/scripttools/debugging/qscriptdebuggerbackend.cpp b/src/scripttools/debugging/qscriptdebuggerbackend.cpp index c7577d6..7f4211c 100644 --- a/src/scripttools/debugging/qscriptdebuggerbackend.cpp +++ b/src/scripttools/debugging/qscriptdebuggerbackend.cpp @@ -417,12 +417,10 @@ void QScriptDebuggerBackend::attachTo(QScriptEngine *engine) // global.setProperty(QString::fromLatin1("qAssert"), assertFunction()); d->origFileNameFunction = global.property(QString::fromLatin1("__FILE__")); global.setProperty(QString::fromLatin1("__FILE__"), fileNameFunction(), - QScriptValue::PropertyGetter | QScriptValue::PropertySetter - | QScriptValue::ReadOnly); + QScriptValue::PropertyGetter | QScriptValue::ReadOnly); d->origLineNumberFunction = global.property(QString::fromLatin1("__LINE__")); global.setProperty(QString::fromLatin1("__LINE__"), lineNumberFunction(), - QScriptValue::PropertyGetter | QScriptValue::PropertySetter - | QScriptValue::ReadOnly); + QScriptValue::PropertyGetter | QScriptValue::ReadOnly); engine->setAgent(d->agent); } @@ -444,8 +442,12 @@ void QScriptDebuggerBackend::detach() global.setProperty(QString::fromLatin1("print"), d->origTraceFunction); d->origTraceFunction = QScriptValue(); // global.setProperty(QString::fromLatin1("qAssert"), QScriptValue()); + global.setProperty(QString::fromLatin1("__FILE__"), QScriptValue(), + QScriptValue::PropertyGetter); global.setProperty(QString::fromLatin1("__FILE__"), d->origFileNameFunction); d->origFileNameFunction = QScriptValue(); + global.setProperty(QString::fromLatin1("__LINE__"), QScriptValue(), + QScriptValue::PropertyGetter); global.setProperty(QString::fromLatin1("__LINE__"), d->origLineNumberFunction); d->origLineNumberFunction = QScriptValue(); d->agent->nullifyBackendPointer(); diff --git a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp index 5e5b701..cbdaf1e 100644 --- a/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp +++ b/tests/auto/qscriptenginedebugger/tst_qscriptenginedebugger.cpp @@ -131,11 +131,9 @@ void tst_QScriptEngineDebugger::attachAndDetach() QVERIFY(!engine.globalObject().property("print").strictlyEquals(oldPrint)); debugger.detach(); - QEXPECT_FAIL("", "Task 256184", Continue); - QVERIFY(!engine.globalObject().property("print").isValid()); - QEXPECT_FAIL("", "Task 256184", Continue); + QVERIFY(engine.globalObject().property("print").strictlyEquals(oldPrint)); QVERIFY(!engine.globalObject().property("__FILE__").isValid()); -// QVERIFY(!engine.globalObject().property("__LINE__").isValid()); + QVERIFY(!engine.globalObject().property("__LINE__").isValid()); } { QScriptEngineDebugger debugger; -- cgit v0.12 From c9ab7a8b8504101c06456b706a84e0eb0693c77e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 15:33:14 +0200 Subject: Speedup QGraphicsScenePrivate::processDirtyItemsRecursive. Don't process invisible items or items with no contents. I've also added cut-offs to QGraphicsViewPrivate::update(Region|Rect) to make sure update areas outside the viewport are discarded immediately. Reviewed-by: lars --- src/gui/graphicsview/qgraphicsitem_p.h | 15 +++++++- src/gui/graphicsview/qgraphicsscene.cpp | 63 ++++++++++++++++++++------------- src/gui/graphicsview/qgraphicsscene_p.h | 5 ++- src/gui/graphicsview/qgraphicsview.cpp | 32 ++++++++++------- src/gui/graphicsview/qgraphicsview_p.h | 4 +-- 5 files changed, 77 insertions(+), 42 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 9c1ee4f..ce74b4f 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -150,6 +150,8 @@ public: geometryChanged(0), inDestructor(0), isObject(0), + ignoreVisible(0), + ignoreOpacity(0), globalStackingOrder(-1), q_ptr(0) { @@ -327,6 +329,15 @@ public: return calcEffectiveOpacity(); } + inline qreal combineOpacityFromParent(qreal parentOpacity) const + { + if (parent && !(flags & QGraphicsItem::ItemIgnoresParentOpacity) + && !(parent->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { + return parentOpacity * opacity; + } + return opacity; + } + inline bool childrenCombineOpacity() const { if (!children.size()) @@ -407,7 +418,9 @@ public: quint32 geometryChanged : 1; quint32 inDestructor : 1; quint32 isObject : 1; - quint32 unused : 14; // feel free to use + quint32 ignoreVisible : 1; + quint32 ignoreOpacity : 1; + quint32 unused : 12; // feel free to use // Optional stacking order int globalStackingOrder; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 811e0d3..dd128ad 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5056,14 +5056,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * 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; - } + opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) { invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity(); if (!invisibleButChildIgnoresParentOpacity) @@ -5297,6 +5290,11 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b item->d_ptr->dirtyChildren = 1; } + if (force) + item->d_ptr->ignoreVisible = 1; + if (ignoreOpacity) + item->d_ptr->ignoreOpacity = 1; + QGraphicsItem *p = item->d_ptr->parent; while (p && !p->d_ptr->dirtyChildren) { p->d_ptr->dirtyChildren = 1; @@ -5304,7 +5302,8 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } } -void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren) +void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, + qreal parentOpacity) { Q_Q(QGraphicsScene); @@ -5318,20 +5317,30 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool wasDirtyParentSceneTransform = true; } - // Process item. bool wasDirtyParentViewBoundingRects = false; + qreal opacity = parentOpacity; + if (item) { + wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; + opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); + if ((!item->d_ptr->ignoreVisible && !item->d_ptr->visible) + || (!item->d_ptr->ignoreOpacity && opacity == 0.0) + || (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)) { + // Make sure we don't process invisible items or items with no content. + item->d_ptr->dirty = 0; + item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; + } + } + + // Process item. 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(); + const QRectF itemBoundingRect = adjustedItemBoundingRect(item); if (item->d_ptr->geometryChanged) { // Update growingItemsBoundingRect. - if (!hasSceneRect) { - QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect); - _q_adjustRect(&itemSceneBoundingRect); - growingItemsBoundingRect |= itemSceneBoundingRect; - } + if (!hasSceneRect) + growingItemsBoundingRect |= item->d_ptr->sceneTransform.mapRect(itemBoundingRect); item->d_ptr->geometryChanged = 0; } @@ -5360,11 +5369,12 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool break; } + QRect &paintedViewBoundingRect = item->d_ptr->paintedViewBoundingRects[viewPrivate->viewport]; if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) { wasDirtyParentViewBoundingRects = true; - QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport); - rect.translate(viewPrivate->dirtyScrollOffset); - viewPrivate->updateRect(rect); + paintedViewBoundingRect.translate(viewPrivate->dirtyScrollOffset); + if (!viewPrivate->updateRect(paintedViewBoundingRect)) + paintedViewBoundingRect = QRect(); } if (!item->d_ptr->dirty) @@ -5372,7 +5382,6 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool if (uninitializedDirtyRect) { dirtyRect = itemBoundingRect; - _q_adjustRect(&dirtyRect); if (!item->d_ptr->fullUpdatePending) { _q_adjustRect(&item->d_ptr->needsRepaint); dirtyRect &= item->d_ptr->needsRepaint; @@ -5390,10 +5399,14 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool 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()); + + if (item->d_ptr->hasBoundingRegionGranularity) { + if (!viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect())))) + paintedViewBoundingRect = QRect(); + } else { + if (!viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect())) + paintedViewBoundingRect = QRect(); + } } } } @@ -5434,7 +5447,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; } - processDirtyItemsRecursive(child, dirtyAncestorContainsChildren); + processDirtyItemsRecursive(child, dirtyAncestorContainsChildren, opacity); } } else if (wasDirtyParentSceneTransform) { item->d_ptr->invalidateChildrenSceneTransform(); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index cd463ee..a8f6699 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -266,7 +266,8 @@ public: 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); + void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false, + qreal parentOpacity = qreal(1.0)); inline void resetDirtyItem(QGraphicsItem *item) { @@ -278,6 +279,8 @@ public: item->d_ptr->needsRepaint = QRectF(); item->d_ptr->allChildrenDirty = 0; item->d_ptr->fullUpdatePending = 0; + item->d_ptr->ignoreVisible = 0; + item->d_ptr->ignoreOpacity = 0; } QStyle *style; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index e349992..715bf37 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -825,19 +825,22 @@ void QGraphicsViewPrivate::processPendingUpdates() dirtyRegion = QRegion(); } -void QGraphicsViewPrivate::updateRegion(const QRegion &r) +bool QGraphicsViewPrivate::updateRegion(const QRegion &r) { - if (r.isEmpty() || fullUpdatePending) - return; + if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate || r.isEmpty()) + return false; + + const QRect boundingRect = r.boundingRect(); + if (!boundingRect.intersects(viewport->rect())) + return false; // Update region outside viewport. - // Rect intersects viewport - update everything? switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; viewport->update(); break; case QGraphicsView::BoundingRectViewportUpdate: - dirtyBoundingRect |= r.boundingRect(); + dirtyBoundingRect |= boundingRect; if (dirtyBoundingRect.contains(viewport->rect())) { fullUpdatePending = true; viewport->update(); @@ -855,18 +858,20 @@ void QGraphicsViewPrivate::updateRegion(const QRegion &r) } break; } - case QGraphicsView::NoViewportUpdate: - // Unreachable + default: break; } + + return true; } -void QGraphicsViewPrivate::updateRect(const QRect &r) +bool QGraphicsViewPrivate::updateRect(const QRect &r) { - if (r.isEmpty() || fullUpdatePending) - return; + if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate + || !r.intersects(viewport->rect())) { + return false; + } - // Rect intersects viewport - update everything? switch (viewportUpdateMode) { case QGraphicsView::FullViewportUpdate: fullUpdatePending = true; @@ -886,10 +891,11 @@ void QGraphicsViewPrivate::updateRect(const QRect &r) else dirtyRegion += r.adjusted(-2, -2, 2, 2); break; - case QGraphicsView::NoViewportUpdate: - // Unreachable + default: break; } + + return true; } QStyleOptionGraphicsItem *QGraphicsViewPrivate::allocStyleOptionsArray(int numItems) diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index fac7bf9..9551ff6 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -171,8 +171,8 @@ public: dirtyBoundingRect = QRect(); dirtyRegion = QRegion(); } - void updateRect(const QRect &rect); - void updateRegion(const QRegion ®ion); + bool updateRect(const QRect &rect); + bool updateRegion(const QRegion ®ion); bool updateSceneSlotReimplementedChecked; QRegion exposedRegion; -- cgit v0.12 From f87863b11be8b0c909e52fac1b117516cf44d8fa Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 17 Jun 2009 15:45:28 +0200 Subject: QSslCertificate: Doc fix Change doc that refered to functions that got renamed --- src/network/ssl/qsslcertificate.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index d2cd0d6..9d8cfb0 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -71,9 +71,10 @@ After loading a certificate, you can find information about the certificate, its subject, and its issuer, by calling one of the many accessor functions, including version(), serialNumber(), - issuerInfo() and subjectInfo(). You can call notValidBefore() and - notValidAfter() to check when the certificate was issued, and when - it expires. The publicKey() function returns the certificate + issuerInfo() and subjectInfo(). You can call effectiveDate() and + expiryDate() to check when the certificate starts being + effective and when it expires. + The publicKey() function returns the certificate subject's public key as a QSslKey. You can call issuerInfo() or subjectInfo() to get detailed information about the certificate issuer and its subject. -- cgit v0.12 From a31a48445a8a9c0e0ef046c6eaf611906e9c77a4 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 17 Jun 2009 15:51:30 +0200 Subject: QNAM: Added comment to de-confuse myself I mixed this up several times before, so here is the comment for it. --- src/network/access/qnetworkaccesshttpbackend.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 460cbe3..8a6f27a 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -316,6 +316,7 @@ void QNetworkAccessHttpBackend::disconnectFromHttp() cache->releaseEntry(cacheKey); } + // This is abut disconnecting signals, not about disconnecting TCP connections if (httpReply) disconnect(httpReply, 0, this, 0); -- cgit v0.12 From 5c3c867989ca4c02114d25a7f91d698f6d334c06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 16:25:34 +0200 Subject: Fix tst_QGraphicsItem::opacityZeroUpdates Child items must ignore visible/opacity if parent does. Broke after: c9ab7a8b8504101c06456b706a84e0eb0693c77e --- src/gui/graphicsview/qgraphicsscene.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index dd128ad..e89d80f 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5419,12 +5419,18 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); } + const bool parentIgnoresVisible = item && item->d_ptr->ignoreVisible; + const bool parentIgnoresOpacity = item && item->d_ptr->ignoreOpacity; 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 (parentIgnoresVisible) + child->d_ptr->ignoreVisible = 1; + if (parentIgnoresOpacity) + child->d_ptr->ignoreOpacity = 1; if (allChildrenDirty) { child->d_ptr->dirty = 1; -- cgit v0.12 From cb59c2fcfaed088f1dc82af7b5b7ec1d5e2a8edc Mon Sep 17 00:00:00 2001 From: Thomas Zander Date: Tue, 16 Jun 2009 16:31:45 +0200 Subject: Fixes: Tablet not sending mouse release events. Rewrote the usage of XCheckTypedWindowEvent to now use a XCheckIfEvent based scanner. Using XCheckTypedWindowEvent caused us to sometimes hop over relevant events while doing compression. So we could end up merging a tablet move event with another tablet move event even while there was a mouse-release event between them. This rewrite makes sure we stop merging when needed. Task: 249606 Reviewed-by: Bradley T. Hughes --- src/gui/kernel/qapplication_x11.cpp | 128 +++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 61 deletions(-) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 988b34a..942836a 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -4611,6 +4611,46 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId) } #endif +struct qt_tablet_motion_data +{ + Time timestamp; + int tabletMotionType; + bool error; // found a reason to stop searching +}; + +static Bool qt_mouseMotion_scanner(Display *, XEvent *event, XPointer arg) +{ + qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; + if (data->error) + return false; + + if (event->type == MotionNotify) + return true; + + data->error = event->type != data->tabletMotionType; // we stop compression when another event gets in between. + return false; +} + +static Bool qt_tabletMotion_scanner(Display *, XEvent *event, XPointer arg) +{ + qt_tablet_motion_data *data = (qt_tablet_motion_data *) arg; + if (data->error) + return false; + + if (event->type == data->tabletMotionType) { + if (data->timestamp > 0) { + if ((reinterpret_cast(event))->time > data->timestamp) { + data->error = true; + return false; + } + } + return true; + } + + data->error = event->type != MotionNotify; // we stop compression when another event gets in between. + return false; +} + bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet) { #if defined (Q_OS_IRIX) @@ -4637,7 +4677,6 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet qreal rotation = 0; int deviceType = QTabletEvent::NoDevice; int pointerType = QTabletEvent::UnknownPointer; - XEvent xinputMotionEvent; XEvent mouseMotionEvent; const XDeviceMotionEvent *motion = 0; XDeviceButtonEvent *button = 0; @@ -4645,8 +4684,6 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet QEvent::Type t; Qt::KeyboardModifiers modifiers = 0; bool reinsertMouseEvent = false; - bool neverFoundMouseEvent = true; - XEvent xinputMotionEventNext; XEvent mouseMotionEventSave; #if !defined (Q_OS_IRIX) XID device_id; @@ -4654,72 +4691,41 @@ bool QETWidget::translateXinputEvent(const XEvent *ev, QTabletDeviceData *tablet if (ev->type == tablet->xinput_motion) { motion = reinterpret_cast(ev); - for (;;) { - // get the corresponding mouseMotionEvent for motion - if (XCheckTypedWindowEvent(X11->display, internalWinId(), MotionNotify, &mouseMotionEvent)) { + + // Do event compression. Skip over tablet+mouse move events if there are newer ones. + qt_tablet_motion_data tabletMotionData; + tabletMotionData.tabletMotionType = tablet->xinput_motion; + while (true) { + // Find first mouse event since we expect them in pairs inside Qt + tabletMotionData.error =false; + tabletMotionData.timestamp = 0; + if (XCheckIfEvent(X11->display, &mouseMotionEvent, &qt_mouseMotion_scanner, (XPointer) &tabletMotionData)) { mouseMotionEventSave = mouseMotionEvent; reinsertMouseEvent = true; - neverFoundMouseEvent = false; - - if (mouseMotionEvent.xmotion.time > motion->time) { - XEvent xinputMotionEventLoop = *ev; - - // xinput event is older than the mouse event --> search for the corresponding xinput event for the given mouse event - while (mouseMotionEvent.xmotion.time > (reinterpret_cast(&xinputMotionEventLoop))->time) { - if (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) { - xinputMotionEvent = xinputMotionEventLoop; - } - else { - break; - } - } - motion = reinterpret_cast(&xinputMotionEvent); - } - - // get the next xinputMotionEvent, for the next loop run - if (!XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventNext)) { - XPutBackEvent(X11->display, &mouseMotionEvent); - reinsertMouseEvent = false; - break; - } - - if (mouseMotionEvent.xmotion.time != motion->time) { - // reinsert in order - if (mouseMotionEvent.xmotion.time >= motion->time) { - XPutBackEvent(X11->display, &mouseMotionEvent); - XPutBackEvent(X11->display, &xinputMotionEventNext); - // next entry in queue is xinputMotionEventNext - } - else { - XPutBackEvent(X11->display, &xinputMotionEventNext); - XPutBackEvent(X11->display, &mouseMotionEvent); - // next entry in queue is mouseMotionEvent - } - reinsertMouseEvent = false; - break; - } - } - else { + } else { break; } - xinputMotionEvent = xinputMotionEventNext; - motion = (reinterpret_cast(&xinputMotionEvent)); - } + // Now discard any duplicate tablet events. + XEvent dummy; + tabletMotionData.error = false; + tabletMotionData.timestamp = mouseMotionEvent.xmotion.time; + while (XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { + motion = reinterpret_cast(&dummy); + } - if (reinsertMouseEvent) { - XPutBackEvent(X11->display, &mouseMotionEventSave); + // now check if there are more recent tablet motion events since we'll compress the current one with + // newer ones in that case + tabletMotionData.error = false; + tabletMotionData.timestamp = 0; + if (! XCheckIfEvent(X11->display, &dummy, &qt_tabletMotion_scanner, (XPointer) &tabletMotionData)) { + break; // done with compression + } + motion = reinterpret_cast(&dummy); } - if (neverFoundMouseEvent) { - XEvent xinputMotionEventLoop; - bool eventFound = false; - // xinput event without mouseMotionEvent --> search the newest xinputMotionEvent - while (XCheckTypedWindowEvent(X11->display, internalWinId(), tablet->xinput_motion, &xinputMotionEventLoop)) { - xinputMotionEvent = xinputMotionEventLoop; - eventFound = true; - } - if (eventFound) motion = reinterpret_cast(&xinputMotionEvent); + if (reinsertMouseEvent) { + XPutBackEvent(X11->display, &mouseMotionEventSave); } t = QEvent::TabletMove; -- cgit v0.12 From 38ef45edb1955b07c537be37bc4283749d8f28b2 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 17 Jun 2009 17:16:59 +0200 Subject: Compile fix on HP-UX Explicit casts make aCC happy. --- tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index e8a6d10..981efeb 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -3952,7 +3952,7 @@ 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); - QVariant expectedFlags = qVariantFromValue(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges); + QVariant expectedFlags = qVariantFromValue(QGraphicsItem::GraphicsItemFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges)); QCOMPARE(tester.values.at(tester.values.size() - 2), expectedFlags); QCOMPARE(tester.values.at(tester.values.size() - 1), qVariantFromValue(QGraphicsItem::ItemIsSelectable)); } -- cgit v0.12 From 652b2ca3379715f757776654b406c1ac08573f22 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Wed, 17 Jun 2009 17:01:45 +0200 Subject: QNAM: More comments, some renamings Renamed some classes and member variables. Their names were causing confusion before because. Reviewed-by: Peter Hartmann --- src/network/access/qnetworkaccesscache_p.h | 3 +++ src/network/access/qnetworkaccessftpbackend.cpp | 18 +++++++++--------- src/network/access/qnetworkaccessftpbackend_p.h | 4 ++-- src/network/access/qnetworkaccesshttpbackend.cpp | 19 +++++++++++++------ src/network/access/qnetworkaccesshttpbackend_p.h | 4 ++-- src/network/access/qnetworkaccessmanager.cpp | 24 ++++++++++++------------ src/network/access/qnetworkaccessmanager_p.h | 12 +++++++++--- 7 files changed, 50 insertions(+), 34 deletions(-) diff --git a/src/network/access/qnetworkaccesscache_p.h b/src/network/access/qnetworkaccesscache_p.h index 3fdfbb4..439b3a0 100644 --- a/src/network/access/qnetworkaccesscache_p.h +++ b/src/network/access/qnetworkaccesscache_p.h @@ -64,6 +64,9 @@ QT_BEGIN_NAMESPACE class QNetworkRequest; class QUrl; +// this class is not about caching files but about +// caching objects used by QNetworkAccessManager, e.g. existing TCP connections +// or credentials. class QNetworkAccessCache: public QObject { Q_OBJECT diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 9be433d..d6276a3 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -82,11 +82,11 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op, return 0; } -class QNetworkAccessFtpFtp: public QFtp, public QNetworkAccessCache::CacheableObject +class QNetworkAccessCachedFtpConnection: public QFtp, public QNetworkAccessCache::CacheableObject { // Q_OBJECT public: - QNetworkAccessFtpFtp() + QNetworkAccessCachedFtpConnection() { setExpires(true); setShareable(false); @@ -148,11 +148,11 @@ void QNetworkAccessFtpBackend::open() } state = LoggingIn; - QNetworkAccessCache* cache = QNetworkAccessManagerPrivate::getCache(this); + QNetworkAccessCache* objectCache = QNetworkAccessManagerPrivate::getObjectCache(this); QByteArray cacheKey = makeCacheKey(url); - if (!cache->requestEntry(cacheKey, this, + if (!objectCache->requestEntry(cacheKey, this, SLOT(ftpConnectionReady(QNetworkAccessCache::CacheableObject*)))) { - ftp = new QNetworkAccessFtpFtp; + ftp = new QNetworkAccessCachedFtpConnection; #ifndef QT_NO_NETWORKPROXY if (proxy.type() == QNetworkProxy::FtpCachingProxy) ftp->setProxy(proxy.hostName(), proxy.port()); @@ -160,7 +160,7 @@ void QNetworkAccessFtpBackend::open() ftp->connectToHost(url.host(), url.port(DefaultFtpPort)); ftp->login(url.userName(), url.password()); - cache->addEntry(cacheKey, ftp); + objectCache->addEntry(cacheKey, ftp); ftpConnectionReady(ftp); } @@ -207,7 +207,7 @@ void QNetworkAccessFtpBackend::downstreamReadyWrite() void QNetworkAccessFtpBackend::ftpConnectionReady(QNetworkAccessCache::CacheableObject *o) { - ftp = static_cast(o); + ftp = static_cast(o); connect(ftp, SIGNAL(done(bool)), SLOT(ftpDone())); connect(ftp, SIGNAL(rawCommandReply(int,QString)), SLOT(ftpRawCommandReply(int,QString))); connect(ftp, SIGNAL(readyRead()), SLOT(ftpReadyRead())); @@ -227,7 +227,7 @@ void QNetworkAccessFtpBackend::disconnectFromFtp() disconnect(ftp, 0, this, 0); QByteArray key = makeCacheKey(url()); - QNetworkAccessManagerPrivate::getCache(this)->releaseEntry(key); + QNetworkAccessManagerPrivate::getObjectCache(this)->releaseEntry(key); ftp = 0; } @@ -278,7 +278,7 @@ void QNetworkAccessFtpBackend::ftpDone() // we're not connected, so remove the cache entry: QByteArray key = makeCacheKey(url()); - QNetworkAccessManagerPrivate::getCache(this)->removeEntry(key); + QNetworkAccessManagerPrivate::getObjectCache(this)->removeEntry(key); disconnect(ftp, 0, this, 0); ftp->dispose(); diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h index 9626403..bb6d766 100644 --- a/src/network/access/qnetworkaccessftpbackend_p.h +++ b/src/network/access/qnetworkaccessftpbackend_p.h @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE class QNetworkAccessFtpIODevice; -class QNetworkAccessFtpFtp; +class QNetworkAccessCachedFtpConnection; class QNetworkAccessFtpBackend: public QNetworkAccessBackend { @@ -101,7 +101,7 @@ public slots: private: friend class QNetworkAccessFtpIODevice; - QPointer ftp; + QPointer ftp; QIODevice *uploadDevice; qint64 totalBytes; int helpId, sizeId, mdtmId; diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index 8a6f27a..71808d4 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -270,12 +270,12 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const return code; } -class QNetworkAccessHttpBackendCache: public QHttpNetworkConnection, +class QNetworkAccessCachedHttpConnection: public QHttpNetworkConnection, public QNetworkAccessCache::CacheableObject { // Q_OBJECT public: - QNetworkAccessHttpBackendCache(const QString &hostName, quint16 port, bool encrypt) + QNetworkAccessCachedHttpConnection(const QString &hostName, quint16 port, bool encrypt) : QHttpNetworkConnection(hostName, port, encrypt) { setExpires(true); @@ -311,8 +311,11 @@ QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend() void QNetworkAccessHttpBackend::disconnectFromHttp() { if (http) { + // This is abut disconnecting signals, not about disconnecting TCP connections disconnect(http, 0, this, 0); - QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this); + + // Get the object cache that stores our QHttpNetworkConnection objects + QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this); cache->releaseEntry(cacheKey); } @@ -583,16 +586,20 @@ void QNetworkAccessHttpBackend::open() // check if we have an open connection to this host cacheKey = makeCacheKey(this, theProxy); - QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getCache(this); - if ((http = static_cast(cache->requestEntryNow(cacheKey))) == 0) { + QNetworkAccessCache *cache = QNetworkAccessManagerPrivate::getObjectCache(this); + // the http object is actually a QHttpNetworkConnection + http = static_cast(cache->requestEntryNow(cacheKey)); + if (http == 0) { // no entry in cache; create an object - http = new QNetworkAccessHttpBackendCache(url.host(), url.port(), encrypt); + // the http object is actually a QHttpNetworkConnection + http = new QNetworkAccessCachedHttpConnection(url.host(), url.port(), encrypt); #ifndef QT_NO_NETWORKPROXY http->setTransparentProxy(transparentProxy); http->setCacheProxy(cacheProxy); #endif + // cache the QHttpNetworkConnection corresponding to this cache key cache->addEntry(cacheKey, http); } diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h index e0801ce..dec69d0 100644 --- a/src/network/access/qnetworkaccesshttpbackend_p.h +++ b/src/network/access/qnetworkaccesshttpbackend_p.h @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE -class QNetworkAccessHttpBackendCache; +class QNetworkAccessCachedHttpConnection; class QNetworkAccessHttpBackendIODevice; @@ -106,7 +106,7 @@ private slots: private: QHttpNetworkReply *httpReply; - QPointer http; + QPointer http; QByteArray cacheKey; QNetworkAccessBackendUploadIODevice *uploadDevice; diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 0ae920b..ed2f220 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -836,7 +836,7 @@ void QNetworkAccessManagerPrivate::addCredentials(const QNetworkProxy &p, QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache; auth->insert(QString(), authenticator->user(), authenticator->password()); - cache.addEntry(cacheKey, auth); // replace the existing one, if there's any + objectCache.addEntry(cacheKey, auth); // replace the existing one, if there's any if (realm.isEmpty()) { break; @@ -870,13 +870,13 @@ QNetworkAccessManagerPrivate::fetchCachedCredentials(const QNetworkProxy &p, QByteArray cacheKey = proxyAuthenticationKey(proxy, realm); if (cacheKey.isEmpty()) return 0; - if (!cache.hasEntry(cacheKey)) + if (!objectCache.hasEntry(cacheKey)) return 0; QNetworkAuthenticationCache *auth = - static_cast(cache.requestEntryNow(cacheKey)); + static_cast(objectCache.requestEntryNow(cacheKey)); QNetworkAuthenticationCredential *cred = auth->findClosestMatch(QString()); - cache.releaseEntry(cacheKey); + objectCache.releaseEntry(cacheKey); // proxy cache credentials always have exactly one item Q_ASSERT_X(cred, "QNetworkAccessManager", @@ -917,15 +917,15 @@ void QNetworkAccessManagerPrivate::addCredentials(const QUrl &url, copy.setUserName(authenticator->user()); do { QByteArray cacheKey = authenticationKey(copy, realm); - if (cache.hasEntry(cacheKey)) { + if (objectCache.hasEntry(cacheKey)) { QNetworkAuthenticationCache *auth = - static_cast(cache.requestEntryNow(cacheKey)); + static_cast(objectCache.requestEntryNow(cacheKey)); auth->insert(domain, authenticator->user(), authenticator->password()); - cache.releaseEntry(cacheKey); + objectCache.releaseEntry(cacheKey); } else { QNetworkAuthenticationCache *auth = new QNetworkAuthenticationCache; auth->insert(domain, authenticator->user(), authenticator->password()); - cache.addEntry(cacheKey, auth); + objectCache.addEntry(cacheKey, auth); } if (copy.userName().isEmpty()) { @@ -959,19 +959,19 @@ QNetworkAccessManagerPrivate::fetchCachedCredentials(const QUrl &url, realm = authentication->realm(); QByteArray cacheKey = authenticationKey(url, realm); - if (!cache.hasEntry(cacheKey)) + if (!objectCache.hasEntry(cacheKey)) return 0; QNetworkAuthenticationCache *auth = - static_cast(cache.requestEntryNow(cacheKey)); + static_cast(objectCache.requestEntryNow(cacheKey)); QNetworkAuthenticationCredential *cred = auth->findClosestMatch(url.path()); - cache.releaseEntry(cacheKey); + objectCache.releaseEntry(cacheKey); return cred; } void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager) { - manager->d_func()->cache.clear(); + manager->d_func()->objectCache.clear(); } QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index c80613b..bcf9a2b 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -98,10 +98,12 @@ public: QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request); + // this is the cache for storing downloaded files QAbstractNetworkCache *networkCache; + QNetworkCookieJar *cookieJar; - QNetworkAccessCache cache; + #ifndef QT_NO_NETWORKPROXY QNetworkProxy proxy; QNetworkProxyFactory *proxyFactory; @@ -109,8 +111,12 @@ public: bool cookieJarCreated; - static inline QNetworkAccessCache *getCache(QNetworkAccessBackend *backend) - { return &backend->manager->cache; } + + // this cache can be used by individual backends to cache e.g. their TCP connections to a server + // and use the connections for multiple requests. + QNetworkAccessCache objectCache; + static inline QNetworkAccessCache *getObjectCache(QNetworkAccessBackend *backend) + { return &backend->manager->objectCache; } Q_AUTOTEST_EXPORT static void clearCache(QNetworkAccessManager *manager); Q_DECLARE_PUBLIC(QNetworkAccessManager) -- cgit v0.12 From de0b9a76f8903448caa8e8995084b4d153f5c888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 16:00:11 +0200 Subject: Remove two work-arounds in QGraphicsView::paintEvent. The accelerate scrolling work-around is fixed by: 8ebe882b077fffedc3ff80fb80d2e181d5e56ab8 The other case was trying to avoid doing expensive QRegion calculations when everything must be repainted anyways. However, it was not entirely correct to assume all paintEvents are triggered by GV itself. Anyways, we don't need it anymore :-) Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsview.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 715bf37..d354b49 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3233,10 +3233,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Determine the exposed region d->exposedRegion = event->region(); - if (!d->accelerateScrolling) - d->exposedRegion = viewport()->rect(); - else if (d->viewportUpdateMode == BoundingRectViewportUpdate) - d->exposedRegion = event->rect(); QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect(); // Set up the painter -- cgit v0.12 From 85f811b849f3b0e0b79e0f1b7bf41512d7f53414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 16:49:57 +0200 Subject: Reduce QTransform operations in QGraphicsView::paintEvent. The view is usually untransformed, and in that case there's no need to call QGraphicsView::viewportTransform() and QPainter::setWorldTransform(). Reviewed-by: Andreas --- src/gui/graphicsview/qgraphicsview.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index d354b49..5ed3a11 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3246,8 +3246,9 @@ void QGraphicsView::paintEvent(QPaintEvent *event) painter.setRenderHints(d->renderHints, true); // Set up viewport transform - const QTransform viewTransform = viewportTransform(); - painter.setWorldTransform(viewTransform); + const bool viewTransformed = isTransformed(); + if (viewTransformed) + painter.setWorldTransform(viewportTransform()); // Draw background if ((d->cacheMode & CacheBackground) @@ -3272,16 +3273,22 @@ void QGraphicsView::paintEvent(QPaintEvent *event) if (!d->backgroundPixmapExposed.isEmpty()) { QPainter backgroundPainter(&d->backgroundPixmap); backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); - backgroundPainter.setTransform(viewportTransform()); + if (viewTransformed) + backgroundPainter.setTransform(painter.worldTransform()); backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); drawBackground(&backgroundPainter, exposedSceneRect); d->backgroundPixmapExposed = QRegion(); } // Blit the background from the background pixmap - painter.setWorldTransform(QTransform()); - painter.drawPixmap(QPoint(), d->backgroundPixmap); - painter.setWorldTransform(viewTransform); + if (viewTransformed) { + const QTransform viewTransform = painter.worldTransform(); + painter.setWorldTransform(QTransform()); + painter.drawPixmap(QPoint(), d->backgroundPixmap); + painter.setWorldTransform(viewTransform); + } else { + painter.drawPixmap(QPoint(), d->backgroundPixmap); + } } else { if (!(d->optimizationFlags & DontSavePainterState)) painter.save(); @@ -3292,7 +3299,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Items if (!(d->optimizationFlags & IndirectPainting)) { - d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion, + d->scene->d_func()->drawSubtreeRecursive(0, &painter, painter.worldTransform(), &d->exposedRegion, viewport(), 0); } else { // Find all exposed items @@ -3304,8 +3311,10 @@ void QGraphicsView::paintEvent(QPaintEvent *event) 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); + for (int i = 0; i < numItems; ++i) { + itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painter.worldTransform(), + d->exposedRegion, allItems); + } // Draw the items. drawItems(&painter, numItems, itemArray, styleOptionArray); d->freeStyleOptionsArray(styleOptionArray); -- cgit v0.12 From 2b7765b82720e844ec815d3f4fe84cd59624576e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 18:03:43 +0200 Subject: Sometimes broken transforms in GV. Broken after: 85f811b849f3b0e0b79e0f1b7bf41512d7f53414 QPainter::worldTransform returns a const reference(!) so we have to make a copy. --- src/gui/graphicsview/qgraphicsview.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 5ed3a11..fb1a822 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -3249,6 +3249,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) const bool viewTransformed = isTransformed(); if (viewTransformed) painter.setWorldTransform(viewportTransform()); + const QTransform viewTransform = painter.worldTransform(); // Draw background if ((d->cacheMode & CacheBackground) @@ -3274,7 +3275,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) QPainter backgroundPainter(&d->backgroundPixmap); backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip); if (viewTransformed) - backgroundPainter.setTransform(painter.worldTransform()); + backgroundPainter.setTransform(viewTransform); backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source); drawBackground(&backgroundPainter, exposedSceneRect); d->backgroundPixmapExposed = QRegion(); @@ -3282,7 +3283,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Blit the background from the background pixmap if (viewTransformed) { - const QTransform viewTransform = painter.worldTransform(); painter.setWorldTransform(QTransform()); painter.drawPixmap(QPoint(), d->backgroundPixmap); painter.setWorldTransform(viewTransform); @@ -3299,7 +3299,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) // Items if (!(d->optimizationFlags & IndirectPainting)) { - d->scene->d_func()->drawSubtreeRecursive(0, &painter, painter.worldTransform(), &d->exposedRegion, + d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion, viewport(), 0); } else { // Find all exposed items @@ -3312,7 +3312,7 @@ void QGraphicsView::paintEvent(QPaintEvent *event) 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], painter.worldTransform(), + itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems); } // Draw the items. -- cgit v0.12 From 08c80cc1bc50f9f2990f0fc459f09d2b554bce08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 20:35:25 +0200 Subject: Speedup QGraphicsScenePrivate::processDirtyItemsRecursive Don't calculate dirty scene transforms for invisible items. --- src/gui/graphicsview/qgraphicsscene.cpp | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index e89d80f..7dbe6d9 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5307,24 +5307,27 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool { 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; - } - bool wasDirtyParentViewBoundingRects = false; + bool wasDirtyParentSceneTransform = false; qreal opacity = parentOpacity; + if (item) { wasDirtyParentViewBoundingRects = item->d_ptr->paintedViewBoundingRectsNeedRepaint; opacity = item->d_ptr->combineOpacityFromParent(parentOpacity); - if ((!item->d_ptr->ignoreVisible && !item->d_ptr->visible) - || (!item->d_ptr->ignoreOpacity && opacity == 0.0) - || (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)) { + const bool itemIsHidden = !item->d_ptr->ignoreVisible && !item->d_ptr->visible; + const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity == 0.0; + + if (item->d_ptr->dirtySceneTransform && !itemIsHidden && !item->d_ptr->itemIsUntransformable() + && !(itemIsFullyTransparent && item->d_ptr->childrenCombineOpacity())) { + // Calculate the full scene transform for this item. + 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; + } + + if (itemIsHidden || itemIsFullyTransparent || (item->d_ptr->flags & QGraphicsItem::ItemHasNoContents)) { // Make sure we don't process invisible items or items with no content. item->d_ptr->dirty = 0; item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0; -- cgit v0.12 From e920c83084b48db7fe1925c7b98e34794eec6d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 21:34:59 +0200 Subject: Speedup QGraphicsScenePrivate::processDirtyItemsRecursive Avoid QTransform copy in common case. --- src/gui/graphicsview/qgraphicsitem_p.h | 9 +++++++++ src/gui/graphicsview/qgraphicsscene.cpp | 24 +++++++++++------------- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index ce74b4f..b7fb122 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -55,6 +55,7 @@ #include "qgraphicsitem.h" #include "qpixmapcache.h" +#include "qgraphicsview_p.h" #include @@ -365,6 +366,14 @@ public: || (childrenCombineOpacity() && isFullyTransparent()); } + inline bool updateHelper(QGraphicsViewPrivate *view, const QRectF &rect, const QTransform &xform) const + { + Q_ASSERT(view); + if (hasBoundingRegionGranularity) + return view->updateRegion(xform.map(QRegion(rect.toRect()))); + return view->updateRect(xform.mapRect(rect).toRect()); + } + inline QTransform transformToParent() const; QPainterPath cachedClipPath; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7dbe6d9..3f4bdde 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5395,21 +5395,19 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool 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) { - if (!viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect())))) - paintedViewBoundingRect = QRect(); + bool valid = false; + if (untransformableItem) { + valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect, + item->deviceTransform(view->viewportTransform())); + } else if (!view->isTransformed()) { + valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect, item->d_ptr->sceneTransform); } else { - if (!viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect())) - paintedViewBoundingRect = QRect(); + QTransform deviceTransform = item->d_ptr->sceneTransform; + deviceTransform *= view->viewportTransform(); + valid = !item->d_ptr->updateHelper(viewPrivate, dirtyRect, deviceTransform); } + if (!valid) + paintedViewBoundingRect = QRect(); } } } -- cgit v0.12 From f5d119bf15e248634ef02437ffd9b77755262f00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Wed, 17 Jun 2009 22:05:28 +0200 Subject: Small optimization to QGraphicsScenePrivate::drawSubtreeRecursive. We save three function calls by calling item->paint() directly. --- src/gui/graphicsview/qgraphicsscene.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 3f4bdde..71a4f08 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5206,7 +5206,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (clipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); painter->setOpacity(opacity); - drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); + + if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget) + item->paint(painter, &styleOptionTmp, widget); + else + drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection); if (savePainter) painter->restore(); -- cgit v0.12 From 7d6da125cb94f70f2b14b60c87ded71876e28149 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 17 Jun 2009 17:31:23 -0700 Subject: Fix a couple of issues after QPixmapData optims Make sure we always set w, h and d. See fa8030a935acaacee570eee320e7510a4cfdc853 Reviewed-by: TrustMe --- .../gfxdrivers/directfb/qdirectfbpaintdevice.cpp | 10 +++------ .../gfxdrivers/directfb/qdirectfbpixmap.cpp | 25 +++++++++++++--------- .../gfxdrivers/directfb/qdirectfbscreen.cpp | 7 +----- src/plugins/gfxdrivers/directfb/qdirectfbscreen.h | 1 + 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp index 52f6a37..905fec3 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp @@ -129,18 +129,14 @@ int QDirectFBPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const if (!dfbSurface) return 0; - int w, h; - dfbSurface->GetSize(dfbSurface, &w, &h); - switch (metric) { case QPaintDevice::PdmWidth: - return w; case QPaintDevice::PdmHeight: - return h; + return (metric == PdmWidth ? size().width() : size().height()); case QPaintDevice::PdmWidthMM: - return (w * 1000) / dotsPerMeterX(); + return (size().width() * 1000) / dotsPerMeterX(); case QPaintDevice::PdmHeightMM: - return (h * 1000) / dotsPerMeterY(); + return (size().height() * 1000) / dotsPerMeterY(); case QPaintDevice::PdmPhysicalDpiX: case QPaintDevice::PdmDpiX: return (dotsPerMeterX() * 254) / 10000; // 0.0254 meters-per-inch diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index c239248..1c86466 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -72,9 +72,10 @@ void QDirectFBPixmapData::resize(int width, int height) } format = screen->pixelFormat(); - dfbSurface = QDirectFBScreen::instance()->createDFBSurface(QSize(width, height), - format, - QDirectFBScreen::TrackSurface); + dfbSurface = screen->createDFBSurface(QSize(width, height), + format, + QDirectFBScreen::TrackSurface); + d = screen->depth(); alpha = false; if (!dfbSurface) { invalidate(); @@ -195,8 +196,8 @@ void QDirectFBPixmapData::fromImage(const QImage &i, invalidate(); return; } - w = metric(QPaintDevice::PdmWidth); - h = metric(QPaintDevice::PdmHeight); + w = img.width(); + h = img.height(); is_null = (w <= 0 || h <= 0); d = metric(QPaintDevice::PdmDepth); setSerialNumber(++global_ser_no); @@ -209,7 +210,8 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) return; } - IDirectFBSurface *src = static_cast(data)->directFBSurface(); + const QDirectFBPixmapData *otherData = static_cast(data); + IDirectFBSurface *src = otherData->directFBSurface(); alpha = data->hasAlphaChannel(); format = (alpha ? QDirectFBScreen::instance()->alphaPixmapFormat() @@ -232,6 +234,9 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect) } const DFBRectangle blitRect = { rect.x(), rect.y(), rect.width(), rect.height() }; + w = rect.width(); + h = rect.height(); + d = otherData->d; DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0); #if (Q_DIRECTFB_VERSION >= 0x010000) dfbSurface->ReleaseSource(dfbSurface); @@ -303,9 +308,6 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, return QPixmap(data); } - int w, h; - dfbSurface->GetSize(dfbSurface, &w, &h); - const QSize size = transform.mapRect(QRect(0, 0, w, h)).size(); if (size.isEmpty()) return QPixmap(); @@ -326,6 +328,8 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform, const DFBRectangle destRect = { 0, 0, size.width(), size.height() }; data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect); + data->w = size.width(); + data->h = size.height(); #if (Q_DIRECTFB_VERSION >= 0x010000) data->dfbSurface->ReleaseSource(data->dfbSurface); #endif @@ -338,7 +342,7 @@ QImage QDirectFBPixmapData::toImage() const return QImage(); #ifndef QT_NO_DIRECTFB_PREALLOCATED - QImage ret(size(), QDirectFBScreen::getImageFormat(dfbSurface)); + QImage ret(w, h, QDirectFBScreen::getImageFormat(dfbSurface)); if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) { if (hasAlphaChannel()) { imgSurface->SetBlittingFlags(imgSurface, DSBLIT_BLEND_ALPHACHANNEL); @@ -387,6 +391,7 @@ void QDirectFBPixmapData::invalidate() { setSerialNumber(0); alpha = false; + d = w = h = 0; format = QImage::Format_Invalid; } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 5d89994..62fef5b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -751,12 +751,7 @@ QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType typ return new QDirectFBPixmapData(type); } -#ifdef QT_NO_DEBUG -struct FlagDescription; -static const FlagDescription *accelerationDescriptions = 0; -static const FlagDescription *blitDescriptions = 0; -static const FlagDescription *drawDescriptions = 0; -#else +#ifndef QT_NO_DEBUG struct FlagDescription { const char *name; uint flag; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index c2c9a59..4239156 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -118,6 +118,7 @@ public: SurfaceCreationOptions options); void releaseDFBSurface(IDirectFBSurface *surface); + using QScreen::depth; static int depth(DFBSurfacePixelFormat format); static DFBSurfacePixelFormat getSurfacePixelFormat(QImage::Format format); -- cgit v0.12 From 7e8008cdd707d4ea3504df4ad02a4589c7b16510 Mon Sep 17 00:00:00 2001 From: David Faure Date: Thu, 18 Jun 2009 08:27:37 +0200 Subject: Fix nasty qt3-qt4 porting trap: for a QStringList, lst.remove(lst.at(idx)) used to only remove one item in Qt3, while it removes all occurrences of the item in Qt4 (remove==removeAll). To catch it I commented out remove(T) in my qlist.h, which caught this. Reviewed-by: Friedemann Kleint --- tools/qtconfig/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/qtconfig/mainwindow.cpp b/tools/qtconfig/mainwindow.cpp index eabaec6..a59f790 100644 --- a/tools/qtconfig/mainwindow.cpp +++ b/tools/qtconfig/mainwindow.cpp @@ -829,7 +829,7 @@ void MainWindow::removeSubstitute() int item = sublistbox->currentItem(); QStringList subs = QFont::substitutes(familysubcombo->currentText()); - subs.remove(subs.at(sublistbox->currentItem())); + subs.removeAt(sublistbox->currentItem()); sublistbox->clear(); sublistbox->insertStringList(subs); if (uint(item) > sublistbox->count()) @@ -909,7 +909,7 @@ void MainWindow::removeFontpath() return; int item = fontpathlistbox->currentItem(); - fontpaths.remove(fontpaths.at(fontpathlistbox->currentItem())); + fontpaths.removeAt(fontpathlistbox->currentItem()); fontpathlistbox->clear(); fontpathlistbox->insertStringList(fontpaths); if (uint(item) > fontpathlistbox->count()) -- cgit v0.12 From 578dd524b62b0f76fdd205e30102b374c48f21e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Thu, 18 Jun 2009 11:07:55 +0200 Subject: Use the unified toolbar on Mac. --- examples/graphicsview/diagramscene/mainwindow.cpp | 1 + examples/webkit/fancybrowser/mainwindow.cpp | 1 + examples/webkit/formextractor/mainwindow.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/examples/graphicsview/diagramscene/mainwindow.cpp b/examples/graphicsview/diagramscene/mainwindow.cpp index ad8006e..4783280 100644 --- a/examples/graphicsview/diagramscene/mainwindow.cpp +++ b/examples/graphicsview/diagramscene/mainwindow.cpp @@ -76,6 +76,7 @@ MainWindow::MainWindow() setCentralWidget(widget); setWindowTitle(tr("Diagramscene")); + setUnifiedTitleAndToolBarOnMac(true); } //! [0] diff --git a/examples/webkit/fancybrowser/mainwindow.cpp b/examples/webkit/fancybrowser/mainwindow.cpp index 9f899b4..6d477db 100644 --- a/examples/webkit/fancybrowser/mainwindow.cpp +++ b/examples/webkit/fancybrowser/mainwindow.cpp @@ -94,6 +94,7 @@ MainWindow::MainWindow() toolsMenu->addAction(tr("Remove all embedded elements"), this, SLOT(removeEmbeddedElements())); setCentralWidget(view); + setUnifiedTitleAndToolBarOnMac(true); } //! [3] diff --git a/examples/webkit/formextractor/mainwindow.cpp b/examples/webkit/formextractor/mainwindow.cpp index bc92f85..f774737 100644 --- a/examples/webkit/formextractor/mainwindow.cpp +++ b/examples/webkit/formextractor/mainwindow.cpp @@ -48,6 +48,7 @@ MainWindow::MainWindow() createMenus(); centralWidget = new FormExtractor(this); setCentralWidget(centralWidget); + setUnifiedTitleAndToolBarOnMac(true); } void MainWindow::createActions() -- cgit v0.12 From a22578e1fe0070442d4f7f5eae5187e32bc58ecd Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Thu, 18 Jun 2009 11:13:13 +0200 Subject: Doc: Resolved merge conflict in state machine overview Reviewed-by: Trust Me --- doc/src/statemachine.qdoc | 141 ++++++---------------------------------------- 1 file changed, 16 insertions(+), 125 deletions(-) diff --git a/doc/src/statemachine.qdoc b/doc/src/statemachine.qdoc index c017827..d2b508d 100644 --- a/doc/src/statemachine.qdoc +++ b/doc/src/statemachine.qdoc @@ -85,36 +85,20 @@ The following snippet shows the code needed to create such a state machine. First, we create the state machine and states: - \code - QStateMachine machine; - QState *s1 = new QState(); - QState *s2 = new QState(); - QState *s3 = new QState(); - \endcode + \snippet doc/src/snippets/statemachine/main.cpp 0 Then, we create the transitions by using the QState::addTransition() function: - \code - s1->addTransition(button, SIGNAL(clicked()), s2); - s2->addTransition(button, SIGNAL(clicked()), s3); - s3->addTransition(button, SIGNAL(clicked()), s1); - \endcode + \snippet doc/src/snippets/statemachine/main.cpp 1 Next, we add the states to the machine and set the machine's initial state: - \code - machine.addState(s1); - machine.addState(s2); - machine.addState(s3); - machine.setInitialState(s1); - \endcode + \snippet doc/src/snippets/statemachine/main.cpp 2 Finally, we start the state machine: - \code - machine.start(); - \endcode + \snippet doc/src/snippets/statemachine/main.cpp 3 The state machine executes asynchronously, i.e. it becomes part of your application's event loop. @@ -127,11 +111,7 @@ entered. In the following snippet, the value that should be assigned to a QLabel's text property is specified for each state: - \code - s1->assignProperty(label, "text", "In state s1"); - s2->assignProperty(label, "text", "In state s2"); - s3->assignProperty(label, "text", "In state s3"); - \endcode + \snippet doc/src/snippets/statemachine/main.cpp 4 When any of the states is entered, the label's text will be changed accordingly. @@ -142,10 +122,7 @@ state \c s3 is entered, and the button's showMinimized() slot will be called when \c s3 is exited: - \code - QObject::connect(s3, SIGNAL(entered()), button, SLOT(showMaximized())); - QObject::connect(s3, SIGNAL(exited()), button, SLOT(showMinimized())); - \endcode + \snippet doc/src/snippets/statemachine/main.cpp 5 Custom states can reimplement QAbstractState::onEntry() and QAbstractState::onExit(). @@ -194,22 +171,9 @@ initial one (i.e. which child state the state machine should enter when the parent state is the target of a transition). - \code - QState *s1 = new QState(); - QState *s11 = new QState(s1); - QState *s12 = new QState(s1); - QState *s13 = new QState(s1); - s1->setInitialState(s11); - machine.addState(s1); - \endcode + \snippet doc/src/snippets/statemachine/main2.cpp 0 - \code - QFinalState *s2 = new QFinalState(); - s1->addTransition(quitButton, SIGNAL(clicked()), s2); - machine.addState(s2); - - QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit())); - \endcode + \snippet doc/src/snippets/statemachine/main2.cpp 1 In this case we want the application to quit when the state machine is finished, so the machine's finished() signal is connected to the @@ -219,9 +183,7 @@ following code adds a transition that effectively causes the Quit button to be ignored when the state machine is in state \c s12. - \code - s12>addTransition(quitButton, SIGNAL(clicked()), s12); - \endcode + \snippet doc/src/snippets/statemachine/main2.cpp 2 A transition can have any state as its target, i.e. the target state does not have to be on the same level in the state hierarchy as the source state. @@ -259,21 +221,7 @@ simply display a message box when \c s3 is entered, then immediately return to the previous child state of \c s1 via the history state. - \code - QHistoryState *s1h = s1->addHistoryState(); - - QState *s3 = new QState(); - s3->assignProperty(label, "text", "In s3"); - QMessageBox mbox; - mbox.addButton(QMessageBox::Ok); - mbox.setText("Interrupted!"); - mbox.setIcon(QMessageBox::Information); - QObject::connect(s3, SIGNAL(entered()), &mbox, SLOT(exec())); - s3->addTransition(s1h); - machine.addState(s3); - - s1->addTransition(interruptButton, SIGNAL(clicked()), s3); - \endcode + \snippet doc/src/snippets/statemachine/main2.cpp 3 \section1 Using Parallel States to Avoid a Combinatorial Explosion of States @@ -305,12 +253,7 @@ To create a parallel state group, pass QState::ParallelStates to the QState constructor. - \code - QState *s1 = new QState(QState::ParallelStates); - // s11 and s12 will be entered in parallel - QState *s11 = new QState(s1); - QState *s12 = new QState(s1); - \endcode + \snippet doc/src/snippets/statemachine/main3.cpp 0 When a parallel state group is entered, all its child states will be simultaneously entered. Transitions within the individual child states @@ -334,9 +277,7 @@ finished(). We use a signal transition to cause this event to trigger a state change: - \code - s1->addTransition(s1, SIGNAL(finished()), s2); - \endcode + \snippet doc/src/snippets/statemachine/main3.cpp 1 Using final states in composite states is useful when you want to hide the internal details of a composite state; i.e. the only thing the outside world @@ -372,42 +313,12 @@ Here we define our own custom event type, \c StringEvent, for posting strings to the state machine: - \code - struct StringEvent : public QEvent - { - StringEvent(const QString &val) - : QEvent(QEvent::Type(QEvent::User+1)), - value(val) {} - - QString value; - }; - \endcode + \snippet doc/src/snippets/statemachine/main4.cpp 0 Next, we define a transition that only triggers when the event's string matches a particular string (a \e guarded transition): - \code - class StringTransition : public QAbstractTransition - { - public: - StringTransition(const QString &value) - : m_value(value) {} - - protected: - virtual bool eventTest(QEvent *e) const - { - if (e->type() != QEvent::Type(QEvent::User+1)) // StringEvent - return false; - StringEvent *se = static_cast(e); - return (m_value == se->value); - } - - virtual void onTransition(QEvent *) {} - - private: - QString m_value; - }; - \endcode + \snippet doc/src/snippets/statemachine/main4.cpp 1 In the eventTest() reimplementation, we first check if the event type is the desired one; if so, we cast the event to a StringEvent and perform the @@ -422,31 +333,11 @@ Here's what the implementation of the statechart looks like: - \code - QStateMachine machine; - QState *s1 = new QState(); - QState *s2 = new QState(); - QFinalState *done = new QFinalState(); - - StringTransition *t1 = new StringTransition("Hello"); - t1->setTargetState(s2); - s1->addTransition(t1); - StringTransition *t2 = new StringTransition("world"); - t2->setTargetState(done); - s2->addTransition(t2); - - machine.addState(s1); - machine.addState(s2); - machine.addState(done); - machine.setInitialState(s1); - \endcode + \snippet doc/src/snippets/statemachine/main4.cpp 2 Once the machine is started, we can post events to it. - \code - machine.postEvent(new StringEvent("Hello")); - machine.postEvent(new StringEvent("world")); - \endcode + \snippet doc/src/snippets/statemachine/main4.cpp 3 An event that is not handled by any relevant transition will be silently consumed by the state machine. It can be useful to group states and provide -- cgit v0.12 From 3af96d2fc56dffc5891f162de5daa3a804d9a91d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 18 Jun 2009 11:15:03 +0200 Subject: Remove wrong negation. I changed the logic in e920c83084b48db7fe1925c7b98e34794eec6d55 and this negation incidentally snuck in. --- src/gui/graphicsview/qgraphicsscene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 71a4f08..15e8742 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5408,7 +5408,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool } else { QTransform deviceTransform = item->d_ptr->sceneTransform; deviceTransform *= view->viewportTransform(); - valid = !item->d_ptr->updateHelper(viewPrivate, dirtyRect, deviceTransform); + valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect, deviceTransform); } if (!valid) paintedViewBoundingRect = QRect(); -- cgit v0.12 From e9247f1da01f20ecd9e70b47286e7eb68bae892a Mon Sep 17 00:00:00 2001 From: mae Date: Thu, 18 Jun 2009 11:52:54 +0200 Subject: Fix accidental selection of popup items under the mouse in QComboBox If the widget under mouse is hidden, Qt can generate a synthetic mouse move event which gets delivered to the already hidden widget. This can then result in the wrong item being selected. Workaround: in QListView, ignore mouse move events when the widget is hidden. Reviewed-by: Denis --- src/gui/itemviews/qlistview.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index 9b25730..f1b0d19 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -827,6 +827,8 @@ void QListView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int e */ void QListView::mouseMoveEvent(QMouseEvent *e) { + if (!isVisible()) + return; Q_D(QListView); QAbstractItemView::mouseMoveEvent(e); if (state() == DragSelectingState -- cgit v0.12 From a9e11b46bdcbc93d89078f0fcca1e7ac91975ffc Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Thu, 18 Jun 2009 12:08:45 +0200 Subject: doc: Added explanation of QStringBuilder in QString The QStringBuilder class documentation is marked \internal. A section has been added to the documentation for QString that explains how to use the reimplemented '%' operator of QStringBuilder to obtain more efficient string concatenation operations. --- doc/src/snippets/qstring/stringbuilder.cpp | 28 ++++++++++++ src/corelib/tools/qstring.cpp | 68 ++++++++++++++++++++++++++++++ src/corelib/tools/qstringbuilder.cpp | 2 + 3 files changed, 98 insertions(+) create mode 100644 doc/src/snippets/qstring/stringbuilder.cpp diff --git a/doc/src/snippets/qstring/stringbuilder.cpp b/doc/src/snippets/qstring/stringbuilder.cpp new file mode 100644 index 0000000..90803e2 --- /dev/null +++ b/doc/src/snippets/qstring/stringbuilder.cpp @@ -0,0 +1,28 @@ + +//! [0] + QString foo; + QString type = "long"; + + foo->setText(QLatin1String("vector<") + type + QLatin1String(">::iterator")); + + if (foo.startsWith("(" + type + ") 0x")) + ... +//! [0] + +//! [3] + #define QT_USE_FAST_CONCATENATION +//! [3] + +//! [4] + #define QT_USE_FAST_CONCATENATION + #define QT_USE_FAST_OPERATOR_PLUS +//! [4] + +//! [5] + #include + + QString hello("hello"); + QStringRef el(&hello, 2, 3); + QLatin1String world("world"); + QString message = hello % el % world % QChar('!'); +//! [5] diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index ced6dd5..3b70f44 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -663,6 +663,74 @@ const QString::Null QString::null = { }; formats, the \e precision represents the maximum number of significant digits (trailing zeroes are omitted). + \section1 More Efficient String Construction + + Using the QString \c{'+'} operator, it is easy to construct a + complex string from multiple substrings. You will often write code + like this: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 0 + + There is nothing wrong with either of these string constructions, + but there are a few hidden inefficiencies. Beginning with Qt 4.6, + you can eliminate them. + + First, multiple uses of the \c{'+'} operator usually means + multiple memory allocations. When concatenating \e{n} substrings, + where \e{n > 2}, there can be as many as \e{n - 1} calls to the + memory allocator. + + Second, QLatin1String does not store its length internally but + calls qstrlen() when it needs to know its length. + + In 4.6, an internal template class \c{QStringBuilder} has been + added along with a few helper functions. This class is marked + internal and does not appear in the documentation, because you + aren't meant to instantiate it in your code. Its use will be + automatic, as described below. The class is found in + \c {src/corelib/tools/qstringbuilder.cpp} if you want to have a + look at it. + + \c{QStringBuilder} uses expression templates and reimplements the + \c{'%'} operator so that when you use \c{'%'} for string + concatenation instead of \c{'+'}, multiple substring + concatenations will be postponed until the final result is about + to be assigned to a QString. At this point, the amount of memory + required for the final result is known. The memory allocator is + then called \e{once} to get the required space, and the substrings + are copied into it one by one. + + \c{QLatin1Literal} is a second internal class that can replace + QLatin1String, which can't be changed for compatibility reasons. + \c{QLatin1Literal} stores its length, thereby saving time when + \c{QStringBuilder} computes the amount of memory required for the + final string. + + Additional efficiency is gained by inlining and reduced reference + counting (the QString created from a \c{QStringBuilder} typically + has a ref count of 1, whereas QString::append() needs an extra + test). + + There are three ways you can access this improved method of string + construction. The straightforward way is to include + \c{QStringBuilder} wherever you want to use it, and use the + \c{'%'} operator instead of \c{'+'} when concatenating strings: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 5 + + A more global approach is to include this define: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 3 + + and use \c{'%'} instead of \c{'+'} for string concatenation + everywhere. The third approach, which is the most convenient but + not entirely source compatible, is to include two defines: + + \snippet doc/src/snippets/qstring/stringbuilder.cpp 4 + + and the \c{'+'} will automatically be performed as the + \c{QStringBuilder} \c{'%'} everywhere. + \sa fromRawData(), QChar, QLatin1String, QByteArray, QStringRef */ diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp index 17e2cec..fbb784e 100644 --- a/src/corelib/tools/qstringbuilder.cpp +++ b/src/corelib/tools/qstringbuilder.cpp @@ -43,6 +43,7 @@ /*! \class QLatin1Literal + \internal \reentrant \since 4.6 @@ -83,6 +84,7 @@ /*! \class QStringBuilder + \internal \reentrant \since 4.6 -- cgit v0.12 From c38ece31d036cf2216392dda9c96736eabcb0f34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Thu, 18 Jun 2009 12:13:44 +0200 Subject: Compile on MSVC. The QtSVG module failed to link because it includes qgraphicsitem_p.h, which had an inlined function (updateHelper) that called an undeclared function (QGraphicViewPrivate::update(Region|Rect))...Resulting in unresolved symbols. Reviewed-by: MariusSO --- src/gui/graphicsview/qgraphicsitem_p.h | 8 -------- src/gui/graphicsview/qgraphicsscene.cpp | 18 ++++++++++++++---- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index b7fb122..b9e7041 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -366,14 +366,6 @@ public: || (childrenCombineOpacity() && isFullyTransparent()); } - inline bool updateHelper(QGraphicsViewPrivate *view, const QRectF &rect, const QTransform &xform) const - { - Q_ASSERT(view); - if (hasBoundingRegionGranularity) - return view->updateRegion(xform.map(QRegion(rect.toRect()))); - return view->updateRect(xform.mapRect(rect).toRect()); - } - inline QTransform transformToParent() const; QPainterPath cachedClipPath; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 15e8742..d9d31ef 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5306,6 +5306,16 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b } } +static inline bool updateHelper(QGraphicsViewPrivate *view, QGraphicsItemPrivate *item, + const QRectF &rect, const QTransform &xform) +{ + Q_ASSERT(view); + Q_ASSERT(item); + if (item->hasBoundingRegionGranularity) + return view->updateRegion(xform.map(QRegion(rect.toRect()))); + return view->updateRect(xform.mapRect(rect).toRect()); +} + void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren, qreal parentOpacity) { @@ -5401,14 +5411,14 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool bool valid = false; if (untransformableItem) { - valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect, - item->deviceTransform(view->viewportTransform())); + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, + item->deviceTransform(view->viewportTransform())); } else if (!view->isTransformed()) { - valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect, item->d_ptr->sceneTransform); + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, item->d_ptr->sceneTransform); } else { QTransform deviceTransform = item->d_ptr->sceneTransform; deviceTransform *= view->viewportTransform(); - valid = item->d_ptr->updateHelper(viewPrivate, dirtyRect, deviceTransform); + valid = updateHelper(viewPrivate, item->d_ptr, dirtyRect, deviceTransform); } if (!valid) paintedViewBoundingRect = QRect(); -- cgit v0.12 From cab70bbf1d29a7cdf81d561fdd74e16f7280c689 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 18 Jun 2009 11:23:24 +0200 Subject: Autotests: fix compile issue on hpux --- tests/auto/modeltest/modeltest.cpp | 4 ++-- tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro | 1 + tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro | 1 + tests/auto/qstatemachine/tst_qstatemachine.cpp | 10 +++++----- tests/auto/qtabbar/tst_qtabbar.cpp | 2 +- tests/auto/windowsmobile/test/tst_windowsmobile.cpp | 2 ++ 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/tests/auto/modeltest/modeltest.cpp b/tests/auto/modeltest/modeltest.cpp index 68b723f..c4cc820 100644 --- a/tests/auto/modeltest/modeltest.cpp +++ b/tests/auto/modeltest/modeltest.cpp @@ -475,7 +475,7 @@ void ModelTest::data() void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end ) { // Q_UNUSED(end); - qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).value() + qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); Changing c; @@ -496,7 +496,7 @@ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) Changing c = insert.pop(); Q_ASSERT ( c.parent == parent ); qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize - << "parent=" << model->data ( parent ).value() << "current rowcount of parent=" << model->rowCount ( parent ); + << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); for (int ii=start; ii <= end; ii++) { diff --git a/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro b/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro index bc750c5..3283873 100644 --- a/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro +++ b/tests/auto/qhttpnetworkconnection/qhttpnetworkconnection.pro @@ -1,4 +1,5 @@ load(qttest_p4) SOURCES += tst_qhttpnetworkconnection.cpp +INCLUDEPATH += $$(QTDIR)/src/3rdparty/zlib QT = core network diff --git a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro index 9593c55..0755055 100644 --- a/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro +++ b/tests/auto/qhttpnetworkreply/qhttpnetworkreply.pro @@ -1,4 +1,5 @@ load(qttest_p4) SOURCES += tst_qhttpnetworkreply.cpp +INCLUDEPATH += $$(QTDIR)/src/3rdparty/zlib QT = core network diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 6040abd..b39f0a1 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -413,7 +413,7 @@ void tst_QStateMachine::customGlobalErrorState() machine.start(); QCoreApplication::processEvents(); - QCOMPARE(machine.errorState(), customErrorState); + QCOMPARE(machine.errorState(), static_cast(customErrorState)); QCOMPARE(machine.configuration().count(), 1); QVERIFY(machine.configuration().contains(initialState)); @@ -1724,18 +1724,18 @@ void tst_QStateMachine::signalTransitions() QStateMachine machine; QState *s0 = new QState(machine.rootState()); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: sender cannot be null"); - QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QAbstractTransition*)0); + QCOMPARE(s0->addTransition(0, SIGNAL(noSuchSignal()), 0), (QSignalTransition*)0); SignalEmitter emitter; QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: signal cannot be null"); - QCOMPARE(s0->addTransition(&emitter, 0, 0), (QAbstractTransition*)0); + QCOMPARE(s0->addTransition(&emitter, 0, 0), (QSignalTransition*)0); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: cannot add transition to null state"); - QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QAbstractTransition*)0); + QCOMPARE(s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), 0), (QSignalTransition*)0); QFinalState *s1 = new QFinalState(machine.rootState()); QTest::ignoreMessage(QtWarningMsg, "QState::addTransition: no such signal SignalEmitter::noSuchSignal()"); - QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QAbstractTransition*)0); + QCOMPARE(s0->addTransition(&emitter, SIGNAL(noSuchSignal()), s1), (QSignalTransition*)0); QSignalTransition *trans = s0->addTransition(&emitter, SIGNAL(signalWithNoArg()), s1); QVERIFY(trans != 0); diff --git a/tests/auto/qtabbar/tst_qtabbar.cpp b/tests/auto/qtabbar/tst_qtabbar.cpp index 29f42df..f908d3f 100644 --- a/tests/auto/qtabbar/tst_qtabbar.cpp +++ b/tests/auto/qtabbar/tst_qtabbar.cpp @@ -370,7 +370,7 @@ void tst_QTabBar::tabButton() tabbar.setTabButton(0, position, button); - QCOMPARE(tabbar.tabButton(0, position), static_cast(button)); + QCOMPARE(tabbar.tabButton(0, position), static_cast(button)); QTRY_VERIFY(!button->isHidden()); QVERIFY(tabbar.tabButton(0, otherSide) == 0); QCOMPARE(button->parent(), static_cast(&tabbar)); diff --git a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp b/tests/auto/windowsmobile/test/tst_windowsmobile.cpp index 843974d..8c7c021 100644 --- a/tests/auto/windowsmobile/test/tst_windowsmobile.cpp +++ b/tests/auto/windowsmobile/test/tst_windowsmobile.cpp @@ -44,8 +44,10 @@ #include #include #include +#ifdef Q_OS_WINCE_WM #include #include +#endif -- cgit v0.12 From cc08a4d04894eace196631029731a3af37547b7f Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Thu, 18 Jun 2009 12:39:46 +0200 Subject: QMenuBar: fixed highlight problem on actions without menu An item without menu could stay highlighted even when the mouse left the menu bar. Task-number: 256322 Reviewed-by: alexis --- src/gui/widgets/qmenubar.cpp | 3 ++- tests/auto/qmenubar/tst_qmenubar.cpp | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index 3857e30..34de252 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1253,7 +1253,8 @@ void QMenuBar::mouseMoveEvent(QMouseEvent *e) void QMenuBar::leaveEvent(QEvent *) { Q_D(QMenuBar); - if(!hasFocus() && !d->popupState) + if((!hasFocus() && !d->popupState) || + (d->currentAction && d->currentAction->menu() == 0)) d->setCurrentAction(0); } diff --git a/tests/auto/qmenubar/tst_qmenubar.cpp b/tests/auto/qmenubar/tst_qmenubar.cpp index 5404d46..8a38782 100644 --- a/tests/auto/qmenubar/tst_qmenubar.cpp +++ b/tests/auto/qmenubar/tst_qmenubar.cpp @@ -149,6 +149,7 @@ private slots: void check_shortcutPress(); void check_menuPosition(); void task223138_triggered(); + void task256322_highlight(); #if defined(QT3_SUPPORT) void indexBasedInsertion_data(); @@ -1520,6 +1521,41 @@ void tst_QMenuBar::task223138_triggered() QCOMPARE(submenuSpy.count(), 1); } +void tst_QMenuBar::task256322_highlight() +{ + QMainWindow win; + QMenu menu; + QAction *file = win.menuBar()->addMenu(&menu); + file->setText("file"); + QMenu menu2; + QAction *file2 = win.menuBar()->addMenu(&menu2); + file2->setText("file2"); + QAction *nothing = win.menuBar()->addAction("nothing"); + + win.show(); + + QTest::mouseClick(win.menuBar(), Qt::LeftButton, 0, win.menuBar()->actionGeometry(file).center()); + QVERIFY(menu.isVisible()); + QVERIFY(!menu2.isVisible()); + QCOMPARE(win.menuBar()->activeAction(), file); + + QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(file2).center()); + QVERIFY(!menu.isVisible()); + QVERIFY(menu2.isVisible()); + QCOMPARE(win.menuBar()->activeAction(), file2); + + QTest::mouseMove(win.menuBar(), win.menuBar()->actionGeometry(nothing).center()); + QVERIFY(!menu.isVisible()); + QVERIFY(!menu2.isVisible()); + QCOMPARE(win.menuBar()->activeAction(), nothing); + + QTest::mouseMove(&win, win.menuBar()->geometry().bottomLeft() + QPoint(1,1)); + + QVERIFY(!menu.isVisible()); + QVERIFY(!menu2.isVisible()); + QVERIFY(!win.menuBar()->activeAction()); +} + #if defined(QT3_SUPPORT) void tst_QMenuBar::indexBasedInsertion_data() -- cgit v0.12 From b11eb293ca873691e4a84afdf4e89ecf16ed03b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 18 Jun 2009 11:54:23 +0200 Subject: Added save state detection in OpenGL engine to avoid dirtying state. When setState() is called right after createState() it means that none of the OpenGL state needs changing, so we can simply return. Task-number: 254658 Reviewed-by: Trond --- src/opengl/qpaintengine_opengl.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 84ad4d5..044090b 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -662,6 +662,7 @@ public: , txop(QTransform::TxNone) , inverseScale(1) , moveToCount(0) + , last_created_state(0) , shader_ctx(0) , grad_palette(0) , drawable_texture(0) @@ -788,6 +789,8 @@ public: void updateGLMatrix() const; + mutable QPainterState *last_created_state; + QGLContext *shader_ctx; GLuint grad_palette; @@ -5502,6 +5505,13 @@ void QOpenGLPaintEngine::setState(QPainterState *s) { Q_D(QOpenGLPaintEngine); QPaintEngineEx::setState(s); + + // are we in a save() ? + if (s == d->last_created_state) { + d->last_created_state = 0; + return; + } + if (isActive()) { d->updateDepthClip(); penChanged(); @@ -5515,12 +5525,15 @@ void QOpenGLPaintEngine::setState(QPainterState *s) QPainterState *QOpenGLPaintEngine::createState(QPainterState *orig) const { + const Q_D(QOpenGLPaintEngine); + QOpenGLPaintEngineState *s; if (!orig) s = new QOpenGLPaintEngineState(); else s = new QOpenGLPaintEngineState(*static_cast(orig)); + d->last_created_state = s; return s; } -- cgit v0.12 From c23d4d6644bff2195fbb6aa84d3425dc2d31491a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Thu, 18 Jun 2009 12:10:12 +0200 Subject: Prevented unnecessary depth clip updates in OpenGL paint engine. Keep track of whether the depth clip has actually changed between states, so that when QPainter::restore() is called we don't call the potentially expensive updateDepthClip() function when not needed. Task-number: 254658 Reviewed-by: Trond --- src/opengl/qpaintengine_opengl.cpp | 10 +++++++++- src/opengl/qpaintengine_opengl_p.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 044090b..b594f5b 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -2222,6 +2222,8 @@ void QOpenGLPaintEnginePrivate::updateDepthClip() { Q_Q(QOpenGLPaintEngine); + ++q->state()->depthClipId; + glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); @@ -5504,6 +5506,9 @@ void QOpenGLPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) void QOpenGLPaintEngine::setState(QPainterState *s) { Q_D(QOpenGLPaintEngine); + QOpenGLPaintEngineState *new_state = static_cast(s); + QOpenGLPaintEngineState *old_state = state(); + QPaintEngineEx::setState(s); // are we in a save() ? @@ -5513,7 +5518,8 @@ void QOpenGLPaintEngine::setState(QPainterState *s) } if (isActive()) { - d->updateDepthClip(); + if (old_state->depthClipId != new_state->depthClipId) + d->updateDepthClip(); penChanged(); brushChanged(); opacityChanged(); @@ -5547,11 +5553,13 @@ QOpenGLPaintEngineState::QOpenGLPaintEngineState(QOpenGLPaintEngineState &other) clipRegion = other.clipRegion; hasClipping = other.hasClipping; fastClip = other.fastClip; + depthClipId = other.depthClipId; } QOpenGLPaintEngineState::QOpenGLPaintEngineState() { hasClipping = false; + depthClipId = 0; } QOpenGLPaintEngineState::~QOpenGLPaintEngineState() diff --git a/src/opengl/qpaintengine_opengl_p.h b/src/opengl/qpaintengine_opengl_p.h index 891cbd6..439782b 100644 --- a/src/opengl/qpaintengine_opengl_p.h +++ b/src/opengl/qpaintengine_opengl_p.h @@ -69,6 +69,7 @@ public: QRegion clipRegion; bool hasClipping; QRect fastClip; + uint depthClipId; }; class QOpenGLPaintEngine : public QPaintEngineEx -- cgit v0.12