From 29202f033c87b5efe305e606805a26c59886875b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Wed, 29 Jul 2009 18:13:24 +1000 Subject: Add CONSTANT attribute to Q_PROPERTY() This will be used by the declarative module to determine if a property lacking a NOTIFY signal is truly constant, or just missing a NOTIFY signal. Reviewed-by: Roberto Raggi --- doc/src/properties.qdoc | 6 ++++++ doc/src/snippets/code/doc_src_properties.qdoc | 3 ++- src/corelib/kernel/qmetaobject.cpp | 29 ++++++++++++++++++++++++++- src/corelib/kernel/qmetaobject.h | 2 ++ src/tools/moc/generator.cpp | 7 ++++++- src/tools/moc/moc.cpp | 23 +++++++++++++++++++++ src/tools/moc/moc.h | 3 ++- tests/auto/qmetaobject/tst_qmetaobject.cpp | 17 ++++++++++++++++ 8 files changed, 86 insertions(+), 4 deletions(-) diff --git a/doc/src/properties.qdoc b/doc/src/properties.qdoc index 5490dd0..cac5016 100644 --- a/doc/src/properties.qdoc +++ b/doc/src/properties.qdoc @@ -122,6 +122,12 @@ editable property for (checkable) buttons. Note that QItemDelegate gets and sets a widget's \c USER property. + \o The presence of the \c CONSTANT attibute indicates that the property + value is constant. For a given object instance, the READ method of a + constant property must return the same value every time it is called. This + constant value may be different for different instances of the object. A + constant property cannot have a WRTE method or a NOTIFY signal. + \endlist The \c READ, \c WRITE, and \c RESET functions can be inherited. diff --git a/doc/src/snippets/code/doc_src_properties.qdoc b/doc/src/snippets/code/doc_src_properties.qdoc index 377cc9c..64e5377 100644 --- a/doc/src/snippets/code/doc_src_properties.qdoc +++ b/doc/src/snippets/code/doc_src_properties.qdoc @@ -7,7 +7,8 @@ Q_PROPERTY(type name [DESIGNABLE bool] [SCRIPTABLE bool] [STORED bool] - [USER bool]) + [USER bool] + [CONSTANT]) //! [0] diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 08cecaf..fee2da9 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -159,7 +159,9 @@ enum PropertyFlags { ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000, - Notify = 0x00400000 + Notify = 0x00400000, + Dynamic = 0x00800000, + Constant = 0x00000400 }; enum MethodFlags { @@ -2439,6 +2441,31 @@ bool QMetaProperty::isUser(const QObject *object) const } /*! + \internal +*/ +bool QMetaProperty::isDynamic() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Dynamic; +} + +/*! + Returns true if the property is constant; otherwise returns false. + + A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute + is set. +*/ +bool QMetaProperty::isConstant() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Constant; +} + +/*! \obsolete Returns true if the property is editable for the given \a object; diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 000ba6e..73b52a9 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -187,6 +187,8 @@ public: bool isStored(const QObject *obj = 0) const; bool isEditable(const QObject *obj = 0) const; bool isUser(const QObject *obj = 0) const; + bool isDynamic() const; + bool isConstant() const; bool isFlagType() const; bool isEnumType() const; diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index b872dfd..e4086e6 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -66,7 +66,9 @@ enum PropertyFlags { ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000, - Notify = 0x00400000 + Notify = 0x00400000, + Dynamic = 0x00800000, + Constant = 0x00000400 }; enum MethodFlags { AccessPrivate = 0x00, @@ -597,6 +599,9 @@ void Generator::generateProperties() if (p.notifyId != -1) flags |= Notify; + if (p.constant) + flags |= Constant; + fprintf(out, " %4d, %4d, ", strreg(p.name), strreg(p.type)); diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 797595f..66012ca 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -908,6 +908,12 @@ void Moc::parseProperty(ClassDef *def) propDef.name = lexem(); while (test(IDENTIFIER)) { QByteArray l = lexem(); + + if (l[0] == 'C' && l == "CONSTANT") { + propDef.constant = true; + continue; + } + QByteArray v, v2; if (test(LPAREN)) { v = lexemUntil(RPAREN); @@ -963,6 +969,23 @@ void Moc::parseProperty(ClassDef *def) msg += " has no READ accessor function. The property will be invalid."; warning(msg.constData()); } + if (propDef.constant && !propDef.write.isNull()) { + QByteArray msg; + msg += "Property declaration "; + msg += propDef.name; + msg += " is both WRITEable and CONSTANT. CONSTANT will be ignored."; + propDef.constant = false; + warning(msg.constData()); + } + if (propDef.constant && !propDef.notify.isNull()) { + QByteArray msg; + msg += "Property declaration "; + msg += propDef.name; + msg += " is both NOTIFYable and CONSTANT. CONSTANT will be ignored."; + propDef.constant = false; + warning(msg.constData()); + } + if(!propDef.notify.isEmpty()) def->notifyableProperties++; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 9fa9ac2..494d53e 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -115,9 +115,10 @@ struct FunctionDef struct PropertyDef { - PropertyDef():notifyId(-1), gspec(ValueSpec){} + PropertyDef():notifyId(-1), constant(false), gspec(ValueSpec){} QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify; int notifyId; + bool constant; enum Specification { ValueSpec, ReferenceSpec, PointerSpec }; Specification gspec; bool stdCppSet() const { diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index dea0ffb..f4cff2b 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -108,6 +108,7 @@ class tst_QMetaObject : public QObject Q_PROPERTY(int value6 READ value6 NOTIFY value6Changed) Q_PROPERTY(MyStruct value7 READ value7 WRITE setVal7 NOTIFY value7Changed) Q_PROPERTY(int value8 READ value8 NOTIFY value8Changed) + Q_PROPERTY(int value9 READ value9 CONSTANT) public: enum EnumType { EnumType1 }; @@ -137,6 +138,8 @@ public: int value8() const { return 1; } + int value9() const { return 1; } + QList value4; QVariantList value5; @@ -159,6 +162,7 @@ private slots: void customPropertyType(); void checkScope(); void propertyNotify(); + void propertyConstant(); void stdSet(); void classInfo(); @@ -785,6 +789,19 @@ void tst_QMetaObject::propertyNotify() QCOMPARE(signal.signature(), (const char *)0); } +void tst_QMetaObject::propertyConstant() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("value8")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.isConstant()); + + prop = mo->property(mo->indexOfProperty("value9")); + QVERIFY(prop.isValid()); + QVERIFY(prop.isConstant()); +} + class ClassInfoTestObjectA : public QObject { Q_OBJECT -- cgit v0.12 From 7ebd2024f49bdaf798f0beaaa35946dfa890f276 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 16 Jul 2009 12:35:08 +1000 Subject: Add FINAL attribute to Q_PROPERTY() This will be used by the declarative module to optimize property bindings. Reviewed-by: Roberto Raggi --- doc/src/properties.qdoc | 5 +++++ doc/src/snippets/code/doc_src_properties.qdoc | 3 ++- src/corelib/kernel/qmetaobject.cpp | 17 ++++++++++++++++- src/corelib/kernel/qmetaobject.h | 1 + src/tools/moc/generator.cpp | 5 ++++- src/tools/moc/moc.cpp | 3 +++ src/tools/moc/moc.h | 3 ++- tests/auto/qmetaobject/tst_qmetaobject.cpp | 17 +++++++++++++++++ 8 files changed, 50 insertions(+), 4 deletions(-) diff --git a/doc/src/properties.qdoc b/doc/src/properties.qdoc index cac5016..2d03e91 100644 --- a/doc/src/properties.qdoc +++ b/doc/src/properties.qdoc @@ -128,6 +128,11 @@ constant value may be different for different instances of the object. A constant property cannot have a WRTE method or a NOTIFY signal. + \o The presence of the \c FINAL attribute indicates that the property + will not be overridden by a derived class. This can be used for performance + optimizations in some cases, but is not enforced by moc. Care must be taken + never to override a \c FINAL property. + \endlist The \c READ, \c WRITE, and \c RESET functions can be inherited. diff --git a/doc/src/snippets/code/doc_src_properties.qdoc b/doc/src/snippets/code/doc_src_properties.qdoc index 64e5377..3c9109f 100644 --- a/doc/src/snippets/code/doc_src_properties.qdoc +++ b/doc/src/snippets/code/doc_src_properties.qdoc @@ -8,7 +8,8 @@ Q_PROPERTY(type name [SCRIPTABLE bool] [STORED bool] [USER bool] - [CONSTANT]) + [CONSTANT] + [FINAL]) //! [0] diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index fee2da9..3b09061 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -161,7 +161,8 @@ enum PropertyFlags { ResolveUser = 0x00200000, Notify = 0x00400000, Dynamic = 0x00800000, - Constant = 0x00000400 + Constant = 0x00000400, + Final = 0x00000800 }; enum MethodFlags { @@ -2466,6 +2467,20 @@ bool QMetaProperty::isConstant() const } /*! + Returns true if the property is final; otherwise returns false. + + A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute + is set. +*/ +bool QMetaProperty::isFinal() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Final; +} + +/*! \obsolete Returns true if the property is editable for the given \a object; diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 73b52a9..bd47582 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -189,6 +189,7 @@ public: bool isUser(const QObject *obj = 0) const; bool isDynamic() const; bool isConstant() const; + bool isFinal() const; bool isFlagType() const; bool isEnumType() const; diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index e4086e6..fbc434d 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -68,7 +68,8 @@ enum PropertyFlags { ResolveUser = 0x00200000, Notify = 0x00400000, Dynamic = 0x00800000, - Constant = 0x00000400 + Constant = 0x00000400, + Final = 0x00000800 }; enum MethodFlags { AccessPrivate = 0x00, @@ -601,6 +602,8 @@ void Generator::generateProperties() if (p.constant) flags |= Constant; + if (p.final) + flags |= Final; fprintf(out, " %4d, %4d, ", strreg(p.name), diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 66012ca..aa11d0e 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -912,6 +912,9 @@ void Moc::parseProperty(ClassDef *def) if (l[0] == 'C' && l == "CONSTANT") { propDef.constant = true; continue; + } else if(l[0] == 'F' && l == "FINAL") { + propDef.final = true; + continue; } QByteArray v, v2; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 494d53e..767f84e 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -115,10 +115,11 @@ struct FunctionDef struct PropertyDef { - PropertyDef():notifyId(-1), constant(false), gspec(ValueSpec){} + PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec){} QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify; int notifyId; bool constant; + bool final; enum Specification { ValueSpec, ReferenceSpec, PointerSpec }; Specification gspec; bool stdCppSet() const { diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index f4cff2b..ac2858c 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -109,6 +109,7 @@ class tst_QMetaObject : public QObject Q_PROPERTY(MyStruct value7 READ value7 WRITE setVal7 NOTIFY value7Changed) Q_PROPERTY(int value8 READ value8 NOTIFY value8Changed) Q_PROPERTY(int value9 READ value9 CONSTANT) + Q_PROPERTY(int value10 READ value10 FINAL) public: enum EnumType { EnumType1 }; @@ -140,6 +141,8 @@ public: int value9() const { return 1; } + int value10() const { return 1; } + QList value4; QVariantList value5; @@ -163,6 +166,7 @@ private slots: void checkScope(); void propertyNotify(); void propertyConstant(); + void propertyFinal(); void stdSet(); void classInfo(); @@ -802,6 +806,19 @@ void tst_QMetaObject::propertyConstant() QVERIFY(prop.isConstant()); } +void tst_QMetaObject::propertyFinal() +{ + const QMetaObject *mo = metaObject(); + + QMetaProperty prop = mo->property(mo->indexOfProperty("value10")); + QVERIFY(prop.isValid()); + QVERIFY(prop.isFinal()); + + prop = mo->property(mo->indexOfProperty("value9")); + QVERIFY(prop.isValid()); + QVERIFY(!prop.isFinal()); +} + class ClassInfoTestObjectA : public QObject { Q_OBJECT -- cgit v0.12 From 87239ef6438b50b2dfa7b6526a5e5cbe7d5598d5 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 10:18:05 +1000 Subject: extend the QObjectPrivate::connectedSignals bitfield to make space for all the required NOTIFY signals we need for QML bindings. An additional internal function QMetaObject::isConnected() allows to query the bits, or you use connectedSignals[0] if you know that the signal in question has a QMetaObject::indexOfSignal() < 32. Authored-by: mae Reviewed-by: Aaron Kennedy --- src/corelib/animation/qvariantanimation.cpp | 2 +- src/corelib/kernel/qobject.cpp | 77 +++++++++++++++++++++++------ src/corelib/kernel/qobject_p.h | 2 +- src/corelib/kernel/qobjectdefs.h | 3 ++ src/gui/graphicsview/qgraphicsitem.cpp | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 8 +-- 6 files changed, 72 insertions(+), 22 deletions(-) diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 48e5ec1..fdd98c2 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -267,7 +267,7 @@ void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress) localProgress); qSwap(currentValue, ret); q->updateCurrentValue(currentValue); - if ((connectedSignals & changedSignalMask) && currentValue != ret) { + if ((connectedSignals[0] & changedSignalMask) && currentValue != ret) { //the value has changed emit q->valueChanged(currentValue); } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 6503ab0..e5cc375 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -139,7 +139,8 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals = 0; + for (uint i = 0; i < (sizeof connectedSignals / sizeof connectedSignals[0]); ++i) + connectedSignals[i] = 0; inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; @@ -2849,10 +2850,16 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, s->d_func()->addConnection(signal_index, c); - if (signal_index < 0) - sender->d_func()->connectedSignals = ~0u; - else if (signal_index < 32) - sender->d_func()->connectedSignals |= (1 << signal_index); + if (signal_index < 0) { + for (uint i = 0; i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0] ); ++i) + sender->d_func()->connectedSignals[i] = ~0u; + } else if (signal_index < (int)sizeof sender->d_func()->connectedSignals * 8) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + sender->d_func()->connectedSignals[n] |= (1 << (signal_index - n * 8 + * sizeof sender->d_func()->connectedSignals[0])); + } + return true; } @@ -3192,11 +3199,12 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal */ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) { - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3209,11 +3217,12 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void **argv) { int signal_index = m->methodOffset() + local_signal_index; - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = 1 << signal_index; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3225,21 +3234,59 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void QMetaObject::activate(QObject *sender, const QMetaObject *m, int from_local_signal_index, int to_local_signal_index, void **argv) { + Q_ASSERT(from_local_signal_index <= to_local_signal_index); int offset = m->methodOffset(); int from_signal_index = offset + from_local_signal_index; int to_signal_index = offset + to_local_signal_index; - if (to_signal_index < 32 + + if (to_signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !qt_signal_spy_callback_set.signal_begin_callback && !qt_signal_spy_callback_set.signal_end_callback) { - uint signal_mask = (1 << (to_signal_index + 1)) - 1; - signal_mask ^= (1 << from_signal_index) - 1; - if ((sender->d_func()->connectedSignals & signal_mask) == 0) + + uint n = (from_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (from_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + uint nt = (to_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint mt = 1 << (to_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + bool connected = false; + quint32 *connectedSignals = sender->d_func()->connectedSignals; + for (uint i = 0; !connected && i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0]); ++i) { + uint mask = 0; + if (i > n) + mask = ~0u; + else if (i == n) + mask = ~(m -1); + if (i > nt) + mask = 0; + else if (i == nt) + mask &= (mt << 1) - 1; + connected = connectedSignals[i] & mask; + } + if (!connected) // nothing connected to these signals, and no spy return; } activate(sender, from_signal_index, to_signal_index, argv); } +/*! \internal + + Returns true if the signal with index \a signal_index from object \a sender is connected. + Signals with indices above a certain range are always considered connected (see connectedSignals + in QObjectPrivate). If a signal spy is installed, all signals are considered connected. +*/ +bool QMetaObject::isConnected(QObject *sender, int signal_index) { + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 + && !qt_signal_spy_callback_set.signal_begin_callback + && !qt_signal_spy_callback_set.signal_end_callback) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) + // nothing connected to these signals, and no spy + return false; + } + return true; +} /***************************************************************************** Properties diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 07c397f..6a20040 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -140,7 +140,7 @@ public: QList propertyValues; }; ExtraData *extraData; - mutable quint32 connectedSignals; + mutable quint32 connectedSignals[2]; QString objectName; diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 9187765..300e9fa 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -334,6 +334,9 @@ struct Q_CORE_EXPORT QMetaObject static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv); static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); + + static bool isConnected(QObject *sender, int signal_index); + // internal guarded pointers static void addGuard(QObject **ptr); static void removeGuard(QObject **ptr); diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5aae93e..3884af9 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -6462,7 +6462,7 @@ void QGraphicsItem::prepareGeometryChange() // if someone is connected to the changed signal or the scene has no views. // Note that this has to be done *after* markDirty to ensure that // _q_processDirtyItems is called before _q_emitUpdated. - if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask) + if ((scenePrivate->connectedSignals[0] & scenePrivate->changedSignalMask) || scenePrivate->views.isEmpty()) { if (d_ptr->hasTranslateOnlySceneTransform()) { d_ptr->scene->update(boundingRect().translated(d_ptr->sceneTransform.dx(), diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index a846cf6..da4a347 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -344,7 +344,7 @@ void QGraphicsScenePrivate::_q_emitUpdated() // the optimization that items send updates directly to the views, but it // needs to happen in order to keep compatibility with the behavior from // Qt 4.4 and backward. - if (connectedSignals & changedSignalMask) { + if (connectedSignals[0] & changedSignalMask) { for (int i = 0; i < views.size(); ++i) { QGraphicsView *view = views.at(i); if (!view->d_func()->connectedToScene) { @@ -2899,7 +2899,7 @@ void QGraphicsScene::update(const QRectF &rect) // Check if anyone's connected; if not, we can send updates directly to // the views. Otherwise or if there are no views, use old behavior. - bool directUpdates = !(d->connectedSignals & d->changedSignalMask) && !d->views.isEmpty(); + bool directUpdates = !(d->connectedSignals[0] & d->changedSignalMask) && !d->views.isEmpty(); if (rect.isNull()) { d->updateAll = true; d->updatedRects.clear(); @@ -4477,7 +4477,7 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b if (removingItemFromScene) { // Note that this function can be called from the item's destructor, so // do NOT call any virtual functions on it within this block. - if ((connectedSignals & changedSignalMask) || views.isEmpty()) { + if ((connectedSignals[0] & changedSignalMask) || views.isEmpty()) { // This block of code is kept for compatibility. Since 4.5, by default // QGraphicsView does not connect the signal and we use the below // method of delivering updates. @@ -4623,7 +4623,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // Process item. if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) { - const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); + const bool useCompatUpdate = views.isEmpty() || (connectedSignals[0] & changedSignalMask); const QRectF itemBoundingRect = adjustedItemBoundingRect(item); if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) { -- cgit v0.12 From 46ca473d569b92cdfc567c2096b1c4af3ba68f80 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 10:52:40 +1000 Subject: Allow retrieval of interface IId from class type. This method is necessary for QML to support Qt interfaces, but probably shouldn't be used otherwise. Reviewed-by: Roberto Raggi --- src/corelib/kernel/qobject.h | 10 ++++++++++ tests/auto/qobject/tst_qobject.cpp | 11 +++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 1fb216b..4715626 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -379,6 +379,9 @@ inline QList qFindChildren(const QObject *o, const QRegExp &re) #endif // Q_MOC_RUN +template inline const char * qobject_interface_iid() +{ return 0; } + template inline T qobject_cast_helper(QObject *object, T) { return static_cast(((T)0)->staticMetaObject.cast(object)); } @@ -395,6 +398,8 @@ inline T qobject_cast(const QObject *object) #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid() \ + { return IId; } \ template <> inline IFace *qobject_cast_helper(QObject *object, IFace *) \ { return (IFace *)(object ? object->qt_metacast(IId) : 0); } \ template <> inline IFace *qobject_cast_helper(const QObject *object, IFace *) \ @@ -458,8 +463,13 @@ inline T qobject_cast(const QObject *object) } +template inline const char * qobject_interface_iid() +{ return 0; } + #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid() \ + { return IId; } \ template <> inline IFace *qobject_cast(QObject *object) \ { return reinterpret_cast((object ? object->qt_metacast(IId) : 0)); } \ template <> inline IFace *qobject_cast(const QObject *object) \ diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 4f25af6..3df83d7 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -118,6 +118,7 @@ private slots: void connectToSender(); void qobjectConstCast(); void uniqConnection(); + void interfaceIid(); protected: }; @@ -2887,5 +2888,15 @@ void tst_QObject::uniqConnection() delete r2; } +void tst_QObject::interfaceIid() +{ + QCOMPARE(QByteArray(qobject_interface_iid()), + QByteArray(Bleh_iid)); + QCOMPARE(QByteArray(qobject_interface_iid()), + QByteArray("com.qtest.foobar")); + QCOMPARE(QByteArray(qobject_interface_iid()), + QByteArray()); +} + QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" -- cgit v0.12 From 25d7123a0fce87673eb64afe405e310b08f721b9 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 11:04:03 +1000 Subject: Add non-threadsafe QGuard class Cherry pick of 4031c0f0613090d70cd1fcacfc5b8316b12eb14e Reviewed-by: Andreas --- src/corelib/kernel/kernel.pri | 6 +- src/corelib/kernel/qguard.cpp | 26 +++++++ src/corelib/kernel/qguard_p.h | 151 +++++++++++++++++++++++++++++++++++++++++ src/corelib/kernel/qobject.cpp | 18 ++++- src/corelib/kernel/qobject_p.h | 2 + 5 files changed, 200 insertions(+), 3 deletions(-) create mode 100644 src/corelib/kernel/qguard.cpp create mode 100644 src/corelib/kernel/qguard_p.h diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 7177293..d30f294 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -32,7 +32,8 @@ HEADERS += \ kernel/qsharedmemory_p.h \ kernel/qsystemsemaphore.h \ kernel/qsystemsemaphore_p.h \ - kernel/qfunctions_p.h + kernel/qfunctions_p.h \ + kernel/qguard_p.h SOURCES += \ kernel/qabstracteventdispatcher.cpp \ @@ -54,7 +55,8 @@ SOURCES += \ kernel/qcoreglobaldata.cpp \ kernel/qsharedmemory.cpp \ kernel/qsystemsemaphore.cpp \ - kernel/qpointer.cpp + kernel/qpointer.cpp \ + kernel/qguard.cpp win32 { SOURCES += \ diff --git a/src/corelib/kernel/qguard.cpp b/src/corelib/kernel/qguard.cpp new file mode 100644 index 0000000..c61be00 --- /dev/null +++ b/src/corelib/kernel/qguard.cpp @@ -0,0 +1,26 @@ +#include "qguard_p.h" +#include + +void q_guard_addGuard(QGuard *g) +{ + QObjectPrivate *p = QObjectPrivate::get(g->o); + if (p->wasDeleted) { + qWarning("QGuard: cannot add guard to deleted object"); + g->o = 0; + return; + } + + g->next = p->objectGuards; + p->objectGuards = g; + g->prev = &p->objectGuards; + if (g->next) + g->next->prev = &g->next; +} + +void q_guard_removeGuard(QGuard *g) +{ + *g->prev = g->next; + g->next = 0; + g->prev = 0; +} + diff --git a/src/corelib/kernel/qguard_p.h b/src/corelib/kernel/qguard_p.h new file mode 100644 index 0000000..7236ed6 --- /dev/null +++ b/src/corelib/kernel/qguard_p.h @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUARD_P_H +#define QGUARD_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header +// file may change from version to version without notice, or even be removed. +// +// We mean it. +// + +#include "QtCore/qglobal.h" + +QT_BEGIN_NAMESPACE + +class QObject; +template +class QGuard +{ + QObject *o; + QGuard *next; + QGuard **prev; + friend void q_guard_addGuard(QGuard *); + friend void q_guard_removeGuard(QGuard *); + friend class QObjectPrivate; +public: + inline QGuard(); + inline QGuard(T *); + inline QGuard(const QGuard &); + inline virtual ~QGuard(); + + inline QGuard &operator=(const QGuard &o); + inline QGuard &operator=(T *); + + inline bool isNull() const + { return !o; } + + inline T* operator->() const + { return static_cast(const_cast(o)); } + inline T& operator*() const + { return *static_cast(const_cast(o)); } + inline operator T*() const + { return static_cast(const_cast(o)); } + inline T* data() const + { return static_cast(const_cast(o)); } + +protected: + virtual void objectDestroyed(T *) {} +}; + +void Q_CORE_EXPORT q_guard_addGuard(QGuard *); +void Q_CORE_EXPORT q_guard_removeGuard(QGuard *); + +template +QGuard::QGuard() +: o(0), next(0), prev(0) +{ +} + +template +QGuard::QGuard(T *g) +: o(g), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast *>(this)); +} + +template +QGuard::QGuard(const QGuard &g) +: o(g.o), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast *>(this)); +} + +template +QGuard::~QGuard() +{ + if (prev) q_guard_removeGuard(reinterpret_cast *>(this)); + o = 0; +} + +template +QGuard &QGuard::operator=(const QGuard &g) +{ + if (g.o != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast *>(this)); + o = g.o; + if (o) q_guard_addGuard(reinterpret_cast *>(this)); + } + return *this; +} + +template +inline QGuard &QGuard::operator=(T *g) +{ + if (g != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast *>(this)); + o = g; + if (o) q_guard_addGuard(reinterpret_cast *>(this)); + } + return *this; +} + +QT_END_NAMESPACE + +#endif // QGUARD_P_H diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index e5cc375..a1702d9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -144,6 +144,7 @@ QObjectPrivate::QObjectPrivate(int version) inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; + objectGuards = 0; hasGuards = false; } @@ -426,7 +427,22 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - if (!QObjectPrivate::get(object)->hasGuards) + QObjectPrivate *priv = QObjectPrivate::get(object); + QGuard *guard = priv->objectGuards; + while (guard) { + guard->o = 0; + guard = guard->next; + } + while (priv->objectGuards) { + guard = priv->objectGuards; + guard->prev = 0; + if (guard->next) guard->next->prev = &priv->objectGuards; + priv->objectGuards = guard->next; + guard->next = 0; + guard->objectDestroyed(object); + } + + if (!priv->hasGuards) return; GuardHash *hash = guardHash(); if (hash) { diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 6a20040..335768c 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -60,6 +60,7 @@ #include "QtCore/qvector.h" #include "QtCore/qreadwritelock.h" #include "QtCore/qvariant.h" +#include "qguard_p.h" QT_BEGIN_NAMESPACE @@ -174,6 +175,7 @@ public: static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); int *deleteWatch; + QGuard *objectGuards; static QObjectPrivate *get(QObject *o) { return o->d_func(); -- cgit v0.12 From 4238094aad5b3c9b5980bfa6c1ae83e02dc5b9bf Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 11:06:24 +1000 Subject: removing Q_CORE_EXPORT for q_guard_addGuard() and q_guard_removeGuard() I made the functions inline instead and moved them to qobject_p.h Authored-by: Thomas Hartmann Reviewed-by: Aaron Kennedy (cherry picked from commit fd27c5ac9670b56ccd60e8d8f6791237358f3633) --- src/corelib/kernel/kernel.pri | 3 +-- src/corelib/kernel/qguard.cpp | 26 -------------------------- src/corelib/kernel/qguard_p.h | 3 +-- src/corelib/kernel/qobject_p.h | 24 ++++++++++++++++++++++++ 4 files changed, 26 insertions(+), 30 deletions(-) delete mode 100644 src/corelib/kernel/qguard.cpp diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index d30f294..3493784 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -55,8 +55,7 @@ SOURCES += \ kernel/qcoreglobaldata.cpp \ kernel/qsharedmemory.cpp \ kernel/qsystemsemaphore.cpp \ - kernel/qpointer.cpp \ - kernel/qguard.cpp + kernel/qpointer.cpp win32 { SOURCES += \ diff --git a/src/corelib/kernel/qguard.cpp b/src/corelib/kernel/qguard.cpp deleted file mode 100644 index c61be00..0000000 --- a/src/corelib/kernel/qguard.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "qguard_p.h" -#include - -void q_guard_addGuard(QGuard *g) -{ - QObjectPrivate *p = QObjectPrivate::get(g->o); - if (p->wasDeleted) { - qWarning("QGuard: cannot add guard to deleted object"); - g->o = 0; - return; - } - - g->next = p->objectGuards; - p->objectGuards = g; - g->prev = &p->objectGuards; - if (g->next) - g->next->prev = &g->next; -} - -void q_guard_removeGuard(QGuard *g) -{ - *g->prev = g->next; - g->next = 0; - g->prev = 0; -} - diff --git a/src/corelib/kernel/qguard_p.h b/src/corelib/kernel/qguard_p.h index 7236ed6..cbc9cca 100644 --- a/src/corelib/kernel/qguard_p.h +++ b/src/corelib/kernel/qguard_p.h @@ -54,6 +54,7 @@ // #include "QtCore/qglobal.h" +#include "private/qobject_p.h" QT_BEGIN_NAMESPACE @@ -92,8 +93,6 @@ protected: virtual void objectDestroyed(T *) {} }; -void Q_CORE_EXPORT q_guard_addGuard(QGuard *); -void Q_CORE_EXPORT q_guard_removeGuard(QGuard *); template QGuard::QGuard() diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 335768c..7e3e97d 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -182,6 +182,30 @@ public: } }; +inline void q_guard_addGuard(QGuard *g) +{ + QObjectPrivate *p = QObjectPrivate::get(g->o); + if (p->wasDeleted) { + qWarning("QGuard: cannot add guard to deleted object"); + g->o = 0; + return; + } + + g->next = p->objectGuards; + p->objectGuards = g; + g->prev = &p->objectGuards; + if (g->next) + g->next->prev = &g->next; +} + +inline void q_guard_removeGuard(QGuard *g) +{ + if (g->next) g->next->prev = g->prev; + *g->prev = g->next; + g->next = 0; + g->prev = 0; +} + Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE); -- cgit v0.12 From 1237ea8bac2f5fd055553b45eae296fd44abd3e8 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 27 Jul 2009 16:35:38 +0200 Subject: Fixed missing forward declarations, which made gcc fail to compile anything that included qobject.h Reviewed-by: Thomas Hartmann (cherry picked from commit cc287101308fa606eb4de2597b5309c8099654c3) --- src/corelib/kernel/qguard_p.h | 9 ++++++++- src/corelib/kernel/qobject_p.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qguard_p.h b/src/corelib/kernel/qguard_p.h index cbc9cca..6af01ac 100644 --- a/src/corelib/kernel/qguard_p.h +++ b/src/corelib/kernel/qguard_p.h @@ -54,7 +54,6 @@ // #include "QtCore/qglobal.h" -#include "private/qobject_p.h" QT_BEGIN_NAMESPACE @@ -93,6 +92,14 @@ protected: virtual void objectDestroyed(T *) {} }; +QT_END_NAMESPACE + +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +inline void q_guard_addGuard(QGuard *); +inline void q_guard_removeGuard(QGuard *); template QGuard::QGuard() diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 7e3e97d..54c98ad 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -60,7 +60,7 @@ #include "QtCore/qvector.h" #include "QtCore/qreadwritelock.h" #include "QtCore/qvariant.h" -#include "qguard_p.h" +#include "private/qguard_p.h" QT_BEGIN_NAMESPACE -- cgit v0.12 From 13e3bbf2c46077f2b970bc6c0bc9850112b81cb7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 11:52:53 +1000 Subject: Autotest for QGuard Reviewed-by: Andreas --- tests/auto/qguard/qguard.pro | 2 + tests/auto/qguard/tst_qguard.cpp | 350 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 352 insertions(+) create mode 100644 tests/auto/qguard/qguard.pro create mode 100644 tests/auto/qguard/tst_qguard.cpp diff --git a/tests/auto/qguard/qguard.pro b/tests/auto/qguard/qguard.pro new file mode 100644 index 0000000..f249dde --- /dev/null +++ b/tests/auto/qguard/qguard.pro @@ -0,0 +1,2 @@ +load(qttest_p4) +SOURCES += tst_qguard.cpp diff --git a/tests/auto/qguard/tst_qguard.cpp b/tests/auto/qguard/tst_qguard.cpp new file mode 100644 index 0000000..96d1b60 --- /dev/null +++ b/tests/auto/qguard/tst_qguard.cpp @@ -0,0 +1,350 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// NOTE: This is identical to the QPointer autotest + +#include + +#include +#include +#include +#include + +class tst_QGuard : public QObject +{ + Q_OBJECT +public: + tst_QGuard(); + ~tst_QGuard(); + + inline tst_QGuard *me() const + { return const_cast(this); } + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); +private slots: + void constructors(); + void destructor(); + void assignment_operators(); + void equality_operators(); + void isNull(); + void dereference_operators(); + void disconnect(); + void castDuringDestruction(); + void data() const; + void dataSignature() const; +}; + +tst_QGuard::tst_QGuard() +{ } + +tst_QGuard::~tst_QGuard() +{ } + +void tst_QGuard::initTestCase() +{ } + +void tst_QGuard::cleanupTestCase() +{ } + +void tst_QGuard::init() +{ } + +void tst_QGuard::cleanup() +{ } + +void tst_QGuard::constructors() +{ + QGuard p1; + QGuard p2(this); + QGuard p3(p2); + QCOMPARE(p1, QGuard(0)); + QCOMPARE(p2, QGuard(this)); + QCOMPARE(p3, QGuard(this)); +} + +void tst_QGuard::destructor() +{ + QObject *object = new QObject; + QGuard p = object; + QCOMPARE(p, QGuard(object)); + delete object; + QCOMPARE(p, QGuard(0)); +} + +void tst_QGuard::assignment_operators() +{ + QGuard p1; + QGuard p2; + + p1 = this; + p2 = p1; + + QCOMPARE(p1, QGuard(this)); + QCOMPARE(p2, QGuard(this)); + QCOMPARE(p1, QGuard(p2)); + + p1 = 0; + p2 = p1; + QCOMPARE(p1, QGuard(0)); + QCOMPARE(p2, QGuard(0)); + QCOMPARE(p1, QGuard(p2)); + + QObject *object = new QObject; + + p1 = object; + p2 = p1; + QCOMPARE(p1, QGuard(object)); + QCOMPARE(p2, QGuard(object)); + QCOMPARE(p1, QGuard(p2)); + + delete object; + QCOMPARE(p1, QGuard(0)); + QCOMPARE(p2, QGuard(0)); + QCOMPARE(p1, QGuard(p2)); +} + +void tst_QGuard::equality_operators() +{ + QGuard p1; + QGuard p2; + + QVERIFY(p1 == p2); + + QObject *object = 0; + QWidget *widget = 0; + + p1 = object; + QVERIFY(p1 == p2); + QVERIFY(p1 == object); + p2 = object; + QVERIFY(p2 == p1); + QVERIFY(p2 == object); + + p1 = this; + QVERIFY(p1 != p2); + p2 = p1; + QVERIFY(p1 == p2); + + // compare to zero + p1 = 0; + QVERIFY(p1 == 0); + QVERIFY(0 == p1); + QVERIFY(p2 != 0); + QVERIFY(0 != p2); + QVERIFY(p1 == object); + QVERIFY(object == p1); + QVERIFY(p2 != object); + QVERIFY(object != p2); + QVERIFY(p1 == widget); + QVERIFY(widget == p1); + QVERIFY(p2 != widget); + QVERIFY(widget != p2); +} + +void tst_QGuard::isNull() +{ + QGuard p1; + QVERIFY(p1.isNull()); + p1 = this; + QVERIFY(!p1.isNull()); + p1 = 0; + QVERIFY(p1.isNull()); +} + +void tst_QGuard::dereference_operators() +{ + QGuard p1 = this; + + QObject *object = p1->me(); + QVERIFY(object == this); + + QObject &ref = *p1; + QVERIFY(&ref == this); + + object = static_cast(p1); + QVERIFY(object == this); +} + +void tst_QGuard::disconnect() +{ + QGuard p1 = new QObject; + QVERIFY(!p1.isNull()); + p1->disconnect(); + QVERIFY(!p1.isNull()); + delete static_cast(p1); + QVERIFY(p1.isNull()); +} + +class ChildObject : public QObject +{ + QGuard guardedPointer; + +public: + ChildObject(QObject *parent) + : QObject(parent), guardedPointer(parent) + { } + ~ChildObject(); +}; + +ChildObject::~ChildObject() +{ + QCOMPARE(static_cast(guardedPointer), static_cast(0)); + QCOMPARE(qobject_cast(guardedPointer), static_cast(0)); +} + +class ChildWidget : public QWidget +{ + QGuard guardedPointer; + +public: + ChildWidget(QWidget *parent) + : QWidget(parent), guardedPointer(parent) + { } + ~ChildWidget(); +}; + +ChildWidget::~ChildWidget() +{ + QCOMPARE(static_cast(guardedPointer), static_cast(0)); + QCOMPARE(qobject_cast(guardedPointer), static_cast(0)); +} + +class DerivedChild; + +class DerivedParent : public QObject +{ + Q_OBJECT + + DerivedChild *derivedChild; + +public: + DerivedParent(); + ~DerivedParent(); +}; + +class DerivedChild : public QObject +{ + Q_OBJECT + + DerivedParent *parentPointer; + QGuard guardedParentPointer; + +public: + DerivedChild(DerivedParent *parent) + : QObject(parent), parentPointer(parent), guardedParentPointer(parent) + { } + ~DerivedChild(); +}; + +DerivedParent::DerivedParent() + : QObject() +{ + derivedChild = new DerivedChild(this); +} + +DerivedParent::~DerivedParent() +{ + delete derivedChild; +} + +DerivedChild::~DerivedChild() +{ + QCOMPARE(static_cast(guardedParentPointer), parentPointer); + QCOMPARE(qobject_cast(guardedParentPointer), parentPointer); +} + +void tst_QGuard::castDuringDestruction() +{ + { + QObject *parentObject = new QObject(); + (void) new ChildObject(parentObject); + delete parentObject; + } + + { + QWidget *parentWidget = new QWidget(); + (void) new ChildWidget(parentWidget); + delete parentWidget; + } + + { + delete new DerivedParent(); + } +} + +void tst_QGuard::data() const +{ + /* Check value of a default constructed object. */ + { + QGuard p; + QCOMPARE(p.data(), static_cast(0)); + } + + /* Check value of a default constructed object. */ + { + QObject *const object = new QObject(); + QGuard p(object); + QCOMPARE(p.data(), object); + } +} + +void tst_QGuard::dataSignature() const +{ + /* data() should be const. */ + { + const QGuard p; + p.data(); + } + + /* The return type should be T. */ + { + const QGuard p; + /* If the types differs, the QCOMPARE will fail to instansiate. */ + QCOMPARE(p.data(), static_cast(0)); + } +} + +QTEST_MAIN(tst_QGuard) +#include "tst_qguard.moc" -- cgit v0.12 From c257996dfdc87b9a9682d35419792730e477d3ac Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 12:05:11 +1000 Subject: Make setRoleNames() protected and improve docs. (cherry picked from commit 15be8a6b259a5cb4f528b1c765bfcddfc9edd044) Authored-by: Martin Jones Reviewed-by: mbm --- src/corelib/kernel/qabstractitemmodel.cpp | 42 +++++++++++++++++++++++++++++++ src/corelib/kernel/qabstractitemmodel.h | 4 +++ src/corelib/kernel/qabstractitemmodel_p.h | 5 +++- 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 3d9263e..cd17076 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,6 +467,21 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +const QHash &QAbstractItemModelPrivate::defaultRoleNames() +{ + static QHash roleNames; + if (roleNames.isEmpty()) { + roleNames[Qt::DisplayRole] = "display"; + roleNames[Qt::DecorationRole] = "decoration"; + roleNames[Qt::EditRole] = "edit"; + roleNames[Qt::ToolTipRole] = "toolTip"; + roleNames[Qt::StatusTipRole] = "statusTip"; + roleNames[Qt::WhatsThisRole] = "whatsThis"; + } + + return roleNames; +} + /*! \internal return true if \a value contains a numerical type @@ -1863,6 +1878,33 @@ QSize QAbstractItemModel::span(const QModelIndex &) const } /*! + Sets the model's role names to \a roleNames. + + This function is provided to allow mapping of role identifiers to + role property names in Declarative UI. This function must be called + before the model is used. Modifying the role names after the model + has been set may result in undefined behaviour. + + \sa roleNames() +*/ +void QAbstractItemModel::setRoleNames(const QHash &roleNames) +{ + Q_D(QAbstractItemModel); + d->roleNames = roleNames; +} + +/*! + Returns the model's role names. + + \sa setRoleNames +*/ +const QHash &QAbstractItemModel::roleNames() const +{ + Q_D(const QAbstractItemModel); + return d->roleNames; +} + +/*! Called to let the model know that it should submit whatever it has cached to the permanent storage. Typically used for row editing. diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h index dc7d7bd..a6bbff4 100644 --- a/src/corelib/kernel/qabstractitemmodel.h +++ b/src/corelib/kernel/qabstractitemmodel.h @@ -220,6 +220,8 @@ public: Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const; virtual QSize span(const QModelIndex &index) const; + const QHash &roleNames() const; + #ifdef Q_NO_USING_KEYWORD inline QObject *parent() const { return QObject::parent(); } #else @@ -282,6 +284,8 @@ protected: void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to); QModelIndexList persistentIndexList() const; + void setRoleNames(const QHash &roleNames); + private: Q_DECLARE_PRIVATE(QAbstractItemModel) Q_DISABLE_COPY(QAbstractItemModel) diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index c047f95..6a29723 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -78,7 +78,7 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QAbstractItemModel) public: - QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1) {} + QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {} void removePersistentIndexData(QPersistentModelIndexData *data); void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last); void rowsInserted(const QModelIndex &parent, int first, int last); @@ -144,6 +144,9 @@ public: } persistent; Qt::DropActions supportedDragActions; + + QHash roleNames; + static const QHash &defaultRoleNames(); }; QT_END_NAMESPACE -- cgit v0.12 From b859422e23a31af1cda5011883d8a25c934cea65 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 15:52:29 +1000 Subject: Make QAbstractItemModel default rolenames reentrant Reviewed-by: Martin Jones Reviewed-by: mbm --- src/corelib/kernel/qabstractitemmodel.cpp | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index cd17076..01440e4 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,19 +467,25 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +namespace { + struct DefaultRoleNames : public QHash + { + DefaultRoleNames() { + (*this)[Qt::DisplayRole] = "display"; + (*this)[Qt::DecorationRole] = "decoration"; + (*this)[Qt::EditRole] = "edit"; + (*this)[Qt::ToolTipRole] = "toolTip"; + (*this)[Qt::StatusTipRole] = "statusTip"; + (*this)[Qt::WhatsThisRole] = "whatsThis"; + } + }; +} + +Q_GLOBAL_STATIC(DefaultRoleNames, q_defaultRoleNames); + const QHash &QAbstractItemModelPrivate::defaultRoleNames() { - static QHash roleNames; - if (roleNames.isEmpty()) { - roleNames[Qt::DisplayRole] = "display"; - roleNames[Qt::DecorationRole] = "decoration"; - roleNames[Qt::EditRole] = "edit"; - roleNames[Qt::ToolTipRole] = "toolTip"; - roleNames[Qt::StatusTipRole] = "statusTip"; - roleNames[Qt::WhatsThisRole] = "whatsThis"; - } - - return roleNames; + return *q_defaultRoleNames(); } /*! -- cgit v0.12 From 025dcc2bb9651708d456a5b1e5d2888e67d67bf4 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 16:04:47 +1000 Subject: Add a declarative data ptr to QObjectPrivate This data ptr does not increase the size of the QObject, as we take advantage of space otherwise only used during destruction. Reviewed-by: Andreas --- src/corelib/kernel/qobject.cpp | 8 ++++++++ src/corelib/kernel/qobject_p.h | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a1702d9..b0ddd81 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -842,6 +842,14 @@ QObject::~QObject() d->eventFilters.clear(); + // As declarativeData is in a union with currentChildBeingDeleted, this must + // be done (and declarativeData set back to 0) before deleting children. + if(d->declarativeData) { + QDeclarativeData *dd = d->declarativeData; + d->declarativeData = 0; + dd->destroyed(this); + } + if (!d->children.isEmpty()) d->deleteChildren(); diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 54c98ad..19df642 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -86,6 +86,13 @@ inline QObjectData::~QObjectData() {} enum { QObjectPrivateVersion = QT_VERSION }; +class QDeclarativeData +{ +public: + virtual ~QDeclarativeData() {} + virtual void destroyed(QObject *) {} +}; + class Q_CORE_EXPORT QObjectPrivate : public QObjectData { Q_DECLARE_PUBLIC(QObject) @@ -118,7 +125,10 @@ public: // object currently activating the object Sender *currentSender; - QObject *currentChildBeingDeleted; + union { + QObject *currentChildBeingDeleted; + QDeclarativeData *declarativeData; + }; bool isSender(const QObject *receiver, const char *signal) const; QObjectList receiverList(const char *signal) const; -- cgit v0.12 From 45c11a97a32170d0c6ab9265a102cc8d94fa63ee Mon Sep 17 00:00:00 2001 From: Thomas Hartmann Date: Tue, 16 Jun 2009 15:43:46 +0200 Subject: Fixing qml for QWidget support (crash) QWidget deletes its children in its own constructor so we have to cleanup before explicitly Reviewed-by: Aaron Kennedy (cherry picked from commit 59629ac728f2fdbc3047554d715e2f908b1844c4) --- src/gui/kernel/qwidget.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index bca607c..e24b7cb 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1375,6 +1375,12 @@ QWidget::~QWidget() // set all QPointers for this object to zero QObjectPrivate::clearGuards(this); + if(d->declarativeData) { + QDeclarativeData *dd = d->declarativeData; + d->declarativeData = 0; + dd->destroyed(this); + } + if (!d->children.isEmpty()) d->deleteChildren(); -- cgit v0.12 From b30a25280556599177b217f0e8ed3fbe4b11705d Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 16:27:28 +1000 Subject: Add index methods to QMetaProperty and QMetaMethod Authored-by: Kent Hansen Reviewed-by: Aaron Kennedy --- src/corelib/kernel/qmetaobject.cpp | 20 ++++++++++++++++++++ src/corelib/kernel/qmetaobject.h | 2 ++ 2 files changed, 22 insertions(+) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 3b09061..611eff3 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1329,6 +1329,16 @@ int QMetaMethod::attributes() const } /*! + Returns this method's index. +*/ +int QMetaMethod::methodIndex() const +{ + if (!mobj) + return -1; + return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); +} + +/*! Returns the access specification of this method (private, protected, or public). @@ -2043,6 +2053,16 @@ int QMetaProperty::userType() const } /*! + Returns this property's index. +*/ +int QMetaProperty::propertyIndex() const +{ + if (!mobj) + return -1; + return idx + mobj->propertyOffset(); +} + +/*! Returns true if the property's type is an enumeration value that is used as a flag; otherwise returns false. diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index bd47582..9f36106 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -69,6 +69,7 @@ public: MethodType methodType() const; enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 }; int attributes() const; + int methodIndex() const; inline const QMetaObject *enclosingMetaObject() const { return mobj; } @@ -178,6 +179,7 @@ public: const char *typeName() const; QVariant::Type type() const; int userType() const; + int propertyIndex() const; bool isReadable() const; bool isWritable() const; -- cgit v0.12 From f858dd8083e59eb918058694956cd3546fb303b2 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 16:44:02 +1000 Subject: Dynamic meta object support This is an internal API used by declarative. Authored-by: mae Reviewed-by: Aaron Kennedy --- src/corelib/kernel/qmetaobject.cpp | 55 +++++++++++++++++++++++++++----------- src/corelib/kernel/qobject.cpp | 9 ++++--- src/corelib/kernel/qobject.h | 1 + src/corelib/kernel/qobject_p.h | 8 ++++++ src/corelib/kernel/qobjectdefs.h | 2 ++ src/tools/moc/generator.cpp | 9 ++++--- 6 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 611eff3..fc17e00 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -182,6 +182,10 @@ enum MethodFlags { MethodScriptable = 0x40 }; +enum MetaObjectFlags { + DynamicMetaObject = 0x01 +}; + struct QMetaObjectPrivate { int revision; @@ -191,6 +195,7 @@ struct QMetaObjectPrivate int propertyCount, propertyData; int enumeratorCount, enumeratorData; int constructorCount, constructorData; + int flags; }; static inline const QMetaObjectPrivate *priv(const uint* data) @@ -280,6 +285,17 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const } /*! + \internal +*/ +int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv) +{ + if (QMetaObject *mo = object->d_ptr->metaObject) + return static_cast(mo)->metaCall(cl, idx, argv); + else + return object->qt_metacall(cl, idx, argv); +} + +/*! \fn const char *QMetaObject::className() const Returns the class name. @@ -699,6 +715,14 @@ int QMetaObject::indexOfProperty(const char *name) const } m = m->d.superdata; } + + if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){ + QAbstractDynamicMetaObject *me = + const_cast(static_cast(this)); + + i = me->createProperty(name, 0); + } + return i; } @@ -1538,7 +1562,7 @@ bool QMetaMethod::invoke(QObject *object, // recompute the methodIndex by reversing the arithmetic in QMetaObject::property() int methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); if (connectionType == Qt::DirectConnection) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; } else { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " @@ -2174,9 +2198,8 @@ QVariant QMetaProperty::read(const QObject *object) const value = QVariant(t, (void*)0); argv[0] = value.data(); } - const_cast(object)->qt_metacall(QMetaObject::ReadProperty, - idx + mobj->propertyOffset(), - argv); + QMetaObject::metacall(const_cast(object), QMetaObject::ReadProperty, + idx + mobj->propertyOffset(), argv); if (status != -1) return value; @@ -2247,7 +2270,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const argv[0] = &v; else argv[0] = v.data(); - object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); return status; } @@ -2264,7 +2287,7 @@ bool QMetaProperty::reset(QObject *object) const if (!object || !mobj || !isResettable()) return false; void *argv[] = { 0 }; - object->qt_metacall(QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); return true; } @@ -2378,8 +2401,8 @@ bool QMetaProperty::isDesignable(const QObject *object) const bool b = flags & Designable; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyDesignable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyDesignable, + idx + mobj->propertyOffset(), argv); } return b; @@ -2404,8 +2427,8 @@ bool QMetaProperty::isScriptable(const QObject *object) const bool b = flags & Scriptable; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyScriptable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyScriptable, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2428,8 +2451,8 @@ bool QMetaProperty::isStored(const QObject *object) const bool b = flags & Stored; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyStored, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyStored, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2455,8 +2478,8 @@ bool QMetaProperty::isUser(const QObject *object) const bool b = flags & User; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyUser, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyUser, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2520,8 +2543,8 @@ bool QMetaProperty::isEditable(const QObject *object) const bool b = flags & Editable; if (object) { void *argv[] = { &b }; - const_cast(object)->qt_metacall(QMetaObject::QueryPropertyEditable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast(object), QMetaObject::QueryPropertyEditable, + idx + mobj->propertyOffset(), argv); } return b; } diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index b0ddd81..ab91799 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -145,11 +145,13 @@ QObjectPrivate::QObjectPrivate(int version) inThreadChangeEvent = false; deleteWatch = 0; objectGuards = 0; + metaObject = 0; hasGuards = false; } QObjectPrivate::~QObjectPrivate() { + delete static_cast(metaObject); if (deleteWatch) *deleteWatch = 1; #ifndef QT_NO_USERDATA @@ -484,7 +486,7 @@ QMetaCallEvent::~QMetaCallEvent() */ int QMetaCallEvent::placeMetaCall(QObject *object) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_); + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_); } /*! @@ -3171,10 +3173,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal } #if defined(QT_NO_EXCEPTIONS) - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); #else try { - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); } catch (...) { locker.relock(); @@ -3917,6 +3919,7 @@ void qDeleteInEventHandler(QObject *o) delete o; } + QT_END_NAMESPACE #include "moc_qobject.cpp" diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 4715626..9169a90 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -109,6 +109,7 @@ public: uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; int postedEvents; + QMetaObject *metaObject; // assert dynamic }; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 19df642..e908753 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -256,6 +256,14 @@ private: void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o); + +struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject +{ + virtual ~QAbstractDynamicMetaObject() {} + virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } + virtual int createProperty(const char *, const char *) { return -1; } +}; + QT_END_NAMESPACE #endif // QOBJECT_P_H diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 300e9fa..1ae46d5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -431,6 +431,7 @@ struct Q_CORE_EXPORT QMetaObject }; int static_metacall(Call, int, void **) const; + static int metacall(QObject *, Call, int, void **); #ifdef QT3_SUPPORT QT3_SUPPORT const char *superClassName() const; @@ -442,6 +443,7 @@ struct Q_CORE_EXPORT QMetaObject const uint *data; const void *extradata; } d; + }; struct QMetaObjectExtraData diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index fbc434d..6df762d 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -205,10 +205,10 @@ void Generator::generateCode() QByteArray qualifiedClassNameIdentifier = cdef->qualified; qualifiedClassNameIdentifier.replace(':', '_'); - int index = 12; + int index = 13; fprintf(out, "static const uint qt_meta_data_%s[] = {\n", qualifiedClassNameIdentifier.constData()); fprintf(out, "\n // content:\n"); - fprintf(out, " %4d, // revision\n", 2); + fprintf(out, " %4d, // revision\n", 3); fprintf(out, " %4d, // classname\n", strreg(cdef->qualified)); fprintf(out, " %4d, %4d, // classinfo\n", cdef->classInfoList.count(), cdef->classInfoList.count() ? index : 0); index += cdef->classInfoList.count() * 2; @@ -228,6 +228,9 @@ void Generator::generateCode() fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0, isConstructible ? index : 0); + fprintf(out, " %4d, // flags\n", 0); + + // // Build classinfo array // @@ -382,7 +385,7 @@ void Generator::generateCode() if (isQt || !cdef->hasQObject) return; - fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return &staticMetaObject;\n}\n", + fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;\n}\n", cdef->qualified.constData()); // // Generate smart cast function -- cgit v0.12 From 545a2e68b49fa648e85e6cca4df97badb89773bb Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 17:57:32 +1000 Subject: Export QTextControl This class is used in declarative. Reviewed-by: Andreas --- src/gui/text/qtextcontrol_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 872bcd5..eb0d749 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -83,7 +83,7 @@ class QAbstractScrollArea; class QEvent; class QTimerEvent; -class Q_AUTOTEST_EXPORT QTextControl : public QObject +class Q_GUI_EXPORT QTextControl : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QTextControl) -- cgit v0.12 From 048ac3827d103bfd08b4675c3ec783e10902f381 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 30 Jul 2009 18:01:42 +1000 Subject: Add NOTIFY attribute to QAction properties Authored-by: Warwick Allison Reviewed-by: Henrik Hartz --- src/gui/kernel/qaction.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/gui/kernel/qaction.h b/src/gui/kernel/qaction.h index 133fab4..cb681c4 100644 --- a/src/gui/kernel/qaction.h +++ b/src/gui/kernel/qaction.h @@ -68,24 +68,24 @@ class Q_GUI_EXPORT QAction : public QObject Q_ENUMS(MenuRole) Q_ENUMS(Priority) - Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable) + Q_PROPERTY(bool checkable READ isCheckable WRITE setCheckable NOTIFY changed) Q_PROPERTY(bool checked READ isChecked WRITE setChecked DESIGNABLE isCheckable NOTIFY toggled) - Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) - Q_PROPERTY(QIcon icon READ icon WRITE setIcon) - Q_PROPERTY(QString text READ text WRITE setText) - Q_PROPERTY(QString iconText READ iconText WRITE setIconText) - Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip) - Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip) - Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis) - Q_PROPERTY(QFont font READ font WRITE setFont) + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY changed) + Q_PROPERTY(QIcon icon READ icon WRITE setIcon NOTIFY changed) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY changed) + Q_PROPERTY(QString iconText READ iconText WRITE setIconText NOTIFY changed) + Q_PROPERTY(QString toolTip READ toolTip WRITE setToolTip NOTIFY changed) + Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed) + Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed) + Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed) #ifndef QT_NO_SHORTCUT - Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut) - Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext) - Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat) + Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed) + Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed) + Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed) #endif - Q_PROPERTY(bool visible READ isVisible WRITE setVisible) - Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole) - Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed) + Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed) + Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed) Q_PROPERTY(Priority priority READ priority WRITE setPriority) public: -- cgit v0.12 From 8fca9052e72d1dc983443c3a8065f804bebf77e7 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Tue, 5 May 2009 15:27:04 +1000 Subject: QtScript must respect dynamic metaobject's when installed (cherry picked from commit f39ccc5ed802ee8461122b8b067c8faa9aae8f8a) Reviewed-by: Roberto Raggi --- src/script/qscriptextqobject.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/script/qscriptextqobject.cpp b/src/script/qscriptextqobject.cpp index 88fd007..3ea5963 100644 --- a/src/script/qscriptextqobject.cpp +++ b/src/script/qscriptextqobject.cpp @@ -736,7 +736,7 @@ static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType meta->static_metacall(QMetaObject::CreateInstance, chosenIndex, params); } else { Q_ASSERT(thisQObject != 0); - thisQObject->qt_metacall(QMetaObject::InvokeMetaMethod, chosenIndex, params); + QMetaObject::metacall(thisQObject, QMetaObject::InvokeMetaMethod, chosenIndex, params); } if (scriptable) -- cgit v0.12 From 33e475e2f39b26327c60a52bc02ad50500ad7cbe Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 6 May 2009 15:10:56 +1000 Subject: Don't process input events while waiting for network response. (cherry picked from commit 4b84041c072325bd09bb7177d121330048133103) Reviewed-by: mbm --- src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp index 1cd84db..8019551 100644 --- a/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp +++ b/src/xmlpatterns/acceltree/qacceltreeresourceloader.cpp @@ -125,7 +125,7 @@ QNetworkReply *AccelTreeResourceLoader::load(const QUrl &uri, networkLoop.connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError))); networkLoop.connect(reply, SIGNAL(finished()), SLOT(finished())); - if(networkLoop.exec()) + if(networkLoop.exec(QEventLoop::ExcludeUserInputEvents)) { const QString errorMessage(escape(reply->errorString())); -- cgit v0.12 From dee897be8d8a9bbb67f654cee89337af6db09872 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 31 Jul 2009 10:58:21 +1000 Subject: Reorder flag values in ascending order Reviewed-by: Roberto Raggi --- src/corelib/kernel/qmetaobject.cpp | 8 ++++---- src/tools/moc/generator.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index fc17e00..fb59b98 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -148,7 +148,9 @@ enum PropertyFlags { Resettable = 0x00000004, EnumOrFlag = 0x00000008, StdCppSet = 0x00000100, -// Override = 0x00000200, +// Override = 0x00000200, + Constant = 0x00000400, + Final = 0x00000800, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, @@ -160,9 +162,7 @@ enum PropertyFlags { User = 0x00100000, ResolveUser = 0x00200000, Notify = 0x00400000, - Dynamic = 0x00800000, - Constant = 0x00000400, - Final = 0x00000800 + Dynamic = 0x00800000 }; enum MethodFlags { diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 6df762d..dd31336 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -56,6 +56,8 @@ enum PropertyFlags { EnumOrFlag = 0x00000008, StdCppSet = 0x00000100, // Override = 0x00000200, + Constant = 0x00000400, + Final = 0x00000800, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, @@ -67,10 +69,9 @@ enum PropertyFlags { User = 0x00100000, ResolveUser = 0x00200000, Notify = 0x00400000, - Dynamic = 0x00800000, - Constant = 0x00000400, - Final = 0x00000800 + Dynamic = 0x00800000 }; + enum MethodFlags { AccessPrivate = 0x00, AccessProtected = 0x01, -- cgit v0.12 From 78085510b570d3d1a16339e7440172f0955798d1 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 31 Jul 2009 11:13:43 +1000 Subject: Remove isDynamic property flag Reviewed-by: Roberto Raggi --- src/corelib/kernel/qmetaobject.cpp | 14 +------------- src/corelib/kernel/qmetaobject.h | 1 - src/tools/moc/generator.cpp | 3 +-- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index fb59b98..9ff0bc1 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -161,8 +161,7 @@ enum PropertyFlags { ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000, - Notify = 0x00400000, - Dynamic = 0x00800000 + Notify = 0x00400000 }; enum MethodFlags { @@ -2485,17 +2484,6 @@ bool QMetaProperty::isUser(const QObject *object) const } /*! - \internal -*/ -bool QMetaProperty::isDynamic() const -{ - if (!mobj) - return false; - int flags = mobj->d.data[handle + 2]; - return flags & Dynamic; -} - -/*! Returns true if the property is constant; otherwise returns false. A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 9f36106..419fe06 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -189,7 +189,6 @@ public: bool isStored(const QObject *obj = 0) const; bool isEditable(const QObject *obj = 0) const; bool isUser(const QObject *obj = 0) const; - bool isDynamic() const; bool isConstant() const; bool isFinal() const; diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index dd31336..e3ce2ec 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -68,8 +68,7 @@ enum PropertyFlags { ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000, - Notify = 0x00400000, - Dynamic = 0x00800000 + Notify = 0x00400000 }; enum MethodFlags { -- cgit v0.12 From 52e52af114a9ebb2534de0573ee52550dfdd0130 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Fri, 31 Jul 2009 11:49:45 +1000 Subject: Update QAbstractItemModel following review Reviewed-by: mbm --- src/corelib/kernel/qabstractitemmodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 01440e4..80da80e 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -481,11 +481,11 @@ namespace { }; } -Q_GLOBAL_STATIC(DefaultRoleNames, q_defaultRoleNames); +Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames) const QHash &QAbstractItemModelPrivate::defaultRoleNames() { - return *q_defaultRoleNames(); + return *qDefaultRoleNames(); } /*! -- cgit v0.12 From 4066cc8a2f2b824d1047913d863b4d3261dd2479 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 31 Jul 2009 09:09:47 +0200 Subject: Show open directory dialog for new gesture example RevBy: denis --- examples/gestures/imageviewer/main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/gestures/imageviewer/main.cpp b/examples/gestures/imageviewer/main.cpp index 6bda418..cd1928b 100644 --- a/examples/gestures/imageviewer/main.cpp +++ b/examples/gestures/imageviewer/main.cpp @@ -81,6 +81,9 @@ int main(int argc, char *argv[]) if (QApplication::arguments().size() > 1) w.openDirectory(QApplication::arguments().at(1)); + else + w.openDirectory(QFileDialog::getExistingDirectory(0, "Select image folder")); + return app.exec(); } -- cgit v0.12 From 65f6a08ba7d26405a9de683ea0806b400ba8b26d Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 31 Jul 2009 10:17:20 +0200 Subject: test that activation and this-object can be inherited from parent context --- tests/auto/qscriptcontext/tst_qscriptcontext.cpp | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp index d96006d..3c9ea4c9 100644 --- a/tests/auto/qscriptcontext/tst_qscriptcontext.cpp +++ b/tests/auto/qscriptcontext/tst_qscriptcontext.cpp @@ -72,6 +72,7 @@ private slots: void scopeChain(); void pushAndPopScope(); void getSetActivationObject(); + void inheritActivationAndThisObject(); void toString(); }; @@ -689,6 +690,35 @@ void tst_QScriptContext::getSetActivationObject() } } +static QScriptValue myEval(QScriptContext *ctx, QScriptEngine *eng) +{ + QString code = ctx->argument(0).toString(); + ctx->setActivationObject(ctx->parentContext()->activationObject()); + ctx->setThisObject(ctx->parentContext()->thisObject()); + return eng->evaluate(code); +} + +void tst_QScriptContext::inheritActivationAndThisObject() +{ + QScriptEngine eng; + eng.globalObject().setProperty("myEval", eng.newFunction(myEval)); + { + QScriptValue ret = eng.evaluate("var a = 123; myEval('a')"); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toInt32(), 123); + } + { + QScriptValue ret = eng.evaluate("(function() { return myEval('this'); }).call(Number)"); + QVERIFY(ret.isFunction()); + QVERIFY(ret.equals(eng.globalObject().property("Number"))); + } + { + QScriptValue ret = eng.evaluate("(function(a) { return myEval('a'); })(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toInt32(), 123); + } +} + static QScriptValue parentContextToString(QScriptContext *ctx, QScriptEngine *) { return ctx->parentContext()->toString(); -- cgit v0.12 From 919ac1291c6e7d163b58679eae691f866b40f71b Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 30 Jul 2009 14:09:22 +0200 Subject: Compile on HP-UXi There is no monotonic clock support on HP-UXi at all, and the _POSIX_MONOTONIC_CLOCK macro is not defined at all (not even to -1). We handle this in the event dispatcher, but not in qcore_unix.cpp. Since the monotonic clock time code has moved, the define of _POSIX_MONOTONIC_CLOCK to -1 should also move. Reviewed-by: thiago --- src/corelib/kernel/qcore_unix_p.h | 4 ++++ src/corelib/kernel/qeventdispatcher_unix_p.h | 3 --- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index dceb73a..69ebb05 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -323,6 +323,10 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) #endif // Q_OS_VXWORKS +#if !defined(_POSIX_MONOTONIC_CLOCK) +# define _POSIX_MONOTONIC_CLOCK -1 +#endif + bool qt_gettime_is_monotonic(); timeval qt_gettime(); Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 9c67c70..5e016d3 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -69,9 +69,6 @@ #endif QT_BEGIN_NAMESPACE -#if !defined(_POSIX_MONOTONIC_CLOCK) -# define _POSIX_MONOTONIC_CLOCK -1 -#endif // internal timer info struct QTimerInfo { -- cgit v0.12 From 18fbfdf0f774198e2e1277e064cc3a8eb9dbb29d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 31 Jul 2009 10:30:44 +0200 Subject: Fix compilation with xlC 7: operands to ?: must match. See 3ae2cab9c8bd1790a00da2755ac036143a3a35f4 for another similar fix. Reviewed-by: Trust Me --- tools/linguist/shared/po.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/linguist/shared/po.cpp b/tools/linguist/shared/po.cpp index 796d012..a6795cb 100644 --- a/tools/linguist/shared/po.cpp +++ b/tools/linguist/shared/po.cpp @@ -359,7 +359,7 @@ bool loadPO(Translator &translator, QIODevice &dev, ConversionData &cd) const QChar quote = QLatin1Char('"'); const QChar newline = QLatin1Char('\n'); QTextStream in(&dev); - in.setCodec(cd.m_codecForSource.isEmpty() ? "UTF-8" : cd.m_codecForSource); + in.setCodec(cd.m_codecForSource.isEmpty() ? QByteArray("UTF-8") : cd.m_codecForSource); bool error = false; // format of a .po file entry: @@ -555,7 +555,7 @@ bool savePO(const Translator &translator, QIODevice &dev, ConversionData &cd) { bool ok = true; QTextStream out(&dev); - out.setCodec(cd.m_outputCodec.isEmpty() ? "UTF-8" : cd.m_outputCodec); + out.setCodec(cd.m_outputCodec.isEmpty() ? QByteArray("UTF-8") : cd.m_outputCodec); bool first = true; if (translator.messages().isEmpty() || !translator.messages().first().sourceText().isEmpty()) { -- cgit v0.12 From 1a7286691a74016a0577073275fc462aea2fe1bc Mon Sep 17 00:00:00 2001 From: Geir Vattekar Date: Fri, 31 Jul 2009 11:07:13 +0200 Subject: Doc: Fixed a snippet bug in QFileInfo Task-number: 258371 Reviewed-by: Trust Me --- doc/src/snippets/code/src_corelib_io_qfileinfo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/src/snippets/code/src_corelib_io_qfileinfo.cpp b/doc/src/snippets/code/src_corelib_io_qfileinfo.cpp index 2ab15ee..89b4f33 100644 --- a/doc/src/snippets/code/src_corelib_io_qfileinfo.cpp +++ b/doc/src/snippets/code/src_corelib_io_qfileinfo.cpp @@ -13,9 +13,9 @@ info1.size(); // returns 56201 info1.symLinkTarget(); // returns "/opt/pretty++/bin/untabify" QFileInfo info2(info1.symLinkTarget()); -info1.isSymLink(); // returns false -info1.absoluteFilePath(); // returns "/opt/pretty++/bin/untabify" -info1.size(); // returns 56201 +info2.isSymLink(); // returns false +info2.absoluteFilePath(); // returns "/opt/pretty++/bin/untabify" +info2.size(); // returns 56201 #endif //! [0] -- cgit v0.12 From 8a0a59e6776e1384f884e0f6e7ec6fe10f3be054 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 31 Jul 2009 11:28:34 +0200 Subject: remove const from QSignalEvent::sender* QObject::sender() does not return const QObject*, so neither should this API; it just forces you to const_cast for no good reason. --- src/corelib/statemachine/qsignalevent.h | 6 +++--- src/corelib/statemachine/qstatemachine.cpp | 4 ++-- src/corelib/statemachine/qstatemachine_p.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h index c09c5a3..b7ca61f 100644 --- a/src/corelib/statemachine/qsignalevent.h +++ b/src/corelib/statemachine/qsignalevent.h @@ -58,16 +58,16 @@ QT_MODULE(Core) class Q_CORE_EXPORT QSignalEvent : public QEvent { public: - QSignalEvent(const QObject *sender, int signalIndex, + QSignalEvent(QObject *sender, int signalIndex, const QList &arguments); ~QSignalEvent(); - inline const QObject *sender() const { return m_sender; } + inline QObject *sender() const { return m_sender; } inline int signalIndex() const { return m_signalIndex; } inline QList arguments() const { return m_arguments; } private: - const QObject *m_sender; + QObject *m_sender; int m_signalIndex; QList m_arguments; }; diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index a02480b..d89ad98 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1446,7 +1446,7 @@ void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transitio } #endif -void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int signalIndex, +void QStateMachinePrivate::handleTransitionSignal(QObject *sender, int signalIndex, void **argv) { Q_ASSERT(connections[sender].at(signalIndex) != 0); @@ -2026,7 +2026,7 @@ QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent) Constructs a new QSignalEvent object with the given \a sender, \a signalIndex and \a arguments. */ -QSignalEvent::QSignalEvent(const QObject *sender, int signalIndex, +QSignalEvent::QSignalEvent(QObject *sender, int signalIndex, const QList &arguments) : QEvent(QEvent::Signal), m_sender(sender), m_signalIndex(signalIndex), m_arguments(arguments) diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index cae21aa..590cffe 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -147,7 +147,7 @@ public: #endif void unregisterTransition(QAbstractTransition *transition); void unregisterAllTransitions(); - void handleTransitionSignal(const QObject *sender, int signalIndex, + void handleTransitionSignal(QObject *sender, int signalIndex, void **args); void scheduleProcess(); -- cgit v0.12 From f12085f8a00957ed17c33e9d75e51dc74a3d2115 Mon Sep 17 00:00:00 2001 From: kh Date: Fri, 31 Jul 2009 12:02:46 +0200 Subject: Fix internal documentation after QUrl change. Reviewed-by: kh --- tools/assistant/tools/assistant/assistant.qch | Bin 368640 -> 368640 bytes tools/assistant/tools/assistant/doc/assistant.qhp | 2 +- tools/assistant/tools/assistant/helpviewer.cpp | 4 ++-- tools/assistant/tools/assistant/main.cpp | 2 +- tools/assistant/tools/assistant/mainwindow.cpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/assistant/tools/assistant/assistant.qch b/tools/assistant/tools/assistant/assistant.qch index 99687ed..3e66bd9 100644 Binary files a/tools/assistant/tools/assistant/assistant.qch and b/tools/assistant/tools/assistant/assistant.qch differ diff --git a/tools/assistant/tools/assistant/doc/assistant.qhp b/tools/assistant/tools/assistant/doc/assistant.qhp index 7a26101..7ea4cdd 100644 --- a/tools/assistant/tools/assistant/doc/assistant.qhp +++ b/tools/assistant/tools/assistant/doc/assistant.qhp @@ -1,7 +1,7 @@ assistant - com.trolltech.com.assistantinternal_1.0.0 + com.trolltech.com.assistantinternal-1.0.0 assistant.html diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp index 6799db3..5422bf46 100644 --- a/tools/assistant/tools/assistant/helpviewer.cpp +++ b/tools/assistant/tools/assistant/helpviewer.cpp @@ -306,7 +306,7 @@ void HelpViewer::setSource(const QUrl &url) loadFinished = false; if (url.toString() == QLatin1String("help")) { load(QUrl(QLatin1String("qthelp://com.trolltech.com." - "assistantinternal_1.0.0/assistant/assistant.html"))); + "assistantinternal-1.0.0/assistant/assistant.html"))); } else { load(url); } @@ -425,7 +425,7 @@ void HelpViewer::setSource(const QUrl &url) if (help) { QTextBrowser::setSource(QUrl(QLatin1String("qthelp://com.trolltech.com." - "assistantinternal_1.0.0/assistant/assistant.html"))); + "assistantinternal-1.0.0/assistant/assistant.html"))); } else { QTextBrowser::setSource(url); setHtml(tr("Error 404...


" diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp index 05355d9..a0a5a0d 100644 --- a/tools/assistant/tools/assistant/main.cpp +++ b/tools/assistant/tools/assistant/main.cpp @@ -306,7 +306,7 @@ int main(int argc, char *argv[]) } } - QLatin1String intern("com.trolltech.com.assistantinternal_"); + QLatin1String intern("com.trolltech.com.assistantinternal-"); foreach (const QString &doc, userDocs) { if (!callerDocs.contains(doc) && !doc.startsWith(intern)) user.unregisterDocumentation(doc); diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp index 7926020..0c1723c 100644 --- a/tools/assistant/tools/assistant/mainwindow.cpp +++ b/tools/assistant/tools/assistant/mainwindow.cpp @@ -274,7 +274,7 @@ bool MainWindow::initHelpDB() return false; bool assistantInternalDocRegistered = false; - QString intern(QLatin1String("com.trolltech.com.assistantinternal_")); + QString intern(QLatin1String("com.trolltech.com.assistantinternal-")); foreach (const QString &ns, m_helpEngine->registeredDocumentations()) { if (ns.startsWith(intern)) { intern = ns; -- cgit v0.12 From fbbd7f9a27216dc66a77a064179a4775ce9fb91e Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 31 Jul 2009 13:42:08 +0200 Subject: add private goToState() function to state machine Needed for Declarative UI integration. --- src/corelib/statemachine/qstatemachine.cpp | 96 ++++++++++++++++++++++++-- src/corelib/statemachine/qstatemachine_p.h | 8 ++- tests/auto/qstatemachine/tst_qstatemachine.cpp | 41 +++++++++++ 3 files changed, 138 insertions(+), 7 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index d89ad98..5aa5917 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -205,6 +205,7 @@ This is QStateMachinePrivate::QStateMachinePrivate() { state = NotRunning; + _startState = 0; processing = false; processingScheduled = false; stop = false; @@ -1146,6 +1147,20 @@ protected: } // namespace +QState *QStateMachinePrivate::startState() +{ + Q_Q(QStateMachine); + if (_startState == 0) + _startState = new StartState(q); + return _startState; +} + +void QStateMachinePrivate::removeStartState() +{ + delete _startState; + _startState = 0; +} + void QStateMachinePrivate::_q_start() { Q_Q(QStateMachine); @@ -1165,11 +1180,19 @@ void QStateMachinePrivate::_q_start() processingScheduled = true; // we call _q_process() below emit q->started(); - StartState *start = new StartState(rootState()); - QAbstractTransition *initialTransition = new InitialTransition(initial); - start->addTransition(initialTransition); - QList transitions; - transitions.append(initialTransition); + QState *start = startState(); + Q_ASSERT(start != 0); + + QList transitions = QStatePrivate::get(start)->transitions(); + + // If a transition has already been added, then we skip this step, as the + // initial transition in that case has been overridden. + if (transitions.isEmpty()) { + QAbstractTransition *initialTransition = new InitialTransition(initial); + start->addTransition(initialTransition); + transitions.append(initialTransition); + } + QEvent nullEvent(QEvent::None); executeTransitionContent(&nullEvent, transitions); QList enteredStates = enterStates(&nullEvent, transitions); @@ -1177,7 +1200,7 @@ void QStateMachinePrivate::_q_start() applyProperties(transitions, QList() << start, enteredStates); #endif - delete start; + removeStartState(); #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": initial configuration:" << configuration; @@ -1277,6 +1300,67 @@ void QStateMachinePrivate::scheduleProcess() QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection); } +namespace { + +class GoToStateTransition : public QAbstractTransition +{ +public: + GoToStateTransition(QAbstractState *target) + : QAbstractTransition(QList() << target) {} +protected: + void onTransition(QEvent *) { deleteLater(); } + bool eventTest(QEvent *) { return true; } +}; + +} // namespace + +/*! + \internal + + Causes this state machine to unconditionally transition to the given + \a targetState. + + Provides a backdoor for using the state machine "imperatively"; i.e. rather + than defining explicit transitions, you drive the machine's execution by + calling this function. It breaks the whole integrity of the + transition-driven model, but is provided for pragmatic reasons. +*/ +void QStateMachinePrivate::goToState(QAbstractState *targetState) +{ + if (!targetState) { + qWarning("QStateMachine::goToState(): cannot go to null state"); + return; + } + + if (configuration.contains(targetState)) + return; + + QState *sourceState = 0; + if (state == Running) { + QSet::const_iterator it; + for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { + sourceState = qobject_cast(*it); + if (sourceState != 0) + break; + } + } else { + sourceState = startState(); + } + + Q_ASSERT(sourceState != 0); + // Reuse previous GoToStateTransition in case of several calls to + // goToState() in a row. + GoToStateTransition *trans = qFindChild(sourceState); + if (!trans) { + trans = new GoToStateTransition(targetState); + sourceState->addTransition(trans); + } else { + trans->setTargetState(targetState); + } + + scheduleProcess(); +} + void QStateMachinePrivate::registerTransitions(QAbstractState *state) { QState *group = qobject_cast(state); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 590cffe..714a40b 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -79,7 +79,7 @@ class QAbstractAnimation; #endif class QStateMachine; -class QStateMachinePrivate : public QStatePrivate +class Q_AUTOTEST_EXPORT QStateMachinePrivate : public QStatePrivate { Q_DECLARE_PUBLIC(QStateMachine) public: @@ -116,6 +116,9 @@ public: QState *rootState() const; + QState *startState(); + void removeStartState(); + void microstep(QEvent *event, const QList &transitionList); bool isPreempted(const QAbstractState *s, const QSet &transitions) const; QSet selectTransitions(QEvent *event) const; @@ -138,6 +141,8 @@ public: static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other); static QList properAncestors(const QAbstractState *s, const QState *upperBound); + void goToState(QAbstractState *targetState); + void registerTransitions(QAbstractState *state); void registerSignalTransition(QSignalTransition *transition); void unregisterSignalTransition(QSignalTransition *transition); @@ -162,6 +167,7 @@ public: #endif State state; + QState *_startState; bool processing; bool processingScheduled; bool stop; diff --git a/tests/auto/qstatemachine/tst_qstatemachine.cpp b/tests/auto/qstatemachine/tst_qstatemachine.cpp index 7f4d9f5..32812e2 100644 --- a/tests/auto/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/qstatemachine/tst_qstatemachine.cpp @@ -192,6 +192,7 @@ private slots: // void overrideDefaultTargetAnimationWithSource(); void nestedStateMachines(); + void goToState(); }; tst_QStateMachine::tst_QStateMachine() @@ -3900,5 +3901,45 @@ void tst_QStateMachine::nestedStateMachines() QTRY_COMPARE(finishedSpy.count(), 1); } +void tst_QStateMachine::goToState() +{ + QStateMachine machine; + QState *s1 = new QState(&machine); + QState *s2 = new QState(&machine); + machine.setInitialState(s1); + QSignalSpy startedSpy(&machine, SIGNAL(started())); + machine.start(); + QTRY_COMPARE(startedSpy.count(), 1); + + QStateMachinePrivate::get(&machine)->goToState(s2); + QCoreApplication::processEvents(); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s2)); + + QStateMachinePrivate::get(&machine)->goToState(s2); + QCoreApplication::processEvents(); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s2)); + + QStateMachinePrivate::get(&machine)->goToState(s1); + QStateMachinePrivate::get(&machine)->goToState(s2); + QStateMachinePrivate::get(&machine)->goToState(s1); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s2)); + + QCoreApplication::processEvents(); + QCOMPARE(machine.configuration().size(), 1); + QVERIFY(machine.configuration().contains(s1)); + + // go to state in group + QState *s2_1 = new QState(s2); + s2->setInitialState(s2_1); + QStateMachinePrivate::get(&machine)->goToState(s2_1); + QCoreApplication::processEvents(); + QCOMPARE(machine.configuration().size(), 2); + QVERIFY(machine.configuration().contains(s2)); + QVERIFY(machine.configuration().contains(s2_1)); +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v0.12 From 18d9902a2c5650e48a33b09ef68596479e7cb9ff Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 31 Jul 2009 13:40:17 +0200 Subject: Fix compilation: add #include if placement new is used I'm not sure this is the proper fix, though. xlC 7 complains with: "/usr/vacpp/include/new", line 97.10: 1540-1298 (I) "void *operator new(size_t, void *) throw()" needs to be declared in the containing scope to be found by name lookup. Also add some calculations to the padding in the data structure. Reviewed-by: Trust Me --- src/corelib/tools/qcontiguouscache.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 0020d22..7221925 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -44,6 +44,7 @@ #include #include +#include QT_BEGIN_HEADER @@ -76,6 +77,12 @@ struct QContiguousCacheTypedData int start; int offset; uint sharable : 1; + // uint unused : 31; + + // total is 24 bytes (HP-UX aCC: 40 bytes) + // the next entry is already aligned to 8 bytes + // there will be an 8 byte gap here if T requires 16-byte alignment + // (such as long double on 64-bit platforms, __int128, __float128) T array[1]; }; -- cgit v0.12 From 991c2299078978d38692b3499580eb86d0ed7d9b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 31 Jul 2009 13:56:37 +0200 Subject: Revert "Small simplification of code in ItemViews (delegate)" This reverts commit 95560abfdd3a1755b69f238eff2954d164dff6a5. Fix comboboxes used as editor. isAncestor() stops at windows. we want to go tought the whole widget chain, including parent windows Use case: examples/itemviews/coloreditorfactory/coloreditorfactory Task-number: 259034 --- src/gui/itemviews/qitemdelegate.cpp | 9 ++++++--- src/gui/itemviews/qstyleditemdelegate.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/gui/itemviews/qitemdelegate.cpp b/src/gui/itemviews/qitemdelegate.cpp index 336ca79..aff715c 100644 --- a/src/gui/itemviews/qitemdelegate.cpp +++ b/src/gui/itemviews/qitemdelegate.cpp @@ -1226,9 +1226,12 @@ bool QItemDelegate::eventFilter(QObject *object, QEvent *event) } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) { //the Hide event will take care of he editors that are in fact complete dialogs if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) { - if (editor->isAncestorOf(QApplication::focusWidget())) - return false; // don't worry about focus changes internally in the editor - + QWidget *w = QApplication::focusWidget(); + while (w) { // don't worry about focus changes internally in the editor + if (w == editor) + return false; + w = w->parentWidget(); + } #ifndef QT_NO_DRAGANDDROP // The window may lose focus during an drag operation. // i.e when dragging involves the taskbar on Windows. diff --git a/src/gui/itemviews/qstyleditemdelegate.cpp b/src/gui/itemviews/qstyleditemdelegate.cpp index bd8fdac..7ec2afe 100644 --- a/src/gui/itemviews/qstyleditemdelegate.cpp +++ b/src/gui/itemviews/qstyleditemdelegate.cpp @@ -674,9 +674,12 @@ bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event) } else if (event->type() == QEvent::FocusOut || (event->type() == QEvent::Hide && editor->isWindow())) { //the Hide event will take care of he editors that are in fact complete dialogs if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) { - if (editor->isAncestorOf(QApplication::focusWidget())) - return false; // don't worry about focus changes internally in the editor - + QWidget *w = QApplication::focusWidget(); + while (w) { // don't worry about focus changes internally in the editor + if (w == editor) + return false; + w = w->parentWidget(); + } #ifndef QT_NO_DRAGANDDROP // The window may lose focus during an drag operation. // i.e when dragging involves the taskbar on Windows. -- cgit v0.12 From 193b109814a0bbf4fc8b5d7bd8911c920194838d Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 31 Jul 2009 14:25:58 +0200 Subject: compile Broke on WinCE since QStateMachinePrivate is now using Q_AUTOTEST_EXPORT. --- src/corelib/statemachine/qstatemachine_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 714a40b..5d8c788 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -214,7 +214,7 @@ public: f_cloneEvent cloneEvent; }; - static Q_CORE_EXPORT const Handler *handler; + static const Handler *handler; }; QT_END_NAMESPACE -- cgit v0.12 From 7c4b1863495905c3486ea36e0d559f49c6f2ebb4 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 31 Jul 2009 14:33:30 +0200 Subject: Doc: fix warnings. --- src/corelib/kernel/qabstractitemmodel.cpp | 2 +- src/testlib/qtestcase.cpp | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 80da80e..bc95c60 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -1902,7 +1902,7 @@ void QAbstractItemModel::setRoleNames(const QHash &roleNames) /*! Returns the model's role names. - \sa setRoleNames + \sa setRoleNames() */ const QHash &QAbstractItemModel::roleNames() const { diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index 1dae828..ac4ca83 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -818,6 +818,8 @@ void filter_unprintable(char *str) } } +/*! \internal + */ int qt_asprintf(char **str, const char *format, ...) { static const int MAXSIZE = 1024*1024*2; -- cgit v0.12 From c0f0e798e903c39d5f8b6dc6dd2abdfbcc8a7d93 Mon Sep 17 00:00:00 2001 From: ck Date: Fri, 31 Jul 2009 14:41:45 +0200 Subject: Assistant: Performance fixes for help generator's pattern matching. Reading a help project was unacceptably slow with pattern matching. Now we do it only for filenames that contain wildcard symbols. Also, we cache the results of QDir::entryList() calls. --- tools/assistant/lib/qhelpprojectdata.cpp | 43 ++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/tools/assistant/lib/qhelpprojectdata.cpp b/tools/assistant/lib/qhelpprojectdata.cpp index 55b4ea7..5df0426 100644 --- a/tools/assistant/lib/qhelpprojectdata.cpp +++ b/tools/assistant/lib/qhelpprojectdata.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,8 @@ private: void readFiles(); void raiseUnknownTokenError(); void addMatchingFiles(const QString &pattern); + + QMap dirEntriesCache; }; void QHelpProjectDataPrivate::raiseUnknownTokenError() @@ -265,14 +268,40 @@ void QHelpProjectDataPrivate::readFiles() // meaningful warning later. void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern) { + // The pattern matching is expensive, so we skip it if no + // wildcard symbols occur in the string. + if (!pattern.contains('?') && !pattern.contains('*') + && !pattern.contains('[') && !pattern.contains(']')) { + filterSectionList.last().addFile(pattern); + return; + } + QFileInfo fileInfo(rootPath + '/' + pattern); - const QStringList &matches = - fileInfo.dir().entryList(QStringList(fileInfo.fileName())); - for (QStringList::ConstIterator it = matches.constBegin(); - it != matches.constEnd(); - ++it) - filterSectionList.last().addFile(QFileInfo(pattern).dir().path() + '/' + *it); - if (matches.empty()) + const QDir &dir = fileInfo.dir(); + const QString &path = dir.canonicalPath(); + + // QDir::entryList() is expensive, so we cache the results. + QMap::ConstIterator it = dirEntriesCache.find(path); + const QStringList &entries = it != dirEntriesCache.constEnd() ? + it.value() : dir.entryList(QDir::Files); + if (it == dirEntriesCache.constEnd()) + dirEntriesCache.insert(path, entries); + + bool matchFound = false; +#ifdef Q_OS_WIN + Qt::CaseSensitivity cs = Qt::CaseInSensitive; +#else + Qt::CaseSensitivity cs = Qt::CaseSensitive; +#endif + QRegExp regExp(fileInfo.fileName(), cs, QRegExp::Wildcard); + foreach (const QString &file, entries) { + if (regExp.exactMatch(file)) { + matchFound = true; + filterSectionList.last(). + addFile(QFileInfo(pattern).dir().path() + '/' + file); + } + } + if (!matchFound) filterSectionList.last().addFile(pattern); } -- cgit v0.12 From 9d511567ece87258ab0bdc77f8c0ab62c075f454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Fri, 31 Jul 2009 14:52:29 +0200 Subject: Crash DirectFb plugin when resizing verticaly QRasterPaintEngine assumes device does not change size. Therefore create a new engine when resizing. Reviewed-by: Tom --- src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index a1009ac..8cddc76 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -209,7 +209,6 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) if (!dfbWindow) createWindow(); ::setGeometry(dfbWindow, oldRect, rect); - // ### do I need to release and get the surface again here? #endif break; case Offscreen: { @@ -227,7 +226,10 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) if (result != DFB_OK) DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result); } - + if (engine) { + delete engine; + engine = 0; + } QWSWindowSurface::setGeometry(rect); } -- cgit v0.12 From 7c56a5b3825de2372712b9f0087df868ca1fd157 Mon Sep 17 00:00:00 2001 From: Prasanth Ullattil Date: Thu, 30 Jul 2009 13:12:56 +0200 Subject: QCheckBox on an out-of-process server wont allow key & Focus rect is not drawn correctly. Depending on the type of server, QAxClientSite::TranslateAccelerator() needs to process the message differently. For ActiveQt based in-process-servers, only normal Qt event handling is required. For ActiveQt based out-of-process-servers, the message has to be forwarded and Qt event handling needs to continue. For all other type of servers, forward the message and stop Qt event processing. Styles use the WA_KeyboardFocusChange attribute set on the window to decide on drawing the focus rect. ActiveQt handles the VK_TAB key in the QAxServerBase::TranslateAcceleratorW(), the attibute is now set when focus is changed. Task-number: 253763 Reviewed-by: Volker Hilsheimer --- src/activeqt/container/qaxwidget.cpp | 40 ++++++++++++++- src/activeqt/control/qaxserverbase.cpp | 90 ++++++++++++++++++---------------- src/activeqt/shared/qaxtypes.h | 3 ++ 3 files changed, 90 insertions(+), 43 deletions(-) diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp index ae468ef..19f00db 100644 --- a/src/activeqt/container/qaxwidget.cpp +++ b/src/activeqt/container/qaxwidget.cpp @@ -118,6 +118,8 @@ public: QSize minimumSizeHint() const; int qt_metacall(QMetaObject::Call, int isignal, void **argv); + void* qt_metacast(const char *clname); + inline QAxClientSite *clientSite() const { return axhost; @@ -478,7 +480,9 @@ bool axc_FilterProc(void *m) QAxWidget *ax = 0; QAxHostWidget *host = 0; while (!host && hwnd) { - host = qobject_cast(QWidget::find(hwnd)); + QWidget *widget = QWidget::find(hwnd); + if (widget && widget->inherits("QAxHostWidget")) + host = qobject_cast(widget); hwnd = ::GetParent(hwnd); } if (host) @@ -976,10 +980,34 @@ HRESULT WINAPI QAxClientSite::TransformCoords(POINTL* /*pPtlHimetric*/, POINTF* HRESULT WINAPI QAxClientSite::TranslateAccelerator(LPMSG lpMsg, DWORD /*grfModifiers*/) { - eventTranslated = false; if (lpMsg->message == WM_KEYDOWN && !lpMsg->wParam) return S_OK; + + bool ActiveQtDetected = false; + bool fromInProcServer = false; + LONG_PTR serverType = GetWindowLongPtr(lpMsg->hwnd, GWLP_USERDATA); + if (serverType == QAX_INPROC_SERVER) { + ActiveQtDetected = true; + fromInProcServer = true; + } else if (serverType == QAX_OUTPROC_SERVER) { + ActiveQtDetected = true; + fromInProcServer = false; + } + + eventTranslated = false; + if (!ActiveQtDetected || !fromInProcServer) { + // if the request is coming from an out-of-proc server or a non ActiveQt server, + // we send the message to the host window. This will make sure this key event + // comes to Qt for processing. SendMessage(host->winId(), lpMsg->message, lpMsg->wParam, lpMsg->lParam); + if (ActiveQtDetected && !fromInProcServer) { + // ActiveQt based servers will need further processing of the event + // (eg. key for a checkbox), so we return false. + return S_FALSE; + } + } + // ActiveQt based in-processes-servers will handle the event properly, so + // we dont need to send this key event to the host. return S_OK; } @@ -1617,6 +1645,14 @@ int QAxHostWidget::qt_metacall(QMetaObject::Call call, int isignal, void **argv) return -1; } +void* QAxHostWidget::qt_metacast(const char *clname) +{ + if (!clname) return 0; + if (!qstrcmp(clname,"QAxHostWidget")) + return static_cast(const_cast< QAxHostWidget*>(this)); + return QWidget::qt_metacast(clname); +} + QSize QAxHostWidget::sizeHint() const { return axhost ? axhost->sizeHint() : QWidget::sizeHint(); diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp index d7a8e07..e482c60 100644 --- a/src/activeqt/control/qaxserverbase.cpp +++ b/src/activeqt/control/qaxserverbase.cpp @@ -3502,24 +3502,24 @@ Q_GUI_EXPORT int qt_translateKeyCode(int); HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg) { if (pMsg->message != WM_KEYDOWN || !isWidget) - return S_FALSE; + return S_FALSE; DWORD dwKeyMod = 0; if (::GetKeyState(VK_SHIFT) < 0) - dwKeyMod |= 1; // KEYMOD_SHIFT + dwKeyMod |= 1; // KEYMOD_SHIFT if (::GetKeyState(VK_CONTROL) < 0) - dwKeyMod |= 2; // KEYMOD_CONTROL + dwKeyMod |= 2; // KEYMOD_CONTROL if (::GetKeyState(VK_MENU) < 0) - dwKeyMod |= 4; // KEYMOD_ALT + dwKeyMod |= 4; // KEYMOD_ALT switch (LOWORD(pMsg->wParam)) { case VK_TAB: - if (isUIActive) { - bool shift = ::GetKeyState(VK_SHIFT) < 0; - bool giveUp = true; + if (isUIActive) { + bool shift = ::GetKeyState(VK_SHIFT) < 0; + bool giveUp = true; QWidget *curFocus = qt.widget->focusWidget(); if (curFocus) { - if (shift) { + if (shift) { if (!curFocus->isWindow()) { QWidget *nextFocus = curFocus->nextInFocusChain(); QWidget *prevFocus = 0; @@ -3537,9 +3537,10 @@ HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg) if (!topLevel) { giveUp = false; ((HackWidget*)curFocus)->focusNextPrevChild(false); + curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange); } } - } else { + } else { QWidget *nextFocus = curFocus; while (1) { nextFocus = nextFocus->nextInFocusChain(); @@ -3548,63 +3549,70 @@ HRESULT WINAPI QAxServerBase::TranslateAcceleratorW(MSG *pMsg) if (nextFocus->focusPolicy() & Qt::TabFocus) { giveUp = false; ((HackWidget*)curFocus)->focusNextPrevChild(true); + curFocus->window()->setAttribute(Qt::WA_KeyboardFocusChange); break; } } - } + } + } + if (giveUp) { + HWND hwnd = ::GetParent(m_hWnd); + ::SetFocus(hwnd); + } else { + return S_OK; } - if (giveUp) { - HWND hwnd = ::GetParent(m_hWnd); - ::SetFocus(hwnd); - } else { - return S_OK; - } - } - break; + } + break; case VK_LEFT: case VK_RIGHT: case VK_UP: case VK_DOWN: - if (isUIActive) - return S_FALSE; - break; + if (isUIActive) + return S_FALSE; + break; default: - if (isUIActive && qt.widget->focusWidget()) { + if (isUIActive && qt.widget->focusWidget()) { int state = Qt::NoButton; - if (dwKeyMod & 1) - state |= Qt::ShiftModifier; - if (dwKeyMod & 2) - state |= Qt::ControlModifier; - if (dwKeyMod & 4) - state |= Qt::AltModifier; - - int key = pMsg->wParam; + if (dwKeyMod & 1) + state |= Qt::ShiftModifier; + if (dwKeyMod & 2) + state |= Qt::ControlModifier; + if (dwKeyMod & 4) + state |= Qt::AltModifier; + + int key = pMsg->wParam; if (!(key >= 'A' && key <= 'Z') && !(key >= '0' && key <= '9')) key = qt_translateKeyCode(pMsg->wParam); - QKeyEvent override(QEvent::ShortcutOverride, key, (Qt::KeyboardModifiers)state); - override.ignore(); - QApplication::sendEvent(qt.widget->focusWidget(), &override); - if (override.isAccepted()) - return S_FALSE; - } - break; + QKeyEvent override(QEvent::ShortcutOverride, key, (Qt::KeyboardModifiers)state); + override.ignore(); + QApplication::sendEvent(qt.widget->focusWidget(), &override); + if (override.isAccepted()) + return S_FALSE; + } + break; } if (!m_spClientSite) - return S_FALSE; + return S_FALSE; IOleControlSite *controlSite = 0; m_spClientSite->QueryInterface(IID_IOleControlSite, (void**)&controlSite); if (!controlSite) - return S_FALSE; - + return S_FALSE; + bool resetUserData = false; + // set server type in the user-data of the window. + LONG_PTR serverType = QAX_INPROC_SERVER; + if (qAxOutProcServer) + serverType = QAX_OUTPROC_SERVER; + LONG_PTR oldData = SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, serverType); HRESULT hres = controlSite->TranslateAcceleratorW(pMsg, dwKeyMod); - controlSite->Release(); + // reset the user-data for the window. + SetWindowLongPtr(pMsg->hwnd, GWLP_USERDATA, oldData); return hres; } diff --git a/src/activeqt/shared/qaxtypes.h b/src/activeqt/shared/qaxtypes.h index 4f647a3..e3c7138 100644 --- a/src/activeqt/shared/qaxtypes.h +++ b/src/activeqt/shared/qaxtypes.h @@ -89,6 +89,9 @@ extern QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName extern bool QVariantToVoidStar(const QVariant &var, void *data, const QByteArray &typeName, uint type = 0); extern void clearVARIANT(VARIANT *var); +#define QAX_INPROC_SERVER (0x51540001) +#define QAX_OUTPROC_SERVER (0x51540002) + QT_END_NAMESPACE #endif // QT_NO_WIN_ACTIVEQT -- cgit v0.12 From ed6e0d67211938de7bcba844519d5bad8d2965b6 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 31 Jul 2009 15:30:12 +0200 Subject: Export symbol used in QtGui. Reviewed-by: Kent Hansen --- src/corelib/statemachine/qstatemachine_p.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 5d8c788..387e42e 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -214,7 +214,11 @@ public: f_cloneEvent cloneEvent; }; - static const Handler *handler; + static +#ifndef QT_BUILD_INTERNAL // otherwise Q_AUTOTEST_EXPORT exports it all + Q_CORE_EXPORT +#endif + const Handler *handler; }; QT_END_NAMESPACE -- cgit v0.12 From 2cadc571339d4abee6d7cfb0da08e3119d934524 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 31 Jul 2009 15:52:55 +0200 Subject: Doc: Use new APIs in example and correct documentation regarding replacement. --- doc/src/examples/collidingmice-example.qdoc | 4 ++-- examples/graphicsview/collidingmice/mouse.cpp | 4 ++-- src/gui/graphicsview/qgraphicsitem.cpp | 31 +++++++++++++++++++++++---- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/doc/src/examples/collidingmice-example.qdoc b/doc/src/examples/collidingmice-example.qdoc index 5b124f9..f627fbf 100644 --- a/doc/src/examples/collidingmice-example.qdoc +++ b/doc/src/examples/collidingmice-example.qdoc @@ -95,11 +95,11 @@ the global qrand() function which is a thread-safe version of the standard C++ rand() function. - Then we call the \l {QGraphicsItem::rotate()}{rotate()} function + Then we call the \l {QGraphicsItem::setRotation()}{setRotation()} function inherited from QGraphicsItem. Items live in their own local coordinate system. Their coordinates are usually centered around (0, 0), and this is also the center for all transformations. By - calling the item's \l {QGraphicsItem::rotate()}{rotate()} function + calling the item's \l {QGraphicsItem::setRotation()}{setRotation()} function we alter the direction in which the mouse will start moving. When the QGraphicsScene decides to advance the scene a frame it will call diff --git a/examples/graphicsview/collidingmice/mouse.cpp b/examples/graphicsview/collidingmice/mouse.cpp index c6a67b1..4cc29dd 100644 --- a/examples/graphicsview/collidingmice/mouse.cpp +++ b/examples/graphicsview/collidingmice/mouse.cpp @@ -64,7 +64,7 @@ Mouse::Mouse() : angle(0), speed(0), mouseEyeDirection(0), color(qrand() % 256, qrand() % 256, qrand() % 256) { - rotate(qrand() % (360 * 16)); + setRotation(qrand() % (360 * 16)); } //! [0] @@ -195,7 +195,7 @@ void Mouse::advance(int step) qreal dx = ::sin(angle) * 10; mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; - rotate(dx); + setRotation(rotation() + dx); setPos(mapToParent(0, -(3 + sin(speed) * 3))); } //! [11] diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index eaf9896..a4eca4d 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3535,7 +3535,13 @@ void QGraphicsItem::resetTransform() /*! \obsolete - Use setRotation() instead + Use + + \code + setRotation(rotation() + angle); + \endcode + + instead. Rotates the current item transformation \a angle degrees clockwise around its origin. To translate around an arbitrary point (x, y), you need to @@ -3555,7 +3561,13 @@ void QGraphicsItem::rotate(qreal angle) /*! \obsolete - Use setScale() instead + Use + + \code + setTransform(QTransform::fromScale(sx, sy), true); + \encode + + instead. Scales the current item transformation by (\a sx, \a sy) around its origin. To scale from an arbitrary point (x, y), you need to combine @@ -3575,7 +3587,13 @@ void QGraphicsItem::scale(qreal sx, qreal sy) /*! \obsolete - Use setTransform() instead. + Use + + \code + setTransform(QTransform().shear(sh, sv), true); + \endcode + + instead. Shears the current item transformation by (\a sh, \a sv). @@ -3589,7 +3607,12 @@ void QGraphicsItem::shear(qreal sh, qreal sv) /*! \obsolete - Use setPos() or setTransformOriginPoint() instead. + Use setPos() or setTransformOriginPoint() instead. For identical + behavior, use + + \code + setTransform(QTransform::fromTranslate(dx, dy), true); + \endcode Translates the current item transformation by (\a dx, \a dy). -- cgit v0.12 From c6cdfcb02d74f726e79ead9f890f294587a7c63c Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 31 Jul 2009 15:55:41 +0200 Subject: Doc: Use new APIs in example and correct documentation regarding replacement. --- src/gui/graphicsview/qgraphicsitem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a4eca4d..a047e6a 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3565,7 +3565,7 @@ void QGraphicsItem::rotate(qreal angle) \code setTransform(QTransform::fromScale(sx, sy), true); - \encode + \endcode instead. -- cgit v0.12 From c57ed134a536c177d1774d9272ca187bdfb28e6b Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 31 Jul 2009 16:16:01 +0200 Subject: Revert "Fix QFormLayout which allowed fields to be smaller that their minimum size" This reverts commit 244f5ee9c2c34ddee200e4d5cdc1345762a5901b. Valgrind complains about the label fields that are not inisialized yet, and indeed. They are initialized right after, and need the maxLabelWidth to be computed. This is a chicken and egg problem difficult to solve, so I rather revert the change as the bug is not critical --- src/gui/kernel/qformlayout.cpp | 6 +----- tests/auto/qformlayout/tst_qformlayout.cpp | 30 ------------------------------ 2 files changed, 1 insertion(+), 35 deletions(-) diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp index 0b7656f..de33f93 100644 --- a/src/gui/kernel/qformlayout.cpp +++ b/src/gui/kernel/qformlayout.cpp @@ -689,16 +689,12 @@ void QFormLayoutPrivate::setupVerticalLayoutData(int width) // are split. maxLabelWidth = 0; if (!wrapAllRows) { - int maxFieldMinWidth = 0; //the maximum minimum size of the field for (int i = 0; i < rr; ++i) { const QFormLayoutItem *label = m_matrix(i, 0); const QFormLayoutItem *field = m_matrix(i, 1); - if (label && field && label->sideBySide) + if (label && (label->sizeHint.width() + (field ? field->minSize.width() : 0) <= width)) maxLabelWidth = qMax(maxLabelWidth, label->sizeHint.width()); - if (field) - maxFieldMinWidth = qMax(maxFieldMinWidth, field->minSize.width() + field->sbsHSpace); } - maxLabelWidth = qMin(maxLabelWidth, width - maxFieldMinWidth); } else { maxLabelWidth = width; } diff --git a/tests/auto/qformlayout/tst_qformlayout.cpp b/tests/auto/qformlayout/tst_qformlayout.cpp index 74384a9..9806557 100644 --- a/tests/auto/qformlayout/tst_qformlayout.cpp +++ b/tests/auto/qformlayout/tst_qformlayout.cpp @@ -125,7 +125,6 @@ private slots: Qt::Orientations expandingDirections() const; */ - void fieldMinimumSize(); }; tst_QFormLayout::tst_QFormLayout() @@ -906,35 +905,6 @@ void tst_QFormLayout::layoutAlone() QTest::qWait(500); } - -void tst_QFormLayout::fieldMinimumSize() -{ - //check that the field with is bigger than its minimumSizeHint for any size of the widget - // even if the label with is not fixed - QWidget w; - QFormLayout layout; - layout.setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow); - w.setLayout(&layout); - QLabel label1("Here is a strange test case"); - label1.setWordWrap(true); - QLabel label2("Here is another label"); - label2.setWordWrap(true); - QLabel shortLabel("short"); - QLabel longLabel("Quite long label"); - layout.addRow(&label1, &shortLabel); - layout.addRow(&label2, &longLabel); - w.show(); - int width = w.size().width() + 9; - - do { - w.resize(width, w.size().height()); - layout.activate(); - QVERIFY(shortLabel.size().width() >= shortLabel.minimumSizeHint().width()); - QVERIFY(longLabel.size().width() >= longLabel.minimumSizeHint().width()); - width -= 3; - } while(width >= w.minimumSizeHint().width()); -} - QTEST_MAIN(tst_QFormLayout) #include "tst_qformlayout.moc" -- cgit v0.12 From 5aed3db0a4084f470769ad4b965001f17b878c79 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Sat, 1 Aug 2009 12:04:25 +0200 Subject: Compilare necessus est --- tools/assistant/lib/qhelpprojectdata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/assistant/lib/qhelpprojectdata.cpp b/tools/assistant/lib/qhelpprojectdata.cpp index 5df0426..9412f1c 100644 --- a/tools/assistant/lib/qhelpprojectdata.cpp +++ b/tools/assistant/lib/qhelpprojectdata.cpp @@ -289,7 +289,7 @@ void QHelpProjectDataPrivate::addMatchingFiles(const QString &pattern) bool matchFound = false; #ifdef Q_OS_WIN - Qt::CaseSensitivity cs = Qt::CaseInSensitive; + Qt::CaseSensitivity cs = Qt::CaseInsensitive; #else Qt::CaseSensitivity cs = Qt::CaseSensitive; #endif -- cgit v0.12