diff options
author | axis <qt-info@nokia.com> | 2011-02-24 16:07:22 (GMT) |
---|---|---|
committer | axis <qt-info@nokia.com> | 2011-02-24 16:07:22 (GMT) |
commit | 2b768ad7d4de4862584762a7d106d9cfcc3416df (patch) | |
tree | 0ddfe84f345d7e61ce71daa51fbbfb373c3e3106 /src | |
parent | bb7d9bcc8e0c617091e91f7a40f3d33f8c1cdec1 (diff) | |
parent | ca7be48b7a150952a9657d1000941fb986e5bb2b (diff) | |
download | Qt-2b768ad7d4de4862584762a7d106d9cfcc3416df.zip Qt-2b768ad7d4de4862584762a7d106d9cfcc3416df.tar.gz Qt-2b768ad7d4de4862584762a7d106d9cfcc3416df.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt into earth-master
Conflicts:
src/network/access/qnetworkreplyimpl.cpp
tests/auto/moc/tst_moc.cpp
Diffstat (limited to 'src')
310 files changed, 9095 insertions, 2507 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog index c2b1155..9cbf0c1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog +++ b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog @@ -358,6 +358,31 @@ * wtf/AlwaysInline.h: +2010-02-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=33731 + Many false leaks in release builds due to PtrAndFlags + + Remove UntypedPtrAndBitfield (similar to PtrAndFlags) in UStringImpl, + and steal bits from the refCount instead. + + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::baseSharedBuffer): + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UStringImpl::cost): + (JSC::UStringImpl::isIdentifier): + (JSC::UStringImpl::setIsIdentifier): + (JSC::UStringImpl::ref): + (JSC::UStringImpl::deref): + (JSC::UStringImpl::UStringImpl): + (JSC::UStringImpl::bufferOwnerString): + (JSC::UStringImpl::bufferOwnership): + (JSC::UStringImpl::isStatic): + (JSC::UStringImpl::): + 2010-02-12 Kwang Yul Seo <skyul@company100.net> Reviewed by Adam Barth. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp index 4b0d1c9..4fde49e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp @@ -38,12 +38,14 @@ namespace JSC { SharedUChar* UStringImpl::baseSharedBuffer() { ASSERT((bufferOwnership() == BufferShared) - || ((bufferOwnership() == BufferOwned) && !m_dataBuffer.asPtr<void*>())); + || ((bufferOwnership() == BufferOwned) && !m_buffer)); - if (bufferOwnership() != BufferShared) - m_dataBuffer = UntypedPtrAndBitfield(SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(), BufferShared); + if (bufferOwnership() != BufferShared) { + m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared; + m_bufferShared = SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(); + } - return m_dataBuffer.asPtr<SharedUChar*>(); + return m_bufferShared; } SharedUChar* UStringImpl::sharedBuffer() @@ -71,10 +73,10 @@ UStringImpl::~UStringImpl() if (bufferOwnership() == BufferOwned) fastFree(m_data); else if (bufferOwnership() == BufferSubstring) - m_dataBuffer.asPtr<UStringImpl*>()->deref(); + m_bufferSubstring->deref(); else { ASSERT(bufferOwnership() == BufferShared); - m_dataBuffer.asPtr<SharedUChar*>()->deref(); + m_bufferShared->deref(); } } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h index 4e1ddc7..e6d1a8a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h @@ -40,48 +40,6 @@ class IdentifierTable; typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; -class UntypedPtrAndBitfield { -public: - UntypedPtrAndBitfield() {} - - UntypedPtrAndBitfield(void* ptrValue, uintptr_t bitValue) - : m_value(reinterpret_cast<uintptr_t>(ptrValue) | bitValue) -#ifndef NDEBUG - , m_leaksPtr(ptrValue) -#endif - { - ASSERT(ptrValue == asPtr<void*>()); - ASSERT((*this & ~s_alignmentMask) == bitValue); - } - - template<typename T> - T asPtr() const { return reinterpret_cast<T>(m_value & s_alignmentMask); } - - UntypedPtrAndBitfield& operator&=(uintptr_t bits) - { - m_value &= bits | s_alignmentMask; - return *this; - } - - UntypedPtrAndBitfield& operator|=(uintptr_t bits) - { - m_value |= bits & ~s_alignmentMask; - return *this; - } - - uintptr_t operator&(uintptr_t mask) const - { - return m_value & mask & ~s_alignmentMask; - } - -private: - static const uintptr_t s_alignmentMask = ~static_cast<uintptr_t>(0x7); - uintptr_t m_value; -#ifndef NDEBUG - void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced. -#endif -}; - class UStringImpl : Noncopyable { public: template<size_t inlineCapacity> @@ -151,21 +109,27 @@ public: { // For substrings, return the cost of the base string. if (bufferOwnership() == BufferSubstring) - return m_dataBuffer.asPtr<UStringImpl*>()->cost(); + return m_bufferSubstring->cost(); - if (m_dataBuffer & s_reportedCostBit) + if (m_refCountAndFlags & s_refCountFlagHasReportedCost) return 0; - m_dataBuffer |= s_reportedCostBit; + m_refCountAndFlags |= s_refCountFlagHasReportedCost; return m_length; } unsigned hash() const { if (!m_hash) m_hash = computeHash(data(), m_length); return m_hash; } unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers - bool isIdentifier() const { return m_isIdentifier; } - void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; } + bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; } + void setIsIdentifier(bool isIdentifier) + { + if (isIdentifier) + m_refCountAndFlags |= s_refCountFlagIsIdentifier; + else + m_refCountAndFlags &= ~s_refCountFlagIsIdentifier; + } - UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; } - ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) delete this; } + UStringImpl* ref() { m_refCountAndFlags += s_refCountIncrement; return this; } + ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) delete this; } static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) { @@ -205,11 +169,10 @@ private: // Used to construct normal strings with an internal or external buffer. UStringImpl(UChar* data, int length, BufferOwnership ownership) : m_data(data) + , m_buffer(0) , m_length(length) - , m_refCount(s_refCountIncrement) + , m_refCountAndFlags(s_refCountIncrement | ownership) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(0, ownership) { ASSERT((ownership == BufferInternal) || (ownership == BufferOwned)); checkConsistency(); @@ -221,11 +184,10 @@ private: enum StaticStringConstructType { ConstructStaticString }; UStringImpl(UChar* data, int length, StaticStringConstructType) : m_data(data) + , m_buffer(0) , m_length(length) - , m_refCount(s_staticRefCountInitialValue) + , m_refCountAndFlags(s_refCountFlagStatic | BufferOwned) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(0, BufferOwned) { checkConsistency(); } @@ -233,28 +195,26 @@ private: // Used to create new strings that are a substring of an existing string. UStringImpl(UChar* data, int length, PassRefPtr<UStringImpl> base) : m_data(data) + , m_bufferSubstring(base.releaseRef()) , m_length(length) - , m_refCount(s_refCountIncrement) + , m_refCountAndFlags(s_refCountIncrement | BufferSubstring) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(base.releaseRef(), BufferSubstring) { // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes // that all pointers will be at least 8-byte aligned, we cannot guarantee that of // UStringImpls that are not heap allocated. - ASSERT(m_dataBuffer.asPtr<UStringImpl*>()->size()); - ASSERT(!m_dataBuffer.asPtr<UStringImpl*>()->isStatic()); + ASSERT(m_bufferSubstring->size()); + ASSERT(!m_bufferSubstring->isStatic()); checkConsistency(); } // Used to construct new strings sharing an existing shared buffer. UStringImpl(UChar* data, int length, PassRefPtr<SharedUChar> sharedBuffer) : m_data(data) + , m_bufferShared(sharedBuffer.releaseRef()) , m_length(length) - , m_refCount(s_refCountIncrement) + , m_refCountAndFlags(s_refCountIncrement | BufferShared) , m_hash(0) - , m_isIdentifier(false) - , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared) { checkConsistency(); } @@ -277,26 +237,31 @@ private: // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. static const int s_minLengthToShare = 10; static const unsigned s_copyCharsInlineCutOff = 20; - static const uintptr_t s_bufferOwnershipMask = 3; - static const uintptr_t s_reportedCostBit = 4; // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2. // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero. - static const int s_refCountIncrement = 2; - static const int s_staticRefCountInitialValue = 1; - - UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } - const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } + static const unsigned s_refCountMask = 0xFFFFFFF0; + static const int s_refCountIncrement = 0x20; + static const int s_refCountFlagStatic = 0x10; + static const unsigned s_refCountFlagHasReportedCost = 0x8; + static const unsigned s_refCountFlagIsIdentifier = 0x4; + static const unsigned s_refCountMaskBufferOwnership = 0x3; + + UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } + const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } SharedUChar* baseSharedBuffer(); - unsigned bufferOwnership() const { return m_dataBuffer & s_bufferOwnershipMask; } - bool isStatic() const { return m_refCount & 1; } + unsigned bufferOwnership() const { return m_refCountAndFlags & s_refCountMaskBufferOwnership; } + bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } // unshared data UChar* m_data; + union { + void* m_buffer; + UStringImpl* m_bufferSubstring; + SharedUChar* m_bufferShared; + }; int m_length; - unsigned m_refCount; - mutable unsigned m_hash : 31; - mutable unsigned m_isIdentifier : 1; - UntypedPtrAndBitfield m_dataBuffer; + unsigned m_refCountAndFlags; + mutable unsigned m_hash; JS_EXPORTDATA static UStringImpl* s_null; JS_EXPORTDATA static UStringImpl* s_empty; diff --git a/src/3rdparty/javascriptcore/VERSION b/src/3rdparty/javascriptcore/VERSION index b4744b7..13943b2 100644 --- a/src/3rdparty/javascriptcore/VERSION +++ b/src/3rdparty/javascriptcore/VERSION @@ -4,8 +4,8 @@ This is a snapshot of JavaScriptCore from The commit imported was from the - javascriptcore-snapshot-24012011 branch/tag + javascriptcore-snapshot-27012011 branch/tag and has the sha1 checksum - d143bde5ae8cff229aebd43487a2fce5e713e990 + 3ab0f621048fbeb480b687a28ed31d92d8506150 diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index e82ec4c..2de6961 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -15,7 +15,7 @@ symbian: { webkitlibs.path = /sys/bin vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ diff --git a/src/3rdparty/webkit/WebKit/qt/declarative/qdeclarativewebview.cpp b/src/3rdparty/webkit/WebKit/qt/declarative/qdeclarativewebview.cpp index 7a8aae7..4238d33 100644 --- a/src/3rdparty/webkit/WebKit/qt/declarative/qdeclarativewebview.cpp +++ b/src/3rdparty/webkit/WebKit/qt/declarative/qdeclarativewebview.cpp @@ -742,11 +742,11 @@ QWebPage* QDeclarativeWebView::page() const See QWebSettings for details of these properties. \qml - WebView { - settings.pluginsEnabled: true - settings.standardFontFamily: "Arial" - ... - } + WebView { + settings.pluginsEnabled: true + settings.standardFontFamily: "Arial" + // ... + } \endqml */ QDeclarativeWebSettings* QDeclarativeWebView::settingsObject() const diff --git a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit-bridge.qdoc b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit-bridge.qdoc index c2a38fd..d8ca5f9 100644 --- a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit-bridge.qdoc +++ b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit-bridge.qdoc @@ -415,7 +415,7 @@ \section2 Internet Security - When exposing native object to an open web environment, it is importwhichant to understand the security + When exposing native object to an open web environment, it is important to understand the security implications. Think whether the exposed object enables the web environment access to things that shouldn't be open, and whether the web content loaded by that web page comes from a trusted. In general, when exposing native QObjects that give the web environment access to private information or to functionality diff --git a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc index 0335d46..2be8e5e 100644 --- a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc +++ b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc @@ -103,8 +103,8 @@ The following locations are searched for plugins: \table - \header \o Linux/Unix (X11) \o Windows - \row \o{1,3} + \header \o Linux/Unix (X11) + \row \o \list \o \c{.mozilla/plugins} in the user's home directory \o \c{.netscape/plugins} in the user's home directory @@ -134,19 +134,20 @@ \o \c{$QTWEBKIT_PLUGIN_PATH} \endlist \endlist + \endtable - \o + \table + \header \o Windows + \row \o \list \o The user's \c{Application Data\Mozilla\plugins} directory \o Standard system locations of plugins for Quicktime, Flash, etc. \endlist + \endtable - \row - \raw HTML - <th class="qt-style">Mac OS X</th> - \endraw - \row - \o + \table + \header \o Mac OS X + \row \o \list \o \c{Library/Internet Plug-Ins} in the user's home directory \o The system \c{/Library/Internet Plug-Ins} directory diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 7c16f7e..aa83aac 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -491,6 +491,7 @@ QDefaultAnimationDriver::QDefaultAnimationDriver(QUnifiedTimer *timer) void QDefaultAnimationDriver::timerEvent(QTimerEvent *e) { Q_ASSERT(e->timerId() == m_timer.timerId()); + Q_UNUSED(e); // if the assertions are disabled advance(); } diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp index 212e85d..c76cb89 100644 --- a/src/corelib/animation/qvariantanimation.cpp +++ b/src/corelib/animation/qvariantanimation.cpp @@ -431,12 +431,17 @@ void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator fun { // will override any existing interpolators QInterpolatorVector *interpolators = registeredInterpolators(); + // When built on solaris with GCC, the destructors can be called + // in such an order that we get here with interpolators == NULL, + // to continue causes the app to crash on exit with a SEGV + if (interpolators) { #ifndef QT_NO_THREAD - QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators)); + QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators)); #endif - if (int(interpolationType) >= interpolators->count()) - interpolators->resize(int(interpolationType) + 1); - interpolators->replace(interpolationType, func); + if (int(interpolationType) >= interpolators->count()) + interpolators->resize(int(interpolationType) + 1); + interpolators->replace(interpolationType, func); + } } diff --git a/src/corelib/arch/qatomic_armv5.h b/src/corelib/arch/qatomic_armv5.h index f0f2f9a..820be7b 100644 --- a/src/corelib/arch/qatomic_armv5.h +++ b/src/corelib/arch/qatomic_armv5.h @@ -107,7 +107,7 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() // kernel places a restartable cmpxchg implementation at a fixed address extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr); -extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(const void *oldval, void *newval, volatile void *ptr); +extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(const void *oldval, const void *newval, volatile void *ptr); #define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0)) #define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0)) diff --git a/src/corelib/arch/symbian/qt_hybridheap_symbian_p.h b/src/corelib/arch/symbian/qt_hybridheap_symbian_p.h index 4eff0f3..d1ce705 100644 --- a/src/corelib/arch/symbian/qt_hybridheap_symbian_p.h +++ b/src/corelib/arch/symbian/qt_hybridheap_symbian_p.h @@ -43,8 +43,9 @@ #define QT_HYBRIDHEAP_SYMBIAN_H #include <qglobal.h> +#include <e32cmn.h> -#if !defined(SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS) && !defined(__WINS__) +#if !defined(__SYMBIAN_KERNEL_HYBRID_HEAP__) && !defined(__WINS__) //Enable the (backported) new allocator. When it is available in OS, //this flag should be disabled for that OS version onward #define QT_USE_NEW_SYMBIAN_ALLOCATOR diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index e946d5d..f03550d 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -40,7 +40,10 @@ contains(DEFINES,QT_EVAL):include(eval.pri) symbian: { TARGET.UID3=0x2001B2DC - # Workaroud for problems with paging this dll - MMP_RULES -= PAGED - MMP_RULES *= UNPAGED + # Problems using data exports from this DLL mean that we can't page it on releases that don't support + # data exports (currently that's any release before Symbian^3) + pagingBlock = "$${LITERAL_HASH}ifndef SYMBIAN_DLL_DATA_EXPORTS_SUPPORTED" \ + "UNPAGED" \ + "$${LITERAL_HASH}endif" + MMP_RULES += pagingBlock } diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 960fe6e..d849349 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -460,7 +460,6 @@ namespace QT_NAMESPACE {} # if defined(__INTEL_COMPILER) /* Intel C++ also masquerades as GCC 3.2.0 */ # define Q_CC_INTEL -# define Q_NO_TEMPLATE_FRIENDS # endif # if defined(__clang__) /* Clang also masquerades as GCC 4.2.1 */ @@ -763,6 +762,24 @@ namespace QT_NAMESPACE {} # error "Qt has not been tested with this compiler - talk to qt-bugs@trolltech.com" #endif +#ifdef Q_CC_INTEL +# if __INTEL_COMPILER < 1200 +# define Q_NO_TEMPLATE_FRIENDS +# endif +# if defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) +# if __INTEL_COMPILER >= 1100 +# define Q_COMPILER_RVALUE_REFS +# define Q_COMPILER_EXTERN_TEMPLATES +# elif __INTEL_COMPILER >= 1200 +# define Q_COMPILER_VARIADIC_TEMPLATES +# define Q_COMPILER_AUTO_TYPE +# define Q_COMPILER_DEFAULT_DELETE_MEMBERS +# define Q_COMPILER_CLASS_ENUM +# define Q_COMPILER_LAMBDA +# endif +# endif +#endif + #ifndef Q_PACKED # define Q_PACKED # undef Q_NO_PACKED_REFERENCE diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 7a6ab36..d84da0d 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -511,9 +511,16 @@ public: #if 0 // these values are reserved for Maemo5 - do not re-use them WA_Maemo5NonComposited = 126, WA_Maemo5StackedWindow = 127, - WA_Maemo5PortraitOrientation = 128, - WA_Maemo5LandscapeOrientation = 129, - WA_Maemo5AutoOrientation = 130, +#endif + + WA_LockPortraitOrientation = 128, + WA_LockLandscapeOrientation = 129, + WA_AutoOrientation = 130, + +#if 0 // these values are reserved for Maemo5 - do not re-use them + WA_Maemo5PortraitOrientation = WA_LockPortraitOrientation, + WA_Maemo5LandscapeOrientation = WA_LockLandscapeOrientation, + WA_Maemo5AutoOrientation = WA_AutoOrientation, WA_Maemo5ShowProgressIndicator = 131, #endif @@ -536,7 +543,8 @@ public: AA_DontUseNativeMenuBar = 6, AA_MacDontSwapCtrlAndMeta = 7, AA_S60DontConstructApplicationPanes = 8, - AA_X11InitThreads = 9, + AA_S60DisablePartialScreenInputMode = 9, + AA_X11InitThreads = 10, // Add new attributes before this line AA_AttributeCount diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 9facad7..cbdf9d1 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -156,11 +156,17 @@ whole lifetime. This attribute must be set before QApplication is constructed. + \omitvalue AA_S60DisablePartialScreenInputMode By default in Symbian^3, + a separate editing window is opened on top of an application. This is exactly + like editing on previous versions of Symbian behave. When this attribute + is true, a virtual keyboard window is shown on top of application and it + is ensured that the focused text widget is visible. This is only supported in + Symbian^3. (internal) + \value AA_X11InitThreads Calls XInitThreads() as part of the QApplication construction in order to make Xlib calls thread-safe. This attribute must be set before QApplication is constructed. - \omitvalue AA_AttributeCount */ @@ -1257,6 +1263,13 @@ to this top level window. This attribute has no effect on non-X11 platforms. + \value WA_LockPortraitOrientation Locks the widget to a portrait orientation, + ignoring changes to the display's orientation with respect to the user. + \value WA_LockLandscapeOrientation Locks the widget to a landscape orientation, + ignoring changes to the display's orientation with respect to the user. + \value WA_AutoOrientation Causes the widget to change orientation whenever the + display changes orientation with respect to the user. + \value WA_MacNoShadow Since Qt 4.8, this attribute disables drop shadows for this top level window. Only affects Cocoa builds of Qt for Mac OS X. diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index b120f7f..ba61bda 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -169,27 +169,17 @@ private: Q_GLOBAL_STATIC(QMutex, processManagerGlobalMutex) -static QProcessManager *processManagerInstance = 0; - -static QProcessManager *processManager() -{ +static QProcessManager *processManager() { // The constructor of QProcessManager should be called only once // so we cannot use Q_GLOBAL_STATIC directly for QProcessManager QMutex *mutex = processManagerGlobalMutex(); QMutexLocker locker(mutex); - - if (!processManagerInstance) - QProcessPrivate::initializeProcessManager(); - - Q_ASSERT(processManagerInstance); - return processManagerInstance; + static QProcessManager processManager; + return &processManager; } QProcessManager::QProcessManager() { - // can only be called from main thread - Q_ASSERT(!qApp || qApp->thread() == QThread::currentThread()); - #if defined (QPROCESS_DEBUG) qDebug() << "QProcessManager::QProcessManager()"; #endif @@ -208,8 +198,6 @@ QProcessManager::QProcessManager() ::sigaction(SIGCHLD, &action, &oldAction); if (oldAction.sa_handler != qt_sa_sigchld_handler) qt_sa_old_sigchld_handler = oldAction.sa_handler; - - processManagerInstance = this; } QProcessManager::~QProcessManager() @@ -238,8 +226,6 @@ QProcessManager::~QProcessManager() if (oldAction.sa_handler != qt_sa_sigchld_handler) { ::sigaction(SIGCHLD, &oldAction, 0); } - - processManagerInstance = 0; } void QProcessManager::run() @@ -659,7 +645,7 @@ void QProcessPrivate::startProcess() if (childPid < 0) { // Cleanup, report error and return #if defined (QPROCESS_DEBUG) - qDebug("qt_fork failed: %s", qt_error_string(lastForkErrno)); + qDebug("qt_fork failed: %s", qPrintable(qt_error_string(lastForkErrno))); #endif processManager()->unlock(); q->setProcessState(QProcess::NotRunning); @@ -863,7 +849,7 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) qDebug("QProcessPrivate::writeToStdin(%p \"%s\", %lld) == %lld", data, qt_prettyDebug(data, maxlen, 16).constData(), maxlen, written); if (written == -1) - qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qt_error_string(errno)); + qDebug("QProcessPrivate::writeToStdin(), failed to write (%s)", qPrintable(qt_error_string(errno))); #endif // If the O_NONBLOCK flag is set and If some data can be written without blocking // the process, write() will transfer what it can and return the number of bytes written. @@ -1306,15 +1292,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a void QProcessPrivate::initializeProcessManager() { - if (qApp && qApp->thread() != QThread::currentThread()) { - // The process manager must be initialized in the main thread - // Note: The call below will re-enter this function, but in the right thread, - // so the else statement below will be executed. - QMetaObject::invokeMethod(qApp, "_q_initializeProcessManager", Qt::BlockingQueuedConnection); - } else { - static QProcessManager processManager; - Q_UNUSED(processManager); - } + (void) processManager(); } QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index 3ef71e0..5b48689 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -158,6 +158,22 @@ Q_CORE_EXPORT RFs& qt_s60GetRFs(); // Defined in qlocale_symbian.cpp. Q_CORE_EXPORT QByteArray qt_symbianLocaleName(int code); +template <typename R> +struct QScopedPointerRCloser +{ + static inline void cleanup(R *rPointer) + { + // Enforce a complete type. + // If you get a compile error here, read the section on forward declared + // classes in the QScopedPointer documentation. + typedef char IsIncompleteType[ sizeof(R) ? 1 : -1 ]; + (void) sizeof(IsIncompleteType); + + if (rPointer) + rPointer->Close(); + } +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 9bd32d1..be86c58 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -392,16 +392,6 @@ void QCoreApplicationPrivate::createEventDispatcher() #endif } -void QCoreApplicationPrivate::_q_initializeProcessManager() -{ -#ifndef QT_NO_PROCESS -# ifdef Q_OS_UNIX - QProcessPrivate::initializeProcessManager(); -# endif -#endif -} - - QThread *QCoreApplicationPrivate::theMainThread = 0; QThread *QCoreApplicationPrivate::mainThread() { @@ -482,10 +472,10 @@ QString qAppName() operations can call processEvents() to keep the application responsive. - In general, we recommend that you create a QCoreApplication or - a QApplication object in your \c main() function as early as - possible. exit() will not return until the event loop exits; - e.g., when quit() is called. + In general, we recommend that you create a QCoreApplication or a + QApplication object in your \c main() function as early as + possible. exec() will not return until the event loop exits; e.g., + when quit() is called. Several static convenience functions are also provided. The QCoreApplication object is available from instance(). Events can @@ -666,6 +656,12 @@ void QCoreApplication::init() } #endif +#if defined(Q_OS_UNIX) && !(defined(QT_NO_PROCESS)) + // Make sure the process manager thread object is created in the main + // thread. + QProcessPrivate::initializeProcessManager(); +#endif + #ifdef QT_EVAL extern void qt_core_eval_init(uint); qt_core_eval_init(d->application_type); @@ -2732,5 +2728,3 @@ int QCoreApplication::loopLevel() */ QT_END_NAMESPACE - -#include "moc_qcoreapplication.cpp" diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index 024c509..3957158 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -205,7 +205,6 @@ protected: QCoreApplication(QCoreApplicationPrivate &p); private: - Q_PRIVATE_SLOT(d_func(), void _q_initializeProcessManager()) static bool sendSpontaneousEvent(QObject *receiver, QEvent *event); bool notifyInternal(QObject *receiver, QEvent *event); diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h index fdceab4..add2a35 100644 --- a/src/corelib/kernel/qcoreapplication_p.h +++ b/src/corelib/kernel/qcoreapplication_p.h @@ -85,8 +85,6 @@ public: bool sendThroughObjectEventFilters(QObject *, QEvent *); bool notify_helper(QObject *, QEvent *); - void _q_initializeProcessManager(); - virtual QString appName() const; virtual void createEventDispatcher(); static void removePostedEvent(QEvent *); diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp index 8872045..53796be 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian.cpp +++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp @@ -657,7 +657,7 @@ public: : m_state(STATE_RUN), m_stop(false) { qt_symbian_throwIfError(m_lock.CreateLocal(0)); - TInt err = m_idleDetectorThread.Create(KNullDesC(), &idleDetectorThreadFunc, 1024, NULL, this); + TInt err = m_idleDetectorThread.Create(KNullDesC(), &idleDetectorThreadFunc, 1024, &User::Allocator(), this); if (err != KErrNone) m_lock.Close(); qt_symbian_throwIfError(err); @@ -692,6 +692,7 @@ public: private: static TInt idleDetectorThreadFunc(TAny* self) { + User::RenameThread(_L("IdleDetectorThread")); static_cast<QIdleDetectorThread*>(self)->IdleLoop(); return KErrNone; } @@ -809,7 +810,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla m_interrupt = false; #ifdef QT_SYMBIAN_PRIORITY_DROP - QTime eventTimer; + QElapsedTimer eventTimer; #endif while (1) { diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h index b785aea..bdb6dce 100644 --- a/src/corelib/kernel/qeventdispatcher_symbian_p.h +++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h @@ -63,6 +63,7 @@ #include <qwaitcondition.h> #include <qsocketnotifier.h> #include <qdatetime.h> +#include <qelapsedtimer.h> #include <e32base.h> @@ -284,7 +285,7 @@ private: int m_delay; int m_avgEventTime; - QTime m_lastIdleRequestTimer; + QElapsedTimer m_lastIdleRequestTimer; }; #ifdef QT_DEBUG diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 3d8352e..6badb6a 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -532,10 +532,7 @@ LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp) PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0); } } else if (d->sendPostedEventsWindowsTimerId == 0 - && localSerialNumber != d->lastSerialNumber - // if this message IS the one that triggers sendPostedEvents(), no need to post it again - && (msg->hwnd != d->internalHwnd - || msg->message != WM_QT_SENDPOSTEDEVENTS)) { + && localSerialNumber != d->lastSerialNumber) { // start a special timer to continue delivering posted events while // there are still input and timer messages in the message queue d->sendPostedEventsWindowsTimerId = SetTimer(d->internalHwnd, diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 7928f4f..c5775f6 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -1387,6 +1387,25 @@ int QMetaMethod::methodIndex() const } /*! + \internal + + Returns the method revision if one was + specified by Q_REVISION, otherwise returns 0. + */ +int QMetaMethod::revision() const +{ + if (!mobj) + return 0; + if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) { + int offset = priv(mobj->d.data)->methodData + + priv(mobj->d.data)->methodCount * 5 + + (handle - priv(mobj->d.data)->methodData) / 5; + return mobj->d.data[offset]; + } + return 0; +} + +/*! Returns the access specification of this method (private, protected, or public). @@ -2394,6 +2413,35 @@ int QMetaProperty::notifySignalIndex() const } /*! + \internal + + Returns the property revision if one was + specified by REVISION, otherwise returns 0. + */ +int QMetaProperty::revision() const +{ + if (!mobj) + return 0; + int flags = mobj->d.data[handle + 2]; + if (flags & Revisioned) { + int offset = priv(mobj->d.data)->propertyData + + priv(mobj->d.data)->propertyCount * 3 + idx; + // Revision data is placed after NOTIFY data, if present. + // Iterate through properties to discover whether we have NOTIFY signals. + for (int i = 0; i < priv(mobj->d.data)->propertyCount; ++i) { + int handle = priv(mobj->d.data)->propertyData + 3*i; + if (mobj->d.data[handle + 2] & Notify) { + offset += priv(mobj->d.data)->propertyCount; + break; + } + } + return mobj->d.data[offset]; + } else { + return 0; + } +} + +/*! Returns true if this property is writable; otherwise returns false. diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 4fb353d..e9bba45 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -70,6 +70,7 @@ public: enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 }; int attributes() const; int methodIndex() const; + int revision() const; inline const QMetaObject *enclosingMetaObject() const { return mobj; } @@ -202,6 +203,8 @@ public: QMetaMethod notifySignal() const; int notifySignalIndex() const; + int revision() const; + QVariant read(const QObject *obj) const; bool write(QObject *obj, const QVariant &value) const; bool reset(QObject *obj) const; diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index dd0baf0..210b32c 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -78,7 +78,8 @@ enum PropertyFlags { ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000, - Notify = 0x00400000 + Notify = 0x00400000, + Revisioned = 0x00800000 }; enum MethodFlags { @@ -95,7 +96,8 @@ enum MethodFlags { MethodCompatibility = 0x10, MethodCloned = 0x20, - MethodScriptable = 0x40 + MethodScriptable = 0x40, + MethodRevisioned = 0x80 }; enum MetaObjectFlags { diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 47d3a3b..a2bb7d1 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -138,7 +138,7 @@ template <typename T> void *qMetaTypeConstructHelper(const T *t) { if (!t) - return new T; + return new T(); return new T(*static_cast<const T*>(t)); } diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 94e6241..54b5ab2 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -79,6 +79,7 @@ class QString; #define Q_INTERFACES(x) #define Q_PROPERTY(text) #define Q_PRIVATE_PROPERTY(d, text) +#define Q_REVISION(v) #define Q_OVERRIDE(text) #define Q_ENUMS(x) #define Q_FLAGS(x) @@ -180,6 +181,7 @@ private: #define Q_INTERFACES(x) Q_INTERFACES(x) #define Q_PROPERTY(text) Q_PROPERTY(text) #define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text) +#define Q_REVISION(v) Q_REVISION(v) #define Q_OVERRIDE(text) Q_OVERRIDE(text) #define Q_ENUMS(x) Q_ENUMS(x) #define Q_FLAGS(x) Q_FLAGS(x) diff --git a/src/corelib/thread/qmutex_unix.cpp b/src/corelib/thread/qmutex_unix.cpp index 5321252..11e2060 100644 --- a/src/corelib/thread/qmutex_unix.cpp +++ b/src/corelib/thread/qmutex_unix.cpp @@ -180,8 +180,11 @@ bool QMutexPrivate::wait(int timeout) errorCode = pthread_cond_timedwait(&cond, &mutex, &ti); } if (errorCode) { - if (errorCode == ETIMEDOUT) + if (errorCode == ETIMEDOUT) { + if (wakeup) + errorCode = 0; break; + } report_error(errorCode, "QMutex::lock()", "cv wait"); } } diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 1494745..326f494 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -515,10 +515,12 @@ int QThread::exec() Note that unlike the C library function of the same name, this function \e does return to the caller -- it is event processing - that stops. - - This function does nothing if the thread does not have an event - loop. + that stops. + + No QEventLoops will be started anymore in this thread until + QThread::exec() has been called again. If the eventloop in QThread::exec() + is not running then the next call to QThread::exec() will also return + immediately. \sa quit() QEventLoop */ diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index cc81c1b..b281c1b 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -492,7 +492,7 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel) #endif /*! - \fn QByteArray qUncompress(const QByteArray& data) + \fn QByteArray qUncompress(const QByteArray &data) \relates QByteArray @@ -506,10 +506,10 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel) feature was added. \bold{Note:} If you want to use this function to uncompress external - data compressed using zlib, you first need to prepend four bytes to the - byte array that contain the expected length (as an unsigned integer) - of the uncompressed data encoded in big-endian order (most significant - byte first). + data that was compressed using zlib, you first need to prepend a four + byte header to the byte array containing the data. The header must + contain the expected length (in bytes) of the uncompressed data, + expressed as an unsigned, big-endian, 32-bit integer. \sa qCompress() */ diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp index 801600a..7daf95a 100644 --- a/src/corelib/tools/qeasingcurve.cpp +++ b/src/corelib/tools/qeasingcurve.cpp @@ -92,14 +92,18 @@ animation.setEasingCurve(QEasingCurve::InOutQuad); \endcode - The ability to set an amplitude, overshoot, or period depends on the QEasingCurve type. Amplitude access - is available to curves that behave as springs such as elastic and bounce curves. Changing the amplitude changes - the height of the curve. Period access is only available to elastic curves and setting a higher period slows - the rate of bounce. Only curves that have "boomerang" behaviors such as the InBack, OutBack, InOutBack, and OutInBack - have overshoot settings. These curves will interpolate beyond the end points and return to the end point, - acting similar to a boomerang. - - The \l{Easing Curves Example} contains samples of QEasingCurve types and lets you change the curve settings. + The ability to set an amplitude, overshoot, or period depends on + the QEasingCurve type. Amplitude access is available to curves + that behave as springs such as elastic and bounce curves. Changing + the amplitude changes the height of the curve. Period access is + only available to elastic curves and setting a higher period slows + the rate of bounce. Only curves that have "boomerang" behaviors + such as the InBack, OutBack, InOutBack, and OutInBack have + overshoot settings. These curves will interpolate beyond the end + points and return to the end point, acting similar to a boomerang. + + The \l{Easing Curves Example} contains samples of QEasingCurve + types and lets you change the curve settings. */ diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index fcfa8f0..6515edb 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -2199,7 +2199,7 @@ static quint16 localePrivateIndex(const QLocalePrivate *p) /*! Constructs a QLocale object with the specified \a name, which has the format - "language[_country][.codeset][@modifier]" or "C", where: + "language[_territory][.codeset][@modifier]" or "C", where: \list \i language is a lowercase, two-letter, ISO 639 language code, diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h index a8ae40c..a2a8052 100644 --- a/src/corelib/tools/qset.h +++ b/src/corelib/tools/qset.h @@ -335,7 +335,7 @@ class QMutableSetIterator typedef typename QSet<T>::iterator iterator; QSet<T> *c; iterator i, n; - inline bool item_exists() const { return n != c->constEnd(); } + inline bool item_exists() const { return c->constEnd() != n; } public: inline QMutableSetIterator(QSet<T> &container) diff --git a/src/corelib/tools/qshareddata.h b/src/corelib/tools/qshareddata.h index 1bdba2c..1494373 100644 --- a/src/corelib/tools/qshareddata.h +++ b/src/corelib/tools/qshareddata.h @@ -114,6 +114,7 @@ public: return *this; } #ifdef Q_COMPILER_RVALUE_REFS + QSharedDataPointer(QSharedDataPointer &&o) : d(o.d) { o.d = 0; } inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) { qSwap(d, other.d); return *this; } #endif @@ -197,7 +198,8 @@ public: return *this; } #ifdef Q_COMPILER_RVALUE_REFS - inline QSharedDataPointer<T> &operator=(QSharedDataPointer<T> &&other) + inline QExplicitlySharedDataPointer(QExplicitlySharedDataPointer &&o) : d(o.d) { o.d = 0; } + inline QExplicitlySharedDataPointer<T> &operator=(QExplicitlySharedDataPointer<T> &&other) { qSwap(d, other.d); return *this; } #endif diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 273c5bd..b29e5b6 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -44,7 +44,17 @@ #ifndef QSHAREDPOINTER_H #error Do not include qsharedpointer_impl.h directly #endif + #if 0 +// These macros are duplicated here to make syncqt not complain a about +// this header, as we have a "qt_sync_stop_processing" below, which in turn +// is here because this file contains a template mess and duplicates the +// classes found in qsharedpointer.h +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE +QT_MODULE(Core) +QT_END_NAMESPACE +QT_END_HEADER #pragma qt_sync_stop_processing #endif diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 95c80a1..b7272ec 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -658,10 +658,11 @@ const QString::Null QString::null = { }; class.) \table 100 % + \header + \o Note for C Programmers + \row \o - \section1 Note for C Programmers - Due to C++'s type system and the fact that QString is \l{implicitly shared}, QStrings may be treated like \c{int}s or other basic types. For example: @@ -3890,8 +3891,7 @@ const char *QString::latin1_helper() const If \a size is -1 (default), it is taken to be qstrlen(\a str). - QTextCodec::codecForLocale() is used to perform the conversion - from Unicode. + QTextCodec::codecForLocale() is used to perform the conversion. \sa toLocal8Bit(), fromAscii(), fromLatin1(), fromUtf8() */ diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h index 2c8693b..e331d8f 100644 --- a/src/dbus/qdbusargument.h +++ b/src/dbus/qdbusargument.h @@ -376,6 +376,21 @@ inline const QDBusArgument &operator>>(const QDBusArgument &arg, QHash<Key, T> & return arg; } +inline QDBusArgument &operator<<(QDBusArgument &arg, const QVariantHash &map) +{ + arg.beginMap(QVariant::String, qMetaTypeId<QDBusVariant>()); + QVariantHash::ConstIterator it = map.constBegin(); + QVariantHash::ConstIterator end = map.constEnd(); + for ( ; it != end; ++it) { + arg.beginMapEntry(); + arg << it.key() << QDBusVariant(it.value()); + arg.endMapEntry(); + } + arg.endMap(); + return arg; +} + + QT_END_NAMESPACE Q_DECLARE_METATYPE(QDBusArgument) diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index 3c0cb6e..14138e0 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -558,8 +558,9 @@ bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg) switch (amsg.type()) { case QDBusMessage::SignalMessage: handleSignal(amsg); - return true; - break; + // if there are any other filters in this DBusConnection, + // let them see the signal too + return false; case QDBusMessage::MethodCallMessage: handleObjectCall(amsg); return true; @@ -2073,30 +2074,20 @@ void QDBusConnectionPrivate::connectSignal(const QString &key, const SignalHook if (connection) { qDBusDebug("Adding rule: %s", hook.matchRule.constData()); - QDBusErrorInternal error; - q_dbus_bus_add_match(connection, hook.matchRule, error); - if (!!error) { - QDBusError qerror = error; - qWarning("QDBusConnectionPrivate::connectSignal: received error from D-Bus server " - "while connecting signal to %s::%s: %s (%s)", - hook.obj->metaObject()->className(), - hook.obj->metaObject()->method(hook.midx).signature(), - qPrintable(qerror.name()), qPrintable(qerror.message())); - Q_ASSERT(false); - } else { - // Successfully connected the signal - // Do we need to watch for this name? - if (shouldWatchService(hook.service)) { - WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; - if (++data.refcount == 1) { - // we need to watch for this service changing - connectSignal(dbusServiceString(), QString(), dbusInterfaceString(), - QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), - this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); - data.owner = getNameOwnerNoCache(hook.service); - qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" - << data.owner << ")"; - } + q_dbus_bus_add_match(connection, hook.matchRule, NULL); + + // Successfully connected the signal + // Do we need to watch for this name? + if (shouldWatchService(hook.service)) { + WatchedServicesHash::mapped_type &data = watchedServices[hook.service]; + if (++data.refcount == 1) { + // we need to watch for this service changing + connectSignal(dbusServiceString(), QString(), dbusInterfaceString(), + QLatin1String("NameOwnerChanged"), QStringList() << hook.service, QString(), + this, SLOT(serviceOwnerChangedNoLock(QString,QString,QString))); + data.owner = getNameOwnerNoCache(hook.service); + qDBusDebug() << this << "Watching service" << hook.service << "for owner changes (current owner:" + << data.owner << ")"; } } } diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp index 5fe0589..6683505 100644 --- a/src/dbus/qdbusmetaobject.cpp +++ b/src/dbus/qdbusmetaobject.cpp @@ -169,6 +169,8 @@ QDBusMetaObjectGenerator::QDBusMetaObjectGenerator(const QString &interfaceName, } } +Q_DBUS_EXPORT bool qt_dbus_metaobject_skip_annotations = false; + QDBusMetaObjectGenerator::Type QDBusMetaObjectGenerator::findType(const QByteArray &signature, const QDBusIntrospection::Annotations &annotations, @@ -178,7 +180,7 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, result.id = QVariant::Invalid; int type = QDBusMetaType::signatureToType(signature); - if (type == QVariant::Invalid) { + if (type == QVariant::Invalid && !qt_dbus_metaobject_skip_annotations) { // it's not a type normally handled by our meta type system // it must contain an annotation QString annotationName = QString::fromLatin1("com.trolltech.QtDBus.QtTypeName"); @@ -201,6 +203,20 @@ QDBusMetaObjectGenerator::findType(const QByteArray &signature, return result; // unknown type is invalid too result.name = typeName; + } else if (type == QVariant::Invalid) { + // this case is used only by the qdbus command-line tool + // invalid, let's create an impossible type that contains the signature + + if (signature == "av") { + result.name = "QVariantList"; + type = QVariant::List; + } else if (signature == "a{sv}") { + result.name = "QVariantMap"; + type = QVariant::Map; + } else { + result.name = "QDBusRawType::" + signature; + type = -1; + } } else { result.name = QVariant::typeToName( QVariant::Type(type) ); } diff --git a/src/dbus/qdbusmetatype.cpp b/src/dbus/qdbusmetatype.cpp index 6de5d93..9f29205 100644 --- a/src/dbus/qdbusmetatype.cpp +++ b/src/dbus/qdbusmetatype.cpp @@ -127,6 +127,7 @@ void QDBusMetaTypeId::init() registerHelper<QLineF>(); registerHelper<QVariantList>(); registerHelper<QVariantMap>(); + registerHelper<QVariantHash>(); qDBusRegisterMetaType<QList<bool> >(); qDBusRegisterMetaType<QList<short> >(); diff --git a/src/declarative/debugger/debugger.pri b/src/declarative/debugger/debugger.pri index 25f7687..75287b4 100644 --- a/src/declarative/debugger/debugger.pri +++ b/src/declarative/debugger/debugger.pri @@ -7,13 +7,17 @@ SOURCES += \ $$PWD/qdeclarativedebugclient.cpp \ $$PWD/qdeclarativedebug.cpp \ $$PWD/qdeclarativedebugtrace.cpp \ - $$PWD/qdeclarativedebughelper.cpp + $$PWD/qdeclarativedebughelper.cpp \ + $$PWD/qdeclarativedebugserver.cpp HEADERS += \ $$PWD/qdeclarativedebuggerstatus_p.h \ $$PWD/qpacketprotocol_p.h \ $$PWD/qdeclarativedebugservice_p.h \ + $$PWD/qdeclarativedebugservice_p_p.h \ $$PWD/qdeclarativedebugclient_p.h \ $$PWD/qdeclarativedebug_p.h \ $$PWD/qdeclarativedebugtrace_p.h \ - $$PWD/qdeclarativedebughelper_p.h + $$PWD/qdeclarativedebughelper_p.h \ + $$PWD/qdeclarativedebugserver_p.h \ + debugger/qdeclarativedebugserverconnection_p.h diff --git a/src/declarative/debugger/qdeclarativedebugclient.cpp b/src/declarative/debugger/qdeclarativedebugclient.cpp index e6a3f69..036dee1 100644 --- a/src/declarative/debugger/qdeclarativedebugclient.cpp +++ b/src/declarative/debugger/qdeclarativedebugclient.cpp @@ -61,7 +61,7 @@ public: QDeclarativeDebugClientPrivate(); QString name; - QDeclarativeDebugConnection *client; + QDeclarativeDebugConnection *connection; }; class QDeclarativeDebugConnectionPrivate : public QObject @@ -202,7 +202,7 @@ QDeclarativeDebugConnection::~QDeclarativeDebugConnection() { QHash<QString, QDeclarativeDebugClient*>::iterator iter = d->plugins.begin(); for (; iter != d->plugins.end(); ++iter) { - iter.value()->d_func()->client = 0; + iter.value()->d_func()->connection = 0; iter.value()->statusChanged(QDeclarativeDebugClient::NotConnected); } } @@ -213,7 +213,7 @@ bool QDeclarativeDebugConnection::isConnected() const } QDeclarativeDebugClientPrivate::QDeclarativeDebugClientPrivate() -: client(0) +: connection(0) { } @@ -223,26 +223,26 @@ QDeclarativeDebugClient::QDeclarativeDebugClient(const QString &name, { Q_D(QDeclarativeDebugClient); d->name = name; - d->client = parent; + d->connection = parent; - if (!d->client) + if (!d->connection) return; - if (d->client->d->plugins.contains(name)) { + if (d->connection->d->plugins.contains(name)) { qWarning() << "QDeclarativeDebugClient: Conflicting plugin name" << name; - d->client = 0; + d->connection = 0; } else { - d->client->d->plugins.insert(name, this); - d->client->d->advertisePlugins(); + d->connection->d->plugins.insert(name, this); + d->connection->d->advertisePlugins(); } } QDeclarativeDebugClient::~QDeclarativeDebugClient() { Q_D(const QDeclarativeDebugClient); - if (d->client && d->client->d) { - d->client->d->plugins.remove(d->name); - d->client->d->advertisePlugins(); + if (d->connection && d->connection->d) { + d->connection->d->plugins.remove(d->name); + d->connection->d->advertisePlugins(); } } @@ -255,12 +255,12 @@ QString QDeclarativeDebugClient::name() const QDeclarativeDebugClient::Status QDeclarativeDebugClient::status() const { Q_D(const QDeclarativeDebugClient); - if (!d->client - || !d->client->isConnected() - || !d->client->d->gotHello) + if (!d->connection + || !d->connection->isConnected() + || !d->connection->d->gotHello) return NotConnected; - if (d->client->d->serverPlugins.contains(d->name)) + if (d->connection->d->serverPlugins.contains(d->name)) return Enabled; return Unavailable; @@ -275,8 +275,8 @@ void QDeclarativeDebugClient::sendMessage(const QByteArray &message) QPacket pack; pack << d->name << message; - d->client->d->protocol->send(pack); - d->client->d->q->flush(); + d->connection->d->protocol->send(pack); + d->connection->d->q->flush(); } void QDeclarativeDebugClient::statusChanged(Status) diff --git a/src/declarative/debugger/qdeclarativedebugserver.cpp b/src/declarative/debugger/qdeclarativedebugserver.cpp new file mode 100644 index 0000000..ea3d9a3 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserver.cpp @@ -0,0 +1,361 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativedebugserver_p.h" +#include "private/qdeclarativedebugservice_p.h" +#include "private/qdeclarativedebugservice_p_p.h" +#include "private/qdeclarativeengine_p.h" + +#include <QtCore/QDir> +#include <QtCore/QPluginLoader> +#include <QtCore/QStringList> + +#include <private/qobject_p.h> +#include <private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +/* + QDeclarativeDebug Protocol (Version 1): + + handshake: + 1. Client sends + "QDeclarativeDebugServer" 0 version pluginNames + version: an int representing the highest protocol version the client knows + pluginNames: plugins available on client side + 2. Server sends + "QDeclarativeDebugClient" 0 version pluginNames + version: an int representing the highest protocol version the client & server know + pluginNames: plugins available on server side. plugins both in the client and server message are enabled. + client plugin advertisement + 1. Client sends + "QDeclarativeDebugServer" 1 pluginNames + server plugin advertisement + 1. Server sends + "QDeclarativeDebugClient" 1 pluginNames + plugin communication: + Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin. + */ + +const int protocolVersion = 1; + + +class QDeclarativeDebugServerPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugServer) +public: + QDeclarativeDebugServerPrivate(); + + void advertisePlugins(); + + QDeclarativeDebugServerConnection *connection; + QHash<QString, QDeclarativeDebugService *> plugins; + QStringList clientPlugins; + bool gotHello; + + static QDeclarativeDebugServerConnection *loadConnectionPlugin(); +}; + +QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() : + connection(0), + gotHello(false) +{ +} + +void QDeclarativeDebugServerPrivate::advertisePlugins() +{ + if (!gotHello) + return; + + QByteArray message; + { + QDataStream out(&message, QIODevice::WriteOnly); + out << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); + } + connection->send(message); +} + +QDeclarativeDebugServerConnection *QDeclarativeDebugServerPrivate::loadConnectionPlugin() +{ + QStringList pluginCandidates; + const QStringList paths = QCoreApplication::libraryPaths(); + foreach (const QString &libPath, paths) { + const QDir dir(libPath + QLatin1String("/qmltooling")); + if (dir.exists()) { + QStringList plugins(dir.entryList(QDir::Files)); + foreach (const QString &pluginPath, plugins) { + pluginCandidates << dir.absoluteFilePath(pluginPath); + } + } + } + + foreach (const QString &pluginPath, pluginCandidates) { + QPluginLoader loader(pluginPath); + if (!loader.load()) { + continue; + } + QDeclarativeDebugServerConnection *connection = 0; + if (QObject *instance = loader.instance()) + connection = qobject_cast<QDeclarativeDebugServerConnection*>(instance); + + if (connection) + return connection; + loader.unload(); + } + return 0; +} + +bool QDeclarativeDebugServer::hasDebuggingClient() const +{ + Q_D(const QDeclarativeDebugServer); + return d->connection + && d->connection->isConnected() + && d->gotHello; +} + +QDeclarativeDebugServer *QDeclarativeDebugServer::instance() +{ + static bool commandLineTested = false; + static QDeclarativeDebugServer *server = 0; + + if (!commandLineTested) { + commandLineTested = true; + +#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL + QApplicationPrivate *appD = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp)); + // ### remove port definition when protocol is changed + int port = 0; + bool block = false; + bool ok = false; + + // format: qmljsdebugger=port:3768[,block] + if (!appD->qmljsDebugArgumentsString().isEmpty()) { + if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { + const QString message = + QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Debugging has not been enabled.").arg( + appD->qmljsDebugArgumentsString()); + qWarning("%s", qPrintable(message)); + return 0; + } + + if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) { + int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(',')); + port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok); + } + block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block")); + + if (ok) { + server = new QDeclarativeDebugServer(); + + QDeclarativeDebugServerConnection *connection + = QDeclarativeDebugServerPrivate::loadConnectionPlugin(); + if (connection) { + server->d_func()->connection = connection; + + connection->setServer(server); + connection->setPort(port, block); + } else { + qWarning() << QString::fromAscii("QDeclarativeDebugServer: Ignoring\"-qmljsdebugger=%1\". " + "Remote debugger plugin has not been found.").arg(appD->qmljsDebugArgumentsString()); + } + + } else { + qWarning(QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " + "Format is -qmljsdebugger=port:<port>[,block]").arg( + appD->qmljsDebugArgumentsString()).toAscii().constData()); + } + } +#endif + } + + return server; +} + +QDeclarativeDebugServer::QDeclarativeDebugServer() +: QObject(*(new QDeclarativeDebugServerPrivate)) +{ +} + +void QDeclarativeDebugServer::receiveMessage(const QByteArray &message) +{ + Q_D(QDeclarativeDebugServer); + + QDataStream in(message); + if (!d->gotHello) { + + QString name; + int op; + in >> name >> op; + + if (name != QLatin1String("QDeclarativeDebugServer") + || op != 0) { + qWarning("QDeclarativeDebugServer: Invalid hello message"); + d->connection->disconnect(); + return; + } + + int version; + in >> version >> d->clientPlugins; + + QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(iter.key())) + newStatus = QDeclarativeDebugService::Enabled; + iter.value()->d_func()->status = newStatus; + iter.value()->statusChanged(newStatus); + } + + QByteArray helloAnswer; + { + QDataStream out(&helloAnswer, QIODevice::WriteOnly); + out << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); + } + d->connection->send(helloAnswer); + + d->gotHello = true; + qWarning("QDeclarativeDebugServer: Connection established"); + } else { + + QString debugServer(QLatin1String("QDeclarativeDebugServer")); + + QString name; + in >> name; + + if (name == debugServer) { + int op = -1; + in >> op; + + if (op == 1) { + // Service Discovery + QStringList oldClientPlugins = d->clientPlugins; + in >> d->clientPlugins; + + QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); + for (; iter != d->plugins.end(); ++iter) { + const QString pluginName = iter.key(); + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(pluginName)) + newStatus = QDeclarativeDebugService::Enabled; + + if (oldClientPlugins.contains(pluginName) + != d->clientPlugins.contains(pluginName)) { + iter.value()->d_func()->status = newStatus; + iter.value()->statusChanged(newStatus); + } + } + } else { + qWarning("QDeclarativeDebugServer: Invalid control message %d", op); + } + } else { + QByteArray message; + in >> message; + + QHash<QString, QDeclarativeDebugService *>::Iterator iter = + d->plugins.find(name); + if (iter == d->plugins.end()) { + qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << name; + } else { + (*iter)->messageReceived(message); + } + } + } +} + +QList<QDeclarativeDebugService*> QDeclarativeDebugServer::services() const +{ + const Q_D(QDeclarativeDebugServer); + return d->plugins.values(); +} + +QStringList QDeclarativeDebugServer::serviceNames() const +{ + const Q_D(QDeclarativeDebugServer); + return d->plugins.keys(); +} + +bool QDeclarativeDebugServer::addService(QDeclarativeDebugService *service) +{ + Q_D(QDeclarativeDebugServer); + if (!service || d->plugins.contains(service->name())) + return false; + + d->plugins.insert(service->name(), service); + d->advertisePlugins(); + + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; + if (d->clientPlugins.contains(service->name())) + newStatus = QDeclarativeDebugService::Enabled; + service->d_func()->status = newStatus; + service->statusChanged(newStatus); + return true; +} + +bool QDeclarativeDebugServer::removeService(QDeclarativeDebugService *service) +{ + Q_D(QDeclarativeDebugServer); + if (!service || !d->plugins.contains(service->name())) + return false; + + d->plugins.remove(service->name()); + d->advertisePlugins(); + + QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::NotConnected; + service->d_func()->server = 0; + service->d_func()->status = newStatus; + service->statusChanged(newStatus); + return true; +} + +void QDeclarativeDebugServer::sendMessage(QDeclarativeDebugService *service, + const QByteArray &message) +{ + Q_D(QDeclarativeDebugServer); + QByteArray msg; + { + QDataStream out(&msg, QIODevice::WriteOnly); + out << service->name() << message; + } + d->connection->send(msg); +} + +QT_END_NAMESPACE diff --git a/src/declarative/debugger/qdeclarativedebugserver_p.h b/src/declarative/debugger/qdeclarativedebugserver_p.h new file mode 100644 index 0000000..ec3e60f --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserver_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVER_H +#define QDECLARATIVEDEBUGSERVER_H + +#include <private/qdeclarativeglobal_p.h> +#include <private/qdeclarativedebugserverconnection_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugService; + +class QDeclarativeDebugServerPrivate; +class Q_DECLARATIVE_EXPORT QDeclarativeDebugServer : public QObject +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QDeclarativeDebugServer) + Q_DISABLE_COPY(QDeclarativeDebugServer) +public: + static QDeclarativeDebugServer *instance(); + + void setConnection(QDeclarativeDebugServerConnection *connection); + + bool hasDebuggingClient() const; + + QList<QDeclarativeDebugService*> services() const; + QStringList serviceNames() const; + + bool addService(QDeclarativeDebugService *service); + bool removeService(QDeclarativeDebugService *service); + + void sendMessage(QDeclarativeDebugService *service, const QByteArray &message); + void receiveMessage(const QByteArray &message); + +private: + friend class QDeclarativeDebugService; + friend class QDeclarativeDebugServicePrivate; + QDeclarativeDebugServer(); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_H diff --git a/src/declarative/debugger/qdeclarativedebugserverconnection_p.h b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h new file mode 100644 index 0000000..631da74 --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugserverconnection_p.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVERCONNECTION_H +#define QDECLARATIVEDEBUGSERVERCONNECTION_H + +#include <QtDeclarative/private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServer; +class Q_DECLARATIVE_EXPORT QDeclarativeDebugServerConnection +{ +public: + QDeclarativeDebugServerConnection() {} + virtual ~QDeclarativeDebugServerConnection() {} + + virtual void setServer(QDeclarativeDebugServer *server) = 0; + virtual void setPort(int port, bool bock) = 0; + virtual bool isConnected() const = 0; + virtual void send(const QByteArray &message) = 0; + virtual void disconnect() = 0; +}; + +Q_DECLARE_INTERFACE(QDeclarativeDebugServerConnection, "com.trolltech.Qt.QDeclarativeDebugServerConnection/1.0") + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVERCONNECTION_H diff --git a/src/declarative/debugger/qdeclarativedebugservice.cpp b/src/declarative/debugger/qdeclarativedebugservice.cpp index e916de4..1b39f1c 100644 --- a/src/declarative/debugger/qdeclarativedebugservice.cpp +++ b/src/declarative/debugger/qdeclarativedebugservice.cpp @@ -40,301 +40,14 @@ ****************************************************************************/ #include "private/qdeclarativedebugservice_p.h" +#include "private/qdeclarativedebugservice_p_p.h" +#include "private/qdeclarativedebugserver_p.h" -#include "private/qpacketprotocol_p.h" -#include "private/qdeclarativeengine_p.h" - -#include <QtCore/qdebug.h> -#include <QtNetwork/qtcpserver.h> -#include <QtNetwork/qtcpsocket.h> -#include <QtCore/qstringlist.h> - -#include <private/qobject_p.h> -#include <private/qapplication_p.h> -#include <QtGui/qapplication.h> +#include <QtCore/QDebug> +#include <QtCore/QStringList> QT_BEGIN_NAMESPACE -/* - QDeclarativeDebug Protocol (Version 1): - - handshake: - 1. Client sends - "QDeclarativeDebugServer" 0 version pluginNames - version: an int representing the highest protocol version the client knows - pluginNames: plugins available on client side - 2. Server sends - "QDeclarativeDebugClient" 0 version pluginNames - version: an int representing the highest protocol version the client & server know - pluginNames: plugins available on server side. plugins both in the client and server message are enabled. - client plugin advertisement - 1. Client sends - "QDeclarativeDebugServer" 1 pluginNames - server plugin advertisement - 1. Server sends - "QDeclarativeDebugClient" 1 pluginNames - plugin communication: - Everything send with a header different to "QDeclarativeDebugServer" is sent to the appropriate plugin. - */ - -const int protocolVersion = 1; - -class QDeclarativeDebugServerPrivate; -class QDeclarativeDebugServer : public QObject -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QDeclarativeDebugServer) - Q_DISABLE_COPY(QDeclarativeDebugServer) -public: - static QDeclarativeDebugServer *instance(); - void listen(); - void waitForConnection(); - bool hasDebuggingClient() const; - -private Q_SLOTS: - void readyRead(); - void newConnection(); - -private: - friend class QDeclarativeDebugService; - friend class QDeclarativeDebugServicePrivate; - QDeclarativeDebugServer(int); -}; - -class QDeclarativeDebugServerPrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeDebugServer) -public: - QDeclarativeDebugServerPrivate(); - - void advertisePlugins(); - - int port; - QTcpSocket *connection; - QPacketProtocol *protocol; - QHash<QString, QDeclarativeDebugService *> plugins; - QStringList clientPlugins; - QTcpServer *tcpServer; - bool gotHello; -}; - -class QDeclarativeDebugServicePrivate : public QObjectPrivate -{ - Q_DECLARE_PUBLIC(QDeclarativeDebugService) -public: - QDeclarativeDebugServicePrivate(); - - QString name; - QDeclarativeDebugServer *server; -}; - -QDeclarativeDebugServerPrivate::QDeclarativeDebugServerPrivate() -: connection(0), protocol(0), gotHello(false) -{ -} - -void QDeclarativeDebugServerPrivate::advertisePlugins() -{ - if (!connection - || connection->state() != QTcpSocket::ConnectedState - || !gotHello) - return; - - QPacket pack; - pack << QString(QLatin1String("QDeclarativeDebugClient")) << 1 << plugins.keys(); - protocol->send(pack); - connection->flush(); -} - -void QDeclarativeDebugServer::listen() -{ - Q_D(QDeclarativeDebugServer); - - d->tcpServer = new QTcpServer(this); - QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); - if (d->tcpServer->listen(QHostAddress::Any, d->port)) - qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); - else - qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); -} - -void QDeclarativeDebugServer::waitForConnection() -{ - Q_D(QDeclarativeDebugServer); - d->tcpServer->waitForNewConnection(-1); -} - -void QDeclarativeDebugServer::newConnection() -{ - Q_D(QDeclarativeDebugServer); - - if (d->connection) { - qWarning("QDeclarativeDebugServer error: another client is already connected"); - QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); - delete faultyConnection; - return; - } - - d->connection = d->tcpServer->nextPendingConnection(); - d->connection->setParent(this); - d->protocol = new QPacketProtocol(d->connection, this); - QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); -} - -bool QDeclarativeDebugServer::hasDebuggingClient() const -{ - Q_D(const QDeclarativeDebugServer); - return d->connection - && (d->connection->state() == QTcpSocket::ConnectedState) - && d->gotHello; -} - -QDeclarativeDebugServer *QDeclarativeDebugServer::instance() -{ - static bool commandLineTested = false; - static QDeclarativeDebugServer *server = 0; - - if (!commandLineTested) { - commandLineTested = true; - -#ifndef QDECLARATIVE_NO_DEBUG_PROTOCOL - QApplicationPrivate *appD = static_cast<QApplicationPrivate*>(QObjectPrivate::get(qApp)); - // ### remove port definition when protocol is changed - int port = 0; - bool block = false; - bool ok = false; - - // format: qmljsdebugger=port:3768[,block] - if (!appD->qmljsDebugArgumentsString().isEmpty()) { - if (!QDeclarativeEnginePrivate::qml_debugging_enabled) { - qWarning() << QString::fromLatin1("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " - "Debugging has not been enabled.").arg( - appD->qmljsDebugArgumentsString()).toAscii().constData(); - return 0; - } - - if (appD->qmljsDebugArgumentsString().indexOf(QLatin1String("port:")) == 0) { - int separatorIndex = appD->qmljsDebugArgumentsString().indexOf(QLatin1Char(',')); - port = appD->qmljsDebugArgumentsString().mid(5, separatorIndex - 5).toInt(&ok); - } - block = appD->qmljsDebugArgumentsString().contains(QLatin1String("block")); - - if (ok) { - server = new QDeclarativeDebugServer(port); - server->listen(); - if (block) { - server->waitForConnection(); - } - } else { - const QString message = - QString::fromAscii("QDeclarativeDebugServer: Ignoring \"-qmljsdebugger=%1\". " - "Format is -qmljsdebugger=port:<port>[,block]"). - arg(appD->qmljsDebugArgumentsString()); - qWarning("%s", qPrintable(message)); - } - } -#endif - } - - return server; -} - -QDeclarativeDebugServer::QDeclarativeDebugServer(int port) -: QObject(*(new QDeclarativeDebugServerPrivate)) -{ - Q_D(QDeclarativeDebugServer); - d->port = port; -} - -void QDeclarativeDebugServer::readyRead() -{ - Q_D(QDeclarativeDebugServer); - - if (!d->gotHello) { - QPacket hello = d->protocol->read(); - - QString name; - int op; - hello >> name >> op; - - if (name != QLatin1String("QDeclarativeDebugServer") - || op != 0) { - qWarning("QDeclarativeDebugServer: Invalid hello message"); - QObject::disconnect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); - d->protocol->deleteLater(); - d->protocol = 0; - d->connection->deleteLater(); - d->connection = 0; - return; - } - - int version; - hello >> version >> d->clientPlugins; - - QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; - if (d->clientPlugins.contains(iter.key())) - newStatus = QDeclarativeDebugService::Enabled; - iter.value()->statusChanged(newStatus); - } - - QPacket helloAnswer; - helloAnswer << QString(QLatin1String("QDeclarativeDebugClient")) << 0 << protocolVersion << d->plugins.keys(); - d->protocol->send(helloAnswer); - d->connection->flush(); - - d->gotHello = true; - qWarning("QDeclarativeDebugServer: Connection established"); - } - - QString debugServer(QLatin1String("QDeclarativeDebugServer")); - - while (d->protocol->packetsAvailable()) { - QPacket pack = d->protocol->read(); - - QString name; - pack >> name; - - if (name == debugServer) { - int op = -1; - pack >> op; - - if (op == 1) { - // Service Discovery - QStringList oldClientPlugins = d->clientPlugins; - pack >> d->clientPlugins; - - QHash<QString, QDeclarativeDebugService*>::Iterator iter = d->plugins.begin(); - for (; iter != d->plugins.end(); ++iter) { - const QString pluginName = iter.key(); - QDeclarativeDebugService::Status newStatus = QDeclarativeDebugService::Unavailable; - if (d->clientPlugins.contains(pluginName)) - newStatus = QDeclarativeDebugService::Enabled; - - if (oldClientPlugins.contains(pluginName) - != d->clientPlugins.contains(pluginName)) { - iter.value()->statusChanged(newStatus); - } - } - } else { - qWarning("QDeclarativeDebugServer: Invalid control message %d", op); - } - } else { - QByteArray message; - pack >> message; - - QHash<QString, QDeclarativeDebugService *>::Iterator iter = - d->plugins.find(name); - if (iter == d->plugins.end()) { - qWarning() << "QDeclarativeDebugServer: Message received for missing plugin" << name; - } else { - (*iter)->messageReceived(message); - } - } - } -} - QDeclarativeDebugServicePrivate::QDeclarativeDebugServicePrivate() : server(0) { @@ -346,16 +59,16 @@ QDeclarativeDebugService::QDeclarativeDebugService(const QString &name, QObject Q_D(QDeclarativeDebugService); d->name = name; d->server = QDeclarativeDebugServer::instance(); + d->status = QDeclarativeDebugService::NotConnected; if (!d->server) return; - if (d->server->d_func()->plugins.contains(name)) { + if (d->server->serviceNames().contains(name)) { qWarning() << "QDeclarativeDebugService: Conflicting plugin name" << name; d->server = 0; } else { - d->server->d_func()->plugins.insert(name, this); - d->server->d_func()->advertisePlugins(); + d->server->addService(this); } } @@ -363,8 +76,7 @@ QDeclarativeDebugService::~QDeclarativeDebugService() { Q_D(const QDeclarativeDebugService); if (d->server) { - d->server->d_func()->plugins.remove(d->name); - d->server->d_func()->advertisePlugins(); + d->server->removeService(this); } } @@ -377,13 +89,7 @@ QString QDeclarativeDebugService::name() const QDeclarativeDebugService::Status QDeclarativeDebugService::status() const { Q_D(const QDeclarativeDebugService); - if (!d->server - || !d->server->hasDebuggingClient()) - return NotConnected; - if (d->server->d_func()->clientPlugins.contains(d->name)) - return Enabled; - - return Unavailable; + return d->status; } namespace { @@ -500,10 +206,7 @@ void QDeclarativeDebugService::sendMessage(const QByteArray &message) if (status() != Enabled) return; - QPacket pack; - pack << d->name << message; - d->server->d_func()->protocol->send(pack); - d->server->d_func()->connection->flush(); + d->server->sendMessage(this, message); } void QDeclarativeDebugService::statusChanged(Status) @@ -515,5 +218,3 @@ void QDeclarativeDebugService::messageReceived(const QByteArray &) } QT_END_NAMESPACE - -#include <qdeclarativedebugservice.moc> diff --git a/src/declarative/debugger/qdeclarativedebugservice_p_p.h b/src/declarative/debugger/qdeclarativedebugservice_p_p.h new file mode 100644 index 0000000..d2c8dda --- /dev/null +++ b/src/declarative/debugger/qdeclarativedebugservice_p_p.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEDEBUGSERVICE_P_H +#define QDECLARATIVEDEBUGSERVICE_P_H + +#include <QtCore/qglobal.h> +#include <private/qobject_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeDebugServer; + +class QDeclarativeDebugServicePrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeDebugService) +public: + QDeclarativeDebugServicePrivate(); + + QString name; + QDeclarativeDebugServer *server; + QDeclarativeDebugService::Status status; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEDEBUGSERVICE_P_H diff --git a/src/declarative/debugger/qdeclarativedebugtrace.cpp b/src/declarative/debugger/qdeclarativedebugtrace.cpp index 5b78683..6f28736 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace.cpp +++ b/src/declarative/debugger/qdeclarativedebugtrace.cpp @@ -43,11 +43,29 @@ #include <QtCore/qdatastream.h> #include <QtCore/qurl.h> +#include <QtCore/qtimer.h> Q_GLOBAL_STATIC(QDeclarativeDebugTrace, traceInstance); +// convert to a QByteArray that can be sent to the debug client +// use of QDataStream can skew results if m_deferredSend == false +// (see tst_qperformancetimer::trace() benchmark) +QByteArray QDeclarativeDebugData::toByteArray() const +{ + QByteArray data; + //### using QDataStream is relatively expensive + QDataStream ds(&data, QIODevice::WriteOnly); + ds << time << messageType << detailType; + if (messageType == (int)QDeclarativeDebugTrace::RangeData) + ds << detailData; + if (messageType == (int)QDeclarativeDebugTrace::RangeLocation) + ds << detailData << line; + return data; +} + QDeclarativeDebugTrace::QDeclarativeDebugTrace() -: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")) +: QDeclarativeDebugService(QLatin1String("CanvasFrameRate")), + m_enabled(false), m_deferredSend(true) { m_timer.start(); } @@ -64,10 +82,28 @@ void QDeclarativeDebugTrace::startRange(RangeType t) traceInstance()->startRangeImpl(t); } -void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &url) +void QDeclarativeDebugTrace::rangeData(RangeType t, const QString &data) { if (QDeclarativeDebugService::isDebuggingEnabled()) - traceInstance()->rangeDataImpl(t, url); + traceInstance()->rangeDataImpl(t, data); +} + +void QDeclarativeDebugTrace::rangeData(RangeType t, const QUrl &data) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeDataImpl(t, data); +} + +void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QString &fileName, int line) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeLocationImpl(t, fileName, line); +} + +void QDeclarativeDebugTrace::rangeLocation(RangeType t, const QUrl &fileName, int line) +{ + if (QDeclarativeDebugService::isDebuggingEnabled()) + traceInstance()->rangeLocationImpl(t, fileName, line); } void QDeclarativeDebugTrace::endRange(RangeType t) @@ -78,45 +114,105 @@ void QDeclarativeDebugTrace::endRange(RangeType t) void QDeclarativeDebugTrace::addEventImpl(EventType event) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)Event << (int)event; - sendMessage(data); + QDeclarativeDebugData ed = {m_timer.elapsed(), (int)Event, (int)event, QString(), -1}; + processMessage(ed); } void QDeclarativeDebugTrace::startRangeImpl(RangeType range) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeStart << (int)range; - sendMessage(data); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeStart, (int)range, QString(), -1}; + processMessage(rd); } -void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &u) +void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QString &rData) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeData << (int)range << (QString)u.toString(); - sendMessage(data); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData, -1}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeDataImpl(RangeType range, const QUrl &rData) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeData, (int)range, rData.toString(QUrl::FormattingOption(0x100)), -1}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QString &fileName, int line) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName, line}; + processMessage(rd); +} + +void QDeclarativeDebugTrace::rangeLocationImpl(RangeType range, const QUrl &fileName, int line) +{ + if (status() != Enabled || !m_enabled) + return; + + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeLocation, (int)range, fileName.toString(QUrl::FormattingOption(0x100)), line}; + processMessage(rd); } void QDeclarativeDebugTrace::endRangeImpl(RangeType range) { - if (status() != Enabled) + if (status() != Enabled || !m_enabled) return; - QByteArray data; - QDataStream ds(&data, QIODevice::WriteOnly); - ds << m_timer.elapsed() << (int)RangeEnd << (int)range; - sendMessage(data); + QDeclarativeDebugData rd = {m_timer.elapsed(), (int)RangeEnd, (int)range, QString(), -1}; + processMessage(rd); +} + +/* + Either send the message directly, or queue up + a list of messages to send later (via sendMessages) +*/ +void QDeclarativeDebugTrace::processMessage(const QDeclarativeDebugData &message) +{ + if (m_deferredSend) + m_data.append(message); + else + sendMessage(message.toByteArray()); } +/* + Send the messages queued up by processMessage +*/ +void QDeclarativeDebugTrace::sendMessages() +{ + if (m_deferredSend) { + //### this is a suboptimal way to send batched messages + for (int i = 0; i < m_data.count(); ++i) + sendMessage(m_data.at(i).toByteArray()); + m_data.clear(); + + //indicate completion + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << (qint64)-1 << (int)Complete; + sendMessage(data); + } +} + +void QDeclarativeDebugTrace::messageReceived(const QByteArray &message) +{ + QByteArray rwData = message; + QDataStream stream(&rwData, QIODevice::ReadOnly); + + stream >> m_enabled; + + if (!m_enabled) + sendMessages(); +} diff --git a/src/declarative/debugger/qdeclarativedebugtrace_p.h b/src/declarative/debugger/qdeclarativedebugtrace_p.h index 008b618..ae0653e 100644 --- a/src/declarative/debugger/qdeclarativedebugtrace_p.h +++ b/src/declarative/debugger/qdeclarativedebugtrace_p.h @@ -43,37 +43,54 @@ #define QDECLARATIVEDEBUGTRACE_P_H #include <private/qdeclarativedebugservice_p.h> -#include <QtCore/qelapsedtimer.h> +#include <private/qperformancetimer_p.h> QT_BEGIN_HEADER QT_BEGIN_NAMESPACE +struct QDeclarativeDebugData +{ + qint64 time; + int messageType; + int detailType; + + //### + QString detailData; //used by RangeData and RangeLocation + int line; //used by RangeLocation + + QByteArray toByteArray() const; +}; + class QUrl; class Q_AUTOTEST_EXPORT QDeclarativeDebugTrace : public QDeclarativeDebugService { public: - enum EventType { - FramePaint, - Mouse, - Key, - - MaximumEventType - }; - enum Message { Event, RangeStart, RangeData, + RangeLocation, RangeEnd, + Complete, MaximumMessage }; + enum EventType { + FramePaint, + Mouse, + Key, + + MaximumEventType + }; + enum RangeType { Painting, Compiling, Creating, + Binding, //running a binding + HandlingSignal, //running a signal handler MaximumRangeType }; @@ -81,16 +98,29 @@ public: static void addEvent(EventType); static void startRange(RangeType); + static void rangeData(RangeType, const QString &); static void rangeData(RangeType, const QUrl &); + static void rangeLocation(RangeType, const QString &, int); + static void rangeLocation(RangeType, const QUrl &, int); static void endRange(RangeType); QDeclarativeDebugTrace(); +protected: + virtual void messageReceived(const QByteArray &); private: void addEventImpl(EventType); void startRangeImpl(RangeType); + void rangeDataImpl(RangeType, const QString &); void rangeDataImpl(RangeType, const QUrl &); + void rangeLocationImpl(RangeType, const QString &, int); + void rangeLocationImpl(RangeType, const QUrl &, int); void endRangeImpl(RangeType); - QElapsedTimer m_timer; + void processMessage(const QDeclarativeDebugData &); + void sendMessages(); + QPerformanceTimer m_timer; + bool m_enabled; + bool m_deferredSend; + QList<QDeclarativeDebugData> m_data; }; QT_END_NAMESPACE diff --git a/src/declarative/debugger/qpacketprotocol.cpp b/src/declarative/debugger/qpacketprotocol.cpp index 0adfb76..15a14cf 100644 --- a/src/declarative/debugger/qpacketprotocol.cpp +++ b/src/declarative/debugger/qpacketprotocol.cpp @@ -407,6 +407,7 @@ QPacket::QPacket() buf = new QBuffer(&b); buf->open(QIODevice::WriteOnly); setDevice(buf); + setVersion(QDataStream::Qt_4_7); } /*! @@ -452,6 +453,14 @@ bool QPacket::isEmpty() const } /*! + Returns raw packet data. + */ +QByteArray QPacket::data() const +{ + return b; +} + +/*! Clears data in the packet. This is useful for reusing one writable packet. For example \code diff --git a/src/declarative/debugger/qpacketprotocol_p.h b/src/declarative/debugger/qpacketprotocol_p.h index 120579d..accb8ef 100644 --- a/src/declarative/debugger/qpacketprotocol_p.h +++ b/src/declarative/debugger/qpacketprotocol_p.h @@ -59,7 +59,7 @@ class QPacket; class QPacketAutoSend; class QPacketProtocolPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QPacketProtocol : public QObject +class Q_DECLARATIVE_EXPORT QPacketProtocol : public QObject { Q_OBJECT public: @@ -89,7 +89,7 @@ private: }; -class Q_DECLARATIVE_PRIVATE_EXPORT QPacket : public QDataStream +class Q_DECLARATIVE_EXPORT QPacket : public QDataStream { public: QPacket(); @@ -98,6 +98,7 @@ public: void clear(); bool isEmpty() const; + QByteArray data() const; protected: friend class QPacketProtocol; diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro index 4ed4f9f..6bd314f 100644 --- a/src/declarative/declarative.pro +++ b/src/declarative/declarative.pro @@ -27,6 +27,13 @@ include(debugger/debugger.pri) symbian: { TARGET.UID3=0x2001E623 LIBS += -lefsrv + + contains(QT_CONFIG, freetype) { + DEFINES += QT_NO_FONTCONFIG + INCLUDEPATH += \ + ../3rdparty/freetype/src \ + ../3rdparty/freetype/include + } } DEFINES += QT_NO_OPENTYPE diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri index ffdeb29..9904274 100644 --- a/src/declarative/graphicsitems/graphicsitems.pri +++ b/src/declarative/graphicsitems/graphicsitems.pri @@ -50,7 +50,12 @@ HEADERS += \ $$PWD/qdeclarativelayoutitem_p.h \ $$PWD/qdeclarativeitemchangelistener_p.h \ $$PWD/qdeclarativegraphicswidget_p.h \ - $$PWD/qdeclarativetextlayout_p.h + $$PWD/qdeclarativetextlayout_p.h \ + $$PWD/qdeclarativepincharea_p.h \ + $$PWD/qdeclarativepincharea_p_p.h \ + $$PWD/qdeclarativeimplicitsizeitem_p.h \ + $$PWD/qdeclarativeimplicitsizeitem_p_p.h + SOURCES += \ $$PWD/qdeclarativeitemsmodule.cpp \ @@ -83,5 +88,7 @@ SOURCES += \ $$PWD/qdeclarativelistview.cpp \ $$PWD/qdeclarativelayoutitem.cpp \ $$PWD/qdeclarativegraphicswidget.cpp \ - $$PWD/qdeclarativetextlayout.cpp + $$PWD/qdeclarativetextlayout.cpp \ + $$PWD/qdeclarativepincharea.cpp \ + $$PWD/qdeclarativeimplicitsizeitem.cpp diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp index 4729817..016b87d 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage.cpp @@ -86,6 +86,25 @@ QT_BEGIN_NAMESPACE \sa BorderImage, Image */ +/*! + \qmlproperty bool AnimatedImage::cache + \since Quick 1.1 + + Specifies whether the image should be cached. The default value is + true. Setting \a cache to false is useful when dealing with large images, + to make sure that they aren't cached at the expense of small 'ui element' images. +*/ + +/*! + \qmlproperty bool AnimatedImage::mirror + \since Quick 1.1 + + This property holds whether the image should be horizontally inverted + (effectively displaying a mirrored image). + + The default value is false. +*/ + QDeclarativeAnimatedImage::QDeclarativeAnimatedImage(QDeclarativeItem *parent) : QDeclarativeImage(*(new QDeclarativeAnimatedImagePrivate), parent) { @@ -126,7 +145,7 @@ void QDeclarativeAnimatedImage::setPaused(bool pause) \qmlproperty bool AnimatedImage::playing This property holds whether the animated image is playing. - By defaults, this property is true, meaning that the animation + By default, this property is true, meaning that the animation will start playing immediately. */ bool QDeclarativeAnimatedImage::isPlaying() const @@ -202,13 +221,22 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) } d->url = url; + emit sourceChanged(d->url); + + if (isComponentComplete()) + load(); +} + +void QDeclarativeAnimatedImage::load() +{ + Q_D(QDeclarativeAnimatedImage); - if (url.isEmpty()) { + if (d->url.isEmpty()) { delete d->_movie; d->status = Null; } else { #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML - QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url); + QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url); if (!lf.isEmpty()) { //### should be unified with movieRequestFinished d->_movie = new QMovie(lf); @@ -216,6 +244,8 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString(); delete d->_movie; d->_movie = 0; + d->status = Error; + emit statusChanged(d->status); return; } connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)), @@ -245,7 +275,6 @@ void QDeclarativeAnimatedImage::setSource(const QUrl &url) QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(movieRequestFinished())); } - emit statusChanged(d->status); } @@ -275,6 +304,8 @@ void QDeclarativeAnimatedImage::movieRequestFinished() #endif delete d->_movie; d->_movie = 0; + d->status = Error; + emit statusChanged(d->status); return; } connect(d->_movie, SIGNAL(stateChanged(QMovie::MovieState)), @@ -291,6 +322,8 @@ void QDeclarativeAnimatedImage::movieRequestFinished() if(d->paused) d->_movie->setPaused(true); d->setPixmap(d->_movie->currentPixmap()); + d->status = Ready; + emit statusChanged(d->status); } void QDeclarativeAnimatedImage::movieUpdate() @@ -317,6 +350,8 @@ void QDeclarativeAnimatedImage::componentComplete() { Q_D(QDeclarativeAnimatedImage); QDeclarativeItem::componentComplete(); // NOT QDeclarativeImage + if (d->url.isValid()) + load(); if (!d->reply) { setCurrentFrame(d->preset_currentframe); d->preset_currentframe = 0; diff --git a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h index e5025bf..e2ed70b 100644 --- a/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h +++ b/src/declarative/graphicsitems/qdeclarativeanimatedimage_p.h @@ -97,6 +97,7 @@ private Q_SLOTS: void playingStatusChanged(); protected: + virtual void load(); void componentComplete(); private: diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 16fb376..c03c624 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -200,6 +200,16 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage() */ /*! + \qmlproperty bool BorderImage::mirror + \since Quick 1.1 + + This property holds whether the image should be horizontally inverted + (effectively displaying a mirrored image). + + The default value is false. +*/ + +/*! \qmlproperty url BorderImage::source This property holds the URL that refers to the source image. @@ -215,17 +225,29 @@ QDeclarativeBorderImage::~QDeclarativeBorderImage() image \c picture.png: \qml - border.left: 10 - border.top: 10 - border.bottom: 10 - border.right: 10 - source: picture.png + BorderImage { + border.left: 10 + border.top: 10 + border.bottom: 10 + border.right: 10 + source: "picture.png" + } \endqml The URL may be absolute, or relative to the URL of the component. \sa QDeclarativeImageProvider */ + +/*! + \qmlproperty QSize BorderImage::sourceSize + + This property holds the actual width and height of the loaded image. + + In BorderImage, this property is read-only. + + \sa Image::sourceSize +*/ void QDeclarativeBorderImage::setSource(const QUrl &url) { Q_D(QDeclarativeBorderImage); @@ -290,7 +312,12 @@ void QDeclarativeBorderImage::load() } } else { - d->pix.load(qmlEngine(this), d->url, d->async); + QDeclarativePixmap::Options options; + if (d->async) + options |= QDeclarativePixmap::Asynchronous; + if (d->cache) + options |= QDeclarativePixmap::Cache; + d->pix.load(qmlEngine(this), d->url, options); if (d->pix.isLoading()) { d->pix.connectFinished(this, SLOT(requestFinished())); @@ -310,6 +337,7 @@ void QDeclarativeBorderImage::load() d->progress = 1.0; emit statusChanged(d->status); emit progressChanged(d->progress); + requestFinished(); update(); } } @@ -337,7 +365,10 @@ void QDeclarativeBorderImage::load() the bottom of the image: \qml - border.bottom: 10 + BorderImage { + border.bottom: 10 + // ... + } \endqml The border lines can also be specified using a @@ -413,7 +444,12 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl())); - d->pix.load(qmlEngine(this), d->sciurl, d->async); + QDeclarativePixmap::Options options; + if (d->async) + options |= QDeclarativePixmap::Asynchronous; + if (d->cache) + options |= QDeclarativePixmap::Cache; + d->pix.load(qmlEngine(this), d->sciurl, options); if (d->pix.isLoading()) { static int thisRequestProgress = -1; @@ -465,6 +501,9 @@ void QDeclarativeBorderImage::requestFinished() setImplicitWidth(impsize.width()); setImplicitHeight(impsize.height()); + if (d->sourcesize.width() != d->pix.width() || d->sourcesize.height() != d->pix.height()) + emit sourceSizeChanged(); + d->progress = 1.0; emit statusChanged(d->status); emit progressChanged(1.0); @@ -514,8 +553,15 @@ void QDeclarativeBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem bool oldAA = p->testRenderHint(QPainter::Antialiasing); bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + QTransform oldTransform; if (d->smooth) p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + if (d->mirror) { + oldTransform = p->transform(); + QTransform mirror; + mirror.translate(d->width(), 0).scale(-1, 1.0); + p->setWorldTransform(mirror * oldTransform); + } const QDeclarativeScaleGrid *border = d->getScaleGrid(); int left = border->left(); @@ -541,6 +587,8 @@ void QDeclarativeBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem p->setRenderHint(QPainter::Antialiasing, oldAA); p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); } + if (d->mirror) + p->setWorldTransform(oldTransform); } QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h index ca1eae8..f4c6594 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage_p.h +++ b/src/declarative/graphicsitems/qdeclarativeborderimage_p.h @@ -63,6 +63,9 @@ class Q_AUTOTEST_EXPORT QDeclarativeBorderImage : public QDeclarativeImageBase Q_PROPERTY(TileMode horizontalTileMode READ horizontalTileMode WRITE setHorizontalTileMode NOTIFY horizontalTileModeChanged) Q_PROPERTY(TileMode verticalTileMode READ verticalTileMode WRITE setVerticalTileMode NOTIFY verticalTileModeChanged) + // read-only for BorderImage + Q_PROPERTY(QSize sourceSize READ sourceSize NOTIFY sourceSizeChanged) + public: QDeclarativeBorderImage(QDeclarativeItem *parent=0); ~QDeclarativeBorderImage(); @@ -83,6 +86,7 @@ public: Q_SIGNALS: void horizontalTileModeChanged(); void verticalTileModeChanged(); + void sourceSizeChanged(); protected: virtual void load(); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index d35718b..0faa296 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -53,6 +53,10 @@ QT_BEGIN_NAMESPACE // before we perform a flick. static const int FlickThreshold = 20; +// RetainGrabVelocity is the maxmimum instantaneous velocity that +// will ensure the Flickable retains the grab on consecutive flicks. +static const int RetainGrabVelocity = 15; + QDeclarativeFlickableVisibleArea::QDeclarativeFlickableVisibleArea(QDeclarativeFlickable *parent) : QObject(parent), flickable(parent), m_xPosition(0.), m_widthRatio(0.) , m_yPosition(0.), m_heightRatio(0.) @@ -373,9 +377,9 @@ void QDeclarativeFlickablePrivate::updateBeginningEnd() \section1 Example Usage - \beginfloatright + \div {float-right} \inlineimage flickable.gif - \endfloat + \enddiv The following example shows a small view onto a large image in which the user can drag or flick the image in order to view different parts of it. @@ -672,7 +676,8 @@ void QDeclarativeFlickable::setFlickableDirection(FlickableDirection direction) void QDeclarativeFlickablePrivate::handleMousePressEvent(QGraphicsSceneMouseEvent *event) { Q_Q(QDeclarativeFlickable); - if (interactive && timeline.isActive() && (qAbs(hData.velocity) > 10 || qAbs(vData.velocity) > 10)) + if (interactive && timeline.isActive() + && (qAbs(hData.smoothVelocity.value()) > RetainGrabVelocity || qAbs(vData.smoothVelocity.value()) > RetainGrabVelocity)) stealMouse = true; // If we've been flicked then steal the click. else stealMouse = false; @@ -876,7 +881,7 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) Q_D(QDeclarativeFlickable); if (!d->interactive) { QDeclarativeItem::wheelEvent(event); - } else if (yflick()) { + } else if (yflick() && event->orientation() == Qt::Vertical) { if (event->delta() > 0) d->vData.velocity = qMax(event->delta() - d->vData.smoothVelocity.value(), qreal(250.0)); else @@ -888,7 +893,7 @@ void QDeclarativeFlickable::wheelEvent(QGraphicsSceneWheelEvent *event) movementStarting(); } event->accept(); - } else if (xflick()) { + } else if (xflick() && event->orientation() == Qt::Horizontal) { if (event->delta() > 0) d->hData.velocity = qMax(event->delta() - d->hData.smoothVelocity.value(), qreal(250.0)); else @@ -1250,6 +1255,60 @@ void QDeclarativeFlickable::setContentHeight(qreal h) d->updateBeginningEnd(); } +/*! + \qmlmethod Flickable::resizeContent(real width, real height, QPointF center) + \preliminary + + Resizes the content to \a width x \a height about \a center. + + \bold {This method was added in QtQuick 1.1.} + + This does not scale the contents of the Flickable - it only resizes the \l contentWidth + and \l contentHeight. + + Resizing the content may result in the content being positioned outside + the bounds of the Flickable. Calling \l returnToBounds() will + move the content back within legal bounds. +*/ +void QDeclarativeFlickable::resizeContent(qreal w, qreal h, QPointF center) +{ + Q_D(QDeclarativeFlickable); + if (w != d->hData.viewSize) { + qreal oldSize = d->hData.viewSize; + setContentWidth(w); + if (center.x() != 0) { + qreal pos = center.x() * w / oldSize; + setContentX(contentX() + pos - center.x()); + } + } + if (h != d->vData.viewSize) { + qreal oldSize = d->vData.viewSize; + setContentHeight(h); + if (center.y() != 0) { + qreal pos = center.y() * h / oldSize; + setContentY(contentY() + pos - center.y()); + } + } +} + +/*! + \qmlmethod Flickable::returnToBounds() + \preliminary + + Ensures the content is within legal bounds. + + \bold {This method was added in QtQuick 1.1.} + + This may be called to ensure that the content is within legal bounds + after manually positioning the content. +*/ +void QDeclarativeFlickable::returnToBounds() +{ + Q_D(QDeclarativeFlickable); + d->fixupX(); + d->fixupY(); +} + qreal QDeclarativeFlickable::vWidth() const { Q_D(const QDeclarativeFlickable); diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h index 1359dc8..4fde1d5 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h @@ -149,6 +149,9 @@ public: FlickableDirection flickableDirection() const; void setFlickableDirection(FlickableDirection); + Q_INVOKABLE Q_REVISION(1) void resizeContent(qreal w, qreal h, QPointF center); + Q_INVOKABLE Q_REVISION(1) void returnToBounds(); + Q_SIGNALS: void contentWidthChanged(); void contentHeightChanged(); diff --git a/src/declarative/graphicsitems/qdeclarativeflipable.cpp b/src/declarative/graphicsitems/qdeclarativeflipable.cpp index 160872c..5fda758 100644 --- a/src/declarative/graphicsitems/qdeclarativeflipable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflipable.cpp @@ -142,6 +142,7 @@ void QDeclarativeFlipable::setFront(QGraphicsObject *front) d->front->setParentItem(this); if (Back == d->current) d->front->setOpacity(0.); + emit frontChanged(); } QGraphicsObject *QDeclarativeFlipable::back() @@ -165,6 +166,7 @@ void QDeclarativeFlipable::setBack(QGraphicsObject *back) this, SLOT(retransformBack())); connect(back, SIGNAL(heightChanged()), this, SLOT(retransformBack())); + emit backChanged(); } void QDeclarativeFlipable::retransformBack() diff --git a/src/declarative/graphicsitems/qdeclarativeflipable_p.h b/src/declarative/graphicsitems/qdeclarativeflipable_p.h index c294697..4ea2ec0 100644 --- a/src/declarative/graphicsitems/qdeclarativeflipable_p.h +++ b/src/declarative/graphicsitems/qdeclarativeflipable_p.h @@ -60,8 +60,8 @@ class Q_AUTOTEST_EXPORT QDeclarativeFlipable : public QDeclarativeItem Q_OBJECT Q_ENUMS(Side) - Q_PROPERTY(QGraphicsObject *front READ front WRITE setFront) - Q_PROPERTY(QGraphicsObject *back READ back WRITE setBack) + Q_PROPERTY(QGraphicsObject *front READ front WRITE setFront NOTIFY frontChanged) + Q_PROPERTY(QGraphicsObject *back READ back WRITE setBack NOTIFY backChanged) Q_PROPERTY(Side side READ side NOTIFY sideChanged) //### flipAxis //### flipRotation @@ -79,6 +79,8 @@ public: Side side() const; Q_SIGNALS: + void frontChanged(); + void backChanged(); void sideChanged(); private Q_SLOTS: diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index 4c04a6b..694130b 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -331,11 +331,14 @@ public: } } } else if ((header && header->item == item) || (footer && footer->item == item)) { - updateHeader(); - updateFooter(); + if (header) + updateHeader(); + if (footer) + updateFooter(); } } + void positionViewAtIndex(int index, int mode); virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent); virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity); @@ -1095,9 +1098,9 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0 - \beginfloatright + \div {float-right} \inlineimage gridview-simple.png - \endfloat + \enddiv This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules} for more information about creating reusable components like this. @@ -1111,9 +1114,9 @@ void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal m \codeline \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple - \beginfloatright + \div {float-right} \inlineimage gridview-highlight.png - \endfloat + \enddiv The view will create a new delegate for each item in the model. Note that the delegate is able to access the model's \c name and \c portrait data directly. @@ -1615,6 +1618,8 @@ void QDeclarativeGridView::setFlow(Flow flow) setContentHeight(-1); setFlickableDirection(QDeclarativeFlickable::HorizontalFlick); } + setContentX(0); + setContentY(0); d->clear(); d->updateGrid(); refill(); @@ -1776,6 +1781,9 @@ void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer) Q_D(QDeclarativeGridView); if (d->footerComponent != footer) { if (d->footer) { + if (scene()) + scene()->removeItem(d->footer->item); + d->footer->item->deleteLater(); delete d->footer; d->footer = 0; } @@ -1783,6 +1791,7 @@ void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer) if (isComponentComplete()) { d->updateFooter(); d->updateGrid(); + d->fixupPosition(); } emit footerChanged(); } @@ -1808,6 +1817,9 @@ void QDeclarativeGridView::setHeader(QDeclarativeComponent *header) Q_D(QDeclarativeGridView); if (d->headerComponent != header) { if (d->header) { + if (scene()) + scene()->removeItem(d->header->item); + d->header->item->deleteLater(); delete d->header; d->header = 0; } @@ -1816,6 +1828,7 @@ void QDeclarativeGridView::setHeader(QDeclarativeComponent *header) d->updateHeader(); d->updateFooter(); d->updateGrid(); + d->fixupPosition(); } emit headerChanged(); } @@ -2122,6 +2135,78 @@ void QDeclarativeGridView::moveCurrentIndexRight() } } +void QDeclarativeGridViewPrivate::positionViewAtIndex(int index, int mode) +{ + Q_Q(QDeclarativeGridView); + if (!isValid()) + return; + if (mode < QDeclarativeGridView::Beginning || mode > QDeclarativeGridView::Contain) + return; + + int idx = qMax(qMin(index, model->count()-1), 0); + + if (layoutScheduled) + layout(); + qreal pos = position(); + FxGridItem *item = visibleItem(idx); + qreal maxExtent = flow == QDeclarativeGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent(); + if (!item) { + int itemPos = rowPosAt(idx); + // save the currently visible items in case any of them end up visible again + QList<FxGridItem*> oldVisible = visibleItems; + visibleItems.clear(); + visibleIndex = idx - idx % columns; + maxExtent = flow == QDeclarativeGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent(); + setPosition(qMin(qreal(itemPos), maxExtent)); + // now release the reference to all the old visible items. + for (int i = 0; i < oldVisible.count(); ++i) + releaseItem(oldVisible.at(i)); + item = visibleItem(idx); + } + if (item) { + qreal itemPos = item->rowPos(); + switch (mode) { + case QDeclarativeGridView::Beginning: + pos = itemPos; + if (index < 0 && header) { + pos -= flow == QDeclarativeGridView::LeftToRight + ? header->item->height() + : header->item->width(); + } + break; + case QDeclarativeGridView::Center: + pos = itemPos - (size() - rowSize())/2; + break; + case QDeclarativeGridView::End: + pos = itemPos - size() + rowSize(); + if (index >= model->count() && footer) { + pos += flow == QDeclarativeGridView::LeftToRight + ? footer->item->height() + : footer->item->width(); + } + break; + case QDeclarativeGridView::Visible: + if (itemPos > pos + size()) + pos = itemPos - size() + rowSize(); + else if (item->endRowPos() < pos) + pos = itemPos; + break; + case QDeclarativeGridView::Contain: + if (item->endRowPos() > pos + size()) + pos = itemPos - size() + rowSize(); + if (itemPos < pos) + pos = itemPos; + } + pos = qMin(pos, maxExtent); + qreal minExtent = flow == QDeclarativeGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent(); + pos = qMax(pos, minExtent); + moveReason = QDeclarativeGridViewPrivate::Other; + q->cancelFlick(); + setPosition(pos); + } + fixupPosition(); +} + /*! \qmlmethod GridView::positionViewAtIndex(int index, PositionMode mode) @@ -2159,58 +2244,42 @@ void QDeclarativeGridView::positionViewAtIndex(int index, int mode) Q_D(QDeclarativeGridView); if (!d->isValid() || index < 0 || index >= d->model->count()) return; - if (mode < Beginning || mode > Contain) + d->positionViewAtIndex(index, mode); +} + +/*! + \qmlmethod GridView::positionViewAtBeginning() + \qmlmethod GridView::positionViewAtEnd() + + Positions the view at the beginning or end, taking into account any header or footer. + + It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view + at a particular index. This is unreliable since removing items from the start + of the list does not cause all other items to be repositioned, and because + the actual start of the view can vary based on the size of the delegates. + + \bold Note: methods should only be called after the Component has completed. To position + the view at startup, this method should be called by Component.onCompleted. For + example, to position the view at the end on startup: + + \code + Component.onCompleted: positionViewAtEnd() + \endcode +*/ +void QDeclarativeGridView::positionViewAtBeginning() +{ + Q_D(QDeclarativeGridView); + if (!d->isValid()) return; + d->positionViewAtIndex(-1, Beginning); +} - if (d->layoutScheduled) - d->layout(); - qreal pos = d->position(); - qreal maxExtent = d->flow == QDeclarativeGridView::LeftToRight ? -maxYExtent() : -maxXExtent(); - FxGridItem *item = d->visibleItem(index); - if (!item) { - int itemPos = d->rowPosAt(index); - // save the currently visible items in case any of them end up visible again - QList<FxGridItem*> oldVisible = d->visibleItems; - d->visibleItems.clear(); - d->visibleIndex = index - index % d->columns; - d->setPosition(qMin(qreal(itemPos), maxExtent)); - // now release the reference to all the old visible items. - for (int i = 0; i < oldVisible.count(); ++i) - d->releaseItem(oldVisible.at(i)); - item = d->visibleItem(index); - } - if (item) { - qreal itemPos = item->rowPos(); - switch (mode) { - case Beginning: - pos = itemPos; - break; - case Center: - pos = itemPos - (d->size() - d->rowSize())/2; - break; - case End: - pos = itemPos - d->size() + d->rowSize(); - break; - case Visible: - if (itemPos > pos + d->size()) - pos = itemPos - d->size() + d->rowSize(); - else if (item->endRowPos() < pos) - pos = itemPos; - break; - case Contain: - if (item->endRowPos() > pos + d->size()) - pos = itemPos - d->size() + d->rowSize(); - if (itemPos < pos) - pos = itemPos; - } - pos = qMin(pos, maxExtent); - qreal minExtent = d->flow == QDeclarativeGridView::LeftToRight ? -minYExtent() : -minXExtent(); - pos = qMax(pos, minExtent); - d->moveReason = QDeclarativeGridViewPrivate::Other; - cancelFlick(); - d->setPosition(pos); - } - d->fixupPosition(); +void QDeclarativeGridView::positionViewAtEnd() +{ + Q_D(QDeclarativeGridView); + if (!d->isValid()) + return; + d->positionViewAtIndex(d->model->count(), End); } /*! @@ -2321,24 +2390,9 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) Q_D(QDeclarativeGridView); if (!isComponentComplete()) return; - if (!d->visibleItems.count() || d->model->count() <= 1) { - d->scheduleLayout(); - if (d->itemCount && d->currentIndex >= modelIndex) { - // adjust current item index - d->currentIndex += count; - if (d->currentItem) - d->currentItem->index = d->currentIndex; - emit currentIndexChanged(); - } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { - d->updateCurrent(0); - } - d->itemCount += count; - emit countChanged(); - return; - } - int index = d->mapFromModel(modelIndex); - if (index == -1) { + int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0; + if (index < 0) { int i = d->visibleItems.count() - 1; while (i > 0 && d->visibleItems.at(i)->index == -1) --i; @@ -2369,28 +2423,35 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) } } - // At least some of the added items will be visible int insertCount = count; - if (index < d->visibleIndex) { + if (index < d->visibleIndex && d->visibleItems.count()) { insertCount -= d->visibleIndex - index; index = d->visibleIndex; modelIndex = d->visibleIndex; } - index -= d->visibleIndex; int to = d->buffer+d->position()+d->size()-1; - int colPos, rowPos; - if (index < d->visibleItems.count()) { - colPos = d->visibleItems.at(index)->colPos(); - rowPos = d->visibleItems.at(index)->rowPos(); - } else { - // appending items to visible list - colPos = d->visibleItems.at(index-1)->colPos() + d->colSize(); - rowPos = d->visibleItems.at(index-1)->rowPos(); - if (colPos > d->colSize() * (d->columns-1)) { - colPos = 0; - rowPos += d->rowSize(); + int colPos = 0; + int rowPos = 0; + if (d->visibleItems.count()) { + index -= d->visibleIndex; + if (index < d->visibleItems.count()) { + colPos = d->visibleItems.at(index)->colPos(); + rowPos = d->visibleItems.at(index)->rowPos(); + } else { + // appending items to visible list + colPos = d->visibleItems.at(index-1)->colPos() + d->colSize(); + rowPos = d->visibleItems.at(index-1)->rowPos(); + if (colPos > d->colSize() * (d->columns-1)) { + colPos = 0; + rowPos += d->rowSize(); + } } + } else if (d->itemCount == 0 && d->header) { + if (d->flow == QDeclarativeGridView::LeftToRight) + rowPos = d->headerSize(); + else + colPos = d->headerSize(); } // Update the indexes of the following visible items. @@ -2443,6 +2504,8 @@ void QDeclarativeGridView::itemsInserted(int modelIndex, int count) if (d->currentItem) { d->currentItem->index = d->currentIndex; d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex)); + } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { + d->updateCurrent(0); } emit currentIndexChanged(); } @@ -2560,12 +2623,8 @@ void QDeclarativeGridView::itemsMoved(int from, int to, int count) return; QHash<int,FxGridItem*> moved; - bool removedBeforeVisible = false; FxGridItem *firstItem = d->firstVisibleItem(); - if (from < to && from < d->visibleIndex && to > d->visibleIndex) - removedBeforeVisible = true; - QList<FxGridItem*>::Iterator it = d->visibleItems.begin(); while (it != d->visibleItems.end()) { FxGridItem *item = *it; @@ -2574,16 +2633,12 @@ void QDeclarativeGridView::itemsMoved(int from, int to, int count) item->index += (to-from); moved.insert(item->index, item); it = d->visibleItems.erase(it); - if (item->rowPos() < firstItem->rowPos()) - removedBeforeVisible = true; } else { if (item->index > from && item->index != -1) { // move everything after the moved items. item->index -= count; if (item->index < d->visibleIndex) d->visibleIndex = item->index; - } else if (item->index != -1) { - removedBeforeVisible = true; } ++it; } diff --git a/src/declarative/graphicsitems/qdeclarativegridview_p.h b/src/declarative/graphicsitems/qdeclarativegridview_p.h index 7dc8954..248b9ef 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview_p.h +++ b/src/declarative/graphicsitems/qdeclarativegridview_p.h @@ -159,6 +159,8 @@ public: Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(int x, int y) const; + Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning(); + Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd(); static QDeclarativeGridViewAttached *qmlAttachedProperties(QObject *); diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp index e90a4df..2c9bde5 100644 --- a/src/declarative/graphicsitems/qdeclarativeimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp @@ -458,84 +458,102 @@ QRectF QDeclarativeImage::boundingRect() const are always loaded asynchonously. */ +/*! + \qmlproperty bool Image::cache + \since Quick 1.1 + + Specifies whether the image should be cached. The default value is + true. Setting \a cache to false is useful when dealing with large images, + to make sure that they aren't cached at the expense of small 'ui element' images. +*/ + +/*! + \qmlproperty bool Image::mirror + \since Quick 1.1 + + This property holds whether the image should be horizontally inverted + (effectively displaying a mirrored image). + + The default value is false. +*/ + + void QDeclarativeImage::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) { Q_D(QDeclarativeImage); if (d->pix.pixmap().isNull() ) return; - bool oldAA = p->testRenderHint(QPainter::Antialiasing); - bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); - if (d->smooth) - p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + int drawWidth = width(); + int drawHeight = height(); + bool doClip = false; + QTransform transform; + qreal widthScale = width() / qreal(d->pix.width()); + qreal heightScale = height() / qreal(d->pix.height()); if (width() != d->pix.width() || height() != d->pix.height()) { if (d->fillMode >= Tile) { - if (d->fillMode == Tile) { - p->drawTiledPixmap(QRectF(0,0,width(),height()), d->pix); - } else { - qreal widthScale = width() / qreal(d->pix.width()); - qreal heightScale = height() / qreal(d->pix.height()); - - QTransform scale; - if (d->fillMode == TileVertically) { - scale.scale(widthScale, 1.0); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawTiledPixmap(QRectF(0,0,d->pix.width(),height()), d->pix); - p->setWorldTransform(old); - } else { - scale.scale(1.0, heightScale); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawTiledPixmap(QRectF(0,0,width(),d->pix.height()), d->pix); - p->setWorldTransform(old); - } + if (d->fillMode == TileVertically) { + transform.scale(widthScale, 1.0); + drawWidth = d->pix.width(); + } else if (d->fillMode == TileHorizontally) { + transform.scale(1.0, heightScale); + drawHeight = d->pix.height(); } } else { - qreal widthScale = width() / qreal(d->pix.width()); - qreal heightScale = height() / qreal(d->pix.height()); - - QTransform scale; - if (d->fillMode == PreserveAspectFit) { if (widthScale <= heightScale) { heightScale = widthScale; - scale.translate(0, (height() - heightScale * d->pix.height()) / 2); + transform.translate(0, (height() - heightScale * d->pix.height()) / 2); } else if(heightScale < widthScale) { widthScale = heightScale; - scale.translate((width() - widthScale * d->pix.width()) / 2, 0); + transform.translate((width() - widthScale * d->pix.width()) / 2, 0); } } else if (d->fillMode == PreserveAspectCrop) { if (widthScale < heightScale) { widthScale = heightScale; - scale.translate((width() - widthScale * d->pix.width()) / 2, 0); + transform.translate((width() - widthScale * d->pix.width()) / 2, 0); } else if(heightScale < widthScale) { heightScale = widthScale; - scale.translate(0, (height() - heightScale * d->pix.height()) / 2); + transform.translate(0, (height() - heightScale * d->pix.height()) / 2); } } - if (clip()) { - p->save(); - p->setClipRect(QRectF(0, 0, d->mWidth, d->mHeight), Qt::IntersectClip); - } - scale.scale(widthScale, heightScale); - QTransform old = p->transform(); - p->setWorldTransform(scale * old); - p->drawPixmap(0, 0, d->pix); - p->setWorldTransform(old); - if (clip()) { - p->restore(); - } + transform.scale(widthScale, heightScale); + drawWidth = d->pix.width(); + drawHeight = d->pix.height(); + doClip = clip(); } - } else { - p->drawPixmap(0, 0, d->pix); } + QTransform oldTransform; + bool oldAA = p->testRenderHint(QPainter::Antialiasing); + bool oldSmooth = p->testRenderHint(QPainter::SmoothPixmapTransform); + if (d->smooth) + p->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, d->smooth); + if (doClip) { + p->save(); + p->setClipRect(QRectF(0, 0, d->mWidth, d->mHeight), Qt::IntersectClip); + } + if (d->mirror) + transform.translate(drawWidth, 0).scale(-1.0, 1.0); + if (!transform.isIdentity()) { + oldTransform = p->transform(); + p->setWorldTransform(transform * oldTransform); + } + + if (d->fillMode >= Tile) + p->drawTiledPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix); + else + p->drawPixmap(QRectF(0, 0, drawWidth, drawHeight), d->pix, QRectF(0, 0, drawWidth, drawHeight)); + if (d->smooth) { p->setRenderHint(QPainter::Antialiasing, oldAA); p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth); } + if (doClip) + p->restore(); + if (!transform.isIdentity()) + p->setWorldTransform(oldTransform); } void QDeclarativeImage::pixmapChange() diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp index 74e9337..471c87f 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp +++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp @@ -48,8 +48,13 @@ QT_BEGIN_NAMESPACE +QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeItem *parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeImageBasePrivate), parent) +{ +} + QDeclarativeImageBase::QDeclarativeImageBase(QDeclarativeImageBasePrivate &dd, QDeclarativeItem *parent) - : QDeclarativeItem(dd, parent) + : QDeclarativeImplicitSizeItem(dd, parent) { } @@ -128,6 +133,44 @@ QSize QDeclarativeImageBase::sourceSize() const return QSize(width != -1 ? width : implicitWidth(), height != -1 ? height : implicitHeight()); } +bool QDeclarativeImageBase::cache() const +{ + Q_D(const QDeclarativeImageBase); + return d->cache; +} + +void QDeclarativeImageBase::setCache(bool cache) +{ + Q_D(QDeclarativeImageBase); + if (d->cache == cache) + return; + + d->cache = cache; + emit cacheChanged(); + if (isComponentComplete()) + load(); +} + +void QDeclarativeImageBase::setMirror(bool mirror) +{ + Q_D(QDeclarativeImageBase); + if (mirror == d->mirror) + return; + + d->mirror = mirror; + + if (isComponentComplete()) + update(); + + emit mirrorChanged(); +} + +bool QDeclarativeImageBase::mirror() const +{ + Q_D(const QDeclarativeImageBase); + return d->mirror; +} + void QDeclarativeImageBase::load() { Q_D(QDeclarativeImageBase); @@ -143,7 +186,12 @@ void QDeclarativeImageBase::load() pixmapChange(); update(); } else { - d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), d->async); + QDeclarativePixmap::Options options; + if (d->async) + options |= QDeclarativePixmap::Asynchronous; + if (d->cache) + options |= QDeclarativePixmap::Cache; + d->pix.load(qmlEngine(this), d->url, d->explicitSourceSize ? sourceSize() : QSize(), options); if (d->pix.isLoading()) { d->progress = 0.0; diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h index 7135170..abee25d 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h @@ -42,14 +42,14 @@ #ifndef QDECLARATIVEIMAGEBASE_H #define QDECLARATIVEIMAGEBASE_H -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" QT_BEGIN_HEADER QT_BEGIN_NAMESPACE class QDeclarativeImageBasePrivate; -class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeItem +class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeImplicitSizeItem { Q_OBJECT Q_ENUMS(Status) @@ -58,9 +58,12 @@ class Q_AUTOTEST_EXPORT QDeclarativeImageBase : public QDeclarativeItem Q_PROPERTY(QUrl source READ source WRITE setSource NOTIFY sourceChanged) Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged) Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged) + Q_PROPERTY(bool cache READ cache WRITE setCache NOTIFY cacheChanged REVISION 1) Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged) + Q_PROPERTY(bool mirror READ mirror WRITE setMirror NOTIFY mirrorChanged REVISION 1) public: + QDeclarativeImageBase(QDeclarativeItem *parent=0); ~QDeclarativeImageBase(); enum Status { Null, Ready, Loading, Error }; Status status() const; @@ -72,15 +75,23 @@ public: bool asynchronous() const; void setAsynchronous(bool); + bool cache() const; + void setCache(bool); + virtual void setSourceSize(const QSize&); QSize sourceSize() const; + virtual void setMirror(bool mirror); + bool mirror() const; + Q_SIGNALS: void sourceChanged(const QUrl &); void sourceSizeChanged(); void statusChanged(QDeclarativeImageBase::Status); void progressChanged(qreal progress); void asynchronousChanged(); + Q_REVISION(1) void cacheChanged(); + Q_REVISION(1) void mirrorChanged(); protected: virtual void load(); diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h index 5d892ad..ab16e66 100644 --- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h @@ -53,7 +53,7 @@ // We mean it. // -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include "private/qdeclarativepixmapcache_p.h" #include <QtCore/QPointer> @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE class QNetworkReply; -class QDeclarativeImageBasePrivate : public QDeclarativeItemPrivate +class QDeclarativeImageBasePrivate : public QDeclarativeImplicitSizeItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeImageBase) @@ -70,7 +70,9 @@ public: : status(QDeclarativeImageBase::Null), progress(0.0), explicitSourceSize(false), - async(false) + async(false), + cache(true), + mirror(false) { QGraphicsItemPrivate::flags = QGraphicsItemPrivate::flags & ~QGraphicsItem::ItemHasNoContents; } @@ -82,6 +84,8 @@ public: QSize sourcesize; bool explicitSourceSize : 1; bool async : 1; + bool cache : 1; + bool mirror: 1; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp new file mode 100644 index 0000000..31ac28f --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qdeclarativeimplicitsizeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" + +QT_BEGIN_NAMESPACE + +void QDeclarativeImplicitSizeItemPrivate::implicitWidthChanged() +{ + Q_Q(QDeclarativeImplicitSizeItem); + emit q->implicitWidthChanged(); +} + +void QDeclarativeImplicitSizeItemPrivate::implicitHeightChanged() +{ + Q_Q(QDeclarativeImplicitSizeItem); + emit q->implicitHeightChanged(); +} + +QDeclarativeImplicitSizeItem::QDeclarativeImplicitSizeItem(QDeclarativeItem *parent) + : QDeclarativeItem(*(new QDeclarativeImplicitSizeItemPrivate), parent) +{ +} + +QDeclarativeImplicitSizeItem::QDeclarativeImplicitSizeItem(QDeclarativeImplicitSizeItemPrivate &dd, QDeclarativeItem *parent) + : QDeclarativeItem(dd, parent) +{ +} + + +void QDeclarativeImplicitSizePaintedItemPrivate::implicitWidthChanged() +{ + Q_Q(QDeclarativeImplicitSizePaintedItem); + emit q->implicitWidthChanged(); +} + +void QDeclarativeImplicitSizePaintedItemPrivate::implicitHeightChanged() +{ + Q_Q(QDeclarativeImplicitSizePaintedItem); + emit q->implicitHeightChanged(); +} + +QDeclarativeImplicitSizePaintedItem::QDeclarativeImplicitSizePaintedItem(QDeclarativeItem *parent) + : QDeclarativePaintedItem(*(new QDeclarativeImplicitSizePaintedItemPrivate), parent) +{ +} + +QDeclarativeImplicitSizePaintedItem::QDeclarativeImplicitSizePaintedItem(QDeclarativeImplicitSizePaintedItemPrivate &dd, QDeclarativeItem *parent) + : QDeclarativePaintedItem(dd, parent) +{ +} + +QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h new file mode 100644 index 0000000..1863d95 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEIMPLICITSIZEITEM_H +#define QDECLARATIVEIMPLICITSIZEITEM_H + +#include "qdeclarativepainteditem_p.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QDeclarativeImplicitSizeItemPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeImplicitSizeItem : public QDeclarativeItem +{ + Q_OBJECT + Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged REVISION 1) + Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged REVISION 1) + +public: + QDeclarativeImplicitSizeItem(QDeclarativeItem *parent = 0); + +protected: + QDeclarativeImplicitSizeItem(QDeclarativeImplicitSizeItemPrivate &dd, QDeclarativeItem *parent); + +Q_SIGNALS: + Q_REVISION(1) void implicitWidthChanged(); + Q_REVISION(1) void implicitHeightChanged(); + +private: + Q_DISABLE_COPY(QDeclarativeImplicitSizeItem) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeImplicitSizeItem) +}; + +class QDeclarativeImplicitSizePaintedItemPrivate; +class Q_AUTOTEST_EXPORT QDeclarativeImplicitSizePaintedItem : public QDeclarativePaintedItem +{ + Q_OBJECT + Q_PROPERTY(qreal implicitWidth READ implicitWidth NOTIFY implicitWidthChanged REVISION 1) + Q_PROPERTY(qreal implicitHeight READ implicitHeight NOTIFY implicitHeightChanged REVISION 1) + +public: + QDeclarativeImplicitSizePaintedItem(QDeclarativeItem *parent = 0); + +protected: + QDeclarativeImplicitSizePaintedItem(QDeclarativeImplicitSizePaintedItemPrivate &dd, QDeclarativeItem *parent); + virtual void drawContents(QPainter *, const QRect &) {}; + +Q_SIGNALS: + Q_REVISION(1) void implicitWidthChanged(); + Q_REVISION(1) void implicitHeightChanged(); + +private: + Q_DISABLE_COPY(QDeclarativeImplicitSizePaintedItem) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeImplicitSizePaintedItem) +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QDECLARATIVEIMPLICITSIZEITEM_H diff --git a/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h new file mode 100644 index 0000000..0bb7163 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativeimplicitsizeitem_p_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEIMPLICITSIZEITEM_P_H +#define QDECLARATIVEIMPLICITSIZEITEM_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativepainteditem_p_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativeImplicitSizeItemPrivate : public QDeclarativeItemPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeImplicitSizeItem) + +public: + QDeclarativeImplicitSizeItemPrivate() + { + } + + virtual void implicitWidthChanged(); + virtual void implicitHeightChanged(); +}; + + +class QDeclarativeImplicitSizePaintedItemPrivate : public QDeclarativePaintedItemPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeImplicitSizePaintedItem) + +public: + QDeclarativeImplicitSizePaintedItemPrivate() + { + } + + virtual void implicitWidthChanged(); + virtual void implicitHeightChanged(); +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEIMPLICITSIZEITEM_P_H diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 2e3a5a2..ffef61b 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -444,6 +444,11 @@ void QDeclarativeItemKeyFilter::componentComplete() \c KeyNavigation.BeforeItem allows the event to be used for key navigation before the item, rather than after. + If item to which the focus is switching is not enabled or visible, an attempt will + be made to skip this item and focus on the next. This is possible if there are + a chain of items with the same KeyNavigation handler. If multiple items in a row are not enabled + or visible, they will also be skipped. + \sa {Keys}{Keys attached property} */ @@ -452,10 +457,12 @@ void QDeclarativeItemKeyFilter::componentComplete() \qmlproperty Item KeyNavigation::right \qmlproperty Item KeyNavigation::up \qmlproperty Item KeyNavigation::down + \qmlproperty Item KeyNavigation::tab + \qmlproperty Item KeyNavigation::backtab These properties hold the item to assign focus to - when the left, right, up or down cursor keys are - pressed. + when the left, right, up or down cursor keys, or the + tab key are pressed. */ /*! @@ -611,37 +618,37 @@ void QDeclarativeKeyNavigationAttached::keyPressed(QKeyEvent *event, bool post) switch(event->key()) { case Qt::Key_Left: if (d->left) { - d->left->setFocus(true); + setFocusNavigation(d->left, "left"); event->accept(); } break; case Qt::Key_Right: if (d->right) { - d->right->setFocus(true); + setFocusNavigation(d->right, "right"); event->accept(); } break; case Qt::Key_Up: if (d->up) { - d->up->setFocus(true); + setFocusNavigation(d->up, "up"); event->accept(); } break; case Qt::Key_Down: if (d->down) { - d->down->setFocus(true); + setFocusNavigation(d->down, "down"); event->accept(); } break; case Qt::Key_Tab: if (d->tab) { - d->tab->setFocus(true); + setFocusNavigation(d->tab, "tab"); event->accept(); } break; case Qt::Key_Backtab: if (d->backtab) { - d->backtab->setFocus(true); + setFocusNavigation(d->backtab, "backtab"); event->accept(); } break; @@ -700,6 +707,29 @@ void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post) if (!event->isAccepted()) QDeclarativeItemKeyFilter::keyReleased(event, post); } +void QDeclarativeKeyNavigationAttached::setFocusNavigation(QDeclarativeItem *currentItem, const char *dir) +{ + QDeclarativeItem *initialItem = currentItem; + bool isNextItem = false; + do { + isNextItem = false; + if (currentItem->isVisible() && currentItem->isEnabled()) { + currentItem->setFocus(true); + } else { + QObject *attached = + qmlAttachedPropertiesObject<QDeclarativeKeyNavigationAttached>(currentItem, false); + if (attached) { + QDeclarativeItem *tempItem = qvariant_cast<QDeclarativeItem*>(attached->property(dir)); + if (tempItem) { + currentItem = tempItem; + isNextItem = true; + } + } + } + } + while (currentItem != initialItem && isNextItem); +} + /*! \qmlclass Keys QDeclarativeKeysAttached \ingroup qml-basic-interaction-elements @@ -799,10 +829,18 @@ void QDeclarativeKeyNavigationAttached::keyReleased(QKeyEvent *event, bool post) This example forwards key events to two lists: \qml - ListView { id: list1 ... } - ListView { id: list2 ... } - Keys.forwardTo: [list1, list2] - focus: true + Item { + ListView { + id: list1 + // ... + } + ListView { + id: list2 + // ... + } + Keys.forwardTo: [list1, list2] + focus: true + } \endqml */ @@ -1881,11 +1919,26 @@ void QDeclarativeItem::setClip(bool c) /*! \qmlproperty bool Item::visible - Whether the item is visible. By default this is true. + This property holds whether the item is visible. By default this is true. + + Setting this property directly affects the \c visible value of child + items. When set to \c false, the \c visible values of all child items also + become \c false. When set to \c true, the \c visible values of child items + are returned to \c true, unless they have explicitly been set to \c false. - \note visible is not linked to actual visibility; if an item - moves off screen, or the opacity changes to 0, this will - not affect the visible property. + (Because of this flow-on behavior, using the \c visible property may not + have the intended effect if a property binding should only respond to + explicit property changes. In such cases it may be better to use the + \l opacity property instead.) + + Setting this property to \c false automatically causes \l focus to be set + to \c false, and this item will longer receive mouse and keyboard events. + (In contrast, setting the \l opacity to 0 does not affect the \l focus + property and the receiving of key events.) + + \note This property's value is only affected by changes to this property or + the parent's \c visible property. It does not change, for example, if this + item moves off-screen, or if the \l opacity changes to 0. */ @@ -2116,13 +2169,18 @@ QDeclarativeAnchorLine QDeclarativeItemPrivate::baseline() const \o \image declarative-anchors_example.png \o Text anchored to Image, horizontally centered and vertically below, with a margin. \qml - Image { id: pic; ... } - Text { - id: label - anchors.horizontalCenter: pic.horizontalCenter - anchors.top: pic.bottom - anchors.topMargin: 5 - ... + Item { + Image { + id: pic + // ... + } + Text { + id: label + anchors.horizontalCenter: pic.horizontalCenter + anchors.top: pic.bottom + anchors.topMargin: 5 + // ... + } } \endqml \row @@ -2132,13 +2190,18 @@ QDeclarativeAnchorLine QDeclarativeItemPrivate::baseline() const property of both defaults to 0. \qml - Image { id: pic; ... } - Text { - id: label - anchors.left: pic.right - anchors.leftMargin: 5 - ... - } + Item { + Image { + id: pic + // ... + } + Text { + id: label + anchors.left: pic.right + anchors.leftMargin: 5 + // ... + } + } \endqml \endtable @@ -2259,13 +2322,15 @@ void QDeclarativeItem::setBaselineOffset(qreal offset) /*! \qmlproperty real Item::opacity - The opacity of the item. Opacity is specified as a number between 0 - (fully transparent) and 1 (fully opaque). The default is 1. + This property holds the opacity of the item. Opacity is specified as a + number between 0 (fully transparent) and 1 (fully opaque). The default is 1. - Opacity is an \e inherited attribute. That is, the opacity is - also applied individually to child items. In almost all cases this - is what you want, but in some cases (like the following example) - it may produce undesired results. + When this property is set, the specified opacity is also applied + individually to child items. In almost all cases this is what you want, + but in some cases it may produce undesired results. For example in the + second set of rectangles below, the red rectangle has specified an opacity + of 0.5, which affects the opacity of its blue child rectangle even though + the child has not specified an opacity. \table \row @@ -2300,6 +2365,12 @@ void QDeclarativeItem::setBaselineOffset(qreal offset) } \endqml \endtable + + If an item's opacity is set to 0, the item will no longer receive mouse + events, but will continue to receive key events and will retain the keyboard + \l focus if it has been set. (In contrast, setting the \l visible property + to \c false stops both mouse and keyboard events, and also removes focus + from the item.) */ /*! @@ -2452,11 +2523,15 @@ QDeclarativeListProperty<QObject> QDeclarativeItemPrivate::resources() \qml Item { - states: [ - State { ... }, - State { ... } - ... - ] + states: [ + State { + // ... + }, + State { + // ... + } + // ... + ] } \endqml @@ -2474,11 +2549,15 @@ QDeclarativeListProperty<QDeclarativeState> QDeclarativeItemPrivate::states() \qml Item { - transitions: [ - Transition { ... }, - Transition { ... } - ... - ] + transitions: [ + Transition { + // ... + }, + Transition { + // ... + } + // ... + ] } \endqml @@ -2503,11 +2582,15 @@ QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeItemPrivate::transi \qml Item { - filter: [ - Blur { ... }, - Reflection { ... } - ... - ] + filter: [ + Blur { + // ... + }, + Reflection { + // ... + } + // ... + ] } \endqml */ @@ -2542,14 +2625,14 @@ QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeItemPrivate::transi This property is often used in scripts to change between states. For example: - \qml - function toggle() { - if (button.state == 'On') - button.state = 'Off'; - else - button.state = 'On'; - } - \endqml + \js + function toggle() { + if (button.state == 'On') + button.state = 'Off'; + else + button.state = 'On'; + } + \endjs If the item is in its base state (i.e. no explicit state has been set), \c state will be a blank string. Likewise, you can return an @@ -3026,13 +3109,24 @@ void QDeclarativeItemPrivate::resetWidth() q->setImplicitWidth(q->implicitWidth()); } +void QDeclarativeItemPrivate::implicitWidthChanged() +{ + Q_Q(QDeclarativeItem); + emit q->implicitWidthChanged(); +} + +qreal QDeclarativeItemPrivate::implicitWidth() const +{ + return mImplicitWidth; +} + /*! Returns the width of the item that is implied by other properties that determine the content. */ qreal QDeclarativeItem::implicitWidth() const { Q_D(const QDeclarativeItem); - return d->implicitWidth; + return d->implicitWidth(); } /*! @@ -3042,9 +3136,13 @@ qreal QDeclarativeItem::implicitWidth() const void QDeclarativeItem::setImplicitWidth(qreal w) { Q_D(QDeclarativeItem); - d->implicitWidth = w; - if (d->mWidth == w || widthValid()) + bool changed = w != d->mImplicitWidth; + d->mImplicitWidth = w; + if (d->mWidth == w || widthValid()) { + if (changed) + d->implicitWidthChanged(); return; + } qreal oldWidth = d->mWidth; @@ -3053,6 +3151,9 @@ void QDeclarativeItem::setImplicitWidth(qreal w) geometryChanged(QRectF(x(), y(), width(), height()), QRectF(x(), y(), oldWidth, height())); + + if (changed) + d->implicitWidthChanged(); } /*! @@ -3134,25 +3235,77 @@ void QDeclarativeItemPrivate::resetHeight() q->setImplicitHeight(q->implicitHeight()); } +void QDeclarativeItemPrivate::implicitHeightChanged() +{ + Q_Q(QDeclarativeItem); + emit q->implicitHeightChanged(); +} + +qreal QDeclarativeItemPrivate::implicitHeight() const +{ + return mImplicitHeight; +} + /*! Returns the height of the item that is implied by other properties that determine the content. */ qreal QDeclarativeItem::implicitHeight() const { Q_D(const QDeclarativeItem); - return d->implicitHeight; + return d->implicitHeight(); } /*! + \qmlproperty real Item::implicitWidth + \qmlproperty real Item::implicitHeight + \since Quick 1.1 + + Defines the natural width or height of the Item if no \l width or \l height is specified. + + The default implicit size for most items is 0x0, however some elements have an inherent + implicit size which cannot be overridden, e.g. Image, Text. + + Setting the implicit size is useful for defining components that have a preferred size + based on their content, for example: + + \code + // Label.qml + import QtQuick 1.1 + + Item { + property alias icon: image.source + property alias label: text.text + implicitWidth: text.implicitWidth + image.implicitWidth + implicitHeight: Math.max(text.implicitHeight, image.implicitHeight) + Image { id: image } + Text { + id: text + wrapMode: Text.Wrap + anchors.left: image.right; anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + } + } + \endcode + + \bold Note: using implicitWidth of Text or TextEdit and setting the width explicitly + incurs a performance penalty as the text must be laid out twice. +*/ + + +/*! Sets the implied height of the item to \a h. This is the height implied by other properties that determine the content. */ void QDeclarativeItem::setImplicitHeight(qreal h) { Q_D(QDeclarativeItem); - d->implicitHeight = h; - if (d->mHeight == h || heightValid()) + bool changed = h != d->mImplicitHeight; + d->mImplicitHeight = h; + if (d->mHeight == h || heightValid()) { + if (changed) + d->implicitHeightChanged(); return; + } qreal oldHeight = d->mHeight; @@ -3161,6 +3314,9 @@ void QDeclarativeItem::setImplicitHeight(qreal h) geometryChanged(QRectF(x(), y(), width(), height()), QRectF(x(), y(), width(), oldHeight)); + + if (changed) + d->implicitHeightChanged(); } /*! diff --git a/src/declarative/graphicsitems/qdeclarativeitem.h b/src/declarative/graphicsitems/qdeclarativeitem.h index 0dd3937..839b934 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.h +++ b/src/declarative/graphicsitems/qdeclarativeitem.h @@ -92,6 +92,9 @@ class Q_DECLARATIVE_EXPORT QDeclarativeItem : public QGraphicsObject, public QDe Q_PROPERTY(TransformOrigin transformOrigin READ transformOrigin WRITE setTransformOrigin NOTIFY transformOriginChanged) Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint) // transformOriginPoint is read-only for Item Q_PROPERTY(bool smooth READ smooth WRITE setSmooth NOTIFY smoothChanged) + Q_PROPERTY(qreal implicitWidth READ implicitWidth WRITE setImplicitWidth NOTIFY implicitWidthChanged REVISION 1) + Q_PROPERTY(qreal implicitHeight READ implicitHeight WRITE setImplicitHeight NOTIFY implicitHeightChanged REVISION 1) + Q_ENUMS(TransformOrigin) Q_CLASSINFO("DefaultProperty", "data") @@ -161,6 +164,8 @@ Q_SIGNALS: void transformOriginChanged(TransformOrigin); void smoothChanged(bool); void clipChanged(bool); + Q_REVISION(1) void implicitWidthChanged(); + Q_REVISION(1) void implicitHeightChanged(); protected: bool isComponentComplete() const; diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h index 781dd6d..4303c0a 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem_p.h +++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h @@ -126,7 +126,7 @@ public: widthValid(false), heightValid(false), componentComplete(true), keepMouse(false), smooth(false), transformOriginDirty(true), doneEventPreHandler(false), keyHandler(0), - mWidth(0), mHeight(0), implicitWidth(0), implicitHeight(0), hadSubFocusItem(false) + mWidth(0), mHeight(0), mImplicitWidth(0), mImplicitHeight(0), hadSubFocusItem(false) { QGraphicsItemPrivate::acceptedMouseButtons = 0; isDeclarativeItem = 1; @@ -157,6 +157,11 @@ public: void setHeight(qreal); void resetHeight(); + virtual qreal implicitWidth() const; + virtual qreal implicitHeight() const; + virtual void implicitWidthChanged(); + virtual void implicitHeightChanged(); + QDeclarativeListProperty<QObject> data(); QDeclarativeListProperty<QObject> resources(); @@ -272,8 +277,8 @@ public: qreal mWidth; qreal mHeight; - qreal implicitWidth; - qreal implicitHeight; + qreal mImplicitWidth; + qreal mImplicitHeight; bool hadSubFocusItem; @@ -415,6 +420,7 @@ Q_SIGNALS: private: virtual void keyPressed(QKeyEvent *event, bool post); virtual void keyReleased(QKeyEvent *event, bool post); + void setFocusNavigation(QDeclarativeItem *currentItem, const char *dir); }; class QDeclarativeKeysAttachedPrivate : public QObjectPrivate diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp index 52703c2..bc4a2d0 100644 --- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp @@ -78,6 +78,7 @@ #include "private/qdeclarativewebview_p_p.h" #endif #include "private/qdeclarativeanchors_p.h" +#include "private/qdeclarativepincharea_p.h" static QDeclarativePrivate::AutoParentResult qgraphicsobject_autoParent(QObject *obj, QObject *parent) { @@ -174,6 +175,29 @@ void QDeclarativeItemModule::defineModule() qmlRegisterUncreatableType<QDeclarativeKeyNavigationAttached>("QtQuick",1,0,"KeyNavigation",QDeclarativeKeyNavigationAttached::tr("KeyNavigation is only available via attached properties")); qmlRegisterUncreatableType<QDeclarativeKeysAttached>("QtQuick",1,0,"Keys",QDeclarativeKeysAttached::tr("Keys is only available via attached properties")); + // QtQuick 1.1 items + qmlRegisterType<QDeclarativePinchArea>("QtQuick",1,1,"PinchArea"); + qmlRegisterType<QDeclarativePinch>("QtQuick",1,1,"Pinch"); + qmlRegisterType<QDeclarativePinchEvent>(); + qmlRegisterType<QDeclarativeItem,1>("QtQuick",1,1,"Item"); + qmlRegisterType<QDeclarativeFlickable,1>("QtQuick",1,1,"Flickable"); + qmlRegisterType<QDeclarativeListView,1>("QtQuick",1,1,"ListView"); + qmlRegisterType<QDeclarativeGridView,1>("QtQuick",1,1,"GridView"); + qmlRegisterType<QDeclarativeRow,1>("QtQuick",1,1,"Row"); + qmlRegisterType<QDeclarativeGrid,1>("QtQuick",1,1,"Grid"); + qmlRegisterType<QDeclarativeFlow,1>("QtQuick",1,1,"Flow"); + qmlRegisterType<QDeclarativeRepeater,1>("QtQuick",1,1,"Repeater"); + qmlRegisterType<QDeclarativeText,1>("QtQuick",1,1,"Text"); + qmlRegisterType<QDeclarativeTextEdit,1>("QtQuick",1,1,"TextEdit"); +#ifndef QT_NO_LINEEDIT + qmlRegisterType<QDeclarativeTextInput,1>("QtQuick",1,1,"TextInput"); +#endif + qmlRegisterRevision<QDeclarativeImageBase,1>("QtQuick",1,1); + qmlRegisterRevision<QDeclarativeImplicitSizeItem,0>("QtQuick",1,0); + qmlRegisterRevision<QDeclarativeImplicitSizeItem,1>("QtQuick",1,1); + qmlRegisterRevision<QDeclarativeImplicitSizePaintedItem,0>("QtQuick",1,0); + qmlRegisterRevision<QDeclarativeImplicitSizePaintedItem,1>("QtQuick",1,1); + #ifndef QT_NO_IMPORT_QT47_QML #ifdef QT_NO_MOVIE qmlRegisterTypeNotAvailable("Qt",4,7,"AnimatedImage", diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index b4b3fa7..a60a4aa 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -413,8 +413,10 @@ public: } } if ((header && header->item == item) || (footer && footer->item == item)) { - updateHeader(); - updateFooter(); + if (header) + updateHeader(); + if (footer) + updateFooter(); } if (currentItem && currentItem->item == item) updateHighlight(); @@ -451,6 +453,7 @@ public: void updateHeader(); void updateFooter(); void fixupPosition(); + void positionViewAtIndex(int index, int mode); virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent); virtual void flick(QDeclarativeFlickablePrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity); @@ -935,6 +938,9 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem) } } listItem->setPosition(pos); + } else { + QDeclarativeContext *context = QDeclarativeEngine::contextForObject(listItem->section)->parentContext(); + context->setContextProperty(QLatin1String("section"), listItem->attached->m_section); } } else if (listItem->section) { qreal pos = listItem->position(); @@ -2231,6 +2237,9 @@ void QDeclarativeListView::setFooter(QDeclarativeComponent *footer) Q_D(QDeclarativeListView); if (d->footerComponent != footer) { if (d->footer) { + if (scene()) + scene()->removeItem(d->footer->item); + d->footer->item->deleteLater(); delete d->footer; d->footer = 0; } @@ -2240,6 +2249,7 @@ void QDeclarativeListView::setFooter(QDeclarativeComponent *footer) if (isComponentComplete()) { d->updateFooter(); d->updateViewport(); + d->fixupPosition(); } emit footerChanged(); } @@ -2265,6 +2275,9 @@ void QDeclarativeListView::setHeader(QDeclarativeComponent *header) Q_D(QDeclarativeListView); if (d->headerComponent != header) { if (d->header) { + if (scene()) + scene()->removeItem(d->header->item); + d->header->item->deleteLater(); delete d->header; d->header = 0; } @@ -2275,6 +2288,7 @@ void QDeclarativeListView::setHeader(QDeclarativeComponent *header) d->updateHeader(); d->updateFooter(); d->updateViewport(); + d->fixupPosition(); } emit headerChanged(); } @@ -2558,6 +2572,78 @@ void QDeclarativeListView::decrementCurrentIndex() } } +void QDeclarativeListViewPrivate::positionViewAtIndex(int index, int mode) +{ + Q_Q(QDeclarativeListView); + if (!isValid()) + return; + if (mode < QDeclarativeListView::Beginning || mode > QDeclarativeListView::Contain) + return; + int idx = qMax(qMin(index, model->count()-1), 0); + + if (layoutScheduled) + layout(); + qreal pos = position(); + FxListItem *item = visibleItem(idx); + qreal maxExtent = orient == QDeclarativeListView::Vertical ? -q->maxYExtent() : -q->maxXExtent(); + if (!item) { + int itemPos = positionAt(idx); + // save the currently visible items in case any of them end up visible again + QList<FxListItem*> oldVisible = visibleItems; + visibleItems.clear(); + visiblePos = itemPos; + visibleIndex = idx; + setPosition(qMin(qreal(itemPos), maxExtent)); + // now release the reference to all the old visible items. + for (int i = 0; i < oldVisible.count(); ++i) + releaseItem(oldVisible.at(i)); + item = visibleItem(idx); + } + if (item) { + const qreal itemPos = item->position(); + switch (mode) { + case QDeclarativeListView::Beginning: + pos = itemPos; + if (index < 0 && header) + pos -= header->size(); + break; + case QDeclarativeListView::Center: + pos = itemPos - (size() - item->size())/2; + break; + case QDeclarativeListView::End: + pos = itemPos - size() + item->size(); + if (index >= model->count() && footer) + pos += footer->size(); + break; + case QDeclarativeListView::Visible: + if (itemPos > pos + size()) + pos = itemPos - size() + item->size(); + else if (item->endPosition() < pos) + pos = itemPos; + break; + case QDeclarativeListView::Contain: + if (item->endPosition() > pos + size()) + pos = itemPos - size() + item->size(); + if (itemPos < pos) + pos = itemPos; + } + pos = qMin(pos, maxExtent); + qreal minExtent = orient == QDeclarativeListView::Vertical ? -q->minYExtent() : -q->minXExtent(); + pos = qMax(pos, minExtent); + moveReason = QDeclarativeListViewPrivate::Other; + q->cancelFlick(); + setPosition(pos); + if (highlight) { + if (autoHighlight) { + highlight->setPosition(currentItem->itemPosition()); + highlight->setSize(currentItem->itemSize()); + } + updateHighlight(); + } + } + fixupPosition(); +} + /*! \qmlmethod ListView::positionViewAtIndex(int index, PositionMode mode) @@ -2596,66 +2682,42 @@ void QDeclarativeListView::positionViewAtIndex(int index, int mode) Q_D(QDeclarativeListView); if (!d->isValid() || index < 0 || index >= d->model->count()) return; - if (mode < Beginning || mode > Contain) + d->positionViewAtIndex(index, mode); +} + +/*! + \qmlmethod ListView::positionViewAtBeginning() + \qmlmethod ListView::positionViewAtEnd() + + Positions the view at the beginning or end, taking into account any header or footer. + + It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view + at a particular index. This is unreliable since removing items from the start + of the list does not cause all other items to be repositioned, and because + the actual start of the view can vary based on the size of the delegates. + + \bold Note: methods should only be called after the Component has completed. To position + the view at startup, this method should be called by Component.onCompleted. For + example, to position the view at the end on startup: + + \code + Component.onCompleted: positionViewAtEnd() + \endcode +*/ +void QDeclarativeListView::positionViewAtBeginning() +{ + Q_D(QDeclarativeListView); + if (!d->isValid()) return; + d->positionViewAtIndex(-1, Beginning); +} - if (d->layoutScheduled) - d->layout(); - qreal pos = d->position(); - FxListItem *item = d->visibleItem(index); - qreal maxExtent = d->orient == QDeclarativeListView::Vertical ? -maxYExtent() : -maxXExtent(); - if (!item) { - int itemPos = d->positionAt(index); - // save the currently visible items in case any of them end up visible again - QList<FxListItem*> oldVisible = d->visibleItems; - d->visibleItems.clear(); - d->visiblePos = itemPos; - d->visibleIndex = index; - d->setPosition(qMin(qreal(itemPos), maxExtent)); - // now release the reference to all the old visible items. - for (int i = 0; i < oldVisible.count(); ++i) - d->releaseItem(oldVisible.at(i)); - item = d->visibleItem(index); - } - if (item) { - const qreal itemPos = item->position(); - switch (mode) { - case Beginning: - pos = itemPos; - break; - case Center: - pos = itemPos - (d->size() - item->size())/2; - break; - case End: - pos = itemPos - d->size() + item->size(); - break; - case Visible: - if (itemPos > pos + d->size()) - pos = itemPos - d->size() + item->size(); - else if (item->endPosition() < pos) - pos = itemPos; - break; - case Contain: - if (item->endPosition() > pos + d->size()) - pos = itemPos - d->size() + item->size(); - if (itemPos < pos) - pos = itemPos; - } - pos = qMin(pos, maxExtent); - qreal minExtent = d->orient == QDeclarativeListView::Vertical ? -minYExtent() : -minXExtent(); - pos = qMax(pos, minExtent); - d->moveReason = QDeclarativeListViewPrivate::Other; - cancelFlick(); - d->setPosition(pos); - if (d->highlight) { - if (d->autoHighlight) { - d->highlight->setPosition(d->currentItem->itemPosition()); - d->highlight->setSize(d->currentItem->itemSize()); - } - d->updateHighlight(); - } - } - d->fixupPosition(); +void QDeclarativeListView::positionViewAtEnd() +{ + Q_D(QDeclarativeListView); + if (!d->isValid()) + return; + d->positionViewAtIndex(d->model->count(), End); } /*! @@ -2791,23 +2853,8 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) return; d->updateUnrequestedIndexes(); d->moveReason = QDeclarativeListViewPrivate::Other; - if (!d->visibleItems.count() || d->model->count() <= 1) { - d->scheduleLayout(); - if (d->itemCount && d->currentIndex >= modelIndex) { - // adjust current item index - d->currentIndex += count; - if (d->currentItem) - d->currentItem->index = d->currentIndex; - emit currentIndexChanged(); - } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { - d->updateCurrent(0); - } - d->itemCount += count; - emit countChanged(); - return; - } - int index = d->mapFromModel(modelIndex); + int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0; if (index < 0) { int i = d->visibleItems.count() - 1; while (i > 0 && d->visibleItems.at(i)->index == -1) @@ -2843,11 +2890,15 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) } } - // At least some of the added items will be visible - // index can be the next item past the end of the visible items list (i.e. appended) - int pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position() + int pos = 0; + if (d->visibleItems.count()) { + pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position() : d->visibleItems.last()->endPosition()+d->spacing+1; + } else if (d->itemCount == 0 && d->header) { + pos = d->header->size(); + } + int initialPos = pos; int diff = 0; QList<FxListItem*> added; @@ -2914,6 +2965,8 @@ void QDeclarativeListView::itemsInserted(int modelIndex, int count) if (d->currentItem) { d->currentItem->index = d->currentIndex; d->currentItem->setPosition(d->currentItem->position() + diff); + } else if (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared)) { + d->updateCurrent(0); } emit currentIndexChanged(); } diff --git a/src/declarative/graphicsitems/qdeclarativelistview_p.h b/src/declarative/graphicsitems/qdeclarativelistview_p.h index 7ffcb43..10fbf10 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview_p.h +++ b/src/declarative/graphicsitems/qdeclarativelistview_p.h @@ -209,6 +209,8 @@ public: Q_INVOKABLE void positionViewAtIndex(int index, int mode); Q_INVOKABLE int indexAt(int x, int y) const; + Q_INVOKABLE Q_REVISION(1) void positionViewAtBeginning(); + Q_INVOKABLE Q_REVISION(1) void positionViewAtEnd(); public Q_SLOTS: void incrementCurrentIndex(); diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index ded2be3..6c1f1be 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -48,7 +48,8 @@ QT_BEGIN_NAMESPACE QDeclarativeLoaderPrivate::QDeclarativeLoaderPrivate() - : item(0), component(0), ownComponent(false) + : item(0), component(0), ownComponent(false), updatingSize(false), + itemWidthValid(false), itemHeightValid(false) { } @@ -58,8 +59,13 @@ QDeclarativeLoaderPrivate::~QDeclarativeLoaderPrivate() void QDeclarativeLoaderPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, const QRectF &newGeometry, const QRectF &oldGeometry) { - if (resizeItem == item) + if (resizeItem == item) { + if (!updatingSize && newGeometry.width() != oldGeometry.width()) + itemWidthValid = true; + if (!updatingSize && newGeometry.height() != oldGeometry.height()) + itemHeightValid = true; _q_updateSize(false); + } QDeclarativeItemChangeListener::itemGeometryChanged(resizeItem, newGeometry, oldGeometry); } @@ -99,6 +105,10 @@ void QDeclarativeLoaderPrivate::initResize() QDeclarativeItemPrivate *p = static_cast<QDeclarativeItemPrivate *>(QGraphicsItemPrivate::get(qmlItem)); p->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); + // We may override the item's size, so we need to remember + // whether the item provided its own valid size. + itemWidthValid = p->widthValid; + itemHeightValid = p->heightValid; } else if (item && item->isWidget()) { QGraphicsWidget *widget = static_cast<QGraphicsWidget*>(item); widget->installEventFilter(q); @@ -216,7 +226,7 @@ void QDeclarativeLoaderPrivate::initResize() */ QDeclarativeLoader::QDeclarativeLoader(QDeclarativeItem *parent) - : QDeclarativeItem(*(new QDeclarativeLoaderPrivate), parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeLoaderPrivate), parent) { Q_D(QDeclarativeLoader); d->flags |= QGraphicsItem::ItemIsFocusScope; @@ -262,6 +272,7 @@ void QDeclarativeLoader::setSource(const QUrl &url) d->clear(); d->source = url; + if (d->source.isEmpty()) { emit sourceChanged(); emit statusChanged(); @@ -272,18 +283,9 @@ void QDeclarativeLoader::setSource(const QUrl &url) d->component = new QDeclarativeComponent(qmlEngine(this), d->source, this); d->ownComponent = true; - if (!d->component->isLoading()) { - d->_q_sourceLoaded(); - } else { - connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), - this, SLOT(_q_sourceLoaded())); - connect(d->component, SIGNAL(progressChanged(qreal)), - this, SIGNAL(progressChanged())); - emit statusChanged(); - emit progressChanged(); - emit sourceChanged(); - emit itemChanged(); - } + + if (isComponentComplete()) + d->load(); } /*! @@ -324,6 +326,7 @@ void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp) d->component = comp; d->ownComponent = false; + if (!d->component) { emit sourceChanged(); emit statusChanged(); @@ -332,18 +335,8 @@ void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp) return; } - if (!d->component->isLoading()) { - d->_q_sourceLoaded(); - } else { - connect(d->component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), - this, SLOT(_q_sourceLoaded())); - connect(d->component, SIGNAL(progressChanged(qreal)), - this, SIGNAL(progressChanged())); - emit progressChanged(); - emit sourceChanged(); - emit statusChanged(); - emit itemChanged(); - } + if (isComponentComplete()) + d->load(); } void QDeclarativeLoader::resetSourceComponent() @@ -351,6 +344,27 @@ void QDeclarativeLoader::resetSourceComponent() setSourceComponent(0); } +void QDeclarativeLoaderPrivate::load() +{ + Q_Q(QDeclarativeLoader); + + if (!q->isComponentComplete() || !component) + return; + + if (!component->isLoading()) { + _q_sourceLoaded(); + } else { + QObject::connect(component, SIGNAL(statusChanged(QDeclarativeComponent::Status)), + q, SLOT(_q_sourceLoaded())); + QObject::connect(component, SIGNAL(progressChanged(qreal)), + q, SIGNAL(progressChanged())); + emit q->statusChanged(); + emit q->progressChanged(); + emit q->sourceChanged(); + emit q->itemChanged(); + } +} + void QDeclarativeLoaderPrivate::_q_sourceLoaded() { Q_Q(QDeclarativeLoader); @@ -465,9 +479,10 @@ QDeclarativeLoader::Status QDeclarativeLoader::status() const void QDeclarativeLoader::componentComplete() { + Q_D(QDeclarativeLoader); + QDeclarativeItem::componentComplete(); - if (status() == Ready) - emit loaded(); + d->load(); } @@ -504,13 +519,21 @@ qreal QDeclarativeLoader::progress() const void QDeclarativeLoaderPrivate::_q_updateSize(bool loaderGeometryChanged) { Q_Q(QDeclarativeLoader); - if (!item) + if (!item || updatingSize) return; + + updatingSize = true; if (QDeclarativeItem *qmlItem = qobject_cast<QDeclarativeItem*>(item)) { - q->setImplicitWidth(qmlItem->width()); + if (!itemWidthValid) + q->setImplicitWidth(qmlItem->implicitWidth()); + else + q->setImplicitWidth(qmlItem->width()); if (loaderGeometryChanged && q->widthValid()) qmlItem->setWidth(q->width()); - q->setImplicitHeight(qmlItem->height()); + if (!itemHeightValid) + q->setImplicitHeight(qmlItem->implicitHeight()); + else + q->setImplicitHeight(qmlItem->height()); if (loaderGeometryChanged && q->heightValid()) qmlItem->setHeight(q->height()); } else if (item && item->isWidget()) { @@ -525,6 +548,7 @@ void QDeclarativeLoaderPrivate::_q_updateSize(bool loaderGeometryChanged) if (widget->size() != widgetSize) widget->resize(widgetSize); } + updatingSize = false; } /*! diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p.h index 1fe7ae7..96b883c 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p.h @@ -42,7 +42,7 @@ #ifndef QDECLARATIVELOADER_H #define QDECLARATIVELOADER_H -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" QT_BEGIN_HEADER @@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeLoaderPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeLoader : public QDeclarativeItem +class Q_AUTOTEST_EXPORT QDeclarativeLoader : public QDeclarativeImplicitSizeItem { Q_OBJECT Q_ENUMS(Status) diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h index 45ab595..4593dfc 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h @@ -55,13 +55,13 @@ #include "private/qdeclarativeloader_p.h" -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include "private/qdeclarativeitemchangelistener_p.h" QT_BEGIN_NAMESPACE class QDeclarativeContext; -class QDeclarativeLoaderPrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener +class QDeclarativeLoaderPrivate : public QDeclarativeImplicitSizeItemPrivate, public QDeclarativeItemChangeListener { Q_DECLARE_PUBLIC(QDeclarativeLoader) @@ -72,11 +72,15 @@ public: void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); void clear(); void initResize(); + void load(); QUrl source; QGraphicsObject *item; QDeclarativeComponent *component; bool ownComponent : 1; + bool updatingSize: 1; + bool itemWidthValid : 1; + bool itemHeightValid : 1; void _q_sourceLoaded(); void _q_updateSize(bool loaderGeometryChanged = true); diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp index 4b555d0..5b73a29 100644 --- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp +++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp @@ -216,9 +216,9 @@ QDeclarativeMouseAreaPrivate::~QDeclarativeMouseAreaPrivate() \section1 Example Usage - \beginfloatright + \div {float-right} \inlineimage qml-mousearea-snippet.png - \endfloat + \enddiv The following example uses a MouseArea in a \l Rectangle that changes the \l Rectangle color to red when clicked: @@ -314,6 +314,8 @@ QDeclarativeMouseAreaPrivate::~QDeclarativeMouseAreaPrivate() position of the release of the click, and whether the click was held. The \e accepted property of the MouseEvent parameter is ignored in this handler. + + \sa onCanceled() */ /*! @@ -583,18 +585,22 @@ void QDeclarativeMouseArea::hoverEnterEvent(QGraphicsSceneHoverEvent *event) Q_D(QDeclarativeMouseArea); if (!d->absorb) QDeclarativeItem::hoverEnterEvent(event); - else + else { + d->lastPos = event->pos(); setHovered(true); + QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers(), false, false); + emit mousePositionChanged(&me); + } } void QDeclarativeMouseArea::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { Q_D(QDeclarativeMouseArea); if (!d->absorb) { - QDeclarativeItem::hoverEnterEvent(event); + QDeclarativeItem::hoverMoveEvent(event); } else { d->lastPos = event->pos(); - QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, d->lastButtons, d->lastModifiers, false, d->longPress); + QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, event->modifiers(), false, false); emit mousePositionChanged(&me); me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); @@ -859,15 +865,16 @@ bool QDeclarativeMouseArea::setPressed(bool p) me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); emit mousePositionChanged(&me); + emit pressedChanged(); } else { emit released(&me); me.setX(d->lastPos.x()); me.setY(d->lastPos.y()); + emit pressedChanged(); if (isclick && !d->longPress && !d->doubleClick) emit clicked(&me); } - emit pressedChanged(); return me.isAccepted(); } return false; diff --git a/src/declarative/graphicsitems/qdeclarativepath.cpp b/src/declarative/graphicsitems/qdeclarativepath.cpp index bc395d2..48e3f66 100644 --- a/src/declarative/graphicsitems/qdeclarativepath.cpp +++ b/src/declarative/graphicsitems/qdeclarativepath.cpp @@ -845,7 +845,7 @@ void QDeclarativePathCubic::addToPath(QPainterPath &path) \o \qml PathView { - ... + // ... Path { startX: 20; startY: 0 PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 } @@ -859,7 +859,7 @@ void QDeclarativePathCubic::addToPath(QPainterPath &path) \o \qml PathView { - ... + // ... Path { startX: 20; startY: 0 PathQuad { x: 50; y: 80; controlX: 0; controlY: 80 } @@ -892,7 +892,7 @@ void QDeclarativePathCubic::addToPath(QPainterPath &path) \qml PathView { - ... + // ... Path { startX: 0; startY: 0 PathLine { x:100; y: 0; } diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp index 64656af..4e401e9 100644 --- a/src/declarative/graphicsitems/qdeclarativepathview.cpp +++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp @@ -379,14 +379,14 @@ void QDeclarativePathViewPrivate::regenerate() \l decrementCurrentIndex() or \l incrementCurrentIndex(), for example to navigate using the left and right arrow keys: - \code + \qml PathView { - ... + // ... focus: true Keys.onLeftPressed: decrementCurrentIndex() Keys.onRightPressed: incrementCurrentIndex() } - \endcode + \endqml The path view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details). @@ -444,7 +444,7 @@ QDeclarativePathView::~QDeclarativePathView() Component { Rectangle { visible: PathView.onPath - ... + // ... } } \endqml @@ -706,14 +706,14 @@ void QDeclarativePathViewPrivate::setAdjustedOffset(qreal o) of the \l{PathView::onPath}{PathView.onPath} attached property to ensure that the highlight is hidden when flicked away from the path. - \code + \qml Component { Rectangle { visible: PathView.onPath - ... + // ... } } - \endcode + \endqml \sa highlightItem, highlightRangeMode */ @@ -1152,7 +1152,7 @@ void QDeclarativePathViewPrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent moveReason = QDeclarativePathViewPrivate::Mouse; qreal diff = (newPc - startPc)*modelCount*mappedRange; if (diff) { - setOffset(offset + diff); + q->setOffset(offset + diff); if (diff > modelCount/2) diff -= modelCount; @@ -1455,17 +1455,18 @@ void QDeclarativePathView::itemsInserted(int modelIndex, int count) if (!d->isValid() || !isComponentComplete()) return; - d->itemCache += d->items; - d->items.clear(); - if (modelIndex <= d->currentIndex) { - d->currentIndex += count; - emit currentIndexChanged(); - } else if (d->offset != 0) { - d->offset += count; - d->offsetAdj += count; + if (d->modelCount) { + d->itemCache += d->items; + d->items.clear(); + if (modelIndex <= d->currentIndex) { + d->currentIndex += count; + emit currentIndexChanged(); + } else if (d->offset != 0) { + d->offset += count; + d->offsetAdj += count; + } } - - d->modelCount = d->model->count(); + d->modelCount += count; if (d->flicking || d->moving) { d->regenerate(); d->updateCurrent(); @@ -1502,18 +1503,29 @@ void QDeclarativePathView::itemsRemoved(int modelIndex, int count) d->itemCache += d->items; d->items.clear(); + bool changedOffset = false; if (modelIndex > d->currentIndex) { if (d->offset >= count) { + changedOffset = true; d->offset -= count; d->offsetAdj -= count; } } - d->modelCount = d->model->count(); - d->regenerate(); - d->updateCurrent(); - if (!d->modelCount) + d->modelCount -= count; + if (!d->modelCount) { + while (d->itemCache.count()) + d->releaseItem(d->itemCache.takeLast()); + d->offset = 0; + changedOffset = true; + d->tl.reset(d->moveOffset); update(); + } else { + d->regenerate(); + d->updateCurrent(); + } + if (changedOffset) + emit offsetChanged(); if (currentChanged) emit currentIndexChanged(); emit countChanged(); @@ -1601,7 +1613,7 @@ void QDeclarativePathView::movementEnding() int QDeclarativePathViewPrivate::calcCurrentIndex() { int current = -1; - if (model && items.count()) { + if (modelCount && model && items.count()) { offset = qmlMod(offset, modelCount); if (offset < 0) offset += modelCount; @@ -1617,7 +1629,7 @@ void QDeclarativePathViewPrivate::updateCurrent() Q_Q(QDeclarativePathView); if (moveReason != Mouse) return; - if (!haveHighlightRange || highlightRangeMode != QDeclarativePathView::StrictlyEnforceRange) + if (!modelCount || !haveHighlightRange || highlightRangeMode != QDeclarativePathView::StrictlyEnforceRange) return; int idx = calcCurrentIndex(); diff --git a/src/declarative/graphicsitems/qdeclarativepincharea.cpp b/src/declarative/graphicsitems/qdeclarativepincharea.cpp new file mode 100644 index 0000000..eae83f6 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativepincharea.cpp @@ -0,0 +1,582 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativepincharea_p.h" +#include "qdeclarativepincharea_p_p.h" + +#include <QApplication> +#include <QGraphicsScene> + +#include <float.h> +#include <math.h> + +QT_BEGIN_NAMESPACE + + +/*! + \qmlclass PinchEvent QDeclarativePinchEvent + \ingroup qml-event-elements + \brief The PinchEvent object provides information about a pinch event. + + \bold {The PinchEvent element was added in QtQuick 1.1} + + The \c center, \c startCenter, \c previousCenter properties provide the center position between the two touch points. + + The \c scale and \c previousScale properties provide the scale factor. + + The \c angle, \c previousAngle and \c rotation properties provide the angle between the two points and the amount of rotation. + + The \c point1, \c point2, \c startPoint1, \c startPoint2 properties provide the positions of the touch points. + + The \c accepted property may be set to false in the \c onPinchStarted handler if the gesture should not + be handled. + + \sa PinchArea +*/ + +/*! + \qmlproperty QPointF PinchEvent::center + \qmlproperty QPointF PinchEvent::startCenter + \qmlproperty QPointF PinchEvent::previousCenter + + These properties hold the position of the center point between the two touch points. + + \list + \o \c center is the current center point + \o \c previousCenter is the center point of the previous event. + \o \c startCenter is the center point when the gesture began + \endlist +*/ + +/*! + \qmlproperty real PinchEvent::scale + \qmlproperty real PinchEvent::previousScale + + These properties hold the scale factor determined by the change in distance between the two touch points. + + \list + \o \c scale is the current scale factor. + \o \c previousScale is the scale factor of the previous event. + \endlist + + When a pinch gesture is started, the scale is 1.0. +*/ + +/*! + \qmlproperty real PinchEvent::angle + \qmlproperty real PinchEvent::previousAngle + \qmlproperty real PinchEvent::rotation + + These properties hold the angle between the two touch points. + + \list + \o \c angle is the current angle between the two points in the range -180 to 180. + \o \c previousAngle is the angle of the previous event. + \o \c rotation is the total rotation since the pinch gesture started. + \endlist + + When a pinch gesture is started, the rotation is 0.0. +*/ + +/*! + \qmlproperty QPointF PinchEvent::point1 + \qmlproperty QPointF PinchEvent::startPoint1 + \qmlproperty QPointF PinchEvent::point2 + \qmlproperty QPointF PinchEvent::startPoint2 + + These properties provide the actual touch points generating the pinch. + + \list + \o \c point1 and \c point2 hold the current positions of the points. + \o \c startPoint1 and \c startPoint2 hold the positions of the points when the second point was touched. + \endlist +*/ + +/*! + \qmlproperty bool PinchEvent::accepted + + Setting this property to false in the \c PinchArea::onPinchStarted handler + will result in no further pinch events being generated, and the gesture + ignored. +*/ + +QDeclarativePinch::QDeclarativePinch() + : m_target(0), m_minScale(1.0), m_maxScale(1.0) + , m_minRotation(0.0), m_maxRotation(0.0) + , m_axis(NoDrag), m_xmin(-FLT_MAX), m_xmax(FLT_MAX) + , m_ymin(-FLT_MAX), m_ymax(FLT_MAX), m_active(false) +{ +} + +QDeclarativePinchAreaPrivate::~QDeclarativePinchAreaPrivate() +{ + delete pinch; +} + +/*! + \qmlclass PinchArea QDeclarativePinchArea + \brief The PinchArea item enables simple pinch gesture handling. + \inherits Item + + \bold {The PinchArea element was added in QtQuick 1.1} + + A PinchArea is an invisible item that is typically used in conjunction with + a visible item in order to provide pinch gesture handling for that item. + + The \l enabled property is used to enable and disable pinch handling for + the proxied item. When disabled, the pinch area becomes transparent to + mouse/touch events. + + PinchArea can be used in two ways: + + \list + \o setting a \c pinch.target to provide automatic interaction with an element + \o using the onPinchStarted, onPinchUpdated and onPinchFinished handlers + \endlist + + \sa PinchEvent +*/ + +/*! + \qmlsignal PinchArea::onPinchStarted() + + This handler is called when the pinch area detects that a pinch gesture has started. + + The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture, + including the scale, center and angle of the pinch. + + To ignore this gesture set the \c pinch.accepted property to false. The gesture + will be cancelled and no further events will be sent. +*/ + +/*! + \qmlsignal PinchArea::onPinchUpdated() + + This handler is called when the pinch area detects that a pinch gesture has changed. + + The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture, + including the scale, center and angle of the pinch. +*/ + +/*! + \qmlsignal PinchArea::onPinchFinished() + + This handler is called when the pinch area detects that a pinch gesture has finished. + + The \l {PinchEvent}{pinch} parameter provides information about the pinch gesture, + including the scale, center and angle of the pinch. +*/ + + +/*! + \qmlproperty Item PinchArea::pinch.target + \qmlproperty bool PinchArea::pinch.active + \qmlproperty real PinchArea::pinch.minimumScale + \qmlproperty real PinchArea::pinch.maximumScale + \qmlproperty real PinchArea::pinch.minimumRotation + \qmlproperty real PinchArea::pinch.maximumRotation + \qmlproperty enumeration PinchArea::pinch.dragAxis + \qmlproperty real PinchArea::pinch.minimumX + \qmlproperty real PinchArea::pinch.maximumX + \qmlproperty real PinchArea::pinch.minimumY + \qmlproperty real PinchArea::pinch.maximumY + + \c pinch provides a convenient way to make an item react to pinch gestures. + + \list + \i \c pinch.target specifies the id of the item to drag. + \i \c pinch.active specifies if the target item is currently being dragged. + \i \c pinch.minimumScale and \c pinch.maximumScale limit the range of the Item::scale property. + \i \c pinch.minimumRotation and \c pinch.maximumRotation limit the range of the Item::rotation property. + \i \c pinch.dragAxis specifies whether dragging in not allowed (\c Pinch.NoDrag), can be done horizontally (\c Pinch.XAxis), vertically (\c Pinch.YAxis), or both (\c Pinch.XandYAxis) + \i \c pinch.minimum and \c pinch.maximum limit how far the target can be dragged along the corresponding axes. + \endlist +*/ + +QDeclarativePinchArea::QDeclarativePinchArea(QDeclarativeItem *parent) + : QDeclarativeItem(*(new QDeclarativePinchAreaPrivate), parent) +{ + Q_D(QDeclarativePinchArea); + d->init(); +} + +QDeclarativePinchArea::~QDeclarativePinchArea() +{ +} + +/*! + \qmlproperty bool PinchArea::enabled + This property holds whether the item accepts pinch gestures. + + This property defaults to true. +*/ +bool QDeclarativePinchArea::isEnabled() const +{ + Q_D(const QDeclarativePinchArea); + return d->absorb; +} + +void QDeclarativePinchArea::setEnabled(bool a) +{ + Q_D(QDeclarativePinchArea); + if (a != d->absorb) { + d->absorb = a; + emit enabledChanged(); + } +} + +bool QDeclarativePinchArea::event(QEvent *event) +{ + Q_D(QDeclarativePinchArea); + if (!d->absorb || !isVisible()) + return QDeclarativeItem::event(event); + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: { + QTouchEvent *touch = static_cast<QTouchEvent*>(event); + d->touchPoints.clear(); + for (int i = 0; i < touch->touchPoints().count(); ++i) { + if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) { + d->touchPoints << touch->touchPoints().at(i); + } + } + updatePinch(); + } + return true; + case QEvent::TouchEnd: + d->touchPoints.clear(); + updatePinch(); + break; + default: + return QDeclarativeItem::event(event); + } + + return QDeclarativeItem::event(event); +} + +void QDeclarativePinchArea::updatePinch() +{ + Q_D(QDeclarativePinchArea); + if (d->touchPoints.count() != 2) { + if (d->inPinch) { + d->stealMouse = false; + setKeepMouseGrab(false); + d->inPinch = false; + const qreal rotationAngle = d->pinchStartAngle - d->pinchLastAngle; + QPointF pinchCenter = mapFromScene(d->sceneLastCenter); + QDeclarativePinchEvent pe(pinchCenter, d->pinchLastScale, d->pinchLastAngle, rotationAngle); + pe.setStartCenter(d->pinchStartCenter); + pe.setPreviousCenter(pinchCenter); + pe.setPreviousAngle(d->pinchLastAngle); + pe.setPreviousScale(d->pinchLastScale); + pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); + pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); + pe.setPoint1(d->lastPoint1); + pe.setPoint2(d->lastPoint2); + emit pinchFinished(&pe); + d->pinchStartDist = 0; + if (d->pinch && d->pinch->target()) + d->pinch->setActive(false); + } + return; + } + if (d->touchPoints.at(0).state() & Qt::TouchPointPressed + || d->touchPoints.at(1).state() & Qt::TouchPointPressed) { + d->sceneStartPoint1 = d->touchPoints.at(0).scenePos(); + d->sceneStartPoint2 = d->touchPoints.at(1).scenePos(); + d->inPinch = false; + d->pinchRejected = false; + } else if (!d->pinchRejected){ + QDeclarativeItem *grabber = scene() ? qobject_cast<QDeclarativeItem*>(scene()->mouseGrabberItem()) : 0; + if (grabber == this || !grabber || !grabber->keepMouseGrab()) { + const int dragThreshold = QApplication::startDragDistance(); + QPointF p1 = d->touchPoints.at(0).scenePos(); + QPointF p2 = d->touchPoints.at(1).scenePos(); + qreal dx = p1.x() - p2.x(); + qreal dy = p1.y() - p2.y(); + qreal dist = sqrt(dx*dx + dy*dy); + QPointF sceneCenter = (p1 + p2)/2; + qreal angle = QLineF(p1, p2).angle(); + if (angle > 180) + angle -= 360; + if (!d->inPinch) { + if (qAbs(p1.x()-d->sceneStartPoint1.x()) > dragThreshold + || qAbs(p1.y()-d->sceneStartPoint1.y()) > dragThreshold + || qAbs(p2.x()-d->sceneStartPoint2.x()) > dragThreshold + || qAbs(p2.y()-d->sceneStartPoint2.y()) > dragThreshold) { + d->sceneStartCenter = sceneCenter; + d->sceneLastCenter = sceneCenter; + d->pinchStartCenter = mapFromScene(sceneCenter); + d->pinchStartDist = dist; + d->pinchStartAngle = angle; + d->pinchLastScale = 1.0; + d->pinchLastAngle = angle; + d->lastPoint1 = d->touchPoints.at(0).pos(); + d->lastPoint2 = d->touchPoints.at(1).pos(); + QDeclarativePinchEvent pe(d->pinchStartCenter, 1.0, angle, 0.0); + pe.setStartCenter(d->pinchStartCenter); + pe.setPreviousCenter(d->pinchStartCenter); + pe.setPreviousAngle(d->pinchLastAngle); + pe.setPreviousScale(d->pinchLastScale); + pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); + pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); + pe.setPoint1(d->lastPoint1); + pe.setPoint2(d->lastPoint2); + emit pinchStarted(&pe); + if (pe.accepted()) { + d->inPinch = true; + d->stealMouse = true; + QGraphicsScene *s = scene(); + if (s && s->mouseGrabberItem() != this) + grabMouse(); + setKeepMouseGrab(true); + if (d->pinch && d->pinch->target()) { + d->pinchStartPos = pinch()->target()->pos(); + d->pinchStartScale = d->pinch->target()->scale(); + d->pinchStartRotation = d->pinch->target()->rotation(); + d->pinch->setActive(true); + } + } else { + d->pinchRejected = true; + } + } + } else if (d->pinchStartDist > 0) { + qreal scale = dist / d->pinchStartDist; + qreal rotationAngle = d->pinchStartAngle - angle; + if (rotationAngle > 180) + rotationAngle -= 360; + QPointF pinchCenter = mapFromScene(sceneCenter); + QDeclarativePinchEvent pe(pinchCenter, scale, angle, rotationAngle); + pe.setStartCenter(d->pinchStartCenter); + pe.setPreviousCenter(mapFromScene(d->sceneLastCenter)); + pe.setPreviousAngle(d->pinchLastAngle); + pe.setPreviousScale(d->pinchLastScale); + pe.setStartPoint1(mapFromScene(d->sceneStartPoint1)); + pe.setStartPoint2(mapFromScene(d->sceneStartPoint2)); + pe.setPoint1(d->touchPoints.at(0).pos()); + pe.setPoint2(d->touchPoints.at(1).pos()); + d->pinchLastScale = scale; + d->sceneLastCenter = sceneCenter; + d->pinchLastAngle = angle; + d->lastPoint1 = d->touchPoints.at(0).pos(); + d->lastPoint2 = d->touchPoints.at(1).pos(); + emit pinchUpdated(&pe); + if (d->pinch && d->pinch->target()) { + qreal s = d->pinchStartScale * scale; + s = qMin(qMax(pinch()->minimumScale(),s), pinch()->maximumScale()); + pinch()->target()->setScale(s); + QPointF pos = sceneCenter - d->sceneStartCenter + d->pinchStartPos; + if (pinch()->axis() & QDeclarativePinch::XAxis) { + qreal x = pos.x(); + if (x < pinch()->xmin()) + x = pinch()->xmin(); + else if (x > pinch()->xmax()) + x = pinch()->xmax(); + pinch()->target()->setX(x); + } + if (pinch()->axis() & QDeclarativePinch::YAxis) { + qreal y = pos.y(); + if (y < pinch()->ymin()) + y = pinch()->ymin(); + else if (y > pinch()->ymax()) + y = pinch()->ymax(); + pinch()->target()->setY(y); + } + if (d->pinchStartRotation >= pinch()->minimumRotation() + && d->pinchStartRotation <= pinch()->maximumRotation()) { + qreal r = rotationAngle + d->pinchStartRotation; + r = qMin(qMax(pinch()->minimumRotation(),r), pinch()->maximumRotation()); + pinch()->target()->setRotation(r); + } + } + } + } + } +} + +void QDeclarativePinchArea::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + d->stealMouse = false; + if (!d->absorb) + QDeclarativeItem::mousePressEvent(event); + else { + setKeepMouseGrab(false); + event->setAccepted(true); + } +} + +void QDeclarativePinchArea::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + if (!d->absorb) { + QDeclarativeItem::mouseMoveEvent(event); + return; + } +} + +void QDeclarativePinchArea::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + d->stealMouse = false; + if (!d->absorb) { + QDeclarativeItem::mouseReleaseEvent(event); + } else { + QGraphicsScene *s = scene(); + if (s && s->mouseGrabberItem() == this) + ungrabMouse(); + setKeepMouseGrab(false); + } +} + +bool QDeclarativePinchArea::sceneEvent(QEvent *event) +{ + bool rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + setKeepMouseGrab(false); + } + return rv; +} + +bool QDeclarativePinchArea::sendMouseEvent(QGraphicsSceneMouseEvent *event) +{ + Q_D(QDeclarativePinchArea); + QGraphicsSceneMouseEvent mouseEvent(event->type()); + QRectF myRect = mapToScene(QRectF(0, 0, width(), height())).boundingRect(); + + QGraphicsScene *s = scene(); + QDeclarativeItem *grabber = s ? qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()) : 0; + bool stealThisEvent = d->stealMouse; + if ((stealThisEvent || myRect.contains(event->scenePos().toPoint())) && (!grabber || !grabber->keepMouseGrab())) { + mouseEvent.setAccepted(false); + for (int i = 0x1; i <= 0x10; i <<= 1) { + if (event->buttons() & i) { + Qt::MouseButton button = Qt::MouseButton(i); + mouseEvent.setButtonDownPos(button, mapFromScene(event->buttonDownPos(button))); + } + } + mouseEvent.setScenePos(event->scenePos()); + mouseEvent.setLastScenePos(event->lastScenePos()); + mouseEvent.setPos(mapFromScene(event->scenePos())); + mouseEvent.setLastPos(mapFromScene(event->lastScenePos())); + + switch(mouseEvent.type()) { + case QEvent::GraphicsSceneMouseMove: + mouseMoveEvent(&mouseEvent); + break; + case QEvent::GraphicsSceneMousePress: + mousePressEvent(&mouseEvent); + break; + case QEvent::GraphicsSceneMouseRelease: + mouseReleaseEvent(&mouseEvent); + break; + default: + break; + } + grabber = qobject_cast<QDeclarativeItem*>(s->mouseGrabberItem()); + if (grabber && stealThisEvent && !grabber->keepMouseGrab() && grabber != this) + grabMouse(); + + return stealThisEvent; + } + if (mouseEvent.type() == QEvent::GraphicsSceneMouseRelease) { + d->stealMouse = false; + if (s && s->mouseGrabberItem() == this) + ungrabMouse(); + setKeepMouseGrab(false); + } + return false; +} + +bool QDeclarativePinchArea::sceneEventFilter(QGraphicsItem *i, QEvent *e) +{ + Q_D(QDeclarativePinchArea); + if (!d->absorb || !isVisible()) + return QDeclarativeItem::sceneEventFilter(i, e); + switch (e->type()) { + case QEvent::GraphicsSceneMousePress: + case QEvent::GraphicsSceneMouseMove: + case QEvent::GraphicsSceneMouseRelease: + return sendMouseEvent(static_cast<QGraphicsSceneMouseEvent *>(e)); + break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: { + QTouchEvent *touch = static_cast<QTouchEvent*>(e); + d->touchPoints.clear(); + for (int i = 0; i < touch->touchPoints().count(); ++i) + if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) + d->touchPoints << touch->touchPoints().at(i); + updatePinch(); + } + return d->inPinch; + case QEvent::TouchEnd: + d->touchPoints.clear(); + updatePinch(); + break; + default: + break; + } + + return QDeclarativeItem::sceneEventFilter(i, e); +} + +void QDeclarativePinchArea::geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) +{ + QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); +} + +QVariant QDeclarativePinchArea::itemChange(GraphicsItemChange change, + const QVariant &value) +{ + return QDeclarativeItem::itemChange(change, value); +} + +QDeclarativePinch *QDeclarativePinchArea::pinch() +{ + Q_D(QDeclarativePinchArea); + if (!d->pinch) + d->pinch = new QDeclarativePinch; + return d->pinch; +} + + +QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p.h new file mode 100644 index 0000000..6d04708 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p.h @@ -0,0 +1,308 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPINCHAREA_H +#define QDECLARATIVEPINCHAREA_H + +#include <qdeclarativeitem.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class Q_AUTOTEST_EXPORT QDeclarativePinch : public QObject +{ + Q_OBJECT + + Q_ENUMS(Axis) + Q_PROPERTY(QGraphicsObject *target READ target WRITE setTarget RESET resetTarget) + Q_PROPERTY(qreal minimumScale READ minimumScale WRITE setMinimumScale NOTIFY minimumScaleChanged) + Q_PROPERTY(qreal maximumScale READ maximumScale WRITE setMaximumScale NOTIFY maximumScaleChanged) + Q_PROPERTY(qreal minimumRotation READ minimumRotation WRITE setMinimumRotation NOTIFY minimumRotationChanged) + Q_PROPERTY(qreal maximumRotation READ maximumRotation WRITE setMaximumRotation NOTIFY maximumRotationChanged) + Q_PROPERTY(Axis dragAxis READ axis WRITE setAxis NOTIFY dragAxisChanged) + Q_PROPERTY(qreal minimumX READ xmin WRITE setXmin NOTIFY minimumXChanged) + Q_PROPERTY(qreal maximumX READ xmax WRITE setXmax NOTIFY maximumXChanged) + Q_PROPERTY(qreal minimumY READ ymin WRITE setYmin NOTIFY minimumYChanged) + Q_PROPERTY(qreal maximumY READ ymax WRITE setYmax NOTIFY maximumYChanged) + Q_PROPERTY(bool active READ active NOTIFY activeChanged) + +public: + QDeclarativePinch(); + + QGraphicsObject *target() const { return m_target; } + void setTarget(QGraphicsObject *target) { + if (target == m_target) + return; + m_target = target; + emit targetChanged(); + } + void resetTarget() { + if (!m_target) + return; + m_target = 0; + emit targetChanged(); + } + + qreal minimumScale() const { return m_minScale; } + void setMinimumScale(qreal s) { + if (s == m_minScale) + return; + m_minScale = s; + emit minimumScaleChanged(); + } + qreal maximumScale() const { return m_maxScale; } + void setMaximumScale(qreal s) { + if (s == m_maxScale) + return; + m_maxScale = s; + emit maximumScaleChanged(); + } + + qreal minimumRotation() const { return m_minRotation; } + void setMinimumRotation(qreal r) { + if (r == m_minRotation) + return; + m_minRotation = r; + emit minimumRotationChanged(); + } + qreal maximumRotation() const { return m_maxRotation; } + void setMaximumRotation(qreal r) { + if (r == m_maxRotation) + return; + m_maxRotation = r; + emit maximumRotationChanged(); + } + + enum Axis { NoDrag=0x00, XAxis=0x01, YAxis=0x02, XandYAxis=0x03 }; + Axis axis() const { return m_axis; } + void setAxis(Axis a) { + if (a == m_axis) + return; + m_axis = a; + emit dragAxisChanged(); + } + + qreal xmin() const { return m_xmin; } + void setXmin(qreal x) { + if (x == m_xmin) + return; + m_xmin = x; + emit minimumXChanged(); + } + qreal xmax() const { return m_xmax; } + void setXmax(qreal x) { + if (x == m_xmax) + return; + m_xmax = x; + emit maximumXChanged(); + } + qreal ymin() const { return m_ymin; } + void setYmin(qreal y) { + if (y == m_ymin) + return; + m_ymin = y; + emit minimumYChanged(); + } + qreal ymax() const { return m_ymax; } + void setYmax(qreal y) { + if (y == m_ymax) + return; + m_ymax = y; + emit maximumYChanged(); + } + + bool active() const { return m_active; } + void setActive(bool a) { + if (a == m_active) + return; + m_active = a; + emit activeChanged(); + } + +signals: + void targetChanged(); + void minimumScaleChanged(); + void maximumScaleChanged(); + void minimumRotationChanged(); + void maximumRotationChanged(); + void dragAxisChanged(); + void minimumXChanged(); + void maximumXChanged(); + void minimumYChanged(); + void maximumYChanged(); + void activeChanged(); + +private: + QGraphicsObject *m_target; + qreal m_minScale; + qreal m_maxScale; + qreal m_minRotation; + qreal m_maxRotation; + Axis m_axis; + qreal m_xmin; + qreal m_xmax; + qreal m_ymin; + qreal m_ymax; + bool m_active; +}; + +class Q_AUTOTEST_EXPORT QDeclarativePinchEvent : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QPointF center READ center) + Q_PROPERTY(QPointF startCenter READ startCenter) + Q_PROPERTY(QPointF previousCenter READ previousCenter) + Q_PROPERTY(qreal scale READ scale) + Q_PROPERTY(qreal previousScale READ previousScale) + Q_PROPERTY(qreal angle READ angle) + Q_PROPERTY(qreal previousAngle READ previousAngle) + Q_PROPERTY(qreal rotation READ rotation) + Q_PROPERTY(QPointF point1 READ point1) + Q_PROPERTY(QPointF startPoint1 READ startPoint1) + Q_PROPERTY(QPointF point2 READ point2) + Q_PROPERTY(QPointF startPoint2 READ startPoint2) + Q_PROPERTY(bool accepted READ accepted WRITE setAccepted) + +public: + QDeclarativePinchEvent(QPointF c, qreal s, qreal a, qreal r) + : QObject(), m_center(c), m_scale(s), m_angle(a), m_rotation(r), m_accepted(true) {} + + QPointF center() const { return m_center; } + QPointF startCenter() const { return m_startCenter; } + void setStartCenter(QPointF c) { m_startCenter = c; } + QPointF previousCenter() const { return m_lastCenter; } + void setPreviousCenter(QPointF c) { m_lastCenter = c; } + qreal scale() const { return m_scale; } + qreal previousScale() const { return m_lastScale; } + void setPreviousScale(qreal s) { m_lastScale = s; } + qreal angle() const { return m_angle; } + qreal previousAngle() const { return m_lastAngle; } + void setPreviousAngle(qreal a) { m_lastAngle = a; } + qreal rotation() const { return m_rotation; } + QPointF point1() const { return m_point1; } + void setPoint1(QPointF p) { m_point1 = p; } + QPointF startPoint1() const { return m_startPoint1; } + void setStartPoint1(QPointF p) { m_startPoint1 = p; } + QPointF point2() const { return m_point2; } + void setPoint2(QPointF p) { m_point2 = p; } + QPointF startPoint2() const { return m_startPoint2; } + void setStartPoint2(QPointF p) { m_startPoint2 = p; } + + bool accepted() const { return m_accepted; } + void setAccepted(bool a) { m_accepted = a; } + +private: + QPointF m_center; + QPointF m_startCenter; + QPointF m_lastCenter; + qreal m_scale; + qreal m_lastScale; + qreal m_angle; + qreal m_lastAngle; + qreal m_rotation; + QPointF m_point1; + QPointF m_point2; + QPointF m_startPoint1; + QPointF m_startPoint2; + bool m_accepted; +}; + + +class QDeclarativeMouseEvent; +class QDeclarativePinchAreaPrivate; +class Q_AUTOTEST_EXPORT QDeclarativePinchArea : public QDeclarativeItem +{ + Q_OBJECT + + Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(QDeclarativePinch *pinch READ pinch CONSTANT) + +public: + QDeclarativePinchArea(QDeclarativeItem *parent=0); + ~QDeclarativePinchArea(); + + bool isEnabled() const; + void setEnabled(bool); + + QDeclarativePinch *pinch(); + +Q_SIGNALS: + void enabledChanged(); + void pinchStarted(QDeclarativePinchEvent *pinch); + void pinchUpdated(QDeclarativePinchEvent *pinch); + void pinchFinished(QDeclarativePinchEvent *pinch); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); + bool sceneEvent(QEvent *); + bool sendMouseEvent(QGraphicsSceneMouseEvent *event); + bool sceneEventFilter(QGraphicsItem *i, QEvent *e); + bool event(QEvent *); + + virtual void geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry); + virtual QVariant itemChange(GraphicsItemChange change, const QVariant& value); + +private: + void updatePinch(); + void handlePress(); + void handleRelease(); + +private: + Q_DISABLE_COPY(QDeclarativePinchArea) + Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativePinchArea) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativePinch) +QML_DECLARE_TYPE(QDeclarativePinchEvent) +QML_DECLARE_TYPE(QDeclarativePinchArea) + +QT_END_HEADER + +#endif // QDECLARATIVEPINCHAREA_H diff --git a/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h new file mode 100644 index 0000000..5641e35 --- /dev/null +++ b/src/declarative/graphicsitems/qdeclarativepincharea_p_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEPINCHAREA_P_H +#define QDECLARATIVEPINCHAREA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qdatetime.h> +#include <qbasictimer.h> +#include <qevent.h> +#include <qgraphicssceneevent.h> +#include "qdeclarativeitem_p.h" + +QT_BEGIN_NAMESPACE + +class QDeclarativePinch; +class QDeclarativePinchAreaPrivate : public QDeclarativeItemPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativePinchArea) +public: + QDeclarativePinchAreaPrivate() + : absorb(true), stealMouse(false), inPinch(false) + , pinchRejected(false), pinch(0), pinchStartDist(0) + { + } + + ~QDeclarativePinchAreaPrivate(); + + void init() + { + Q_Q(QDeclarativePinchArea); + q->setAcceptedMouseButtons(Qt::LeftButton); + q->setAcceptTouchEvents(true); + q->setFiltersChildEvents(true); + } + + bool absorb : 1; + bool stealMouse : 1; + bool inPinch : 1; + bool pinchRejected : 1; + QDeclarativePinch *pinch; + QPointF sceneStartPoint1; + QPointF sceneStartPoint2; + QPointF lastPoint1; + QPointF lastPoint2; + qreal pinchStartDist; + qreal pinchStartScale; + qreal pinchLastScale; + qreal pinchStartRotation; + qreal pinchStartAngle; + qreal pinchLastAngle; + QPointF sceneStartCenter; + QPointF pinchStartCenter; + QPointF sceneLastCenter; + QPointF pinchStartPos; + QList<QTouchEvent::TouchPoint> touchPoints; +}; + +QT_END_NAMESPACE + +#endif // QDECLARATIVEPINCHAREA_P_H diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 4e049c7..27a1301 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -111,14 +111,14 @@ void QDeclarativeBasePositioner::graphicsWidgetGeometryChanged() Note that the subclass is responsible for adding the spacing in between items. */ QDeclarativeBasePositioner::QDeclarativeBasePositioner(PositionerType at, QDeclarativeItem *parent) - : QDeclarativeItem(*(new QDeclarativeBasePositionerPrivate), parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeBasePositionerPrivate), parent) { Q_D(QDeclarativeBasePositioner); d->init(at); } QDeclarativeBasePositioner::QDeclarativeBasePositioner(QDeclarativeBasePositionerPrivate &dd, PositionerType at, QDeclarativeItem *parent) - : QDeclarativeItem(dd, parent) + : QDeclarativeImplicitSizeItem(dd, parent) { Q_D(QDeclarativeBasePositioner); d->init(at); @@ -364,9 +364,13 @@ void QDeclarativeBasePositioner::finishApplyTransitions() \qml Column { spacing: 2 - add: ... - move: ... - ... + add: Transition { + // Define an animation for adding a new item... + } + move: Transition { + // Define an animation for moving items within the column... + } + // ... } \endqml @@ -381,7 +385,7 @@ void QDeclarativeBasePositioner::finishApplyTransitions() Items with a width or height of 0 will not be positioned. - \sa Row, Grid, Flow, {declarative/positioners}{Positioners example} + \sa Row, Grid, Flow, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Column::add @@ -421,7 +425,7 @@ void QDeclarativeBasePositioner::finishApplyTransitions() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Column::spacing @@ -524,7 +528,7 @@ void QDeclarativeColumn::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Column, Grid, Flow, {declarative/positioners}{Positioners example} + \sa Column, Grid, Flow, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Row::add @@ -563,7 +567,7 @@ void QDeclarativeColumn::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Row::spacing @@ -574,21 +578,55 @@ void QDeclarativeColumn::reportConflictingAnchors() \sa Grid::spacing */ QDeclarativeRow::QDeclarativeRow(QDeclarativeItem *parent) -: QDeclarativeBasePositioner(Horizontal, parent) +: QDeclarativeBasePositioner(Horizontal, parent), m_layoutDirection(Qt::LeftToRight) { } +/*! + \qmlproperty enumeration Row::layoutDirection + This property holds the layoutDirection of the row. + + Possible values: + + \list + \o Qt.LeftToRight (default) - Items are laid out from left to right. If the width of the row is explicitly set, + the left anchor remains to the left of the row. + \o Qt.RightToLeft - Items are laid out from right to left. If the width of the row is explicitly set, + the right anchor remains to the right of the row. + \endlist + + \sa Grid::layoutDirection, Flow::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} +*/ +Qt::LayoutDirection QDeclarativeRow::layoutDirection() const +{ + return m_layoutDirection; +} + +void QDeclarativeRow::setLayoutDirection(Qt::LayoutDirection layoutDirection) +{ + if (m_layoutDirection != layoutDirection) { + m_layoutDirection = layoutDirection; + prePositioning(); + emit layoutDirectionChanged(); + } +} + void QDeclarativeRow::doPositioning(QSizeF *contentSize) { int hoffset = 0; + QList<int> hoffsets; for (int ii = 0; ii < positionedItems.count(); ++ii) { const PositionedItem &child = positionedItems.at(ii); if (!child.item || !child.isVisible) continue; - if(child.item->x() != hoffset) - positionX(hoffset, child); + if(m_layoutDirection == Qt::LeftToRight){ + if(child.item->x() != hoffset) + positionX(hoffset, child); + }else{ + hoffsets << hoffset; + } contentSize->setHeight(qMax(contentSize->height(), QGraphicsItemPrivate::get(child.item)->height())); @@ -597,6 +635,26 @@ void QDeclarativeRow::doPositioning(QSizeF *contentSize) } contentSize->setWidth(hoffset - spacing()); + + if(m_layoutDirection == Qt::LeftToRight) + return; + + //Right to Left layout + int end = 0; + if(!widthValid()) + end = contentSize->width(); + else + end = width(); + + int acc = 0; + for (int ii = 0; ii < positionedItems.count(); ++ii) { + const PositionedItem &child = positionedItems.at(ii); + if (!child.item || !child.isVisible) + continue; + hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width(); + if(child.item->x() != hoffset) + positionX(hoffset, child); + } } void QDeclarativeRow::reportConflictingAnchors() @@ -674,7 +732,7 @@ void QDeclarativeRow::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Flow, Row, Column, {declarative/positioners}{Positioners example} + \sa Flow, Row, Column, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Grid::add @@ -712,7 +770,7 @@ void QDeclarativeRow::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Grid::spacing @@ -732,7 +790,7 @@ void QDeclarativeRow::reportConflictingAnchors() \sa rows, columns */ QDeclarativeGrid::QDeclarativeGrid(QDeclarativeItem *parent) : - QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight) + QDeclarativeBasePositioner(Both, parent), m_rows(-1), m_columns(-1), m_flow(LeftToRight), m_layoutDirection(Qt::LeftToRight) { } @@ -780,7 +838,7 @@ void QDeclarativeGrid::setRows(const int rows) \list \o Grid.LeftToRight (default) - Items are positioned next to - to each other from left to right, then wrapped to the next line. + each other in the \l layoutDirection, then wrapped to the next line. \o Grid.TopToBottom - Items are positioned next to each other from top to bottom, then wrapped to the next column. \endlist @@ -799,6 +857,37 @@ void QDeclarativeGrid::setFlow(Flow flow) } } +/*! + \qmlproperty enumeration Grid::layoutDirection + This property holds the layout direction of the layout. + + Possible values are: + + \list + \o Qt.LeftToRight (default) - Items are positioned beginning + from the top, left anchor. The flow direction is dependent + on the \l Grid::flow property. + \o Qt.RightToLeft - Items are positioned beginning from the + top, right anchor. The flow direction is dependent on the + \l Grid::flow property. + \endlist + + \sa Flow::layoutDirection, Row::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} +*/ +Qt::LayoutDirection QDeclarativeGrid::layoutDirection() const +{ + return m_layoutDirection; +} + +void QDeclarativeGrid::setLayoutDirection(Qt::LayoutDirection layoutDirection) +{ + if (m_layoutDirection != layoutDirection) { + m_layoutDirection = layoutDirection; + prePositioning(); + emit layoutDirectionChanged(); + } +} + void QDeclarativeGrid::doPositioning(QSizeF *contentSize) { @@ -821,6 +910,9 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) c = (numVisible+(m_rows-1))/m_rows; } + if(r==0 || c==0) + return; //Nothing to do + QList<int> maxColWidth; QList<int> maxRowHeight; int childIndex =0; @@ -851,7 +943,7 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) if (i==0) maxColWidth << 0; - if (childIndex == positionedItems.count()) + if (childIndex == visibleItems.count()) break; const PositionedItem &child = visibleItems.at(childIndex++); @@ -864,40 +956,71 @@ void QDeclarativeGrid::doPositioning(QSizeF *contentSize) } } + int widthSum = 0; + for(int j=0; j < maxColWidth.size(); j++){ + if(j) + widthSum += spacing(); + widthSum += maxColWidth[j]; + } + + int heightSum = 0; + for(int i=0; i < maxRowHeight.size(); i++){ + if(i) + heightSum += spacing(); + heightSum += maxRowHeight[i]; + } + + contentSize->setHeight(heightSum); + contentSize->setWidth(widthSum); + + int end = 0; + if(widthValid()) + end = width(); + else + end = widthSum; + int xoffset=0; + if(m_layoutDirection == Qt::RightToLeft) + xoffset=end; int yoffset=0; int curRow =0; int curCol =0; for (int i = 0; i < visibleItems.count(); ++i) { const PositionedItem &child = visibleItems.at(i); - if((child.item->x()!=xoffset)||(child.item->y()!=yoffset)){ - positionX(xoffset, child); + int childXOffset = xoffset; + if(m_layoutDirection == Qt::RightToLeft) + childXOffset -= QGraphicsItemPrivate::get(child.item)->width(); + if((child.item->x()!=childXOffset)||(child.item->y()!=yoffset)){ + positionX(childXOffset, child); positionY(yoffset, child); } if (m_flow == LeftToRight) { - contentSize->setWidth(qMax(contentSize->width(), xoffset + QGraphicsItemPrivate::get(child.item)->width())); - contentSize->setHeight(yoffset + maxRowHeight[curRow]); - - xoffset+=maxColWidth[curCol]+spacing(); + if(m_layoutDirection == Qt::LeftToRight) + xoffset+=maxColWidth[curCol]+spacing(); + else + xoffset-=maxColWidth[curCol]+spacing(); curCol++; curCol%=c; if (!curCol){ yoffset+=maxRowHeight[curRow]+spacing(); - xoffset=0; + if(m_layoutDirection == Qt::LeftToRight) + xoffset=0; + else + xoffset=end; curRow++; if (curRow>=r) break; } } else { - contentSize->setHeight(qMax(contentSize->height(), yoffset + QGraphicsItemPrivate::get(child.item)->height())); - contentSize->setWidth(xoffset + maxColWidth[curCol]); - yoffset+=maxRowHeight[curRow]+spacing(); curRow++; curRow%=r; if (!curRow){ - xoffset+=maxColWidth[curCol]+spacing(); + if(m_layoutDirection == Qt::LeftToRight) + xoffset+=maxColWidth[curCol]+spacing(); + else + xoffset-=maxColWidth[curCol]+spacing(); yoffset=0; curCol++; if (curCol>=c) @@ -973,7 +1096,7 @@ void QDeclarativeGrid::reportConflictingAnchors() Items with a width or height of 0 will not be positioned. - \sa Column, Row, Grid, {declarative/positioners}{Positioners example} + \sa Column, Row, Grid, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty Transition Flow::add @@ -1012,7 +1135,7 @@ void QDeclarativeGrid::reportConflictingAnchors() } \endqml - \sa add, {declarative/positioners}{Positioners example} + \sa add, {declarative/positioners/addandremove}{Positioners example} */ /*! \qmlproperty int Flow::spacing @@ -1029,10 +1152,12 @@ class QDeclarativeFlowPrivate : public QDeclarativeBasePositionerPrivate public: QDeclarativeFlowPrivate() - : QDeclarativeBasePositionerPrivate(), flow(QDeclarativeFlow::LeftToRight) + : QDeclarativeBasePositionerPrivate(), flow(QDeclarativeFlow::LeftToRight), + layoutDirection(Qt::LeftToRight) {} QDeclarativeFlow::Flow flow; + Qt::LayoutDirection layoutDirection; }; QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent) @@ -1051,7 +1176,7 @@ QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent) \list \o Flow.LeftToRight (default) - Items are positioned next to - to each other from left to right until the width of the Flow + to each other according to the \l layoutDirection until the width of the Flow is exceeded, then wrapped to the next line. \o Flow.TopToBottom - Items are positioned next to each other from top to bottom until the height of the Flow is exceeded, @@ -1074,6 +1199,40 @@ void QDeclarativeFlow::setFlow(Flow flow) } } +/*! + \qmlproperty enumeration Flow::layoutDirection + This property holds the layout direction of the layout. + + Possible values are: + + \list + \o Qt.LeftToRight (default) - Items are positioned beginning + from the top, left anchor. The flow direction is dependent + on the \l Flow::flow property. + \o Qt.RightToLeft - Items are positioned beginning from the + top, right anchor. The flow direction is dependent on the + \l Flow::flow property. + \endlist + + \sa Grid::layoutDirection, Row::layoutDirection, {declarative/positioners/layoutdirection}{Layout directions example} +*/ + +Qt::LayoutDirection QDeclarativeFlow::layoutDirection() const +{ + Q_D(const QDeclarativeFlow); + return d->layoutDirection; +} + +void QDeclarativeFlow::setLayoutDirection(Qt::LayoutDirection layoutDirection) +{ + Q_D(QDeclarativeFlow); + if (d->layoutDirection != layoutDirection) { + d->layoutDirection = layoutDirection; + prePositioning(); + emit layoutDirectionChanged(); + } +} + void QDeclarativeFlow::doPositioning(QSizeF *contentSize) { Q_D(QDeclarativeFlow); @@ -1081,6 +1240,7 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) int hoffset = 0; int voffset = 0; int linemax = 0; + QList<int> hoffsets; for (int i = 0; i < positionedItems.count(); ++i) { const PositionedItem &child = positionedItems.at(i); @@ -1102,10 +1262,14 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) } } - if(child.item->x() != hoffset || child.item->y() != voffset){ - positionX(hoffset, child); - positionY(voffset, child); + if(d->layoutDirection == Qt::LeftToRight){ + if(child.item->x() != hoffset) + positionX(hoffset, child); + }else{ + hoffsets << hoffset; } + if(child.item->y() != voffset) + positionY(voffset, child); contentSize->setWidth(qMax(contentSize->width(), hoffset + childPrivate->width())); contentSize->setHeight(qMax(contentSize->height(), voffset + childPrivate->height())); @@ -1120,6 +1284,24 @@ void QDeclarativeFlow::doPositioning(QSizeF *contentSize) linemax = qMax(linemax, qCeil(childPrivate->width())); } } + + if(d->layoutDirection == Qt::LeftToRight) + return; + + int end; + if(widthValid()) + end = width(); + else + end = contentSize->width(); + int acc = 0; + for (int i = 0; i < positionedItems.count(); ++i) { + const PositionedItem &child = positionedItems.at(i); + if (!child.item || !child.isVisible) + continue; + hoffset = end - hoffsets[acc++] - QGraphicsItemPrivate::get(child.item)->width(); + if(child.item->x() != hoffset) + positionX(hoffset, child); + } } void QDeclarativeFlow::reportConflictingAnchors() diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p.h index 9efbeb9..55d8fa1 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p.h @@ -42,7 +42,7 @@ #ifndef QDECLARATIVELAYOUTS_H #define QDECLARATIVELAYOUTS_H -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" #include <private/qdeclarativestate_p.h> #include <private/qpodvector_p.h> @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeBasePositionerPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBasePositioner : public QDeclarativeItem +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBasePositioner : public QDeclarativeImplicitSizeItem { Q_OBJECT @@ -129,12 +129,21 @@ private: class Q_AUTOTEST_EXPORT QDeclarativeRow: public QDeclarativeBasePositioner { Q_OBJECT + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1) public: QDeclarativeRow(QDeclarativeItem *parent=0); + + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection (Qt::LayoutDirection); + +Q_SIGNALS: + Q_REVISION(1) void layoutDirectionChanged(); + protected: virtual void doPositioning(QSizeF *contentSize); virtual void reportConflictingAnchors(); private: + Qt::LayoutDirection m_layoutDirection; Q_DISABLE_COPY(QDeclarativeRow) }; @@ -144,6 +153,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeGrid : public QDeclarativeBasePositioner Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) Q_PROPERTY(int columns READ columns WRITE setColumns NOTIFY columnsChanged) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1) public: QDeclarativeGrid(QDeclarativeItem *parent=0); @@ -159,10 +169,14 @@ public: Flow flow() const; void setFlow(Flow); + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection (Qt::LayoutDirection); + Q_SIGNALS: void rowsChanged(); void columnsChanged(); void flowChanged(); + Q_REVISION(1) void layoutDirectionChanged(); protected: virtual void doPositioning(QSizeF *contentSize); @@ -172,6 +186,7 @@ private: int m_rows; int m_columns; Flow m_flow; + Qt::LayoutDirection m_layoutDirection; Q_DISABLE_COPY(QDeclarativeGrid) }; @@ -179,6 +194,7 @@ class QDeclarativeFlowPrivate; class Q_AUTOTEST_EXPORT QDeclarativeFlow: public QDeclarativeBasePositioner { Q_OBJECT + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged REVISION 1) Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged) public: QDeclarativeFlow(QDeclarativeItem *parent=0); @@ -188,8 +204,12 @@ public: Flow flow() const; void setFlow(Flow); + Qt::LayoutDirection layoutDirection() const; + void setLayoutDirection (Qt::LayoutDirection); + Q_SIGNALS: void flowChanged(); + Q_REVISION(1) void layoutDirectionChanged(); protected: virtual void doPositioning(QSizeF *contentSize); diff --git a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h index c6535a7..df105c6 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativepositioners_p_p.h @@ -55,7 +55,7 @@ #include "private/qdeclarativepositioners_p.h" -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include <qdeclarativestate_p.h> #include <qdeclarativetransitionmanager_p_p.h> @@ -67,7 +67,7 @@ #include <QDebug> QT_BEGIN_NAMESPACE -class QDeclarativeBasePositionerPrivate : public QDeclarativeItemPrivate, public QDeclarativeItemChangeListener +class QDeclarativeBasePositionerPrivate : public QDeclarativeImplicitSizeItemPrivate, public QDeclarativeItemChangeListener { Q_DECLARE_PUBLIC(QDeclarativeBasePositioner) diff --git a/src/declarative/graphicsitems/qdeclarativerectangle.cpp b/src/declarative/graphicsitems/qdeclarativerectangle.cpp index 94db2f1..d962919 100644 --- a/src/declarative/graphicsitems/qdeclarativerectangle.cpp +++ b/src/declarative/graphicsitems/qdeclarativerectangle.cpp @@ -60,7 +60,10 @@ QT_BEGIN_NAMESPACE Example: \qml - Rectangle { border.width: 2; border.color: "red" ... } + Rectangle { + border.width: 2 + border.color: "red" + } \endqml */ @@ -131,9 +134,9 @@ void QDeclarativeGradientStop::updateGradient() \section1 Example Usage - \beginfloatright + \div {float-right} \inlineimage qml-gradient.png - \endfloat + \enddiv The following example declares a \l Rectangle item with a gradient starting with red, blending to yellow at one third of the height of the rectangle, @@ -217,9 +220,9 @@ void QDeclarativeGradient::doUpdate() \section1 Example Usage - \beginfloatright + \div {float-right} \inlineimage declarative-rect.png - \endfloat + \enddiv The following example shows the effects of some of the common properties on a Rectangle item, which in this case is used to create a square: @@ -269,9 +272,9 @@ void QDeclarativeRectangle::doUpdate() rectangle (as documented for QRect rendering). This can cause unintended effects if \c border.width is 1 and the rectangle is \l{Item::clip}{clipped} by a parent item: - \beginfloatright + \div {float-right} \inlineimage rect-border-width.png - \endfloat + \enddiv \snippet doc/src/snippets/declarative/rectangle/rect-border-width.qml 0 @@ -293,9 +296,9 @@ QDeclarativePen *QDeclarativeRectangle::border() This property allows for the construction of simple vertical gradients. Other gradients may by formed by adding rotation to the rectangle. - \beginfloatleft + \div {float-left} \inlineimage declarative-rect_gradient.png - \endfloat + \enddiv \snippet doc/src/snippets/declarative/rectangle/rectangle-gradient.qml rectangles \clearfloat @@ -361,9 +364,9 @@ void QDeclarativeRectangle::setRadius(qreal radius) The default color is white. - \beginfloatright + \div {float-right} \inlineimage rect-color.png - \endfloat + \enddiv The following example shows rectangles with colors specified using hexadecimal and named color notation: diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp index 7aa30e5..4d0f34c 100644 --- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp +++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp @@ -84,43 +84,23 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate() \image repeater-simple.png - The \l model of a Repeater can be any of the supported \l {qmlmodels}{Data Models}. + A Repeater's \l model can be any of the supported \l {qmlmodels}{data models}. + Additionally, like delegates for other views, a Repeater delegate can access + its index within the repeater, as well as the model data relevant to the + delegate. See the \l delegate property documentation for details. Items instantiated by the Repeater are inserted, in order, as children of the Repeater's parent. The insertion starts immediately after the repeater's position in its parent stacking list. This allows a Repeater to be used inside a layout. For example, the following Repeater's items are stacked between a red rectangle and a blue rectangle: - + \snippet doc/src/snippets/declarative/repeaters/repeater.qml layout \image repeater.png - \section2 The \c index and \c modelData properties - - The index of a delegate is exposed as an accessible \c index property in the delegate. - Properties of the model are also available depending upon the type of \l {qmlmodels}{Data Model}. - - Here is a Repeater that uses the \c index property inside the instantiated items: - - \table - \row - \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml index - \o \image repeater-index.png - \endtable - - Here is another Repeater that uses the \c modelData property to reference the data for a - particular index: - - \table - \row - \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml modeldata - \o \image repeater-modeldata.png - \endtable - - - A Repeater item owns all items it instantiates. Removing or dynamically destroying + \note A Repeater item owns all items it instantiates. Removing or dynamically destroying an item created by a Repeater results in unpredictable behavior. @@ -146,6 +126,27 @@ QDeclarativeRepeaterPrivate::~QDeclarativeRepeaterPrivate() \endcode */ +/*! + \qmlsignal Repeater::onItemAdded(int index, Item item) + \since Quick 1.1 + + This handler is called when an item is added to the repeater. The \a index + parameter holds the index at which the item has been inserted within the + repeater, and the \a item parameter holds the \l Item that has been added. +*/ + +/*! + \qmlsignal Repeater::onItemRemoved(int index, Item item) + \since Quick 1.1 + + This handler is called when an item is removed from the repeater. The \a index + parameter holds the index at which the item was removed from the repeater, + and the \a item parameter holds the \l Item that was removed. + + Do not keep a reference to \a item if it was created by this repeater, as + in these cases it will be deleted shortly after the handler is called. +*/ + QDeclarativeRepeater::QDeclarativeRepeater(QDeclarativeItem *parent) : QDeclarativeItem(*(new QDeclarativeRepeaterPrivate), parent) { @@ -160,26 +161,16 @@ QDeclarativeRepeater::~QDeclarativeRepeater() The model providing data for the repeater. - This property can be set to any of the following: + This property can be set to any of the supported \l {qmlmodels}{data models}: \list - \o A number that indicates the number of delegates to be created + \o A number that indicates the number of delegates to be created by the repeater \o A model (e.g. a ListModel item, or a QAbstractItemModel subclass) \o A string list \o An object list \endlist - In each case, the data element and the index is exposed to each instantiated - component. The index is always exposed as an accessible \c index property. - In the case of an object or string list, the data element (of type string - or object) is available as the \c modelData property. In the case of a Qt model, - all roles are available as named properties just like in the view classes. - - As a special case the model can also be merely a number. In this case it will - create that many instances of the component. They will also be assigned an index - based on the order they are created. - - Models can also be created directly in QML, using a \l{ListModel} or \l{XmlListModel}. + The type of model affects the properties that are exposed to the \l delegate. \sa {qmlmodels}{Data Models} */ @@ -207,7 +198,6 @@ void QDeclarativeRepeater::setModel(const QVariant &model) */ } d->dataSource = model; - emit modelChanged(); QObject *object = qvariant_cast<QObject*>(model); QDeclarativeVisualModel *vim = 0; if (object && (vim = qobject_cast<QDeclarativeVisualModel *>(object))) { @@ -235,6 +225,7 @@ void QDeclarativeRepeater::setModel(const QVariant &model) */ regenerate(); } + emit modelChanged(); emit countChanged(); } @@ -243,8 +234,33 @@ void QDeclarativeRepeater::setModel(const QVariant &model) \default The delegate provides a template defining each item instantiated by the repeater. - The index is exposed as an accessible \c index property. Properties of the - model are also available depending upon the type of \l {qmlmodels}{Data Model}. + + Delegates are exposed to a read-only \c index property that indicates the index + of the delegate within the repeater. For example, the following \l Text delegate + displays the index of each repeated item: + + \table + \row + \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml index + \o \image repeater-index.png + \endtable + + If the \l model is a \l{QStringList-based model}{string list} or + \l{QObjectList-based model}{object list}, the delegate is also exposed to + a read-only \c modelData property that holds the string or object data. For + example: + + \table + \row + \o \snippet doc/src/snippets/declarative/repeaters/repeater.qml modeldata + \o \image repeater-modeldata.png + \endtable + + If the \l model is a model object (such as a \l ListModel) the delegate + can access all model roles as named properties, in the same way that delegates + do for view classes like ListView. + + \sa {QML Data Models} */ QDeclarativeComponent *QDeclarativeRepeater::delegate() const { @@ -288,6 +304,21 @@ int QDeclarativeRepeater::count() const return 0; } +/*! + \qmlmethod Item Repeater::itemAt(index) + \since Quick 1.1 + + Returns the \l Item that has been created at the given \a index, or \c null + if no item exists at \a index. +*/ +QDeclarativeItem *QDeclarativeRepeater::itemAt(int index) const +{ + Q_D(const QDeclarativeRepeater); + if (index >= 0 && index < d->deletables.count()) + return d->deletables[index]; + return 0; + +} void QDeclarativeRepeater::componentComplete() { @@ -309,8 +340,13 @@ QVariant QDeclarativeRepeater::itemChange(GraphicsItemChange change, void QDeclarativeRepeater::clear() { Q_D(QDeclarativeRepeater); + bool complete = isComponentComplete(); + if (d->model) { - foreach (QDeclarativeItem *item, d->deletables) { + while (d->deletables.count() > 0) { + QDeclarativeItem *item = d->deletables.takeLast(); + if (complete) + emit itemRemoved(d->deletables.count()-1, item); d->model->release(item); } } @@ -335,6 +371,7 @@ void QDeclarativeRepeater::regenerate() item->setParentItem(parentItem()); item->stackBefore(this); d->deletables << item; + emit itemAdded(ii, item); } } } @@ -355,6 +392,7 @@ void QDeclarativeRepeater::itemsInserted(int index, int count) else item->stackBefore(this); d->deletables.insert(modelIndex, item); + emit itemAdded(modelIndex, item); } } emit countChanged(); @@ -367,6 +405,7 @@ void QDeclarativeRepeater::itemsRemoved(int index, int count) return; while (count--) { QDeclarativeItem *item = d->deletables.takeAt(index); + emit itemRemoved(index, item); if (item) d->model->release(item); else diff --git a/src/declarative/graphicsitems/qdeclarativerepeater_p.h b/src/declarative/graphicsitems/qdeclarativerepeater_p.h index 73b50c2..9cb4e30 100644 --- a/src/declarative/graphicsitems/qdeclarativerepeater_p.h +++ b/src/declarative/graphicsitems/qdeclarativerepeater_p.h @@ -72,10 +72,16 @@ public: int count() const; + Q_INVOKABLE Q_REVISION(1) QDeclarativeItem *itemAt(int index) const; + Q_SIGNALS: void modelChanged(); void delegateChanged(); void countChanged(); + + Q_REVISION(1) void itemAdded(int index, QDeclarativeItem *item); + Q_REVISION(1) void itemRemoved(int index, QDeclarativeItem *item); + private: void clear(); void regenerate(); diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 640965c..559d061 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -54,6 +54,7 @@ #include <QPainter> #include <QAbstractTextDocumentLayout> #include <qmath.h> +#include <limits.h> QT_BEGIN_NAMESPACE @@ -84,12 +85,16 @@ private: DEFINE_BOOL_CONFIG_OPTION(enableImageCache, QML_ENABLE_TEXT_IMAGE_CACHE); +QString QDeclarativeTextPrivate::elideChar = QString(0x2026); + QDeclarativeTextPrivate::QDeclarativeTextPrivate() : color((QRgb)0), style(QDeclarativeText::Normal), hAlign(QDeclarativeText::AlignLeft), vAlign(QDeclarativeText::AlignTop), elideMode(QDeclarativeText::ElideNone), - format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), imageCacheDirty(true), - updateOnComponentComplete(true), richText(false), singleline(false), cacheAllTextAsImage(true), - internalWidthUpdate(false), doc(0) + format(QDeclarativeText::AutoText), wrapMode(QDeclarativeText::NoWrap), lineHeight(1), + lineHeightMode(QDeclarativeText::ProportionalHeight), + lineCount(1), truncated(false), maximumLineCount(INT_MAX), + maximumLineCountValid(false), imageCacheDirty(true), updateOnComponentComplete(true), richText(false), singleline(false), + cacheAllTextAsImage(true), internalWidthUpdate(false), requireImplicitWidth(false), naturalWidth(0), doc(0) { cacheAllTextAsImage = enableImageCache(); QGraphicsItemPrivate::acceptedMouseButtons = Qt::LeftButton; @@ -176,6 +181,18 @@ QDeclarativeTextPrivate::~QDeclarativeTextPrivate() { } +qreal QDeclarativeTextPrivate::implicitWidth() const +{ + if (!requireImplicitWidth) { + // We don't calculate implicitWidth unless it is required. + // We need to force a size update now to ensure implicitWidth is calculated + QDeclarativeTextPrivate *me = const_cast<QDeclarativeTextPrivate*>(this); + me->requireImplicitWidth = true; + me->updateSize(); + } + return mImplicitWidth; +} + void QDeclarativeTextPrivate::updateLayout() { Q_Q(QDeclarativeText); @@ -192,9 +209,13 @@ void QDeclarativeTextPrivate::updateLayout() QString tmp = text; tmp.replace(QLatin1Char('\n'), QChar::LineSeparator); singleline = !tmp.contains(QChar::LineSeparator); - if (singleline && elideMode != QDeclarativeText::ElideNone && q->widthValid()) { + if (singleline && !maximumLineCountValid && elideMode != QDeclarativeText::ElideNone && q->widthValid()) { QFontMetrics fm(font); tmp = fm.elidedText(tmp,(Qt::TextElideMode)elideMode,q->width()); // XXX still worth layout...? + if (tmp != text && !truncated) { + truncated = true; + emit q->truncatedChanged(); + } } layout.setText(tmp); } else { @@ -215,12 +236,20 @@ void QDeclarativeTextPrivate::updateSize() return; } + if (!requireImplicitWidth) { + emit q->implicitWidthChanged(); + // if the implicitWidth is used, then updateSize() has already been called (recursively) + if (requireImplicitWidth) + return; + } + invalidateImageCache(); QFontMetrics fm(font); if (text.isEmpty()) { q->setImplicitWidth(0); q->setImplicitHeight(fm.height()); + paintedSize = QSize(0, fm.height()); emit q->paintedSizeChanged(); q->update(); return; @@ -241,9 +270,14 @@ void QDeclarativeTextPrivate::updateSize() singleline = false; // richtext can't elide or be optimized for single-line case ensureDoc(); doc->setDefaultFont(font); - QTextOption option((Qt::Alignment)int(hAlign | vAlign)); + QTextOption option; + option.setAlignment((Qt::Alignment)int(hAlign | vAlign)); option.setWrapMode(QTextOption::WrapMode(wrapMode)); doc->setDefaultTextOption(option); + if (requireImplicitWidth && q->widthValid()) { + doc->setTextWidth(-1); + naturalWidth = doc->idealWidth(); + } if (wrapMode != QDeclarativeText::NoWrap && q->widthValid()) doc->setTextWidth(q->width()); else @@ -268,10 +302,16 @@ void QDeclarativeTextPrivate::updateSize() //### need to comfirm cost of always setting these for richText internalWidthUpdate = true; - q->setImplicitWidth(size.width()); + if (!q->widthValid()) + q->setImplicitWidth(size.width()); + else if (requireImplicitWidth) + q->setImplicitWidth(naturalWidth); internalWidthUpdate = false; q->setImplicitHeight(size.height()); - emit q->paintedSizeChanged(); + if (paintedSize != size) { + paintedSize = size; + emit q->paintedSizeChanged(); + } q->update(); } @@ -291,25 +331,107 @@ QSize QDeclarativeTextPrivate::setupTextLayout() qreal height = 0; qreal widthUsed = 0; qreal lineWidth = 0; + int visibleTextLength = 0; + int visibleCount = 0; //set manual width if ((wrapMode != QDeclarativeText::NoWrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid()) lineWidth = q->width(); QTextOption textOption = layout.textOption(); + if (hAlign == QDeclarativeText::AlignJustify) + textOption.setAlignment(Qt::Alignment(hAlign)); textOption.setWrapMode(QTextOption::WrapMode(wrapMode)); layout.setTextOption(textOption); - layout.beginLayout(); - forever { - QTextLine line = layout.createLine(); - if (!line.isValid()) - break; + QDeclarativeText::HAlignment hAlignment = hAlign; + if(text.isRightToLeft()) { + if ((hAlign == QDeclarativeText::AlignLeft) || (hAlign == QDeclarativeText::AlignJustify)) { + hAlignment = QDeclarativeText::AlignRight; + } else if (hAlign == QDeclarativeText::AlignRight) { + hAlignment = QDeclarativeText::AlignLeft; + } else { + hAlignment = hAlign; + } + } - if (lineWidth) + bool elideText = false; + bool truncate = false; + + QFontMetrics fm(layout.font()); + qreal elideWidth = fm.width(elideChar); + elidePos = QPointF(); + + if (requireImplicitWidth && q->widthValid()) { + // requires an extra layout + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + } + layout.endLayout(); + naturalWidth = 0; + for (int i = 0; i < layout.lineCount(); ++i) { + QTextLine line = layout.lineAt(i); + naturalWidth = qMax(naturalWidth, line.naturalTextWidth()); + } + } + + if (maximumLineCountValid) { + layout.beginLayout(); + if (!lineWidth) + lineWidth = INT_MAX; + int y = 0; + int linesLeft = maximumLineCount; + while (linesLeft > 0) { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + + visibleCount++; line.setLineWidth(lineWidth); + visibleTextLength += line.textLength(); + + if (--linesLeft == 0) { + if (visibleTextLength < text.length()) { + truncate = true; + if (elideMode==QDeclarativeText::ElideRight && q->widthValid()) { + // Need to correct for alignment + line.setLineWidth(lineWidth-elideWidth); + int x = line.naturalTextWidth(); + if (hAlignment == QDeclarativeText::AlignRight) { + x = q->width()-elideWidth; + } else if (hAlignment == QDeclarativeText::AlignHCenter) { + x = (q->width()+line.naturalTextWidth()-elideWidth)/2; + } + elidePos = QPointF(x, y + fm.ascent()); + elideText = true; + } + } + } + + y += line.height(); + } + layout.endLayout(); + + //Update truncated + if (truncated != truncate) { + truncated = truncate; + emit q->truncatedChanged(); + } + } else { + layout.beginLayout(); + forever { + QTextLine line = layout.createLine(); + if (!line.isValid()) + break; + visibleCount++; + if (lineWidth) + line.setLineWidth(lineWidth); + } + layout.endLayout(); } - layout.endLayout(); for (int i = 0; i < layout.lineCount(); ++i) { QTextLine line = layout.lineAt(i); @@ -317,26 +439,38 @@ QSize QDeclarativeTextPrivate::setupTextLayout() } qreal layoutWidth = q->widthValid() ? q->width() : widthUsed; + if (!q->widthValid()) + naturalWidth = layoutWidth; qreal x = 0; for (int i = 0; i < layout.lineCount(); ++i) { QTextLine line = layout.lineAt(i); line.setPosition(QPointF(0, height)); - height += line.height(); + height += (lineHeightMode == QDeclarativeText::FixedHeight) ? lineHeight : line.height() * lineHeight; if (!cacheAllTextAsImage) { - if (hAlign == QDeclarativeText::AlignLeft) { + if ((hAlignment == QDeclarativeText::AlignLeft) || (hAlignment == QDeclarativeText::AlignJustify)) { x = 0; - } else if (hAlign == QDeclarativeText::AlignRight) { + } else if (hAlignment == QDeclarativeText::AlignRight) { x = layoutWidth - line.naturalTextWidth(); - } else if (hAlign == QDeclarativeText::AlignHCenter) { + if (elideText && i == layout.lineCount()-1) + x -= elideWidth; // Correct for when eliding multilines + } else if (hAlignment == QDeclarativeText::AlignHCenter) { x = (layoutWidth - line.naturalTextWidth()) / 2; + if (elideText && i == layout.lineCount()-1) + x -= elideWidth/2; // Correct for when eliding multilines } line.setPosition(QPointF(x, line.y())); } } - return layout.boundingRect().toAlignedRect().size(); + //Update the number of visible lines + if (lineCount != visibleCount) { + lineCount = visibleCount; + emit q->lineCountChanged(); + } + + return QSize(qCeil(widthUsed), qCeil(height)); } /*! @@ -351,7 +485,7 @@ QPixmap QDeclarativeTextPrivate::textLayoutImage(bool drawStyle) qreal x = 0; for (int i = 0; i < layout.lineCount(); ++i) { QTextLine line = layout.lineAt(i); - if (hAlign == QDeclarativeText::AlignLeft) { + if ((hAlign == QDeclarativeText::AlignLeft) || (hAlign == QDeclarativeText::AlignJustify)) { x = 0; } else if (hAlign == QDeclarativeText::AlignRight) { x = size.width() - line.naturalTextWidth(); @@ -389,7 +523,9 @@ void QDeclarativeTextPrivate::drawTextLayout(QPainter *painter, const QPointF &p else painter->setPen(color); painter->setFont(font); - layout.draw(painter, pos); + layout.draw(painter, pos); + if (!elidePos.isNull()) + painter->drawText(elidePos, elideChar); } /*! @@ -558,11 +694,24 @@ QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixma \brief The Text item allows you to add formatted text to a scene. \inherits Item - A Text item can display both plain and rich text. For example: + Text items can display both plain and rich text. For example, red text with + a specific font and size can be defined like this: \qml - Text { text: "Hello World!"; font.family: "Helvetica"; font.pointSize: 24; color: "red" } - Text { text: "<b>Hello</b> <i>World!</i>" } + Text { + text: "Hello World!" + font.family: "Helvetica" + font.pointSize: 24 + color: "red" + } + \endqml + + Rich text is defined using HTML-style markup: + + \qml + Text { + text: "<b>Hello</b> <i>World!</i>" + } \endqml \image declarative-text.png @@ -582,7 +731,7 @@ QPixmap QDeclarativeTextPrivate::drawOutline(const QPixmap &source, const QPixma \sa {declarative/text/fonts}{Fonts example} */ QDeclarativeText::QDeclarativeText(QDeclarativeItem *parent) - : QDeclarativeItem(*(new QDeclarativeTextPrivate), parent) + : QDeclarativeImplicitSizeItem(*(new QDeclarativeTextPrivate), parent) { } @@ -798,12 +947,20 @@ void QDeclarativeText::setText(const QString &n) The text color. + An example of green text defined using hexadecimal notation: \qml - //green text using hexadecimal notation - Text { color: "#00FF00"; ... } + Text { + color: "#00FF00" + text: "green text" + } + \endqml - //steelblue text using SVG color name - Text { color: "steelblue"; ... } + An example of steel blue text defined using an SVG color name: + \qml + Text { + color: "steelblue" + text: "blue text" + } \endqml */ QColor QDeclarativeText::color() const @@ -907,8 +1064,8 @@ void QDeclarativeText::setStyleColor(const QColor &color) Sets the horizontal and vertical alignment of the text within the Text items width and height. By default, the text is top-left aligned. - The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight and - \c Text.AlignHCenter. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom + The valid values for \c horizontalAlignment are \c Text.AlignLeft, \c Text.AlignRight, \c Text.AlignHCenter and + \c Text.AlignJustify. The valid values for \c verticalAlignment are \c Text.AlignTop, \c Text.AlignBottom and \c Text.AlignVCenter. Note that for a single line of text, the size of the text is the area of the text. In this common case, @@ -986,6 +1143,76 @@ void QDeclarativeText::setWrapMode(WrapMode mode) emit wrapModeChanged(); } +/*! + \qmlproperty int Text::lineCount + + Returns the number of lines visible in the text item. + + This property is not supported for rich text. + + \sa maximumLineCount +*/ +int QDeclarativeText::lineCount() const +{ + Q_D(const QDeclarativeText); + return d->lineCount; +} + +/*! + \qmlproperty bool Text::truncated + + Returns true if the text has been truncated due to \l maximumLineCount + or \l elide. + + This property is not supported for rich text. + + \sa maximumLineCount, elide +*/ +bool QDeclarativeText::truncated() const +{ + Q_D(const QDeclarativeText); + return d->truncated; +} + +/*! + \qmlproperty int Text::maximumLineCount + + Set this property to limit the number of lines that the text item will show. + If elide is set to Text.ElideRight, the text will be elided appropriately. + By default, this is the value of the largest possible integer. + + This property is not supported for rich text. + + \sa lineCount, elide +*/ +int QDeclarativeText::maximumLineCount() const +{ + Q_D(const QDeclarativeText); + return d->maximumLineCount; +} + +void QDeclarativeText::setMaximumLineCount(int lines) +{ + Q_D(QDeclarativeText); + + d->maximumLineCountValid = lines==INT_MAX ? false : true; + if (d->maximumLineCount != lines) { + d->maximumLineCount = lines; + d->updateLayout(); + emit maximumLineCountChanged(); + } +} + +void QDeclarativeText::resetMaximumLineCount() +{ + Q_D(QDeclarativeText); + setMaximumLineCount(INT_MAX); + d->elidePos = QPointF(); + if (d->truncated != false) { + d->truncated = false; + emit truncatedChanged(); + } +} /*! \qmlproperty enumeration Text::textFormat @@ -1073,7 +1300,7 @@ void QDeclarativeText::setTextFormat(TextFormat format) Set this property to elide parts of the text fit to the Text item's width. The text will only elide if an explicit width has been set. - This property cannot be used with multi-line text or with rich text. + This property cannot be used with rich text. Eliding can be: \list @@ -1083,6 +1310,9 @@ void QDeclarativeText::setTextFormat(TextFormat format) \o Text.ElideRight \endlist + If this property is set to Text.ElideRight, it can be used with multiline + text. The text will only elide if maximumLineCount has been set. + If the text is a multi-length string, and the mode is not \c Text.ElideNone, the first string that fits will be used, otherwise the last will be elided. @@ -1126,6 +1356,7 @@ QRectF QDeclarativeText::boundingRect() const switch (d->hAlign) { case AlignLeft: + case AlignJustify: x = 0; break; case AlignRight: @@ -1159,7 +1390,7 @@ void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF & && (d->wrapMode != QDeclarativeText::NoWrap || d->elideMode != QDeclarativeText::ElideNone || d->hAlign != QDeclarativeText::AlignLeft)) { - if (d->singleline && d->elideMode != QDeclarativeText::ElideNone && widthValid()) { + if ((d->singleline || d->maximumLineCountValid) && d->elideMode != QDeclarativeText::ElideNone && widthValid()) { // We need to re-elide d->updateLayout(); } else { @@ -1179,7 +1410,8 @@ void QDeclarativeText::geometryChanged(const QRectF &newGeometry, const QRectF & */ qreal QDeclarativeText::paintedWidth() const { - return implicitWidth(); + Q_D(const QDeclarativeText); + return d->paintedSize.width(); } /*! @@ -1190,7 +1422,65 @@ qreal QDeclarativeText::paintedWidth() const */ qreal QDeclarativeText::paintedHeight() const { - return implicitHeight(); + Q_D(const QDeclarativeText); + return d->paintedSize.height(); +} + +/*! + \qmlproperty real Text::lineHeight + + Sets the line height for the text. + The value can be in pixels or a multiplier depending on lineHeightMode. + + The default value is a multiplier of 1.0. + The line height must be a positive value. +*/ +qreal QDeclarativeText::lineHeight() const +{ + Q_D(const QDeclarativeText); + return d->lineHeight; +} + +void QDeclarativeText::setLineHeight(qreal lineHeight) +{ + Q_D(QDeclarativeText); + + if ((d->lineHeight == lineHeight) || (lineHeight < 0.0)) + return; + + d->lineHeight = lineHeight; + d->updateLayout(); + emit lineHeightChanged(lineHeight); +} + +/*! + \qmlproperty enumeration Text::lineHeightMode + + This property determines how the line height is specified. + The possible values are: + + \list + \o Text.ProportionalHeight (default) - this sets the spacing proportional to the + line (as a multiplier). For example, set to 2 for double spacing. + \o Text.FixedHeight - this sets the line height to a fixed line height (in pixels). + \endlist +*/ +QDeclarativeText::LineHeightMode QDeclarativeText::lineHeightMode() const +{ + Q_D(const QDeclarativeText); + return d->lineHeightMode; +} + +void QDeclarativeText::setLineHeightMode(LineHeightMode mode) +{ + Q_D(QDeclarativeText); + if (mode == d->lineHeightMode) + return; + + d->lineHeightMode = mode; + d->updateLayout(); + + emit lineHeightModeChanged(mode); } /*! diff --git a/src/declarative/graphicsitems/qdeclarativetext_p.h b/src/declarative/graphicsitems/qdeclarativetext_p.h index abc45f9..b8835d1 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p.h @@ -43,7 +43,7 @@ #define QDECLARATIVETEXT_H #include <QtGui/qtextoption.h> -#include "qdeclarativeitem.h" +#include "qdeclarativeimplicitsizeitem_p.h" #include <private/qdeclarativeglobal_p.h> @@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) class QDeclarativeTextPrivate; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeItem +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeImplicitSizeItem { Q_OBJECT Q_ENUMS(HAlignment) @@ -62,6 +62,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeItem Q_ENUMS(TextFormat) Q_ENUMS(TextElideMode) Q_ENUMS(WrapMode) + Q_ENUMS(LineHeightMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged) @@ -71,10 +72,16 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeText : public QDeclarativeItem Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) + Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged REVISION 1) + Q_PROPERTY(bool truncated READ truncated NOTIFY truncatedChanged REVISION 1) + Q_PROPERTY(int maximumLineCount READ maximumLineCount WRITE setMaximumLineCount NOTIFY maximumLineCountChanged RESET resetMaximumLineCount REVISION 1) + Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) Q_PROPERTY(TextElideMode elide READ elideMode WRITE setElideMode NOTIFY elideModeChanged) //### elideMode? Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) + Q_PROPERTY(qreal lineHeight READ lineHeight WRITE setLineHeight NOTIFY lineHeightChanged REVISION 1) + Q_PROPERTY(LineHeightMode lineHeightMode READ lineHeightMode WRITE setLineHeightMode NOTIFY lineHeightModeChanged REVISION 1) public: QDeclarativeText(QDeclarativeItem *parent=0); @@ -82,7 +89,8 @@ public: enum HAlignment { AlignLeft = Qt::AlignLeft, AlignRight = Qt::AlignRight, - AlignHCenter = Qt::AlignHCenter }; + AlignHCenter = Qt::AlignHCenter, + AlignJustify = Qt::AlignJustify }; // ### VERSIONING: Only in QtQuick 1.1 enum VAlignment { AlignTop = Qt::AlignTop, AlignBottom = Qt::AlignBottom, AlignVCenter = Qt::AlignVCenter }; @@ -106,6 +114,8 @@ public: Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + enum LineHeightMode { ProportionalHeight, FixedHeight }; + QString text() const; void setText(const QString &); @@ -130,12 +140,25 @@ public: WrapMode wrapMode() const; void setWrapMode(WrapMode w); + int lineCount() const; + bool truncated() const; + + int maximumLineCount() const; + void setMaximumLineCount(int lines); + void resetMaximumLineCount(); + TextFormat textFormat() const; void setTextFormat(TextFormat format); TextElideMode elideMode() const; void setElideMode(TextElideMode); + qreal lineHeight() const; + void setLineHeight(qreal lineHeight); + + LineHeightMode lineHeightMode() const; + void setLineHeightMode(LineHeightMode); + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); virtual void componentComplete(); @@ -157,9 +180,14 @@ Q_SIGNALS: void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); void wrapModeChanged(); + Q_REVISION(1) void lineCountChanged(); + Q_REVISION(1) void truncatedChanged(); + Q_REVISION(1) void maximumLineCountChanged(); void textFormatChanged(TextFormat textFormat); void elideModeChanged(TextElideMode mode); void paintedSizeChanged(); + Q_REVISION(1) void lineHeightChanged(qreal lineHeight); + Q_REVISION(1) void lineHeightModeChanged(LineHeightMode mode); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index e749bc9..36ae123 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -54,7 +54,7 @@ // #include "qdeclarativeitem.h" -#include "private/qdeclarativeitem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include "private/qdeclarativetextlayout_p.h" #include <qdeclarative.h> @@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; class QTextDocumentWithImageResources; -class QDeclarativeTextPrivate : public QDeclarativeItemPrivate +class Q_AUTOTEST_EXPORT QDeclarativeTextPrivate : public QDeclarativeImplicitSizeItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeText) public: @@ -89,6 +89,15 @@ public: QDeclarativeText::TextElideMode elideMode; QDeclarativeText::TextFormat format; QDeclarativeText::WrapMode wrapMode; + qreal lineHeight; + QDeclarativeText::LineHeightMode lineHeightMode; + int lineCount; + bool truncated; + int maximumLineCount; + int maximumLineCountValid; + QPointF elidePos; + + static QString elideChar; void invalidateImageCache(); void checkImageCache(); @@ -100,9 +109,12 @@ public: bool singleline:1; bool cacheAllTextAsImage:1; bool internalWidthUpdate:1; + bool requireImplicitWidth:1; QSize layedOutTextSize; - + QSize paintedSize; + qreal naturalWidth; + virtual qreal implicitWidth() const; void ensureDoc(); QPixmap textDocumentImage(bool drawStyle); QTextDocumentWithImageResources *doc; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index cb62a2c..e2f6265 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -51,6 +51,7 @@ #include <QTextLayout> #include <QTextLine> #include <QTextDocument> +#include <QTextObject> #include <QGraphicsSceneMouseEvent> #include <QDebug> #include <QPainter> @@ -103,8 +104,16 @@ TextEdit { \sa Text, TextInput, {declarative/text/textselection}{Text Selection example} */ +/*! + \qmlsignal TextEdit::onLinkActivated(string link) + \since Quick 1.1 + + This handler is called when the user clicks on a link embedded in the text. + The link must be in rich text or HTML format and the + \a link string provides access to the particular link. +*/ QDeclarativeTextEdit::QDeclarativeTextEdit(QDeclarativeItem *parent) -: QDeclarativePaintedItem(*(new QDeclarativeTextEditPrivate), parent) +: QDeclarativeImplicitSizePaintedItem(*(new QDeclarativeTextEditPrivate), parent) { Q_D(QDeclarativeTextEdit); d->init(); @@ -363,11 +372,13 @@ void QDeclarativeTextEdit::setFont(const QFont &font) The text color. \qml -// green text using hexadecimal notation -TextEdit { color: "#00FF00"; ... } + // green text using hexadecimal notation + TextEdit { color: "#00FF00" } + \endqml -// steelblue text using SVG color name -TextEdit { color: "steelblue"; ... } + \qml + // steelblue text using SVG color name + TextEdit { color: "steelblue" } \endqml */ QColor QDeclarativeTextEdit::color() const @@ -455,6 +466,7 @@ void QDeclarativeTextEdit::setSelectedTextColor(const QColor &color) \o TextEdit.AlignLeft (default) \o TextEdit.AlignRight \o TextEdit.AlignHCenter + \o TextEdit.AlignJustify \endlist Valid values for \c verticalAlignment are: @@ -531,6 +543,17 @@ void QDeclarativeTextEdit::setWrapMode(WrapMode mode) } /*! + \qmlproperty int TextEdit::lineCount + + Returns the total number of lines in the textEdit item. +*/ +int QDeclarativeTextEdit::lineCount() const +{ + Q_D(const QDeclarativeTextEdit); + return d->lineCount; +} + +/*! \qmlproperty real TextEdit::paintedWidth Returns the width of the text, including the width past the width @@ -538,7 +561,8 @@ void QDeclarativeTextEdit::setWrapMode(WrapMode mode) */ qreal QDeclarativeTextEdit::paintedWidth() const { - return implicitWidth(); + Q_D(const QDeclarativeTextEdit); + return d->paintedSize.width(); } /*! @@ -549,7 +573,8 @@ qreal QDeclarativeTextEdit::paintedWidth() const */ qreal QDeclarativeTextEdit::paintedHeight() const { - return implicitHeight(); + Q_D(const QDeclarativeTextEdit); + return d->paintedSize.height(); } /*! @@ -583,37 +608,101 @@ int QDeclarativeTextEdit::positionAt(int x, int y) const return r; } +void QDeclarativeTextEdit::moveCursorSelection(int pos) +{ + //Note that this is the same as setCursorPosition but with the KeepAnchor flag set + Q_D(QDeclarativeTextEdit); + QTextCursor cursor = d->control->textCursor(); + if (cursor.position() == pos) + return; + cursor.setPosition(pos, QTextCursor::KeepAnchor); + d->control->setTextCursor(cursor); +} + /*! - \qmlmethod int TextEdit::moveCursorSelection(int pos) + \qmlmethod void TextEdit::moveCursorSelection(int position, SelectionMode mode = TextEdit.SelectCharacters) + \since Quick 1.1 - Moves the cursor to \a position and updates the selection accordingly. - (To only move the cursor, set the \l cursorPosition property.) + Moves the cursor to \a position and updates the selection according to the optional \a mode + parameter. (To only move the cursor, set the \l cursorPosition property.) When this method is called it additionally sets either the selectionStart or the selectionEnd (whichever was at the previous cursor position) to the specified position. This allows you to easily extend and contract the selected text range. + The selection mode specifies whether the selection is updated on a per character or a per word + basis. If not specified the selection mode will default to TextEdit.SelectCharacters. + + \list + \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at + the previous cursor position) to the specified position. + \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all + words between the specified postion and the previous cursor position. Words partially in the + range are included. + \endlist + For example, take this sequence of calls: \code cursorPosition = 5 - moveCursorSelection(9) - moveCursorSelection(7) + moveCursorSelection(9, TextEdit.SelectCharacters) + moveCursorSelection(7, TextEdit.SelectCharacters) \endcode This moves the cursor to position 5, extend the selection end from 5 to 9 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7 selected (the 6th and 7th characters). + + The same sequence with TextEdit.SelectWords will extend the selection start to a word boundary + before or on position 5 and extend the selection end to a word boundary on or past position 9. */ -void QDeclarativeTextEdit::moveCursorSelection(int pos) +void QDeclarativeTextEdit::moveCursorSelection(int pos, SelectionMode mode) { - //Note that this is the same as setCursorPosition but with the KeepAnchor flag set Q_D(QDeclarativeTextEdit); QTextCursor cursor = d->control->textCursor(); if (cursor.position() == pos) return; - cursor.setPosition(pos, QTextCursor::KeepAnchor); + if (mode == SelectCharacters) { + cursor.setPosition(pos, QTextCursor::KeepAnchor); + } else if (cursor.anchor() < pos || (cursor.anchor() == pos && cursor.position() < pos)) { + if (cursor.anchor() > cursor.position()) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + if (cursor.position() == cursor.anchor()) + cursor.movePosition(QTextCursor::PreviousWord, QTextCursor::MoveAnchor); + else + cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor); + } else { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::MoveAnchor); + } + + cursor.setPosition(pos, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + if (cursor.position() != pos) + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + } else if (cursor.anchor() > pos || (cursor.anchor() == pos && cursor.position() > pos)) { + if (cursor.anchor() < cursor.position()) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor); + } else { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + if (cursor.position() != cursor.anchor()) { + cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::MoveAnchor); + } + } + + cursor.setPosition(pos, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor); + if (cursor.position() != pos) { + cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor); + cursor.movePosition(QTextCursor::StartOfWord, QTextCursor::KeepAnchor); + } + } d->control->setTextCursor(cursor); } @@ -659,7 +748,7 @@ void QDeclarativeTextEdit::setCursorPosition(int pos) if (pos < 0 || pos > d->text.length()) return; QTextCursor cursor = d->control->textCursor(); - if (cursor.position() == pos) + if (cursor.position() == pos && cursor.anchor() == pos) return; cursor.setPosition(pos); d->control->setTextCursor(cursor); @@ -887,11 +976,41 @@ void QDeclarativeTextEdit::setSelectByMouse(bool on) Q_D(QDeclarativeTextEdit); if (d->selectByMouse != on) { d->selectByMouse = on; + setKeepMouseGrab(on); emit selectByMouseChanged(on); } } +/*! + \qmlproperty enum TextEdit::mouseSelectionMode + \since Quick 1.1 + + Specifies how text should be selected using a mouse. + + \list + \o TextEdit.SelectCharacters - The selection is updated with individual characters. (Default) + \o TextEdit.SelectWords - The selection is updated with whole words. + \endlist + + This property only applies when \l selectByMouse is true. +*/ + +QDeclarativeTextEdit::SelectionMode QDeclarativeTextEdit::mouseSelectionMode() const +{ + Q_D(const QDeclarativeTextEdit); + return d->mouseSelectionMode; +} + +void QDeclarativeTextEdit::setMouseSelectionMode(SelectionMode mode) +{ + Q_D(QDeclarativeTextEdit); + if (d->mouseSelectionMode != mode) { + d->mouseSelectionMode = mode; + d->control->setWordSelectionEnabled(mode == SelectWords); + emit mouseSelectionModeChanged(mode); + } +} /*! \qmlproperty bool TextEdit::readOnly @@ -907,12 +1026,13 @@ void QDeclarativeTextEdit::setReadOnly(bool r) if (r == isReadOnly()) return; + setFlag(QGraphicsItem::ItemAcceptsInputMethod, !r); - Qt::TextInteractionFlags flags = Qt::NoTextInteraction; + Qt::TextInteractionFlags flags = Qt::LinksAccessibleByMouse; if (r) { - flags = Qt::TextSelectableByMouse; + flags = flags | Qt::TextSelectableByMouse; } else { - flags = Qt::TextEditorInteraction; + flags = flags | Qt::TextEditorInteraction; } d->control->setTextInteractionFlags(flags); if (!r) @@ -1010,6 +1130,19 @@ void QDeclarativeTextEditPrivate::focusChanged(bool hasFocus) } /*! + \qmlmethod void TextEdit::deselect() + + Removes active text selection. +*/ +void QDeclarativeTextEdit::deselect() +{ + Q_D(QDeclarativeTextEdit); + QTextCursor c = d->control->textCursor(); + c.clearSelection(); + d->control->setTextCursor(c); +} + +/*! \qmlmethod void TextEdit::selectAll() Causes all text to be selected. @@ -1250,6 +1383,21 @@ void QDeclarativeTextEdit::updateImgCache(const QRectF &rf) filtering at the beginning of the animation and reenable it at the conclusion. */ +/*! + \qmlproperty bool TextEdit::canPaste + + Returns true if the TextEdit is writable and the content of the clipboard is + suitable for pasting into the TextEdit. + + \since QtQuick 1.1 +*/ + +bool QDeclarativeTextEdit::canPaste() const +{ + Q_D(const QDeclarativeTextEdit); + return d->canPaste; +} + void QDeclarativeTextEditPrivate::init() { Q_Q(QDeclarativeTextEdit); @@ -1261,6 +1409,8 @@ void QDeclarativeTextEditPrivate::init() control = new QTextControl(q); control->setIgnoreUnusedNavigationEvents(true); + control->setTextInteractionFlags(control->textInteractionFlags() | Qt::LinksAccessibleByMouse); + control->setDragEnabled(false); // QTextControl follows the default text color // defined by the platform, declarative text @@ -1279,6 +1429,11 @@ void QDeclarativeTextEditPrivate::init() QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SLOT(updateSelectionMarkers())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorPositionChanged())); QObject::connect(control, SIGNAL(cursorPositionChanged()), q, SIGNAL(cursorRectangleChanged())); + QObject::connect(control, SIGNAL(linkActivated(QString)), q, SIGNAL(linkActivated(QString))); +#ifndef QT_NO_CLIPBOARD + QObject::connect(q, SIGNAL(readOnlyChanged(bool)), q, SLOT(q_canPasteChanged())); + QObject::connect(QApplication::clipboard(), SIGNAL(dataChanged()), q, SLOT(q_canPasteChanged())); +#endif document = control->document(); document->setDefaultFont(font); @@ -1293,6 +1448,7 @@ void QDeclarativeTextEdit::q_textChanged() Q_D(QDeclarativeTextEdit); d->text = text(); updateSize(); + updateTotalLines(); updateMicroFocus(); emit textChanged(d->text); } @@ -1354,6 +1510,17 @@ QRectF QDeclarativeTextEdit::boundingRect() const return r.translated(0,d->yoff); } +qreal QDeclarativeTextEditPrivate::implicitWidth() const +{ + Q_Q(const QDeclarativeTextEdit); + if (!requireImplicitWidth) { + // We don't calculate implicitWidth unless it is required. + // We need to force a size update now to ensure implicitWidth is calculated + const_cast<QDeclarativeTextEditPrivate*>(this)->requireImplicitWidth = true; + const_cast<QDeclarativeTextEdit*>(q)->updateSize(); + } + return mImplicitWidth; +} //### we should perhaps be a bit smarter here -- depending on what has changed, we shouldn't // need to do all the calculations each time @@ -1361,16 +1528,27 @@ void QDeclarativeTextEdit::updateSize() { Q_D(QDeclarativeTextEdit); if (isComponentComplete()) { - QFontMetrics fm = QFontMetrics(d->font); - int dy = height(); + qreal naturalWidth = d->mImplicitWidth; // ### assumes that if the width is set, the text will fill to edges // ### (unless wrap is false, then clipping will occur) if (widthValid()) { + if (!d->requireImplicitWidth) { + emit implicitWidthChanged(); + // if the implicitWidth is used, then updateSize() has already been called (recursively) + if (d->requireImplicitWidth) + return; + } + if (d->requireImplicitWidth) { + d->document->setTextWidth(-1); + naturalWidth = d->document->idealWidth(); + } if (d->document->textWidth() != width()) d->document->setTextWidth(width()); } else { d->document->setTextWidth(-1); } + QFontMetrics fm = QFontMetrics(d->font); + int dy = height(); dy -= (int)d->document->size().height(); int nyoff; @@ -1395,12 +1573,15 @@ void QDeclarativeTextEdit::updateSize() if (!widthValid() && d->document->textWidth() != newWidth) d->document->setTextWidth(newWidth); // ### Text does not align if width is not set (QTextDoc bug) // ### Setting the implicitWidth triggers another updateSize(), and unless there are bindings nothing has changed. - setImplicitWidth(newWidth); + if (!widthValid()) + setImplicitWidth(newWidth); + else if (d->requireImplicitWidth) + setImplicitWidth(naturalWidth); qreal newHeight = d->document->isEmpty() ? fm.height() : (int)d->document->size().height(); setImplicitHeight(newHeight); - setContentsSize(QSize(newWidth, newHeight)); - + d->paintedSize = QSize(newWidth, newHeight); + setContentsSize(d->paintedSize); emit paintedSizeChanged(); } else { d->dirty = true; @@ -1408,6 +1589,26 @@ void QDeclarativeTextEdit::updateSize() emit update(); } +void QDeclarativeTextEdit::updateTotalLines() +{ + Q_D(QDeclarativeTextEdit); + + int subLines = 0; + + for (QTextBlock it = d->document->begin(); it != d->document->end(); it = it.next()) { + QTextLayout *layout = it.layout(); + if (!layout) + continue; + subLines += layout->lineCount()-1; + } + + int newTotalLines = d->document->lineCount() + subLines; + if (d->lineCount != newTotalLines) { + d->lineCount = newTotalLines; + emit lineCountChanged(); + } +} + void QDeclarativeTextEditPrivate::updateDefaultTextOption() { QTextOption opt = document->defaultTextOption(); @@ -1536,4 +1737,13 @@ void QDeclarativeTextEdit::focusInEvent(QFocusEvent *event) QDeclarativePaintedItem::focusInEvent(event); } +void QDeclarativeTextEdit::q_canPasteChanged() +{ + Q_D(QDeclarativeTextEdit); + bool old = d->canPaste; + d->canPaste = d->control->canPaste(); + if(old!=d->canPaste) + emit canPasteChanged(); +} + QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p.h index cff55f0..7785a7a 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p.h @@ -43,7 +43,7 @@ #define QDECLARATIVETEXTEDIT_H #include "private/qdeclarativetext_p.h" -#include "private/qdeclarativepainteditem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p.h" #include <QtGui/qtextdocument.h> #include <QtGui/qtextoption.h> @@ -58,13 +58,14 @@ QT_MODULE(Declarative) class QDeclarativeTextEditPrivate; -class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem +class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativeImplicitSizePaintedItem { Q_OBJECT Q_ENUMS(VAlignment) Q_ENUMS(HAlignment) Q_ENUMS(TextFormat) Q_ENUMS(WrapMode) + Q_ENUMS(SelectionMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) @@ -74,6 +75,7 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(HAlignment horizontalAlignment READ hAlign WRITE setHAlign NOTIFY horizontalAlignmentChanged) Q_PROPERTY(VAlignment verticalAlignment READ vAlign WRITE setVAlign NOTIFY verticalAlignmentChanged) Q_PROPERTY(WrapMode wrapMode READ wrapMode WRITE setWrapMode NOTIFY wrapModeChanged) + Q_PROPERTY(int lineCount READ lineCount NOTIFY lineCountChanged REVISION 1) Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedSizeChanged) Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedSizeChanged) Q_PROPERTY(TextFormat textFormat READ textFormat WRITE setTextFormat NOTIFY textFormatChanged) @@ -90,6 +92,8 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextEdit : public QDeclarativePaintedItem Q_PROPERTY(qreal textMargin READ textMargin WRITE setTextMargin NOTIFY textMarginChanged) Q_PROPERTY(Qt::InputMethodHints inputMethodHints READ inputMethodHints WRITE setInputMethodHints) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) + Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1) + Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) public: QDeclarativeTextEdit(QDeclarativeItem *parent=0); @@ -97,7 +101,8 @@ public: enum HAlignment { AlignLeft = Qt::AlignLeft, AlignRight = Qt::AlignRight, - AlignHCenter = Qt::AlignHCenter + AlignHCenter = Qt::AlignHCenter, + AlignJustify = Qt::AlignJustify // ### VERSIONING: Only in QtQuick 1.1 }; enum VAlignment { @@ -119,6 +124,11 @@ public: Wrap = QTextOption::WrapAtWordBoundaryOrAnywhere }; + enum SelectionMode { + SelectCharacters, + SelectWords + }; + Q_INVOKABLE void openSoftwareInputPanel(); Q_INVOKABLE void closeSoftwareInputPanel(); @@ -149,6 +159,8 @@ public: WrapMode wrapMode() const; void setWrapMode(WrapMode w); + int lineCount() const; + bool isCursorVisible() const; void setCursorVisible(bool on); @@ -175,6 +187,11 @@ public: bool selectByMouse() const; void setSelectByMouse(bool); + SelectionMode mouseSelectionMode() const; + void setMouseSelectionMode(SelectionMode mode); + + bool canPaste() const; + virtual void componentComplete(); /* FROM EDIT */ @@ -194,6 +211,7 @@ public: Q_INVOKABLE QRectF positionToRectangle(int) const; Q_INVOKABLE int positionAt(int x, int y) const; Q_INVOKABLE void moveCursorSelection(int pos); + Q_INVOKABLE Q_REVISION(1) void moveCursorSelection(int pos, SelectionMode mode); QRectF boundingRect() const; @@ -212,6 +230,7 @@ Q_SIGNALS: void horizontalAlignmentChanged(HAlignment alignment); void verticalAlignmentChanged(VAlignment alignment); void wrapModeChanged(); + void lineCountChanged(); void textFormatChanged(TextFormat textFormat); void readOnlyChanged(bool isReadOnly); void cursorVisibleChanged(bool isCursorVisible); @@ -220,11 +239,15 @@ Q_SIGNALS: void persistentSelectionChanged(bool isPersistentSelection); void textMarginChanged(qreal textMargin); void selectByMouseChanged(bool selectByMouse); + Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode); + Q_REVISION(1) void linkActivated(const QString &link); + Q_REVISION(1) void canPasteChanged(); public Q_SLOTS: void selectAll(); void selectWord(); void select(int start, int end); + Q_REVISION(1) void deselect(); #ifndef QT_NO_CLIPBOARD void cut(); void copy(); @@ -237,9 +260,11 @@ private Q_SLOTS: void updateSelectionMarkers(); void moveCursorDelegate(); void loadCursorDelegate(); + void q_canPasteChanged(); private: void updateSize(); + void updateTotalLines(); protected: virtual void geometryChanged(const QRectF &newGeometry, diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 3a45541..111cc02 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -54,7 +54,7 @@ // #include "qdeclarativeitem.h" -#include "private/qdeclarativepainteditem_p_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include <qdeclarative.h> @@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE class QTextLayout; class QTextDocument; class QTextControl; -class QDeclarativeTextEditPrivate : public QDeclarativePaintedItemPrivate +class QDeclarativeTextEditPrivate : public QDeclarativeImplicitSizePaintedItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeTextEdit) @@ -70,10 +70,10 @@ public: QDeclarativeTextEditPrivate() : color("black"), hAlign(QDeclarativeTextEdit::AlignLeft), vAlign(QDeclarativeTextEdit::AlignTop), imgDirty(true), dirty(false), richText(false), cursorVisible(false), focusOnPress(true), - showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true), textMargin(0.0), - lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), + showInputPanelOnFocus(true), clickCausedFocus(false), persistentSelection(true), requireImplicitWidth(false), + textMargin(0.0), lastSelectionStart(0), lastSelectionEnd(0), cursorComponent(0), cursor(0), format(QDeclarativeTextEdit::AutoText), document(0), wrapMode(QDeclarativeTextEdit::NoWrap), - selectByMouse(false), + mouseSelectionMode(QDeclarativeTextEdit::SelectCharacters), selectByMouse(false), canPaste(false), yoff(0) { #ifdef Q_OS_SYMBIAN @@ -88,6 +88,7 @@ public: void updateDefaultTextOption(); void relayoutDocument(); void updateSelection(); + qreal implicitWidth() const; void focusChanged(bool); QString text; @@ -110,6 +111,7 @@ public: bool showInputPanelOnFocus : 1; bool clickCausedFocus : 1; bool persistentSelection : 1; + bool requireImplicitWidth:1; qreal textMargin; int lastSelectionStart; int lastSelectionEnd; @@ -119,8 +121,12 @@ public: QTextDocument *document; QTextControl *control; QDeclarativeTextEdit::WrapMode wrapMode; + QDeclarativeTextEdit::SelectionMode mouseSelectionMode; + int lineCount; bool selectByMouse; + bool canPaste; int yoff; + QSize paintedSize; }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index ef3404f..3c95ab8 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -50,6 +50,8 @@ #include <QApplication> #include <QFontMetrics> #include <QPainter> +#include <QTextBoundaryFinder> +#include <qstyle.h> #ifndef QT_NO_LINEEDIT @@ -75,7 +77,7 @@ QT_BEGIN_NAMESPACE \sa TextEdit, Text, {declarative/text/textselection}{Text Selection example} */ QDeclarativeTextInput::QDeclarativeTextInput(QDeclarativeItem* parent) - : QDeclarativePaintedItem(*(new QDeclarativeTextInputPrivate), parent) + : QDeclarativeImplicitSizePaintedItem(*(new QDeclarativeTextInputPrivate), parent) { Q_D(QDeclarativeTextInput); d->init(); @@ -353,6 +355,16 @@ void QDeclarativeTextInput::setHAlign(HAlignment align) emit horizontalAlignmentChanged(d->hAlign); } +/*! + \qmlproperty bool TextInput::readOnly + + Sets whether user input can modify the contents of the TextInput. + + If readOnly is set to true, then user input will not affect the text + property. Any bindings or attempts to set the text property will still + work. +*/ + bool QDeclarativeTextInput::isReadOnly() const { Q_D(const QDeclarativeTextInput); @@ -365,11 +377,20 @@ void QDeclarativeTextInput::setReadOnly(bool ro) if (d->control->isReadOnly() == ro) return; + setFlag(QGraphicsItem::ItemAcceptsInputMethod, !ro); d->control->setReadOnly(ro); emit readOnlyChanged(ro); } +/*! + \qmlproperty int TextInput::maximumLength + The maximum permitted length of the text in the TextInput. + + If the text is too long, it is truncated at the limit. + + By default, this property contains a value of 32767. +*/ int QDeclarativeTextInput::maxLength() const { Q_D(const QDeclarativeTextInput); @@ -529,10 +550,10 @@ void QDeclarativeTextInput::select(int start, int end) It is equivalent to the following snippet, but is faster and easier to use. - \qml + \js myTextInput.text.toString().substring(myTextInput.selectionStart, myTextInput.selectionEnd); - \endqml + \endjs */ QString QDeclarativeTextInput::selectedText() const { @@ -593,6 +614,11 @@ void QDeclarativeTextInput::setAutoScroll(bool b) \ingroup qml-basic-visual-elements This element provides a validator for integer values. + + IntValidator uses the \l {QLocale::setDefault()}{default locale} to interpret the number and + will accept locale specific digits, group separators, and positive and negative signs. In + addition, IntValidator is always guaranteed to accept a number formatted according to the "C" + locale. */ /*! \qmlproperty int IntValidator::top @@ -750,6 +776,15 @@ bool QDeclarativeTextInput::hasAcceptableInput() const } /*! + \qmlsignal TextInput::onAccepted() + + This handler is called when the Return or Enter key is pressed. + Note that if there is a \l validator or \l inputMask set on the text + input, the handler will only be emitted if the input is in an acceptable + state. +*/ + +/*! \qmlproperty enumeration TextInput::echoMode Specifies how the text should be displayed in the TextInput. @@ -954,6 +989,7 @@ void QDeclarativeTextInput::inputMethodEvent(QInputMethodEvent *ev) } else { d->control->processInputMethodEvent(ev); updateSize(); + d->updateHorizontalScroll(); } if (!ev->isAccepted()) QDeclarativePaintedItem::inputMethodEvent(ev); @@ -992,6 +1028,10 @@ void QDeclarativeTextInput::mousePressEvent(QGraphicsSceneMouseEvent *event) } } } + if (d->selectByMouse) { + setKeepMouseGrab(false); + d->pressPos = event->pos(); + } bool mark = event->modifiers() & Qt::ShiftModifier; int cursor = d->xToPos(event->pos().x()); d->control->moveCursor(cursor, mark); @@ -1002,7 +1042,9 @@ void QDeclarativeTextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); if (d->selectByMouse) { - d->control->moveCursor(d->xToPos(event->pos().x()), true); + if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance()) + setKeepMouseGrab(true); + moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode); event->setAccepted(true); } else { QDeclarativePaintedItem::mouseMoveEvent(event); @@ -1016,6 +1058,8 @@ Handles the given mouse \a event. void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_D(QDeclarativeTextInput); + if (d->selectByMouse) + setKeepMouseGrab(false); if (!d->showInputPanelOnFocus) { // input panel on click if (d->focusOnPress && !isReadOnly() && boundingRect().contains(event->pos())) { if (QGraphicsView * view = qobject_cast<QGraphicsView*>(qApp->focusWidget())) { @@ -1031,6 +1075,15 @@ void QDeclarativeTextInput::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QDeclarativePaintedItem::mouseReleaseEvent(event); } +bool QDeclarativeTextInput::sceneEvent(QEvent *event) +{ + bool rv = QDeclarativeItem::sceneEvent(event); + if (event->type() == QEvent::UngrabMouse) { + setKeepMouseGrab(false); + } + return rv; +} + bool QDeclarativeTextInput::event(QEvent* ev) { Q_D(QDeclarativeTextInput); @@ -1072,13 +1125,15 @@ int QDeclarativeTextInputPrivate::calculateTextWidth() void QDeclarativeTextInputPrivate::updateHorizontalScroll() { Q_Q(QDeclarativeTextInput); - int cix = qRound(control->cursorToX()); + const int preeditLength = control->preeditAreaText().length(); + int cix = qRound(control->cursorToX(control->cursor() + preeditLength)); QRect br(q->boundingRect().toRect()); int widthUsed = calculateTextWidth(); + Qt::Alignment va = QStyle::visualAlignment(control->layoutDirection(), QFlag(Qt::Alignment(hAlign))); if (autoScroll) { if (widthUsed <= br.width()) { // text fits in br; use hscroll for alignment - switch (hAlign & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { + switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { case Qt::AlignRight: hscroll = widthUsed - br.width() - 1; break; @@ -1101,13 +1156,26 @@ void QDeclarativeTextInputPrivate::updateHorizontalScroll() // right hscroll = widthUsed - br.width() + 1; } + if (preeditLength > 0) { + // check to ensure long pre-edit text doesn't push the cursor + // off to the left + cix = qRound(control->cursorToX( + control->cursor() + qMax(0, control->preeditCursor() - 1))); + if (cix < hscroll) + hscroll = cix; + } } else { - if(hAlign == QDeclarativeTextInput::AlignRight){ + switch (va & ~(Qt::AlignAbsolute|Qt::AlignVertical_Mask)) { + case Qt::AlignRight: hscroll = q->width() - widthUsed; - }else if(hAlign == QDeclarativeTextInput::AlignHCenter){ + break; + case Qt::AlignHCenter: hscroll = (q->width() - widthUsed) / 2; - } else { + break; + default: + // Left hscroll = 0; + break; } } } @@ -1169,6 +1237,17 @@ QVariant QDeclarativeTextInput::inputMethodQuery(Qt::InputMethodQuery property) } /*! + \qmlmethod void TextInput::deselect() + + Removes active text selection. +*/ +void QDeclarativeTextInput::deselect() +{ + Q_D(QDeclarativeTextInput); + d->control->deselect(); +} + +/*! \qmlmethod void TextInput::selectAll() Causes all text to be selected. @@ -1211,7 +1290,8 @@ void QDeclarativeTextInput::copy() void QDeclarativeTextInput::paste() { Q_D(QDeclarativeTextInput); - d->control->paste(); + if(!d->control->isReadOnly()) + d->control->paste(); } #endif // QT_NO_CLIPBOARD @@ -1310,35 +1390,137 @@ void QDeclarativeTextInput::setSelectByMouse(bool on) } } +/*! + \qmlproperty enum TextInput::mouseSelectionMode + \since Quick 1.1 + + Specifies how text should be selected using a mouse. + + \list + \o TextInput.SelectCharacters - The selection is updated with individual characters. (Default) + \o TextInput.SelectWords - The selection is updated with whole words. + \endlist + + This property only applies when \l selectByMouse is true. +*/ + +QDeclarativeTextInput::SelectionMode QDeclarativeTextInput::mouseSelectionMode() const +{ + Q_D(const QDeclarativeTextInput); + return d->mouseSelectionMode; +} + +void QDeclarativeTextInput::setMouseSelectionMode(SelectionMode mode) +{ + Q_D(QDeclarativeTextInput); + if (d->mouseSelectionMode != mode) { + d->mouseSelectionMode = mode; + emit mouseSelectionModeChanged(mode); + } +} + +bool QDeclarativeTextInput::canPaste() const +{ + Q_D(const QDeclarativeTextInput); + return d->canPaste; +} + +void QDeclarativeTextInput::moveCursorSelection(int position) +{ + Q_D(QDeclarativeTextInput); + d->control->moveCursor(position, true); + d->updateHorizontalScroll(); +} /*! - \qmlmethod void TextInput::moveCursorSelection(int position) + \qmlmethod void TextInput::moveCursorSelection(int position, SelectionMode mode = TextInput.SelectCharacters) + \since Quick 1.1 - Moves the cursor to \a position and updates the selection accordingly. - (To only move the cursor, set the \l cursorPosition property.) + Moves the cursor to \a position and updates the selection according to the optional \a mode + parameter. (To only move the cursor, set the \l cursorPosition property.) When this method is called it additionally sets either the selectionStart or the selectionEnd (whichever was at the previous cursor position) to the specified position. This allows you to easily extend and contract the selected text range. + The selection mode specifies whether the selection is updated on a per character or a per word + basis. If not specified the selection mode will default to TextInput.SelectCharacters. + + \list + \o TextEdit.SelectCharacters - Sets either the selectionStart or selectionEnd (whichever was at + the previous cursor position) to the specified position. + \o TextEdit.SelectWords - Sets the selectionStart and selectionEnd to include all + words between the specified postion and the previous cursor position. Words partially in the + range are included. + \endlist + For example, take this sequence of calls: \code cursorPosition = 5 - moveCursorSelection(9) - moveCursorSelection(7) + moveCursorSelection(9, TextInput.SelectCharacters) + moveCursorSelection(7, TextInput.SelectCharacters) \endcode This moves the cursor to position 5, extend the selection end from 5 to 9 and then retract the selection end from 9 to 7, leaving the text from position 5 to 7 selected (the 6th and 7th characters). + + The same sequence with TextInput.SelectWords will extend the selection start to a word boundary + before or on position 5 and extend the selection end to a word boundary on or past position 9. */ -void QDeclarativeTextInput::moveCursorSelection(int position) +void QDeclarativeTextInput::moveCursorSelection(int pos, SelectionMode mode) { Q_D(QDeclarativeTextInput); - d->control->moveCursor(position, true); - d->updateHorizontalScroll(); + + if (mode == SelectCharacters) { + d->control->moveCursor(pos, true); + } else if (pos != d->control->cursor()){ + const int cursor = d->control->cursor(); + int anchor; + if (!d->control->hasSelectedText()) + anchor = d->control->cursor(); + else if (d->control->selectionStart() == d->control->cursor()) + anchor = d->control->selectionEnd(); + else + anchor = d->control->selectionStart(); + + if (anchor < pos || (anchor == pos && cursor < pos)) { + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + finder.setPosition(anchor); + + const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); + if (!(reasons & QTextBoundaryFinder::StartWord) + || ((reasons & QTextBoundaryFinder::EndWord) && anchor > cursor)) { + finder.toPreviousBoundary(); + } + anchor = finder.position(); + + finder.setPosition(pos); + if (!finder.isAtBoundary()) + finder.toNextBoundary(); + + d->control->setSelection(anchor, finder.position() - anchor); + } else if (anchor > pos || (anchor == pos && cursor > pos)) { + QTextBoundaryFinder finder(QTextBoundaryFinder::Word, d->control->text()); + finder.setPosition(anchor); + + const QTextBoundaryFinder::BoundaryReasons reasons = finder.boundaryReasons(); + if (!(reasons & QTextBoundaryFinder::EndWord) + || ((reasons & QTextBoundaryFinder::StartWord) && anchor < cursor)) { + finder.toNextBoundary(); + } + + anchor = finder.position(); + + finder.setPosition(pos); + if (!finder.isAtBoundary()) + finder.toPreviousBoundary(); + + d->control->setSelection(anchor, finder.position() - anchor); + } + } } /*! @@ -1474,6 +1656,12 @@ void QDeclarativeTextInputPrivate::init() q, SIGNAL(accepted())); q->connect(control, SIGNAL(updateNeeded(QRect)), q, SLOT(updateRect(QRect))); +#ifndef QT_NO_CLIPBOARD + q->connect(q, SIGNAL(readOnlyChanged(bool)), + q, SLOT(q_canPasteChanged())); + q->connect(QApplication::clipboard(), SIGNAL(dataChanged()), + q, SLOT(q_canPasteChanged())); +#endif // QT_NO_CLIPBOARD q->updateSize(); oldValidity = control->hasAcceptableInput(); lastSelectionStart = 0; @@ -1575,6 +1763,17 @@ void QDeclarativeTextInput::updateSize(bool needsRedraw) } } +void QDeclarativeTextInput::q_canPasteChanged() +{ + Q_D(QDeclarativeTextInput); + bool old = d->canPaste; +#ifndef QT_NO_CLIPBOARD + d->canPaste = !d->control->isReadOnly() && QApplication::clipboard()->text().length() != 0; +#endif + if(d->canPaste != old) + emit canPasteChanged(); +} + QT_END_NAMESPACE #endif // QT_NO_LINEEDIT diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p.h index abea0e8..e1e66a9 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p.h @@ -43,7 +43,7 @@ #define QDECLARATIVETEXTINPUT_H #include "private/qdeclarativetext_p.h" -#include "private/qdeclarativepainteditem_p.h" +#include "private/qdeclarativeimplicitsizeitem_p.h" #include <QGraphicsSceneMouseEvent> #include <QIntValidator> @@ -58,11 +58,12 @@ QT_MODULE(Declarative) class QDeclarativeTextInputPrivate; class QValidator; -class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativePaintedItem +class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativeImplicitSizePaintedItem { Q_OBJECT Q_ENUMS(HAlignment) Q_ENUMS(EchoMode) + Q_ENUMS(SelectionMode) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) @@ -94,6 +95,8 @@ class Q_AUTOTEST_EXPORT QDeclarativeTextInput : public QDeclarativePaintedItem Q_PROPERTY(QString displayText READ displayText NOTIFY displayTextChanged) Q_PROPERTY(bool autoScroll READ autoScroll WRITE setAutoScroll NOTIFY autoScrollChanged) Q_PROPERTY(bool selectByMouse READ selectByMouse WRITE setSelectByMouse NOTIFY selectByMouseChanged) + Q_PROPERTY(SelectionMode mouseSelectionMode READ mouseSelectionMode WRITE setMouseSelectionMode NOTIFY mouseSelectionModeChanged REVISION 1) + Q_PROPERTY(bool canPaste READ canPaste NOTIFY canPasteChanged REVISION 1) public: QDeclarativeTextInput(QDeclarativeItem* parent=0); @@ -112,10 +115,16 @@ public: AlignHCenter = Qt::AlignHCenter }; + enum SelectionMode { + SelectCharacters, + SelectWords + }; + //Auxilliary functions needed to control the TextInput from QML Q_INVOKABLE int positionAt(int x) const; Q_INVOKABLE QRectF positionToRectangle(int pos) const; Q_INVOKABLE void moveCursorSelection(int pos); + Q_INVOKABLE Q_REVISION(1) void moveCursorSelection(int pos, SelectionMode mode); Q_INVOKABLE void openSoftwareInputPanel(); Q_INVOKABLE void closeSoftwareInputPanel(); @@ -184,12 +193,16 @@ public: bool selectByMouse() const; void setSelectByMouse(bool); + SelectionMode mouseSelectionMode() const; + void setMouseSelectionMode(SelectionMode mode); + bool hasAcceptableInput() const; void drawContents(QPainter *p,const QRect &r); QVariant inputMethodQuery(Qt::InputMethodQuery property) const; QRectF boundingRect() const; + bool canPaste() const; Q_SIGNALS: void textChanged(); @@ -216,6 +229,8 @@ Q_SIGNALS: void activeFocusOnPressChanged(bool activeFocusOnPress); void autoScrollChanged(bool autoScroll); void selectByMouseChanged(bool selectByMouse); + Q_REVISION(1) void mouseSelectionModeChanged(SelectionMode mode); + Q_REVISION(1) void canPasteChanged(); protected: virtual void geometryChanged(const QRectF &newGeometry, @@ -225,6 +240,7 @@ protected: void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); + bool sceneEvent(QEvent *event); void keyPressEvent(QKeyEvent* ev); void inputMethodEvent(QInputMethodEvent *); bool event(QEvent *e); @@ -234,6 +250,7 @@ public Q_SLOTS: void selectAll(); void selectWord(); void select(int start, int end); + Q_REVISION(1) void deselect(); #ifndef QT_NO_CLIPBOARD void cut(); void copy(); @@ -248,6 +265,7 @@ private Q_SLOTS: void moveCursor(); void cursorPosChanged(); void updateRect(const QRect &r = QRect()); + void q_canPasteChanged(); private: Q_DECLARE_PRIVATE_D(QGraphicsItem::d_ptr.data(), QDeclarativeTextInput) diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 16827b3..f7446b4 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -44,7 +44,7 @@ #include "private/qdeclarativetextinput_p.h" -#include "private/qdeclarativepainteditem_p_p.h" +#include "private/qdeclarativeimplicitsizeitem_p_p.h" #include <qdeclarative.h> @@ -66,16 +66,17 @@ QT_BEGIN_NAMESPACE -class QDeclarativeTextInputPrivate : public QDeclarativePaintedItemPrivate +class Q_AUTOTEST_EXPORT QDeclarativeTextInputPrivate : public QDeclarativeImplicitSizePaintedItemPrivate { Q_DECLARE_PUBLIC(QDeclarativeTextInput) public: QDeclarativeTextInputPrivate() : control(new QLineControl(QString())), color((QRgb)0), style(QDeclarativeText::Normal), styleColor((QRgb)0), hAlign(QDeclarativeTextInput::AlignLeft), + mouseSelectionMode(QDeclarativeTextInput::SelectCharacters), hscroll(0), oldScroll(0), focused(false), focusOnPress(true), showInputPanelOnFocus(true), clickCausedFocus(false), cursorVisible(false), - autoScroll(true), selectByMouse(false) + autoScroll(true), selectByMouse(false), canPaste(false) { #ifdef Q_OS_SYMBIAN if (QSysInfo::symbianVersion() == QSysInfo::SV_SF_1 || QSysInfo::symbianVersion() == QSysInfo::SV_SF_3) { @@ -114,8 +115,10 @@ public: QDeclarativeText::TextStyle style; QColor styleColor; QDeclarativeTextInput::HAlignment hAlign; + QDeclarativeTextInput::SelectionMode mouseSelectionMode; QPointer<QDeclarativeComponent> cursorComponent; QPointer<QDeclarativeItem> cursorItem; + QPointF pressPos; int lastSelectionStart; int lastSelectionEnd; @@ -131,6 +134,11 @@ public: bool cursorVisible; bool autoScroll; bool selectByMouse; + bool canPaste; + + static inline QDeclarativeTextInputPrivate *get(QDeclarativeTextInput *t) { + return t->d_func(); + } }; QT_END_NAMESPACE diff --git a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp index 065a388..a8082f8 100644 --- a/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp +++ b/src/declarative/graphicsitems/qdeclarativevisualitemmodel.cpp @@ -557,8 +557,9 @@ QDeclarativeVisualDataModelData::~QDeclarativeVisualDataModelData() void QDeclarativeVisualDataModelData::ensureProperties() { QDeclarativeVisualDataModelPrivate *modelPriv = QDeclarativeVisualDataModelPrivate::get(m_model); - if (modelPriv->m_metaDataCacheable && !modelPriv->m_metaDataCreated) { - modelPriv->createMetaData(); + if (modelPriv->m_metaDataCacheable) { + if (!modelPriv->m_metaDataCreated) + modelPriv->createMetaData(); if (modelPriv->m_metaDataCreated) m_meta->setCached(true); } @@ -1076,7 +1077,7 @@ QDeclarativeItem *QDeclarativeVisualDataModel::item(int index, const QByteArray } else { delete data; delete ctxt; - qmlInfo(this, d->m_delegate->errors()) << "Error creating delgate"; + qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate"; } } QDeclarativeItem *item = qobject_cast<QDeclarativeItem *>(nobj); diff --git a/src/declarative/qml/qdeclarative.h b/src/declarative/qml/qdeclarative.h index 3017385..5da7901 100644 --- a/src/declarative/qml/qdeclarative.h +++ b/src/declarative/qml/qdeclarative.h @@ -113,6 +113,7 @@ int qmlRegisterType() 0, 0, + 0, 0 }; @@ -148,6 +149,7 @@ int qmlRegisterUncreatableType(const char *uri, int versionMajor, int versionMin 0, 0, + 0, 0 }; @@ -181,12 +183,82 @@ int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const c 0, 0, + 0, 0 }; return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); } +template<typename T, int metaObjectRevision> +int qmlRegisterType(const char *uri, int versionMajor, int versionMinor, const char *qmlName) +{ + QByteArray name(T::staticMetaObject.className()); + + QByteArray pointerName(name + '*'); + QByteArray listName("QDeclarativeListProperty<" + name + ">"); + + QDeclarativePrivate::RegisterType type = { + 1, + + qRegisterMetaType<T *>(pointerName.constData()), + qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), + sizeof(T), QDeclarativePrivate::createInto<T>, + QString(), + + uri, versionMajor, versionMinor, qmlName, &T::staticMetaObject, + + QDeclarativePrivate::attachedPropertiesFunc<T>(), + QDeclarativePrivate::attachedPropertiesMetaObject<T>(), + + QDeclarativePrivate::StaticCastSelector<T,QDeclarativeParserStatus>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueSource>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueInterceptor>::cast(), + + 0, 0, + + 0, + metaObjectRevision + }; + + return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); +} + +template<typename T, int metaObjectRevision> +int qmlRegisterRevision(const char *uri, int versionMajor, int versionMinor) +{ + QByteArray name(T::staticMetaObject.className()); + + QByteArray pointerName(name + '*'); + QByteArray listName("QDeclarativeListProperty<" + name + ">"); + + QDeclarativePrivate::RegisterType type = { + 1, + + qRegisterMetaType<T *>(pointerName.constData()), + qRegisterMetaType<QDeclarativeListProperty<T> >(listName.constData()), + sizeof(T), QDeclarativePrivate::createInto<T>, + QString(), + + uri, versionMajor, versionMinor, 0, &T::staticMetaObject, + + QDeclarativePrivate::attachedPropertiesFunc<T>(), + QDeclarativePrivate::attachedPropertiesMetaObject<T>(), + + QDeclarativePrivate::StaticCastSelector<T,QDeclarativeParserStatus>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueSource>::cast(), + QDeclarativePrivate::StaticCastSelector<T,QDeclarativePropertyValueInterceptor>::cast(), + + 0, 0, + + 0, + metaObjectRevision + }; + + return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); +} + + template<typename T, typename E> int qmlRegisterExtendedType() { @@ -214,6 +286,7 @@ int qmlRegisterExtendedType() QDeclarativePrivate::createParent<E>, &E::staticMetaObject, + 0, 0 }; @@ -255,6 +328,7 @@ int qmlRegisterExtendedType(const char *uri, int versionMajor, int versionMinor, QDeclarativePrivate::createParent<E>, &E::staticMetaObject, + 0, 0 }; @@ -309,7 +383,8 @@ int qmlRegisterCustomType(const char *uri, int versionMajor, int versionMinor, 0, 0, - parser + parser, + 0 }; return QDeclarativePrivate::qmlregister(QDeclarativePrivate::TypeRegistration, &type); diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index d9dff44..a5bd604 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -46,9 +46,11 @@ #include "qdeclarativecontext.h" #include "qdeclarativeinfo.h" #include "private/qdeclarativecontext_p.h" +#include "private/qdeclarativecompiler_p.h" #include "private/qdeclarativedata_p.h" #include "private/qdeclarativestringconverters_p.h" #include "private/qdeclarativestate_p_p.h" +#include "private/qdeclarativedebugtrace_p.h" #include <QVariant> #include <QtCore/qdebug.h> @@ -207,6 +209,8 @@ void QDeclarativeAbstractBinding::setEnabled(bool enabled, QDeclarativePropertyP if (enabled) update(flags); } +QDeclarativeBinding::Identifier QDeclarativeBinding::Invalid = -1; + void QDeclarativeBindingPrivate::refresh() { Q_Q(QDeclarativeBinding); @@ -232,6 +236,28 @@ QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, Q setNotifyOnValueChanged(true); } +QDeclarativeBinding * +QDeclarativeBinding::createBinding(Identifier id, QObject *obj, QDeclarativeContext *ctxt, + const QString &url, int lineNumber, QObject *parent) +{ + if (id < 0) + return 0; + + QDeclarativeContextData *ctxtdata = QDeclarativeContextData::get(ctxt); + + QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(qmlEngine(obj)); + QDeclarativeCompiledData *cdata = 0; + QDeclarativeTypeData *typeData = 0; + if (engine && ctxtdata && !ctxtdata->url.isEmpty()) { + typeData = engine->typeLoader.get(ctxtdata->url); + cdata = typeData->compiledData(); + } + QDeclarativeBinding *rv = cdata ? new QDeclarativeBinding((void*)cdata->datas.at(id).constData(), cdata, obj, ctxtdata, url, lineNumber, parent) : 0; + if (typeData) + typeData->release(); + return rv; +} + QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDeclarativeContext *ctxt, QObject *parent) : QDeclarativeExpression(QDeclarativeContextData::get(ctxt), obj, str, *new QDeclarativeBindingPrivate) @@ -248,6 +274,13 @@ QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDecl setNotifyOnValueChanged(true); } +QDeclarativeBinding::QDeclarativeBinding(const QScriptValue &func, QObject *obj, QDeclarativeContextData *ctxt, QObject *parent) +: QDeclarativeExpression(ctxt, obj, func, *new QDeclarativeBindingPrivate) +{ + setParent(parent); + setNotifyOnValueChanged(true); +} + QDeclarativeBinding::~QDeclarativeBinding() { } @@ -266,6 +299,34 @@ QDeclarativeProperty QDeclarativeBinding::property() const return d->property; } +void QDeclarativeBinding::setEvaluateFlags(EvaluateFlags flags) +{ + Q_D(QDeclarativeBinding); + d->setEvaluateFlags(QDeclarativeQtScriptExpression::EvaluateFlags(static_cast<int>(flags))); +} + +QDeclarativeBinding::EvaluateFlags QDeclarativeBinding::evaluateFlags() const +{ + Q_D(const QDeclarativeBinding); + return QDeclarativeBinding::EvaluateFlags(static_cast<int>(d->evaluateFlags())); +} + + +class QDeclarativeBindingProfiler { +public: + QDeclarativeBindingProfiler(QDeclarativeBinding *bind) + { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Binding, bind->expression()); + QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Binding, bind->sourceFile(), bind->lineNumber()); + } + + ~QDeclarativeBindingProfiler() + { + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); + } +}; + void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) { Q_D(QDeclarativeBinding); @@ -274,6 +335,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags) return; if (!d->updating) { + QDeclarativeBindingProfiler prof(this); d->updating = true; bool wasDeleted = false; d->deleted = &wasDeleted; diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 56a5d77..0260b95 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -147,14 +147,21 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBinding : public QDeclarativeExpr { Q_OBJECT public: + enum EvaluateFlag { RequiresThisObject = 0x01 }; + Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag) + QDeclarativeBinding(const QString &, QObject *, QDeclarativeContext *, QObject *parent=0); QDeclarativeBinding(const QString &, QObject *, QDeclarativeContextData *, QObject *parent=0); QDeclarativeBinding(void *, QDeclarativeRefCount *, QObject *, QDeclarativeContextData *, const QString &, int, QObject *parent); + QDeclarativeBinding(const QScriptValue &, QObject *, QDeclarativeContextData *, QObject *parent=0); void setTarget(const QDeclarativeProperty &); QDeclarativeProperty property() const; + void setEvaluateFlags(EvaluateFlags flags); + EvaluateFlags evaluateFlags() const; + bool enabled() const; // Inherited from QDeclarativeAbstractBinding @@ -162,6 +169,10 @@ public: virtual void update(QDeclarativePropertyPrivate::WriteFlags flags); virtual QString expression() const; + typedef int Identifier; + static Identifier Invalid; + static QDeclarativeBinding *createBinding(Identifier, QObject *, QDeclarativeContext *, const QString &, int, QObject *parent=0); + public Q_SLOTS: void update() { update(QDeclarativePropertyPrivate::DontRemoveBinding); } @@ -173,6 +184,8 @@ private: Q_DECLARE_PRIVATE(QDeclarativeBinding) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeBinding::EvaluateFlags) + QT_END_NAMESPACE Q_DECLARE_METATYPE(QDeclarativeBinding*) diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp index d039c68..28dfea9 100644 --- a/src/declarative/qml/qdeclarativeboundsignal.cpp +++ b/src/declarative/qml/qdeclarativeboundsignal.cpp @@ -49,7 +49,9 @@ #include "qdeclarative.h" #include "qdeclarativecontext.h" #include "private/qdeclarativeglobal_p.h" +#include "private/qdeclarativedebugtrace_p.h" +#include <QtCore/qstringbuilder.h> #include <QtCore/qdebug.h> QT_BEGIN_NAMESPACE @@ -165,6 +167,13 @@ QDeclarativeBoundSignal *QDeclarativeBoundSignal::cast(QObject *o) int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) { if (c == QMetaObject::InvokeMetaMethod && id == evaluateIdx) { + if (!m_expression) + return -1; + if (QDeclarativeDebugService::isDebuggingEnabled()) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::HandlingSignal); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::HandlingSignal, QLatin1String(m_signal.signature()) % QLatin1String(": ") % m_expression->expression()); + QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::HandlingSignal, m_expression->sourceFile(), m_expression->lineNumber()); + } m_isEvaluating = true; if (!m_paramsValid) { if (!m_signal.parameterTypes().isEmpty()) @@ -180,6 +189,7 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) } if (m_params) m_params->clearValues(); m_isEvaluating = false; + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::HandlingSignal); return -1; } else { return QObject::qt_metacall(c, id, a); @@ -187,13 +197,12 @@ int QDeclarativeBoundSignal::qt_metacall(QMetaObject::Call c, int id, void **a) } QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMetaMethod &method, - QObject *parent) + QObject *parent) : QObject(parent), types(0), values(0) { MetaObject *mo = new MetaObject(this); // ### Optimize! - // ### Ensure only supported types are allowed, otherwise it might crash QMetaObjectBuilder mob; mob.setSuperClass(&QDeclarativeBoundSignalParameters::staticMetaObject); mob.setClassName("QDeclarativeBoundSignalParameters"); @@ -216,9 +225,15 @@ QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMeta QMetaPropertyBuilder prop = mob.addProperty(name, "QObject*"); prop.setWritable(false); } else { - types[ii] = t; - QMetaPropertyBuilder prop = mob.addProperty(name, type); - prop.setWritable(false); + if (QDeclarativeMetaType::canCopy(t)) { + types[ii] = t; + QMetaPropertyBuilder prop = mob.addProperty(name, type); + prop.setWritable(false); + } else { + types[ii] = 0x80000000 | t; + QMetaPropertyBuilder prop = mob.addProperty(name, "QVariant"); + prop.setWritable(false); + } } } myMetaObject = mob.toMetaObject(); @@ -249,7 +264,11 @@ int QDeclarativeBoundSignalParameters::metaCall(QMetaObject::Call c, int id, voi return -1; if (c == QMetaObject::ReadProperty && id >= 1) { - QDeclarativeMetaType::copy(types[id - 1], a[0], values[id]); + if (types[id - 1] & 0x80000000) { + *((QVariant *)a[0]) = QVariant(types[id - 1] & 0x7FFFFFFF, values[id]); + } else { + QDeclarativeMetaType::copy(types[id - 1], a[0], values[id]); + } return -1; } else { return qt_metacall(c, id, a); diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp index 9db24de..a6fcce4 100644 --- a/src/declarative/qml/qdeclarativecompiledbindings.cpp +++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ // #define COMPILEDBINDINGS_DEBUG +// #define REGISTER_CLEANUP_DEBUG #include "private/qdeclarativecompiledbindings_p.h" @@ -54,6 +55,7 @@ #include <private/qdeclarativeanchors_p_p.h> #include <private/qdeclarativeglobal_p.h> #include <private/qdeclarativefastproperties_p.h> +#include <private/qdeclarativedebugtrace_p.h> QT_BEGIN_NAMESPACE @@ -170,6 +172,24 @@ struct Register { int type; // Optional type void *data[2]; // Object stored here + +#ifdef REGISTER_CLEANUP_DEBUG + Register() { + type = 0; + } + + ~Register() { + int allowedTypes[] = { QMetaType::QObjectStar, QMetaType::QReal, QMetaType::Int, QMetaType::Bool, 0 }; + bool found = (type == 0); + int *ctype = allowedTypes; + while (!found && *ctype) { + found = (*ctype == type); + ++ctype; + } + if (!found) + qWarning("Register leaked of type %d", type); + } +#endif }; } @@ -302,7 +322,9 @@ void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarati void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding); parent->run(this, flags); + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding); } void QDeclarativeCompiledBindingsPrivate::Binding::destroy() @@ -1409,10 +1431,16 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, QML_BEGIN_INSTR(CleanupString) registers[instr->cleanup.reg].getstringptr()->~QString(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif QML_END_INSTR(CleanupString) QML_BEGIN_INSTR(CleanupUrl) registers[instr->cleanup.reg].geturlptr()->~QUrl(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif QML_END_INSTR(CleanupUrl) QML_BEGIN_INSTR(Fetch) @@ -1530,10 +1558,19 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex, int type = registers[instr->cleanup.reg].gettype(); if (type == qMetaTypeId<QVariant>()) { registers[instr->cleanup.reg].getvariantptr()->~QVariant(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif } else if (type == QMetaType::QString) { registers[instr->cleanup.reg].getstringptr()->~QString(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif } else if (type == QMetaType::QUrl) { registers[instr->cleanup.reg].geturlptr()->~QUrl(); +#ifdef REGISTER_CLEANUP_DEBUG + registers[instr->cleanup.reg].setUndefined(); +#endif } } QML_END_INSTR(CleanupGeneric) @@ -1746,7 +1783,6 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node done.common.type = Instr::Done; bytecode << done; - return true; } else { // Can we store the final value? if (type.type == QVariant::Int && @@ -1788,12 +1824,12 @@ bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node Instr done; done.common.type = Instr::Done; bytecode << done; - - return true; } else { return false; } } + + return true; } bool QDeclarativeBindingCompilerPrivate::parseExpression(QDeclarativeJS::AST::Node *node, Result &type) @@ -2233,6 +2269,8 @@ bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result if (lhsTmp != -1) releaseReg(lhsTmp); if (rhsTmp != -1) releaseReg(rhsTmp); + releaseReg(lhs.reg); + releaseReg(rhs.reg); return true; } @@ -2524,6 +2562,10 @@ bool QDeclarativeBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo rv.metaObject = 0; rv.type = 0; + //XXX binding optimizer doesn't handle properties with a revision + if (prop.revision() > 0) + return false; + int fastFetchIndex = fastProperties()->accessorIndexForProperty(mo, idx); Instr fetch; diff --git a/src/declarative/qml/qdeclarativecompileddata.cpp b/src/declarative/qml/qdeclarativecompileddata.cpp index 70cace4..03deea1 100644 --- a/src/declarative/qml/qdeclarativecompileddata.cpp +++ b/src/declarative/qml/qdeclarativecompileddata.cpp @@ -171,6 +171,8 @@ QDeclarativeCompiledData::~QDeclarativeCompiledData() for (int ii = 0; ii < types.count(); ++ii) { if (types.at(ii).component) types.at(ii).component->release(); + if (types.at(ii).typePropertyCache) + types.at(ii).typePropertyCache->release(); } for (int ii = 0; ii < propertyCaches.count(); ++ii) @@ -209,6 +211,34 @@ const QMetaObject *QDeclarativeCompiledData::TypeReference::metaObject() const } } +/*! +Returns the property cache, if one alread exists. The cache is not referenced. +*/ +QDeclarativePropertyCache *QDeclarativeCompiledData::TypeReference::propertyCache() const +{ + if (type) + return typePropertyCache; + else + return component->rootPropertyCache; +} + +/*! +Returns the property cache, creating one if it doesn't already exist. The cache is not referenced. +*/ +QDeclarativePropertyCache *QDeclarativeCompiledData::TypeReference::createPropertyCache(QDeclarativeEngine *engine) +{ + if (typePropertyCache) { + return typePropertyCache; + } else if (type) { + typePropertyCache = QDeclarativeEnginePrivate::get(engine)->cache(type->metaObject()); + typePropertyCache->addref(); + return typePropertyCache; + } else { + return component->rootPropertyCache; + } +} + + void QDeclarativeCompiledData::dumpInstructions() { if (!name.isEmpty()) diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp index 5c73f76..0554897 100644 --- a/src/declarative/qml/qdeclarativecompiler.cpp +++ b/src/declarative/qml/qdeclarativecompiler.cpp @@ -589,6 +589,18 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine, err = tr( "Element is not creatable."); COMPILE_EXCEPTION(parserRef->refObjects.first(), err); } + + if (ref.type->containsRevisionedAttributes()) { + QDeclarativeError cacheError; + ref.typePropertyCache = + QDeclarativeEnginePrivate::get(engine)->cache(ref.type, resolvedTypes.at(ii).minorVersion, cacheError); + + if (!ref.typePropertyCache) { + COMPILE_EXCEPTION(parserRef->refObjects.first(), cacheError.description()); + } + ref.typePropertyCache->addref(); + } + } else if (tref.typeData) { ref.component = tref.typeData->compiledData(); } @@ -886,8 +898,7 @@ bool QDeclarativeCompiler::buildObject(Object *obj, const BindingContext &ctxt) void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) { - const QDeclarativeCompiledData::TypeReference &tr = - output->types.at(obj->type); + QDeclarativeCompiledData::TypeReference &tr = output->types[obj->type]; if (tr.type && obj->metatype == &QDeclarativeComponent::staticMetaObject) { genComponent(obj); return; @@ -902,6 +913,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) create.line = obj->location.start.line; create.createSimple.create = output->types.at(obj->type).type->createFunction(); create.createSimple.typeSize = output->types.at(obj->type).type->createSize(); + create.createSimple.type = obj->type; create.createSimple.column = obj->location.start.column; output->bytecode << create; @@ -935,16 +947,10 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) meta.storeMeta.data = output->indexForByteArray(obj->metadata); meta.storeMeta.aliasData = output->indexForByteArray(obj->synthdata); meta.storeMeta.propertyCache = output->propertyCaches.count(); - // ### Surely the creation of this property cache could be more efficient - QDeclarativePropertyCache *propertyCache = 0; - if (tr.component) - propertyCache = tr.component->rootPropertyCache->copy(); - else - propertyCache = enginePrivate->cache(obj->metaObject()->superClass())->copy(); - propertyCache->append(engine, obj->metaObject(), QDeclarativePropertyCache::Data::NoFlags, - QDeclarativePropertyCache::Data::IsVMEFunction, - QDeclarativePropertyCache::Data::IsVMESignal); + QDeclarativePropertyCache *propertyCache = obj->synthCache; + Q_ASSERT(propertyCache); + propertyCache->addref(); // Add flag for alias properties if (!obj->synthdata.isEmpty()) { @@ -964,11 +970,7 @@ void QDeclarativeCompiler::genObject(QDeclarativeParser::Object *obj) output->propertyCaches << propertyCache; output->bytecode << meta; } else if (obj == unitRoot) { - if (tr.component) - output->rootPropertyCache = tr.component->rootPropertyCache; - else - output->rootPropertyCache = enginePrivate->cache(obj->metaObject()); - + output->rootPropertyCache = tr.createPropertyCache(engine); output->rootPropertyCache->addref(); } @@ -1103,15 +1105,7 @@ void QDeclarativeCompiler::genObjectBody(QDeclarativeParser::Object *obj) meta.line = 0; meta.storeMeta.data = output->indexForByteArray(prop->value->metadata); meta.storeMeta.aliasData = output->indexForByteArray(prop->value->synthdata); - meta.storeMeta.propertyCache = output->propertyCaches.count(); - // ### Surely the creation of this property cache could be more efficient - QDeclarativePropertyCache *propertyCache = - enginePrivate->cache(prop->value->metaObject()->superClass())->copy(); - propertyCache->append(engine, prop->value->metaObject(), QDeclarativePropertyCache::Data::NoFlags, - QDeclarativePropertyCache::Data::IsVMEFunction, - QDeclarativePropertyCache::Data::IsVMESignal); - - output->propertyCaches << propertyCache; + meta.storeMeta.propertyCache = -1; output->bytecode << meta; } @@ -1351,10 +1345,22 @@ bool QDeclarativeCompiler::buildSignal(QDeclarativeParser::Property *prop, QDecl if(name[0] >= 'A' && name[0] <= 'Z') name[0] = name[0] - 'A' + 'a'; - int sigIdx = QDeclarativePropertyPrivate::findSignalByName(obj->metaObject(), name).methodIndex(); + bool notInRevision = false; + int sigIdx = indexOfSignal(obj, name, ¬InRevision); if (sigIdx == -1) { + if (notInRevision && -1 == indexOfProperty(obj, prop->name, 0)) { + Q_ASSERT(obj->type != -1); + const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); + const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); + if (type.type) { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + } else { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name))); + } + } + // If the "on<Signal>" name doesn't resolve into a signal, try it as a // property. COMPILE_CHECK(buildProperty(prop, obj, ctxt)); @@ -1403,7 +1409,7 @@ bool QDeclarativeCompiler::doesPropertyExist(QDeclarativeParser::Property *prop, QMetaProperty p = QDeclarativeMetaType::defaultProperty(mo); return p.name() != 0; } else { - int idx = mo->indexOfProperty(prop->name.constData()); + int idx = indexOfProperty(obj, prop->name); return idx != -1 && mo->property(idx).isScriptable(); } } @@ -1464,7 +1470,17 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, } } else { - prop->index = metaObject->indexOfProperty(prop->name.constData()); + bool notInRevision = false; + prop->index = indexOfProperty(obj, prop->name, ¬InRevision); + if (prop->index == -1 && notInRevision) { + const QList<QDeclarativeTypeData::TypeReference> &resolvedTypes = unit->resolvedTypes(); + const QDeclarativeTypeData::TypeReference &type = resolvedTypes.at(obj->type); + if (type.type) { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available in %3 %4.%5.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name)).arg(QString::fromUtf8(type.type->module())).arg(type.majorVersion).arg(type.minorVersion)); + } else { + COMPILE_EXCEPTION(prop, tr("\"%1.%2\" is not available due to component versioning.").arg(QString::fromUtf8(obj->className)).arg(QString::fromUtf8(prop->name))); + } + } if (prop->index != -1) { p = metaObject->property(prop->index); @@ -1479,9 +1495,8 @@ bool QDeclarativeCompiler::buildProperty(QDeclarativeParser::Property *prop, // We can't error here as the "id" property does not require a // successful index resolution - if (p.name()) { + if (p.name()) prop->type = p.userType(); - } // Check if this is an alias if (prop->index != -1 && @@ -1894,14 +1909,22 @@ bool QDeclarativeCompiler::buildValueTypeProperty(QObject *type, COMPILE_EXCEPTION(prop, tr("Unexpected object assignment")); } else if (value->value.isScript()) { // ### Check for writability - BindingReference reference; - reference.expression = value->value; - reference.property = prop; - reference.value = value; - reference.bindingContext = ctxt; - reference.bindingContext.owner++; - addBindingReference(reference); - value->type = Value::PropertyBinding; + + //optimization for <Type>.<EnumValue> enum assignments + bool isEnumAssignment = false; + COMPILE_CHECK(testQualifiedEnumAssignment(p, obj, value, &isEnumAssignment)); + if (isEnumAssignment) { + value->type = Value::Literal; + } else { + BindingReference reference; + reference.expression = value->value; + reference.property = prop; + reference.value = value; + reference.bindingContext = ctxt; + reference.bindingContext.owner++; + addBindingReference(reference); + value->type = Value::PropertyBinding; + } } else { COMPILE_CHECK(testLiteralAssignment(p, value)); value->type = Value::Literal; @@ -2196,7 +2219,15 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop QDeclarativeType *type = 0; unit->imports().resolveType(typeName.toUtf8(), &type, 0, 0, 0, 0); - if (!type || obj->typeName != type->qmlTypeName()) + //handle enums on value types (where obj->typeName is empty) + QByteArray objTypeName = obj->typeName; + if (objTypeName.isEmpty()) { + QDeclarativeType *objType = toQmlType(obj); + if (objType) + objTypeName = objType->qmlTypeName(); + } + + if (!type || objTypeName != type->qmlTypeName()) return true; QString enumValue = parts.at(1); @@ -2246,6 +2277,35 @@ const QMetaObject *QDeclarativeCompiler::resolveType(const QByteArray& name) con return qmltype->metaObject(); } +// similar to logic of completeComponentBuild, but also sticks data +// into datas at the end +int QDeclarativeCompiler::rewriteBinding(const QString& expression, const QByteArray& name) +{ + QDeclarativeRewrite::RewriteBinding rewriteBinding; + rewriteBinding.setName('$' + name.mid(name.lastIndexOf('.') + 1)); + bool isSharable = false; + QString rewrite = rewriteBinding(expression, 0, &isSharable); + + quint32 length = rewrite.length(); + quint32 pc; + + if (isSharable) { + pc = output->cachedClosures.count(); + pc |= 0x80000000; + output->cachedClosures.append(0); + } else { + pc = output->cachedPrograms.length(); + output->cachedPrograms.append(0); + } + + QByteArray compiledData = + QByteArray((const char *)&pc, sizeof(quint32)) + + QByteArray((const char *)&length, sizeof(quint32)) + + QByteArray((const char *)rewrite.constData(), + rewrite.length() * sizeof(QChar)); + + return output->indexForByteArray(compiledData); +} // Ensures that the dynamic meta specification on obj is valid bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj) @@ -2370,8 +2430,7 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn for (int ii = 0; ii < obj->dynamicProperties.count(); ++ii) { const Object::DynamicProperty &p = obj->dynamicProperties.at(ii); - int propIdx = - obj->metaObject()->indexOfProperty(p.name.constData()); + int propIdx = obj->metaObject()->indexOfProperty(p.name.constData()); if (-1 != propIdx) { QMetaProperty prop = obj->metaObject()->property(propIdx); if (prop.isFinal()) @@ -2556,6 +2615,19 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn obj->synthdata = dynamicData; + if (obj->synthCache) { + obj->synthCache->release(); + obj->synthCache = 0; + } + + if (obj->type != -1) { + QDeclarativePropertyCache *cache = output->types[obj->type].createPropertyCache(engine)->copy(); + cache->append(engine, &obj->extObject, QDeclarativePropertyCache::Data::NoFlags, + QDeclarativePropertyCache::Data::IsVMEFunction, + QDeclarativePropertyCache::Data::IsVMESignal); + obj->synthCache = cache; + } + return true; } @@ -2605,9 +2677,9 @@ static QStringList astNodeToStringList(QDeclarativeJS::AST::Node *node) } bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, - QByteArray &data, - Object *obj, - const Object::DynamicProperty &prop) + QByteArray &data, + Object *obj, + const Object::DynamicProperty &prop) { if (!prop.defaultValue) COMPILE_EXCEPTION(obj, tr("No property alias location")); @@ -2637,7 +2709,7 @@ bool QDeclarativeCompiler::compileAlias(QMetaObjectBuilder &builder, int flags = 0; bool writable = false; if (alias.count() == 2 || alias.count() == 3) { - propIdx = idObject->metaObject()->indexOfProperty(alias.at(1).toUtf8().constData()); + propIdx = indexOfProperty(idObject, alias.at(1).toUtf8()); if (-1 == propIdx) { COMPILE_EXCEPTION(prop.defaultValue, tr("Invalid alias location")); @@ -2849,13 +2921,10 @@ bool QDeclarativeCompiler::completeComponentBuild() // Pre-rewrite the expression QString expression = binding.expression.asScript(); - // ### Optimize - QDeclarativeRewrite::SharedBindingTester sharableTest; - bool isSharable = sharableTest.isSharable(expression); - QDeclarativeRewrite::RewriteBinding rewriteBinding; rewriteBinding.setName('$'+binding.property->name); - expression = rewriteBinding(expression); + bool isSharable = false; + expression = rewriteBinding(binding.expression.asAST(), expression, &isSharable); quint32 length = expression.length(); quint32 pc; @@ -2981,4 +3050,74 @@ QStringList QDeclarativeCompiler::deferredProperties(QDeclarativeParser::Object return rv; } +// This code must match the semantics of QDeclarativePropertyPrivate::findSignalByName +int QDeclarativeCompiler::indexOfSignal(QDeclarativeParser::Object *object, const QByteArray &name, + bool *notInRevision) +{ + if (notInRevision) *notInRevision = false; + + if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) { + // XXX fromUtf8 + QString strName(QString::fromUtf8(name)); + QDeclarativePropertyCache *cache = + object->synthCache?object->synthCache:output->types.at(object->type).propertyCache(); + + QDeclarativePropertyCache::Data *d = cache->property(strName); + if (notInRevision) *notInRevision = false; + + while (d && !(d->flags & QDeclarativePropertyCache::Data::IsFunction)) + d = cache->overrideData(d); + + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return -1; + } else if (d) { + return d->coreIndex; + } + + if (name.endsWith("Changed")) { + QByteArray propName = name.mid(0, name.length() - 7); + + int propIndex = indexOfProperty(object, propName, notInRevision); + if (propIndex != -1) { + d = cache->property(propIndex); + return d->notifyIndex; + } + } + + return -1; + } else { + return QDeclarativePropertyPrivate::findSignalByName(object->metaObject(), name).methodIndex(); + } + +} + +int QDeclarativeCompiler::indexOfProperty(QDeclarativeParser::Object *object, const QByteArray &name, + bool *notInRevision) +{ + if (notInRevision) *notInRevision = false; + + if (object->synthCache || (object->type != -1 && output->types.at(object->type).propertyCache())) { + // XXX fromUtf8 + QString strName(QString::fromUtf8(name)); + QDeclarativePropertyCache *cache = + object->synthCache?object->synthCache:output->types.at(object->type).propertyCache(); + + QDeclarativePropertyCache::Data *d = cache->property(strName); + // Find the first property + while (d && d->flags & QDeclarativePropertyCache::Data::IsFunction) + d = cache->overrideData(d); + + if (d && !cache->isAllowedInRevision(d)) { + if (notInRevision) *notInRevision = true; + return -1; + } else { + return d?d->coreIndex:-1; + } + } else { + const QMetaObject *mo = object->metaObject(); + return mo->indexOfProperty(name.constData()); + } +} + QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h index 984db81..93b6a09 100644 --- a/src/declarative/qml/qdeclarativecompiler_p.h +++ b/src/declarative/qml/qdeclarativecompiler_p.h @@ -89,14 +89,17 @@ public: struct TypeReference { TypeReference() - : type(0), component(0) {} + : type(0), typePropertyCache(0), component(0) {} QByteArray className; QDeclarativeType *type; + QDeclarativePropertyCache *typePropertyCache; QDeclarativeCompiledData *component; QObject *createInstance(QDeclarativeContextData *, const QBitField &, QList<QDeclarativeError> *) const; const QMetaObject *metaObject() const; + QDeclarativePropertyCache *propertyCache() const; + QDeclarativePropertyCache *createPropertyCache(QDeclarativeEngine *); }; QList<TypeReference> types; struct CustomTypeData @@ -161,6 +164,7 @@ public: int evaluateEnum(const QByteArray& script) const; // for QDeclarativeCustomParser::evaluateEnum const QMetaObject *resolveType(const QByteArray& name) const; // for QDeclarativeCustomParser::resolveType + int rewriteBinding(const QString& expression, const QByteArray& name); // for QDeclarativeCustomParser::rewriteBinding private: static void reset(QDeclarativeCompiledData *); @@ -276,6 +280,8 @@ private: bool canCoerce(int to, QDeclarativeParser::Object *from); QStringList deferredProperties(QDeclarativeParser::Object *); + int indexOfProperty(QDeclarativeParser::Object *, const QByteArray &, bool *notInRevision = 0); + int indexOfSignal(QDeclarativeParser::Object *, const QByteArray &, bool *notInRevision = 0); void addId(const QString &, QDeclarativeParser::Object *); diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index f716f85..5840f70 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -54,11 +54,13 @@ #include "private/qdeclarativescriptparser_p.h" #include "private/qdeclarativedebugtrace_p.h" #include "private/qdeclarativeenginedebug_p.h" +#include <QtScript/qscriptvalueiterator.h> #include <QStack> #include <QStringList> #include <QtCore/qdebug.h> #include <QApplication> +#include <qdeclarativeinfo.h> QT_BEGIN_NAMESPACE @@ -613,7 +615,7 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q } /*! - \qmlmethod object Component::createObject(Item parent) + \qmlmethod object Component::createObject(Item parent, Script valuemap = null) Creates and returns an object instance of this component that will have the given \a parent. Returns null if object creation fails. @@ -631,6 +633,12 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q it is not destroyed by the garbage collector. This is regardless of Item.parent being set afterwards, since setting the Item parent does not change object ownership; only the graphical parent is changed. + Since QtQuick 1.1, a map of property values can be optionally passed to the method that applies values to the object's properties + before its creation is finalised. This will avoid binding issues that can occur when the object is + instantiated before property bindings have been set. For example: + + \code component.createObject(parent, {"x": 100, "y": 100, "specialProperty": someObject}); \endcode + Dynamically created instances can be deleted with the \c destroy() method. See \l {Dynamic Object Management in QML} for more information. */ @@ -646,25 +654,46 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q QScriptValue QDeclarativeComponent::createObject(QObject* parent) { Q_D(QDeclarativeComponent); - QDeclarativeContext* ctxt = creationContext(); - if(!ctxt && d->engine) - ctxt = d->engine->rootContext(); + return d->createObject(parent, QScriptValue(QScriptValue::NullValue)); +} + +/*! + \internal + Overloadable method allows properties to be set during creation +*/ +QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap) +{ + Q_D(QDeclarativeComponent); + + if (!valuemap.isObject() || valuemap.isArray()) { + qmlInfo(this) << tr("createObject: value is not an object"); + return QScriptValue(QScriptValue::NullValue); + } + return d->createObject(parent, valuemap); +} + +QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap) +{ + Q_Q(QDeclarativeComponent); + QDeclarativeContext* ctxt = q->creationContext(); + if(!ctxt && engine) + ctxt = engine->rootContext(); if (!ctxt) return QScriptValue(QScriptValue::NullValue); - QObject* ret = beginCreate(ctxt); + QObject* ret = q->beginCreate(ctxt); if (!ret) { - completeCreate(); + q->completeCreate(); return QScriptValue(QScriptValue::NullValue); } - if (parent) { - ret->setParent(parent); + if (publicParent) { + ret->setParent(publicParent); QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions(); bool needParent = false; for (int ii = 0; ii < functions.count(); ++ii) { - QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, parent); + QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent); if (res == QDeclarativePrivate::Parented) { needParent = false; break; @@ -673,14 +702,41 @@ QScriptValue QDeclarativeComponent::createObject(QObject* parent) } } - if (needParent) + if (needParent) qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene."); } - completeCreate(); - QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(d->engine); + QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine); QDeclarativeData::get(ret, true)->setImplicitDestructible(); - return priv->objectClass->newQObject(ret, QMetaType::QObjectStar); + QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar); + + if (valuemap.isObject() && !valuemap.isArray()) { + //Iterate through and assign properties + QScriptValueIterator it(valuemap); + while (it.hasNext()) { + it.next(); + QScriptValue prop = newObject; + QString propName = it.name(); + int index = propName.indexOf(QLatin1Char('.')); + if (index > 0) { + QString subProp = propName; + int lastIndex = 0; + while (index > 0) { + subProp = propName.mid(lastIndex, index - lastIndex); + prop = prop.property(subProp); + lastIndex = index + 1; + index = propName.indexOf(QLatin1Char('.'), index + 1); + } + prop.setProperty(propName.mid(propName.lastIndexOf(QLatin1Char('.')) + 1), it.value()); + } else { + newObject.setProperty(propName, it.value()); + } + } + } + + q->completeCreate(); + + return newObject; } /*! @@ -782,8 +838,10 @@ QObject * QDeclarativeComponentPrivate::begin(QDeclarativeContextData *parentCon Q_ASSERT(!isRoot || state); // Either this isn't a root component, or a state data must be provided Q_ASSERT((state != 0) ^ (errors != 0)); // One of state or errors (but not both) must be provided - if (isRoot) + if (isRoot) { QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, component->url); + } QDeclarativeContextData *ctxt = new QDeclarativeContextData; ctxt->isInternal = true; diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h index 6f28f2e..9a60a8b 100644 --- a/src/declarative/qml/qdeclarativecomponent.h +++ b/src/declarative/qml/qdeclarativecomponent.h @@ -110,6 +110,7 @@ Q_SIGNALS: protected: QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject* parent); Q_INVOKABLE QScriptValue createObject(QObject* parent); + Q_INVOKABLE Q_REVISION(1) QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning private: QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, int, QObject *parent); diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h index 02a6ce8..f8bec2b 100644 --- a/src/declarative/qml/qdeclarativecomponent_p.h +++ b/src/declarative/qml/qdeclarativecomponent_p.h @@ -116,6 +116,8 @@ public: ConstructionState *state); static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state); + QScriptValue createObject(QObject *publicParent, const QScriptValue valuemap); + QDeclarativeEngine *engine; QDeclarativeGuardedContextData creationContext; diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h index f7d2c62..b7e4c6a 100644 --- a/src/declarative/qml/qdeclarativecontext_p.h +++ b/src/declarative/qml/qdeclarativecontext_p.h @@ -77,7 +77,6 @@ class QDeclarativeEngine; class QDeclarativeExpression; class QDeclarativeExpressionPrivate; class QDeclarativeAbstractExpression; -class QDeclarativeBinding_Id; class QDeclarativeCompiledBindings; class QDeclarativeContextData; diff --git a/src/declarative/qml/qdeclarativecustomparser.cpp b/src/declarative/qml/qdeclarativecustomparser.cpp index e8ffe3b..8dd6824 100644 --- a/src/declarative/qml/qdeclarativecustomparser.cpp +++ b/src/declarative/qml/qdeclarativecustomparser.cpp @@ -304,5 +304,14 @@ const QMetaObject *QDeclarativeCustomParser::resolveType(const QByteArray& name) return compiler->resolveType(name); } +/*! + Rewrites \a expression and returns an identifier that can be + used to construct the binding later. \a name + is used as the name of the rewritten function. +*/ +QDeclarativeBinding::Identifier QDeclarativeCustomParser::rewriteBinding(const QString& expression, const QByteArray& name) +{ + return compiler->rewriteBinding(expression, name); +} QT_END_NAMESPACE diff --git a/src/declarative/qml/qdeclarativecustomparser_p.h b/src/declarative/qml/qdeclarativecustomparser_p.h index 32d85ae..be9f514 100644 --- a/src/declarative/qml/qdeclarativecustomparser_p.h +++ b/src/declarative/qml/qdeclarativecustomparser_p.h @@ -56,6 +56,7 @@ #include "private/qdeclarativemetatype_p.h" #include "qdeclarativeerror.h" #include "private/qdeclarativeparser_p.h" +#include "private/qdeclarativebinding_p.h" #include <QtCore/qbytearray.h> #include <QtCore/qxmlstream.h> @@ -140,6 +141,8 @@ protected: const QMetaObject *resolveType(const QByteArray&) const; + QDeclarativeBinding::Identifier rewriteBinding(const QString&, const QByteArray&); + private: QList<QDeclarativeError> exceptions; QDeclarativeCompiler *compiler; diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp index 89aa79a..f1296aa 100644 --- a/src/declarative/qml/qdeclarativedom.cpp +++ b/src/declarative/qml/qdeclarativedom.cpp @@ -334,10 +334,10 @@ QList<QByteArray> QDeclarativeDomProperty::propertyNameParts() const Return true if this property is used as a default property in the QML document. - \qml + \code <Text text="hello"/> <Text>hello</Text> - \endqml + \endcode The above two examples return the same DOM tree, except that the second has the default property flag set on the text property. Observe that whether @@ -509,10 +509,10 @@ QByteArray QDeclarativeDomDynamicProperty::propertyTypeName() const Return true if this property is used as a default property in the QML document. - \qml + \code <Text text="hello"/> <Text>hello</Text> - \endqml + \endcode The above two examples return the same DOM tree, except that the second has the default property flag set on the text property. Observe that whether diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp index 545037f..b7a02f1 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -69,6 +69,8 @@ #include "private/qdeclarativetypenamecache_p.h" #include "private/qdeclarativeinclude_p.h" #include "private/qdeclarativenotifier_p.h" +#include "private/qdeclarativedebugtrace_p.h" +#include "private/qdeclarativeapplication_p.h" #include <QtCore/qmetaobject.h> #include <QScriptClass> @@ -202,8 +204,9 @@ void QDeclarativeEnginePrivate::defineModule() \brief The \c Qt object provides useful enums and functions from Qt, for use in all QML files. -The \c Qt object is not a QML element; it cannot be instantiated. It is a global object -with enums and functions. To use it, call the members of the global \c Qt object directly. +The \c Qt object is a global object with utility functions, properties and enums. + +It is not instantiable; to use it, call the members of the global \c Qt object directly. For example: \qml @@ -218,8 +221,8 @@ Text { \section1 Enums -The Qt object contains enums that declared into Qt's Meta-Object System. For example, you can access -the \c Leftbutton member of the \c Qt::MouseButton enum with \c Qt.LeftButton. +The Qt object contains the enums available in the \l {Qt Namespace}. For example, you can access +the \l Qt::LeftButton and \l Qt::RightButton enum values as \c Qt.LeftButton and \c Qt.RightButton. \section1 Types @@ -261,6 +264,57 @@ of their use. \endlist */ + +/*! + \qmlproperty object QML:Qt::application + \since QtQuick 1.1 + + The \c application object provides access to global application state + properties shared by many QML components. + + Its properties are: + + \table + \row + \o \c application.active + \o + This read-only property indicates whether the application is the top-most and focused + application, and the user is able to interact with the application. The property + is false when the application is in the background, the device keylock or screen + saver is active, the screen backlight is turned off, or the global system dialog + is being displayed on top of the application. It can be used for stopping and + pausing animations, timers and active processing of data in order to save device + battery power and free device memory and processor load when the application is not + active. + + \row + \o \c application.layoutDirection + \o + This read-only property can be used to query the default layout direction of the + application. On system start-up, the default layout direction depends on the + application's language. The property has a value of \c Qt.RightToLeft in locales + where text and graphic elements are read from right to left, and \c Qt.LeftToRight + where the reading direction flows from left to right. You can bind to this + property to customize your application layouts to support both layout directions. + + Possible values are: + + \list + \o Qt.LeftToRight - Text and graphics elements should be positioned + from left to right. + \o Qt.RightToLeft - Text and graphics elements should be positioned + from right to left. + \endlist + \endtable + + The following example uses the \c application object to indicate + whether the application is currently active: + + \snippet doc/src/snippets/declarative/application.qml document + +*/ + + /*! \qmlmethod object Qt::include(string url, jsobject callback) @@ -458,6 +512,8 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate() (*iter)->release(); for(QHash<const QMetaObject *, QDeclarativePropertyCache *>::Iterator iter = propertyCache.begin(); iter != propertyCache.end(); ++iter) (*iter)->release(); + for(QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *>::Iterator iter = typePropertyCache.begin(); iter != typePropertyCache.end(); ++iter) + (*iter)->release(); } @@ -520,6 +576,9 @@ void QDeclarativeEnginePrivate::init() listClass = new QDeclarativeListScriptClass(q); rootContext = new QDeclarativeContext(q,true); + QScriptValue applicationObject = objectClass->newQObject(new QDeclarativeApplication(q)); + scriptEngine.globalObject().property(QLatin1String("Qt")).setProperty(QLatin1String("application"), applicationObject); + if (QCoreApplication::instance()->thread() == q->thread() && QDeclarativeEngineDebugServer::isDebuggingEnabled()) { isDebugging = true; @@ -717,7 +776,7 @@ void QDeclarativeEngine::addImageProvider(const QString &providerId, QDeclarativ { Q_D(QDeclarativeEngine); QMutexLocker locker(&d->mutex); - d->imageProviders.insert(providerId, QSharedPointer<QDeclarativeImageProvider>(provider)); + d->imageProviders.insert(providerId.toLower(), QSharedPointer<QDeclarativeImageProvider>(provider)); } /*! @@ -959,7 +1018,14 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) QDeclarativeData *data = QDeclarativeData::get(object); if (data && data->deferredComponent) { - + if (QDeclarativeDebugService::isDebuggingEnabled()) { + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Creating); + QDeclarativeType *type = QDeclarativeMetaType::qmlType(object->metaObject()); + QString typeName = type ? QLatin1String(type->qmlTypeName()) : QString::fromLatin1(object->metaObject()->className()); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Creating, typeName); + if (data->outerContext) + QDeclarativeDebugTrace::rangeLocation(QDeclarativeDebugTrace::Creating, data->outerContext->url, data->lineNumber); + } QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(data->context->engine); QDeclarativeComponentPrivate::ConstructionState state; @@ -969,6 +1035,7 @@ Q_AUTOTEST_EXPORT void qmlExecuteDeferred(QObject *object) data->deferredComponent = 0; QDeclarativeComponentPrivate::complete(ep, &state); + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Creating); } } @@ -1372,7 +1439,17 @@ QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEn /*! \qmlmethod string Qt::formatDate(datetime date, variant format) -Returns the string representation of \c date, formatted according to \c format. + +Returns a string representation of \c date, optionally formatted according +to \c format. + +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date} +property, a QDate, or QDateTime value. The \a format parameter may be any of +the possible format values as described for +\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}. + +If \a format is not specified, \a date is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. */ #ifndef QT_NO_DATESTRING QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine) @@ -1399,9 +1476,16 @@ QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptE /*! \qmlmethod string Qt::formatTime(datetime time, variant format) -Returns the string representation of \c time, formatted according to \c format. -See Qt::formatDateTime for how to define \c format. +Returns a string representation of \c time, optionally formatted according to +\c format. + +The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime +value. The \a format parameter may be any of the possible format values as +described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}. + +If \a format is not specified, \a time is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. */ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine) { @@ -1409,29 +1493,49 @@ QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptE if(argCount == 0 || argCount > 2) return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid arguments")); - QTime date = ctxt->argument(0).toDateTime().time(); + QTime time; + QScriptValue sv = ctxt->argument(0); + if (sv.isDate()) + time = sv.toDateTime().time(); + else if (sv.toVariant().type() == QVariant::Time) + time = sv.toVariant().toTime(); + Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; if (argCount == 2) { QScriptValue formatArg = ctxt->argument(1); if (formatArg.isString()) { QString format = formatArg.toString(); - return engine->newVariant(QVariant::fromValue(date.toString(format))); + return engine->newVariant(QVariant::fromValue(time.toString(format))); } else if (formatArg.isNumber()) { enumFormat = Qt::DateFormat(formatArg.toUInt32()); } else { return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format")); } } - return engine->newVariant(QVariant::fromValue(date.toString(enumFormat))); + return engine->newVariant(QVariant::fromValue(time.toString(enumFormat))); } /*! \qmlmethod string Qt::formatDateTime(datetime dateTime, variant format) -Returns the string representation of \c dateTime, formatted according to \c format. -\c format for the date/time formatting functions is be specified as follows. +Returns a string representation of \c datetime, optionally formatted according to +\c format. + +The \a date parameter may be a JavaScript \c Date object, a \l{date}{date} +property, a QDate, QTime, or QDateTime value. - These expressions may be used for the date: +If \a format is not provided, \a dateTime is formatted using +\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise, +\a format should be either. + +\list +\o One of the Qt::DateFormat enumeration values, such as + \c Qt.DefaultLocaleShortDate or \c Qt.ISODate +\o A string that specifies the format of the returned string, as detailed below. +\endlist + +If \a format specifies a format string, it should use the following expressions +to specify the date: \table \header \i Expression \i Output @@ -1455,7 +1559,7 @@ Returns the string representation of \c dateTime, formatted according to \c form \row \i yyyy \i the year as four digit number \endtable - These expressions may be used for the time: +In addition the following expressions can be used to specify the time: \table \header \i Expression \i Output @@ -1476,23 +1580,28 @@ Returns the string representation of \c dateTime, formatted according to \c form \endtable All other input characters will be ignored. Any sequence of characters that - are enclosed in singlequotes will be treated as text and not be used as an - expression. Two consecutive singlequotes ("''") are replaced by a singlequote + are enclosed in single quotes will be treated as text and not be used as an + expression. Two consecutive single quotes ("''") are replaced by a single quote in the output. - Example format strings (assumed that the date and time is 21 May 2001 - 14:13:09): +For example, if the following date/time value was specified: + + \code + // 21 May 2001 14:13:09 + var dateTime = new Date(2001, 5, 21, 14, 13, 09) + \endcode + +This \a dateTime value could be passed to \c Qt.formatDateTime(), +\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()} +with the \a format values below to produce the following results: \table - \header \i Format \i Result - \row \i dd.MM.yyyy \i 21.05.2001 - \row \i ddd MMMM d yy \i Tue May 21 01 - \row \i hh:mm:ss.zzz \i 14:13:09.042 - \row \i h:m:s ap \i 2:13:9 pm + \header \i Format \i Result + \row \i "dd.MM.yyyy" \i 21.05.2001 + \row \i "ddd MMMM d yy" \i Tue May 21 01 + \row \i "hh:mm:ss.zzz" \i 14:13:09.042 + \row \i "h:m:s ap" \i 2:13:9 pm \endtable - -If no format is specified the locale's short format is used. Alternatively, you can specify -\c Qt.DefaultLocaleLongDate to get the locale's long format. */ QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine) { @@ -1872,14 +1981,24 @@ QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptE } /*! -\qmlmethod color Qt::tint(color baseColor, color tintColor) + \qmlmethod color Qt::tint(color baseColor, color tintColor) This function allows tinting one color with another. - The tint color should usually be mostly transparent, or you will not be able to see the underlying color. The below example provides a slight red tint by having the tint color be pure red which is only 1/16th opaque. + The tint color should usually be mostly transparent, or you will not be + able to see the underlying color. The below example provides a slight red + tint by having the tint color be pure red which is only 1/16th opaque. \qml - Rectangle { x: 0; width: 80; height: 80; color: "lightsteelblue" } - Rectangle { x: 100; width: 80; height: 80; color: Qt.tint("lightsteelblue", "#10FF0000") } + Item { + Rectangle { + x: 0; width: 80; height: 80 + color: "lightsteelblue" + } + Rectangle { + x: 100; width: 80; height: 80 + color: Qt.tint("lightsteelblue", "#10FF0000") + } + } \endqml \image declarative-rect_tint.png @@ -1994,10 +2113,11 @@ QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val /*! Adds \a path as a directory where the engine searches for installed modules in a URL-based directory structure. + The \a path may be a local filesystem directory or a URL. The newly added \a path will be first in the importPathList(). - \sa setImportPathList() + \sa setImportPathList(), \l {QML Modules} */ void QDeclarativeEngine::addImportPath(const QString& path) { @@ -2152,6 +2272,125 @@ static void *voidptr_constructor(const void *v) } } +QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(const QMetaObject *mo) +{ + Q_Q(QDeclarativeEngine); + + if (!mo->superClass()) { + QDeclarativePropertyCache *rv = new QDeclarativePropertyCache(q, mo); + propertyCache.insert(mo, rv); + return rv; + } else { + QDeclarativePropertyCache *super = cache(mo->superClass()); + QDeclarativePropertyCache *rv = super->copy(); + rv->append(q, mo); + propertyCache.insert(mo, rv); + return rv; + } +} + +QDeclarativePropertyCache *QDeclarativeEnginePrivate::createCache(QDeclarativeType *type, int minorVersion, + QDeclarativeError &error) +{ + QList<QDeclarativeType *> types; + + int maxMinorVersion = 0; + + const QMetaObject *metaObject = type->metaObject(); + while (metaObject) { + QDeclarativeType *t = QDeclarativeMetaType::qmlType(metaObject, type->module(), + type->majorVersion(), minorVersion); + if (t) { + maxMinorVersion = qMax(maxMinorVersion, t->minorVersion()); + types << t; + } else { + types << 0; + } + + metaObject = metaObject->superClass(); + } + + if (QDeclarativePropertyCache *c = typePropertyCache.value(qMakePair(type, maxMinorVersion))) { + c->addref(); + typePropertyCache.insert(qMakePair(type, minorVersion), c); + return c; + } + + QDeclarativePropertyCache *raw = cache(type->metaObject()); + + bool hasCopied = false; + + for (int ii = 0; ii < types.count(); ++ii) { + QDeclarativeType *currentType = types.at(ii); + if (!currentType) + continue; + + int rev = currentType->metaObjectRevision(); + int moIndex = types.count() - 1 - ii; + + if (raw->allowedRevisionCache[moIndex] != rev) { + if (!hasCopied) { + raw = raw->copy(); + hasCopied = true; + } + raw->allowedRevisionCache[moIndex] = rev; + } + } + + // Test revision compatibility - the basic rule is: + // * Anything that is excluded, cannot overload something that is not excluded * + + // Signals override: + // * other signals and methods of the same name. + // * properties named on<Signal Name> + // * automatic <property name>Changed notify signals + + // Methods override: + // * other methods of the same name + + // Properties override: + // * other elements of the same name + + bool overloadError = false; + QString overloadName; + +#if 0 + for (QDeclarativePropertyCache::StringCache::ConstIterator iter = raw->stringCache.begin(); + !overloadError && iter != raw->stringCache.end(); + ++iter) { + + QDeclarativePropertyCache::Data *d = *iter; + if (raw->isAllowedInRevision(d)) + continue; // Not excluded - no problems + + // check that a regular "name" overload isn't happening + QDeclarativePropertyCache::Data *current = d; + while (!overloadError && current) { + current = d->overrideData(current); + if (current && raw->isAllowedInRevision(current)) + overloadError = true; + } + } +#endif + + if (overloadError) { + if (hasCopied) raw->release(); + + error.setDescription(QLatin1String("Type ") + QString::fromUtf8(type->qmlTypeName()) + QLatin1String(" ") + QString::number(type->majorVersion()) + QLatin1String(".") + QString::number(minorVersion) + QLatin1String(" contains an illegal property \"") + overloadName + QLatin1String("\". This is an error in the type's implementation.")); + return 0; + } + + if (!hasCopied) raw->addref(); + typePropertyCache.insert(qMakePair(type, minorVersion), raw); + + if (minorVersion != maxMinorVersion) { + raw->addref(); + typePropertyCache.insert(qMakePair(type, maxMinorVersion), raw); + } + + return raw; +} + void QDeclarativeEnginePrivate::registerCompositeType(QDeclarativeCompiledData *data) { QByteArray name = data->root->className(); diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h index fc996b5..88b4e80 100644 --- a/src/declarative/qml/qdeclarativeengine_p.h +++ b/src/declarative/qml/qdeclarativeengine_p.h @@ -251,8 +251,12 @@ public: QDeclarativeValueTypeFactory valueTypes; QHash<const QMetaObject *, QDeclarativePropertyCache *> propertyCache; + QHash<QPair<QDeclarativeType *, int>, QDeclarativePropertyCache *> typePropertyCache; inline QDeclarativePropertyCache *cache(QObject *obj); inline QDeclarativePropertyCache *cache(const QMetaObject *); + inline QDeclarativePropertyCache *cache(QDeclarativeType *, int, QDeclarativeError &error); + QDeclarativePropertyCache *createCache(const QMetaObject *); + QDeclarativePropertyCache *createCache(QDeclarativeType *, int, QDeclarativeError &error); void registerCompositeType(QDeclarativeCompiledData *); @@ -330,19 +334,17 @@ Returns a QDeclarativePropertyCache for \a obj if one is available. If \a obj is null, being deleted or contains a dynamic meta object 0 is returned. + +The returned cache is not referenced, so if it is to be stored, call addref(). */ QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QObject *obj) { - Q_Q(QDeclarativeEngine); if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted) return 0; const QMetaObject *mo = obj->metaObject(); QDeclarativePropertyCache *rv = propertyCache.value(mo); - if (!rv) { - rv = new QDeclarativePropertyCache(q, mo); - propertyCache.insert(mo, rv); - } + if (!rv) rv = createCache(mo); return rv; } @@ -352,18 +354,32 @@ Returns a QDeclarativePropertyCache for \a metaObject. As the cache is persisted for the life of the engine, \a metaObject must be a static "compile time" meta-object, or a meta-object that is otherwise known to exist for the lifetime of the QDeclarativeEngine. + +The returned cache is not referenced, so if it is to be stored, call addref(). */ QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(const QMetaObject *metaObject) { - Q_Q(QDeclarativeEngine); Q_ASSERT(metaObject); QDeclarativePropertyCache *rv = propertyCache.value(metaObject); - if (!rv) { - rv = new QDeclarativePropertyCache(q, metaObject); - propertyCache.insert(metaObject, rv); - } + if (!rv) rv = createCache(metaObject); + return rv; +} + +/*! +Returns a QDeclarativePropertyCache for \a type with \a minorVersion. + +The returned cache is not referenced, so if it is to be stored, call addref(). +*/ +QDeclarativePropertyCache *QDeclarativeEnginePrivate::cache(QDeclarativeType *type, int minorVersion, QDeclarativeError &error) +{ + Q_ASSERT(type); + + if (minorVersion == -1 || !type->containsRevisionedAttributes()) + return cache(type->metaObject()); + QDeclarativePropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion)); + if (!rv) rv = createCache(type, minorVersion, error); return rv; } diff --git a/src/declarative/qml/qdeclarativeenginedebug.cpp b/src/declarative/qml/qdeclarativeenginedebug.cpp index 3dfd0f2..8c7f3ad 100644 --- a/src/declarative/qml/qdeclarativeenginedebug.cpp +++ b/src/declarative/qml/qdeclarativeenginedebug.cpp @@ -52,6 +52,7 @@ #include "private/qdeclarativevaluetype_p.h" #include "private/qdeclarativevmemetaobject_p.h" #include "private/qdeclarativeexpression_p.h" +#include "private/qdeclarativepropertychanges_p.h" #include <QtCore/qdebug.h> #include <QtCore/qmetaobject.h> @@ -195,11 +196,6 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message, { message << objectData(object); - // Some children aren't added to an object until particular properties are read - // - e.g. child state objects aren't added until the 'states' property is read - - // but this should only affect internal objects that aren't shown by the - // debugger anyway. - QObjectList children = object->children(); int childrenCount = children.count(); @@ -260,6 +256,18 @@ void QDeclarativeEngineDebugServer::buildObjectDump(QDataStream &message, message << fakeProperties[ii]; } +void QDeclarativeEngineDebugServer::prepareDeferredObjects(QObject *obj) +{ + qmlExecuteDeferred(obj); + + QObjectList children = obj->children(); + for (int ii = 0; ii < children.count(); ++ii) { + QObject *child = children.at(ii); + prepareDeferredObjects(child); + } + +} + void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDeclarativeContext *ctxt) { QDeclarativeContextData *p = QDeclarativeContextData::get(ctxt); @@ -300,6 +308,35 @@ void QDeclarativeEngineDebugServer::buildObjectList(QDataStream &message, QDecla } } +void QDeclarativeEngineDebugServer::buildStatesList(QDeclarativeContext *ctxt, bool cleanList=false) +{ + if (cleanList) + m_allStates.clear(); + + QDeclarativeContextPrivate *ctxtPriv = QDeclarativeContextPrivate::get(ctxt); + for (int ii = 0; ii < ctxtPriv->instances.count(); ++ii) { + buildStatesList(ctxtPriv->instances.at(ii)); + } + + QDeclarativeContextData *child = QDeclarativeContextData::get(ctxt)->childContexts; + while (child) { + buildStatesList(child->asQDeclarativeContext()); + child = child->nextChild; + } +} + +void QDeclarativeEngineDebugServer::buildStatesList(QObject *obj) +{ + if (QDeclarativeState *state = qobject_cast<QDeclarativeState *>(obj)) { + m_allStates.append(state); + } + + QObjectList children = obj->children(); + for (int ii = 0; ii < children.count(); ++ii) { + buildStatesList(children.at(ii)); + } +} + QDeclarativeEngineDebugServer::QDeclarativeObjectData QDeclarativeEngineDebugServer::objectData(QObject *object) { @@ -378,8 +415,10 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message) QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("LIST_OBJECTS_R") << queryId; - if (engine) + if (engine) { buildObjectList(rs, engine->rootContext()); + buildStatesList(engine->rootContext(), true); + } sendMessage(reply); } else if (type == "FETCH_OBJECT") { @@ -396,8 +435,11 @@ void QDeclarativeEngineDebugServer::messageReceived(const QByteArray &message) QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("FETCH_OBJECT_R") << queryId; - if (object) + if (object) { + if (recurse) + prepareDeferredObjects(object); buildObjectDump(rs, object, recurse, dumpProperties); + } sendMessage(reply); } else if (type == "WATCH_OBJECT") { @@ -499,24 +541,63 @@ void QDeclarativeEngineDebugServer::setBinding(int objectId, QDeclarativeContext *context = qmlContext(object); if (object && context) { - QDeclarativeProperty property(object, propertyName, context); - if (isLiteralValue) { - property.write(expression); - } else if (hasValidSignal(object, propertyName)) { - QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString()); - QDeclarativeExpression *oldExpression = QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression); - declarativeExpression->setSourceLocation(oldExpression->sourceFile(), oldExpression->lineNumber()); - } else if (property.isProperty()) { - QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context); - binding->setTarget(property); - binding->setNotifyOnValueChanged(true); - QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding); - if (oldBinding) - oldBinding->destroy(); - binding->update(); + if (property.isValid()) { + + bool inBaseState = true; + + foreach(QWeakPointer<QDeclarativeState> statePointer, m_allStates) { + if (QDeclarativeState *state = statePointer.data()) { + // here we assume that the revert list on itself defines the base state + if (state->isStateActive() && state->containsPropertyInRevertList(object, propertyName)) { + inBaseState = false; + + QDeclarativeBinding *newBinding = 0; + if (!isLiteralValue) { + newBinding = new QDeclarativeBinding(expression.toString(), object, context); + newBinding->setTarget(property); + newBinding->setNotifyOnValueChanged(true); + } + + state->changeBindingInRevertList(object, propertyName, newBinding); + + if (isLiteralValue) + state->changeValueInRevertList(object, propertyName, expression); + } + } + } + + if (inBaseState) { + if (isLiteralValue) { + property.write(expression); + } else if (hasValidSignal(object, propertyName)) { + QDeclarativeExpression *declarativeExpression = new QDeclarativeExpression(context, object, expression.toString()); + QDeclarativeExpression *oldExpression = QDeclarativePropertyPrivate::setSignalExpression(property, declarativeExpression); + declarativeExpression->setSourceLocation(oldExpression->sourceFile(), oldExpression->lineNumber()); + } else if (property.isProperty()) { + QDeclarativeBinding *binding = new QDeclarativeBinding(expression.toString(), object, context); + binding->setTarget(property); + binding->setNotifyOnValueChanged(true); + QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, binding); + if (oldBinding) + oldBinding->destroy(); + binding->update(); + } else { + qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object; + } + } + } else { - qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object; + // not a valid property + if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) { + if (isLiteralValue) { + propertyChanges->changeValue(propertyName, expression); + } else { + propertyChanges->changeExpression(propertyName, expression.toString()); + } + } else { + qWarning() << "QDeclarativeEngineDebugServer::setBinding: unable to set property" << propertyName << "on object" << object; + } } } } @@ -534,11 +615,31 @@ void QDeclarativeEngineDebugServer::resetBinding(int objectId, const QString &pr QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::setBinding(property, 0); if (oldBinding) oldBinding->destroy(); + } + if (property.isResettable()) { + // Note: this will reset the property in any case, without regard to states + // Right now almost no QDeclarativeItem has reset methods for its properties (with the + // notable exception of QDeclarativeAnchors), so this is not a big issue + // later on, setBinding does take states into account + property.reset(); } else { - if (property.isResettable()) { - property.reset(); + // overwrite with default value + if (QDeclarativeType *objType = QDeclarativeMetaType::qmlType(object->metaObject())) { + if (QObject *emptyObject = objType->create()) { + if (emptyObject->property(propertyName.toLatin1()).isValid()) { + QVariant defaultValue = QDeclarativeProperty(emptyObject, propertyName).read(); + if (defaultValue.isValid()) { + setBinding(objectId, propertyName, defaultValue, true); + } + } + delete emptyObject; + } } } + } else { + if (QDeclarativePropertyChanges *propertyChanges = qobject_cast<QDeclarativePropertyChanges *>(object)) { + propertyChanges->removeProperty(propertyName); + } } } } diff --git a/src/declarative/qml/qdeclarativeenginedebug_p.h b/src/declarative/qml/qdeclarativeenginedebug_p.h index 58eb046..e95676c 100644 --- a/src/declarative/qml/qdeclarativeenginedebug_p.h +++ b/src/declarative/qml/qdeclarativeenginedebug_p.h @@ -57,6 +57,7 @@ #include <QtCore/qurl.h> #include <QtCore/qvariant.h> +#include <QWeakPointer> QT_BEGIN_NAMESPACE @@ -64,6 +65,7 @@ class QDeclarativeEngine; class QDeclarativeContext; class QDeclarativeWatcher; class QDataStream; +class QDeclarativeState; class QDeclarativeEngineDebugServer : public QDeclarativeDebugService { @@ -105,8 +107,11 @@ private Q_SLOTS: void propertyChanged(int id, int objectId, const QMetaProperty &property, const QVariant &value); private: + void prepareDeferredObjects(QObject *); void buildObjectList(QDataStream &, QDeclarativeContext *); void buildObjectDump(QDataStream &, QObject *, bool, bool); + void buildStatesList(QDeclarativeContext *, bool); + void buildStatesList(QObject *obj); QDeclarativeObjectData objectData(QObject *); QDeclarativeObjectProperty propertyData(QObject *, int); QVariant valueContents(const QVariant &defaultValue) const; @@ -116,6 +121,7 @@ private: QList<QDeclarativeEngine *> m_engines; QDeclarativeWatcher *m_watch; + QList<QWeakPointer<QDeclarativeState> > m_allStates; }; Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator<<(QDataStream &, const QDeclarativeEngineDebugServer::QDeclarativeObjectData &); Q_DECLARATIVE_PRIVATE_EXPORT QDataStream &operator>>(QDataStream &, QDeclarativeEngineDebugServer::QDeclarativeObjectData &); diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp index 26c91a5..7a85ada 100644 --- a/src/declarative/qml/qdeclarativeexpression.cpp +++ b/src/declarative/qml/qdeclarativeexpression.cpp @@ -103,6 +103,19 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QS expressionFunctionValid = false; } +void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QScriptValue &func, + QObject *me) +{ + expression = func.toString(); + + QDeclarativeAbstractExpression::setContext(ctxt); + scopeObject = me; + + expressionFunction = func; + expressionFunctionMode = ExplicitContext; + expressionFunctionValid = true; +} + void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *expr, QDeclarativeRefCount *rc, QObject *me, const QString &srcUrl, int lineNumber) @@ -304,6 +317,19 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO d->setNotifyObject(this, QDeclarativeExpression_notifyIdx); } +/*! \internal */ +QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, const QScriptValue &func, + QDeclarativeExpressionPrivate &dd) +: QObject(dd, 0) +{ + Q_D(QDeclarativeExpression); + d->init(ctxt, func, scope); + + if (QDeclarativeExpression_notifyIdx == -1) + QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()"); + d->setNotifyObject(this, QDeclarativeExpression_notifyIdx); +} + /*! Destroy the QDeclarativeExpression instance. */ @@ -412,6 +438,16 @@ void QDeclarativeQtScriptExpression::setNotifyObject(QObject *object, int notify } } +void QDeclarativeQtScriptExpression::setEvaluateFlags(EvaluateFlags flags) +{ + evalFlags = flags; +} + +QDeclarativeQtScriptExpression::EvaluateFlags QDeclarativeQtScriptExpression::evaluateFlags() const +{ + return evalFlags; +} + QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope, bool *isUndefined) { Q_ASSERT(context() && context()->engine); @@ -476,7 +512,10 @@ QScriptValue QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool oldOverride = ep->contextClass->setOverrideObject(expressionContext, secondaryScope); } - QScriptValue svalue = expressionFunction.call(); // This could cause this to be deleted + QScriptValue thisObject; + if (evalFlags & RequiresThisObject) + thisObject = ep->objectClass->newQObject(scopeObject); + QScriptValue svalue = expressionFunction.call(thisObject); // This could cause this c++ object to be deleted if (isShared) { ep->sharedContext = oldSharedContext; diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h index 72c5947..d40094b 100644 --- a/src/declarative/qml/qdeclarativeexpression.h +++ b/src/declarative/qml/qdeclarativeexpression.h @@ -59,6 +59,7 @@ class QDeclarativeEngine; class QDeclarativeContext; class QDeclarativeExpressionPrivate; class QDeclarativeContextData; +class QScriptValue; class Q_DECLARATIVE_EXPORT QDeclarativeExpression : public QObject { Q_OBJECT @@ -94,6 +95,8 @@ Q_SIGNALS: protected: QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QString &, QDeclarativeExpressionPrivate &dd); + QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QScriptValue &, + QDeclarativeExpressionPrivate &dd); QDeclarativeExpression(QDeclarativeContextData *, void *, QDeclarativeRefCount *rc, QObject *me, const QString &, int, QDeclarativeExpressionPrivate &dd); diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h index 1d25609..51cae0f 100644 --- a/src/declarative/qml/qdeclarativeexpression_p.h +++ b/src/declarative/qml/qdeclarativeexpression_p.h @@ -113,6 +113,9 @@ class QDeclarativeQtScriptExpression : public QDeclarativeAbstractExpression, public: enum Mode { SharedContext, ExplicitContext }; + enum EvaluateFlag { RequiresThisObject = 0x01 }; + Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag) + QDeclarativeQtScriptExpression(); virtual ~QDeclarativeQtScriptExpression(); @@ -131,6 +134,9 @@ public: void resetNotifyOnChange(); void setNotifyObject(QObject *, int ); + void setEvaluateFlags(EvaluateFlags flags); + EvaluateFlags evaluateFlags() const; + QScriptValue scriptValue(QObject *secondaryScope, bool *isUndefined); class DeleteWatcher { @@ -157,8 +163,13 @@ private: QObject *guardObject; int guardObjectNotifyIndex; bool *deleted; + + EvaluateFlags evalFlags; }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeQtScriptExpression::EvaluateFlags) + + class QDeclarativeExpression; class QString; class QDeclarativeExpressionPrivate : public QObjectPrivate, public QDeclarativeQtScriptExpression @@ -169,6 +180,7 @@ public: ~QDeclarativeExpressionPrivate(); void init(QDeclarativeContextData *, const QString &, QObject *); + void init(QDeclarativeContextData *, const QScriptValue &, QObject *); void init(QDeclarativeContextData *, void *, QDeclarativeRefCount *, QObject *, const QString &, int); QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0); diff --git a/src/declarative/qml/qdeclarativeimageprovider.cpp b/src/declarative/qml/qdeclarativeimageprovider.cpp index 560077f..f111c20 100644 --- a/src/declarative/qml/qdeclarativeimageprovider.cpp +++ b/src/declarative/qml/qdeclarativeimageprovider.cpp @@ -75,6 +75,16 @@ public: invokes the appropriate image provider according to the providers that have been registered through QDeclarativeEngine::addImageProvider(). + Note that the identifiers are case-insensitive, but the rest of the URL will be passed on with + preserved case. For example, the below snippet would still specify that the image is loaded by the + image provider named "myimageprovider", but it would request a different image than the above snippet + ("Image.png" instead of "image.png"). + \qml + Image { source: "image://MyImageProvider/Image.png" } + \endqml + + If you want the rest of the URL to be case insensitive, you will have to take care + of that yourself inside your image provider. \section2 An example diff --git a/src/declarative/qml/qdeclarativeimport.cpp b/src/declarative/qml/qdeclarativeimport.cpp index c89666d..7a1234d 100644 --- a/src/declarative/qml/qdeclarativeimport.cpp +++ b/src/declarative/qml/qdeclarativeimport.cpp @@ -425,8 +425,18 @@ QString QDeclarativeImportsPrivate::resolvedUri(const QString &dir_arg, QDeclara break; } } + + stableRelativePath.replace(QLatin1Char('\\'), QLatin1Char('/')); + + // remove optional versioning in dot notation from uri + int lastSlash = stableRelativePath.lastIndexOf(QLatin1Char('/')); + if (lastSlash >= 0) { + int versionDot = stableRelativePath.indexOf(QLatin1Char('.'), lastSlash); + if (versionDot >= 0) + stableRelativePath = stableRelativePath.left(versionDot); + } + stableRelativePath.replace(QLatin1Char('/'), QLatin1Char('.')); - stableRelativePath.replace(QLatin1Char('\\'), QLatin1Char('.')); return stableRelativePath; } @@ -447,42 +457,85 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp } QString url = uri; + bool versionFound = false; if (importType == QDeclarativeScriptParser::Import::Library) { url.replace(QLatin1Char('.'), QLatin1Char('/')); bool found = false; QString dir; - foreach (const QString &p, database->fileImportPath) { - dir = p+QLatin1Char('/')+url; + // step 1: search for extension with fully encoded version number + if (vmaj >= 0 && vmin >= 0) { + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; - QFileInfo fi(dir+QLatin1String("/qmldir")); - const QString absoluteFilePath = fi.absoluteFilePath(); + QFileInfo fi(dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir")); + const QString absoluteFilePath = fi.absoluteFilePath(); - if (fi.isFile()) { - found = true; + if (fi.isFile()) { + found = true; - url = QUrl::fromLocalFile(fi.absolutePath()).toString(); - uri = resolvedUri(dir, database); - if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) - return false; - break; + url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + uri = resolvedUri(dir, database); + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + return false; + break; + } } } + // step 2: search for extension with encoded version major + if (vmaj >= 0 && vmin >= 0) { + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; + + QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir")); + const QString absoluteFilePath = fi.absoluteFilePath(); + if (fi.isFile()) { + found = true; + + url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + uri = resolvedUri(dir, database); + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + return false; + break; + } + } + } if (!found) { - found = QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin); - if (!found) { - if (errorString) { - bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1); - if (anyversion) - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); - else - *errorString = QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg); + // step 3: search for extension without version number + + foreach (const QString &p, database->fileImportPath) { + dir = p+QLatin1Char('/')+url; + + QFileInfo fi(dir+QLatin1String("/qmldir")); + const QString absoluteFilePath = fi.absoluteFilePath(); + + if (fi.isFile()) { + found = true; + + url = QUrl::fromLocalFile(fi.absolutePath()).toString(); + uri = resolvedUri(dir, database); + if (!importExtension(absoluteFilePath, uri, database, &qmldircomponents, errorString)) + return false; + break; } - return false; } } + + if (QDeclarativeMetaType::isModule(uri.toUtf8(), vmaj, vmin)) + versionFound = true; + + if (!versionFound && qmldircomponents.isEmpty()) { + if (errorString) { + bool anyversion = QDeclarativeMetaType::isModule(uri.toUtf8(), -1, -1); + if (anyversion) + *errorString = QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin); + else + *errorString = QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg); + } + return false; + } } else { if (importType == QDeclarativeScriptParser::Import::File && qmldircomponents.isEmpty()) { @@ -526,7 +579,7 @@ bool QDeclarativeImportsPrivate::add(const QDeclarativeDirComponents &qmldircomp url.chop(1); } - if (vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { + if (!versionFound && vmaj > -1 && vmin > -1 && !qmldircomponents.isEmpty()) { QList<QDeclarativeDirParser::Component>::ConstIterator it = qmldircomponents.begin(); int lowest_maj = INT_MAX; int lowest_min = INT_MAX; @@ -660,6 +713,7 @@ bool QDeclarativeImportedNamespace::find(const QByteArray& type, int *vmajor, in /*! \class QDeclarativeImportDatabase \brief The QDeclarativeImportDatabase class manages the QML imports for a QDeclarativeEngine. +\internal */ QDeclarativeImportDatabase::QDeclarativeImportDatabase(QDeclarativeEngine *e) : engine(e) @@ -874,23 +928,33 @@ QString QDeclarativeImportDatabase::resolvePlugin(const QDir &qmldirPath, const #endif } +/*! + \internal +*/ QStringList QDeclarativeImportDatabase::pluginPathList() const { return filePluginPath; } +/*! + \internal +*/ void QDeclarativeImportDatabase::setPluginPathList(const QStringList &paths) { filePluginPath = paths; } +/*! + \internal +*/ void QDeclarativeImportDatabase::addPluginPath(const QString& path) { if (qmlImportTrace()) qDebug().nospace() << "QDeclarativeImportDatabase::addPluginPath: " << path; QUrl url = QUrl(path); - if (url.isRelative() || url.scheme() == QLatin1String("file")) { + if (url.isRelative() || url.scheme() == QLatin1String("file") + || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path QDir dir = QDir(path); filePluginPath.prepend(dir.canonicalPath()); } else { @@ -898,6 +962,9 @@ void QDeclarativeImportDatabase::addPluginPath(const QString& path) } } +/*! + \internal +*/ void QDeclarativeImportDatabase::addImportPath(const QString& path) { if (qmlImportTrace()) @@ -909,7 +976,8 @@ void QDeclarativeImportDatabase::addImportPath(const QString& path) QUrl url = QUrl(path); QString cPath; - if (url.isRelative() || url.scheme() == QLatin1String("file")) { + if (url.isRelative() || url.scheme() == QLatin1String("file") + || (url.scheme().length() == 1 && QFile::exists(path)) ) { // windows path QDir dir = QDir(path); cPath = dir.canonicalPath(); } else { @@ -922,17 +990,25 @@ void QDeclarativeImportDatabase::addImportPath(const QString& path) fileImportPath.prepend(cPath); } +/*! + \internal +*/ QStringList QDeclarativeImportDatabase::importPathList() const { return fileImportPath; } +/*! + \internal +*/ void QDeclarativeImportDatabase::setImportPathList(const QStringList &paths) { fileImportPath = paths; } - +/*! + \internal +*/ bool QDeclarativeImportDatabase::importPlugin(const QString &filePath, const QString &uri, QString *errorString) { if (qmlImportTrace()) diff --git a/src/declarative/qml/qdeclarativeinstruction_p.h b/src/declarative/qml/qdeclarativeinstruction_p.h index 59cce84..20be889 100644 --- a/src/declarative/qml/qdeclarativeinstruction_p.h +++ b/src/declarative/qml/qdeclarativeinstruction_p.h @@ -182,6 +182,7 @@ public: struct CreateSimpleInstruction { void (*create)(void *); int typeSize; + int type; ushort column; }; struct StoreMetaInstruction { diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp index 27fb2c7..bf1f699 100644 --- a/src/declarative/qml/qdeclarativemetatype.cpp +++ b/src/declarative/qml/qdeclarativemetatype.cpp @@ -134,10 +134,14 @@ public: bool m_isInterface : 1; const char *m_iid; + QByteArray m_module; QByteArray m_name; int m_version_maj; int m_version_min; int m_typeId; int m_listId; + int m_revision; + mutable bool m_containsRevisionedAttributes; + mutable QDeclarativeType *m_superType; int m_allocationSize; void (*m_newFunc)(void *); @@ -155,6 +159,7 @@ public: int m_index; QDeclarativeCustomParser *m_customParser; mutable volatile bool m_isSetup:1; + mutable bool m_haveSuperType : 1; mutable QList<QDeclarativeProxyMetaObject::ProxyData> m_metaObjects; static QHash<const QMetaObject *, int> m_attachedPropertyIds; @@ -163,10 +168,11 @@ public: QHash<const QMetaObject *, int> QDeclarativeTypePrivate::m_attachedPropertyIds; QDeclarativeTypePrivate::QDeclarativeTypePrivate() -: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), - m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), m_attachedPropertiesType(0), - m_parserStatusCast(-1), m_propertyValueSourceCast(-1), m_propertyValueInterceptorCast(-1), - m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), m_isSetup(false) +: m_isInterface(false), m_iid(0), m_typeId(0), m_listId(0), m_revision(0), m_containsRevisionedAttributes(false), + m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0), + m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1), + m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0), + m_isSetup(false), m_haveSuperType(false) { } @@ -192,9 +198,12 @@ QDeclarativeType::QDeclarativeType(int index, const QDeclarativePrivate::Registe if (type.uri) name += '/'; name += type.elementName; + d->m_module = type.uri; d->m_name = name; d->m_version_maj = type.versionMajor; d->m_version_min = type.versionMinor; + if (type.version >= 1) // revisions added in version 1 + d->m_revision = type.revision; d->m_typeId = type.typeId; d->m_listId = type.listId; d->m_allocationSize = type.objectSize; @@ -228,6 +237,11 @@ QDeclarativeType::~QDeclarativeType() delete d; } +QByteArray QDeclarativeType::module() const +{ + return d->m_module; +} + int QDeclarativeType::majorVersion() const { return d->m_version_maj; @@ -243,6 +257,26 @@ bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const return vmajor > d->m_version_maj || (vmajor == d->m_version_maj && vminor >= d->m_version_min); } +bool QDeclarativeType::availableInVersion(const QByteArray &module, int vmajor, int vminor) const +{ + return module == d->m_module && (vmajor > d->m_version_maj || (vmajor == d->m_version_maj && vminor >= d->m_version_min)); +} + +// returns the nearest _registered_ super class +QDeclarativeType *QDeclarativeType::superType() const +{ + if (!d->m_haveSuperType) { + const QMetaObject *mo = d->m_baseMetaObject->superClass(); + while (mo && !d->m_superType) { + d->m_superType = QDeclarativeMetaType::qmlType(mo, d->m_module, d->m_version_maj, d->m_version_min); + mo = mo->superClass(); + } + d->m_haveSuperType = true; + } + + return d->m_superType; +} + static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) { @@ -356,6 +390,25 @@ void QDeclarativeTypePrivate::init() const m_metaObjects[ii].methodOffset = m_metaObjects.at(ii).metaObject->methodOffset(); } + + // Check for revisioned details + { + const QMetaObject *mo = 0; + if (m_metaObjects.isEmpty()) + mo = m_baseMetaObject; + else + mo = m_metaObjects.first().metaObject; + + for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->propertyCount(); ++ii) { + if (mo->property(ii).revision() != 0) + m_containsRevisionedAttributes = true; + } + + for (int ii = 0; !m_containsRevisionedAttributes && ii < mo->methodCount(); ++ii) { + if (mo->method(ii).revision() != 0) + m_containsRevisionedAttributes = true; + } + } m_isSetup = true; lock.unlock(); @@ -464,6 +517,18 @@ const QMetaObject *QDeclarativeType::baseMetaObject() const return d->m_baseMetaObject; } +bool QDeclarativeType::containsRevisionedAttributes() const +{ + d->init(); + + return d->m_containsRevisionedAttributes; +} + +int QDeclarativeType::metaObjectRevision() const +{ + return d->m_revision; +} + QDeclarativeAttachedPropertiesFunc QDeclarativeType::attachedPropertiesFunction() const { return d->m_attachedPropertiesFunc; @@ -572,7 +637,7 @@ int registerType(const QDeclarativePrivate::RegisterType &type) if (!dtype->qmlTypeName().isEmpty()) data->nameToType.insertMulti(dtype->qmlTypeName(), dtype); - data->metaObjectToType.insert(dtype->baseMetaObject(), dtype); + data->metaObjectToType.insertMulti(dtype->baseMetaObject(), dtype); if (data->objects.size() <= type.typeId) data->objects.resize(type.typeId + 16); @@ -862,6 +927,27 @@ QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject) } /*! + Returns the type (if any) that corresponds to the \a metaObject in version specified + by \a version_major and \a version_minor in module specified by \a uri. Returns null if no + type is registered. +*/ +QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor) +{ + QReadLocker lock(metaTypeDataLock()); + QDeclarativeMetaTypeData *data = metaTypeData(); + + QDeclarativeMetaTypeData::MetaObjects::const_iterator it = data->metaObjectToType.find(metaObject); + while (it != data->metaObjectToType.end() && it.key() == metaObject) { + QDeclarativeType *t = *it; + if (version_major < 0 || t->availableInVersion(module, version_major,version_minor)) + return t; + ++it; + } + + return 0; +} + +/*! Returns the type (if any) that corresponds to the QVariant::Type \a userType. Returns null if no type is registered. */ @@ -929,6 +1015,93 @@ QT_END_NAMESPACE Q_DECLARE_METATYPE(QScriptValue); QT_BEGIN_NAMESPACE + +bool QDeclarativeMetaType::canCopy(int type) +{ + switch(type) { + case QMetaType::VoidStar: + case QMetaType::QObjectStar: + case QMetaType::QWidgetStar: + case QMetaType::Long: + case QMetaType::Int: + case QMetaType::Short: + case QMetaType::Char: + case QMetaType::ULong: + case QMetaType::UInt: + case QMetaType::LongLong: + case QMetaType::ULongLong: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::Bool: + case QMetaType::Float: + case QMetaType::Double: + case QMetaType::QChar: + case QMetaType::QVariantMap: + case QMetaType::QVariantHash: + case QMetaType::QVariantList: + case QMetaType::QByteArray: + case QMetaType::QString: + case QMetaType::QStringList: + case QMetaType::QBitArray: + case QMetaType::QDate: + case QMetaType::QTime: + case QMetaType::QDateTime: + case QMetaType::QUrl: + case QMetaType::QLocale: + case QMetaType::QRect: + case QMetaType::QRectF: + case QMetaType::QSize: + case QMetaType::QSizeF: + case QMetaType::QLine: + case QMetaType::QLineF: + case QMetaType::QPoint: + case QMetaType::QPointF: + case QMetaType::QVector3D: +#ifndef QT_NO_REGEXP + case QMetaType::QRegExp: +#endif + case QMetaType::Void: +#ifdef QT3_SUPPORT + case QMetaType::QColorGroup: +#endif + case QMetaType::QFont: + case QMetaType::QPixmap: + case QMetaType::QBrush: + case QMetaType::QColor: + case QMetaType::QPalette: + case QMetaType::QIcon: + case QMetaType::QImage: + case QMetaType::QPolygon: + case QMetaType::QRegion: + case QMetaType::QBitmap: +#ifndef QT_NO_CURSOR + case QMetaType::QCursor: +#endif + case QMetaType::QSizePolicy: + case QMetaType::QKeySequence: + case QMetaType::QPen: + case QMetaType::QTextLength: + case QMetaType::QTextFormat: + case QMetaType::QMatrix: + case QMetaType::QTransform: + case QMetaType::QMatrix4x4: + case QMetaType::QVector2D: + case QMetaType::QVector4D: + case QMetaType::QQuaternion: + return true; + + default: + if (type == qMetaTypeId<QVariant>() || + type == qMetaTypeId<QScriptValue>() || + typeCategory(type) != Unknown) { + return true; + } + break; + } + + return false; +} + /*! Copies \a copy into \a data, assuming they both are of type \a type. If \a copy is zero, a default type is copied. Returns true if the copy was diff --git a/src/declarative/qml/qdeclarativemetatype_p.h b/src/declarative/qml/qdeclarativemetatype_p.h index 4e84ee8..aab1c31 100644 --- a/src/declarative/qml/qdeclarativemetatype_p.h +++ b/src/declarative/qml/qdeclarativemetatype_p.h @@ -69,6 +69,7 @@ class QDeclarativeTypePrivate; class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeMetaType { public: + static bool canCopy(int type); static bool copy(int type, void *data, const void *copy = 0); static QList<QByteArray> qmlTypeNames(); @@ -76,6 +77,7 @@ public: static QDeclarativeType *qmlType(const QByteArray &, int, int); static QDeclarativeType *qmlType(const QMetaObject *); + static QDeclarativeType *qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor); static QDeclarativeType *qmlType(int); static QMetaProperty defaultProperty(const QMetaObject *); @@ -112,9 +114,12 @@ public: QByteArray typeName() const; QByteArray qmlTypeName() const; + QByteArray module() const; int majorVersion() const; int minorVersion() const; + bool availableInVersion(int vmajor, int vminor) const; + bool availableInVersion(const QByteArray &module, int vmajor, int vminor) const; QObject *create() const; void create(QObject **, void **, size_t) const; @@ -135,6 +140,8 @@ public: const QMetaObject *metaObject() const; const QMetaObject *baseMetaObject() const; + int metaObjectRevision() const; + bool containsRevisionedAttributes() const; QDeclarativeAttachedPropertiesFunc attachedPropertiesFunction() const; const QMetaObject *attachedPropertiesType() const; @@ -149,6 +156,7 @@ public: int index() const; private: + QDeclarativeType *superType() const; friend class QDeclarativeTypePrivate; friend struct QDeclarativeMetaTypeData; friend int registerType(const QDeclarativePrivate::RegisterType &); diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index eea928c..2aa2059 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -149,8 +149,8 @@ QDeclarativeObjectScriptClass::queryProperty(Object *object, const Identifier &n QScriptClass::QueryFlags QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name, - QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext, - QueryHints hints) + QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext, + QueryHints hints) { Q_UNUSED(flags); lastData = 0; @@ -165,6 +165,12 @@ QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &nam QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine); lastData = QDeclarativePropertyCache::property(engine, obj, name, local); + if ((hints & ImplicitObject) && lastData && lastData->revision != 0) { + + QDeclarativeData *ddata = QDeclarativeData::get(obj); + if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData)) + return 0; + } if (lastData) return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess; @@ -354,8 +360,20 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, } } + QDeclarativeBinding *newBinding = 0; + if (value.isFunction() && !value.isRegExp()) { + QScriptContextInfo ctxtInfo(context); + QDeclarativePropertyCache::ValueTypeData valueTypeData; + + newBinding = new QDeclarativeBinding(value, obj, evalContext); + newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); + newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext)); + if (newBinding->expression().contains("this")) + newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); + } + QDeclarativeAbstractBinding *delBinding = - QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, 0); + QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding); if (delBinding) delBinding->destroy(); @@ -374,9 +392,8 @@ void QDeclarativeObjectScriptClass::setProperty(QObject *obj, QString error = QLatin1String("Cannot assign [undefined] to ") + QLatin1String(QMetaType::typeName(lastData->propType)); context->throwError(error); - } else if (!value.isRegExp() && value.isFunction()) { - QString error = QLatin1String("Cannot assign a function to a property."); - context->throwError(error); + } else if (value.isFunction() && !value.isRegExp()) { + // this is handled by the binding creation above } else { QVariant v; if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) diff --git a/src/declarative/qml/qdeclarativeparser.cpp b/src/declarative/qml/qdeclarativeparser.cpp index da4016e..35bb0f1 100644 --- a/src/declarative/qml/qdeclarativeparser.cpp +++ b/src/declarative/qml/qdeclarativeparser.cpp @@ -66,13 +66,14 @@ using namespace QDeclarativeJS; using namespace QDeclarativeParser; QDeclarativeParser::Object::Object() -: type(-1), majorVersion(-1), minorVersion(-1), idIndex(-1), metatype(0), defaultProperty(0), parserStatusCast(-1) +: type(-1), majorVersion(-1), minorVersion(-1), idIndex(-1), metatype(0), synthCache(0), defaultProperty(0), parserStatusCast(-1) { } QDeclarativeParser::Object::~Object() { if (defaultProperty) defaultProperty->release(); + if (synthCache) synthCache->release(); foreach(Property *prop, properties) prop->release(); foreach(Property *prop, valueProperties) diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h index 6ef2811..8f41a91 100644 --- a/src/declarative/qml/qdeclarativeparser_p.h +++ b/src/declarative/qml/qdeclarativeparser_p.h @@ -71,6 +71,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) +class QDeclarativePropertyCache; namespace QDeclarativeJS { namespace AST { class Node; } } /* @@ -154,6 +155,7 @@ namespace QDeclarativeParser QAbstractDynamicMetaObject extObject; QByteArray metadata; // Generated by compiler QByteArray synthdata; // Generated by compiler + QDeclarativePropertyCache *synthCache; // Generated by compiler Property *getDefaultProperty(); Property *getProperty(const QByteArray &name, bool create=true); diff --git a/src/declarative/qml/qdeclarativeprivate.h b/src/declarative/qml/qdeclarativeprivate.h index 6e73ec9..7ac3369 100644 --- a/src/declarative/qml/qdeclarativeprivate.h +++ b/src/declarative/qml/qdeclarativeprivate.h @@ -214,6 +214,8 @@ namespace QDeclarativePrivate const QMetaObject *extensionMetaObject; QDeclarativeCustomParser *customParser; + int revision; + // If this is extended ensure "version" is bumped!!! }; struct RegisterInterface { diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 8210314..61e3002 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -106,15 +106,16 @@ qWarning() << "Pixel size should now be 24:" << property.read().toInt(); Create an invalid QDeclarativeProperty. */ QDeclarativeProperty::QDeclarativeProperty() -: d(new QDeclarativePropertyPrivate) +: d(0) { - d->q = this; } /*! \internal */ QDeclarativeProperty::~QDeclarativeProperty() { - delete d; d = 0; + if (d) + d->release(); + d = 0; } /*! @@ -124,7 +125,6 @@ QDeclarativeProperty::~QDeclarativeProperty() QDeclarativeProperty::QDeclarativeProperty(QObject *obj) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->initDefault(obj); } @@ -137,7 +137,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj) QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeContext *ctxt) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = ctxt?QDeclarativeContextData::get(ctxt):0; d->engine = ctxt?ctxt->engine():0; d->initDefault(obj); @@ -152,7 +151,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeContext *ct QDeclarativeProperty::QDeclarativeProperty(QObject *obj, QDeclarativeEngine *engine) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = 0; d->engine = engine; d->initDefault(obj); @@ -178,7 +176,6 @@ void QDeclarativePropertyPrivate::initDefault(QObject *obj) QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->initProperty(obj, name); if (!isValid()) d->object = 0; } @@ -190,7 +187,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name) QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QDeclarativeContext *ctxt) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = ctxt?QDeclarativeContextData::get(ctxt):0; d->engine = ctxt?ctxt->engine():0; d->initProperty(obj, name); @@ -205,7 +201,6 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QD QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QDeclarativeEngine *engine) : d(new QDeclarativePropertyPrivate) { - d->q = this; d->context = 0; d->engine = engine; d->initProperty(obj, name); @@ -315,6 +310,8 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name if (property && !(property->flags & QDeclarativePropertyCache::Data::IsFunction)) { object = currentObject; core = *property; + nameCache = terminal; + isNameCached = true; } } @@ -322,9 +319,10 @@ void QDeclarativePropertyPrivate::initProperty(QObject *obj, const QString &name Create a copy of \a other. */ QDeclarativeProperty::QDeclarativeProperty(const QDeclarativeProperty &other) -: d(new QDeclarativePropertyPrivate(*other.d)) { - d->q = this; + d = other.d; + if (d) + d->addref(); } /*! @@ -353,13 +351,13 @@ QDeclarativeProperty::QDeclarativeProperty(const QDeclarativeProperty &other) */ QDeclarativeProperty::PropertyTypeCategory QDeclarativeProperty::propertyTypeCategory() const { - return d->propertyTypeCategory(); + return d ? d->propertyTypeCategory() : InvalidCategory; } QDeclarativeProperty::PropertyTypeCategory QDeclarativePropertyPrivate::propertyTypeCategory() const { - uint type = q->type(); + uint type = this->type(); if (isValueType()) { return QDeclarativeProperty::Normal; @@ -386,6 +384,8 @@ QDeclarativePropertyPrivate::propertyTypeCategory() const */ const char *QDeclarativeProperty::propertyTypeName() const { + if (!d) + return 0; if (d->isValueType()) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context); @@ -412,6 +412,8 @@ const char *QDeclarativeProperty::propertyTypeName() const */ bool QDeclarativeProperty::operator==(const QDeclarativeProperty &other) const { + if (!d || !other.d) + return false; // category is intentially omitted here as it is generated // from the other members return d->object == other.d->object && @@ -425,7 +427,7 @@ bool QDeclarativeProperty::operator==(const QDeclarativeProperty &other) const */ int QDeclarativeProperty::propertyType() const { - return d->propertyType(); + return d ? d->propertyType() : QVariant::Invalid; } bool QDeclarativePropertyPrivate::isValueType() const @@ -435,7 +437,7 @@ bool QDeclarativePropertyPrivate::isValueType() const int QDeclarativePropertyPrivate::propertyType() const { - uint type = q->type(); + uint type = this->type(); if (isValueType()) { return valueType.valueTypePropType; } else if (type & QDeclarativeProperty::Property) { @@ -448,17 +450,22 @@ int QDeclarativePropertyPrivate::propertyType() const } } +QDeclarativeProperty::Type QDeclarativePropertyPrivate::type() const +{ + if (core.flags & QDeclarativePropertyCache::Data::IsFunction) + return QDeclarativeProperty::SignalProperty; + else if (core.isValid()) + return QDeclarativeProperty::Property; + else + return QDeclarativeProperty::Invalid; +} + /*! Returns the type of the property. */ QDeclarativeProperty::Type QDeclarativeProperty::type() const { - if (d->core.flags & QDeclarativePropertyCache::Data::IsFunction) - return SignalProperty; - else if (d->core.isValid()) - return Property; - else - return Invalid; + return d ? d->type() : Invalid; } /*! @@ -482,7 +489,7 @@ bool QDeclarativeProperty::isSignalProperty() const */ QObject *QDeclarativeProperty::object() const { - return d->object; + return d ? d->object : 0; } /*! @@ -490,15 +497,11 @@ QObject *QDeclarativeProperty::object() const */ QDeclarativeProperty &QDeclarativeProperty::operator=(const QDeclarativeProperty &other) { - d->context = other.d->context; - d->engine = other.d->engine; - d->object = other.d->object; - - d->isNameCached = other.d->isNameCached; - d->core = other.d->core; - d->nameCache = other.d->nameCache; - - d->valueType = other.d->valueType; + if (d) + d->release(); + d = other.d; + if (d) + d->addref(); return *this; } @@ -508,6 +511,8 @@ QDeclarativeProperty &QDeclarativeProperty::operator=(const QDeclarativeProperty */ bool QDeclarativeProperty::isWritable() const { + if (!d) + return false; if (!d->object) return false; if (d->core.flags & QDeclarativePropertyCache::Data::IsQList) //list @@ -525,6 +530,8 @@ bool QDeclarativeProperty::isWritable() const */ bool QDeclarativeProperty::isDesignable() const { + if (!d) + return false; if (type() & Property && d->core.isValid() && d->object) return d->object->metaObject()->property(d->core.coreIndex).isDesignable(); else @@ -536,6 +543,8 @@ bool QDeclarativeProperty::isDesignable() const */ bool QDeclarativeProperty::isResettable() const { + if (!d) + return false; if (type() & Property && d->core.isValid() && d->object) return d->core.flags & QDeclarativePropertyCache::Data::IsResettable; else @@ -548,6 +557,8 @@ bool QDeclarativeProperty::isResettable() const */ bool QDeclarativeProperty::isValid() const { + if (!d) + return false; return type() != Invalid; } @@ -556,6 +567,8 @@ bool QDeclarativeProperty::isValid() const */ QString QDeclarativeProperty::name() const { + if (!d) + return QString(); if (!d->isNameCached) { // ### if (!d->object) { @@ -592,6 +605,8 @@ QString QDeclarativeProperty::name() const */ QMetaProperty QDeclarativeProperty::property() const { + if (!d) + return QMetaProperty(); if (type() & Property && d->core.isValid() && d->object) return d->object->metaObject()->property(d->core.coreIndex); else @@ -604,6 +619,8 @@ QMetaProperty QDeclarativeProperty::property() const */ QMetaMethod QDeclarativeProperty::method() const { + if (!d) + return QMetaMethod(); if (type() & SignalProperty && d->object) return d->object->metaObject()->method(d->core.coreIndex); else @@ -617,7 +634,7 @@ QMetaMethod QDeclarativeProperty::method() const QDeclarativeAbstractBinding * QDeclarativePropertyPrivate::binding(const QDeclarativeProperty &that) { - if (!that.isProperty() || !that.d->object) + if (!that.d || !that.isProperty() || !that.d->object) return 0; return binding(that.d->object, that.d->core.coreIndex, that.d->valueType.valueTypeCoreIdx); @@ -641,7 +658,7 @@ QDeclarativePropertyPrivate::setBinding(const QDeclarativeProperty &that, QDeclarativeAbstractBinding *newBinding, WriteFlags flags) { - if (!that.isProperty() || !that.d->object) { + if (!that.d || !that.isProperty() || !that.d->object) { if (newBinding) newBinding->destroy(); return 0; @@ -891,6 +908,8 @@ QDeclarativePropertyPrivate::setSignalExpression(const QDeclarativeProperty &tha */ QVariant QDeclarativeProperty::read() const { + if (!d) + return QVariant(); if (!d->object) return QVariant(); @@ -1032,8 +1051,10 @@ bool QDeclarativePropertyPrivate::writeEnumProperty(const QMetaProperty &prop, i bool QDeclarativePropertyPrivate::writeValueProperty(const QVariant &value, WriteFlags flags) { // Remove any existing bindings on this property - if (!(flags & DontRemoveBinding)) { - QDeclarativeAbstractBinding *binding = setBinding(*q, 0); + if (!(flags & DontRemoveBinding) && + (type() & QDeclarativeProperty::Property) && object) { + QDeclarativeAbstractBinding *binding = setBinding(object, core.coreIndex, + valueType.valueTypeCoreIdx, 0, flags); if (binding) binding->destroy(); } @@ -1312,6 +1333,8 @@ bool QDeclarativeProperty::reset() const bool QDeclarativePropertyPrivate::write(const QDeclarativeProperty &that, const QVariant &value, WriteFlags flags) { + if (!that.d) + return false; if (that.d->object && that.type() & QDeclarativeProperty::Property && that.d->core.isValid() && that.isWritable()) return that.d->writeValueProperty(value, flags); @@ -1390,12 +1413,12 @@ bool QDeclarativeProperty::connectNotifySignal(QObject *dest, const char *slot) */ int QDeclarativeProperty::index() const { - return d->core.coreIndex; + return d ? d->core.coreIndex : -1; } int QDeclarativePropertyPrivate::valueTypeCoreIndex(const QDeclarativeProperty &that) { - return that.d->valueType.valueTypeCoreIdx; + return that.d ? that.d->valueType.valueTypeCoreIdx : -1; } /*! @@ -1404,6 +1427,8 @@ int QDeclarativePropertyPrivate::valueTypeCoreIndex(const QDeclarativeProperty & */ int QDeclarativePropertyPrivate::bindingIndex(const QDeclarativeProperty &that) { + if (!that.d) + return -1; int rv = that.d->core.coreIndex; if (rv != -1 && that.d->valueType.valueTypeCoreIdx != -1) rv = rv | (that.d->valueType.valueTypeCoreIdx << 24); @@ -1455,18 +1480,28 @@ QDeclarativePropertyPrivate::restore(const QByteArray &data, QObject *object, QD if (data.isEmpty()) return prop; - prop.d->object = object; - prop.d->context = ctxt; - prop.d->engine = ctxt->engine; - const SerializedData *sd = (const SerializedData *)data.constData(); if (sd->isValueType) { const ValueTypeSerializedData *vt = (const ValueTypeSerializedData *)sd; - prop.d->core = vt->core; - prop.d->valueType = vt->valueType; + return restore(vt->core, vt->valueType, object, ctxt); } else { - prop.d->core = sd->core; + QDeclarativePropertyCache::ValueTypeData data; + return restore(sd->core, data, object, ctxt); } +} + +QDeclarativeProperty +QDeclarativePropertyPrivate::restore(const QDeclarativePropertyCache::Data &data, const QDeclarativePropertyCache::ValueTypeData &valueType, QObject *object, QDeclarativeContextData *ctxt) +{ + QDeclarativeProperty prop; + + prop.d = new QDeclarativePropertyPrivate; + prop.d->object = object; + prop.d->context = ctxt; + prop.d->engine = ctxt->engine; + + prop.d->core = data; + prop.d->valueType = valueType; return prop; } diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index 334cfcf..bd2c891 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -65,23 +65,15 @@ QT_BEGIN_NAMESPACE class QDeclarativeContext; class QDeclarativeEnginePrivate; class QDeclarativeExpression; -class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyPrivate +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyPrivate : public QDeclarativeRefCount { public: enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02, RemoveBindingOnAliasWrite = 0x04 }; Q_DECLARE_FLAGS(WriteFlags, WriteFlag) QDeclarativePropertyPrivate() - : q(0), context(0), engine(0), object(0), isNameCached(false) {} - + : context(0), engine(0), object(0), isNameCached(false) {} - QDeclarativePropertyPrivate(const QDeclarativePropertyPrivate &other) - : q(0), context(other.context), engine(other.engine), object(other.object), - isNameCached(other.isNameCached), - core(other.core), nameCache(other.nameCache), - valueType(other.valueType) {} - - QDeclarativeProperty *q; QDeclarativeContextData *context; QDeclarativeEngine *engine; QDeclarativeGuard<QObject> object; @@ -98,6 +90,7 @@ public: bool isValueType() const; int propertyType() const; + QDeclarativeProperty::Type type() const; QDeclarativeProperty::PropertyTypeCategory propertyTypeCategory() const; QVariant readValueProperty(); @@ -119,7 +112,12 @@ public: static QByteArray saveValueType(const QMetaObject *, int, const QMetaObject *, int); static QByteArray saveProperty(const QMetaObject *, int); + static QDeclarativeProperty restore(const QByteArray &, QObject *, QDeclarativeContextData *); + static QDeclarativeProperty restore(const QDeclarativePropertyCache::Data &, + const QDeclarativePropertyCache::ValueTypeData &, + QObject *, + QDeclarativeContextData *); static bool equal(const QMetaObject *, const QMetaObject *); static bool canConvert(const QMetaObject *from, const QMetaObject *to); diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index 91badae..6a39a65 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -88,6 +88,7 @@ void QDeclarativePropertyCache::Data::load(const QMetaProperty &p, QDeclarativeE coreIndex = p.propertyIndex(); notifyIndex = p.notifySignalIndex(); flags = flagsForProperty(p, engine); + revision = p.revision(); } void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) @@ -106,6 +107,7 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m) QList<QByteArray> params = m.parameterTypes(); if (!params.isEmpty()) flags |= Data::HasArguments; + revision = m.revision(); } @@ -216,6 +218,7 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const cache->methodIndexCache = methodIndexCache; cache->stringCache = stringCache; cache->identifierCache = identifierCache; + cache->allowedRevisionCache = allowedRevisionCache; for (int ii = 0; ii < indexCache.count(); ++ii) { if (indexCache.at(ii)) indexCache.at(ii)->addref(); @@ -234,8 +237,18 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) { - QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); + append(engine, metaObject, -1, propertyFlags, methodFlags, signalFlags); +} + +void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaObject *metaObject, + int revision, + Data::Flag propertyFlags, Data::Flag methodFlags, Data::Flag signalFlags) +{ + Q_UNUSED(revision); + + allowedRevisionCache.append(0); + QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine); int methodCount = metaObject->methodCount(); // 3 to block the destroyed signal and the deleteLater() slot int methodOffset = qMax(3, metaObject->methodOffset()); @@ -261,11 +274,15 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb else if (m.methodType() == QMetaMethod::Signal) data->flags |= signalFlags; + data->metaObjectOffset = allowedRevisionCache.count() - 1; + if (stringCache.contains(methodName)) { RData *old = stringCache[methodName]; // We only overload methods in the same class, exactly like C++ if (old->flags & Data::IsFunction && old->coreIndex >= methodOffset) data->relatedIndex = old->coreIndex; + data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); + data->overrideIndex = old->coreIndex; stringCache[methodName]->release(); identifierCache[data->identifier.identifier]->release(); } @@ -294,7 +311,12 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb data->load(p, engine); data->flags |= propertyFlags; + data->metaObjectOffset = allowedRevisionCache.count() - 1; + if (stringCache.contains(propName)) { + RData *old = stringCache[propName]; + data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction); + data->overrideIndex = old->coreIndex; stringCache[propName]->release(); identifierCache[data->identifier.identifier]->release(); } diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index df2412c..eeeff1a 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -110,6 +110,10 @@ public: int notifyIndex; // When !IsFunction int relatedIndex; // When IsFunction }; + uint overrideIndexIsProperty : 1; + int overrideIndex : 31; + int revision; + int metaObjectOffset; static Flags flagsForProperty(const QMetaProperty &, QDeclarativeEngine *engine = 0); void load(const QMetaProperty &, QDeclarativeEngine *engine = 0); @@ -131,8 +135,9 @@ public: QDeclarativePropertyCache *copy() const; void append(QDeclarativeEngine *, const QMetaObject *, Data::Flag propertyFlags = Data::NoFlags, Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags); + void append(QDeclarativeEngine *, const QMetaObject *, int revision, Data::Flag propertyFlags = Data::NoFlags, + Data::Flag methodFlags = Data::NoFlags, Data::Flag signalFlags = Data::NoFlags); - static QDeclarativePropertyCache *create(QDeclarativeEngine *, const QMetaObject *); static Data create(const QMetaObject *, const QString &); inline Data *property(const QScriptDeclarativeClass::Identifier &id) const; @@ -141,13 +146,19 @@ public: Data *method(int) const; QStringList propertyNames() const; + inline Data *overrideData(Data *) const; + inline bool isAllowedInRevision(Data *) const; + inline QDeclarativeEngine *qmlEngine() const; static Data *property(QDeclarativeEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &); static Data *property(QDeclarativeEngine *, QObject *, const QString &, Data &); + protected: virtual void clear(); private: + friend class QDeclarativeEnginePrivate; + struct RData : public Data, public QDeclarativeRefCount { QScriptDeclarativeClass::PersistentIdentifier identifier; }; @@ -155,6 +166,7 @@ private: typedef QVector<RData *> IndexCache; typedef QHash<QString, RData *> StringCache; typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache; + typedef QVector<int> AllowedRevisionCache; void updateRecur(QDeclarativeEngine *, const QMetaObject *); @@ -163,11 +175,13 @@ private: IndexCache methodIndexCache; StringCache stringCache; IdentifierCache identifierCache; + AllowedRevisionCache allowedRevisionCache; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyCache::Data::Flags); QDeclarativePropertyCache::Data::Data() -: flags(0), propType(0), coreIndex(-1), notifyIndex(-1) +: flags(0), propType(0), coreIndex(-1), notifyIndex(-1), overrideIndexIsProperty(false), overrideIndex(-1), + revision(0), metaObjectOffset(-1) { } @@ -176,7 +190,20 @@ bool QDeclarativePropertyCache::Data::operator==(const QDeclarativePropertyCache return flags == other.flags && propType == other.propType && coreIndex == other.coreIndex && - notifyIndex == other.notifyIndex; + notifyIndex == other.notifyIndex && + revision == other.revision; +} + +QDeclarativePropertyCache::Data * +QDeclarativePropertyCache::overrideData(Data *data) const +{ + if (data->overrideIndex < 0) + return 0; + + if (data->overrideIndexIsProperty) + return indexCache.at(data->overrideIndex); + else + return methodIndexCache.at(data->overrideIndex); } QDeclarativePropertyCache::Data * @@ -197,6 +224,12 @@ bool QDeclarativePropertyCache::ValueTypeData::operator==(const ValueTypeData &o valueTypePropType == o.valueTypePropType; } +bool QDeclarativePropertyCache::isAllowedInRevision(Data *data) const +{ + return (data->metaObjectOffset == -1 && data->revision == 0) || + (allowedRevisionCache[data->metaObjectOffset] >= data->revision); +} + QDeclarativeEngine *QDeclarativePropertyCache::qmlEngine() const { return engine; diff --git a/src/declarative/qml/qdeclarativerefcount_p.h b/src/declarative/qml/qdeclarativerefcount_p.h index 868cdc4..b896e5f 100644 --- a/src/declarative/qml/qdeclarativerefcount_p.h +++ b/src/declarative/qml/qdeclarativerefcount_p.h @@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Declarative) -class Q_AUTOTEST_EXPORT QDeclarativeRefCount +class Q_DECLARATIVE_EXPORT QDeclarativeRefCount { public: QDeclarativeRefCount(); diff --git a/src/declarative/qml/qdeclarativerewrite.cpp b/src/declarative/qml/qdeclarativerewrite.cpp index 2cb1c65..6311e01 100644 --- a/src/declarative/qml/qdeclarativerewrite.cpp +++ b/src/declarative/qml/qdeclarativerewrite.cpp @@ -62,12 +62,17 @@ bool SharedBindingTester::isSharable(const QString &code) if (!parser.statement()) return false; + return isSharable(parser.statement()); +} + +bool SharedBindingTester::isSharable(AST::Node *node) +{ _sharable = true; - AST::Node::acceptChild(parser.statement(), this); + AST::Node::acceptChild(node, this); return _sharable; } -QString RewriteBinding::operator()(const QString &code, bool *ok) +QString RewriteBinding::operator()(const QString &code, bool *ok, bool *sharable) { Engine engine; NodePool pool(QString(), &engine); @@ -80,10 +85,63 @@ QString RewriteBinding::operator()(const QString &code, bool *ok) return QString(); } else { if (ok) *ok = true; + if (sharable) { + SharedBindingTester tester; + *sharable = tester.isSharable(parser.statement()); + } } return rewrite(code, 0, parser.statement()); } +QString RewriteBinding::operator()(QDeclarativeJS::AST::Node *node, const QString &code, bool *sharable) +{ + if (!node) + return code; + + if (sharable) { + SharedBindingTester tester; + *sharable = tester.isSharable(node); + } + + QDeclarativeJS::AST::ExpressionNode *expression = node->expressionCast(); + QDeclarativeJS::AST::Statement *statement = node->statementCast(); + if(!expression && !statement) + return code; + + TextWriter w; + _writer = &w; + _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin(); + _inLoop = 0; + + accept(node); + + unsigned startOfStatement = 0; + unsigned endOfStatement = (expression ? expression->lastSourceLocation().end() : statement->lastSourceLocation().end()) - _position; + + QString startString = QLatin1String("(function ") + QString::fromUtf8(_name) + QLatin1String("() { "); + if (expression) + startString += QLatin1String("return "); + _writer->replace(startOfStatement, 0, startString); + _writer->replace(endOfStatement, 0, QLatin1String(" })")); + + if (rewriteDump()) { + qWarning() << "============================================================="; + qWarning() << "Rewrote:"; + qWarning() << qPrintable(code); + } + + QString codeCopy = code; + w.write(&codeCopy); + + if (rewriteDump()) { + qWarning() << "To:"; + qWarning() << qPrintable(code); + qWarning() << "============================================================="; + } + + return codeCopy; +} + void RewriteBinding::accept(AST::Node *node) { AST::Node::acceptChild(node, this); diff --git a/src/declarative/qml/qdeclarativerewrite_p.h b/src/declarative/qml/qdeclarativerewrite_p.h index fc44a81..7c20a39 100644 --- a/src/declarative/qml/qdeclarativerewrite_p.h +++ b/src/declarative/qml/qdeclarativerewrite_p.h @@ -68,6 +68,7 @@ class SharedBindingTester : protected AST::Visitor bool _sharable; public: bool isSharable(const QString &code); + bool isSharable(AST::Node *Node); virtual bool visit(AST::FunctionDeclaration *) { _sharable = false; return false; } virtual bool visit(AST::FunctionExpression *) { _sharable = false; return false; } @@ -81,7 +82,8 @@ class RewriteBinding: protected AST::Visitor QByteArray _name; public: - QString operator()(const QString &code, bool *ok = 0); + QString operator()(const QString &code, bool *ok = 0, bool *sharable = 0); + QString operator()(QDeclarativeJS::AST::Node *node, const QString &code, bool *sharable = 0); //name of the function: used for the debugger void setName(const QByteArray &name) { _name = name; } diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp index 4531381..996920a 100644 --- a/src/declarative/qml/qdeclarativescriptparser.cpp +++ b/src/declarative/qml/qdeclarativescriptparser.cpp @@ -170,12 +170,6 @@ private: StateStack _stateStack; QStringList _scope; QString _contents; - - inline bool isSignalProperty(const QByteArray &propertyName) const { - return (propertyName.length() >= 3 && propertyName.startsWith("on") && - ('A' <= propertyName.at(2) && 'Z' >= propertyName.at(2))); - } - }; ProcessAST::ProcessAST(QDeclarativeScriptParser *parser) @@ -307,7 +301,6 @@ ProcessAST::defineObjectBinding(AST::UiQualifiedId *propertyName, obj->location = location; if (propertyCount) { - Property *prop = currentProperty(); Value *v = new Value; v->object = obj; diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp index 7d3450d..207fb57 100644 --- a/src/declarative/qml/qdeclarativesqldatabase.cpp +++ b/src/declarative/qml/qdeclarativesqldatabase.cpp @@ -351,7 +351,7 @@ static QScriptValue qmlsqldatabase_read_transaction(QScriptContext *context, QSc } /* - Currently documented in doc/src/declarastive/globalobject.qdoc + Currently documented in doc/src/declarative/globalobject.qdoc */ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEngine *engine) { diff --git a/src/declarative/qml/qdeclarativestringconverters.cpp b/src/declarative/qml/qdeclarativestringconverters.cpp index 371c504..aa1de43 100644 --- a/src/declarative/qml/qdeclarativestringconverters.cpp +++ b/src/declarative/qml/qdeclarativestringconverters.cpp @@ -136,7 +136,7 @@ QVariant QDeclarativeStringConverters::variantFromString(const QString &s, int p QColor QDeclarativeStringConverters::colorFromString(const QString &s, bool *ok) { - if (s.startsWith(QLatin1Char('#')) && s.length() == 9) { + if (s.length() == 9 && s.startsWith(QLatin1Char('#'))) { uchar a = fromHex(s, 1); uchar r = fromHex(s, 3); uchar g = fromHex(s, 5); @@ -144,9 +144,7 @@ QColor QDeclarativeStringConverters::colorFromString(const QString &s, bool *ok) if (ok) *ok = true; return QColor(r, g, b, a); } else { - QColor rv; - if (s.startsWith(QLatin1Char('#')) || QColor::colorNames().contains(s.toLower())) - rv = QColor(s); + QColor rv(s); if (ok) *ok = rv.isValid(); return rv; } diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp index 45e6dbf..36cdde9 100644 --- a/src/declarative/qml/qdeclarativetypeloader.cpp +++ b/src/declarative/qml/qdeclarativetypeloader.cpp @@ -45,6 +45,7 @@ #include <private/qdeclarativecompiler_p.h> #include <private/qdeclarativecomponent_p.h> #include <private/qdeclarativeglobal_p.h> +#include <private/qdeclarativedebugtrace_p.h> #include <QtDeclarative/qdeclarativecomponent.h> #include <QtCore/qdebug.h> @@ -895,10 +896,12 @@ void QDeclarativeTypeData::downloadProgressChanged(qreal p) void QDeclarativeTypeData::compile() { Q_ASSERT(m_compiledData == 0); + QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Compiling); m_compiledData = new QDeclarativeCompiledData(typeLoader()->engine()); m_compiledData->url = m_imports.baseUrl(); m_compiledData->name = m_compiledData->url.toString(); + QDeclarativeDebugTrace::rangeData(QDeclarativeDebugTrace::Compiling, m_compiledData->name); QDeclarativeCompiler compiler; if (!compiler.compile(typeLoader()->engine(), this, m_compiledData)) { @@ -906,6 +909,7 @@ void QDeclarativeTypeData::compile() m_compiledData->release(); m_compiledData = 0; } + QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Compiling); } void QDeclarativeTypeData::resolveTypes() @@ -1001,6 +1005,8 @@ void QDeclarativeTypeData::resolveTypes() } if (ref.type) { + ref.majorVersion = majorVersion; + ref.minorVersion = minorVersion; foreach (QDeclarativeParser::Object *obj, parserRef->refObjects) { // store namespace for DOM obj->majorVersion = majorVersion; diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h index beee358..6938892 100644 --- a/src/declarative/qml/qdeclarativetypeloader_p.h +++ b/src/declarative/qml/qdeclarativetypeloader_p.h @@ -215,10 +215,12 @@ class Q_AUTOTEST_EXPORT QDeclarativeTypeData : public QDeclarativeDataBlob public: struct TypeReference { - TypeReference() : type(0), typeData(0) {} + TypeReference() : type(0), majorVersion(0), minorVersion(0), typeData(0) {} QDeclarativeParser::Location location; QDeclarativeType *type; + int majorVersion; + int minorVersion; QDeclarativeTypeData *typeData; }; diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp index 4a8ffe0..d3e2025 100644 --- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp +++ b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp @@ -109,9 +109,8 @@ QDeclarativeTypeNameScriptClass::queryProperty(Object *obj, const Identifier &na } else if (data->type) { - QString strName = toString(name); - - if (strName.at(0).isUpper()) { + if (startsWithUpper(name)) { + QString strName = toString(name); // Must be an enum if (data->mode == IncludeEnums) { // ### Optimize diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp index 659c986..0f884b6 100644 --- a/src/declarative/qml/qdeclarativevaluetype.cpp +++ b/src/declarative/qml/qdeclarativevaluetype.cpp @@ -71,6 +71,7 @@ int qmlRegisterValueTypeEnums(const char *uri, int versionMajor, int versionMino 0, 0, + 0, 0 }; diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp index 558ef90..200cc1c 100644 --- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp +++ b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp @@ -46,6 +46,8 @@ #include "private/qdeclarativeengine_p.h" #include "private/qdeclarativeguard_p.h" +#include <QtScript/qscriptcontextinfo.h> + QT_BEGIN_NAMESPACE struct QDeclarativeValueTypeObject : public QScriptDeclarativeClass::Object { @@ -161,17 +163,41 @@ void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier if (o->objectType == QDeclarativeValueTypeObject::Reference) { QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj); + ref->type->read(ref->object, ref->property); + QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); + + QDeclarativeBinding *newBinding = 0; + if (value.isFunction() && !value.isRegExp()) { + QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(engine)->getContext(context()); + + QDeclarativePropertyCache::Data cacheData; + cacheData.flags = QDeclarativePropertyCache::Data::IsWritable; + cacheData.propType = ref->object->metaObject()->property(ref->property).userType(); + cacheData.coreIndex = ref->property; + + QDeclarativePropertyCache::ValueTypeData valueTypeData; + valueTypeData.valueTypeCoreIdx = m_lastIndex; + valueTypeData.valueTypePropType = p.userType(); + + newBinding = new QDeclarativeBinding(value, ref->object, ctxt); + QScriptContextInfo ctxtInfo(context()); + newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber()); + QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt); + newBinding->setTarget(prop); + if (newBinding->expression().contains("this")) + newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject); + } + QDeclarativeAbstractBinding *delBinding = - QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, 0); + QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, newBinding); if (delBinding) delBinding->destroy(); - ref->type->read(ref->object, ref->property); - QMetaProperty p = ref->type->metaObject()->property(m_lastIndex); if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) v = v.toInt(); p.write(ref->type, v); ref->type->write(ref->object, ref->property, 0); + } else { QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj); copy->type->setValue(copy->value); diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index fb07bef..366c64b 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -247,8 +247,12 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, ::memset(o, 0, instr.createSimple.typeSize + sizeof(QDeclarativeData)); instr.createSimple.create(o); - QDeclarativeData *ddata = - (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); + QDeclarativeData *ddata = (QDeclarativeData *)(((const char *)o) + instr.createSimple.typeSize); + const QDeclarativeCompiledData::TypeReference &ref = types.at(instr.createSimple.type); + if (!ddata->propertyCache && ref.typePropertyCache) { + ddata->propertyCache = ref.typePropertyCache; + ddata->propertyCache->addref(); + } ddata->lineNumber = instr.line; ddata->columnNumber = instr.createSimple.column; @@ -320,10 +324,12 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, (void)new QDeclarativeVMEMetaObject(target, &mo, data, comp); - QDeclarativeData *ddata = QDeclarativeData::get(target, true); - if (ddata->propertyCache) ddata->propertyCache->release(); - ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); - ddata->propertyCache->addref(); + if (instr.storeMeta.propertyCache != -1) { + QDeclarativeData *ddata = QDeclarativeData::get(target, true); + if (ddata->propertyCache) ddata->propertyCache->release(); + ddata->propertyCache = propertyCaches.at(instr.storeMeta.propertyCache); + ddata->propertyCache->addref(); + } } break; @@ -974,6 +980,11 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData ddata->ownMemory = false; QObjectPrivate::get(rv)->declarativeData = ddata; + if (typePropertyCache && !ddata->propertyCache) { + ddata->propertyCache = typePropertyCache; + ddata->propertyCache->addref(); + } + return rv; } else { Q_ASSERT(component); diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index a3a32e9..2e8ab18 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -43,6 +43,7 @@ #include "private/qdeclarativelistmodel_p.h" #include "private/qdeclarativelistmodelworkeragent_p.h" #include "private/qdeclarativeengine_p.h" +#include "private/qdeclarativeexpression_p.h" #include <QtCore/qcoreevent.h> #include <QtCore/qcoreapplication.h> @@ -104,6 +105,19 @@ private: int m_id; }; +class WorkerErrorEvent : public QEvent +{ +public: + enum Type { WorkerError = WorkerRemoveEvent::WorkerRemove + 1 }; + + WorkerErrorEvent(const QDeclarativeError &error); + + QDeclarativeError error() const; + +private: + QDeclarativeError m_error; +}; + class QDeclarativeWorkerScriptEnginePrivate : public QObject { Q_OBJECT @@ -146,6 +160,7 @@ public: WorkerScript(); int id; + QUrl source; bool initialized; QDeclarativeWorkerScript *owner; QScriptValue object; @@ -173,6 +188,7 @@ protected: private: void processMessage(int, const QVariant &); void processLoad(int, const QUrl &); + void reportScriptException(WorkerScript *); }; QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine) @@ -273,6 +289,11 @@ void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QVarian args.setProperty(0, variantToScriptValue(data, workerEngine)); script->callback.call(script->object, args); + + if (workerEngine->hasUncaughtException()) { + reportScriptException(script); + workerEngine->clearExceptions(); + } } } @@ -286,7 +307,7 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) QFile f(fileName); if (f.open(QIODevice::ReadOnly)) { QByteArray data = f.readAll(); - QString script = QString::fromUtf8(data); + QString sourceCode = QString::fromUtf8(data); QScriptValue activation = getWorker(id); @@ -296,10 +317,19 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) ctxt->pushScope(urlContext); ctxt->pushScope(activation); ctxt->setActivationObject(activation); - QDeclarativeScriptParser::extractPragmas(script); + QDeclarativeScriptParser::extractPragmas(sourceCode); workerEngine->baseUrl = url; - workerEngine->evaluate(script); + workerEngine->evaluate(sourceCode); + + WorkerScript *script = workers.value(id); + if (script) { + script->source = url; + if (workerEngine->hasUncaughtException()) { + reportScriptException(script); + workerEngine->clearExceptions(); + } + } workerEngine->popContext(); } else { @@ -307,6 +337,22 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) } } +void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script) +{ + if (!script || !workerEngine->hasUncaughtException()) + return; + + QDeclarativeError error; + QDeclarativeExpressionPrivate::exceptionToError(workerEngine, error); + error.setUrl(script->source); + + QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(workerEngine); + + QMutexLocker(&p->m_lock); + if (script->owner) + QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error)); +} + QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value) { if (value.isBool()) { @@ -453,6 +499,16 @@ int WorkerRemoveEvent::workerId() const return m_id; } +WorkerErrorEvent::WorkerErrorEvent(const QDeclarativeError &error) +: QEvent((QEvent::Type)WorkerError), m_error(error) +{ +} + +QDeclarativeError WorkerErrorEvent::error() const +{ + return m_error; +} + QDeclarativeWorkerScriptEngine::QDeclarativeWorkerScriptEngine(QDeclarativeEngine *parent) : QThread(parent), d(new QDeclarativeWorkerScriptEnginePrivate(parent)) { @@ -544,12 +600,7 @@ void QDeclarativeWorkerScriptEngine::run() The above worker script specifies a JavaScript file, "script.js", that handles the operations to be performed in the new thread. Here is \c script.js: - \qml - WorkerScript.onMessage = function(message) { - // ... long-running operations and calculations are done here - WorkerScript.sendMessage({ 'reply': 'Mouse is at ' + message.x + ',' + message.y }) - } - \endqml + \quotefile doc/src/snippets/declarative/script.js When the user clicks anywhere within the rectangle, \c sendMessage() is called, triggering the \tt WorkerScript.onMessage() handler in @@ -687,6 +738,10 @@ bool QDeclarativeWorkerScript::event(QEvent *event) emit message(value); } return true; + } else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) { + WorkerErrorEvent *workerEvent = static_cast<WorkerErrorEvent *>(event); + QDeclarativeEnginePrivate::warning(qmlEngine(this), workerEvent->error()); + return true; } else { return QObject::event(event); } diff --git a/src/declarative/qml/qmetaobjectbuilder.cpp b/src/declarative/qml/qmetaobjectbuilder.cpp index cefc561..6a0226f 100644 --- a/src/declarative/qml/qmetaobjectbuilder.cpp +++ b/src/declarative/qml/qmetaobjectbuilder.cpp @@ -122,7 +122,7 @@ enum PropertyFlags { User = 0x00100000, ResolveUser = 0x00200000, Notify = 0x00400000, - Dynamic = 0x00800000 + Revisioned = 0x00800000 }; enum MethodFlags { @@ -139,7 +139,8 @@ enum MethodFlags { MethodCompatibility = 0x10, MethodCloned = 0x20, - MethodScriptable = 0x40 + MethodScriptable = 0x40, + MethodRevisioned = 0x80 }; struct QMetaObjectPrivate @@ -2277,21 +2278,6 @@ bool QMetaPropertyBuilder::isEnumOrFlag() const } /*! - Returns true if the property has the dynamic flag set; - otherwise returns false. The default value is false. - - \sa setDynamic() -*/ -bool QMetaPropertyBuilder::isDynamic() const -{ - QMetaPropertyBuilderPrivate *d = d_func(); - if (d) - return d->flag(Dynamic); - else - return false; -} - -/*! Sets this property to readable if \a value is true. \sa isReadable(), setWritable() @@ -2415,19 +2401,6 @@ void QMetaPropertyBuilder::setEnumOrFlag(bool value) } /*! - Sets this property to have the dynamic flag if \a value is - true. - - \sa isDynamic() -*/ -void QMetaPropertyBuilder::setDynamic(bool value) -{ - QMetaPropertyBuilderPrivate *d = d_func(); - if (d) - d->setFlag(Dynamic, value); -} - -/*! \class QMetaEnumBuilder \internal \brief The QMetaEnumBuilder class enables modifications to an enumerator definition on a meta object builder. diff --git a/src/declarative/qml/qmetaobjectbuilder_p.h b/src/declarative/qml/qmetaobjectbuilder_p.h index 6afd755..2678bff 100644 --- a/src/declarative/qml/qmetaobjectbuilder_p.h +++ b/src/declarative/qml/qmetaobjectbuilder_p.h @@ -258,7 +258,6 @@ public: bool isUser() const; bool hasStdCppSet() const; bool isEnumOrFlag() const; - bool isDynamic() const; void setReadable(bool value); void setWritable(bool value); @@ -270,7 +269,6 @@ public: void setUser(bool value); void setStdCppSet(bool value); void setEnumOrFlag(bool value); - void setDynamic(bool value); private: const QMetaObjectBuilder *_mobj; diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 66b69f9..bf9e54a 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -55,7 +55,8 @@ SOURCES += \ $$PWD/qdeclarativedirparser.cpp \ $$PWD/qdeclarativeextensionplugin.cpp \ $$PWD/qdeclarativeimport.cpp \ - $$PWD/qdeclarativelist.cpp + $$PWD/qdeclarativelist.cpp \ + $$PWD/qperformancetimer.cpp HEADERS += \ $$PWD/qdeclarativeparser_p.h \ @@ -129,8 +130,12 @@ HEADERS += \ $$PWD/qdeclarativedirparser_p.h \ $$PWD/qdeclarativeextensioninterface.h \ $$PWD/qdeclarativeimport_p.h \ - $$PWD/qdeclarativeextensionplugin.h + $$PWD/qdeclarativeextensionplugin.h \ + $$PWD/qperformancetimer_p.h QT += sql include(parser/parser.pri) include(rewriter/rewriter.pri) + +# mirrors logic in corelib/kernel/kernel.pri +unix:!symbian: contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri) diff --git a/src/declarative/qml/qperformancetimer.cpp b/src/declarative/qml/qperformancetimer.cpp new file mode 100644 index 0000000..1d7ca80 --- /dev/null +++ b/src/declarative/qml/qperformancetimer.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qperformancetimer_p.h" + +#if defined(Q_OS_MAC) +#include <sys/time.h> +#include <unistd.h> +#include <mach/mach_time.h> +#elif defined(Q_OS_UNIX) +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#elif defined(Q_OS_SYMBIAN) +#include <e32std.h> +#include <sys/time.h> +#include <hal.h> +#elif defined(Q_OS_WIN) +#include <windows.h> +#endif + +// mac/unix code heavily copied from QElapsedTimer + +QT_BEGIN_NAMESPACE + +////////////////////////////// Mac ////////////////////////////// +#if defined(Q_OS_MAC) + +static mach_timebase_info_data_t info = {0,0}; +static qint64 absoluteToNSecs(qint64 cpuTime) +{ + if (info.denom == 0) + mach_timebase_info(&info); + qint64 nsecs = cpuTime * info.numer / info.denom; + return nsecs; +} + +void QPerformanceTimer::start() +{ + t1 = mach_absolute_time(); +} + +qint64 QPerformanceTimer::elapsed() const +{ + uint64_t cpu_time = mach_absolute_time(); + return absoluteToNSecs(cpu_time - t1); +} + +////////////////////////////// Unix ////////////////////////////// +#elif defined(Q_OS_UNIX) + +#if defined(QT_NO_CLOCK_MONOTONIC) || defined(QT_BOOTSTRAPPED) +// turn off the monotonic clock +# ifdef _POSIX_MONOTONIC_CLOCK +# undef _POSIX_MONOTONIC_CLOCK +# endif +# define _POSIX_MONOTONIC_CLOCK -1 +#endif + +#if (_POSIX_MONOTONIC_CLOCK-0 != 0) +static const bool monotonicClockChecked = true; +static const bool monotonicClockAvailable = _POSIX_MONOTONIC_CLOCK > 0; +#else +static int monotonicClockChecked = false; +static int monotonicClockAvailable = false; +#endif + +#ifdef Q_CC_GNU +# define is_likely(x) __builtin_expect((x), 1) +#else +# define is_likely(x) (x) +#endif +#define load_acquire(x) ((volatile const int&)(x)) +#define store_release(x,v) ((volatile int&)(x) = (v)) + +static void unixCheckClockType() +{ +#if (_POSIX_MONOTONIC_CLOCK-0 == 0) + if (is_likely(load_acquire(monotonicClockChecked))) + return; + +# if defined(_SC_MONOTONIC_CLOCK) + // detect if the system support monotonic timers + long x = sysconf(_SC_MONOTONIC_CLOCK); + store_release(monotonicClockAvailable, x >= 200112L); +# endif + + store_release(monotonicClockChecked, true); +#endif +} + +static inline void do_gettime(qint64 *sec, qint64 *frac) +{ +#if (_POSIX_MONOTONIC_CLOCK-0 >= 0) + unixCheckClockType(); + if (is_likely(monotonicClockAvailable)) { + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + *sec = ts.tv_sec; + *frac = ts.tv_nsec; + return; + } +#endif + *sec = 0; + *frac = 0; +} + +void QPerformanceTimer::start() +{ + do_gettime(&t1, &t2); +} + +qint64 QPerformanceTimer::elapsed() const +{ + qint64 sec, frac; + do_gettime(&sec, &frac); + sec = sec - t1; + frac = frac - t2; + + return sec * Q_INT64_C(1000000000) + frac; +} + +////////////////////////////// Symbian ////////////////////////////// +#elif defined(Q_OS_SYMBIAN) + +static qint64 getTimeFromTick(quint64 elapsed) +{ + static TInt freq; + if (!freq) + HAL::Get(HALData::EFastCounterFrequency, freq); + + // ### not sure on units + return elapsed / freq; +} + +void QPerformanceTimer::start() +{ + t1 = User::FastCounter(); +} + +qint64 QPerformanceTimer::elapsed() const +{ + return getTimeFromTick(User::FastCounter() - t1); +} + +////////////////////////////// Windows ////////////////////////////// +#elif defined(Q_OS_WIN) + +static qint64 getTimeFromTick(quint64 elapsed) +{ + static LARGE_INTEGER freq; + if (!freq.QuadPart) + QueryPerformanceFrequency(&freq); + return 1000000000 * elapsed / freq.QuadPart; +} + +void QPerformanceTimer::start() +{ + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + t1 = li.QuadPart; +} + +qint64 QPerformanceTimer::elapsed() const +{ + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + return getTimeFromTick(li.QuadPart - t1); +} + +////////////////////////////// Default ////////////////////////////// +#else + +// default implementation (no hi-perf timer) does nothing +void QPerformanceTimer::start() +{ +} + +qint64 QPerformanceTimer::elapsed() const +{ + return 0; +} + +#endif + +QT_END_NAMESPACE + + diff --git a/src/declarative/qml/qperformancetimer_p.h b/src/declarative/qml/qperformancetimer_p.h new file mode 100644 index 0000000..14310bf --- /dev/null +++ b/src/declarative/qml/qperformancetimer_p.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPERFORMANCETIMER_P_H +#define QPERFORMANCETIMER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of moc. This header file may change from version to version without notice, +// or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class Q_AUTOTEST_EXPORT QPerformanceTimer +{ +public: + void start(); + qint64 elapsed() const; + +private: + qint64 t1; + qint64 t2; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPERFORMANCETIMER_P_H diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 681cea0..eaf0cfa 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -672,7 +672,9 @@ QDeclarativeColorAnimation::~QDeclarativeColorAnimation() \qml Item { - states: [ ... ] + states: [ + // States are defined here... + ] transition: Transition { NumberAnimation { from: "#c0c0c0"; duration: 2000 } @@ -725,40 +727,29 @@ void QDeclarativeColorAnimation::setTo(const QColor &t) /*! \qmlclass ScriptAction QDeclarativeScriptAction - \ingroup qml-animation-transition + \ingroup qml-animation-transition \since 4.7 \inherits Animation \brief The ScriptAction element allows scripts to be run during an animation. - ScriptAction can be used to run script at a specific point in an animation. + ScriptAction can be used to run a script at a specific point in an animation. \qml SequentialAnimation { - NumberAnimation { ... } + NumberAnimation { + // ... + } ScriptAction { script: doSomething(); } - NumberAnimation { ... } + NumberAnimation { + // ... + } } \endqml When used as part of a Transition, you can also target a specific StateChangeScript to run using the \c scriptName property. - \qml - State { - StateChangeScript { - name: "myScript" - script: doStateStuff(); - } - } - ... - Transition { - SequentialAnimation { - NumberAnimation { ... } - ScriptAction { scriptName: "myScript" } - NumberAnimation { ... } - } - } - \endqml + \snippet doc/src/snippets/declarative/states/statechangescript.qml state and transition \sa StateChangeScript */ @@ -870,7 +861,7 @@ QAbstractAnimation *QDeclarativeScriptAction::qtAnimation() /*! \qmlclass PropertyAction QDeclarativePropertyAction - \ingroup qml-animation-transition + \ingroup qml-animation-transition \since 4.7 \inherits Animation \brief The PropertyAction element allows immediate property changes during animation. @@ -896,21 +887,14 @@ QAbstractAnimation *QDeclarativeScriptAction::qtAnimation() However, with this code, the \c transformOrigin is not set until \e after the animation, as a \l State is taken to define the values at the \e end of a transition. The animation would rotate at the default \c transformOrigin, - then jump to \c Item.BottomRight. To fix this, insert a PropertyChanges + then jump to \c Item.BottomRight. To fix this, insert a PropertyAction before the RotationAnimation begins: - \qml - transitions: Transition { - SequentialAnimation { - PropertyAction { target: rect; property: "transformOrigin" } - RotationAnimation { ... } - } - } - \endqml + \snippet doc/src/snippets/declarative/propertyaction-sequential.qml sequential This immediately sets the \c transformOrigin property to the value defined in the end state of the \l Transition (i.e. the value defined in the - PropertyChanges object) so that the rotation animation begins with the + PropertyAction object) so that the rotation animation begins with the correct transform origin. \sa {QML Animation}, QtDeclarative @@ -1195,7 +1179,9 @@ void QDeclarativeNumberAnimation::init() \qml Item { - states: [ ... ] + states: [ + // ... + ] transition: Transition { NumberAnimation { properties: "x"; from: 100; duration: 200 } @@ -1421,7 +1407,9 @@ QDeclarativeRotationAnimation::~QDeclarativeRotationAnimation() \qml Item { - states: [ ... ] + states: [ + // ... + ] transition: Transition { RotationAnimation { properties: "angle"; from: 100; duration: 2000 } @@ -2253,7 +2241,7 @@ void QDeclarativePropertyAnimation::setProperties(const QString &prop) width: 100; height: 100 color: Qt.rgba(0,0,1) //need to explicitly specify target and property - NumberAnimation { id: theAnim; target: theRect; property: "x" to: 500 } + NumberAnimation { id: theAnim; target: theRect; property: "x"; to: 500 } MouseArea { anchors.fill: parent onClicked: theAnim.start() @@ -2555,7 +2543,7 @@ void QDeclarativeParentAnimation::setNewParent(QDeclarativeItem *newParent) ParentAnimation { target: myItem via: topLevelItem - ... + // ... } \endqml */ diff --git a/src/declarative/util/qdeclarativeapplication.cpp b/src/declarative/util/qdeclarativeapplication.cpp new file mode 100644 index 0000000..e0f6df2 --- /dev/null +++ b/src/declarative/util/qdeclarativeapplication.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativeapplication_p.h" +#include <private/qobject_p.h> +#include <QtGui/QApplication> + +QT_BEGIN_NAMESPACE + +class QDeclarativeApplicationPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QDeclarativeApplication) +public: + QDeclarativeApplicationPrivate() : active(QApplication::activeWindow() != 0), + layoutDirection(QApplication::layoutDirection()) {} + bool active; + Qt::LayoutDirection layoutDirection; +}; + +/* + This object and its properties are documented as part of the Qt object, + in qdeclarativengine.cpp +*/ + +QDeclarativeApplication::QDeclarativeApplication(QObject *parent) : QObject(*new QDeclarativeApplicationPrivate(), parent) +{ + if (qApp) + qApp->installEventFilter(this); +} + +QDeclarativeApplication::~QDeclarativeApplication() +{ +} + +bool QDeclarativeApplication::active() const +{ + Q_D(const QDeclarativeApplication); + return d->active; +} + +Qt::LayoutDirection QDeclarativeApplication::layoutDirection() const +{ + Q_D(const QDeclarativeApplication); + return d->layoutDirection; +} + +bool QDeclarativeApplication::eventFilter(QObject *obj, QEvent *event) +{ + Q_UNUSED(obj) + Q_D(QDeclarativeApplication); + if (event->type() == QEvent::ApplicationActivate + || event->type() == QEvent::ApplicationDeactivate) { + bool active = d->active; + if (event->type() == QEvent::ApplicationActivate) + active = true; + else if (event->type() == QEvent::ApplicationDeactivate) + active = false; + + if (d->active != active) { + d->active = active; + emit activeChanged(); + } + } + if (event->type() == QEvent::LayoutDirectionChange) { + Qt::LayoutDirection direction = QApplication::layoutDirection(); + if (d->layoutDirection != direction) { + d->layoutDirection = direction; + emit layoutDirectionChanged(); + } + } + return false; +} + +QT_END_NAMESPACE diff --git a/src/declarative/util/qdeclarativeapplication_p.h b/src/declarative/util/qdeclarativeapplication_p.h new file mode 100644 index 0000000..caaed18 --- /dev/null +++ b/src/declarative/util/qdeclarativeapplication_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEAPPLICATION_P_H +#define QDECLARATIVEAPPLICATION_P_H + +#include <QtCore/QObject> +#include <qdeclarative.h> +#include <private/qdeclarativeglobal_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Declarative) + +class QDeclarativeApplicationPrivate; +class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeApplication : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool active READ active NOTIFY activeChanged) + Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged) + +public: + explicit QDeclarativeApplication(QObject *parent = 0); + virtual ~QDeclarativeApplication(); + bool active() const; + Qt::LayoutDirection layoutDirection() const; + +protected: + bool eventFilter(QObject *obj, QEvent *event); + +Q_SIGNALS: + void activeChanged(); + void layoutDirectionChanged(); + +private: + Q_DISABLE_COPY(QDeclarativeApplication) + Q_DECLARE_PRIVATE(QDeclarativeApplication) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeApplication) + +QT_END_HEADER + +#endif // QDECLARATIVEAPPLICATION_P_H diff --git a/src/declarative/util/qdeclarativeconnections.cpp b/src/declarative/util/qdeclarativeconnections.cpp index 6f35957..5a66aab 100644 --- a/src/declarative/util/qdeclarativeconnections.cpp +++ b/src/declarative/util/qdeclarativeconnections.cpp @@ -45,6 +45,7 @@ #include <qdeclarativeproperty_p.h> #include <qdeclarativeboundsignal_p.h> #include <qdeclarativecontext.h> +#include <qdeclarativecontext_p.h> #include <qdeclarativeinfo.h> #include <QtCore/qdebug.h> @@ -71,8 +72,8 @@ public: /*! \qmlclass Connections QDeclarativeConnections - \ingroup qml-utility-elements - \since 4.7 + \ingroup qml-utility-elements + \since 4.7 \brief A Connections element describes generalized connections to signals. A Connections object creates a connection to a QML signal. @@ -82,7 +83,7 @@ public: \qml MouseArea { - onClicked: { foo(...) } + onClicked: { foo(parameters) } } \endqml @@ -103,7 +104,7 @@ public: \qml MouseArea { Connections { - onClicked: foo(...) + onClicked: foo(parameters) } } \endqml @@ -115,10 +116,10 @@ public: MouseArea { id: area } - ... + // ... Connections { target: area - onClicked: foo(...) + onClicked: foo(parameters) } \endqml @@ -257,7 +258,11 @@ void QDeclarativeConnections::connectSignals() if (prop.isValid() && (prop.type() & QDeclarativeProperty::SignalProperty)) { QDeclarativeBoundSignal *signal = new QDeclarativeBoundSignal(target(), prop.method(), this); - signal->setExpression(new QDeclarativeExpression(qmlContext(this), 0, script)); + QDeclarativeExpression *expression = new QDeclarativeExpression(qmlContext(this), 0, script); + QDeclarativeData *ddata = QDeclarativeData::get(this); + if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) + expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); + signal->setExpression(expression); d->boundsignals += signal; } else { if (!d->ignoreUnknownSignals) diff --git a/src/declarative/util/qdeclarativefontloader.cpp b/src/declarative/util/qdeclarativefontloader.cpp index d39da3f..eba9cf9 100644 --- a/src/declarative/util/qdeclarativefontloader.cpp +++ b/src/declarative/util/qdeclarativefontloader.cpp @@ -262,8 +262,18 @@ void QDeclarativeFontLoader::updateFontInfo(const QString& name, QDeclarativeFon Example: \qml - FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" } - Text { text: "Fancy font"; font.family: webFont.name } + Item { + width: 200; height: 50 + + FontLoader { + id: webFont + source: "http://www.mysite.com/myfont.ttf" + } + Text { + text: "Fancy font" + font.family: webFont.name + } + } \endqml */ QString QDeclarativeFontLoader::name() const diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index e5ba5e0..80b52fd 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -108,9 +108,9 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM The following example shows a ListModel containing three elements, with the roles "name" and "cost". - \beginfloatright + \div {float-right} \inlineimage listmodel.png - \endfloat + \enddiv \snippet doc/src/snippets/declarative/listmodel.qml 0 @@ -133,9 +133,9 @@ QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListM The delegate displays all the fruit attributes: - \beginfloatright + \div {float-right} \inlineimage listmodel-nested.png - \endfloat + \enddiv \snippet doc/src/snippets/declarative/listmodel-nested.qml delegate @@ -559,6 +559,14 @@ QScriptValue QDeclarativeListModel::get(int index) const */ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) { + QList<int> roles; + set(index, valuemap, &roles); + if (!roles.isEmpty() && !inWorkerThread()) + emit itemsChanged(index, 1, roles); +} + +void QDeclarativeListModel::set(int index, const QScriptValue& valuemap, QList<int> *roles) +{ if (!valuemap.isObject() || valuemap.isArray()) { qmlInfo(this) << tr("set: value is not an object"); return; @@ -571,14 +579,10 @@ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) if (index == count()) { append(valuemap); } else { - QList<int> roles; if (m_flat) - m_flat->set(index, valuemap, &roles); + m_flat->set(index, valuemap, roles); else - m_nested->set(index, valuemap, &roles); - - if (!inWorkerThread()) - emit itemsChanged(index, 1, roles); + m_nested->set(index, valuemap, roles); } } @@ -597,19 +601,23 @@ void QDeclarativeListModel::set(int index, const QScriptValue& valuemap) */ void QDeclarativeListModel::setProperty(int index, const QString& property, const QVariant& value) { + QList<int> roles; + setProperty(index, property, value, &roles); + if (!roles.isEmpty() && !inWorkerThread()) + emit itemsChanged(index, 1, roles); +} + +void QDeclarativeListModel::setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles) +{ if (count() == 0 || index >= count() || index < 0) { qmlInfo(this) << tr("set: index %1 out of range").arg(index); return; } - QList<int> roles; if (m_flat) - m_flat->setProperty(index, property, value, &roles); + m_flat->setProperty(index, property, value, roles); else - m_nested->setProperty(index, property, value, &roles); - - if (!inWorkerThread()) - emit itemsChanged(index, 1, roles); + m_nested->setProperty(index, property, value, roles); } /*! @@ -1011,9 +1019,11 @@ void FlatListModel::setProperty(int index, const QString& property, const QVaria } else { role = iter.value(); } - roles->append(role); - m_values[index][role] = value; + if (m_values[index][role] != value) { + roles->append(role); + m_values[index][role] = value; + } } void FlatListModel::move(int from, int to, int n) @@ -1043,6 +1053,10 @@ bool FlatListModel::addValue(const QScriptValue &value, QHash<int, QVariant> *ro iter = m_strings.insert(name, role); if (roles) roles->append(role); + } else { + int role = iter.value(); + if (roles && row->contains(role) && row->value(role) != v) + roles->append(role); } row->insert(*iter, v); } @@ -1151,14 +1165,14 @@ void FlatListScriptClass::setProperty(Object *obj, const Identifier &name, const QHash<int, QVariant> &row = m_model->m_values[index]; row[role] = value.toVariant(); + QList<int> roles; + roles << role; if (m_model->m_parentAgent) { // This is the list in the worker thread, so tell the agent to // emit itemsChanged() later - m_model->m_parentAgent->changedData(index, 1); + m_model->m_parentAgent->changedData(index, 1, roles); } else { // This is the list in the main thread, so emit itemsChanged() - QList<int> roles; - roles << role; emit m_model->m_listModel->itemsChanged(index, 1, roles); } } @@ -1350,7 +1364,9 @@ void NestedListModel::set(int index, const QScriptValue& valuemap, QList<int> *r Q_ASSERT(index >=0 && index < count()); ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); - node->setObjectValue(valuemap); + bool emitItemsChanged = node->setObjectValue(valuemap); + if (!emitItemsChanged) + return; QScriptValueIterator it(valuemap); while (it.hasNext()) { @@ -1369,7 +1385,9 @@ void NestedListModel::setProperty(int index, const QString& property, const QVar Q_ASSERT(index >=0 && index < count()); ModelNode *node = qvariant_cast<ModelNode *>(_root->values.at(index)); - node->setProperty(property, value); + bool emitItemsChanged = node->setProperty(property, value); + if (!emitItemsChanged) + return; int r = roleStrings.indexOf(property); if (r < 0) { @@ -1441,24 +1459,37 @@ void ModelNode::clear() properties.clear(); } -void ModelNode::setObjectValue(const QScriptValue& valuemap, bool writeToCache) { +bool ModelNode::setObjectValue(const QScriptValue& valuemap, bool writeToCache) +{ + bool emitItemsChanged = false; + QScriptValueIterator it(valuemap); while (it.hasNext()) { it.next(); + ModelNode *prev = properties.value(it.name()); ModelNode *value = new ModelNode(m_model); QScriptValue v = it.value(); + if (v.isArray()) { value->isArray = true; value->setListValue(v); + if (writeToCache && objectCache) + objectCache->setValue(it.name().toUtf8(), QVariant::fromValue(value->model(m_model))); + emitItemsChanged = true; // for now, too inefficient to check whether list and sublists have changed } else { value->values << v.toVariant(); if (writeToCache && objectCache) objectCache->setValue(it.name().toUtf8(), value->values.last()); + if (!emitItemsChanged && prev && prev->values.count() == 1 + && prev->values[0] != value->values.last()) { + emitItemsChanged = true; + } } if (properties.contains(it.name())) delete properties[it.name()]; properties.insert(it.name(), value); } + return emitItemsChanged; } void ModelNode::setListValue(const QScriptValue& valuelist) { @@ -1481,9 +1512,12 @@ void ModelNode::setListValue(const QScriptValue& valuelist) { } } -void ModelNode::setProperty(const QString& prop, const QVariant& val) { +bool ModelNode::setProperty(const QString& prop, const QVariant& val) { QHash<QString, ModelNode *>::const_iterator it = properties.find(prop); + bool emitItemsChanged = false; if (it != properties.end()) { + if (val != (*it)->values[0]) + emitItemsChanged = true; (*it)->values[0] = val; } else { ModelNode *n = new ModelNode(m_model); @@ -1492,6 +1526,7 @@ void ModelNode::setProperty(const QString& prop, const QVariant& val) { } if (objectCache) objectCache->setValue(prop.toUtf8(), val); + return emitItemsChanged; } void ModelNode::updateListIndexes() @@ -1559,7 +1594,7 @@ ModelObject::ModelObject(ModelNode *node, NestedListModel *model, QScriptEngine void ModelObject::setValue(const QByteArray &name, const QVariant &val) { m_meta->setValue(name, val); - setProperty(name.constData(), val); + //setProperty(name.constData(), val); } void ModelObject::setNodeUpdatesEnabled(bool enable) @@ -1586,9 +1621,9 @@ void ModelNodeMetaObject::propertyWritten(int index) QScriptValue sv = m_seng->newObject(); sv.setProperty(propName, m_seng->newVariant(value)); - m_obj->m_node->setObjectValue(sv, false); - - m_obj->m_node->changedProperty(propName); + bool changed = m_obj->m_node->setObjectValue(sv, false); + if (changed) + m_obj->m_node->changedProperty(propName); } diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h index 5f73557..7870b4f 100644 --- a/src/declarative/util/qdeclarativelistmodel_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p.h @@ -103,6 +103,9 @@ private: // Constructs a flat list model for a worker agent QDeclarativeListModel(const QDeclarativeListModel *orig, QDeclarativeListModelWorkerAgent *parent); + void set(int index, const QScriptValue&, QList<int> *roles); + void setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles); + bool flatten(); bool inWorkerThread() const; diff --git a/src/declarative/util/qdeclarativelistmodel_p_p.h b/src/declarative/util/qdeclarativelistmodel_p_p.h index 5ba702c..7236e8b 100644 --- a/src/declarative/util/qdeclarativelistmodel_p_p.h +++ b/src/declarative/util/qdeclarativelistmodel_p_p.h @@ -190,7 +190,7 @@ public: bool insert(int index, const QScriptValue&); QScriptValue get(int index) const; void set(int index, const QScriptValue&, QList<int> *roles); - void setProperty(int index, const QString& property, const QVariant& value, QList<int> *role); + void setProperty(int index, const QString& property, const QVariant& value, QList<int> *roles); void move(int from, int to, int count); QVariant valueForNode(ModelNode *, bool *hasNested = 0) const; @@ -255,9 +255,9 @@ struct ModelNode QDeclarativeListModel *model(const NestedListModel *model); ModelObject *object(const NestedListModel *model); - void setObjectValue(const QScriptValue& valuemap, bool writeToCache = true); + bool setObjectValue(const QScriptValue& valuemap, bool writeToCache = true); void setListValue(const QScriptValue& valuelist); - void setProperty(const QString& prop, const QVariant& val); + bool setProperty(const QString& prop, const QVariant& val); void changedProperty(const QString &name) const; void updateListIndexes(); static void dump(ModelNode *node, int ind); diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp index 69353f1..befa8eb 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp +++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp @@ -60,25 +60,25 @@ void QDeclarativeListModelWorkerAgent::Data::clearChange() void QDeclarativeListModelWorkerAgent::Data::insertChange(int index, int count) { - Change c = { Change::Inserted, index, count, 0 }; + Change c = { Change::Inserted, index, count, 0, QList<int>() }; changes << c; } void QDeclarativeListModelWorkerAgent::Data::removeChange(int index, int count) { - Change c = { Change::Removed, index, count, 0 }; + Change c = { Change::Removed, index, count, 0, QList<int>() }; changes << c; } void QDeclarativeListModelWorkerAgent::Data::moveChange(int index, int count, int to) { - Change c = { Change::Moved, index, count, to }; + Change c = { Change::Moved, index, count, to, QList<int>() }; changes << c; } -void QDeclarativeListModelWorkerAgent::Data::changedChange(int index, int count) +void QDeclarativeListModelWorkerAgent::Data::changedChange(int index, int count, const QList<int> &roles) { - Change c = { Change::Changed, index, count, 0 }; + Change c = { Change::Changed, index, count, 0, roles }; changes << c; } @@ -165,14 +165,18 @@ QScriptValue QDeclarativeListModelWorkerAgent::get(int index) const void QDeclarativeListModelWorkerAgent::set(int index, const QScriptValue &value) { - m_copy->set(index, value); - data.changedChange(index, 1); + QList<int> roles; + m_copy->set(index, value, &roles); + if (!roles.isEmpty()) + data.changedChange(index, 1, roles); } void QDeclarativeListModelWorkerAgent::setProperty(int index, const QString& property, const QVariant& value) { - m_copy->setProperty(index, property, value); - data.changedChange(index, 1); + QList<int> roles; + m_copy->setProperty(index, property, value, &roles); + if (!roles.isEmpty()) + data.changedChange(index, 1, roles); } void QDeclarativeListModelWorkerAgent::move(int from, int to, int count) @@ -194,9 +198,9 @@ void QDeclarativeListModelWorkerAgent::sync() mutex.unlock(); } -void QDeclarativeListModelWorkerAgent::changedData(int index, int count) +void QDeclarativeListModelWorkerAgent::changedData(int index, int count, const QList<int> &roles) { - data.changedChange(index, count); + data.changedChange(index, count, roles); } bool QDeclarativeListModelWorkerAgent::event(QEvent *e) @@ -255,7 +259,7 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e) emit m_orig->itemsMoved(change.index, change.to, change.count); break; case Change::Changed: - emit m_orig->itemsChanged(change.index, change.count, orig->m_roles.keys()); + emit m_orig->itemsChanged(change.index, change.count, change.roles); break; } } diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h index fbe0195..4c800e9 100644 --- a/src/declarative/util/qdeclarativelistmodelworkeragent_p.h +++ b/src/declarative/util/qdeclarativelistmodelworkeragent_p.h @@ -124,6 +124,7 @@ private: int index; // Inserted/Removed/Moved/Changed int count; // Inserted/Removed/Moved/Changed int to; // Moved + QList<int> roles; }; struct Data { @@ -133,7 +134,7 @@ private: void insertChange(int index, int count); void removeChange(int index, int count); void moveChange(int index, int count, int to); - void changedChange(int index, int count); + void changedChange(int index, int count, const QList<int> &roles); }; Data data; @@ -143,7 +144,7 @@ private: QDeclarativeListModel *list; }; - void changedData(int index, int count); + void changedData(int index, int count, const QList<int> &roles); QAtomicInt m_ref; QDeclarativeListModel *m_orig; diff --git a/src/declarative/util/qdeclarativeopenmetaobject.cpp b/src/declarative/util/qdeclarativeopenmetaobject.cpp index 510a0c1..0ceda35 100644 --- a/src/declarative/util/qdeclarativeopenmetaobject.cpp +++ b/src/declarative/util/qdeclarativeopenmetaobject.cpp @@ -97,7 +97,6 @@ int QDeclarativeOpenMetaObjectType::createProperty(const QByteArray &name) int id = d->mob.propertyCount(); d->mob.addSignal("__" + QByteArray::number(id) + "()"); QMetaPropertyBuilder build = d->mob.addProperty(name, "QVariant", id); - build.setDynamic(true); propertyCreated(id, build); qFree(d->mem); d->mem = d->mob.toMetaObject(); diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp index 1dd01f6..5190eab 100644 --- a/src/declarative/util/qdeclarativepixmapcache.cpp +++ b/src/declarative/util/qdeclarativepixmapcache.cpp @@ -959,20 +959,20 @@ QRect QDeclarativePixmap::rect() const void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url) { - load(engine, url, QSize(), false); + load(engine, url, QSize(), QDeclarativePixmap::Cache); } -void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, bool async) +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, QDeclarativePixmap::Options options) { - load(engine, url, QSize(), async); + load(engine, url, QSize(), options); } void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &size) { - load(engine, url, size, false); + load(engine, url, size, QDeclarativePixmap::Cache); } -void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, bool async) +void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QSize &requestSize, QDeclarativePixmap::Options options) { if (d) { d->release(); d = 0; } @@ -982,19 +982,20 @@ void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QHash<QDeclarativePixmapKey, QDeclarativePixmapData *>::Iterator iter = store->m_cache.find(key); if (iter == store->m_cache.end()) { - if (async) { + if (options & QDeclarativePixmap::Asynchronous) { // pixmaps can only be loaded synchronously if (url.scheme() == QLatin1String("image") && QDeclarativeEnginePrivate::get(engine)->getImageProviderType(url) == QDeclarativeImageProvider::Pixmap) { - async = false; + options &= ~QDeclarativePixmap::Asynchronous; } } - if (!async) { + if (!(options & QDeclarativePixmap::Asynchronous)) { bool ok = false; d = createPixmapDataSync(engine, url, requestSize, &ok); if (ok) { - d->addToCache(); + if (options & QDeclarativePixmap::Cache) + d->addToCache(); return; } if (d) // loadable, but encountered error while loading @@ -1007,7 +1008,8 @@ void QDeclarativePixmap::load(QDeclarativeEngine *engine, const QUrl &url, const QDeclarativePixmapReader *reader = QDeclarativePixmapReader::instance(engine); d = new QDeclarativePixmapData(url, requestSize); - d->addToCache(); + if (options & QDeclarativePixmap::Cache) + d->addToCache(); d->reply = reader->getImage(d); } else { diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h index f9ebf3b..1cf76dd 100644 --- a/src/declarative/util/qdeclarativepixmapcache_p.h +++ b/src/declarative/util/qdeclarativepixmapcache_p.h @@ -66,6 +66,12 @@ public: enum Status { Null, Ready, Error, Loading }; + enum Option { + Asynchronous = 0x00000001, + Cache = 0x00000002 + }; + Q_DECLARE_FLAGS(Options, Option) + bool isNull() const; bool isReady() const; bool isError() const; @@ -85,9 +91,9 @@ public: inline operator const QPixmap &() const; void load(QDeclarativeEngine *, const QUrl &); - void load(QDeclarativeEngine *, const QUrl &, bool); + void load(QDeclarativeEngine *, const QUrl &, QDeclarativePixmap::Options options); void load(QDeclarativeEngine *, const QUrl &, const QSize &); - void load(QDeclarativeEngine *, const QUrl &, const QSize &, bool); + void load(QDeclarativeEngine *, const QUrl &, const QSize &, QDeclarativePixmap::Options options); void clear(); void clear(QObject *); @@ -107,6 +113,8 @@ inline QDeclarativePixmap::operator const QPixmap &() const return pixmap(); } +Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePixmap::Options) + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/declarative/util/qdeclarativepropertychanges.cpp b/src/declarative/util/qdeclarativepropertychanges.cpp index 1c5d463..ccd122e 100644 --- a/src/declarative/util/qdeclarativepropertychanges.cpp +++ b/src/declarative/util/qdeclarativepropertychanges.cpp @@ -42,6 +42,9 @@ #include "private/qdeclarativepropertychanges_p.h" #include "private/qdeclarativeopenmetaobject_p.h" +#include "private/qdeclarativerewrite_p.h" +#include "private/qdeclarativeengine_p.h" +#include "private/qdeclarativecompiler_p.h" #include <qdeclarativeinfo.h> #include <qdeclarativecustomparser_p.h> @@ -217,11 +220,22 @@ public: void decode(); - QList<QPair<QByteArray, QVariant> > properties; - QList<QPair<QByteArray, QDeclarativeExpression *> > expressions; + class ExpressionChange { + public: + ExpressionChange(const QString &_name, + QDeclarativeBinding::Identifier _id, + QDeclarativeExpression *_expr) + : name(_name), id(_id), expression(_expr) {} + QString name; + QDeclarativeBinding::Identifier id; + QDeclarativeExpression *expression; + }; + + QList<QPair<QString, QVariant> > properties; + QList<ExpressionChange> expressions; QList<QDeclarativeReplaceSignalHandler*> signalReplacements; - QDeclarativeProperty property(const QByteArray &); + QDeclarativeProperty property(const QString &); }; void @@ -267,6 +281,7 @@ QDeclarativePropertyChangesParser::compile(const QList<QDeclarativeCustomParserP QDeclarativeParser::Variant v = qvariant_cast<QDeclarativeParser::Variant>(data.at(ii).second); QVariant var; bool isScript = v.isScript(); + QDeclarativeBinding::Identifier id; switch(v.type()) { case QDeclarativeParser::Variant::Boolean: var = QVariant(v.asBoolean()); @@ -280,10 +295,17 @@ QDeclarativePropertyChangesParser::compile(const QList<QDeclarativeCustomParserP case QDeclarativeParser::Variant::Invalid: case QDeclarativeParser::Variant::Script: var = QVariant(v.asScript()); + { + // Pre-rewrite the expression + QString expression = v.asScript(); + id = rewriteBinding(expression, data.at(ii).first); //### recreates the AST, which is slow + } break; } - ds << data.at(ii).first << isScript << var; + ds << QString::fromUtf8(data.at(ii).first) << isScript << var; + if (isScript) + ds << id; } return rv; @@ -300,12 +322,15 @@ void QDeclarativePropertyChangesPrivate::decode() int count; ds >> count; for (int ii = 0; ii < count; ++ii) { - QByteArray name; + QString name; bool isScript; QVariant data; + QDeclarativeBinding::Identifier id = QDeclarativeBinding::Invalid; ds >> name; ds >> isScript; ds >> data; + if (isScript) + ds >> id; QDeclarativeProperty prop = property(name); //### better way to check for signal property? if (prop.type() & QDeclarativeProperty::SignalProperty) { @@ -322,7 +347,7 @@ void QDeclarativePropertyChangesPrivate::decode() QDeclarativeData *ddata = QDeclarativeData::get(q); if (ddata && ddata->outerContext && !ddata->outerContext->url.isEmpty()) expression->setSourceLocation(ddata->outerContext->url.toString(), ddata->lineNumber); - expressions << qMakePair(name, expression); + expressions << ExpressionChange(name, id, expression); } else { properties << qMakePair(name, data); } @@ -350,7 +375,7 @@ QDeclarativePropertyChanges::~QDeclarativePropertyChanges() { Q_D(QDeclarativePropertyChanges); for(int ii = 0; ii < d->expressions.count(); ++ii) - delete d->expressions.at(ii).second; + delete d->expressions.at(ii).expression; for(int ii = 0; ii < d->signalReplacements.count(); ++ii) delete d->signalReplacements.at(ii); } @@ -389,15 +414,15 @@ void QDeclarativePropertyChanges::setRestoreEntryValues(bool v) } QDeclarativeProperty -QDeclarativePropertyChangesPrivate::property(const QByteArray &property) +QDeclarativePropertyChangesPrivate::property(const QString &property) { Q_Q(QDeclarativePropertyChanges); - QDeclarativeProperty prop(object, QString::fromUtf8(property), qmlContext(q)); + QDeclarativeProperty prop(object, property, qmlContext(q)); if (!prop.isValid()) { - qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(QString::fromUtf8(property)); + qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property); return QDeclarativeProperty(); } else if (!(prop.type() & QDeclarativeProperty::SignalProperty) && !prop.isWritable()) { - qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(QString::fromUtf8(property)); + qmlInfo(q) << QDeclarativePropertyChanges::tr("Cannot assign to read-only property \"%1\"").arg(property); return QDeclarativeProperty(); } return prop; @@ -413,9 +438,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() for (int ii = 0; ii < d->properties.count(); ++ii) { - QByteArray property = d->properties.at(ii).first; - - QDeclarativeAction a(d->object, QString::fromUtf8(property), + QDeclarativeAction a(d->object, d->properties.at(ii).first, qmlContext(this), d->properties.at(ii).second); if (a.property.isValid()) { @@ -437,7 +460,7 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() for (int ii = 0; ii < d->expressions.count(); ++ii) { - QByteArray property = d->expressions.at(ii).first; + const QString &property = d->expressions.at(ii).name; QDeclarativeProperty prop = d->property(property); if (prop.isValid()) { @@ -446,16 +469,20 @@ QDeclarativePropertyChanges::ActionList QDeclarativePropertyChanges::actions() a.property = prop; a.fromValue = a.property.read(); a.specifiedObject = d->object; - a.specifiedProperty = QString::fromUtf8(property); + a.specifiedProperty = property; if (d->isExplicit) { - a.toValue = d->expressions.at(ii).second->evaluate(); + a.toValue = d->expressions.at(ii).expression->evaluate(); } else { - QDeclarativeExpression *e = d->expressions.at(ii).second; - QDeclarativeBinding *newBinding = - new QDeclarativeBinding(e->expression(), object(), qmlContext(this)); + QDeclarativeExpression *e = d->expressions.at(ii).expression; + + QDeclarativeBinding::Identifier id = d->expressions.at(ii).id; + QDeclarativeBinding *newBinding = id != QDeclarativeBinding::Invalid ? QDeclarativeBinding::createBinding(id, object(), qmlContext(this), e->sourceFile(), e->lineNumber()) : 0; + if (!newBinding) { + newBinding = new QDeclarativeBinding(e->expression(), object(), qmlContext(this)); + newBinding->setSourceLocation(e->sourceFile(), e->lineNumber()); + } newBinding->setTarget(prop); - newBinding->setSourceLocation(e->sourceFile(), e->lineNumber()); a.toBinding = newBinding; a.deletableToBinding = true; } @@ -498,10 +525,10 @@ void QDeclarativePropertyChanges::setIsExplicit(bool e) d->isExplicit = e; } -bool QDeclarativePropertyChanges::containsValue(const QByteArray &name) const +bool QDeclarativePropertyChanges::containsValue(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair<QByteArray, QVariant> PropertyEntry; + typedef QPair<QString, QVariant> PropertyEntry; QListIterator<PropertyEntry> propertyIterator(d->properties); while (propertyIterator.hasNext()) { @@ -514,15 +541,15 @@ bool QDeclarativePropertyChanges::containsValue(const QByteArray &name) const return false; } -bool QDeclarativePropertyChanges::containsExpression(const QByteArray &name) const +bool QDeclarativePropertyChanges::containsExpression(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QListIterator<ExpressionEntry> expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { + if (entry.name == name) { return true; } } @@ -530,21 +557,21 @@ bool QDeclarativePropertyChanges::containsExpression(const QByteArray &name) con return false; } -bool QDeclarativePropertyChanges::containsProperty(const QByteArray &name) const +bool QDeclarativePropertyChanges::containsProperty(const QString &name) const { return containsValue(name) || containsExpression(name); } -void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVariant &value) +void QDeclarativePropertyChanges::changeValue(const QString &name, const QVariant &value) { Q_D(QDeclarativePropertyChanges); - typedef QPair<QByteArray, QVariant> PropertyEntry; - typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + typedef QPair<QString, QVariant> PropertyEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { + if (entry.name == name) { expressionIterator.remove(); if (state() && state()->isStateActive()) { QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name)); @@ -576,7 +603,7 @@ void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVar action.property = d->property(name); action.fromValue = action.property.read(); action.specifiedObject = object(); - action.specifiedProperty = QString::fromUtf8(name); + action.specifiedProperty = name; action.toValue = value; propertyIterator.insert(PropertyEntry(name, value)); @@ -589,11 +616,11 @@ void QDeclarativePropertyChanges::changeValue(const QByteArray &name, const QVar } } -void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const QString &expression) +void QDeclarativePropertyChanges::changeExpression(const QString &name, const QString &expression) { Q_D(QDeclarativePropertyChanges); - typedef QPair<QByteArray, QVariant> PropertyEntry; - typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + typedef QPair<QString, QVariant> PropertyEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; bool hadValue = false; @@ -610,8 +637,8 @@ void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { - entry.second->setExpression(expression); + if (entry.name == name) { + entry.expression->setExpression(expression); if (state() && state()->isStateActive()) { QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(d->property(name)); if (oldBinding) { @@ -628,7 +655,7 @@ void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const } QDeclarativeExpression *newExpression = new QDeclarativeExpression(qmlContext(this), d->object, expression); - expressionIterator.insert(ExpressionEntry(name, newExpression)); + expressionIterator.insert(ExpressionEntry(name, QDeclarativeBinding::Invalid, newExpression)); if (state() && state()->isStateActive()) { if (hadValue) { @@ -647,7 +674,7 @@ void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const action.property = d->property(name); action.fromValue = action.property.read(); action.specifiedObject = object(); - action.specifiedProperty = QString::fromUtf8(name); + action.specifiedProperty = name; if (d->isExplicit) { @@ -670,11 +697,11 @@ void QDeclarativePropertyChanges::changeExpression(const QByteArray &name, const // what about the signal handler? } -QVariant QDeclarativePropertyChanges::property(const QByteArray &name) const +QVariant QDeclarativePropertyChanges::property(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair<QByteArray, QVariant> PropertyEntry; - typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + typedef QPair<QString, QVariant> PropertyEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QListIterator<PropertyEntry> propertyIterator(d->properties); while (propertyIterator.hasNext()) { @@ -687,24 +714,24 @@ QVariant QDeclarativePropertyChanges::property(const QByteArray &name) const QListIterator<ExpressionEntry> expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { - return QVariant(entry.second->expression()); + if (entry.name == name) { + return QVariant(entry.expression->expression()); } } return QVariant(); } -void QDeclarativePropertyChanges::removeProperty(const QByteArray &name) +void QDeclarativePropertyChanges::removeProperty(const QString &name) { Q_D(QDeclarativePropertyChanges); - typedef QPair<QByteArray, QVariant> PropertyEntry; - typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + typedef QPair<QString, QVariant> PropertyEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QMutableListIterator<ExpressionEntry> expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { + if (entry.name == name) { expressionIterator.remove(); state()->removeEntryFromRevertList(object(), name); return; @@ -722,10 +749,10 @@ void QDeclarativePropertyChanges::removeProperty(const QByteArray &name) } } -QVariant QDeclarativePropertyChanges::value(const QByteArray &name) const +QVariant QDeclarativePropertyChanges::value(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair<QByteArray, QVariant> PropertyEntry; + typedef QPair<QString, QVariant> PropertyEntry; QListIterator<PropertyEntry> propertyIterator(d->properties); while (propertyIterator.hasNext()) { @@ -738,16 +765,16 @@ QVariant QDeclarativePropertyChanges::value(const QByteArray &name) const return QVariant(); } -QString QDeclarativePropertyChanges::expression(const QByteArray &name) const +QString QDeclarativePropertyChanges::expression(const QString &name) const { Q_D(const QDeclarativePropertyChanges); - typedef QPair<QByteArray, QDeclarativeExpression *> ExpressionEntry; + typedef QDeclarativePropertyChangesPrivate::ExpressionChange ExpressionEntry; QListIterator<ExpressionEntry> expressionIterator(d->expressions); while (expressionIterator.hasNext()) { const ExpressionEntry &entry = expressionIterator.next(); - if (entry.first == name) { - return entry.second->expression(); + if (entry.name == name) { + return entry.expression->expression(); } } diff --git a/src/declarative/util/qdeclarativepropertychanges_p.h b/src/declarative/util/qdeclarativepropertychanges_p.h index aa57657..09e3a16 100644 --- a/src/declarative/util/qdeclarativepropertychanges_p.h +++ b/src/declarative/util/qdeclarativepropertychanges_p.h @@ -75,19 +75,19 @@ public: virtual ActionList actions(); - bool containsProperty(const QByteArray &name) const; - bool containsValue(const QByteArray &name) const; - bool containsExpression(const QByteArray &name) const; - void changeValue(const QByteArray &name, const QVariant &value); - void changeExpression(const QByteArray &name, const QString &expression); - void removeProperty(const QByteArray &name); - QVariant value(const QByteArray &name) const; - QString expression(const QByteArray &name) const; + bool containsProperty(const QString &name) const; + bool containsValue(const QString &name) const; + bool containsExpression(const QString &name) const; + void changeValue(const QString &name, const QVariant &value); + void changeExpression(const QString &name, const QString &expression); + void removeProperty(const QString &name); + QVariant value(const QString &name) const; + QString expression(const QString &name) const; void detachFromState(); void attachToState(); - QVariant property(const QByteArray &name) const; + QVariant property(const QString &name) const; }; class QDeclarativePropertyChangesParser : public QDeclarativeCustomParser diff --git a/src/declarative/util/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index bb1a0b8..5a4e2b1 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -66,7 +66,7 @@ QDeclarativeAction::QDeclarativeAction() QDeclarativeAction::QDeclarativeAction(QObject *target, const QString &propertyName, const QVariant &value) : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), - property(target, propertyName), toValue(value), + property(target, propertyName, qmlEngine(target)), toValue(value), fromBinding(0), event(0), specifiedObject(target), specifiedProperty(propertyName) { @@ -216,15 +216,18 @@ bool QDeclarativeState::isWhenKnown() const \snippet doc/src/snippets/declarative/state-when.qml 0 - If multiple states in a group have \c when clauses that evaluate to \c true at the same time, - the first matching state will be applied. For example, in the following snippet - \c state1 will always be selected rather than \c state2 when sharedCondition becomes - \c true. + If multiple states in a group have \c when clauses that evaluate to \c true + at the same time, the first matching state will be applied. For example, in + the following snippet \c state1 will always be selected rather than + \c state2 when sharedCondition becomes \c true. \qml - states: [ - State { name: "state1"; when: sharedCondition }, - State { name: "state2"; when: sharedCondition } - ] + Item { + states: [ + State { name: "state1"; when: sharedCondition }, + State { name: "state2"; when: sharedCondition } + ] + // ... + } \endqml */ QDeclarativeBinding *QDeclarativeState::when() const @@ -370,7 +373,7 @@ void QDeclarativeAction::deleteFromBinding() } } -bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QByteArray &name) const +bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QString &name) const { Q_D(const QDeclarativeState); @@ -379,7 +382,7 @@ bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QByt while (revertListIterator.hasNext()) { const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) return true; } } @@ -387,7 +390,7 @@ bool QDeclarativeState::containsPropertyInRevertList(QObject *target, const QByt return false; } -bool QDeclarativeState::changeValueInRevertList(QObject *target, const QByteArray &name, const QVariant &revertValue) +bool QDeclarativeState::changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue) { Q_D(QDeclarativeState); @@ -396,7 +399,7 @@ bool QDeclarativeState::changeValueInRevertList(QObject *target, const QByteArra while (revertListIterator.hasNext()) { QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) { + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) { simpleAction.setValue(revertValue); return true; } @@ -406,7 +409,7 @@ bool QDeclarativeState::changeValueInRevertList(QObject *target, const QByteArra return false; } -bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QByteArray &name, QDeclarativeAbstractBinding *binding) +bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding) { Q_D(QDeclarativeState); @@ -415,7 +418,7 @@ bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QByteAr while (revertListIterator.hasNext()) { QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) { + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) { if (simpleAction.binding()) simpleAction.binding()->destroy(); @@ -428,7 +431,7 @@ bool QDeclarativeState::changeBindingInRevertList(QObject *target, const QByteAr return false; } -bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QByteArray &name) +bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QString &name) { Q_D(QDeclarativeState); @@ -437,7 +440,7 @@ bool QDeclarativeState::removeEntryFromRevertList(QObject *target, const QByteAr while (revertListIterator.hasNext()) { QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.property().object() == target && simpleAction.property().name().toUtf8() == name) { + if (simpleAction.property().object() == target && simpleAction.property().name() == name) { QDeclarativeAbstractBinding *oldBinding = QDeclarativePropertyPrivate::binding(simpleAction.property()); if (oldBinding) { QDeclarativePropertyPrivate::setBinding(simpleAction.property(), 0); @@ -517,7 +520,7 @@ void QDeclarativeState::addEntriesToRevertList(const QList<QDeclarativeAction> & } } -QVariant QDeclarativeState::valueInRevertList(QObject *target, const QByteArray &name) const +QVariant QDeclarativeState::valueInRevertList(QObject *target, const QString &name) const { Q_D(const QDeclarativeState); @@ -526,7 +529,7 @@ QVariant QDeclarativeState::valueInRevertList(QObject *target, const QByteArray while (revertListIterator.hasNext()) { const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) return simpleAction.value(); } } @@ -534,7 +537,7 @@ QVariant QDeclarativeState::valueInRevertList(QObject *target, const QByteArray return QVariant(); } -QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *target, const QByteArray &name) const +QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *target, const QString &name) const { Q_D(const QDeclarativeState); @@ -543,7 +546,7 @@ QDeclarativeAbstractBinding *QDeclarativeState::bindingInRevertList(QObject *tar while (revertListIterator.hasNext()) { const QDeclarativeSimpleAction &simpleAction = revertListIterator.next(); - if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty().toUtf8() == name) + if (simpleAction.specifiedObject() == target && simpleAction.specifiedProperty() == name) return simpleAction.binding(); } } diff --git a/src/declarative/util/qdeclarativestate_p.h b/src/declarative/util/qdeclarativestate_p.h index 4a0b4ff..60d0e0b 100644 --- a/src/declarative/util/qdeclarativestate_p.h +++ b/src/declarative/util/qdeclarativestate_p.h @@ -45,7 +45,7 @@ #include <qdeclarative.h> #include <qdeclarativeproperty.h> #include <QtCore/qobject.h> -#include <private/qdeclarativebinding_p.h> +#include <QtCore/qsharedpointer.h> #include <private/qdeclarativeglobal_p.h> QT_BEGIN_HEADER @@ -76,7 +76,7 @@ public: QVariant toValue; QDeclarativeAbstractBinding *fromBinding; - QDeclarativeAbstractBinding::Pointer toBinding; + QWeakPointer<QDeclarativeAbstractBinding> toBinding; QDeclarativeActionEvent *event; //strictly for matching @@ -180,15 +180,15 @@ public: QDeclarativeStateGroup *stateGroup() const; void setStateGroup(QDeclarativeStateGroup *); - bool containsPropertyInRevertList(QObject *target, const QByteArray &name) const; - bool changeValueInRevertList(QObject *target, const QByteArray &name, const QVariant &revertValue); - bool changeBindingInRevertList(QObject *target, const QByteArray &name, QDeclarativeAbstractBinding *binding); - bool removeEntryFromRevertList(QObject *target, const QByteArray &name); + bool containsPropertyInRevertList(QObject *target, const QString &name) const; + bool changeValueInRevertList(QObject *target, const QString &name, const QVariant &revertValue); + bool changeBindingInRevertList(QObject *target, const QString &name, QDeclarativeAbstractBinding *binding); + bool removeEntryFromRevertList(QObject *target, const QString &name); void addEntryToRevertList(const QDeclarativeAction &action); void removeAllEntriesFromRevertList(QObject *target); void addEntriesToRevertList(const QList<QDeclarativeAction> &actions); - QVariant valueInRevertList(QObject *target, const QByteArray &name) const; - QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QByteArray &name) const; + QVariant valueInRevertList(QObject *target, const QString &name) const; + QDeclarativeAbstractBinding *bindingInRevertList(QObject *target, const QString &name) const; bool isStateActive() const; diff --git a/src/declarative/util/qdeclarativestategroup.cpp b/src/declarative/util/qdeclarativestategroup.cpp index 7aeea12..f1d0997 100644 --- a/src/declarative/util/qdeclarativestategroup.cpp +++ b/src/declarative/util/qdeclarativestategroup.cpp @@ -102,10 +102,10 @@ public: id: myStateGroup states: State { name: "state1" - ... + // ... } transitions: Transition { - ... + // ... } } @@ -140,11 +140,15 @@ QList<QDeclarativeState *> QDeclarativeStateGroup::states() const \qml StateGroup { - states: [ - State { ... }, - State { ... } - ... - ] + states: [ + State { + // State definition... + }, + State { + // ... + } + // Other states... + ] } \endqml @@ -197,11 +201,15 @@ void QDeclarativeStateGroupPrivate::clear_states(QDeclarativeListProperty<QDecla \qml StateGroup { - transitions: [ - Transition { ... }, - Transition { ... } - ... - ] + transitions: [ + Transition { + // ... + }, + Transition { + // ... + } + // ... + ] } \endqml @@ -221,14 +229,14 @@ QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeStateGroup::transit This property is often used in scripts to change between states. For example: - \qml - function toggle() { - if (button.state == 'On') - button.state = 'Off'; - else - button.state = 'On'; - } - \endqml + \js + function toggle() { + if (button.state == 'On') + button.state = 'Off'; + else + button.state = 'On'; + } + \endjs If the state group is in its base state (i.e. no explicit state has been set), \c state will be a blank string. Likewise, you can return a diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp index 346a374..9aca71f 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -83,6 +83,13 @@ public: QDeclarativeNullableValue<QDeclarativeScriptString> scaleString; QDeclarativeNullableValue<QDeclarativeScriptString> rotationString; + QDeclarativeNullableValue<qreal> x; + QDeclarativeNullableValue<qreal> y; + QDeclarativeNullableValue<qreal> width; + QDeclarativeNullableValue<qreal> height; + QDeclarativeNullableValue<qreal> scale; + QDeclarativeNullableValue<qreal> rotation; + void doChange(QDeclarativeItem *targetParent, QDeclarativeItem *stackBefore = 0); }; @@ -213,10 +220,21 @@ QDeclarativeScriptString QDeclarativeParentChange::x() const return d->xString.value; } +void tryReal(QDeclarativeNullableValue<qreal> &value, const QString &string) +{ + bool ok = false; + qreal realValue = string.toFloat(&ok); + if (ok) + value = realValue; + else + value.invalidate(); +} + void QDeclarativeParentChange::setX(QDeclarativeScriptString x) { Q_D(QDeclarativeParentChange); d->xString = x; + tryReal(d->x, x.script()); } bool QDeclarativeParentChange::xIsSet() const @@ -235,6 +253,7 @@ void QDeclarativeParentChange::setY(QDeclarativeScriptString y) { Q_D(QDeclarativeParentChange); d->yString = y; + tryReal(d->y, y.script()); } bool QDeclarativeParentChange::yIsSet() const @@ -253,6 +272,7 @@ void QDeclarativeParentChange::setWidth(QDeclarativeScriptString width) { Q_D(QDeclarativeParentChange); d->widthString = width; + tryReal(d->width, width.script()); } bool QDeclarativeParentChange::widthIsSet() const @@ -271,6 +291,7 @@ void QDeclarativeParentChange::setHeight(QDeclarativeScriptString height) { Q_D(QDeclarativeParentChange); d->heightString = height; + tryReal(d->height, height.script()); } bool QDeclarativeParentChange::heightIsSet() const @@ -289,6 +310,7 @@ void QDeclarativeParentChange::setScale(QDeclarativeScriptString scale) { Q_D(QDeclarativeParentChange); d->scaleString = scale; + tryReal(d->scale, scale.script()); } bool QDeclarativeParentChange::scaleIsSet() const @@ -307,6 +329,7 @@ void QDeclarativeParentChange::setRotation(QDeclarativeScriptString rotation) { Q_D(QDeclarativeParentChange); d->rotationString = rotation; + tryReal(d->rotation, rotation.script()); } bool QDeclarativeParentChange::rotationIsSet() const @@ -367,16 +390,15 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() a.event = this; actions << a; + QDeclarativeContext *ctxt = qmlContext(this); + if (d->xString.isValid()) { - bool ok = false; - QString script = d->xString.value.script(); - qreal x = script.toFloat(&ok); - if (ok) { - QDeclarativeAction xa(d->target, QLatin1String("x"), x); + if (d->x.isValid()) { + QDeclarativeAction xa(d->target, QLatin1String("x"), ctxt, d->x.value); actions << xa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->xString.value.script(), d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("x"), ctxt)); QDeclarativeAction xa; xa.property = newBinding->property(); xa.toBinding = newBinding; @@ -387,15 +409,12 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->yString.isValid()) { - bool ok = false; - QString script = d->yString.value.script(); - qreal y = script.toFloat(&ok); - if (ok) { - QDeclarativeAction ya(d->target, QLatin1String("y"), y); + if (d->y.isValid()) { + QDeclarativeAction ya(d->target, QLatin1String("y"), ctxt, d->y.value); actions << ya; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->yString.value.script(), d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("y"), ctxt)); QDeclarativeAction ya; ya.property = newBinding->property(); ya.toBinding = newBinding; @@ -406,15 +425,12 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->scaleString.isValid()) { - bool ok = false; - QString script = d->scaleString.value.script(); - qreal scale = script.toFloat(&ok); - if (ok) { - QDeclarativeAction sa(d->target, QLatin1String("scale"), scale); + if (d->scale.isValid()) { + QDeclarativeAction sa(d->target, QLatin1String("scale"), ctxt, d->scale.value); actions << sa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->scaleString.value.script(), d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("scale"), ctxt)); QDeclarativeAction sa; sa.property = newBinding->property(); sa.toBinding = newBinding; @@ -425,15 +441,12 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->rotationString.isValid()) { - bool ok = false; - QString script = d->rotationString.value.script(); - qreal rotation = script.toFloat(&ok); - if (ok) { - QDeclarativeAction ra(d->target, QLatin1String("rotation"), rotation); + if (d->rotation.isValid()) { + QDeclarativeAction ra(d->target, QLatin1String("rotation"), ctxt, d->rotation.value); actions << ra; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->rotationString.value.script(), d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("rotation"), ctxt)); QDeclarativeAction ra; ra.property = newBinding->property(); ra.toBinding = newBinding; @@ -444,15 +457,12 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->widthString.isValid()) { - bool ok = false; - QString script = d->widthString.value.script(); - qreal width = script.toFloat(&ok); - if (ok) { - QDeclarativeAction wa(d->target, QLatin1String("width"), width); + if (d->width.isValid()) { + QDeclarativeAction wa(d->target, QLatin1String("width"), ctxt, d->width.value); actions << wa; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->widthString.value.script(), d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("width"), ctxt)); QDeclarativeAction wa; wa.property = newBinding->property(); wa.toBinding = newBinding; @@ -463,15 +473,12 @@ QDeclarativeStateOperation::ActionList QDeclarativeParentChange::actions() } if (d->heightString.isValid()) { - bool ok = false; - QString script = d->heightString.value.script(); - qreal height = script.toFloat(&ok); - if (ok) { - QDeclarativeAction ha(d->target, QLatin1String("height"), height); + if (d->height.isValid()) { + QDeclarativeAction ha(d->target, QLatin1String("height"), ctxt, d->height.value); actions << ha; } else { - QDeclarativeBinding *newBinding = new QDeclarativeBinding(script, d->target, qmlContext(this)); - newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height"))); + QDeclarativeBinding *newBinding = new QDeclarativeBinding(d->heightString.value.script(), d->target, ctxt); + newBinding->setTarget(QDeclarativeProperty(d->target, QLatin1String("height"), ctxt)); QDeclarativeAction ha; ha.property = newBinding->property(); ha.toBinding = newBinding; @@ -599,25 +606,7 @@ public: ScriptAction to specify the point in the transition at which the StateChangeScript should to be run. - \qml - State { - name "state1" - StateChangeScript { - name: "myScript" - script: doStateStuff(); - } - ... - } - ... - Transition { - to: "state1" - SequentialAnimation { - NumberAnimation { ... } - ScriptAction { scriptName: "myScript" } - NumberAnimation { ... } - } - } - \endqml + \snippet snippets/declarative/states/statechangescript.qml state and transition \sa ScriptAction */ @@ -652,7 +641,7 @@ void QDeclarativeStateChangeScript::setScript(const QDeclarativeScriptString &s) This property holds the name of the script. This name can be used by a ScriptAction to target a specific script. - \sa ScriptAction::stateChangeScriptName + \sa ScriptAction::scriptName */ QString QDeclarativeStateChangeScript::name() const { @@ -1075,32 +1064,34 @@ QDeclarativeAnchorChanges::ActionList QDeclarativeAnchorChanges::actions() d->vCenterProp = QDeclarativeProperty(d->target, QLatin1String("anchors.verticalCenter")); d->baselineProp = QDeclarativeProperty(d->target, QLatin1String("anchors.baseline")); + QDeclarativeContext *ctxt = qmlContext(this); + if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::LeftAnchor) { - d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, qmlContext(this)); + d->leftBinding = new QDeclarativeBinding(d->anchorSet->d_func()->leftScript.script(), d->target, ctxt); d->leftBinding->setTarget(d->leftProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::RightAnchor) { - d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, qmlContext(this)); + d->rightBinding = new QDeclarativeBinding(d->anchorSet->d_func()->rightScript.script(), d->target, ctxt); d->rightBinding->setTarget(d->rightProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::HCenterAnchor) { - d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, qmlContext(this)); + d->hCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->hCenterScript.script(), d->target, ctxt); d->hCenterBinding->setTarget(d->hCenterProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::TopAnchor) { - d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, qmlContext(this)); + d->topBinding = new QDeclarativeBinding(d->anchorSet->d_func()->topScript.script(), d->target, ctxt); d->topBinding->setTarget(d->topProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::BottomAnchor) { - d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, qmlContext(this)); + d->bottomBinding = new QDeclarativeBinding(d->anchorSet->d_func()->bottomScript.script(), d->target, ctxt); d->bottomBinding->setTarget(d->bottomProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::VCenterAnchor) { - d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, qmlContext(this)); + d->vCenterBinding = new QDeclarativeBinding(d->anchorSet->d_func()->vCenterScript.script(), d->target, ctxt); d->vCenterBinding->setTarget(d->vCenterProp); } if (d->anchorSet->d_func()->usedAnchors & QDeclarativeAnchors::BaselineAnchor) { - d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, qmlContext(this)); + d->baselineBinding = new QDeclarativeBinding(d->anchorSet->d_func()->baselineScript.script(), d->target, ctxt); d->baselineBinding->setTarget(d->baselineProp); } @@ -1380,24 +1371,25 @@ QList<QDeclarativeAction> QDeclarativeAnchorChanges::additionalActions() bool vChange = combined & QDeclarativeAnchors::Vertical_Mask; if (d->target) { + QDeclarativeContext *ctxt = qmlContext(this); QDeclarativeAction a; if (hChange && d->fromX != d->toX) { - a.property = QDeclarativeProperty(d->target, QLatin1String("x")); + a.property = QDeclarativeProperty(d->target, QLatin1String("x"), ctxt); a.toValue = d->toX; extra << a; } if (vChange && d->fromY != d->toY) { - a.property = QDeclarativeProperty(d->target, QLatin1String("y")); + a.property = QDeclarativeProperty(d->target, QLatin1String("y"), ctxt); a.toValue = d->toY; extra << a; } if (hChange && d->fromWidth != d->toWidth) { - a.property = QDeclarativeProperty(d->target, QLatin1String("width")); + a.property = QDeclarativeProperty(d->target, QLatin1String("width"), ctxt); a.toValue = d->toWidth; extra << a; } if (vChange && d->fromHeight != d->toHeight) { - a.property = QDeclarativeProperty(d->target, QLatin1String("height")); + a.property = QDeclarativeProperty(d->target, QLatin1String("height"), ctxt); a.toValue = d->toHeight; extra << a; } diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/declarative/util/qdeclarativetransition.cpp index e533a07..063ec3e 100644 --- a/src/declarative/util/qdeclarativetransition.cpp +++ b/src/declarative/util/qdeclarativetransition.cpp @@ -82,15 +82,7 @@ QT_BEGIN_NAMESPACE To define multiple transitions, specify \l Item::transitions as a list: - \qml - Item { - ... - transitions: [ - Transition { to: "state1" ... }, - Transition { ... } - ] - } - \endqml + \snippet doc/src/snippets/declarative/transitions-list.qml list of transitions If multiple Transitions are specified, only a single (best-matching) Transition will be applied for any particular state change. In the example above, when changing to \c state1, the first transition will be used, rather @@ -222,13 +214,7 @@ void QDeclarativeTransition::prepare(QDeclarativeStateOperation::ActionList &act If the transition was changed to this: - \qml - transitions: Transition { - to: "brighter" - ColorAnimation { duration: 1000 } - } - } - \endqml + \snippet doc/src/snippets/declarative/transition-from-to-modified.qml modified transition The animation would only be applied when changing from the default state to the "brighter" state (i.e. when the mouse is pressed, but not on release). @@ -313,24 +299,12 @@ void QDeclarativeTransition::setToState(const QString &t) This property holds a list of the animations to be run for this transition. - \qml - Transition { - PropertyAnimation { ... } - NumberAnimation { ... } - } - \endqml + \snippet examples/declarative/toys/dynamicscene/dynamicscene.qml top-level transitions The top-level animations are run in parallel. To run them sequentially, define them within a SequentialAnimation: - \qml - Transition { - SequentialAnimation { - PropertyAnimation { ... } - NumberAnimation { ... } - } - } - \endqml + \snippet doc/src/snippets/declarative/transition-reversible.qml sequential animations */ QDeclarativeListProperty<QDeclarativeAbstractAnimation> QDeclarativeTransition::animations() { diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp index 0544f22..f32f390 100644 --- a/src/declarative/util/qdeclarativeutilmodule.cpp +++ b/src/declarative/util/qdeclarativeutilmodule.cpp @@ -66,6 +66,7 @@ #include "private/qdeclarativetimer_p.h" #include "private/qdeclarativetransitionmanager_p_p.h" #include "private/qdeclarativetransition_p.h" +#include "private/qdeclarativeapplication_p.h" #include "qdeclarativeview.h" #include "qdeclarativeinfo.h" #include "private/qdeclarativetypenotavailable_p.h" @@ -75,6 +76,8 @@ void QDeclarativeUtilModule::defineModule() { + qmlRegisterUncreatableType<QDeclarativeApplication>("QtQuick",1,1,"Application", QDeclarativeApplication::tr("Application is an abstract class")); + qmlRegisterType<QDeclarativeAnchorAnimation>("QtQuick",1,0,"AnchorAnimation"); qmlRegisterType<QDeclarativeAnchorChanges>("QtQuick",1,0,"AnchorChanges"); qmlRegisterType<QDeclarativeBehavior>("QtQuick",1,0,"Behavior"); diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp index 20028eb..99c29d5 100644 --- a/src/declarative/util/qdeclarativeview.cpp +++ b/src/declarative/util/qdeclarativeview.cpp @@ -77,7 +77,7 @@ extern Q_GUI_EXPORT bool qt_applefontsmoothing_enabled; class QDeclarativeScene : public QGraphicsScene { public: - QDeclarativeScene(); + QDeclarativeScene(QObject *parent = 0); protected: virtual void keyPressEvent(QKeyEvent *); @@ -88,7 +88,7 @@ protected: virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *); }; -QDeclarativeScene::QDeclarativeScene() +QDeclarativeScene::QDeclarativeScene(QObject *parent) : QGraphicsScene(parent) { } @@ -132,7 +132,8 @@ class QDeclarativeViewPrivate : public QGraphicsViewPrivate, public QDeclarative Q_DECLARE_PUBLIC(QDeclarativeView) public: QDeclarativeViewPrivate() - : root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0), resizeMode(QDeclarativeView::SizeViewToRootObject), initialSize(0,0) {} + : root(0), declarativeItemRoot(0), graphicsWidgetRoot(0), component(0), + resizeMode(QDeclarativeView::SizeViewToRootObject), initialSize(0,0) {} ~QDeclarativeViewPrivate() { delete root; delete engine; } void execute(); void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry); @@ -155,8 +156,6 @@ public: QElapsedTimer frameTimer; void init(); - - QDeclarativeScene scene; }; void QDeclarativeViewPrivate::execute() @@ -234,6 +233,9 @@ void QDeclarativeViewPrivate::itemGeometryChanged(QDeclarativeItem *resizeItem, you can connect to the statusChanged() signal and monitor for QDeclarativeView::Error. The errors are available via QDeclarativeView::errors(). + If you're using your own QGraphicsScene-based scene with QDeclarativeView, remember to + enable scene's sticky focus mode and to set itemIndexMethod to QGraphicsScene::NoIndex. + \sa {Integrating QML with existing Qt UI code}, {Using QML in C++ Applications} */ @@ -277,7 +279,7 @@ void QDeclarativeViewPrivate::init() { Q_Q(QDeclarativeView); engine = new QDeclarativeEngine(); - q->setScene(&scene); + q->setScene(new QDeclarativeScene(q)); q->setOptimizationFlags(QGraphicsView::DontSavePainterState); q->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -286,11 +288,11 @@ void QDeclarativeViewPrivate::init() // These seem to give the best performance q->setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); - scene.setItemIndexMethod(QGraphicsScene::NoIndex); + q->scene()->setItemIndexMethod(QGraphicsScene::NoIndex); q->viewport()->setFocusPolicy(Qt::NoFocus); q->setFocusPolicy(Qt::StrongFocus); - scene.setStickyFocus(true); //### needed for correct focus handling + q->scene()->setStickyFocus(true); //### needed for correct focus handling } /*! @@ -557,14 +559,14 @@ void QDeclarativeView::continueExecute() void QDeclarativeView::setRootObject(QObject *obj) { Q_D(QDeclarativeView); - if (d->root == obj) + if (d->root == obj || !scene()) return; if (QDeclarativeItem *declarativeItem = qobject_cast<QDeclarativeItem *>(obj)) { - d->scene.addItem(declarativeItem); + scene()->addItem(declarativeItem); d->root = declarativeItem; d->declarativeItemRoot = declarativeItem; } else if (QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(obj)) { - d->scene.addItem(graphicsObject); + scene()->addItem(graphicsObject); d->root = graphicsObject; if (graphicsObject->isWidget()) { d->graphicsWidgetRoot = static_cast<QGraphicsWidget*>(graphicsObject); diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 8053a5e..d691f94 100644 --- a/src/declarative/util/qdeclarativexmllistmodel.cpp +++ b/src/declarative/util/qdeclarativexmllistmodel.cpp @@ -90,10 +90,15 @@ typedef QPair<int, int> QDeclarativeXmlListRange; \qml XmlListModel { id: xmlModel - ... - XmlRole { name: "title"; query: "title/string()" } + // ... + XmlRole { + name: "title" + query: "title/string()" + } } + \endqml + \qml ListView { model: xmlModel delegate: Text { text: title } @@ -382,7 +387,7 @@ void QDeclarativeXmlQuery::doSubQueryJob() for (int i = 0; i < queries.size(); ++i) { QList<QVariant> resultList; if (!queries[i].isEmpty()) { - subquery.setQuery(m_prefix + QLatin1String("(let $v := ") + queries[i] + QLatin1String(" return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); + subquery.setQuery(m_prefix + QLatin1String("(let $v := string(") + queries[i] + QLatin1String(") return if ($v) then ") + queries[i] + QLatin1String(" else \"\")")); if (subquery.isValid()) { QXmlResultItems resultItems; subquery.evaluateTo(&resultItems); @@ -792,9 +797,9 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati This will access the \c title value for the first item in the model: - \qml - var title = model.get(0).title; - \endqml + \js + var title = model.get(0).title; + \endjs */ QScriptValue QDeclarativeXmlListModel::get(int index) const { diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index fd57144..62fa8f1 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -1,6 +1,7 @@ INCLUDEPATH += $$PWD SOURCES += \ + $$PWD/qdeclarativeapplication.cpp \ $$PWD/qdeclarativeutilmodule.cpp\ $$PWD/qdeclarativeview.cpp \ $$PWD/qdeclarativeconnections.cpp \ @@ -30,6 +31,7 @@ SOURCES += \ $$PWD/qlistmodelinterface.cpp HEADERS += \ + $$PWD/qdeclarativeapplication_p.h \ $$PWD/qdeclarativeutilmodule_p.h\ $$PWD/qdeclarativeview.h \ $$PWD/qdeclarativeconnections_p.h \ diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index e81773b..0c1304f 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -1770,7 +1770,7 @@ QString QFileDialog::getOpenFileName(QWidget *parent, On Symbian^3 the parameter \a selectedFilter has no meaning and the \a options parameter is only used to define if the native file dialog is - used. + used. On Symbian^3, this function can only return a single filename. \warning Do not delete \a parent during the execution of the dialog. If you want to do this, you should create the dialog yourself using one of the diff --git a/src/gui/dialogs/qfiledialog_symbian.cpp b/src/gui/dialogs/qfiledialog_symbian.cpp index e7197bd..ed98950 100644 --- a/src/gui/dialogs/qfiledialog_symbian.cpp +++ b/src/gui/dialogs/qfiledialog_symbian.cpp @@ -54,6 +54,9 @@ QT_BEGIN_NAMESPACE +extern QStringList qt_make_filter_list(const QString &filter); // defined in qfiledialog.cpp +extern QStringList qt_clean_filter_list(const QString &filter); // defined in qfiledialog.cpp + enum DialogMode { DialogOpen, DialogSave, DialogFolder }; #if defined(Q_WS_S60) && defined(SYMBIAN_VERSION_SYMBIAN3) class CExtensionFilter : public MAknFileFilter @@ -61,56 +64,39 @@ class CExtensionFilter : public MAknFileFilter public: void setFilter(const QString filter) { - filterList.clear(); - if (filter.left(2) == QLatin1String("*.")) { - //Filter has only extensions - filterList << filter.split(QLatin1String(" ")); - return; - } else { - //Extensions are in parenthesis and there may be several filters - QStringList separatedFilters(filter.split(QLatin1String(";;"))); - for (int i = 0; i < separatedFilters.size(); i++) { - if (separatedFilters.at(i).contains(QLatin1String("(*)"))) { - filterList << QLatin1String("(*)"); - return; - } - } - QRegExp rx(QLatin1String("\\(([^\\)]*)\\)")); - int pos = 0; - while ((pos = rx.indexIn(filter, pos)) != -1) { - filterList << rx.cap(1).split(QLatin1String(" ")); - pos += rx.matchedLength(); - } + QStringList unparsedFiltersList = qt_make_filter_list(filter); + QStringList filterList; + filterRxList.clear(); + + foreach (QString unparsedFilter, unparsedFiltersList) { + filterList << qt_clean_filter_list(unparsedFilter); + } + foreach (QString currentFilter, filterList) { + QRegExp filterRx(currentFilter, Qt::CaseInsensitive, QRegExp::Wildcard); + filterRxList << filterRx; } } TBool Accept(const TDesC &/*aDriveAndPath*/, const TEntry &aEntry) const { - if (aEntry.IsDir()) - return ETrue; - //If no filter for files, all can be accepted - if (filterList.isEmpty()) + if (filterRxList.isEmpty()) return ETrue; - if (filterList == QStringList(QLatin1String("(*)"))) + if (aEntry.IsDir()) return ETrue; - for (int i = 0; i < filterList.size(); ++i) { - QString extension = filterList.at(i); - //remove '*' from the beginning of the extension - if (extension.at(0) == QLatin1Char('*')) - extension = extension.mid(1); - + foreach (QRegExp rx, filterRxList) { QString fileName = qt_TDesC2QString(aEntry.iName); - if (fileName.endsWith(extension)) + if (rx.exactMatch(fileName)) return ETrue; } + return EFalse; } private: - QStringList filterList; + QList<QRegExp> filterRxList; }; #endif @@ -140,11 +126,13 @@ static QString launchSymbianDialog(const QString dialogCaption, const QString st CleanupStack::PushL(extensionFilter); extensionFilter->setFilter(filter); select = AknCommonDialogsDynMem::RunSelectDlgLD(types, target, - startFolder, NULL, NULL, titlePtr, extensionFilter); + startFolder, 0, 0, titlePtr, extensionFilter); CleanupStack::Pop(extensionFilter); } else if (dialogMode == DialogSave) { + QString defaultFileName = QFileDialogPrivate::initialSelection(startDirectory); + target = qt_QString2TPtrC(defaultFileName); select = AknCommonDialogsDynMem::RunSaveDlgLD(types, target, - startFolder, NULL, NULL, titlePtr); + startFolder, 0, 0, titlePtr); } else if (dialogMode == DialogFolder) { select = AknCommonDialogsDynMem::RunFolderSelectDlgLD(types, target, startFolder, 0, 0, titlePtr, NULL, NULL); @@ -160,8 +148,10 @@ static QString launchSymbianDialog(const QString dialogCaption, const QString st startFolder = qt_QString2TPtrC(dir); } } - if (select) - selection.append(qt_TDesC2QString(target)); + if (select) { + QFileInfo fi(qt_TDesC2QString(target)); + selection = fi.absoluteFilePath(); + } #endif return selection; } diff --git a/src/gui/dialogs/qpagesetupdialog.cpp b/src/gui/dialogs/qpagesetupdialog.cpp index 2a7847e..4037e1c 100644 --- a/src/gui/dialogs/qpagesetupdialog.cpp +++ b/src/gui/dialogs/qpagesetupdialog.cpp @@ -107,10 +107,10 @@ class QPageSetupDialogPrivate : public QAbstractPageSetupDialogPrivate This value is obsolete and does nothing since Qt 4.5: - \value DontUseSheet In previous versions of Qt, exec() the page setup dialog - would create a sheet by default if the dialog was given a parent. - This is no longer supported in Qt 4.5. If you want to use sheets, use - QPageSetupDialog::open() instead. + \value DontUseSheet In previous versions of QDialog::exec() the + page setup dialog would create a sheet by default if the dialog + was given a parent. This is no longer supported from Qt 4.5. If + you want to use sheets, use QPageSetupDialog::open() instead. \omitvalue None \omitvalue OwnsPrinter diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp index 4656af8..e207ed1 100644 --- a/src/gui/embedded/qscreen_qws.cpp +++ b/src/gui/embedded/qscreen_qws.cpp @@ -1768,7 +1768,7 @@ QImage::Format QScreenPrivate::preferredImageFormat() const This function is called by every \l{Qt for Embedded Linux} application on startup, and must be implemented to map in the framebuffer and the accelerated drivers that the graphics card - control registers. Note that coonnect must be called \e before + control registers. Note that connect must be called \e before the initDevice() function. Ensure that true is returned if a connection to the screen device diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index b059bd2..014b61b 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -56,9 +56,9 @@ Items that are anchored are automatically added to the layout, and if items are removed, all their anchors will be automatically removed. - \beginfloatleft + \div {float-left} \inlineimage simpleanchorlayout-example.png Using an anchor layout to align simple colored widgets. - \endfloat + \enddiv Anchors are always set up between edges of an item, where the "center" is also considered to be an edge. Consider the following example: diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 01fed8c..ecc8941 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -7689,11 +7689,13 @@ void QGraphicsObject::updateMicroFocus() void QGraphicsItemPrivate::children_append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item) { - QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(list->object); - if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) { - item->setParentItem(graphicsObject); - } else { - QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0); + if (item) { + QGraphicsObject *graphicsObject = static_cast<QGraphicsObject *>(list->object); + if (QGraphicsItemPrivate::get(graphicsObject)->sendParentChangeNotification) { + item->setParentItem(graphicsObject); + } else { + QGraphicsItemPrivate::get(item)->setParentItemHelper(graphicsObject, 0, 0); + } } } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7b87239..77ccc8e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -130,7 +130,7 @@ item on the scene gains focus, the scene automatically gains focus. If the scene has focus, hasFocus() will return true, and key events will be forwarded to the focus item, if any. If the scene loses focus, (i.e., - someone calls clearFocus(),) while an item has focus, the scene will + someone calls clearFocus()) while an item has focus, the scene will maintain its item focus information, and once the scene regains focus, it will make sure the last focus item regains focus. @@ -806,28 +806,23 @@ void QGraphicsScenePrivate::setFocusItemHelper(QGraphicsItem *item, } if (focusItem) { - QFocusEvent event(QEvent::FocusOut, focusReason); lastFocusItem = focusItem; - focusItem = 0; - sendEvent(lastFocusItem, &event); #ifndef QT_NO_IM if (lastFocusItem && (lastFocusItem->flags() & QGraphicsItem::ItemAcceptsInputMethod)) { - // Reset any visible preedit text - QInputMethodEvent imEvent; - sendEvent(lastFocusItem, &imEvent); - // Close any external input method panel. This happens // automatically by removing WA_InputMethodEnabled on // the views, but if we are changing focus, we have to // do it ourselves. - if (item) { - for (int i = 0; i < views.size(); ++i) - if (views.at(i)->inputContext()) - views.at(i)->inputContext()->reset(); - } + for (int i = 0; i < views.size(); ++i) + if (views.at(i)->inputContext()) + views.at(i)->inputContext()->reset(); } + + focusItem = 0; + QFocusEvent event(QEvent::FocusOut, focusReason); + sendEvent(lastFocusItem, &event); #endif //QT_NO_IM } @@ -3104,8 +3099,8 @@ bool QGraphicsScene::stickyFocus() const \list \o If the item receives a mouse release event when there are no other buttons pressed, it loses the mouse grab. - \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false))}, - or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false))}, + \o If the item becomes invisible (i.e., someone calls \c {item->setVisible(false)}), + or if it becomes disabled (i.e., someone calls \c {item->setEnabled(false)}), it loses the mouse grab. \o If the item is removed from the scene, it loses the mouse grab. \endlist @@ -5924,6 +5919,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item->isPanel()) break; + if (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation) + break; } // If nobody could take focus, clear it. @@ -5956,6 +5953,8 @@ bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEve } if (item && item->isPanel()) break; + if (item && (item->d_ptr->flags & QGraphicsItem::ItemStopsClickFocusPropagation)) + break; } touchEvent->setAccepted(eventAccepted); diff --git a/src/gui/gui.pro b/src/gui/gui.pro index fe1a595..076fe0a 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -65,15 +65,14 @@ symbian { neon:*-g++* { DEFINES += QT_HAVE_NEON HEADERS += $$NEON_HEADERS - SOURCES += $$NEON_SOURCES DRAWHELPER_NEON_ASM_FILES = $$NEON_ASM - neon_compiler.commands = $$QMAKE_CXX -c -mfpu=neon - neon_compiler.commands += $(CXXFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} + neon_compiler.commands = $$QMAKE_CXX -c + neon_compiler.commands += $(CXXFLAGS) -mfpu=neon $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT} neon_compiler.dependency_type = TYPE_C neon_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)} - neon_compiler.input = DRAWHELPER_NEON_ASM_FILES + neon_compiler.input = DRAWHELPER_NEON_ASM_FILES NEON_SOURCES neon_compiler.variable_out = OBJECTS neon_compiler.name = compiling[neon] ${QMAKE_FILE_IN} silent:neon_compiler.commands = @echo compiling[neon] ${QMAKE_FILE_IN} && $$neon_compiler.commands diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp index 09c086a..6dea9d9 100644 --- a/src/gui/image/qbmphandler.cpp +++ b/src/gui/image/qbmphandler.cpp @@ -246,6 +246,8 @@ static bool read_dib_body(QDataStream &s, const BMP_INFOHDR &bi, int offset, int if (depth != 32) { ncols = bi.biClrUsed ? bi.biClrUsed : 1 << nbits; + if (ncols > 256) // sanity check - don't run out of mem if color table is broken + return false; image.setColorCount(ncols); } diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 91ee697..d992dd5 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -477,12 +477,12 @@ bool QImageData::checkForAlphaPixels() const function. For example: \table + \header + \o {2,1}32-bit \row \o \inlineimage qimage-32bit_scaled.png \o \snippet doc/src/snippets/code/src_gui_image_qimage.cpp 0 - \header - \o {2,1}32-bit \endtable In case of a 8-bit and monchrome images, the pixel value is only @@ -498,12 +498,12 @@ bool QImageData::checkForAlphaPixels() const example: \table + \header + \o {2,1} 8-bit \row \o \inlineimage qimage-8bit_scaled.png \o \snippet doc/src/snippets/code/src_gui_image_qimage.cpp 1 - \header - \o {2,1} 8-bit \endtable QImage also provide the scanLine() function which returns a diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index 01baa36..8face87 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -181,15 +181,17 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format,bool /* if (ok) { xshmimg->data = (char*)shmat(xshminfo.shmid, 0, 0); xshminfo.shmaddr = xshmimg->data; - if (shmctl(xshminfo.shmid, IPC_RMID, 0) == -1) - qWarning() << "Error while marking the shared memory segment to be destroyed"; ok = (xshminfo.shmaddr != (char*)-1); if (ok) image = QImage((uchar *)xshmimg->data, width, height, format); } xshminfo.readOnly = false; - if (ok) + if (ok) { ok = XShmAttach(X11->display, &xshminfo); + XSync(X11->display, False); + if (shmctl(xshminfo.shmid, IPC_RMID, 0) == -1) + qWarning() << "Error while marking the shared memory segment to be destroyed"; + } if (!ok) { qWarning() << "QNativeImage: Unable to attach to shared memory segment."; if (xshmimg->data) { diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index dbe8177..ca5f133 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -1012,6 +1012,33 @@ void QS60PixmapData::fromNativeType(void* pixmap, NativeType nativeType) } } +void QS60PixmapData::convertToDisplayMode(int mode) +{ + const TDisplayMode displayMode = static_cast<TDisplayMode>(mode); + if (!cfbsBitmap || cfbsBitmap->DisplayMode() == displayMode) + return; + if (image.depth() != TDisplayModeUtils::NumDisplayModeBitsPerPixel(displayMode)) { + qWarning("Cannot convert display mode due to depth mismatch"); + return; + } + + const TSize size = cfbsBitmap->SizeInPixels(); + QScopedPointer<CFbsBitmap> newBitmap(createSymbianCFbsBitmap(size, displayMode)); + + const uchar *sptr = const_cast<const QImage &>(image).bits(); + symbianBitmapDataAccess->beginDataAccess(newBitmap.data()); + uchar *dptr = (uchar*)newBitmap->DataAddress(); + Mem::Copy(dptr, sptr, image.byteCount()); + symbianBitmapDataAccess->endDataAccess(newBitmap.data()); + + QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); + delete cfbsBitmap; + lock.relock(); + cfbsBitmap = newBitmap.take(); + setSerialNumber(cfbsBitmap->Handle()); + UPDATE_BUFFER(); +} + QPixmapData *QS60PixmapData::createCompatiblePixmapData() const { return new QS60PixmapData(pixelType()); diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h index e4060dc..c440bbc 100644 --- a/src/gui/image/qpixmap_s60_p.h +++ b/src/gui/image/qpixmap_s60_p.h @@ -107,6 +107,8 @@ public: void* toNativeType(NativeType type); void fromNativeType(void* pixmap, NativeType type); + void convertToDisplayMode(int mode); + private: void release(); void fromSymbianBitmap(CFbsBitmap* bitmap, bool lockFormat=false); diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp index ffad75b..075d5da 100644 --- a/src/gui/image/qxpmhandler.cpp +++ b/src/gui/image/qxpmhandler.cpp @@ -864,7 +864,7 @@ static bool read_xpm_body( QByteArray buf(200, 0); int i; - if (cpp > 15) + if (cpp < 0 || cpp > 15) return false; // For > 256 colors, we delay creation of the image until diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 4dd0aa3..291ec6e 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -657,9 +657,9 @@ QAbstractItemView::~QAbstractItemView() deleteLater() functions to explicitly delete them. The view \e{does not} take ownership of the model unless it is the model's - parent object because the view may be shared between many different views. + parent object because the model may be shared between many different views. - \sa selectionModel(), setSelectionModel() + \sa selectionModel(), setSelectionModel() */ void QAbstractItemView::setModel(QAbstractItemModel *model) { diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index 0d8527a..6e7b9a7 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1245,12 +1245,14 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) #ifdef Q_WS_S60 // If widget is fullscreen/minimized, hide status pane and button container otherwise show them. QWidget *const window = qwidget->window(); - const bool visible = !(window->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool statusPaneVisibility = visible; - const bool isFullscreen = window->windowState() & Qt::WindowFullScreen; - const bool cbaVisibilityHint = window->windowFlags() & Qt::WindowSoftkeysVisibleHint; - const bool buttonGroupVisibility = (visible || (isFullscreen && cbaVisibilityHint)); - S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + if (!window->parentWidget()) { // Only top level native windows have control over cba/status pane + const bool decorationsVisible = !(window->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool statusPaneVisibility = decorationsVisible; + const bool isFullscreen = window->windowState() & Qt::WindowFullScreen; + const bool cbaVisibilityHint = window->windowFlags() & Qt::WindowSoftkeysVisibleHint; + const bool buttonGroupVisibility = (decorationsVisible || (isFullscreen && cbaVisibilityHint)); + S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + } #endif } else if (QApplication::activeWindow() == qwidget->window()) { bool focusedControlFound = false; @@ -1618,7 +1620,9 @@ void qt_init(QApplicationPrivate * /* priv */, int) qRegisterMetaType<WId>("WId"); } +#ifdef QT_NO_FREETYPE extern void qt_cleanup_symbianFontDatabase(); // qfontdatabase_s60.cpp +#endif /***************************************************************************** qt_cleanup() - cleans up when the application is finished @@ -1635,7 +1639,9 @@ void qt_cleanup() QFontCache::cleanup(); // Has to happen now, since QFontEngineS60 has FBS handles QPixmapCache::clear(); // Has to happen now, since QS60PixmapData has FBS handles +#ifdef QT_NO_FREETYPE qt_cleanup_symbianFontDatabase(); +#endif // S60 structure and window server session are freed in eventdispatcher destructor as they are needed there // It's important that this happens here, before the event dispatcher gets diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 2fdad8d..589b12e 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -5661,10 +5661,21 @@ static void sm_performSaveYourself(QSessionManagerPrivate* smd) sm_setProperty(QString::fromLatin1(SmProgram), argument0); // tell the session manager about our user as well. struct passwd *entryPtr = 0; -#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) - QVarLengthArray<char, 1024> buf(sysconf(_SC_GETPW_R_SIZE_MAX)); +#if defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) + QVarLengthArray<char, 1024> buf(qMax<long>(sysconf(_SC_GETPW_R_SIZE_MAX), 1024L)); struct passwd entry; - getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr); + while (getpwuid_r(geteuid(), &entry, buf.data(), buf.size(), &entryPtr) == ERANGE) { + if (buf.size() >= 32768) { + // too big already, fail + static char badusername[] = ""; + entryPtr = &entry; + entry.pw_name = badusername; + break; + } + + // retry with a bigger buffer + buf.resize(buf.size() * 2); + } #else entryPtr = getpwuid(geteuid()); #endif diff --git a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm index 6d7bc19..77cd890 100644 --- a/src/gui/kernel/qcocoaapplicationdelegate_mac.mm +++ b/src/gui/kernel/qcocoaapplicationdelegate_mac.mm @@ -91,6 +91,7 @@ QT_BEGIN_NAMESPACE extern void onApplicationChangedActivation(bool); // qapplication_mac.mm extern void qt_release_apple_event_handler(); //qapplication_mac.mm extern QPointer<QWidget> qt_last_mouse_receiver; // qapplication_mac.cpp +extern QPointer<QWidget> qt_last_native_mouse_receiver; // qt_cocoa_helpers_mac.mm extern QPointer<QWidget> qt_button_down; // qapplication_mac.cpp QT_END_NAMESPACE @@ -268,6 +269,8 @@ static void cleanupCocoaApplicationDelegate() qt_mac_getTargetForMouseEvent(0, QEvent::Enter, qlocal, qglobal, 0, &widgetUnderMouse); QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, 0); qt_last_mouse_receiver = widgetUnderMouse; + qt_last_native_mouse_receiver = widgetUnderMouse ? + (widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget()) : 0; } } @@ -282,6 +285,7 @@ static void cleanupCocoaApplicationDelegate() if (!QWidget::mouseGrabber()) QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver); qt_last_mouse_receiver = 0; + qt_last_native_mouse_receiver = 0; qt_button_down = 0; } diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index f0ae886..3d87a9e 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -78,6 +78,7 @@ QT_BEGIN_NAMESPACE extern void qt_mac_update_cursor(); // qcursor_mac.mm extern bool qt_sendSpontaneousEvent(QObject *, QEvent *); // qapplication.cpp extern QPointer<QWidget> qt_last_mouse_receiver; // qapplication_mac.cpp +extern QPointer<QWidget> qt_last_native_mouse_receiver; // qt_cocoa_helpers_mac.mm extern OSViewRef qt_mac_nativeview_for(const QWidget *w); // qwidget_mac.mm extern OSViewRef qt_mac_effectiveview_for(const QWidget *w); // qwidget_mac.mm extern QPointer<QWidget> qt_button_down; //qapplication_mac.cpp @@ -461,6 +462,7 @@ static int qCocoaViewCount = 0; if (widgetUnderMouse == 0) { QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver); qt_last_mouse_receiver = 0; + qt_last_native_mouse_receiver = 0; } } } diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e7abb47..698c94b 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -53,6 +53,10 @@ #include "qgesture.h" #include "qgesture_p.h" +#ifdef Q_OS_SYMBIAN +#include "private/qcore_symbian_p.h" +#endif + QT_BEGIN_NAMESPACE /*! @@ -724,12 +728,12 @@ QWheelEvent::QWheelEvent(const QPoint &pos, const QPoint& globalPos, int delta, The \a type parameter must be QEvent::KeyPress, QEvent::KeyRelease, or QEvent::ShortcutOverride. - Int \a key is the code for the Qt::Key that the event loop should listen - for. If \a key is 0, the event is not a result of a known key; for + Int \a key is the code for the Qt::Key that the event loop should listen + for. If \a key is 0, the event is not a result of a known key; for example, it may be the result of a compose sequence or keyboard macro. - The \a modifiers holds the keyboard modifiers, and the given \a text - is the Unicode text that the key generated. If \a autorep is true, - isAutoRepeat() will be true. \a count is the number of keys involved + The \a modifiers holds the keyboard modifiers, and the given \a text + is the Unicode text that the key generated. If \a autorep is true, + isAutoRepeat() will be true. \a count is the number of keys involved in the event. */ QKeyEvent::QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text, @@ -1658,7 +1662,7 @@ Qt::ButtonState QContextMenuEvent::state() const string is controlled by the widget only). The AttributeType enum describes the different attributes that can be set. - A class implementing QWidget::inputMethodEvent() or + A class implementing QWidget::inputMethodEvent() or QGraphicsItem::inputMethodEvent() should at least understand and honor the \l TextFormat and \l Cursor attributes. @@ -3023,9 +3027,16 @@ QShowEvent::~QShowEvent() This event is only used to notify the application of a request. It may be safely ignored. - \note This class is currently supported for Mac OS X only. + \note This class is currently supported for Mac OS X and Symbian only. */ +QFileOpenEventPrivate::~QFileOpenEventPrivate() +{ +#ifdef Q_OS_SYMBIAN + file.Close(); +#endif +} + /*! \internal @@ -3049,6 +3060,22 @@ QFileOpenEvent::QFileOpenEvent(const QUrl &url) f = url.toLocalFile(); } +#ifdef Q_OS_SYMBIAN +/*! \internal +*/ +QFileOpenEvent::QFileOpenEvent(const RFile &fileHandle) + : QEvent(FileOpen) +{ + TFileName fullName; + fileHandle.FullName(fullName); + f = qt_TDesC2QString(fullName); + QScopedPointer<QFileOpenEventPrivate> priv(new QFileOpenEventPrivate(QUrl::fromLocalFile(f))); + // Duplicate here allows the file handle to be valid after S60 app construction is complete. + qt_symbian_throwIfError(priv->file.Duplicate(fileHandle)); + d = reinterpret_cast<QEventPrivate *>(priv.take()); +} +#endif + /*! \internal */ QFileOpenEvent::~QFileOpenEvent() @@ -3074,6 +3101,39 @@ QUrl QFileOpenEvent::url() const return reinterpret_cast<const QFileOpenEventPrivate *>(d)->url; } +/*! + \fn bool openFile(QFile &file, QIODevice::OpenMode flags) const + + Opens a QFile on the file referenced by this event. + Returns true if successful; otherwise returns false. + + This is necessary as some files cannot be opened by name, but require specific + information stored in this event. + For example, if this QFileOpenEvent contains a request to open a Symbian data caged file, + the QFile could only be opened from the Symbian RFile used in the construction of this event. + + \since 4.8 +*/ +bool QFileOpenEvent::openFile(QFile &file, QIODevice::OpenMode flags) const +{ + file.setFileName(f); +#ifdef Q_OS_SYMBIAN + const QFileOpenEventPrivate *priv = reinterpret_cast<const QFileOpenEventPrivate *>(d); + if (priv->file.SubSessionHandle()) { + RFile dup; + // Duplicate here means that the opened QFile will continue to be valid beyond the lifetime of this QFileOpenEvent. + // It also allows openFile to be used in threads other than the thread in which the QFileOpenEvent was created. + if (dup.Duplicate(priv->file) == KErrNone) { + QScopedPointer<RFile, QScopedPointerRCloser<RFile> > dupCloser(&dup); + bool open = file.open(dup, flags, QFile::AutoCloseHandle); + dupCloser.take(); + return open; + } + } +#endif + return file.open(flags); +} + #ifndef QT_NO_TOOLBAR /*! \internal @@ -3622,7 +3682,7 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif -/*! +/*! \class QTouchEvent \brief The QTouchEvent class contains parameters that describe a touch event. \since 4.6 diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index a7b06f4..93c2bc5 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -54,6 +54,11 @@ #include <QtCore/qvariant.h> #include <QtCore/qmap.h> #include <QtCore/qset.h> +#include <QtCore/qfile.h> + +#ifdef Q_OS_SYMBIAN +class RFile; +#endif QT_BEGIN_HEADER @@ -641,10 +646,14 @@ class Q_GUI_EXPORT QFileOpenEvent : public QEvent public: QFileOpenEvent(const QString &file); QFileOpenEvent(const QUrl &url); +#ifdef Q_OS_SYMBIAN + QFileOpenEvent(const RFile &fileHandle); +#endif ~QFileOpenEvent(); inline QString file() const { return f; } QUrl url() const; + bool openFile(QFile &file, QIODevice::OpenMode flags) const; private: QString f; }; diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 3a27023..b79f372 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -46,6 +46,10 @@ #include <QtCore/qurl.h> #include <QtGui/qevent.h> +#ifdef Q_OS_SYMBIAN +#include <f32file.h> +#endif + QT_BEGIN_NAMESPACE // @@ -174,8 +178,12 @@ public: : url(url) { } + ~QFileOpenEventPrivate(); QUrl url; +#ifdef Q_OS_SYMBIAN + RFile file; +#endif }; diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 17ede02..56daba2 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -332,7 +332,7 @@ void QPanGesture::setAcceleration(qreal value) /*! \class QPinchGesture \since 4.6 - \brief The QPinchGesture class describes a pinch gesture made my the user. + \brief The QPinchGesture class describes a pinch gesture made by the user. \ingroup touch \ingroup gestures diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp index 1eeaf8e..e014ec8 100644 --- a/src/gui/kernel/qlayout.cpp +++ b/src/gui/kernel/qlayout.cpp @@ -980,10 +980,10 @@ void QLayoutPrivate::reparentChildWidgets(QWidget *mw) /*! This function is called from \c addWidget() functions in - subclasses to add \a w as a child widget. + subclasses to add \a w as a managed widget of a layout. - If \a w is already in a layout, this function will give a warning - and remove \a w from the layout. This function must therefore be + If \a w is already managed by a layout, this function will give a warning + and remove \a w from that layout. This function must therefore be called before adding \a w to the layout's data structure. */ void QLayout::addChildWidget(QWidget *w) diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm index 0e432f3..6a4f0bb 100644 --- a/src/gui/kernel/qmacgesturerecognizer_mac.mm +++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm @@ -69,6 +69,7 @@ QMacSwipeGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e case QNativeGestureEvent::Swipe: { QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); g->setSwipeAngle(ev->angle); + g->setHotSpot(ev->position); return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; break; } default: @@ -110,6 +111,7 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e g->setCenterPoint(g->startCenterPoint()); g->setChangeFlags(QPinchGesture::CenterPointChanged); g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); + g->setHotSpot(ev->position); return QGestureRecognizer::MayBeGesture | QGestureRecognizer::ConsumeEventHint; case QNativeGestureEvent::Rotate: { g->setLastScaleFactor(g->scaleFactor()); @@ -117,6 +119,7 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e g->setRotationAngle(g->rotationAngle() + ev->percentage); g->setChangeFlags(QPinchGesture::RotationAngleChanged); g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); + g->setHotSpot(ev->position); return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; } case QNativeGestureEvent::Zoom: @@ -125,6 +128,7 @@ QMacPinchGestureRecognizer::recognize(QGesture *gesture, QObject *obj, QEvent *e g->setScaleFactor(g->scaleFactor() * (1 + ev->percentage)); g->setChangeFlags(QPinchGesture::ScaleFactorChanged); g->setTotalChangeFlags(g->totalChangeFlags() | g->changeFlags()); + g->setHotSpot(ev->position); return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; case QNativeGestureEvent::GestureEnd: return QGestureRecognizer::FinishGesture | QGestureRecognizer::ConsumeEventHint; @@ -221,6 +225,7 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent * const QPointF posOffset = p - _startPos; g->setLastOffset(g->offset()); g->setOffset(QPointF(posOffset.x(), posOffset.y())); + g->setHotSpot(_startPos); return QGestureRecognizer::TriggerGesture; } } else if (_panTimer.isActive()) { @@ -239,6 +244,7 @@ QMacPanGestureRecognizer::recognize(QGesture *gesture, QObject *target, QEvent * break; // Begin new pan session! _startPos = QCursor::pos(); + g->setHotSpot(_startPos); return QGestureRecognizer::TriggerGesture | QGestureRecognizer::ConsumeEventHint; } break; } diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index ddbf53f..c8132e8 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -1060,30 +1060,26 @@ QWidget *qt_mac_getTargetForMouseEvent( returnGlobalPoint = flipPoint([NSEvent mouseLocation]).toPoint(); QWidget *mouseGrabber = QWidget::mouseGrabber(); bool buttonDownNotBlockedByModal = qt_button_down && !QApplicationPrivate::isBlockedByModal(qt_button_down); + QWidget *popup = QApplication::activePopupWidget(); // Resolve the widget under the mouse: QWidget *widgetUnderMouse = 0; - if (nativeWidget) { + if (popup || qt_button_down || !nativeWidget || !nativeWidget->isVisible()) { + // Using QApplication::widgetAt for finding the widget under the mouse + // is most safe, since it ignores cocoas own mouse down redirections (which + // we need to be prepared for when using nativeWidget as starting point). + // (the only exception is for QMacNativeWidget, where QApplication::widgetAt fails). + // But it is also slower (I guess), so we try to avoid it and use nativeWidget if we can: + widgetUnderMouse = QApplication::widgetAt(returnGlobalPoint); + } + + if (!widgetUnderMouse && nativeWidget) { + // Entering here should be the common case. We + // also handle the QMacNativeWidget fallback case. QPoint p = nativeWidget->mapFromGlobal(returnGlobalPoint); widgetUnderMouse = nativeWidget->childAt(p); - if (!widgetUnderMouse){ - // Cocoa will redirct mouse event to the current - // mouse down widget, which is not what we want for our - // widgetUnderMouse assignment. So we need to check - // if we are actually inside nativeView: - if (nativeWidget->rect().contains(p)) { - widgetUnderMouse = nativeWidget; - } else { - // Ok, fallback to find the widget under mouse ourselves. - widgetUnderMouse = QApplication::widgetAt(returnGlobalPoint); - } - } - } else { - // Calling QApplication::widgetAt is potentially slow, hence the - // reason we avoid it if we can. So supplying a nativeWidget to - // this function is mostly an optimization. But at the same time, - // calling QApplication::widgetAt fails for QMacNativeWidget... - widgetUnderMouse = QApplication::widgetAt(returnGlobalPoint); + if (!widgetUnderMouse && nativeWidget->rect().contains(p)) + widgetUnderMouse = nativeWidget; } if (widgetUnderMouse) { @@ -1107,23 +1103,27 @@ QWidget *qt_mac_getTargetForMouseEvent( if (returnWidgetUnderMouse) *returnWidgetUnderMouse = widgetUnderMouse; - // Resolve the target for the mouse event. Default will be widgetUnderMouse, except - // if there is a popup-"grab", mousegrab, or button-down-"grab": - QWidget *popup = QApplication::activePopupWidget(); + // Resolve the target for the mouse event. Default will be + // widgetUnderMouse, except if there is a grab (popup/mouse/button-down): if (popup && !mouseGrabber) { - if (!popup->isAncestorOf(widgetUnderMouse)) { - // The popup will always grab the mouse unless the - // mouse is over a child, or the user scrolls: + // We special case handling of popups, since they have an implicitt mouse grab. + QWidget *candidate = buttonDownNotBlockedByModal ? qt_button_down : widgetUnderMouse; + if (!popup->isAncestorOf(candidate)) { + // INVARIANT: we have a popup, but the candidate is not + // in it. But the popup will grab the mouse anyway, + // except if the user scrolls: if (eventType == QEvent::Wheel) return 0; returnLocalPoint = popup->mapFromGlobal(returnGlobalPoint); return popup; - } else if (popup == widgetUnderMouse) { + } else if (popup == candidate) { + // INVARIANT: The candidate is the popup itself, and not a child: returnLocalPoint = popup->mapFromGlobal(returnGlobalPoint); return popup; } else { - returnLocalPoint = widgetUnderMouse->mapFromGlobal(returnGlobalPoint); - return widgetUnderMouse; + // INVARIANT: The candidate is a child inside the popup: + returnLocalPoint = candidate->mapFromGlobal(returnGlobalPoint); + return candidate; } } @@ -1139,6 +1139,8 @@ QWidget *qt_mac_getTargetForMouseEvent( return target; } +QPointer<QWidget> qt_last_native_mouse_receiver = 0; + static inline void qt_mac_checkEnterLeaveForNativeWidgets(QWidget *maybeEnterWidget) { // Dispatch enter/leave for the cases where QApplicationPrivate::sendMouseEvent do @@ -1149,29 +1151,25 @@ static inline void qt_mac_checkEnterLeaveForNativeWidgets(QWidget *maybeEnterWid if (qt_button_down || QWidget::mouseGrabber()) return; - if ((maybeEnterWidget == qt_last_mouse_receiver) && qt_last_mouse_receiver) - return; + if ((maybeEnterWidget == qt_last_native_mouse_receiver) && qt_last_native_mouse_receiver) + return; if (maybeEnterWidget) { - if (!qt_last_mouse_receiver) { + if (!qt_last_native_mouse_receiver) { // case 3 QApplicationPrivate::dispatchEnterLeave(maybeEnterWidget, 0); - qt_last_mouse_receiver = maybeEnterWidget; - } else if (qt_last_mouse_receiver->internalWinId() && maybeEnterWidget->internalWinId()) { + qt_last_native_mouse_receiver = maybeEnterWidget->internalWinId() ? maybeEnterWidget : maybeEnterWidget->nativeParentWidget(); + } else if (maybeEnterWidget->internalWinId()) { // case 1 - if (qt_last_mouse_receiver->isVisible()) { - QApplicationPrivate::dispatchEnterLeave(maybeEnterWidget, qt_last_mouse_receiver); - qt_last_mouse_receiver = maybeEnterWidget; - } + QApplicationPrivate::dispatchEnterLeave(maybeEnterWidget, qt_last_native_mouse_receiver); + qt_last_native_mouse_receiver = maybeEnterWidget->internalWinId() ? maybeEnterWidget : maybeEnterWidget->nativeParentWidget(); } // else at lest one of the widgets are alien, so enter/leave will be handled in QApplicationPrivate } else { - if (qt_last_mouse_receiver && qt_last_mouse_receiver->internalWinId()) { + if (qt_last_native_mouse_receiver) { // case 2 - QApplicationPrivate::dispatchEnterLeave(0, qt_last_mouse_receiver); - // This seems to be the only case where we need to update qt_last_mouse_receiver - // from the mac specific code. Otherwise, QApplicationPrivate::sendMouseEvent - // will handle it: + QApplicationPrivate::dispatchEnterLeave(0, qt_last_native_mouse_receiver); qt_last_mouse_receiver = 0; + qt_last_native_mouse_receiver = 0; } } } @@ -1192,16 +1190,14 @@ bool qt_mac_handleMouseEvent(NSEvent *event, QEvent::Type eventType, Qt::MouseBu if (!widgetToGetMouse) return false; - if (!nativeWidget) { - // Path typically taken for mouse moves (send - // directly from [QCocoaWindow sendEvent] - if (!widgetUnderMouse) - return false; - nativeWidget = widgetUnderMouse->internalWinId() ? - widgetUnderMouse : widgetUnderMouse->nativeParentWidget(); - if (!nativeWidget) - return false; - } + // From here on, we let nativeWidget actually be the native widget under widgetUnderMouse. The reason + // for this, is that qt_mac_getTargetForMouseEvent will set cocoa's mouse event redirection aside when + // determining which widget is under the mouse (in other words, it will usually ignore nativeWidget). + // nativeWidget will be used in QApplicationPrivate::sendMouseEvent to correctly dispatch enter/leave events. + if (widgetUnderMouse) + nativeWidget = widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget(); + if (!nativeWidget) + return false; NSView *view = qt_mac_effectiveview_for(nativeWidget); // Handle tablet events (if any) first. @@ -1278,8 +1274,9 @@ bool qt_mac_handleMouseEvent(NSEvent *event, QEvent::Type eventType, Qt::MouseBu if (eventType == QEvent::MouseButtonRelease) { // A mouse button was released, which means that the implicit grab was // released. We therefore need to re-check if should send (delayed) enter leave events: - // qt_button_down has now become NULL since the call at the top of the function. - widgetToGetMouse = qt_mac_getTargetForMouseEvent(0, QEvent::None, localPoint, globalPoint, nativeWidget, &widgetUnderMouse); + // qt_button_down has now become NULL since the call at the top of the function. Also, since + // the relase might have closed a window, we dont give the nativeWidget hint + qt_mac_getTargetForMouseEvent(0, QEvent::None, localPoint, globalPoint, nativeWidget, &widgetUnderMouse); qt_mac_checkEnterLeaveForNativeWidgets(widgetUnderMouse); } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index fdb35d5..40697bf 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -141,6 +141,7 @@ public: int supportsPremultipliedAlpha : 1; int avkonComponentsSupportTransparency : 1; int menuBeingConstructed : 1; + int orientationSet : 1; QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type static CEikButtonGroupContainer *cba; @@ -295,6 +296,7 @@ inline QS60Data::QS60Data() supportsPremultipliedAlpha(0), avkonComponentsSupportTransparency(0), menuBeingConstructed(0), + orientationSet(0), s60ApplicationFactory(0) #ifdef Q_OS_SYMBIAN ,s60InstalledTrapHandler(0) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 547da11..bf9f6f9 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -127,6 +127,10 @@ #include "qtabwidget.h" // Needed in inTabWidget() #endif // QT_KEYPAD_NAVIGATION +#ifdef Q_WS_S60 +#include <aknappui.h> +#endif + // widget/widget data creation count //#define QWIDGET_EXTRA_DEBUG //#define ALIEN_DEBUG @@ -399,11 +403,24 @@ void QWidgetPrivate::scrollChildren(int dx, int dy) } } +QInputContext *QWidgetPrivate::assignedInputContext() const +{ +#ifndef QT_NO_IM + const QWidget *widget = q_func(); + while (widget) { + if (QInputContext *qic = widget->d_func()->ic) + return qic; + widget = widget->parentWidget(); + } +#endif + return 0; +} + QInputContext *QWidgetPrivate::inputContext() const { #ifndef QT_NO_IM - if (ic) - return ic; + if (QInputContext *qic = assignedInputContext()) + return qic; return qApp->inputContext(); #else return 0; @@ -10778,7 +10795,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) case Qt::WA_InputMethodEnabled: { #ifndef QT_NO_IM QWidget *focusWidget = d->effectiveFocusWidget(); - QInputContext *ic = focusWidget->d_func()->ic; + QInputContext *ic = focusWidget->d_func()->assignedInputContext(); if (!ic && (!on || hasFocus())) ic = focusWidget->d_func()->inputContext(); if (ic) { @@ -10871,6 +10888,42 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->registerTouchWindow(); #endif break; + case Qt::WA_LockPortraitOrientation: + case Qt::WA_LockLandscapeOrientation: + case Qt::WA_AutoOrientation: { + const Qt::WidgetAttribute orientations[3] = { + Qt::WA_LockPortraitOrientation, + Qt::WA_LockLandscapeOrientation, + Qt::WA_AutoOrientation + }; + + if (on) { + // We can only have one of these set at a time + for (int i = 0; i < 3; ++i) { + if (orientations[i] != attribute) + setAttribute_internal(orientations[i], false, data, d); + } + } + +#ifdef Q_WS_S60 + CAknAppUiBase* appUi = static_cast<CAknAppUiBase*>(CEikonEnv::Static()->EikAppUi()); + const CAknAppUiBase::TAppUiOrientation s60orientations[] = { + CAknAppUiBase::EAppUiOrientationPortrait, + CAknAppUiBase::EAppUiOrientationLandscape, + CAknAppUiBase::EAppUiOrientationAutomatic + }; + CAknAppUiBase::TAppUiOrientation s60orientation = CAknAppUiBase::EAppUiOrientationUnspecified; + for (int i = 0; i < 3; ++i) { + if (testAttribute(orientations[i])) { + s60orientation = s60orientations[i]; + break; + } + } + QT_TRAP_THROWING(appUi->SetOrientationL(s60orientation)); + S60->orientationSet = true; +#endif + break; + } default: break; } @@ -11229,7 +11282,7 @@ void QWidget::updateMicroFocus() #if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) Q_D(QWidget); // and optimization to update input context only it has already been created. - if (d->ic || qApp->d_func()->inputContext) { + if (d->assignedInputContext() || qApp->d_func()->inputContext) { QInputContext *ic = inputContext(); if (ic) ic->update(); diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 3ba12cd..9a5a5f1 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -186,6 +186,7 @@ extern void qt_mac_event_release(QWidget *w); //qapplication_mac.mm extern void qt_event_request_showsheet(QWidget *); //qapplication_mac.mm extern void qt_event_request_window_change(QWidget *); //qapplication_mac.mm extern QPointer<QWidget> qt_last_mouse_receiver; //qapplication_mac.mm +extern QPointer<QWidget> qt_last_native_mouse_receiver; //qt_cocoa_helpers_mac.mm extern IconRef qt_mac_create_iconref(const QPixmap &); //qpixmap_mac.cpp extern void qt_mac_set_cursor(const QCursor *, const QPoint &); //qcursor_mac.mm extern void qt_mac_update_cursor(); //qcursor_mac.mm @@ -3524,6 +3525,8 @@ void QWidgetPrivate::show_sys() qt_mac_getTargetForMouseEvent(0, QEvent::Enter, qlocal, qglobal, 0, &widgetUnderMouse); QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, qt_last_mouse_receiver); qt_last_mouse_receiver = widgetUnderMouse; + qt_last_native_mouse_receiver = widgetUnderMouse ? + (widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget()) : 0; } #endif @@ -3676,8 +3679,10 @@ void QWidgetPrivate::hide_sys() QPoint qlocal, qglobal; QWidget *widgetUnderMouse = 0; qt_mac_getTargetForMouseEvent(0, QEvent::Leave, qlocal, qglobal, 0, &widgetUnderMouse); - QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, qt_last_mouse_receiver); + QApplicationPrivate::dispatchEnterLeave(widgetUnderMouse, qt_last_native_mouse_receiver); qt_last_mouse_receiver = widgetUnderMouse; + qt_last_native_mouse_receiver = widgetUnderMouse ? + (widgetUnderMouse->internalWinId() ? widgetUnderMouse : widgetUnderMouse->nativeParentWidget()) : 0; } #endif diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 0ac66cb..1083a1f 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -568,6 +568,7 @@ public: // sub-classes that their internals are about to be released. virtual void aboutToDestroy() {} + QInputContext *assignedInputContext() const; QInputContext *inputContext() const; inline QWidget *effectiveFocusWidget() { QWidget *w = q_func(); diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index cb72800..85164d2 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -63,6 +63,19 @@ // CCoeControl objects until after the CONE event handler has finished running. Q_DECLARE_METATYPE(WId) +// Workaround for the fact that S60 SDKs 3.x do not contain the akntoolbar.h +// header, even though the documentation says that it should be there, and indeed +// it is present in the library. +class CAknToolbar : public CAknControl, + public MCoeControlObserver, + public MCoeControlBackground, + public MEikCommandObserver, + public MAknFadedComponent +{ +public: + IMPORT_C void SetToolbarVisibility(const TBool visible); +}; + QT_BEGIN_NAMESPACE extern bool qt_nograb(); @@ -488,6 +501,7 @@ void QWidgetPrivate::show_sys() QSymbianControl *id = static_cast<QSymbianControl *>(q->internalWinId()); const bool isFullscreen = q->windowState() & Qt::WindowFullScreen; + const TBool cbaRequested = q->windowFlags() & Qt::WindowSoftkeysVisibleHint; #ifdef Q_WS_S60 // Lazily initialize the S60 screen furniture when the first window is shown. @@ -507,11 +521,25 @@ void QWidgetPrivate::show_sys() CEikButtonGroupContainer *cba = CEikButtonGroupContainer::NewL(CEikButtonGroupContainer::ECba, CEikButtonGroupContainer::EHorizontal,ui,R_AVKON_SOFTKEYS_EMPTY_WITH_IDS); + if (isFullscreen && !cbaRequested) + cba->MakeVisible(false); CEikButtonGroupContainer *oldCba = factory->SwapButtonGroup(cba); Q_ASSERT(!oldCba); S60->setButtonGroupContainer(cba); + // If the creation of the first widget is delayed, for example by doing it + // inside the event loop, S60 somehow "forgets" to set the visibility of the + // toolbar (the three middle softkeys) when you flip the phone over, so we + // need to do it ourselves to avoid a "hole" in the application, even though + // Qt itself does not use the toolbar directly.. + CAknAppUi *appui = dynamic_cast<CAknAppUi *>(CEikonEnv::Static()->AppUi()); + if (appui) { + CAknToolbar *toolbar = appui->PopupToolbar(); + if (toolbar && !toolbar->IsVisible()) + toolbar->SetToolbarVisibility(ETrue); + } + CEikMenuBar *menuBar = new(ELeave) CEikMenuBar; menuBar->ConstructL(ui, 0, R_AVKON_MENUPANE_EMPTY); menuBar->SetMenuType(CEikMenuBar::EMenuOptions); @@ -1160,14 +1188,17 @@ void QWidget::setWindowState(Qt::WindowStates newstate) } #ifdef Q_WS_S60 - // Hide window decoration when switching to fullsccreen / minimized otherwise show decoration. - // The window decoration visibility has to be changed before doing actual window state - // change since in that order the availableGeometry will return directly the right size and - // we will avoid unnecessarty redraws - const bool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); - const bool statusPaneVisibility = visible; - const bool buttonGroupVisibility = (visible || (isFullscreen && cbaRequested)); - S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + bool decorationsVisible(false); + if (!parentWidget()) { // Only top level native windows have control over cba/status pane + // Hide window decoration when switching to fullscreen / minimized otherwise show decoration. + // The window decoration visibility has to be changed before doing actual window state + // change since in that order the availableGeometry will return directly the right size and + // we will avoid unnecessary redraws + decorationsVisible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized)); + const bool statusPaneVisibility = decorationsVisible; + const bool buttonGroupVisibility = (decorationsVisible || (isFullscreen && cbaRequested)); + S60->setStatusPaneAndButtonGroupVisibility(statusPaneVisibility, buttonGroupVisibility); + } #endif // Q_WS_S60 // Ensure the initial size is valid, since we store it as normalGeometry below. @@ -1191,7 +1222,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) // accurate because it did not consider the status pane. This means that when returning // normal mode after showing the status pane, the geometry would overlap so we should // move it if it never had an explicit position. - if (!wasMoved && S60->statusPane() && visible) { + if (!wasMoved && S60->statusPane() && decorationsVisible) { TPoint tl = static_cast<CEikAppUi*>(S60->appUi())->ClientRect().iTl; normalGeometry.setTopLeft(QPoint(tl.iX, tl.iY)); } diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 418ed7d..4bff5ac 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -444,6 +444,7 @@ static QVector<Atom> getNetWmState(QWidget *w) && actualType == XA_ATOM && actualFormat == 32) { returnValue.resize(bytesLeft / 4); XFree((char*) propertyData); + propertyData = 0; // fetch all data if (XGetWindowProperty(X11->display, w->internalWinId(), ATOM(_NET_WM_STATE), 0, @@ -458,7 +459,8 @@ static QVector<Atom> getNetWmState(QWidget *w) if (!returnValue.isEmpty()) { memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom)); } - XFree((char*) propertyData); + if (propertyData) + XFree((char*) propertyData); } return returnValue; @@ -1325,40 +1327,12 @@ QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const QPoint QWidget::mapToGlobal(const QPoint &pos) const { Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos + offset; - return d->mapToGlobal(pos); } QPoint QWidget::mapFromGlobal(const QPoint &pos) const { Q_D(const QWidget); - QPoint offset = data->crect.topLeft(); - const QWidget *w = this; - const QWidget *p = w->parentWidget(); - while (!w->isWindow() && p) { - w = p; - p = p->parentWidget(); - offset += w->data->crect.topLeft(); - } - - const QWidgetPrivate *wd = w->d_func(); - QTLWExtra *tlw = wd->topData(); - if (!tlw->embedded) - return pos - offset; - return d->mapFromGlobal(pos); } diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp index 47cefe4..49a8194 100644 --- a/src/gui/kernel/qx11embed_x11.cpp +++ b/src/gui/kernel/qx11embed_x11.cpp @@ -415,8 +415,9 @@ static Bool functor(Display *display, XEvent *event, XPointer arg) status = XGetWindowProperty(display, data->id, ATOM(WM_STATE), 0, 2, False, ATOM(WM_STATE), &ret, &format, &nitems, &after, &retval ); if (status == Success && ret == ATOM(WM_STATE) && format == 32 && nitems > 0) { - long *state = (long *)retval; - if (state[0] == WithdrawnState) { + long state = *(long *)retval; + XFree(retval); + if (state == WithdrawnState) { data->clearedWmState = true; return true; } @@ -833,6 +834,8 @@ bool QX11EmbedWidget::x11Event(XEvent *event) XUnmapWindow(x11Info().display(), internalWinId()); } } + if (prop_return) + XFree(prop_return); } } diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h index d9aef20..181eda8 100644 --- a/src/gui/math3d/qgenericmatrix.h +++ b/src/gui/math3d/qgenericmatrix.h @@ -79,9 +79,9 @@ public: void copyDataTo(T *values) const; - T *data() { return m[0]; } - const T *data() const { return m[0]; } - const T *constData() const { return m[0]; } + T *data() { return *m; } + const T *data() const { return *m; } + const T *constData() const { return *m; } #if !defined(Q_NO_TEMPLATE_FRIENDS) template<int NN, int MM, typename TT> diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index 706450a..ad05116 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -173,8 +173,8 @@ public: QGenericMatrix<N, M, qreal> toGenericMatrix() const; inline qreal *data(); - inline const qreal *data() const { return m[0]; } - inline const qreal *constData() const { return m[0]; } + inline const qreal *data() const { return *m; } + inline const qreal *constData() const { return *m; } void optimize(); @@ -974,7 +974,7 @@ inline qreal *QMatrix4x4::data() // We have to assume that the caller will modify the matrix elements, // so we flip it over to "General" mode. flagBits = General; - return m[0]; + return *m; } #ifndef QT_NO_DEBUG_STREAM diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp index 5741667..811f3ae 100644 --- a/src/gui/painting/qbrush.cpp +++ b/src/gui/painting/qbrush.cpp @@ -1217,14 +1217,14 @@ QDataStream &operator>>(QDataStream &s, QBrush &b) Each of the types is represented by a subclass of QGradient: \table - \row - \o \inlineimage qgradient-linear.png - \o \inlineimage qgradient-radial.png - \o \inlineimage qgradient-conical.png \header \o QLinearGradient \o QRadialGradient \o QConicalGradient + \row + \o \inlineimage qgradient-linear.png + \o \inlineimage qgradient-radial.png + \o \inlineimage qgradient-conical.png \endtable The colors in a gradient are defined using stop points of the diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp index 173fb71..73a6ed8 100644 --- a/src/gui/painting/qcolor.cpp +++ b/src/gui/painting/qcolor.cpp @@ -78,12 +78,12 @@ QT_BEGIN_NAMESPACE names. \table + \header + \o RGB \o HSV \o CMYK \row \o \inlineimage qcolor-rgb.png \o \inlineimage qcolor-hsv.png \o \inlineimage qcolor-cmyk.png - \header - \o RGB \o HSV \o CMYK \endtable The QColor constructor creates the color based on RGB values. To diff --git a/src/gui/painting/qdrawhelper_arm_simd.cpp b/src/gui/painting/qdrawhelper_arm_simd.cpp index 806df29..af9854c 100644 --- a/src/gui/painting/qdrawhelper_arm_simd.cpp +++ b/src/gui/painting/qdrawhelper_arm_simd.cpp @@ -201,8 +201,8 @@ argb32constalpha_next_pixel uxtb16 r10, r9 uxtb16 r6, r9, ror #8 - // Negate r11 and extract src alpha - mvn r9, r11 // bitwise not + // Negate r8 and extract src alpha + mvn r9, r8 // bitwise not uxtb r9, r9, ror #24 mla r10, r9, r10, r14 diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 47caa9f..5513010 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -662,19 +662,19 @@ QRasterPaintEngineState::QRasterPaintEngineState() QRasterPaintEngineState::QRasterPaintEngineState(QRasterPaintEngineState &s) : QPainterState(s) + , lastPen(s.lastPen) + , penData(s.penData) , stroker(s.stroker) + , strokeFlags(s.strokeFlags) , lastBrush(s.lastBrush) , brushData(s.brushData) - , lastPen(s.lastPen) - , penData(s.penData) , fillFlags(s.fillFlags) - , strokeFlags(s.strokeFlags) , pixmapFlags(s.pixmapFlags) , intOpacity(s.intOpacity) , txscale(s.txscale) - , flag_bits(s.flag_bits) , clip(s.clip) , dirty(s.dirty) + , flag_bits(s.flag_bits) { brushData.tempImage = 0; penData.tempImage = 0; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a5f4251..2c25e70 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -1126,14 +1126,14 @@ void QPainterPrivate::updateState(QPainterState *newState) the range of available patterns. \table - \row - \o \inlineimage qpainter-vectordeformation.png - \o \inlineimage qpainter-gradients.png - \o \inlineimage qpainter-pathstroking.png \header \o \l {demos/deform}{Vector Deformation} \o \l {demos/gradients}{Gradients} \o \l {demos/pathstroke}{Path Stroking} + \row + \o \inlineimage qpainter-vectordeformation.png + \o \inlineimage qpainter-gradients.png + \o \inlineimage qpainter-pathstroking.png \endtable @@ -1206,13 +1206,13 @@ void QPainterPrivate::updateState(QPainterState *newState) coordinate transformations. \table + \header + \o nop \o rotate() \o scale() \o translate() \row \o \inlineimage qpainter-clock.png \o \inlineimage qpainter-rotation.png \o \inlineimage qpainter-scale.png \o \inlineimage qpainter-translation.png - \header - \o nop \o rotate() \o scale() \o translate() \endtable The most commonly used transformations are scaling, rotation, diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp index 3d532d2..8bff021 100644 --- a/src/gui/painting/qpainterpath.cpp +++ b/src/gui/painting/qpainterpath.cpp @@ -240,12 +240,12 @@ static void qt_debug_path(const QPainterPath &path) provides two methods for filling paths: \table - \row - \o \inlineimage qt-fillrule-oddeven.png - \o \inlineimage qt-fillrule-winding.png \header \o Qt::OddEvenFill \o Qt::WindingFill + \row + \o \inlineimage qt-fillrule-oddeven.png + \o \inlineimage qt-fillrule-winding.png \endtable See the Qt::FillRule documentation for the definition of the @@ -315,12 +315,12 @@ static void qt_debug_path(const QPainterPath &path) QPainterPath to draw text. \table - \row - \o \inlineimage qpainterpath-example.png - \o \inlineimage qpainterpath-demo.png \header \o \l {painting/painterpaths}{Painter Paths Example} \o \l {demos/deform}{Vector Deformation Demo} + \row + \o \inlineimage qpainterpath-example.png + \o \inlineimage qpainterpath-demo.png \endtable \sa QPainterPathStroker, QPainter, QRegion, {Painter Paths Example} @@ -874,7 +874,7 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength); #endif - if (!qt_is_finite(rect.x()) && !qt_is_finite(rect.y()) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) + if ((!qt_is_finite(rect.x()) && !qt_is_finite(rect.y())) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height()) || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) { #ifndef QT_NO_DEBUG qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call"); @@ -1279,12 +1279,12 @@ Qt::FillRule QPainterPath::fillRule() const fillRule. Qt provides two methods for filling paths: \table - \row - \o \inlineimage qt-fillrule-oddeven.png - \o \inlineimage qt-fillrule-winding.png \header \o Qt::OddEvenFill (default) \o Qt::WindingFill + \row + \o \inlineimage qt-fillrule-oddeven.png + \o \inlineimage qt-fillrule-winding.png \endtable \sa fillRule() diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp index 843c9ff..419518ac 100644 --- a/src/gui/painting/qwindowsurface_raster.cpp +++ b/src/gui/painting/qwindowsurface_raster.cpp @@ -78,6 +78,9 @@ public: #ifdef Q_WS_X11 GC gc; +#ifndef QT_NO_MITSHM + uint needsSync : 1; +#endif #ifndef QT_NO_XRENDER uint translucentBackground : 1; #endif @@ -94,6 +97,9 @@ QRasterWindowSurface::QRasterWindowSurface(QWidget *window, bool setDefaultSurfa d_ptr->translucentBackground = X11->use_xrender && window->x11Info().depth() == 32; #endif +#ifndef QT_NO_MITHSM + d_ptr->needsSync = false; +#endif #endif d_ptr->image = 0; d_ptr->inSetGeometry = false; @@ -116,8 +122,23 @@ QPaintDevice *QRasterWindowSurface::paintDevice() return &d_ptr->image->image; } +#if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) +void QRasterWindowSurface::syncX() +{ + // delay writing to the backbuffer until we know for sure X is done reading from it + if (d_ptr->needsSync) { + XSync(X11->display, false); + d_ptr->needsSync = false; + } +} +#endif + void QRasterWindowSurface::beginPaint(const QRegion &rgn) { +#if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) + syncX(); +#endif + #if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE)) if (!qt_widget_private(window())->isOpaque && window()->testAttribute(Qt::WA_TranslucentBackground)) { #if defined(Q_WS_WIN) && !defined(Q_WS_WINCE) @@ -217,13 +238,13 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi if (d_ptr->image->xshmpm) { XCopyArea(X11->display, d_ptr->image->xshmpm, widget->handle(), d_ptr->gc, br.x(), br.y(), br.width(), br.height(), wbr.x(), wbr.y()); - XSync(X11->display, False); + d_ptr->needsSync = true; } else if (d_ptr->image->xshmimg) { const QImage &src = d->image->image; br = br.intersected(src.rect()); XShmPutImage(X11->display, widget->handle(), d_ptr->gc, d_ptr->image->xshmimg, br.x(), br.y(), wbr.x(), wbr.y(), br.width(), br.height(), False); - XSync(X11->display, False); + d_ptr->needsSync = true; } else #endif { @@ -392,6 +413,10 @@ bool QRasterWindowSurface::scroll(const QRegion &area, int dx, int dy) if (!d->image || d->image->image.isNull()) return false; +#if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) + syncX(); +#endif + const QVector<QRect> rects = area.rects(); for (int i = 0; i < rects.size(); ++i) qt_scrollRectInImage(d->image->image, rects.at(i), QPoint(dx, dy)); diff --git a/src/gui/painting/qwindowsurface_raster_p.h b/src/gui/painting/qwindowsurface_raster_p.h index b6e61e1..903810b 100644 --- a/src/gui/painting/qwindowsurface_raster_p.h +++ b/src/gui/painting/qwindowsurface_raster_p.h @@ -107,6 +107,9 @@ public: bool scroll(const QRegion &area, int dx, int dy); private: +#if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) + void syncX(); +#endif void prepareBuffer(QImage::Format format, QWidget *widget); Q_DECLARE_PRIVATE(QRasterWindowSurface) QScopedPointer<QRasterWindowSurfacePrivate> d_ptr; diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp index a860818..71556d7 100644 --- a/src/gui/painting/qwindowsurface_s60.cpp +++ b/src/gui/painting/qwindowsurface_s60.cpp @@ -61,13 +61,11 @@ struct QS60WindowSurfacePrivate QList<QImage*> bufferImages; }; -QS60WindowSurface::QS60WindowSurface(QWidget* widget) - : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) +TDisplayMode displayMode(bool opaque) { TDisplayMode mode = S60->screenDevice()->DisplayMode(); - bool isOpaque = qt_widget_private(widget)->isOpaque; - if (isOpaque) { + if (opaque) { mode = EColor16MU; } else { if (QSysInfo::symbianVersion() >= QSysInfo::SV_SF_3) @@ -75,7 +73,13 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget) else mode = EColor16MA; // Symbian prior to Symbian^3 sw accelerates EColor16MA } + return mode; +} +QS60WindowSurface::QS60WindowSurface(QWidget* widget) + : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate) +{ + TDisplayMode mode = displayMode(qt_widget_private(widget)->isOpaque); // We create empty CFbsBitmap here -> it will be resized in setGeometry CFbsBitmap *bitmap = new CFbsBitmap; // CBase derived object needs check on new Q_CHECK_PTR(bitmap); @@ -122,6 +126,11 @@ void QS60WindowSurface::beginPaint(const QRegion &rgn) if (!qt_widget_private(window())->isOpaque) { QS60PixmapData *pixmapData = static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data()); + + TDisplayMode mode = displayMode(false); + if (pixmapData->cfbsBitmap->DisplayMode() != mode) + pixmapData->convertToDisplayMode(mode); + pixmapData->beginDataAccess(); QPainter p(&pixmapData->image); diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index b5b8b81..0c99f80 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -49,6 +49,7 @@ #include <avkon.rsg> #endif #include <barsread.h> +#include <coeutils.h> #include <qconfig.h> #include "qs60mainappui.h" @@ -401,6 +402,16 @@ void QS60MainAppUi::HandleForegroundEventL(TBool aForeground) QS60MainAppUiBase::HandleForegroundEventL(aForeground); } +/*! + \internal +*/ +TBool QS60MainAppUi::ProcessCommandParametersL(TApaCommand /*aCommand*/, TFileName &/*aDocumentName*/, const TDesC8 &/*aTail*/) +{ + // bypass CEikAppUi::ProcessCommandParametersL(..) which modifies aDocumentName, preventing apparc document opening from working. + // The return value is effectively unused in Qt apps (see QS60MainDocument::OpenFileL) + return EFalse; +} + #ifndef Q_WS_S60 void QS60StubAknAppUi::HandleViewDeactivation(const TVwsViewId &, const TVwsViewId &) {} diff --git a/src/gui/s60framework/qs60mainappui.h b/src/gui/s60framework/qs60mainappui.h index ce3b5b0..bf118ff 100644 --- a/src/gui/s60framework/qs60mainappui.h +++ b/src/gui/s60framework/qs60mainappui.h @@ -131,6 +131,7 @@ public: virtual void HandleViewDeactivation(const TVwsViewId &aViewIdToBeDeactivated, const TVwsViewId &aNewlyActivatedViewId); virtual void PrepareToExit(); virtual void HandleTouchPaneSizeChange(); + virtual TBool ProcessCommandParametersL(TApaCommand aCommand, TFileName &aDocumentName, const TDesC8 &aTail); protected: virtual void HandleScreenDeviceChangedL(); diff --git a/src/gui/s60framework/qs60maindocument.cpp b/src/gui/s60framework/qs60maindocument.cpp index a8886ac..37bd55f 100644 --- a/src/gui/s60framework/qs60maindocument.cpp +++ b/src/gui/s60framework/qs60maindocument.cpp @@ -41,6 +41,9 @@ #include "qs60mainappui.h" #include "qs60maindocument.h" +#include "qcoreapplication.h" +#include "qevent.h" +#include "private/qcore_symbian_p.h" #include <exception> @@ -108,9 +111,15 @@ CEikAppUi *QS60MainDocument::CreateAppUiL() /*! \internal */ -CFileStore *QS60MainDocument::OpenFileL(TBool aDoOpen, const TDesC &aFilename, RFs &aFs) +CFileStore *QS60MainDocument::OpenFileL(TBool /*aDoOpen*/, const TDesC &aFilename, RFs &/*aFs*/) { - return QS60MainDocumentBase::OpenFileL(aDoOpen, aFilename, aFs); + QT_TRYCATCH_LEAVING( { + QCoreApplication* app = QCoreApplication::instance(); + QString qname = qt_TDesC2QString(aFilename); + QFileOpenEvent* event = new QFileOpenEvent(qname); + app->postEvent(app, event); + }) + return 0; } /*! @@ -118,7 +127,12 @@ CFileStore *QS60MainDocument::OpenFileL(TBool aDoOpen, const TDesC &aFilename, R */ void QS60MainDocument::OpenFileL(CFileStore *&aFileStore, RFile &aFile) { - QS60MainDocumentBase::OpenFileL(aFileStore, aFile); + QT_TRYCATCH_LEAVING( { + QCoreApplication* app = QCoreApplication::instance(); + QFileOpenEvent* event = new QFileOpenEvent(aFile); + app->postEvent(app, event); + aFileStore = 0; + }) } QT_END_NAMESPACE diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index 4b591e2..ecf924c 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -4238,7 +4238,7 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op return; case PE_Widget: - if (!rule.hasDrawable()) { + if (w && !rule.hasDrawable()) { QWidget *container = containerWidget(w); if (styleSheetCaches->autoFillDisabledWidgets.contains(container) && (container == w || !renderRule(container, opt).hasBackground())) { diff --git a/src/gui/text/qfont_s60.cpp b/src/gui/text/qfont_s60.cpp index c7d36ef..114191d 100644 --- a/src/gui/text/qfont_s60.cpp +++ b/src/gui/text/qfont_s60.cpp @@ -49,13 +49,14 @@ QT_BEGIN_NAMESPACE #ifdef QT_NO_FREETYPE Q_GLOBAL_STATIC(QMutex, lastResortFamilyMutex); +#endif // QT_NO_FREETYPE + extern QStringList qt_symbian_fontFamiliesOnFontServer(); // qfontdatabase_s60.cpp Q_GLOBAL_STATIC_WITH_INITIALIZER(QStringList, fontFamiliesOnFontServer, { // We are only interested in the initial font families. No Application fonts. // Therefore, we are allowed to cache the list. x->append(qt_symbian_fontFamiliesOnFontServer()); }); -#endif // QT_NO_FREETYPE QString QFont::lastResortFont() const { @@ -95,7 +96,20 @@ QString QFont::lastResortFamily() const const bool isJapaneseOrChineseSystem = User::Language() == ELangJapanese || User::Language() == ELangPrcChinese; - return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":"Series 60 Sans"); + static QString family; + if (family.isEmpty()) { + QStringList families = qt_symbian_fontFamiliesOnFontServer(); + const char* const preferredFamilies[] = {"Nokia Sans S60", "Series 60 Sans"}; + for (int i = 0; i < sizeof preferredFamilies / sizeof preferredFamilies[0]; ++i) { + const QString preferredFamily = QLatin1String(preferredFamilies[i]); + if (families.contains(preferredFamily)) { + family = preferredFamily; + break; + } + } + } + + return QLatin1String(isJapaneseOrChineseSystem?"Heisei Kaku Gothic S60":family.toLatin1()); #endif // QT_NO_FREETYPE } diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index 97426a8..6d3970e 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -464,6 +464,7 @@ void QFontEngineMultiS60::loadEngine(int at) Q_ASSERT(engines[at]); } +#ifdef QT_NO_FREETYPE static bool registerScreenDeviceFont(int screenDeviceFontIndex, const QSymbianFontDatabaseExtrasImplementation *dbExtras) { @@ -525,6 +526,7 @@ static bool registerScreenDeviceFont(int screenDeviceFontIndex, family->writingSystems[system] = QtFontFamily::Supported; return true; } +#endif static void initializeDb() { diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 89ca6bf..e15c06d 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -115,6 +115,7 @@ static QTextLine currentTextLine(const QTextCursor &cursor) QTextControlPrivate::QTextControlPrivate() : doc(0), cursorOn(false), cursorIsFocusIndicator(false), interactionFlags(Qt::TextEditorInteraction), + dragEnabled(true), #ifndef QT_NO_DRAGANDDROP mousePressed(false), mightStartDrag(false), #endif @@ -129,7 +130,8 @@ QTextControlPrivate::QTextControlPrivate() isEnabled(true), hadSelectionOnMousePress(false), ignoreUnusedNavigationEvents(false), - openExternalLinks(false) + openExternalLinks(false), + wordSelectionEnabled(false) {} bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) @@ -1544,15 +1546,21 @@ void QTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton button, con } #endif if (modifiers == Qt::ShiftModifier) { + if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { + selectedWordOnDoubleClick = cursor; + selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); + } + if (selectedBlockOnTrippleClick.hasSelection()) extendBlockwiseSelection(cursorPos); else if (selectedWordOnDoubleClick.hasSelection()) extendWordwiseSelection(cursorPos, pos.x()); - else + else if (wordSelectionEnabled) setCursorPosition(cursorPos, QTextCursor::KeepAnchor); } else { - if (cursor.hasSelection() + if (dragEnabled + && cursor.hasSelection() && !cursorIsFocusIndicator && cursorPos >= cursor.selectionStart() && cursorPos <= cursor.selectionEnd() @@ -1625,6 +1633,11 @@ void QTextControlPrivate::mouseMoveEvent(Qt::MouseButtons buttons, const QPointF if (newCursorPos == -1) return; + if (wordSelectionEnabled && !selectedWordOnDoubleClick.hasSelection()) { + selectedWordOnDoubleClick = cursor; + selectedWordOnDoubleClick.select(QTextCursor::WordUnderCursor); + } + if (selectedBlockOnTrippleClick.hasSelection()) extendBlockwiseSelection(newCursorPos); else if (selectedWordOnDoubleClick.hasSelection()) @@ -2331,6 +2344,31 @@ bool QTextControl::cursorIsFocusIndicator() const return d->cursorIsFocusIndicator; } + +void QTextControl::setDragEnabled(bool enabled) +{ + Q_D(QTextControl); + d->dragEnabled = enabled; +} + +bool QTextControl::isDragEnabled() const +{ + Q_D(const QTextControl); + return d->dragEnabled; +} + +void QTextControl::setWordSelectionEnabled(bool enabled) +{ + Q_D(QTextControl); + d->wordSelectionEnabled = enabled; +} + +bool QTextControl::isWordSelectionEnabled() const +{ + Q_D(const QTextControl); + return d->wordSelectionEnabled; +} + #ifndef QT_NO_PRINTER void QTextControl::print(QPrinter *printer) const { diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 6540f4f..31fa843 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -175,6 +175,12 @@ public: void setCursorIsFocusIndicator(bool b); bool cursorIsFocusIndicator() const; + void setDragEnabled(bool enabled); + bool isDragEnabled() const; + + bool isWordSelectionEnabled() const; + void setWordSelectionEnabled(bool enabled); + #ifndef QT_NO_PRINTER void print(QPrinter *printer) const; #endif @@ -183,8 +189,6 @@ public: virtual QRectF blockBoundingRect(const QTextBlock &block) const; QAbstractTextDocumentLayout::PaintContext getPaintContext(QWidget *widget) const; - - public Q_SLOTS: void setPlainText(const QString &text); void setHtml(const QString &text); diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index 04f4c75..ecd13ea 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -174,6 +174,8 @@ public: QBasicTimer trippleClickTimer; QPointF trippleClickPoint; + bool dragEnabled; + bool mousePressed; bool mightStartDrag; @@ -209,6 +211,8 @@ public: bool ignoreUnusedNavigationEvents; bool openExternalLinks; + bool wordSelectionEnabled; + QString linkToCopy; void _q_copyLink(); void _q_updateBlock(const QTextBlock &); diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index 157b7bc..838face 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -2510,6 +2510,7 @@ static inline void getLineHeightParams(const QTextBlockFormat &blockFormat, cons QFixed *lineAdjustment, QFixed *lineBreakHeight, QFixed *lineHeight) { *lineHeight = QFixed::fromReal(blockFormat.lineHeight(line.height(), scaling)); + if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight || blockFormat.lineHeightType() == QTextBlockFormat::MinimumHeight) { *lineBreakHeight = *lineHeight; if (blockFormat.lineHeightType() == QTextBlockFormat::FixedHeight) diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index daafdd9..d3e8f2d 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -147,8 +147,8 @@ symbian { text/qfontengine_s60.cpp HEADERS += \ text/qfontengine_s60_p.h - LIBS += -lfntstr -lecom } + LIBS += -lfntstr -lecom } !qpa { diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 7946137..b5dda5a 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -2486,10 +2486,18 @@ void QComboBox::showPopup() listRect.setWidth(listRect.height()); //by default popup is centered on screen in landscape listRect.moveCenter(screen.center()); - if (staConTopRect.IsEmpty() && AknLayoutUtils::CbaLocation() != AknLayoutUtils::EAknCbaLocationBottom) { - // landscape without stacon, menu should be at the right - (opt.direction == Qt::LeftToRight) ? listRect.setRight(screen.right()) : - listRect.setLeft(screen.left()); + if (staConTopRect.IsEmpty()) { + TRect cbaRect = TRect(); + AknLayoutUtils::LayoutMetricsRect(AknLayoutUtils::EControlPane, cbaRect); + AknLayoutUtils::TAknCbaLocation cbaLocation = AknLayoutUtils::CbaLocation(); + switch (cbaLocation) { + case AknLayoutUtils::EAknCbaLocationRight: + listRect.setRight(screen.right()); + break; + case AknLayoutUtils::EAknCbaLocationLeft: + listRect.setLeft(screen.left()); + break; + } } } #endif diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 062bb61..4b95000 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -541,10 +541,13 @@ void QLineControl::draw(QPainter *painter, const QPoint &offset, const QRect &cl */ void QLineControl::selectWordAtPos(int cursor) { - int c = m_textLayout.previousCursorPosition(cursor, QTextLayout::SkipWords); + int next = cursor + 1; + if(next > end()) + --next; + int c = m_textLayout.previousCursorPosition(next, QTextLayout::SkipWords); moveCursor(c, false); // ## text layout should support end of words. - int end = m_textLayout.nextCursorPosition(cursor, QTextLayout::SkipWords); + int end = m_textLayout.nextCursorPosition(c, QTextLayout::SkipWords); while (end > cursor && m_text[end-1].isSpace()) --end; moveCursor(end, true); diff --git a/src/gui/widgets/qscrollbar.cpp b/src/gui/widgets/qscrollbar.cpp index 67f34eb..c895b1b 100644 --- a/src/gui/widgets/qscrollbar.cpp +++ b/src/gui/widgets/qscrollbar.cpp @@ -82,21 +82,21 @@ QT_BEGIN_NAMESPACE needs. \table - \row \i \image qscrollbar-picture.png - \i Scroll bars typically include four separate controls: a slider, + \row \o \image qscrollbar-picture.png + \o Scroll bars typically include four separate controls: a slider, scroll arrows, and a page control. \list - \i a. The slider provides a way to quickly go to any part of the + \o a. The slider provides a way to quickly go to any part of the document, but does not support accurate navigation within large documents. - \i b. The scroll arrows are push buttons which can be used to accurately + \o b. The scroll arrows are push buttons which can be used to accurately navigate to a particular place in a document. For a vertical scroll bar connected to a text editor, these typically move the current position one "line" up or down, and adjust the position of the slider by a small amount. In editors and list boxes a "line" might mean one line of text; in an image viewer it might mean 20 pixels. - \i c. The page control is the area over which the slider is dragged (the + \o c. The page control is the area over which the slider is dragged (the scroll bar's background). Clicking here moves the scroll bar towards the click by one "page". This value is usually the same as the length of the slider. @@ -134,13 +134,12 @@ QT_BEGIN_NAMESPACE value of 80. This would give us a scroll bar with five "pages". \table - \row \i \inlineimage qscrollbar-values.png - \i The relationship between a document length, the range of values used + \row \o \inlineimage qscrollbar-values.png + \o The relationship between a document length, the range of values used in a scroll bar, and the page step is simple in many common situations. The scroll bar's range of values is determined by subtracting a chosen page step from some value representing the length of the document. In such cases, the following equation is useful: - \e{document length} = maximum() - minimum() + pageStep(). \endtable @@ -153,18 +152,18 @@ QT_BEGIN_NAMESPACE ScrollBar inherits a comprehensive set of signals from QAbstractSlider: \list - \i \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the + \o \l{QAbstractSlider::valueChanged()}{valueChanged()} is emitted when the scroll bar's value has changed. The tracking() determines whether this signal is emitted during user interaction. - \i \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the + \o \l{QAbstractSlider::rangeChanged()}{rangeChanged()} is emitted when the scroll bar's range of values has changed. - \i \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when + \o \l{QAbstractSlider::sliderPressed()}{sliderPressed()} is emitted when the user starts to drag the slider. - \i \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user + \o \l{QAbstractSlider::sliderMoved()}{sliderMoved()} is emitted when the user drags the slider. - \i \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when + \o \l{QAbstractSlider::sliderReleased()}{sliderReleased()} is emitted when the user releases the slider. - \i \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted + \o \l{QAbstractSlider::actionTriggered()}{actionTriggered()} is emitted when the scroll bar is changed by user interaction or via the \l{QAbstractSlider::triggerAction()}{triggerAction()} function. \endlist @@ -173,12 +172,12 @@ QT_BEGIN_NAMESPACE default focusPolicy() of Qt::NoFocus. Use setFocusPolicy() to enable keyboard interaction with the scroll bar: \list - \i Left/Right move a horizontal scroll bar by one single step. - \i Up/Down move a vertical scroll bar by one single step. - \i PageUp moves up one page. - \i PageDown moves down one page. - \i Home moves to the start (mininum). - \i End moves to the end (maximum). + \o Left/Right move a horizontal scroll bar by one single step. + \o Up/Down move a vertical scroll bar by one single step. + \o PageUp moves up one page. + \o PageDown moves down one page. + \o Home moves to the start (mininum). + \o End moves to the end (maximum). \endlist The slider itself can be controlled by using the diff --git a/src/imports/gestures/qdeclarativegesturearea.cpp b/src/imports/gestures/qdeclarativegesturearea.cpp index ba3adc5..1b6e723 100644 --- a/src/imports/gestures/qdeclarativegesturearea.cpp +++ b/src/imports/gestures/qdeclarativegesturearea.cpp @@ -86,22 +86,22 @@ public: A GestureArea is like a MouseArea, but it has signals for gesture events. - \e {Elements in the Qt.labs module are not guaranteed to remain compatible - in future versions.} + \warning Elements in the Qt.labs module are not guaranteed to remain compatible + in future versions. - \e {This element is only functional on devices with touch input.} + \note This element is only functional on devices with touch input. \qml import Qt.labs.gestures 1.0 GestureArea { anchors.fill: parent - onPan: ... gesture.acceleration ... - onPinch: ... gesture.rotationAngle ... - onSwipe: ... - onTapAndHold: ... - onTap: ... - onGesture: ... + // onPan: ... gesture.acceleration ... + // onPinch: ... gesture.rotationAngle ... + // onSwipe: ... + // onTapAndHold: ... + // onTap: ... + // onGesture: ... } \endqml diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp index ea7cd9f..5db7099 100644 --- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp +++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp @@ -436,8 +436,8 @@ void QAudioOutputPrivate::writePaddingData() unsigned char *ptr = const_cast<unsigned char*>(outputBuffer.Ptr()); Mem::FillZ(ptr, paddingBytes); outputBuffer.SetLength(outputBuffer.Length() + paddingBytes); + Q_ASSERT(m_bytesPadding >= paddingBytes); m_bytesPadding -= paddingBytes; - Q_ASSERT(m_bytesPadding >= 0); if (m_pullMode && m_source->atEnd()) lastBufferFilled(); diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index bad010f..e34e6bb 100644 --- a/src/network/access/qnetworkaccessftpbackend.cpp +++ b/src/network/access/qnetworkaccessftpbackend.cpp @@ -307,8 +307,10 @@ void QNetworkAccessFtpBackend::ftpDone() // logged in successfully, send the stat requests (if supported) QString command = url().path(); command.prepend(QLatin1String("%1 ")); - if (supportsSize) + if (supportsSize) { + ftp->rawCommand(QLatin1String("TYPE I")); sizeId = ftp->rawCommand(command.arg(QLatin1String("SIZE"))); // get size + } if (supportsMdtm) mdtmId = ftp->rawCommand(command.arg(QLatin1String("MDTM"))); // get modified time if (!supportsSize && !supportsMdtm) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index ca8ea0e..7e75045 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1139,10 +1139,11 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co networkSession = QSharedNetworkSessionManager::getSession(config); - QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); - QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection); + //QueuedConnection is used to avoid deleting the networkSession inside its closed signal + QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection); QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), - q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); + q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); _q_networkSessionStateChanged(networkSession->state()); } diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 1f481cd..485f449 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -115,7 +115,7 @@ void QNetworkReplyImplPrivate::_q_startOperation() } #endif - if (backend->isSynchronous()) { + if (backend && backend->isSynchronous()) { state = Finished; q_func()->setFinished(true); } else { @@ -360,7 +360,7 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } #else - if (backend->isSynchronous()) + if (backend && backend->isSynchronous()) _q_startOperation(); else QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index 9927f29..2a46229 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -57,16 +57,17 @@ QT_BEGIN_NAMESPACE { \ delete this_##NAME.pointer; \ this_##NAME.pointer = 0; \ - this_##NAME.destroyed = true; \ } \ static TYPE *NAME() \ { \ - if (!this_##NAME.pointer && !this_##NAME.destroyed) { \ + if (!this_##NAME.pointer) { \ TYPE *x = new TYPE; \ if (!this_##NAME.pointer.testAndSetOrdered(0, x)) \ delete x; \ - else \ + else { \ qAddPostRoutine(NAME##_cleanup); \ + this_##NAME.pointer->updateConfigurations(); \ + } \ } \ return this_##NAME.pointer; \ } @@ -75,15 +76,7 @@ Q_GLOBAL_STATIC_QAPP_DESTRUCTION(QNetworkConfigurationManagerPrivate, connManage QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate() { - static bool initialized = false; - - QNetworkConfigurationManagerPrivate *m = connManager(); - if (!initialized) { - initialized = true; - m->updateConfigurations(); - } - - return m; + return connManager(); } /*! diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp index 143d9b5..af60a43 100644 --- a/src/network/bearer/qnetworksession.cpp +++ b/src/network/bearer/qnetworksession.cpp @@ -250,6 +250,9 @@ QNetworkSession::QNetworkSession(const QNetworkConfiguration &connectionConfig, } } } + + qRegisterMetaType<QNetworkSession::State>(); + qRegisterMetaType<QNetworkSession::SessionError>(); } /*! @@ -677,7 +680,7 @@ void QNetworkSession::connectNotify(const char *signal) //check for preferredConfigurationChanged() signal connect notification //This is not required on all platforms - if (QLatin1String(signal) == SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) + if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0) d->setALREnabled(true); } @@ -698,7 +701,7 @@ void QNetworkSession::disconnectNotify(const char *signal) //check for preferredConfigurationChanged() signal disconnect notification //This is not required on all platforms - if (QLatin1String(signal) == SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) + if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0) d->setALREnabled(false); } diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h index a4baec3..59d048a 100644 --- a/src/network/bearer/qnetworksession.h +++ b/src/network/bearer/qnetworksession.h @@ -146,6 +146,9 @@ QT_END_NAMESPACE QTM_END_NAMESPACE #endif +Q_DECLARE_METATYPE(QNetworkSession::State) +Q_DECLARE_METATYPE(QNetworkSession::SessionError) + QT_END_HEADER #endif // QT_NO_BEARERMANAGEMENT diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 2e21fbd..bbb75bc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1503,7 +1503,7 @@ namespace { { public: QOpenGLStaticTextUserData() - : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0) + : QStaticTextUserData(OpenGLUserData), cacheSize(0, 0), cacheSerialNumber(0) { } @@ -1515,6 +1515,7 @@ namespace { QGL2PEXVertexArray vertexCoordinateArray; QGL2PEXVertexArray textureCoordinateArray; QFontEngineGlyphCache::Type glyphType; + int cacheSerialNumber; }; } @@ -1538,8 +1539,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp staticTextItem->fontEngine()->setGlyphCache(cacheKey, cache); cache->insert(ctx, cache); recreateVertexArrays = true; - } else if (cache->context() == 0) { // Old context has been destroyed, new context has same ptr value - cache->setContext(ctx); } if (staticTextItem->userDataNeedsUpdate) { @@ -1550,8 +1549,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp recreateVertexArrays = true; } else { QOpenGLStaticTextUserData *userData = static_cast<QOpenGLStaticTextUserData *>(staticTextItem->userData()); - if (userData->glyphType != glyphType) + if (userData->glyphType != glyphType) { recreateVertexArrays = true; + } else if (userData->cacheSerialNumber != cache->serialNumber()) { + recreateVertexArrays = true; + } } // We only need to update the cache with new glyphs if we are actually going to recreate the vertex arrays. @@ -1592,6 +1594,7 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp } userData->glyphType = glyphType; + userData->cacheSerialNumber = cache->serialNumber(); // Use cache if backend optimizations is turned on vertexCoordinates = &userData->vertexCoordinateArray; diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp index eb38947..4362c0a 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp @@ -53,12 +53,15 @@ QT_BEGIN_NAMESPACE extern Q_GUI_EXPORT bool qt_cleartype_enabled; #endif +QBasicAtomicInt qgltextureglyphcache_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1); + QGLTextureGlyphCache::QGLTextureGlyphCache(const QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix) : QImageTextureGlyphCache(type, matrix), QGLContextGroupResourceBase() , ctx(0) , pex(0) , m_blitProgram(0) , m_filterMode(Nearest) + , m_serialNumber(qgltextureglyphcache_serial_number.fetchAndAddRelaxed(1)) { #ifdef QT_GL_TEXTURE_GLYPH_CACHE_DEBUG qDebug(" -> QGLTextureGlyphCache() %p for context %p.", this, ctx); diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h index c5c8985..cc6de28 100644 --- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h +++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl_p.h @@ -133,6 +133,8 @@ public: void setContext(const QGLContext *context); inline const QGLContext *context() const { return ctx; } + inline int serialNumber() const { return m_serialNumber; } + enum FilterMode { Nearest, Linear @@ -152,6 +154,8 @@ private: GLfloat m_vertexCoordinateArray[8]; GLfloat m_textureCoordinateArray[8]; + + int m_serialNumber; }; QT_END_NAMESPACE diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index 8b587cf..08ae774 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -163,6 +163,13 @@ symbian { HEADERS += qgl_egl_p.h + contains(QT_CONFIG, freetype) { + DEFINES += QT_NO_FONTCONFIG + INCLUDEPATH += \ + ../3rdparty/freetype/src \ + ../3rdparty/freetype/include + } + symbian:TARGET.UID3 = 0x2002131A } diff --git a/src/opengl/qgl_symbian.cpp b/src/opengl/qgl_symbian.cpp index 82b66f5..a9e2248 100644 --- a/src/opengl/qgl_symbian.cpp +++ b/src/opengl/qgl_symbian.cpp @@ -44,12 +44,14 @@ #include <coemain.h> #include <coecntrl.h> #include <w32std.h> +#include <private/qt_s60_p.h> #include <private/qpixmap_s60_p.h> #include <private/qimagepixmapcleanuphooks_p.h> #include <private/qgl_p.h> #include <private/qpaintengine_opengl_p.h> #include <private/qwidget_p.h> // to access QWExtra #include "qgl_egl_p.h" +#include "qpixmapdata_gl_p.h" #include "qcolormap.h" #include <QDebug> @@ -358,5 +360,117 @@ void QGLWidgetPrivate::recreateEglSurface() eglSurfaceWindowId = currentId; } +/* + * Symbian specific QGLPixmapData functions + */ + +static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) +{ + CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); + if (!copy) + return 0; + + if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) { + delete copy; + copy = 0; + + return 0; + } + + CFbsBitmapDevice* bitmapDevice = 0; + CFbsBitGc *bitmapGc = 0; + QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy)); + QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); + bitmapGc->Activate(bitmapDevice); + + bitmapGc->BitBlt(TPoint(), bitmap); + + delete bitmapGc; + delete bitmapDevice; + + return copy; +} + +void QGLPixmapData::fromNativeType(void* pixmap, NativeType type) +{ + if (type == QPixmapData::FbsBitmap) { + CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); + + bool deleteSourceBitmap = false; +#ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE + + // Rasterize extended bitmaps + + TUid extendedBitmapType = bitmap->ExtendedBitmapType(); + if (extendedBitmapType != KNullUid) { + bitmap = createBlitCopy(bitmap); + deleteSourceBitmap = true; + } +#endif + + if (bitmap->IsCompressedInRAM()) { + bitmap = createBlitCopy(bitmap); + deleteSourceBitmap = true; + } + + TDisplayMode displayMode = bitmap->DisplayMode(); + QImage::Format format = qt_TDisplayMode2Format(displayMode); + + TSize size = bitmap->SizeInPixels(); + int bytesPerLine = bitmap->ScanLineLength(size.iWidth, displayMode); + + bitmap->BeginDataAccess(); + uchar *bytes = (uchar*)bitmap->DataAddress(); + QImage img = QImage(bytes, size.iWidth, size.iHeight, bytesPerLine, format); + img = img.copy(); + bitmap->EndDataAccess(); + + if (displayMode == EGray2) { + //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid + //So invert mono bitmaps so that masks work correctly. + img.invertPixels(); + } else if (displayMode == EColor16M) { + img = img.rgbSwapped(); // EColor16M is BGR + } + + fromImage(img, Qt::AutoColor); + + if (deleteSourceBitmap) + delete bitmap; + } +} + +void* QGLPixmapData::toNativeType(NativeType type) +{ + if (type == QPixmapData::FbsBitmap) { + CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); + + if (bitmap) { + QImage image = toImage(); + + TDisplayMode displayMode(EColor16MU); + if (image.format()==QImage::Format_ARGB32_Premultiplied) + displayMode = EColor16MAP; + + if (bitmap->Create(TSize(image.width(), image.height()), + displayMode) == KErrNone) { + const uchar *sptr = const_cast<const QImage&>(image).bits(); + bitmap->BeginDataAccess(); + + uchar *dptr = (uchar*)bitmap->DataAddress(); + Mem::Copy(dptr, sptr, image.byteCount()); + + bitmap->EndDataAccess(); + } else { + delete bitmap; + bitmap = 0; + } + } + + return reinterpret_cast<void*>(bitmap); + } + return 0; +} + QT_END_NAMESPACE diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp index 7f41339..4598bff 100644 --- a/src/opengl/qglshaderprogram.cpp +++ b/src/opengl/qglshaderprogram.cpp @@ -261,14 +261,14 @@ bool QGLShaderPrivate::compile(QGLShader *q) log = QString::fromLatin1(logbuf); QString name = q->objectName(); - char *types[] = { + const char *types[] = { "Fragment", "Vertex", "Geometry", "" }; - char *type = types[3]; + const char *type = types[3]; if (shaderType == QGLShader::Fragment) type = types[0]; else if (shaderType == QGLShader::Vertex) diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index d12704d..04de1bd 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -55,6 +55,7 @@ #include <qdesktopwidget.h> #include <qfile.h> #include <qimagereader.h> +#include <qbuffer.h> QT_BEGIN_NAMESPACE @@ -369,40 +370,18 @@ void QGLPixmapData::ensureCreated() const void QGLPixmapData::fromImage(const QImage &image, Qt::ImageConversionFlags flags) { - if (image.size() == QSize(w, h)) - setSerialNumber(++qt_gl_pixmap_serial); - resize(image.width(), image.height()); - - if (pixelType() == BitmapType) { - m_source = image.convertToFormat(QImage::Format_MonoLSB); - - } else { - QImage::Format format = QImage::Format_RGB32; - if (qApp->desktop()->depth() == 16) - format = QImage::Format_RGB16; - - if (image.hasAlphaChannel() - && ((flags & Qt::NoOpaqueDetection) - || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) - format = QImage::Format_ARGB32_Premultiplied;; - - m_source = image.convertToFormat(format); - } - - m_dirty = true; - m_hasFillColor = false; + QImage img = image; + createPixmapForImage(img, flags, false); +} - m_hasAlpha = m_source.hasAlphaChannel(); - w = image.width(); - h = image.height(); - is_null = (w <= 0 || h <= 0); - d = m_source.depth(); +void QGLPixmapData::fromImageReader(QImageReader *imageReader, + Qt::ImageConversionFlags flags) +{ + QImage image = imageReader->read(); + if (image.isNull()) + return; - if (m_texture.id) { - QGLShareContextScope ctx(qt_gl_share_context()); - glDeleteTextures(1, &m_texture.id); - m_texture.id = 0; - } + createPixmapForImage(image, flags, true); } bool QGLPixmapData::fromFile(const QString &filename, const char *format, @@ -411,31 +390,37 @@ bool QGLPixmapData::fromFile(const QString &filename, const char *format, if (pixelType() == QPixmapData::BitmapType) return QPixmapData::fromFile(filename, format, flags); QFile file(filename); - if (!file.open(QIODevice::ReadOnly)) - return false; - QByteArray data = file.peek(64); - bool alpha; - if (m_texture.canBindCompressedTexture - (data.constData(), data.size(), format, &alpha)) { - resize(0, 0); - data = file.readAll(); - file.close(); - QGLShareContextScope ctx(qt_gl_share_context()); - QSize size = m_texture.bindCompressedTexture - (data.constData(), data.size(), format); - if (!size.isEmpty()) { - w = size.width(); - h = size.height(); - is_null = false; - d = 32; - m_hasAlpha = alpha; - m_source = QImage(); - m_dirty = isValid(); - return true; + if (file.open(QIODevice::ReadOnly)) { + QByteArray data = file.peek(64); + bool alpha; + if (m_texture.canBindCompressedTexture + (data.constData(), data.size(), format, &alpha)) { + resize(0, 0); + data = file.readAll(); + file.close(); + QGLShareContextScope ctx(qt_gl_share_context()); + QSize size = m_texture.bindCompressedTexture + (data.constData(), data.size(), format); + if (!size.isEmpty()) { + w = size.width(); + h = size.height(); + is_null = false; + d = 32; + m_hasAlpha = alpha; + m_source = QImage(); + m_dirty = isValid(); + return true; + } + return false; } - return false; } - fromImage(QImageReader(&file, format).read(), flags); + + QImage image = QImageReader(filename, format).read(); + if (image.isNull()) + return false; + + createPixmapForImage(image, flags, true); + return !isNull(); } @@ -459,7 +444,67 @@ bool QGLPixmapData::fromData(const uchar *buffer, uint len, const char *format, return true; } } - return QPixmapData::fromData(buffer, len, format, flags); + + QByteArray a = QByteArray::fromRawData(reinterpret_cast<const char *>(buffer), len); + QBuffer b(&a); + b.open(QIODevice::ReadOnly); + QImage image = QImageReader(&b, format).read(); + if (image.isNull()) + return false; + + createPixmapForImage(image, flags, true); + + return !isNull(); +} + +/*! + out-of-place conversion (inPlace == false) will always detach() + */ +void QGLPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) +{ + if (image.size() == QSize(w, h)) + setSerialNumber(++qt_gl_pixmap_serial); + + resize(image.width(), image.height()); + + if (pixelType() == BitmapType) { + m_source = image.convertToFormat(QImage::Format_MonoLSB); + + } else { + QImage::Format format = QImage::Format_RGB32; + if (qApp->desktop()->depth() == 16) + format = QImage::Format_RGB16; + + if (image.hasAlphaChannel() + && ((flags & Qt::NoOpaqueDetection) + || const_cast<QImage &>(image).data_ptr()->checkForAlphaPixels())) + format = QImage::Format_ARGB32_Premultiplied;; + + if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { + m_source = image; + } else { + m_source = image.convertToFormat(format); + + // convertToFormat won't detach the image if format stays the same. + if (image.format() == format) + m_source.detach(); + } + } + + m_dirty = true; + m_hasFillColor = false; + + m_hasAlpha = m_source.hasAlphaChannel(); + w = image.width(); + h = image.height(); + is_null = (w <= 0 || h <= 0); + d = m_source.depth(); + + if (m_texture.id) { + QGLShareContextScope ctx(qt_gl_share_context()); + glDeleteTextures(1, &m_texture.id); + m_texture.id = 0; + } } bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect) @@ -586,6 +631,12 @@ QImage QGLPixmapData::toImage() const if (m_renderFbo) { copyBackFromRenderFbo(true); } else if (!m_source.isNull()) { + QImageData *data = const_cast<QImage &>(m_source).data_ptr(); + if (data->paintEngine && data->paintEngine->isActive() + && data->paintEngine->paintDevice() == &m_source) + { + return m_source.copy(); + } return m_source; } else if (m_dirty || m_hasFillColor) { return fillImage(m_fillColor); diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h index 5545d3c..a4066fd 100644 --- a/src/opengl/qpixmapdata_gl_p.h +++ b/src/opengl/qpixmapdata_gl_p.h @@ -107,6 +107,8 @@ public: // Re-implemented from QPixmapData: void resize(int width, int height); void fromImage(const QImage &image, Qt::ImageConversionFlags flags); + void fromImageReader(QImageReader *imageReader, + Qt::ImageConversionFlags flags); bool fromFile(const QString &filename, const char *format, Qt::ImageConversionFlags flags); bool fromData(const uchar *buffer, uint len, const char *format, @@ -127,6 +129,11 @@ public: GLuint bind(bool copyBack = true) const; QGLTexture *texture() const; +#if defined(Q_OS_SYMBIAN) + void* toNativeType(NativeType type); + void fromNativeType(void* pixmap, NativeType type); +#endif + private: bool isValid() const; @@ -149,6 +156,8 @@ private: QImage fillImage(const QColor &color) const; + void createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace); + mutable QGLFramebufferObject *m_renderFbo; mutable QPaintEngine *m_engine; mutable QGLContext *m_ctx; diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index 5a783ca..cdd3eb9 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -363,7 +363,6 @@ QGLWindowSurface::~QGLWindowSurface() *ctx = 0; } #endif - delete d_ptr->pb; delete d_ptr->fbo; delete d_ptr; @@ -812,20 +811,25 @@ void QGLWindowSurface::updateGeometry() { return; d_ptr->geometry_updated = false; -#ifdef Q_WS_QPA - QSize surfSize = size(); -#else - QSize surfSize = geometry().size(); -#endif + bool hijack(true); + QWidgetPrivate *wd = window()->d_func(); + if (wd->extraData() && wd->extraData()->glContext) + hijack = false; // we already have gl context for widget - hijackWindow(window()); - QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); + if (hijack) + hijackWindow(window()); + + QGLContext *ctx = reinterpret_cast<QGLContext *>(wd->extraData()->glContext); #ifdef Q_WS_MAC ctx->updatePaintDevice(); #endif - const GLenum target = GL_TEXTURE_2D; +#ifdef Q_WS_QPA + QSize surfSize = size(); +#else + QSize surfSize = geometry().size(); +#endif if (surfSize.width() <= 0 || surfSize.height() <= 0) return; @@ -835,6 +839,27 @@ void QGLWindowSurface::updateGeometry() { d_ptr->size = surfSize; +#ifdef Q_OS_SYMBIAN + if (!hijack) { // Symbian needs to recreate EGL surface when native window size changes + if (ctx->d_func()->eglSurface != EGL_NO_SURFACE) { + eglDestroySurface(ctx->d_func()->eglContext->display(), + ctx->d_func()->eglSurface); + } + + ctx->d_func()->eglSurface = QEgl::createSurface(ctx->device(), + ctx->d_func()->eglContext->config()); + +#if !defined(QGL_NO_PRESERVED_SWAP) + eglGetError(); // Clear error state first. + eglSurfaceAttrib(QEgl::display(), ctx->d_func()->eglSurface, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + if (eglGetError() != EGL_SUCCESS) { + qWarning("QGLWindowSurface: could not restore preserved swap behaviour"); + } +#endif + } +#endif + if (d_ptr->ctx) { #ifndef QT_OPENGL_ES_2 if (d_ptr->destructive_swap_buffers) @@ -843,6 +868,7 @@ void QGLWindowSurface::updateGeometry() { return; } + const GLenum target = GL_TEXTURE_2D; if (d_ptr->destructive_swap_buffers && (QGLExtensions::glExtensions() & QGLExtensions::FramebufferObject) && (d_ptr->fbo || !d_ptr->tried_fbo) diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro index e7ed890..e185949 100644 --- a/src/openvg/openvg.pro +++ b/src/openvg/openvg.pro @@ -38,6 +38,13 @@ symbian { DEFINES += QVG_RECREATE_ON_SIZE_CHANGE QVG_BUFFER_SCROLLING QVG_SCISSOR_CLIP SOURCES += \ qvg_symbian.cpp + + contains(QT_CONFIG, freetype) { + DEFINES += QT_NO_FONTCONFIG + INCLUDEPATH += \ + ../3rdparty/freetype/src \ + ../3rdparty/freetype/include + } } include(../qbase.pri) diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index a15f0c3..22cbbf5 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -2201,6 +2201,12 @@ void QVGPaintEngine::updateScissor() #if defined(QVG_SCISSOR_CLIP) // Using the scissor to do clipping, so combine the systemClip // with the current painting clipRegion. + + if (d->maskValid) { + vgSeti(VG_MASKING, VG_FALSE); + d->maskValid = false; + } + QVGPainterState *s = state(); if (s->clipEnabled) { if (region.isEmpty()) @@ -2250,8 +2256,33 @@ void QVGPaintEngine::updateScissor() QVector<QRect> rects = region.rects(); int count = rects.count(); - if (count > d->maxScissorRects) - count = d->maxScissorRects; + if (count > d->maxScissorRects) { +#if !defined(QVG_SCISSOR_CLIP) + count = d->maxScissorRects; +#else + // Use masking + int width = paintDevice()->width(); + int height = paintDevice()->height(); + vgMask(VG_INVALID_HANDLE, VG_CLEAR_MASK, + 0, 0, width, height); + for (int i = 0; i < rects.size(); ++i) { + vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, + rects[i].x(), height - rects[i].y() - rects[i].height(), + rects[i].width(), rects[i].height()); + } + + vgSeti(VG_SCISSORING, VG_FALSE); + vgSeti(VG_MASKING, VG_TRUE); + d->maskValid = true; + d->maskIsSet = false; + d->scissorMask = false; + d->scissorActive = false; + d->scissorDirty = false; + d->scissorRegion = region; + return; +#endif + } + QVarLengthArray<VGint> params(count * 4); int height = paintDevice()->height(); for (int i = 0; i < count; ++i) { diff --git a/src/openvg/qvg_symbian.cpp b/src/openvg/qvg_symbian.cpp index b813800..ff0ab13 100644 --- a/src/openvg/qvg_symbian.cpp +++ b/src/openvg/qvg_symbian.cpp @@ -148,7 +148,7 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) destroyImages(); prevSize = QSize(); - VGImage vgImage = sgImageToVGImage(context, *sgImage); + vgImage = sgImageToVGImage(context, *sgImage); if (vgImage != VG_INVALID_HANDLE) { w = vgGetParameteri(vgImage, VG_IMAGE_WIDTH); h = vgGetParameteri(vgImage, VG_IMAGE_HEIGHT); diff --git a/src/openvg/qwindowsurface_vgegl.cpp b/src/openvg/qwindowsurface_vgegl.cpp index c6db869..ca80886 100644 --- a/src/openvg/qwindowsurface_vgegl.cpp +++ b/src/openvg/qwindowsurface_vgegl.cpp @@ -267,10 +267,7 @@ static QEglContext *createContext(QPaintDevice *device) int redSize = configProps.value(EGL_RED_SIZE); if (redSize == EGL_DONT_CARE || redSize == 0) configProps.setPixelFormat(QImage::Format_ARGB32); // XXX -#ifndef QVG_SCISSOR_CLIP - // If we are using the mask to clip, then explicitly request a mask. configProps.setValue(EGL_ALPHA_MASK_SIZE, 1); -#endif #ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT configProps.setValue(EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT); diff --git a/src/plugins/bearer/icd/dbusdispatcher.cpp b/src/plugins/bearer/icd/dbusdispatcher.cpp index 5fc2a38..13cd8a9 100644 --- a/src/plugins/bearer/icd/dbusdispatcher.cpp +++ b/src/plugins/bearer/icd/dbusdispatcher.cpp @@ -51,10 +51,10 @@ namespace Maemo { /*! - \class DBusDispatcher + \class Maemo::DBusDispatcher - \brief DBusDispatcher is a class, which is able to send DBUS method call - messages and receive unicast signals from DBUS object. + \brief DBusDispatcher is a class that can send DBUS method call + messages and receive unicast signals from DBUS objects. */ class DBusDispatcherPrivate @@ -468,7 +468,7 @@ void DBusDispatcher::setupDBus() d_ptr->signal_vtable.message_function = signalHandler; dbus_connection_set_exit_on_disconnect(d_ptr->connection, FALSE); - dbus_connection_setup_with_g_main(d_ptr->connection, NULL); + dbus_connection_setup_with_g_main(d_ptr->connection, g_main_context_get_thread_default()); dbus_connection_register_object_path(d_ptr->connection, d_ptr->signalPath.toLatin1(), &d_ptr->signal_vtable, diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp index 6d578d3..af5d85e 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.cpp +++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp @@ -125,9 +125,6 @@ static QString get_network_interface(); void QNetworkSessionPrivateImpl::iapStateChanged(const QString& iapid, uint icd_connection_state) { - if ((publicConfig.type() == QNetworkConfiguration::UserChoice) && opened) { - updateIdentifier(iapid); - } if (((publicConfig.type() == QNetworkConfiguration::UserChoice) && (activeConfig.identifier() == iapid)) || @@ -149,6 +146,9 @@ void QNetworkSessionPrivateImpl::iapStateChanged(const QString& iapid, uint icd_ break; } } + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + updateIdentifier(iapid); + } } void QNetworkSessionPrivateImpl::cleanupSession(void) diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 433eef6..741f8c5 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -1552,8 +1552,8 @@ void ConnectionProgressNotifier::StartNotifications() { if (!IsActive()) { SetActive(); + iConnection.ProgressNotification(iProgress, iStatus); } - iConnection.ProgressNotification(iProgress, iStatus); } void ConnectionProgressNotifier::StopNotifications() @@ -1569,10 +1569,10 @@ void ConnectionProgressNotifier::DoCancel() void ConnectionProgressNotifier::RunL() { if (iStatus == KErrNone) { - QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError)); - SetActive(); iConnection.ProgressNotification(iProgress, iStatus); + // warning, this object may be deleted in the callback - do nothing after handleSymbianConnectionStatusChange + QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError)); } } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 6639983..50e0f5f 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -300,40 +300,26 @@ void QDirectFBPixmapData::fromImage(const QImage &img, Qt::ImageConversionFlags { alpha = QDirectFBPixmapData::hasAlphaChannel(img, flags); imageFormat = alpha ? screen->alphaPixmapFormat() : screen->pixelFormat(); + QImage image; if ((flags & ~Qt::NoOpaqueDetection) != Qt::AutoColor) { image = img.convertToFormat(imageFormat, flags); flags = Qt::AutoColor; } else if (img.format() == QImage::Format_RGB32 || img.depth() == 1) { image = img.convertToFormat(imageFormat, flags); + } else if (img.format() != imageFormat) { + image = img.convertToFormat(imageFormat, flags); } else { image = img; } - IDirectFBSurface *imageSurface = screen->createDFBSurface(image, image.format(), QDirectFBScreen::DontTrackSurface); - if (!imageSurface) { - qWarning("QDirectFBPixmapData::fromImage()"); - invalidate(); - return; - } - - dfbSurface = screen->createDFBSurface(image.size(), imageFormat, QDirectFBScreen::TrackSurface); + dfbSurface = screen->createDFBSurface(image, image.format(), QDirectFBScreen::NoPreallocated | QDirectFBScreen::TrackSurface); if (!dfbSurface) { qWarning("QDirectFBPixmapData::fromImage()"); invalidate(); return; } - if (image.hasAlphaChannel()) { - dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_BLEND_ALPHACHANNEL); - } else { - dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); - } - - dfbSurface->Blit(dfbSurface, imageSurface, 0, 0, 0); - imageSurface->Release(imageSurface); - w = image.width(); h = image.height(); is_null = (w <= 0 || h <= 0); diff --git a/src/plugins/graphicssystems/meego/dithering.cpp b/src/plugins/graphicssystems/meego/dithering.cpp index 91e3337..2561c22 100644 --- a/src/plugins/graphicssystems/meego/dithering.cpp +++ b/src/plugins/graphicssystems/meego/dithering.cpp @@ -39,15 +39,22 @@ ** ****************************************************************************/ -// This is an implementation of the 32bit => 16bit Floyd-Steinberg dithering. +// Implements two dithering methods: +// +// * convertRGBA32_to_RGB565 +// +// This is implemented using Ordered Bayer Dithering. The code has been adapted +// from QX11PixmapData::fromImage. This method was originally implemented using +// Floyd-Steinberg dithering but was later changed to Ordered Dithering because +// of the better quality of the results. +// +// * convertRGBA32_to_RGBA4444 +// +// This is implemented using Floyd-Steinberg dithering. +// // The alghorithm used here is not the fastest possible but it's prolly fast enough: // uses look-up tables, integer-only arthmetics and works in one pass on two lines // at a time. It's a high-quality dithering using 1/8 diffusion precission. -// Two functions here to look at: -// -// * convertRGBA32_to_RGB565 -// * convertRGBA32_to_RGBA4444 -// // Each channel (RGBA) is diffused independently and alpha is dithered too. #include <string.h> @@ -76,113 +83,63 @@ // Converts incoming RGB32 (QImage::Format_RGB32) to RGB565. Returns the newly allocated data. unsigned short* convertRGB32_to_RGB565(const unsigned char *in, int width, int height, int stride) { + static bool thresholdMapInitialized = false; + static int thresholdMap[16][16]; + + if (!thresholdMapInitialized) { + int i; + int j; + int n; + + thresholdMap[0][0] = 0; + thresholdMap[1][0] = 2; + thresholdMap[0][1] = 3; + thresholdMap[1][1] = 1; + + for (n=2; n<16; n*=2) { + for (i=0; i<n; i++) { + for (j=0; j<n; j++) { + thresholdMap[i][j] *= 4; + thresholdMap[i+n][j] = thresholdMap[i][j] + 2; + thresholdMap[i][j+n] = thresholdMap[i][j] + 3; + thresholdMap[i+n][j+n] = thresholdMap[i][j] + 1; + } + } + } + + thresholdMapInitialized = true; + } + // Output line stride. Aligned to 4 bytes. int alignedWidth = width; if (alignedWidth % 2 > 0) alignedWidth++; // Will store output - unsigned short *out = (unsigned short *) malloc(alignedWidth * height * 2); - - // Lookup tables for the 8bit => 6bit and 8bit => 5bit conversion - unsigned char lookup_8bit_to_5bit[256]; - short lookup_8bit_to_5bit_diff[256]; - unsigned char lookup_8bit_to_6bit[256]; - short lookup_8bit_to_6bit_diff[256]; - - // Macros for the conversion using the lookup table. - #define CONVERT_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit[v]) - #define DIFF_8BIT_TO_5BIT(v) (lookup_8bit_to_5bit_diff[v]) - - #define CONVERT_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit[v]) - #define DIFF_8BIT_TO_6BIT(v) (lookup_8bit_to_6bit_diff[v]) - - int i; - int x, y, c; // Pixel we're processing. c is component number (0, 1, 2 for r, b, b) - short component[3]; // Stores the new components (r, g, b) for pixel produced during conversion - short diff; // The difference between the converted value and the original one. To be accumulated. - QVarLengthArray <short> accumulatorData(3 * width * 2); // Data for three acumulators for r, g, b. Each accumulator is two lines. - short *accumulator[3]; // Helper for accessing the accumulator on a per-channel basis more easily. - accumulator[0] = accumulatorData.data(); - accumulator[1] = accumulatorData.data() + width; - accumulator[2] = accumulatorData.data() + (width * 2); - - // Produce the conversion lookup tables. - for (i = 0; i < 256; i++) { - lookup_8bit_to_5bit[i] = round(i / 8.0); - - // Before bitshifts: (i * 8) - (... * 8 * 8) - lookup_8bit_to_5bit_diff[i] = (i << 3) - (lookup_8bit_to_5bit[i] << 6); - if (lookup_8bit_to_5bit[i] > 31) - lookup_8bit_to_5bit[i] -= 1; - - lookup_8bit_to_6bit[i] = round(i / 4.0); - - // Before bitshifts: (i * 8) - (... * 4 * 8) - lookup_8bit_to_6bit_diff[i] = (i << 3) - (lookup_8bit_to_6bit[i] << 5); - if (lookup_8bit_to_6bit[i] > 63) - lookup_8bit_to_6bit[i] -= 1; - } + unsigned short *out = (unsigned short *)malloc (alignedWidth * height * 2); - // Clear the accumulators - memset(accumulator[0], 0, width * 4); - memset(accumulator[1], 0, width * 4); - memset(accumulator[2], 0, width * 4); + int x; + int y; + int threshold; // For each line... for (y = 0; y < height; y++) { - // For each accumulator, move the second line (index 1) to replace the first line (index 0). - // Clear the second line (index 1) - memcpy(accumulator[0], accumulator[0] + width, width * 2); - memset(accumulator[0] + width, 0, width * 2); - - memcpy(accumulator[1], accumulator[1] + width, width * 2); - memset(accumulator[1] + width, 0, width * 2); - - memcpy(accumulator[2], accumulator[2] + width, width * 2); - memset(accumulator[2] + width, 0, width * 2); - // For each column.... for (x = 0; x < width; x++) { - // For each component (r, g, b)... - for (c = 0; c < 3; c++) { + int r = GET_RGBA_COMPONENT(in, x, y, stride, 0); + int g = GET_RGBA_COMPONENT(in, x, y, stride, 1); + int b = GET_RGBA_COMPONENT(in, x, y, stride, 2); - // Get the 8bit value from the original image - component[c] = GET_RGBA_COMPONENT(in, x, y, stride, c); - - // Add the diffusion for this pixel we stored in the accumulator. - // >> 7 because the values in accumulator are stored * 128 - if (x != 0 && x != (width - 1)) { - if (accumulator[c][x] >> 7 != 0) - component[c] += rand() % accumulator[c][x] >> 7; - } - - // Make sure we're not over the boundaries. - CLAMP_256(component[c]); - - // For green component we use 6 bits. Otherwise 5 bits. - // Store the difference from converting 8bit => 6 bit and the orig pixel. - // Convert 8bit => 6(5) bit. - if (c == 1) { - diff = DIFF_8BIT_TO_6BIT(component[c]); - component[c] = CONVERT_8BIT_TO_6BIT(component[c]); - } else { - diff = DIFF_8BIT_TO_5BIT(component[c]); - component[c] = CONVERT_8BIT_TO_5BIT(component[c]); - } + threshold = thresholdMap[x%16][y%16]; - // Distribute the difference according to the matrix in the - // accumulation bufffer. - ACCUMULATE(accumulator[c], x + 1, 0, width, diff * 3); - ACCUMULATE(accumulator[c], x - 1, 1, width, diff * 5); - ACCUMULATE(accumulator[c], x, 1, width, diff * 5); - ACCUMULATE(accumulator[c], x + 1, 1, width, diff * 3); - } + if (r <= (255-(1<<3)) && ((r<<5) & 255) > threshold) r += (1<<3); + if (g <= (255-(1<<2)) && ((g<<6) & 255) > threshold) g += (1<<2); + if (b <= (255-(1<<3)) && ((b<<5) & 255) > threshold) b += (1<<3); // Write the newly produced pixel - PUT_565(out, x, y, alignedWidth, component[2], component[1], component[0]); + PUT_565(out, x, y, alignedWidth, ((b >> 3) & 0x1f), ((g >> 2) & 0x3f), ((r >> 3) & 0x1f)); } } diff --git a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp index 20b092e..a70d232 100644 --- a/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp +++ b/src/plugins/graphicssystems/meego/qmeegographicssystem.cpp @@ -42,6 +42,7 @@ #include <QDebug> #include <private/qpixmap_raster_p.h> #include <private/qwindowsurface_gl_p.h> +#include <private/qwindowsurface_raster_p.h> #include <private/qegl_p.h> #include <private/qglextensions_p.h> #include <private/qgl_p.h> @@ -75,7 +76,12 @@ QMeeGoGraphicsSystem::~QMeeGoGraphicsSystem() QWindowSurface* QMeeGoGraphicsSystem::createWindowSurface(QWidget *widget) const { - QGLShareContextScope ctx(qt_gl_share_widget()->context()); + QGLWidget *shareWidget = qt_gl_share_widget(); + + if (!shareWidget) + return new QRasterWindowSurface(widget); + + QGLShareContextScope ctx(shareWidget->context()); QMeeGoGraphicsSystem::surfaceWasCreated = true; QWindowSurface *surface = new QGLWindowSurface(widget); diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 5b0b6f3..3e7da0e 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -15,4 +15,4 @@ symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon contains(QT_CONFIG, multimedia): SUBDIRS *= audio qpa:SUBDIRS += platforms - +contains(QT_CONFIG, declarative): SUBDIRS *= qmltooling diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro new file mode 100644 index 0000000..01cf1a9 --- /dev/null +++ b/src/plugins/qmltooling/qmltooling.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS = tcpserver + diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp new file mode 100644 index 0000000..69c1ef5 --- /dev/null +++ b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qtcpserverconnection.h" + +#include <QtNetwork/qtcpserver.h> +#include <QtNetwork/qtcpsocket.h> + +#include <private/qdeclarativedebugserver_p.h> +#include <private/qpacketprotocol_p.h> + +QT_BEGIN_NAMESPACE + +class QTcpServerConnectionPrivate { +public: + QTcpServerConnectionPrivate(); + + int port; + QTcpSocket *socket; + QPacketProtocol *protocol; + QTcpServer *tcpServer; + + QDeclarativeDebugServer *debugServer; +}; + +QTcpServerConnectionPrivate::QTcpServerConnectionPrivate() : + port(0), + socket(0), + protocol(0), + tcpServer(0), + debugServer(0) +{ +} + +QTcpServerConnection::QTcpServerConnection() : + d_ptr(new QTcpServerConnectionPrivate) +{ + +} + +QTcpServerConnection::~QTcpServerConnection() +{ + delete d_ptr; +} + +void QTcpServerConnection::setServer(QDeclarativeDebugServer *server) +{ + Q_D(QTcpServerConnection); + d->debugServer = server; +} + +bool QTcpServerConnection::isConnected() const +{ + Q_D(const QTcpServerConnection); + return d->socket && d->socket->state() == QTcpSocket::ConnectedState; +} + +void QTcpServerConnection::send(const QByteArray &message) +{ + Q_D(QTcpServerConnection); + + if (!isConnected()) + return; + + QPacket pack; + pack.writeRawData(message.data(), message.length()); + + d->protocol->send(pack); + d->socket->flush(); +} + +void QTcpServerConnection::disconnect() +{ + Q_D(QTcpServerConnection); + + delete d->protocol; + d->protocol = 0; + delete d->socket; + d->socket = 0; +} + +void QTcpServerConnection::setPort(int port, bool block) +{ + Q_D(QTcpServerConnection); + d->port = port; + + listen(); + if (block) + d->tcpServer->waitForNewConnection(-1); +} + +void QTcpServerConnection::listen() +{ + Q_D(QTcpServerConnection); + + d->tcpServer = new QTcpServer(this); + QObject::connect(d->tcpServer, SIGNAL(newConnection()), this, SLOT(newConnection())); + if (d->tcpServer->listen(QHostAddress::Any, d->port)) + qWarning("QDeclarativeDebugServer: Waiting for connection on port %d...", d->port); + else + qWarning("QDeclarativeDebugServer: Unable to listen on port %d", d->port); +} + + +void QTcpServerConnection::readyRead() +{ + Q_D(QTcpServerConnection); + QPacket packet = d->protocol->read(); + + QByteArray content = packet.data(); + d->debugServer->receiveMessage(content); +} + +void QTcpServerConnection::newConnection() +{ + Q_D(QTcpServerConnection); + + if (d->socket) { + qWarning("QDeclarativeDebugServer: Another client is already connected"); + QTcpSocket *faultyConnection = d->tcpServer->nextPendingConnection(); + delete faultyConnection; + return; + } + + d->socket = d->tcpServer->nextPendingConnection(); + d->socket->setParent(this); + d->protocol = new QPacketProtocol(d->socket, this); + QObject::connect(d->protocol, SIGNAL(readyRead()), this, SLOT(readyRead())); +} + + +Q_EXPORT_PLUGIN2(tcpserver, QTcpServerConnection) + +QT_END_NAMESPACE + diff --git a/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h new file mode 100644 index 0000000..a6e17e6 --- /dev/null +++ b/src/plugins/qmltooling/tcpserver/qtcpserverconnection.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative 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 Technology Preview License Agreement accompanying +** this package. +** +** 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.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTCPSERVERCONNECTION_H +#define QTCPSERVERCONNECTION_H + +#include <QtGui/QStylePlugin> +#include <QtDeclarative/private/qdeclarativedebugserverconnection_p.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeDebugServer; +class QTcpServerConnectionPrivate; +class QTcpServerConnection : public QObject, public QDeclarativeDebugServerConnection +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QTcpServerConnection) + Q_DISABLE_COPY(QTcpServerConnection) + Q_INTERFACES(QDeclarativeDebugServerConnection) + + +public: + QTcpServerConnection(); + ~QTcpServerConnection(); + + void setServer(QDeclarativeDebugServer *server); + void setPort(int port, bool bock); + + bool isConnected() const; + void send(const QByteArray &message); + void disconnect(); + + void listen(); + void waitForConnection(); + +private Q_SLOTS: + void readyRead(); + void newConnection(); + +private: + QTcpServerConnectionPrivate *d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QTCPSERVERCONNECTION_H diff --git a/src/plugins/qmltooling/tcpserver/tcpserver.pro b/src/plugins/qmltooling/tcpserver/tcpserver.pro new file mode 100644 index 0000000..f4f2666 --- /dev/null +++ b/src/plugins/qmltooling/tcpserver/tcpserver.pro @@ -0,0 +1,18 @@ +TARGET = tcpserver +QT += declarative network + +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/qmltooling +QTDIR_build:REQUIRES += "contains(QT_CONFIG, declarative)" + +SOURCES += \ + qtcpserverconnection.cpp + +HEADERS += \ + qtcpserverconnection.h + +target.path += $$[QT_INSTALL_PLUGINS]/qmltooling +INSTALLS += target + +symbian:TARGET.UID3=0x20031E90
\ No newline at end of file diff --git a/src/qbase.pri b/src/qbase.pri index 4d835bd..ce69757 100644 --- a/src/qbase.pri +++ b/src/qbase.pri @@ -197,7 +197,7 @@ symbian { # Partial upgrade SIS file vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ diff --git a/src/qt3support/network/q3dns.cpp b/src/qt3support/network/q3dns.cpp index c95edc1..d489652 100644 --- a/src/qt3support/network/q3dns.cpp +++ b/src/qt3support/network/q3dns.cpp @@ -2009,15 +2009,20 @@ Q3ValueList<QHostAddress> Q3Dns::addresses() const \class Q3Dns::MailServer \brief The Q3Dns::MailServer class is described in Q3Dns::mailServers(). - \internal +*/ + + +/*! \fn Q3Dns::MailServer::MailServer(const QString& n, Q_UINT16 p) + The constructor sets the public data members name and priority. + \a n is the name and \a p is the priority. */ /*! Returns a list of mail servers if the record type is \c Mx. The class Q3Dns::MailServer contains the following public variables: \list - \i QString Q3Dns::MailServer::name - \i Q_UINT16 Q3Dns::MailServer::priority + \o QString Q3Dns::MailServer::name + \o Q_UINT16 Q3Dns::MailServer::priority \endlist Note that if you want to iterate over the list, you should iterate @@ -2048,22 +2053,26 @@ Q3ValueList<Q3Dns::MailServer> Q3Dns::mailServers() const return result; } - /*! \class Q3Dns::Server \brief The Q3Dns::Server class is described in Q3Dns::servers(). - \internal +*/ + +/*! \fn Q3Dns::Server::Server(const QString& n, Q_UINT16 p, Q_UINT16 w, Q_UINT16 po) + The constructor sets the public data members name, priority, + weight, and port. \a n is the name, \a p is the priority, + \a w is the weight, and \a po is the port. */ /*! Returns a list of servers if the record type is \c Srv. The class Q3Dns::Server contains the following public variables: \list - \i QString Q3Dns::Server::name - \i Q_UINT16 Q3Dns::Server::priority - \i Q_UINT16 Q3Dns::Server::weight - \i Q_UINT16 Q3Dns::Server::port + \o QString Q3Dns::Server::name + \o Q_UINT16 Q3Dns::Server::priority + \o Q_UINT16 Q3Dns::Server::weight + \o Q_UINT16 Q3Dns::Server::port \endlist Note that if you want to iterate over the list, you should iterate diff --git a/src/qt3support/tools/q3memarray.qdoc b/src/qt3support/tools/q3memarray.qdoc index 9f2f1cc..f05f433 100644 --- a/src/qt3support/tools/q3memarray.qdoc +++ b/src/qt3support/tools/q3memarray.qdoc @@ -221,8 +221,8 @@ New elements are not initialized. - \a optim is either Q3GArray::MemOptim (the default) or - Q3GArray::SpeedOptim. When optimizing for speed rather than memory + \a optim is either \c MemOptim (the default) or + \c SpeedOptim. When optimizing for speed rather than memory consumption, the array uses a smart grow and shrink algorithm that might allocate more memory than is actually needed for \a size elements. This speeds up subsequent resize operations, for example diff --git a/src/qt3support/tools/q3ptrlist.qdoc b/src/qt3support/tools/q3ptrlist.qdoc index c4fdf4f..13e478e 100644 --- a/src/qt3support/tools/q3ptrlist.qdoc +++ b/src/qt3support/tools/q3ptrlist.qdoc @@ -93,7 +93,8 @@ also holds pointers to the next and previous list items. The functions currentNode(), removeNode(), and takeNode() operate directly on the Q3LNode, but they should be used with care. The - data component of the node is available through Q3LNode::getData(). + data component of the node is available through Q3LNode's getData() + function. The Q3StrList class is a list of \c char*. It reimplements newItem(), deleteItem() and compareItems(). (But diff --git a/src/s60installs/bwins/QtCoreu.def b/src/s60installs/bwins/QtCoreu.def index a2692f7..dd7d588 100644 --- a/src/s60installs/bwins/QtCoreu.def +++ b/src/s60installs/bwins/QtCoreu.def @@ -4603,4 +4603,6 @@ EXPORTS ??XQPoint@@QAEAAV0@N@Z @ 4602 NONAME ; class QPoint & QPoint::operator*=(double) ??XQPoint@@QAEAAV0@H@Z @ 4603 NONAME ; class QPoint & QPoint::operator*=(int) ?hasError@QXmlStreamWriter@@QBE_NXZ @ 4604 NONAME ; bool QXmlStreamWriter::hasError(void) const + ?revision@QMetaProperty@@QBEHXZ @ 4605 NONAME ; int QMetaProperty::revision(void) const + ?revision@QMetaMethod@@QBEHXZ @ 4606 NONAME ; int QMetaMethod::revision(void) const diff --git a/src/s60installs/bwins/QtDeclarativeu.def b/src/s60installs/bwins/QtDeclarativeu.def index 9e88df7..7d0a83e 100644 --- a/src/s60installs/bwins/QtDeclarativeu.def +++ b/src/s60installs/bwins/QtDeclarativeu.def @@ -52,7 +52,7 @@ EXPORTS ?isDesignable@QMetaPropertyBuilder@@QBE_NXZ @ 51 NONAME ABSENT ; bool QMetaPropertyBuilder::isDesignable(void) const ?tr@QDeclarativeStateGroup@@SA?AVQString@@PBD0H@Z @ 52 NONAME ; class QString QDeclarativeStateGroup::tr(char const *, char const *, int) ?errors@QDeclarativeView@@QBE?AV?$QList@VQDeclarativeError@@@@XZ @ 53 NONAME ; class QList<class QDeclarativeError> QDeclarativeView::errors(void) const - ??0QPacket@@QAE@ABV0@@Z @ 54 NONAME ABSENT ; QPacket::QPacket(class QPacket const &) + ??0QPacket@@QAE@ABV0@@Z @ 54 NONAME ; QPacket::QPacket(class QPacket const &) ??1QDeclarativeDebugObjectExpressionWatch@@UAE@XZ @ 55 NONAME ABSENT ; QDeclarativeDebugObjectExpressionWatch::~QDeclarativeDebugObjectExpressionWatch(void) ?status@QDeclarativePixmap@@QBE?AW4Status@1@XZ @ 56 NONAME ; enum QDeclarativePixmap::Status QDeclarativePixmap::status(void) const ?bottom@QDeclarativeAnchors@@QBE?AVQDeclarativeAnchorLine@@XZ @ 57 NONAME ABSENT ; class QDeclarativeAnchorLine QDeclarativeAnchors::bottom(void) const @@ -69,7 +69,7 @@ EXPORTS ??0Variant@QDeclarativeParser@@QAE@ABVQString@@@Z @ 68 NONAME ; QDeclarativeParser::Variant::Variant(class QString const &) ?paintedSizeChanged@QDeclarativeText@@IAEXXZ @ 69 NONAME ABSENT ; void QDeclarativeText::paintedSizeChanged(void) ??1QDeclarativeDebugClient@@UAE@XZ @ 70 NONAME ABSENT ; QDeclarativeDebugClient::~QDeclarativeDebugClient(void) - ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 71 NONAME ABSENT ; class QString QPacketProtocol::trUtf8(char const *, char const *) + ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 71 NONAME ; class QString QPacketProtocol::trUtf8(char const *, char const *) ?trUtf8@QDeclarativeListModel@@SA?AVQString@@PBD0@Z @ 72 NONAME ABSENT ; class QString QDeclarativeListModel::trUtf8(char const *, char const *) ?qt_metacast@QDeclarativeState@@UAEPAXPBD@Z @ 73 NONAME ; void * QDeclarativeState::qt_metacast(char const *) ??1QDeclarativeDebugContextReference@@QAE@XZ @ 74 NONAME ABSENT ; QDeclarativeDebugContextReference::~QDeclarativeDebugContextReference(void) @@ -126,7 +126,7 @@ EXPORTS ?addToObject@QDeclarativeAbstractBinding@@QAEXPAVQObject@@@Z @ 125 NONAME ABSENT ; void QDeclarativeAbstractBinding::addToObject(class QObject *) ?trUtf8@QDeclarativeView@@SA?AVQString@@PBD0H@Z @ 126 NONAME ; class QString QDeclarativeView::trUtf8(char const *, char const *, int) ?d_func@QDeclarativeAnchors@@AAEPAVQDeclarativeAnchorsPrivate@@XZ @ 127 NONAME ABSENT ; class QDeclarativeAnchorsPrivate * QDeclarativeAnchors::d_func(void) - ??1QPacket@@UAE@XZ @ 128 NONAME ABSENT ; QPacket::~QPacket(void) + ??1QPacket@@UAE@XZ @ 128 NONAME ; QPacket::~QPacket(void) ?top@QDeclarativeScaleGrid@@QBEHXZ @ 129 NONAME ABSENT ; int QDeclarativeScaleGrid::top(void) const ?setExpression@QDeclarativeExpression@@QAEXABVQString@@@Z @ 130 NONAME ; void QDeclarativeExpression::setExpression(class QString const &) ??1QDeclarativeDebugEngineReference@@QAE@XZ @ 131 NONAME ABSENT ; QDeclarativeDebugEngineReference::~QDeclarativeDebugEngineReference(void) @@ -252,7 +252,7 @@ EXPORTS ??4QDeclarativeDomValueLiteral@@QAEAAV0@ABV0@@Z @ 251 NONAME ABSENT ; class QDeclarativeDomValueLiteral & QDeclarativeDomValueLiteral::operator=(class QDeclarativeDomValueLiteral const &) ?setScript@QDeclarativeScriptString@@QAEXABVQString@@@Z @ 252 NONAME ; void QDeclarativeScriptString::setScript(class QString const &) ?requestImage@QDeclarativeImageProvider@@UAE?AVQImage@@ABVQString@@PAVQSize@@ABV4@@Z @ 253 NONAME ; class QImage QDeclarativeImageProvider::requestImage(class QString const &, class QSize *, class QSize const &) - ?qt_metacast@QPacketProtocol@@UAEPAXPBD@Z @ 254 NONAME ABSENT ; void * QPacketProtocol::qt_metacast(char const *) + ?qt_metacast@QPacketProtocol@@UAEPAXPBD@Z @ 254 NONAME ; void * QPacketProtocol::qt_metacast(char const *) ?addMetaObject@QMetaObjectBuilder@@QAEXPBUQMetaObject@@V?$QFlags@W4AddMember@QMetaObjectBuilder@@@@@Z @ 255 NONAME ABSENT ; void QMetaObjectBuilder::addMetaObject(struct QMetaObject const *, class QFlags<enum QMetaObjectBuilder::AddMember>) ?trUtf8@QDeclarativeRectangle@@SA?AVQString@@PBD0H@Z @ 256 NONAME ABSENT ; class QString QDeclarativeRectangle::trUtf8(char const *, char const *, int) ?qt_metacast@QDeclarativeText@@UAEPAXPBD@Z @ 257 NONAME ABSENT ; void * QDeclarativeText::qt_metacast(char const *) @@ -263,7 +263,7 @@ EXPORTS ?create@QDeclarativeType@@QBEPAVQObject@@XZ @ 262 NONAME ABSENT ; class QObject * QDeclarativeType::create(void) const ?metaObject@QDeclarativeDebugExpressionQuery@@UBEPBUQMetaObject@@XZ @ 263 NONAME ABSENT ; struct QMetaObject const * QDeclarativeDebugExpressionQuery::metaObject(void) const ?engine@QDeclarativeView@@QBEPAVQDeclarativeEngine@@XZ @ 264 NONAME ; class QDeclarativeEngine * QDeclarativeView::engine(void) const - ?readyRead@QPacketProtocol@@IAEXXZ @ 265 NONAME ABSENT ; void QPacketProtocol::readyRead(void) + ?readyRead@QPacketProtocol@@IAEXXZ @ 265 NONAME ; void QPacketProtocol::readyRead(void) ?qt_metacall@QDeclarativeValueType@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 266 NONAME ABSENT ; int QDeclarativeValueType::qt_metacall(enum QMetaObject::Call, int, void * *) ?propertyType@QDeclarativePropertyPrivate@@QBEHXZ @ 267 NONAME ABSENT ; int QDeclarativePropertyPrivate::propertyType(void) const ?inputMethodQuery@QDeclarativeItem@@MBE?AVQVariant@@W4InputMethodQuery@Qt@@@Z @ 268 NONAME ; class QVariant QDeclarativeItem::inputMethodQuery(enum Qt::InputMethodQuery) const @@ -310,7 +310,7 @@ EXPORTS ?setSmooth@QDeclarativeItem@@QAEX_N@Z @ 309 NONAME ; void QDeclarativeItem::setSmooth(bool) ?value@QDeclarativeDebugPropertyReference@@QBE?AVQVariant@@XZ @ 310 NONAME ABSENT ; class QVariant QDeclarativeDebugPropertyReference::value(void) const ?resources@QDeclarativeItemPrivate@@QAE?AV?$QDeclarativeListProperty@VQObject@@@@XZ @ 311 NONAME ; class QDeclarativeListProperty<class QObject> QDeclarativeItemPrivate::resources(void) - ?clear@QPacketProtocol@@QAEXXZ @ 312 NONAME ABSENT ; void QPacketProtocol::clear(void) + ?clear@QPacketProtocol@@QAEXXZ @ 312 NONAME ; void QPacketProtocol::clear(void) ?setState@QDeclarativeItemPrivate@@QAEXABVQString@@@Z @ 313 NONAME ; void QDeclarativeItemPrivate::setState(class QString const &) ??4QDeclarativeDebugPropertyReference@@QAEAAV0@ABV0@@Z @ 314 NONAME ABSENT ; class QDeclarativeDebugPropertyReference & QDeclarativeDebugPropertyReference::operator=(class QDeclarativeDebugPropertyReference const &) ?metaObject@QDeclarativeView@@UBEPBUQMetaObject@@XZ @ 315 NONAME ; struct QMetaObject const * QDeclarativeView::metaObject(void) const @@ -377,7 +377,7 @@ EXPORTS ?status@QDeclarativeView@@QBE?AW4Status@1@XZ @ 376 NONAME ; enum QDeclarativeView::Status QDeclarativeView::status(void) const ??0QDeclarativeEngineDebug@@QAE@PAVQDeclarativeDebugConnection@@PAVQObject@@@Z @ 377 NONAME ABSENT ; QDeclarativeEngineDebug::QDeclarativeEngineDebug(class QDeclarativeDebugConnection *, class QObject *) ?create@QDeclarativeComponent@@UAEPAVQObject@@PAVQDeclarativeContext@@@Z @ 378 NONAME ; class QObject * QDeclarativeComponent::create(class QDeclarativeContext *) - ??_EQPacket@@UAE@I@Z @ 379 NONAME ABSENT ; QPacket::~QPacket(unsigned int) + ??_EQPacket@@UAE@I@Z @ 379 NONAME ; QPacket::~QPacket(unsigned int) ?trUtf8@QDeclarativeScaleGrid@@SA?AVQString@@PBD0H@Z @ 380 NONAME ABSENT ; class QString QDeclarativeScaleGrid::trUtf8(char const *, char const *, int) ?isResettable@QDeclarativeProperty@@QBE_NXZ @ 381 NONAME ; bool QDeclarativeProperty::isResettable(void) const ?isList@QDeclarativeCustomParserProperty@@QBE_NXZ @ 382 NONAME ; bool QDeclarativeCustomParserProperty::isList(void) const @@ -428,7 +428,7 @@ EXPORTS ?line@QDeclarativeError@@QBEHXZ @ 427 NONAME ; int QDeclarativeError::line(void) const ?heightValid@QDeclarativeItem@@IBE_NXZ @ 428 NONAME ; bool QDeclarativeItem::heightValid(void) const ??1QDeclarativeOpenMetaObject@@UAE@XZ @ 429 NONAME ABSENT ; QDeclarativeOpenMetaObject::~QDeclarativeOpenMetaObject(void) - ??0QPacket@@QAE@XZ @ 430 NONAME ABSENT ; QPacket::QPacket(void) + ??0QPacket@@QAE@XZ @ 430 NONAME ; QPacket::QPacket(void) ?trUtf8@QDeclarativePropertyMap@@SA?AVQString@@PBD0H@Z @ 431 NONAME ; class QString QDeclarativePropertyMap::trUtf8(char const *, char const *, int) ?trUtf8@QDeclarativeEngine@@SA?AVQString@@PBD0H@Z @ 432 NONAME ; class QString QDeclarativeEngine::trUtf8(char const *, char const *, int) ??0QDeclarativeDebugEngineReference@@QAE@XZ @ 433 NONAME ABSENT ; QDeclarativeDebugEngineReference::QDeclarativeDebugEngineReference(void) @@ -485,7 +485,7 @@ EXPORTS ?staticMetaObject@QDeclarativeDebugService@@2UQMetaObject@@B @ 484 NONAME ABSENT ; struct QMetaObject const QDeclarativeDebugService::staticMetaObject ?topMargin@QDeclarativeAnchors@@QBEMXZ @ 485 NONAME ABSENT ; float QDeclarativeAnchors::topMargin(void) const ??0QDeclarativeDebugExpressionQuery@@AAE@PAVQObject@@@Z @ 486 NONAME ABSENT ; QDeclarativeDebugExpressionQuery::QDeclarativeDebugExpressionQuery(class QObject *) - ??0QPacket@@IAE@ABVQByteArray@@@Z @ 487 NONAME ABSENT ; QPacket::QPacket(class QByteArray const &) + ??0QPacket@@IAE@ABVQByteArray@@@Z @ 487 NONAME ; QPacket::QPacket(class QByteArray const &) ?implicitSize@QDeclarativePixmap@@QBEABVQSize@@XZ @ 488 NONAME ; class QSize const & QDeclarativePixmap::implicitSize(void) const ?setFlags@QMetaObjectBuilder@@QAEXV?$QFlags@W4MetaObjectFlag@QMetaObjectBuilder@@@@@Z @ 489 NONAME ABSENT ; void QMetaObjectBuilder::setFlags(class QFlags<enum QMetaObjectBuilder::MetaObjectFlag>) ?horizontalCenterChanged@QDeclarativeAnchors@@IAEXXZ @ 490 NONAME ABSENT ; void QDeclarativeAnchors::horizontalCenterChanged(void) @@ -502,7 +502,7 @@ EXPORTS ?qmlAttachedPropertiesObject@@YAPAVQObject@@PAHPBV1@PBUQMetaObject@@_N@Z @ 501 NONAME ; class QObject * qmlAttachedPropertiesObject(int *, class QObject const *, struct QMetaObject const *, bool) ??_EQDeclarativeDebugClient@@UAE@I@Z @ 502 NONAME ABSENT ; QDeclarativeDebugClient::~QDeclarativeDebugClient(unsigned int) ??4QDeclarativeDomComponent@@QAEAAV0@ABV0@@Z @ 503 NONAME ABSENT ; class QDeclarativeDomComponent & QDeclarativeDomComponent::operator=(class QDeclarativeDomComponent const &) - ?tr@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 504 NONAME ABSENT ; class QString QPacketProtocol::tr(char const *, char const *) + ?tr@QPacketProtocol@@SA?AVQString@@PBD0@Z @ 504 NONAME ; class QString QPacketProtocol::tr(char const *, char const *) ?setFont@QDeclarativeText@@QAEXABVQFont@@@Z @ 505 NONAME ABSENT ; void QDeclarativeText::setFont(class QFont const &) ?fromChanged@QDeclarativeTransition@@IAEXXZ @ 506 NONAME ; void QDeclarativeTransition::fromChanged(void) ?addMethod@QMetaObjectBuilder@@QAE?AVQMetaMethodBuilder@@ABVQMetaMethod@@@Z @ 507 NONAME ABSENT ; class QMetaMethodBuilder QMetaObjectBuilder::addMethod(class QMetaMethod const &) @@ -610,7 +610,7 @@ EXPORTS ??0QDeclarativeListReference@@QAE@PAVQObject@@PBDPAVQDeclarativeEngine@@@Z @ 609 NONAME ; QDeclarativeListReference::QDeclarativeListReference(class QObject *, char const *, class QDeclarativeEngine *) ?setData@QListModelInterface@@UAE_NHABV?$QHash@HVQVariant@@@@@Z @ 610 NONAME ABSENT ; bool QListModelInterface::setData(int, class QHash<int, class QVariant> const &) ??0QDeclarativePen@@QAE@PAVQObject@@@Z @ 611 NONAME ABSENT ; QDeclarativePen::QDeclarativePen(class QObject *) - ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 612 NONAME ABSENT ; class QString QPacketProtocol::trUtf8(char const *, char const *, int) + ?trUtf8@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 612 NONAME ; class QString QPacketProtocol::trUtf8(char const *, char const *, int) ?setContextObject@QDeclarativeContext@@QAEXPAVQObject@@@Z @ 613 NONAME ; void QDeclarativeContext::setContextObject(class QObject *) ??_EQDeclarativeState@@UAE@I@Z @ 614 NONAME ; QDeclarativeState::~QDeclarativeState(unsigned int) ?expression@QDeclarativeExpression@@QBE?AVQString@@XZ @ 615 NONAME ; class QString QDeclarativeExpression::expression(void) const @@ -668,7 +668,7 @@ EXPORTS ?setStdCppSet@QMetaPropertyBuilder@@QAEX_N@Z @ 667 NONAME ABSENT ; void QMetaPropertyBuilder::setStdCppSet(bool) ??0QDeclarativeItemPrivate@@QAE@XZ @ 668 NONAME ; QDeclarativeItemPrivate::QDeclarativeItemPrivate(void) ??0QDeclarativeDebugService@@QAE@ABVQString@@PAVQObject@@@Z @ 669 NONAME ABSENT ; QDeclarativeDebugService::QDeclarativeDebugService(class QString const &, class QObject *) - ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@_N@Z @ 670 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, bool) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@_N@Z @ 670 NONAME ABSENT ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, bool) ??_EQPacketAutoSend@@UAE@I@Z @ 671 NONAME ABSENT ; QPacketAutoSend::~QPacketAutoSend(unsigned int) ?saveValueType@QDeclarativePropertyPrivate@@SA?AVQByteArray@@PBUQMetaObject@@H0H@Z @ 672 NONAME ABSENT ; class QByteArray QDeclarativePropertyPrivate::saveValueType(struct QMetaObject const *, int, struct QMetaObject const *, int) ?resetHeight@QDeclarativeItem@@QAEXXZ @ 673 NONAME ; void QDeclarativeItem::resetHeight(void) @@ -688,7 +688,7 @@ EXPORTS ?d_func@QDeclarativeDebugClient@@AAEPAVQDeclarativeDebugClientPrivate@@XZ @ 687 NONAME ABSENT ; class QDeclarativeDebugClientPrivate * QDeclarativeDebugClient::d_func(void) ??1QDeclarativeType@@AAE@XZ @ 688 NONAME ABSENT ; QDeclarativeType::~QDeclarativeType(void) ?colorFromString@QDeclarativeStringConverters@@YA?AVQColor@@ABVQString@@PA_N@Z @ 689 NONAME ABSENT ; class QColor QDeclarativeStringConverters::colorFromString(class QString const &, bool *) - ??_EQPacketProtocol@@UAE@I@Z @ 690 NONAME ABSENT ; QPacketProtocol::~QPacketProtocol(unsigned int) + ??_EQPacketProtocol@@UAE@I@Z @ 690 NONAME ; QPacketProtocol::~QPacketProtocol(unsigned int) ?tr@QDeclarativeListModel@@SA?AVQString@@PBD0@Z @ 691 NONAME ABSENT ; class QString QDeclarativeListModel::tr(char const *, char const *) ??0QDeclarativePixmap@@QAE@XZ @ 692 NONAME ; QDeclarativePixmap::QDeclarativePixmap(void) ??0QDeclarativeDebugObjectReference@@QAE@XZ @ 693 NONAME ABSENT ; QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(void) @@ -704,7 +704,7 @@ EXPORTS ??4QDeclarativeDomDocument@@QAEAAV0@ABV0@@Z @ 703 NONAME ABSENT ; class QDeclarativeDomDocument & QDeclarativeDomDocument::operator=(class QDeclarativeDomDocument const &) ??0QDeclarativeOpenMetaObject@@QAE@PAVQObject@@PAVQDeclarativeOpenMetaObjectType@@_N@Z @ 704 NONAME ABSENT ; QDeclarativeOpenMetaObject::QDeclarativeOpenMetaObject(class QObject *, class QDeclarativeOpenMetaObjectType *, bool) ?trUtf8@QDeclarativeExpression@@SA?AVQString@@PBD0@Z @ 705 NONAME ; class QString QDeclarativeExpression::trUtf8(char const *, char const *) - ??0QPacketProtocol@@QAE@PAVQIODevice@@PAVQObject@@@Z @ 706 NONAME ABSENT ; QPacketProtocol::QPacketProtocol(class QIODevice *, class QObject *) + ??0QPacketProtocol@@QAE@PAVQIODevice@@PAVQObject@@@Z @ 706 NONAME ; QPacketProtocol::QPacketProtocol(class QIODevice *, class QObject *) ??1QDeclarativeListReference@@QAE@XZ @ 707 NONAME ; QDeclarativeListReference::~QDeclarativeListReference(void) ?clearError@QDeclarativeExpression@@QAEXXZ @ 708 NONAME ; void QDeclarativeExpression::clearError(void) ?setLineNumber@QDeclarativeDebugFileReference@@QAEXH@Z @ 709 NONAME ABSENT ; void QDeclarativeDebugFileReference::setLineNumber(int) @@ -757,7 +757,7 @@ EXPORTS ??4QDeclarativeDomValueBinding@@QAEAAV0@ABV0@@Z @ 756 NONAME ABSENT ; class QDeclarativeDomValueBinding & QDeclarativeDomValueBinding::operator=(class QDeclarativeDomValueBinding const &) ??0QDeclarativeExpression@@QAE@XZ @ 757 NONAME ; QDeclarativeExpression::QDeclarativeExpression(void) ?paint@QDeclarativeItem@@UAEXPAVQPainter@@PBVQStyleOptionGraphicsItem@@PAVQWidget@@@Z @ 758 NONAME ; void QDeclarativeItem::paint(class QPainter *, class QStyleOptionGraphicsItem const *, class QWidget *) - ?send@QPacketProtocol@@QAE?AVQPacketAutoSend@@XZ @ 759 NONAME ABSENT ; class QPacketAutoSend QPacketProtocol::send(void) + ?send@QPacketProtocol@@QAE?AVQPacketAutoSend@@XZ @ 759 NONAME ; class QPacketAutoSend QPacketProtocol::send(void) ?countChanged@QDeclarativeListModel@@IAEXXZ @ 760 NONAME ABSENT ; void QDeclarativeListModel::countChanged(void) ??0QDeclarativeGridScaledImage@@QAE@PAVQIODevice@@@Z @ 761 NONAME ABSENT ; QDeclarativeGridScaledImage::QDeclarativeGridScaledImage(class QIODevice *) ??_EQDeclarativeBinding@@UAE@I@Z @ 762 NONAME ABSENT ; QDeclarativeBinding::~QDeclarativeBinding(unsigned int) @@ -776,7 +776,7 @@ EXPORTS ?hasNotifySignal@QDeclarativeProperty@@QBE_NXZ @ 775 NONAME ; bool QDeclarativeProperty::hasNotifySignal(void) const ?create@QDeclarativeType@@QBEXPAPAVQObject@@PAPAXI@Z @ 776 NONAME ABSENT ; void QDeclarativeType::create(class QObject * *, void * *, unsigned int) const ?reversible@QDeclarativeTransition@@QBE_NXZ @ 777 NONAME ; bool QDeclarativeTransition::reversible(void) const - ?invalidPacket@QPacketProtocol@@IAEXXZ @ 778 NONAME ABSENT ; void QPacketProtocol::invalidPacket(void) + ?invalidPacket@QPacketProtocol@@IAEXXZ @ 778 NONAME ; void QPacketProtocol::invalidPacket(void) ??0QDeclarativeDebugObjectReference@@QAE@H@Z @ 779 NONAME ABSENT ; QDeclarativeDebugObjectReference::QDeclarativeDebugObjectReference(int) ?superClass@QMetaObjectBuilder@@QBEPBUQMetaObject@@XZ @ 780 NONAME ABSENT ; struct QMetaObject const * QMetaObjectBuilder::superClass(void) const ?isValid@QDeclarativeListReference@@QBE_NXZ @ 781 NONAME ; bool QDeclarativeListReference::isValid(void) const @@ -813,7 +813,7 @@ EXPORTS ??_EQDeclarativeDebugQuery@@UAE@I@Z @ 812 NONAME ABSENT ; QDeclarativeDebugQuery::~QDeclarativeDebugQuery(unsigned int) ?update@QDeclarativeAbstractBinding@@QAEXXZ @ 813 NONAME ABSENT ; void QDeclarativeAbstractBinding::update(void) ?tr@QDeclarativeBehavior@@SA?AVQString@@PBD0H@Z @ 814 NONAME ABSENT ; class QString QDeclarativeBehavior::tr(char const *, char const *, int) - ?read@QPacketProtocol@@QAE?AVQPacket@@XZ @ 815 NONAME ABSENT ; class QPacket QPacketProtocol::read(void) + ?read@QPacketProtocol@@QAE?AVQPacket@@XZ @ 815 NONAME ; class QPacket QPacketProtocol::read(void) ?setParentItem@QDeclarativeItem@@QAEXPAV1@@Z @ 816 NONAME ; void QDeclarativeItem::setParentItem(class QDeclarativeItem *) ?qmlAttachedProperties@QDeclarativeComponent@@SAPAVQDeclarativeComponentAttached@@PAVQObject@@@Z @ 817 NONAME ; class QDeclarativeComponentAttached * QDeclarativeComponent::qmlAttachedProperties(class QObject *) ??0QDeclarativeView@@QAE@ABVQUrl@@PAVQWidget@@@Z @ 818 NONAME ; QDeclarativeView::QDeclarativeView(class QUrl const &, class QWidget *) @@ -821,7 +821,7 @@ EXPORTS ??_EQDeclarativeView@@UAE@I@Z @ 820 NONAME ; QDeclarativeView::~QDeclarativeView(unsigned int) ?trUtf8@QDeclarativeStateGroup@@SA?AVQString@@PBD0H@Z @ 821 NONAME ; class QString QDeclarativeStateGroup::trUtf8(char const *, char const *, int) ?tag@QMetaMethodBuilder@@QBE?AVQByteArray@@XZ @ 822 NONAME ABSENT ; class QByteArray QMetaMethodBuilder::tag(void) const - ?getStaticMetaObject@QPacketProtocol@@SAABUQMetaObject@@XZ @ 823 NONAME ABSENT ; struct QMetaObject const & QPacketProtocol::getStaticMetaObject(void) + ?getStaticMetaObject@QPacketProtocol@@SAABUQMetaObject@@XZ @ 823 NONAME ; struct QMetaObject const & QPacketProtocol::getStaticMetaObject(void) ?setContext@QDeclarativeScriptString@@QAEXPAVQDeclarativeContext@@@Z @ 824 NONAME ; void QDeclarativeScriptString::setContext(class QDeclarativeContext *) ?addImageProvider@QDeclarativeEngine@@QAEXABVQString@@PAVQDeclarativeImageProvider@@@Z @ 825 NONAME ; void QDeclarativeEngine::addImageProvider(class QString const &, class QDeclarativeImageProvider *) ?d_func@QDeclarativeStateGroup@@ABEPBVQDeclarativeStateGroupPrivate@@XZ @ 826 NONAME ; class QDeclarativeStateGroupPrivate const * QDeclarativeStateGroup::d_func(void) const @@ -1013,7 +1013,7 @@ EXPORTS ?agent@QDeclarativeListModel@@QAEPAVQDeclarativeListModelWorkerAgent@@XZ @ 1012 NONAME ABSENT ; class QDeclarativeListModelWorkerAgent * QDeclarativeListModel::agent(void) ?engine@QDeclarativeExpression@@QBEPAVQDeclarativeEngine@@XZ @ 1013 NONAME ; class QDeclarativeEngine * QDeclarativeExpression::engine(void) const ??_EQDeclarativeDebugWatch@@UAE@I@Z @ 1014 NONAME ABSENT ; QDeclarativeDebugWatch::~QDeclarativeDebugWatch(unsigned int) - ?isEmpty@QPacket@@QBE_NXZ @ 1015 NONAME ABSENT ; bool QPacket::isEmpty(void) const + ?isEmpty@QPacket@@QBE_NXZ @ 1015 NONAME ; bool QPacket::isEmpty(void) const ?qmlType@QDeclarativeMetaType@@SAPAVQDeclarativeType@@PBUQMetaObject@@@Z @ 1016 NONAME ABSENT ; class QDeclarativeType * QDeclarativeMetaType::qmlType(struct QMetaObject const *) ?setFill@QDeclarativeAnchors@@QAEXPAVQGraphicsObject@@@Z @ 1017 NONAME ABSENT ; void QDeclarativeAnchors::setFill(class QGraphicsObject *) ?setHAlign@QDeclarativeText@@QAEXW4HAlignment@1@@Z @ 1018 NONAME ABSENT ; void QDeclarativeText::setHAlign(enum QDeclarativeText::HAlignment) @@ -1029,7 +1029,7 @@ EXPORTS ?staticMetaObject@QDeclarativeText@@2UQMetaObject@@B @ 1028 NONAME ABSENT ; struct QMetaObject const QDeclarativeText::staticMetaObject ?color@QDeclarativeRectangle@@QBE?AVQColor@@XZ @ 1029 NONAME ABSENT ; class QColor QDeclarativeRectangle::color(void) const ?isEnabled@QDeclarativeDebugClient@@QBE_NXZ @ 1030 NONAME ABSENT ; bool QDeclarativeDebugClient::isEnabled(void) const - ?send@QPacketProtocol@@QAEXABVQPacket@@@Z @ 1031 NONAME ABSENT ; void QPacketProtocol::send(class QPacket const &) + ?send@QPacketProtocol@@QAEXABVQPacket@@@Z @ 1031 NONAME ; void QPacketProtocol::send(class QPacket const &) ?width@QDeclarativePixmap@@QBEHXZ @ 1032 NONAME ; int QDeclarativePixmap::width(void) const ?error@QDeclarativeCustomParser@@IAEXABVQDeclarativeCustomParserNode@@ABVQString@@@Z @ 1033 NONAME ; void QDeclarativeCustomParser::error(class QDeclarativeCustomParserNode const &, class QString const &) ?defaultProperty@QDeclarativeMetaType@@SA?AVQMetaProperty@@PBUQMetaObject@@@Z @ 1034 NONAME ABSENT ; class QMetaProperty QDeclarativeMetaType::defaultProperty(struct QMetaObject const *) @@ -1043,7 +1043,7 @@ EXPORTS ?trUtf8@QDeclarativeAnchors@@SA?AVQString@@PBD0@Z @ 1042 NONAME ABSENT ; class QString QDeclarativeAnchors::trUtf8(char const *, char const *) ?getStaticMetaObject@QDeclarativeValueType@@SAABUQMetaObject@@XZ @ 1043 NONAME ABSENT ; struct QMetaObject const & QDeclarativeValueType::getStaticMetaObject(void) ?valueChanged@QDeclarativePropertyMap@@IAEXABVQString@@ABVQVariant@@@Z @ 1044 NONAME ; void QDeclarativePropertyMap::valueChanged(class QString const &, class QVariant const &) - ?staticMetaObject@QPacketProtocol@@2UQMetaObject@@B @ 1045 NONAME ABSENT ; struct QMetaObject const QPacketProtocol::staticMetaObject + ?staticMetaObject@QPacketProtocol@@2UQMetaObject@@B @ 1045 NONAME ; struct QMetaObject const QPacketProtocol::staticMetaObject ?tr@QDeclarativeListModel@@SA?AVQString@@PBD0H@Z @ 1046 NONAME ABSENT ; class QString QDeclarativeListModel::tr(char const *, char const *, int) ??0QDeclarativeScriptString@@QAE@XZ @ 1047 NONAME ; QDeclarativeScriptString::QDeclarativeScriptString(void) ?tr@QListModelInterface@@SA?AVQString@@PBD0@Z @ 1048 NONAME ABSENT ; class QString QListModelInterface::tr(char const *, char const *) @@ -1088,7 +1088,7 @@ EXPORTS ?resetWidth@QDeclarativeItemPrivate@@UAEXXZ @ 1087 NONAME ; void QDeclarativeItemPrivate::resetWidth(void) ??AQDeclarativeOpenMetaObject@@QAEAAVQVariant@@ABVQByteArray@@@Z @ 1088 NONAME ABSENT ; class QVariant & QDeclarativeOpenMetaObject::operator[](class QByteArray const &) ?bottom@QDeclarativeItemPrivate@@QBE?AVQDeclarativeAnchorLine@@XZ @ 1089 NONAME ; class QDeclarativeAnchorLine QDeclarativeItemPrivate::bottom(void) const - ?device@QPacketProtocol@@QAEPAVQIODevice@@XZ @ 1090 NONAME ABSENT ; class QIODevice * QPacketProtocol::device(void) + ?device@QPacketProtocol@@QAEPAVQIODevice@@XZ @ 1090 NONAME ; class QIODevice * QPacketProtocol::device(void) ?trUtf8@QDeclarativeStateGroup@@SA?AVQString@@PBD0@Z @ 1091 NONAME ; class QString QDeclarativeStateGroup::trUtf8(char const *, char const *) ?variantFromString@QDeclarativeStringConverters@@YA?AVQVariant@@ABVQString@@HPA_N@Z @ 1092 NONAME ABSENT ; class QVariant QDeclarativeStringConverters::variantFromString(class QString const &, int, bool *) ?metaObject@QDeclarativeComponent@@UBEPBUQMetaObject@@XZ @ 1093 NONAME ; struct QMetaObject const * QDeclarativeComponent::metaObject(void) const @@ -1110,7 +1110,7 @@ EXPORTS ??0QDeclarativeDebugFileReference@@QAE@XZ @ 1109 NONAME ABSENT ; QDeclarativeDebugFileReference::QDeclarativeDebugFileReference(void) ?mapFromItem@QDeclarativeItem@@QBE?AVQScriptValue@@ABV2@MM@Z @ 1110 NONAME ; class QScriptValue QDeclarativeItem::mapFromItem(class QScriptValue const &, float, float) const ?trUtf8@QDeclarativeStateOperation@@SA?AVQString@@PBD0H@Z @ 1111 NONAME ; class QString QDeclarativeStateOperation::trUtf8(char const *, char const *, int) - ?tr@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 1112 NONAME ABSENT ; class QString QPacketProtocol::tr(char const *, char const *, int) + ?tr@QPacketProtocol@@SA?AVQString@@PBD0H@Z @ 1112 NONAME ; class QString QPacketProtocol::tr(char const *, char const *, int) ?d_func@QDeclarativeAnchors@@ABEPBVQDeclarativeAnchorsPrivate@@XZ @ 1113 NONAME ABSENT ; class QDeclarativeAnchorsPrivate const * QDeclarativeAnchors::d_func(void) const ?setNotifySignal@QMetaPropertyBuilder@@QAEXABVQMetaMethodBuilder@@@Z @ 1114 NONAME ABSENT ; void QMetaPropertyBuilder::setNotifySignal(class QMetaMethodBuilder const &) ?enabled@QDeclarativeBehavior@@QBE_NXZ @ 1115 NONAME ABSENT ; bool QDeclarativeBehavior::enabled(void) const @@ -1132,7 +1132,7 @@ EXPORTS ?noCreationReason@QDeclarativeType@@QBE?AVQString@@XZ @ 1131 NONAME ABSENT ; class QString QDeclarativeType::noCreationReason(void) const ?setUrl@QDeclarativeDebugFileReference@@QAEXABVQUrl@@@Z @ 1132 NONAME ABSENT ; void QDeclarativeDebugFileReference::setUrl(class QUrl const &) ??1QDeclarativeCustomParserProperty@@QAE@XZ @ 1133 NONAME ; QDeclarativeCustomParserProperty::~QDeclarativeCustomParserProperty(void) - ??1QPacketProtocol@@UAE@XZ @ 1134 NONAME ABSENT ; QPacketProtocol::~QPacketProtocol(void) + ??1QPacketProtocol@@UAE@XZ @ 1134 NONAME ; QPacketProtocol::~QPacketProtocol(void) ??1QDeclarativeAbstractBinding@@MAE@XZ @ 1135 NONAME ABSENT ; QDeclarativeAbstractBinding::~QDeclarativeAbstractBinding(void) ?indexOfEnumerator@QMetaObjectBuilder@@QAEHABVQByteArray@@@Z @ 1136 NONAME ABSENT ; int QMetaObjectBuilder::indexOfEnumerator(class QByteArray const &) ?qt_metacast@QDeclarativePen@@UAEPAXPBD@Z @ 1137 NONAME ABSENT ; void * QDeclarativePen::qt_metacast(char const *) @@ -1222,7 +1222,7 @@ EXPORTS ?statusChanged@QDeclarativeComponent@@IAEXW4Status@1@@Z @ 1221 NONAME ; void QDeclarativeComponent::statusChanged(enum QDeclarativeComponent::Status) ?setTarget@QDeclarativeBinding@@QAEXABVQDeclarativeProperty@@@Z @ 1222 NONAME ABSENT ; void QDeclarativeBinding::setTarget(class QDeclarativeProperty const &) ?imageProvider@QDeclarativeEngine@@QBEPAVQDeclarativeImageProvider@@ABVQString@@@Z @ 1223 NONAME ; class QDeclarativeImageProvider * QDeclarativeEngine::imageProvider(class QString const &) const - ?packetsAvailable@QPacketProtocol@@QBE_JXZ @ 1224 NONAME ABSENT ; long long QPacketProtocol::packetsAvailable(void) const + ?packetsAvailable@QPacketProtocol@@QBE_JXZ @ 1224 NONAME ; long long QPacketProtocol::packetsAvailable(void) const ?state@QDeclarativeDebugWatch@@QBE?AW4State@1@XZ @ 1225 NONAME ABSENT ; enum QDeclarativeDebugWatch::State QDeclarativeDebugWatch::state(void) const ?attachedPropertiesFuncById@QDeclarativeMetaType@@SAP6APAVQObject@@PAV2@@ZH@Z @ 1226 NONAME ABSENT ; class QObject * (*)(class QObject *) QDeclarativeMetaType::attachedPropertiesFuncById(int) ?resetBaseline@QDeclarativeAnchors@@QAEXXZ @ 1227 NONAME ABSENT ; void QDeclarativeAnchors::resetBaseline(void) @@ -1341,7 +1341,7 @@ EXPORTS ?implicitWidth@QDeclarativeItem@@QBEMXZ @ 1340 NONAME ; float QDeclarativeItem::implicitWidth(void) const ?metaObject@QDeclarativeContext@@UBEPBUQMetaObject@@XZ @ 1341 NONAME ; struct QMetaObject const * QDeclarativeContext::metaObject(void) const ??0QDeclarativeContext@@AAE@PAVQDeclarativeContextData@@@Z @ 1342 NONAME ; QDeclarativeContext::QDeclarativeContext(class QDeclarativeContextData *) - ?maximumPacketSize@QPacketProtocol@@QBEHXZ @ 1343 NONAME ABSENT ; int QPacketProtocol::maximumPacketSize(void) const + ?maximumPacketSize@QPacketProtocol@@QBEHXZ @ 1343 NONAME ; int QPacketProtocol::maximumPacketSize(void) const ??_EQDeclarativeDebuggerStatus@@UAE@I@Z @ 1344 NONAME ABSENT ; QDeclarativeDebuggerStatus::~QDeclarativeDebuggerStatus(unsigned int) ?error@QDeclarativeCustomParser@@IAEXABVQString@@@Z @ 1345 NONAME ; void QDeclarativeCustomParser::error(class QString const &) ?messageReceived@QDeclarativeDebugService@@MAEXABVQByteArray@@@Z @ 1346 NONAME ABSENT ; void QDeclarativeDebugService::messageReceived(class QByteArray const &) @@ -1389,12 +1389,12 @@ EXPORTS ?setEnabled@QDeclarativeDebugClient@@QAEX_N@Z @ 1388 NONAME ABSENT ; void QDeclarativeDebugClient::setEnabled(bool) ??1QMetaObjectBuilder@@UAE@XZ @ 1389 NONAME ABSENT ; QMetaObjectBuilder::~QMetaObjectBuilder(void) ?tr@QDeclarativeStateOperation@@SA?AVQString@@PBD0@Z @ 1390 NONAME ; class QString QDeclarativeStateOperation::tr(char const *, char const *) - ?clear@QPacket@@QAEXXZ @ 1391 NONAME ABSENT ; void QPacket::clear(void) + ?clear@QPacket@@QAEXXZ @ 1391 NONAME ; void QPacket::clear(void) ?getStaticMetaObject@QDeclarativeDebugClient@@SAABUQMetaObject@@XZ @ 1392 NONAME ABSENT ; struct QMetaObject const & QDeclarativeDebugClient::getStaticMetaObject(void) ??0QDeclarativeDomList@@QAE@ABV0@@Z @ 1393 NONAME ABSENT ; QDeclarativeDomList::QDeclarativeDomList(class QDeclarativeDomList const &) ?gridTop@QDeclarativeGridScaledImage@@QBEHXZ @ 1394 NONAME ABSENT ; int QDeclarativeGridScaledImage::gridTop(void) const ?setUrl@QDeclarativeError@@QAEXABVQUrl@@@Z @ 1395 NONAME ; void QDeclarativeError::setUrl(class QUrl const &) - ?setMaximumPacketSize@QPacketProtocol@@QAEHH@Z @ 1396 NONAME ABSENT ; int QPacketProtocol::setMaximumPacketSize(int) + ?setMaximumPacketSize@QPacketProtocol@@QAEHH@Z @ 1396 NONAME ; int QPacketProtocol::setMaximumPacketSize(int) ??_EQDeclarativeAction@@QAE@I@Z @ 1397 NONAME ABSENT ; QDeclarativeAction::~QDeclarativeAction(unsigned int) ?trUtf8@QDeclarativeDebugWatch@@SA?AVQString@@PBD0@Z @ 1398 NONAME ABSENT ; class QString QDeclarativeDebugWatch::trUtf8(char const *, char const *) ?read@QDeclarativeProperty@@SA?AVQVariant@@PAVQObject@@ABVQString@@@Z @ 1399 NONAME ; class QVariant QDeclarativeProperty::read(class QObject *, class QString const &) @@ -1472,7 +1472,7 @@ EXPORTS ?signalExpression@QDeclarativePropertyPrivate@@SAPAVQDeclarativeExpression@@ABVQDeclarativeProperty@@@Z @ 1471 NONAME ABSENT ; class QDeclarativeExpression * QDeclarativePropertyPrivate::signalExpression(class QDeclarativeProperty const &) ?networkAccessManagerFactory@QDeclarativeEngine@@QBEPAVQDeclarativeNetworkAccessManagerFactory@@XZ @ 1472 NONAME ; class QDeclarativeNetworkAccessManagerFactory * QDeclarativeEngine::networkAccessManagerFactory(void) const ?isStringList@Variant@QDeclarativeParser@@QBE_NXZ @ 1473 NONAME ; bool QDeclarativeParser::Variant::isStringList(void) const - ?packetWritten@QPacketProtocol@@IAEXXZ @ 1474 NONAME ABSENT ; void QPacketProtocol::packetWritten(void) + ?packetWritten@QPacketProtocol@@IAEXXZ @ 1474 NONAME ; void QPacketProtocol::packetWritten(void) ?getStaticMetaObject@QDeclarativeDebugObjectQuery@@SAABUQMetaObject@@XZ @ 1475 NONAME ABSENT ; struct QMetaObject const & QDeclarativeDebugObjectQuery::getStaticMetaObject(void) ?isSignalProperty@QDeclarativeProperty@@QBE_NXZ @ 1476 NONAME ; bool QDeclarativeProperty::isSignalProperty(void) const ?d_func@QDeclarativeDebugService@@AAEPAVQDeclarativeDebugServicePrivate@@XZ @ 1477 NONAME ABSENT ; class QDeclarativeDebugServicePrivate * QDeclarativeDebugService::d_func(void) @@ -1488,7 +1488,7 @@ EXPORTS ?qt_metacast@QDeclarativePropertyMap@@UAEPAXPBD@Z @ 1487 NONAME ; void * QDeclarativePropertyMap::qt_metacast(char const *) ?classBegin@QDeclarativeAnchors@@QAEXXZ @ 1488 NONAME ABSENT ; void QDeclarativeAnchors::classBegin(void) ?color@QDeclarativeText@@QBE?AVQColor@@XZ @ 1489 NONAME ABSENT ; class QColor QDeclarativeText::color(void) const - ?metaObject@QPacketProtocol@@UBEPBUQMetaObject@@XZ @ 1490 NONAME ABSENT ; struct QMetaObject const * QPacketProtocol::metaObject(void) const + ?metaObject@QPacketProtocol@@UBEPBUQMetaObject@@XZ @ 1490 NONAME ; struct QMetaObject const * QPacketProtocol::metaObject(void) const ??4QDeclarativeGridScaledImage@@QAEAAV0@ABV0@@Z @ 1491 NONAME ABSENT ; class QDeclarativeGridScaledImage & QDeclarativeGridScaledImage::operator=(class QDeclarativeGridScaledImage const &) ?tr@QDeclarativeScaleGrid@@SA?AVQString@@PBD0@Z @ 1492 NONAME ABSENT ; class QString QDeclarativeScaleGrid::tr(char const *, char const *) ??1QDeclarativeScriptString@@QAE@XZ @ 1493 NONAME ; QDeclarativeScriptString::~QDeclarativeScriptString(void) @@ -1619,7 +1619,7 @@ EXPORTS ?metaObject@QDeclarativeItem@@UBEPBUQMetaObject@@XZ @ 1618 NONAME ; struct QMetaObject const * QDeclarativeItem::metaObject(void) const ?clear@QDeclarativeAbstractBinding@@IAEXXZ @ 1619 NONAME ABSENT ; void QDeclarativeAbstractBinding::clear(void) ?start@QDeclarativeItemPrivate@@SAXAAVQElapsedTimer@@@Z @ 1620 NONAME ; void QDeclarativeItemPrivate::start(class QElapsedTimer &) - ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@ABVQSize@@_N@Z @ 1621 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QSize const &, bool) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@ABVQSize@@_N@Z @ 1621 NONAME ABSENT ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QSize const &, bool) ?stringToRule@QDeclarativeGridScaledImage@@CA?AW4TileMode@QDeclarativeBorderImage@@ABVQString@@@Z @ 1622 NONAME ABSENT ; enum QDeclarativeBorderImage::TileMode QDeclarativeGridScaledImage::stringToRule(class QString const &) ?setHorizontalCenter@QDeclarativeAnchors@@QAEXABVQDeclarativeAnchorLine@@@Z @ 1623 NONAME ABSENT ; void QDeclarativeAnchors::setHorizontalCenter(class QDeclarativeAnchorLine const &) ?setFocus@QDeclarativeItem@@QAEX_N@Z @ 1624 NONAME ; void QDeclarativeItem::setFocus(bool) @@ -1631,7 +1631,7 @@ EXPORTS ??0QDeclarativeContext@@AAE@PAVQDeclarativeEngine@@_N@Z @ 1630 NONAME ; QDeclarativeContext::QDeclarativeContext(class QDeclarativeEngine *, bool) ?initialValue@QDeclarativeOpenMetaObject@@UAE?AVQVariant@@H@Z @ 1631 NONAME ABSENT ; class QVariant QDeclarativeOpenMetaObject::initialValue(int) ?tr@QDeclarativeView@@SA?AVQString@@PBD0@Z @ 1632 NONAME ; class QString QDeclarativeView::tr(char const *, char const *) - ?qt_metacall@QPacketProtocol@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1633 NONAME ABSENT ; int QPacketProtocol::qt_metacall(enum QMetaObject::Call, int, void * *) + ?qt_metacall@QPacketProtocol@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1633 NONAME ; int QPacketProtocol::qt_metacall(enum QMetaObject::Call, int, void * *) ??0QDeclarativeItem@@QAE@PAV0@@Z @ 1634 NONAME ; QDeclarativeItem::QDeclarativeItem(class QDeclarativeItem *) ?hasDebuggingClient@QDeclarativeDebugService@@SA_NXZ @ 1635 NONAME ABSENT ; bool QDeclarativeDebugService::hasDebuggingClient(void) ?staticMetaObject@QDeclarativeContext@@2UQMetaObject@@B @ 1636 NONAME ; struct QMetaObject const QDeclarativeContext::staticMetaObject @@ -1645,15 +1645,15 @@ EXPORTS ??_EQDeclarativePropertyChanges@@UAE@I@Z @ 1644 NONAME ABSENT ; QDeclarativePropertyChanges::~QDeclarativePropertyChanges(unsigned int) ?setObject@QDeclarativePropertyChanges@@QAEXPAVQObject@@@Z @ 1645 NONAME ABSENT ; void QDeclarativePropertyChanges::setObject(class QObject *) ?staticMetaObject@QDeclarativePropertyChanges@@2UQMetaObject@@B @ 1646 NONAME ABSENT ; struct QMetaObject const QDeclarativePropertyChanges::staticMetaObject - ?removeEntryFromRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@@Z @ 1647 NONAME ; bool QDeclarativeState::removeEntryFromRevertList(class QObject *, class QByteArray const &) + ?removeEntryFromRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@@Z @ 1647 NONAME ABSENT ; bool QDeclarativeState::removeEntryFromRevertList(class QObject *, class QByteArray const &) ?restoreEntryValues@QDeclarativePropertyChanges@@QBE_NXZ @ 1648 NONAME ABSENT ; bool QDeclarativePropertyChanges::restoreEntryValues(void) const ?setRestoreEntryValues@QDeclarativePropertyChanges@@QAEX_N@Z @ 1649 NONAME ABSENT ; void QDeclarativePropertyChanges::setRestoreEntryValues(bool) ?changeValue@QDeclarativePropertyChanges@@QAEXABVQByteArray@@ABVQVariant@@@Z @ 1650 NONAME ABSENT ; void QDeclarativePropertyChanges::changeValue(class QByteArray const &, class QVariant const &) ?metaObject@QDeclarativePropertyChanges@@UBEPBUQMetaObject@@XZ @ 1651 NONAME ABSENT ; struct QMetaObject const * QDeclarativePropertyChanges::metaObject(void) const ?data_clear@QDeclarativeItemPrivate@@SAXPAV?$QDeclarativeListProperty@VQObject@@@@@Z @ 1652 NONAME ; void QDeclarativeItemPrivate::data_clear(class QDeclarativeListProperty<class QObject> *) - ?containsPropertyInRevertList@QDeclarativeState@@QBE_NPAVQObject@@ABVQByteArray@@@Z @ 1653 NONAME ; bool QDeclarativeState::containsPropertyInRevertList(class QObject *, class QByteArray const &) const + ?containsPropertyInRevertList@QDeclarativeState@@QBE_NPAVQObject@@ABVQByteArray@@@Z @ 1653 NONAME ABSENT ; bool QDeclarativeState::containsPropertyInRevertList(class QObject *, class QByteArray const &) const ?containsValue@QDeclarativePropertyChanges@@QBE_NABVQByteArray@@@Z @ 1654 NONAME ABSENT ; bool QDeclarativePropertyChanges::containsValue(class QByteArray const &) const - ?bindingInRevertList@QDeclarativeState@@QBEPAVQDeclarativeAbstractBinding@@PAVQObject@@ABVQByteArray@@@Z @ 1655 NONAME ; class QDeclarativeAbstractBinding * QDeclarativeState::bindingInRevertList(class QObject *, class QByteArray const &) const + ?bindingInRevertList@QDeclarativeState@@QBEPAVQDeclarativeAbstractBinding@@PAVQObject@@ABVQByteArray@@@Z @ 1655 NONAME ABSENT ; class QDeclarativeAbstractBinding * QDeclarativeState::bindingInRevertList(class QObject *, class QByteArray const &) const ?d_func@QDeclarativePropertyChanges@@ABEPBVQDeclarativePropertyChangesPrivate@@XZ @ 1656 NONAME ABSENT ; class QDeclarativePropertyChangesPrivate const * QDeclarativePropertyChanges::d_func(void) const ?containsProperty@QDeclarativePropertyChanges@@QBE_NABVQByteArray@@@Z @ 1657 NONAME ABSENT ; bool QDeclarativePropertyChanges::containsProperty(class QByteArray const &) const ?trUtf8@QDeclarativePropertyChanges@@SA?AVQString@@PBD0H@Z @ 1658 NONAME ABSENT ; class QString QDeclarativePropertyChanges::trUtf8(char const *, char const *, int) @@ -1677,17 +1677,17 @@ EXPORTS ?addEntriesToRevertList@QDeclarativeState@@QAEXABV?$QList@VQDeclarativeAction@@@@@Z @ 1676 NONAME ; void QDeclarativeState::addEntriesToRevertList(class QList<class QDeclarativeAction> const &) ?expression@QDeclarativePropertyChanges@@QBE?AVQString@@ABVQByteArray@@@Z @ 1677 NONAME ABSENT ; class QString QDeclarativePropertyChanges::expression(class QByteArray const &) const ?object@QDeclarativePropertyChanges@@QBEPAVQObject@@XZ @ 1678 NONAME ABSENT ; class QObject * QDeclarativePropertyChanges::object(void) const - ?valueInRevertList@QDeclarativeState@@QBE?AVQVariant@@PAVQObject@@ABVQByteArray@@@Z @ 1679 NONAME ; class QVariant QDeclarativeState::valueInRevertList(class QObject *, class QByteArray const &) const + ?valueInRevertList@QDeclarativeState@@QBE?AVQVariant@@PAVQObject@@ABVQByteArray@@@Z @ 1679 NONAME ABSENT ; class QVariant QDeclarativeState::valueInRevertList(class QObject *, class QByteArray const &) const ?removeAllEntriesFromRevertList@QDeclarativeState@@QAEXPAVQObject@@@Z @ 1680 NONAME ; void QDeclarativeState::removeAllEntriesFromRevertList(class QObject *) ?d_func@QDeclarativeStateOperation@@AAEPAVQDeclarativeStateOperationPrivate@@XZ @ 1681 NONAME ; class QDeclarativeStateOperationPrivate * QDeclarativeStateOperation::d_func(void) - ?changeValueInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@ABVQVariant@@@Z @ 1682 NONAME ; bool QDeclarativeState::changeValueInRevertList(class QObject *, class QByteArray const &, class QVariant const &) + ?changeValueInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@ABVQVariant@@@Z @ 1682 NONAME ABSENT ; bool QDeclarativeState::changeValueInRevertList(class QObject *, class QByteArray const &, class QVariant const &) ?setIsExplicit@QDeclarativePropertyChanges@@QAEX_N@Z @ 1683 NONAME ABSENT ; void QDeclarativePropertyChanges::setIsExplicit(bool) ?isStateActive@QDeclarativeState@@QBE_NXZ @ 1684 NONAME ; bool QDeclarativeState::isStateActive(void) const ?data_count@QDeclarativeItemPrivate@@SAHPAV?$QDeclarativeListProperty@VQObject@@@@@Z @ 1685 NONAME ; int QDeclarativeItemPrivate::data_count(class QDeclarativeListProperty<class QObject> *) ?removeProperty@QDeclarativePropertyChanges@@QAEXABVQByteArray@@@Z @ 1686 NONAME ABSENT ; void QDeclarativePropertyChanges::removeProperty(class QByteArray const &) ?data_at@QDeclarativeItemPrivate@@SAPAVQObject@@PAV?$QDeclarativeListProperty@VQObject@@@@H@Z @ 1687 NONAME ; class QObject * QDeclarativeItemPrivate::data_at(class QDeclarativeListProperty<class QObject> *, int) ?tr@QDeclarativePropertyChanges@@SA?AVQString@@PBD0@Z @ 1688 NONAME ABSENT ; class QString QDeclarativePropertyChanges::tr(char const *, char const *) - ?changeBindingInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@PAVQDeclarativeAbstractBinding@@@Z @ 1689 NONAME ; bool QDeclarativeState::changeBindingInRevertList(class QObject *, class QByteArray const &, class QDeclarativeAbstractBinding *) + ?changeBindingInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQByteArray@@PAVQDeclarativeAbstractBinding@@@Z @ 1689 NONAME ABSENT ; bool QDeclarativeState::changeBindingInRevertList(class QObject *, class QByteArray const &, class QDeclarativeAbstractBinding *) ?getStaticMetaObject@QDeclarativePropertyChanges@@SAABUQMetaObject@@XZ @ 1690 NONAME ABSENT ; struct QMetaObject const & QDeclarativePropertyChanges::getStaticMetaObject(void) ?weakPointer@QDeclarativeAbstractBinding@@QAE?AV?$QWeakPointer@VQDeclarativeAbstractBinding@@@@XZ @ 1691 NONAME ABSENT ; class QWeakPointer<class QDeclarativeAbstractBinding> QDeclarativeAbstractBinding::weakPointer(void) ?getStaticMetaObject@QDeclarativeScriptAction@@SAABUQMetaObject@@XZ @ 1692 NONAME ABSENT ; struct QMetaObject const & QDeclarativeScriptAction::getStaticMetaObject(void) @@ -1840,4 +1840,52 @@ EXPORTS ?qt_metacall@QDeclarativeAbstractAnimation@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1839 NONAME ABSENT ; int QDeclarativeAbstractAnimation::qt_metacall(enum QMetaObject::Call, int, void * *) ?enableDebugging@QDeclarativeDebugHelper@@SAXXZ @ 1840 NONAME ; void QDeclarativeDebugHelper::enableDebugging(void) ?connect@QDeclarativePropertyPrivate@@SA_NPBVQObject@@H0HHPAH@Z @ 1841 NONAME ABSENT ; bool QDeclarativePropertyPrivate::connect(class QObject const *, int, class QObject const *, int, int, int *) + ?qt_metacall@QDeclarativeDebugServer@@UAEHW4Call@QMetaObject@@HPAPAX@Z @ 1842 NONAME ; int QDeclarativeDebugServer::qt_metacall(enum QMetaObject::Call, int, void * *) + ?implicitHeight@QDeclarativeItemPrivate@@UBEMXZ @ 1843 NONAME ; float QDeclarativeItemPrivate::implicitHeight(void) const + ?instance@QDeclarativeDebugServer@@SAPAV1@XZ @ 1844 NONAME ; class QDeclarativeDebugServer * QDeclarativeDebugServer::instance(void) + ?addService@QDeclarativeDebugServer@@QAE_NPAVQDeclarativeDebugService@@@Z @ 1845 NONAME ; bool QDeclarativeDebugServer::addService(class QDeclarativeDebugService *) + ?containsPropertyInRevertList@QDeclarativeState@@QBE_NPAVQObject@@ABVQString@@@Z @ 1846 NONAME ; bool QDeclarativeState::containsPropertyInRevertList(class QObject *, class QString const &) const + ?data@QPacket@@QBE?AVQByteArray@@XZ @ 1847 NONAME ; class QByteArray QPacket::data(void) const + ?removeService@QDeclarativeDebugServer@@QAE_NPAVQDeclarativeDebugService@@@Z @ 1848 NONAME ; bool QDeclarativeDebugServer::removeService(class QDeclarativeDebugService *) + ?serviceNames@QDeclarativeDebugServer@@QBE?AVQStringList@@XZ @ 1849 NONAME ; class QStringList QDeclarativeDebugServer::serviceNames(void) const + ??_EQDeclarativeDebugServer@@UAE@I@Z @ 1850 NONAME ; QDeclarativeDebugServer::~QDeclarativeDebugServer(unsigned int) + ?staticMetaObject@QDeclarativeDebugServer@@2UQMetaObject@@B @ 1851 NONAME ; struct QMetaObject const QDeclarativeDebugServer::staticMetaObject + ?services@QDeclarativeDebugServer@@QBE?AV?$QList@PAVQDeclarativeDebugService@@@@XZ @ 1852 NONAME ; class QList<class QDeclarativeDebugService *> QDeclarativeDebugServer::services(void) const + ?rewriteBinding@QDeclarativeCustomParser@@IAEHABVQString@@ABVQByteArray@@@Z @ 1853 NONAME ; int QDeclarativeCustomParser::rewriteBinding(class QString const &, class QByteArray const &) + ?changeValueInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQString@@ABVQVariant@@@Z @ 1854 NONAME ; bool QDeclarativeState::changeValueInRevertList(class QObject *, class QString const &, class QVariant const &) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@ABVQSize@@V?$QFlags@W4Option@QDeclarativePixmap@@@@@Z @ 1855 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QSize const &, class QFlags<enum QDeclarativePixmap::Option>) + ?implicitHeightChanged@QDeclarativeItemPrivate@@UAEXXZ @ 1856 NONAME ; void QDeclarativeItemPrivate::implicitHeightChanged(void) + ?implicitWidthChanged@QDeclarativeItem@@IAEXXZ @ 1857 NONAME ; void QDeclarativeItem::implicitWidthChanged(void) + ?implicitWidthChanged@QDeclarativeItemPrivate@@UAEXXZ @ 1858 NONAME ; void QDeclarativeItemPrivate::implicitWidthChanged(void) + ?trUtf8@QDeclarativeDebugServer@@SA?AVQString@@PBD0H@Z @ 1859 NONAME ; class QString QDeclarativeDebugServer::trUtf8(char const *, char const *, int) + ?implicitHeightChanged@QDeclarativeItem@@IAEXXZ @ 1860 NONAME ; void QDeclarativeItem::implicitHeightChanged(void) + ?load@QDeclarativePixmap@@QAEXPAVQDeclarativeEngine@@ABVQUrl@@V?$QFlags@W4Option@QDeclarativePixmap@@@@@Z @ 1861 NONAME ; void QDeclarativePixmap::load(class QDeclarativeEngine *, class QUrl const &, class QFlags<enum QDeclarativePixmap::Option>) + ?trUtf8@QDeclarativeDebugServer@@SA?AVQString@@PBD0@Z @ 1862 NONAME ; class QString QDeclarativeDebugServer::trUtf8(char const *, char const *) + ??_EQDeclarativeDebugServerConnection@@UAE@I@Z @ 1863 NONAME ; QDeclarativeDebugServerConnection::~QDeclarativeDebugServerConnection(unsigned int) + ?receiveMessage@QDeclarativeDebugServer@@QAEXABVQByteArray@@@Z @ 1864 NONAME ; void QDeclarativeDebugServer::receiveMessage(class QByteArray const &) + ??0QDeclarativeDebugServer@@AAE@XZ @ 1865 NONAME ; QDeclarativeDebugServer::QDeclarativeDebugServer(void) + ?tr@QDeclarativeDebugServer@@SA?AVQString@@PBD0@Z @ 1866 NONAME ; class QString QDeclarativeDebugServer::tr(char const *, char const *) + ??1QDeclarativeDebugServer@@UAE@XZ @ 1867 NONAME ; QDeclarativeDebugServer::~QDeclarativeDebugServer(void) + ?sendMessage@QDeclarativeDebugServer@@QAEXPAVQDeclarativeDebugService@@ABVQByteArray@@@Z @ 1868 NONAME ; void QDeclarativeDebugServer::sendMessage(class QDeclarativeDebugService *, class QByteArray const &) + ??1QDeclarativeDebugServerConnection@@UAE@XZ @ 1869 NONAME ; QDeclarativeDebugServerConnection::~QDeclarativeDebugServerConnection(void) + ?qt_metacast@QDeclarativeDebugServer@@UAEPAXPBD@Z @ 1870 NONAME ; void * QDeclarativeDebugServer::qt_metacast(char const *) + ?hasDebuggingClient@QDeclarativeDebugServer@@QBE_NXZ @ 1871 NONAME ; bool QDeclarativeDebugServer::hasDebuggingClient(void) const + ?bindingInRevertList@QDeclarativeState@@QBEPAVQDeclarativeAbstractBinding@@PAVQObject@@ABVQString@@@Z @ 1872 NONAME ; class QDeclarativeAbstractBinding * QDeclarativeState::bindingInRevertList(class QObject *, class QString const &) const + ?getStaticMetaObject@QDeclarativeDebugServer@@SAABUQMetaObject@@XZ @ 1873 NONAME ; struct QMetaObject const & QDeclarativeDebugServer::getStaticMetaObject(void) + ?metaObject@QDeclarativeDebugServer@@UBEPBUQMetaObject@@XZ @ 1874 NONAME ; struct QMetaObject const * QDeclarativeDebugServer::metaObject(void) const + ?d_func@QDeclarativeDebugServer@@ABEPBVQDeclarativeDebugServerPrivate@@XZ @ 1875 NONAME ; class QDeclarativeDebugServerPrivate const * QDeclarativeDebugServer::d_func(void) const + ??0QDeclarativeExpression@@IAE@PAVQDeclarativeContextData@@PAVQObject@@ABVQScriptValue@@AAVQDeclarativeExpressionPrivate@@@Z @ 1876 NONAME ; QDeclarativeExpression::QDeclarativeExpression(class QDeclarativeContextData *, class QObject *, class QScriptValue const &, class QDeclarativeExpressionPrivate &) + ?createObject@QDeclarativeComponent@@IAE?AVQScriptValue@@PAVQObject@@ABV2@@Z @ 1877 NONAME ; class QScriptValue QDeclarativeComponent::createObject(class QObject *, class QScriptValue const &) + ?changeBindingInRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQString@@PAVQDeclarativeAbstractBinding@@@Z @ 1878 NONAME ; bool QDeclarativeState::changeBindingInRevertList(class QObject *, class QString const &, class QDeclarativeAbstractBinding *) + ??0QDeclarativeDebugServerConnection@@QAE@XZ @ 1879 NONAME ; QDeclarativeDebugServerConnection::QDeclarativeDebugServerConnection(void) + ?valueInRevertList@QDeclarativeState@@QBE?AVQVariant@@PAVQObject@@ABVQString@@@Z @ 1880 NONAME ; class QVariant QDeclarativeState::valueInRevertList(class QObject *, class QString const &) const + ?removeEntryFromRevertList@QDeclarativeState@@QAE_NPAVQObject@@ABVQString@@@Z @ 1881 NONAME ; bool QDeclarativeState::removeEntryFromRevertList(class QObject *, class QString const &) + ?d_func@QDeclarativeDebugServer@@AAEPAVQDeclarativeDebugServerPrivate@@XZ @ 1882 NONAME ; class QDeclarativeDebugServerPrivate * QDeclarativeDebugServer::d_func(void) + ?tr@QDeclarativeDebugServer@@SA?AVQString@@PBD0H@Z @ 1883 NONAME ; class QString QDeclarativeDebugServer::tr(char const *, char const *, int) + ?implicitWidth@QDeclarativeItemPrivate@@UBEMXZ @ 1884 NONAME ; float QDeclarativeItemPrivate::implicitWidth(void) const + ??_EQDeclarativeRefCount@@UAE@I@Z @ 1885 NONAME ; QDeclarativeRefCount::~QDeclarativeRefCount(unsigned int) + ??0QDeclarativeRefCount@@QAE@XZ @ 1886 NONAME ; QDeclarativeRefCount::QDeclarativeRefCount(void) + ??1QDeclarativeRefCount@@UAE@XZ @ 1887 NONAME ; QDeclarativeRefCount::~QDeclarativeRefCount(void) + ?addref@QDeclarativeRefCount@@QAEXXZ @ 1888 NONAME ; void QDeclarativeRefCount::addref(void) + ?release@QDeclarativeRefCount@@QAEXXZ @ 1889 NONAME ; void QDeclarativeRefCount::release(void) diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def index 322d88b..9b4c0f7 100644 --- a/src/s60installs/bwins/QtGuiu.def +++ b/src/s60installs/bwins/QtGuiu.def @@ -13142,4 +13142,10 @@ EXPORTS ?viewportSize@QScrollPrepareEvent@@QBE?AVQSizeF@@XZ @ 13141 NONAME ; class QSizeF QScrollPrepareEvent::viewportSize(void) const ?staticMetaObject@QScroller@@2UQMetaObject@@B @ 13142 NONAME ; struct QMetaObject const QScroller::staticMetaObject ?staticMetaObject@QFlickGesture@@2UQMetaObject@@B @ 13143 NONAME ; struct QMetaObject const QFlickGesture::staticMetaObject - + ?isDragEnabled@QTextControl@@QBE_NXZ @ 13144 NONAME ; bool QTextControl::isDragEnabled(void) const + ?setWordSelectionEnabled@QTextControl@@QAEX_N@Z @ 13145 NONAME ; void QTextControl::setWordSelectionEnabled(bool) + ?setDragEnabled@QTextControl@@QAEX_N@Z @ 13146 NONAME ; void QTextControl::setDragEnabled(bool) + ?isWordSelectionEnabled@QTextControl@@QBE_NXZ @ 13147 NONAME ; bool QTextControl::isWordSelectionEnabled(void) const + ?ProcessCommandParametersL@QS60MainAppUi@@UAEHW4TApaCommand@@AAV?$TBuf@$0BAA@@@ABVTDesC8@@@Z @ 13148 NONAME ; int QS60MainAppUi::ProcessCommandParametersL(enum TApaCommand, class TBuf<256> &, class TDesC8 const &) + ?openFile@QFileOpenEvent@@QBE_NAAVQFile@@V?$QFlags@W4OpenModeFlag@QIODevice@@@@@Z @ 13149 NONAME ; bool QFileOpenEvent::openFile(class QFile &, class QFlags<enum QIODevice::OpenModeFlag>) const + ??0QFileOpenEvent@@QAE@ABVRFile@@@Z @ 13150 NONAME ; QFileOpenEvent::QFileOpenEvent(class RFile const &) diff --git a/src/s60installs/bwins/QtScriptu.def b/src/s60installs/bwins/QtScriptu.def index 9d998ca..02a0819 100644 --- a/src/s60installs/bwins/QtScriptu.def +++ b/src/s60installs/bwins/QtScriptu.def @@ -403,4 +403,6 @@ EXPORTS ??0Value@QScriptDeclarativeClass@@QAE@PAVQScriptContext@@H@Z @ 402 NONAME ; QScriptDeclarativeClass::Value::Value(class QScriptContext *, int) ??0PersistentIdentifier@QScriptDeclarativeClass@@AAE@PAVQScriptEnginePrivate@@@Z @ 403 NONAME ; QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(class QScriptEnginePrivate *) ?compare@QScriptDeclarativeClass@@UAE_NPAUObject@1@0@Z @ 404 NONAME ; bool QScriptDeclarativeClass::compare(struct QScriptDeclarativeClass::Object *, struct QScriptDeclarativeClass::Object *) + ?toString@PersistentIdentifier@QScriptDeclarativeClass@@QBE?AVQString@@XZ @ 405 NONAME ; class QString QScriptDeclarativeClass::PersistentIdentifier::toString(void) const + ?startsWithUpper@QScriptDeclarativeClass@@QAE_NABQAX@Z @ 406 NONAME ; bool QScriptDeclarativeClass::startsWithUpper(void * const const &) diff --git a/src/s60installs/eabi/QtCoreu.def b/src/s60installs/eabi/QtCoreu.def index 0488d0c..207447f 100644 --- a/src/s60installs/eabi/QtCoreu.def +++ b/src/s60installs/eabi/QtCoreu.def @@ -3804,4 +3804,6 @@ EXPORTS _ZN23QCoreApplicationPrivate18symbianCommandLineEv @ 3803 NONAME _ZNK16QXmlStreamWriter8hasErrorEv @ 3804 NONAME _ZNK13QElapsedTimer12nsecsElapsedEv @ 3805 NONAME + _ZNK11QMetaMethod8revisionEv @ 3806 NONAME + _ZNK13QMetaProperty8revisionEv @ 3807 NONAME diff --git a/src/s60installs/eabi/QtDeclarativeu.def b/src/s60installs/eabi/QtDeclarativeu.def index b0efab4..95180d4 100644 --- a/src/s60installs/eabi/QtDeclarativeu.def +++ b/src/s60installs/eabi/QtDeclarativeu.def @@ -19,24 +19,24 @@ EXPORTS _ZN15QPacketAutoSendD0Ev @ 18 NONAME ABSENT _ZN15QPacketAutoSendD1Ev @ 19 NONAME ABSENT _ZN15QPacketAutoSendD2Ev @ 20 NONAME ABSENT - _ZN15QPacketProtocol11qt_metacallEN11QMetaObject4CallEiPPv @ 21 NONAME ABSENT - _ZN15QPacketProtocol11qt_metacastEPKc @ 22 NONAME ABSENT - _ZN15QPacketProtocol13invalidPacketEv @ 23 NONAME ABSENT - _ZN15QPacketProtocol13packetWrittenEv @ 24 NONAME ABSENT - _ZN15QPacketProtocol16staticMetaObjectE @ 25 NONAME DATA 16 ABSENT - _ZN15QPacketProtocol19getStaticMetaObjectEv @ 26 NONAME ABSENT - _ZN15QPacketProtocol20setMaximumPacketSizeEi @ 27 NONAME ABSENT - _ZN15QPacketProtocol4readEv @ 28 NONAME ABSENT - _ZN15QPacketProtocol4sendERK7QPacket @ 29 NONAME ABSENT - _ZN15QPacketProtocol4sendEv @ 30 NONAME ABSENT - _ZN15QPacketProtocol5clearEv @ 31 NONAME ABSENT - _ZN15QPacketProtocol6deviceEv @ 32 NONAME ABSENT - _ZN15QPacketProtocol9readyReadEv @ 33 NONAME ABSENT - _ZN15QPacketProtocolC1EP9QIODeviceP7QObject @ 34 NONAME ABSENT - _ZN15QPacketProtocolC2EP9QIODeviceP7QObject @ 35 NONAME ABSENT - _ZN15QPacketProtocolD0Ev @ 36 NONAME ABSENT - _ZN15QPacketProtocolD1Ev @ 37 NONAME ABSENT - _ZN15QPacketProtocolD2Ev @ 38 NONAME ABSENT + _ZN15QPacketProtocol11qt_metacallEN11QMetaObject4CallEiPPv @ 21 NONAME + _ZN15QPacketProtocol11qt_metacastEPKc @ 22 NONAME + _ZN15QPacketProtocol13invalidPacketEv @ 23 NONAME + _ZN15QPacketProtocol13packetWrittenEv @ 24 NONAME + _ZN15QPacketProtocol16staticMetaObjectE @ 25 NONAME DATA 16 + _ZN15QPacketProtocol19getStaticMetaObjectEv @ 26 NONAME + _ZN15QPacketProtocol20setMaximumPacketSizeEi @ 27 NONAME + _ZN15QPacketProtocol4readEv @ 28 NONAME + _ZN15QPacketProtocol4sendERK7QPacket @ 29 NONAME + _ZN15QPacketProtocol4sendEv @ 30 NONAME + _ZN15QPacketProtocol5clearEv @ 31 NONAME + _ZN15QPacketProtocol6deviceEv @ 32 NONAME + _ZN15QPacketProtocol9readyReadEv @ 33 NONAME + _ZN15QPacketProtocolC1EP9QIODeviceP7QObject @ 34 NONAME + _ZN15QPacketProtocolC2EP9QIODeviceP7QObject @ 35 NONAME + _ZN15QPacketProtocolD0Ev @ 36 NONAME + _ZN15QPacketProtocolD1Ev @ 37 NONAME + _ZN15QPacketProtocolD2Ev @ 38 NONAME _ZN16QDeclarativeInfoC1EP23QDeclarativeInfoPrivate @ 39 NONAME _ZN16QDeclarativeInfoC1ERKS_ @ 40 NONAME _ZN16QDeclarativeInfoC2EP23QDeclarativeInfoPrivate @ 41 NONAME @@ -241,8 +241,8 @@ EXPORTS _ZN18QDeclarativePixmap23connectDownloadProgressEP7QObjecti @ 240 NONAME _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrl @ 241 NONAME _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSize @ 242 NONAME - _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSizeb @ 243 NONAME - _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlb @ 244 NONAME + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSizeb @ 243 NONAME ABSENT + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlb @ 244 NONAME ABSENT _ZN18QDeclarativePixmap5clearEP7QObject @ 245 NONAME _ZN18QDeclarativePixmap5clearEv @ 246 NONAME _ZN18QDeclarativePixmap9setPixmapERK7QPixmap @ 247 NONAME @@ -1059,20 +1059,20 @@ EXPORTS _ZN39QDeclarativeNetworkAccessManagerFactoryD0Ev @ 1058 NONAME _ZN39QDeclarativeNetworkAccessManagerFactoryD1Ev @ 1059 NONAME _ZN39QDeclarativeNetworkAccessManagerFactoryD2Ev @ 1060 NONAME - _ZN7QPacket5clearEv @ 1061 NONAME ABSENT - _ZN7QPacketC1ERK10QByteArray @ 1062 NONAME ABSENT - _ZN7QPacketC1ERKS_ @ 1063 NONAME ABSENT - _ZN7QPacketC1Ev @ 1064 NONAME ABSENT - _ZN7QPacketC2ERK10QByteArray @ 1065 NONAME ABSENT - _ZN7QPacketC2ERKS_ @ 1066 NONAME ABSENT - _ZN7QPacketC2Ev @ 1067 NONAME ABSENT - _ZN7QPacketD0Ev @ 1068 NONAME ABSENT - _ZN7QPacketD1Ev @ 1069 NONAME ABSENT - _ZN7QPacketD2Ev @ 1070 NONAME ABSENT + _ZN7QPacket5clearEv @ 1061 NONAME + _ZN7QPacketC1ERK10QByteArray @ 1062 NONAME + _ZN7QPacketC1ERKS_ @ 1063 NONAME + _ZN7QPacketC1Ev @ 1064 NONAME + _ZN7QPacketC2ERK10QByteArray @ 1065 NONAME + _ZN7QPacketC2ERKS_ @ 1066 NONAME + _ZN7QPacketC2Ev @ 1067 NONAME + _ZN7QPacketD0Ev @ 1068 NONAME + _ZN7QPacketD1Ev @ 1069 NONAME + _ZN7QPacketD2Ev @ 1070 NONAME _ZNK15QDeclarativePen10metaObjectEv @ 1071 NONAME ABSENT - _ZNK15QPacketProtocol10metaObjectEv @ 1072 NONAME ABSENT - _ZNK15QPacketProtocol16packetsAvailableEv @ 1073 NONAME ABSENT - _ZNK15QPacketProtocol17maximumPacketSizeEv @ 1074 NONAME ABSENT + _ZNK15QPacketProtocol10metaObjectEv @ 1072 NONAME + _ZNK15QPacketProtocol16packetsAvailableEv @ 1073 NONAME + _ZNK15QPacketProtocol17maximumPacketSizeEv @ 1074 NONAME _ZNK16QDeclarativeItem10metaObjectEv @ 1075 NONAME _ZNK16QDeclarativeItem10parentItemEv @ 1076 NONAME _ZNK16QDeclarativeItem10widthValidEv @ 1077 NONAME @@ -1524,10 +1524,10 @@ EXPORTS _ZNK36QDeclarativeDomValueValueInterceptor6objectEv @ 1523 NONAME ABSENT _ZNK38QDeclarativeDebugObjectExpressionWatch10expressionEv @ 1524 NONAME ABSENT _ZNK38QDeclarativeDebugObjectExpressionWatch10metaObjectEv @ 1525 NONAME ABSENT - _ZNK7QPacket7isEmptyEv @ 1526 NONAME ABSENT + _ZNK7QPacket7isEmptyEv @ 1526 NONAME _ZTI15QDeclarativePen @ 1527 NONAME ABSENT _ZTI15QPacketAutoSend @ 1528 NONAME ABSENT - _ZTI15QPacketProtocol @ 1529 NONAME ABSENT + _ZTI15QPacketProtocol @ 1529 NONAME _ZTI16QDeclarativeItem @ 1530 NONAME _ZTI16QDeclarativeText @ 1531 NONAME ABSENT _ZTI16QDeclarativeView @ 1532 NONAME @@ -1574,10 +1574,10 @@ EXPORTS _ZTI36QDeclarativePropertyValueInterceptor @ 1573 NONAME _ZTI38QDeclarativeDebugObjectExpressionWatch @ 1574 NONAME ABSENT _ZTI39QDeclarativeNetworkAccessManagerFactory @ 1575 NONAME - _ZTI7QPacket @ 1576 NONAME ABSENT + _ZTI7QPacket @ 1576 NONAME _ZTV15QDeclarativePen @ 1577 NONAME ABSENT _ZTV15QPacketAutoSend @ 1578 NONAME ABSENT - _ZTV15QPacketProtocol @ 1579 NONAME ABSENT + _ZTV15QPacketProtocol @ 1579 NONAME _ZTV16QDeclarativeItem @ 1580 NONAME _ZTV16QDeclarativeText @ 1581 NONAME ABSENT _ZTV16QDeclarativeView @ 1582 NONAME @@ -1623,7 +1623,7 @@ EXPORTS _ZTV36QDeclarativePropertyValueInterceptor @ 1622 NONAME _ZTV38QDeclarativeDebugObjectExpressionWatch @ 1623 NONAME ABSENT _ZTV39QDeclarativeNetworkAccessManagerFactory @ 1624 NONAME - _ZTV7QPacket @ 1625 NONAME ABSENT + _ZTV7QPacket @ 1625 NONAME _ZThn16_N16QDeclarativeItem10classBeginEv @ 1626 NONAME _ZThn16_N16QDeclarativeItem17componentCompleteEv @ 1627 NONAME _ZThn16_N16QDeclarativeItemD0Ev @ 1628 NONAME @@ -1677,9 +1677,9 @@ EXPORTS _ZN23QDeclarativeEngineDebug10newObjectsEv @ 1676 NONAME ABSENT _ZN17QDeclarativeState20addEntryToRevertListERK18QDeclarativeAction @ 1677 NONAME _ZN17QDeclarativeState22addEntriesToRevertListERK5QListI18QDeclarativeActionE @ 1678 NONAME - _ZN17QDeclarativeState23changeValueInRevertListEP7QObjectRK10QByteArrayRK8QVariant @ 1679 NONAME - _ZN17QDeclarativeState25changeBindingInRevertListEP7QObjectRK10QByteArrayP27QDeclarativeAbstractBinding @ 1680 NONAME - _ZN17QDeclarativeState25removeEntryFromRevertListEP7QObjectRK10QByteArray @ 1681 NONAME + _ZN17QDeclarativeState23changeValueInRevertListEP7QObjectRK10QByteArrayRK8QVariant @ 1679 NONAME ABSENT + _ZN17QDeclarativeState25changeBindingInRevertListEP7QObjectRK10QByteArrayP27QDeclarativeAbstractBinding @ 1680 NONAME ABSENT + _ZN17QDeclarativeState25removeEntryFromRevertListEP7QObjectRK10QByteArray @ 1681 NONAME ABSENT _ZN17QDeclarativeState30removeAllEntriesFromRevertListEP7QObject @ 1682 NONAME _ZN23QDeclarativeItemPrivate10data_clearEP24QDeclarativeListPropertyI7QObjectE @ 1683 NONAME _ZN23QDeclarativeItemPrivate10data_countEP24QDeclarativeListPropertyI7QObjectE @ 1684 NONAME @@ -1706,9 +1706,9 @@ EXPORTS _ZN27QDeclarativePropertyChangesD1Ev @ 1705 NONAME ABSENT _ZN27QDeclarativePropertyChangesD2Ev @ 1706 NONAME ABSENT _ZNK17QDeclarativeState13isStateActiveEv @ 1707 NONAME - _ZNK17QDeclarativeState17valueInRevertListEP7QObjectRK10QByteArray @ 1708 NONAME - _ZNK17QDeclarativeState19bindingInRevertListEP7QObjectRK10QByteArray @ 1709 NONAME - _ZNK17QDeclarativeState28containsPropertyInRevertListEP7QObjectRK10QByteArray @ 1710 NONAME + _ZNK17QDeclarativeState17valueInRevertListEP7QObjectRK10QByteArray @ 1708 NONAME ABSENT + _ZNK17QDeclarativeState19bindingInRevertListEP7QObjectRK10QByteArray @ 1709 NONAME ABSENT + _ZNK17QDeclarativeState28containsPropertyInRevertListEP7QObjectRK10QByteArray @ 1710 NONAME ABSENT _ZNK26QDeclarativeStateOperation5stateEv @ 1711 NONAME _ZNK27QDeclarativePropertyChanges10expressionERK10QByteArray @ 1712 NONAME ABSENT _ZNK27QDeclarativePropertyChanges10isExplicitEv @ 1713 NONAME ABSENT @@ -1885,4 +1885,49 @@ EXPORTS _ZThn8_N29QDeclarativeAbstractAnimationD1Ev @ 1884 NONAME ABSENT _ZN23QDeclarativeDebugHelper15enableDebuggingEv @ 1885 NONAME _ZN27QDeclarativePropertyPrivate7connectEPK7QObjectiS2_iiPi @ 1886 NONAME ABSENT + _ZN16QDeclarativeItem20implicitWidthChangedEv @ 1887 NONAME + _ZN16QDeclarativeItem21implicitHeightChangedEv @ 1888 NONAME + _ZN17QDeclarativeState23changeValueInRevertListEP7QObjectRK7QStringRK8QVariant @ 1889 NONAME + _ZN17QDeclarativeState25changeBindingInRevertListEP7QObjectRK7QStringP27QDeclarativeAbstractBinding @ 1890 NONAME + _ZN17QDeclarativeState25removeEntryFromRevertListEP7QObjectRK7QString @ 1891 NONAME + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrl6QFlagsINS_6OptionEE @ 1892 NONAME + _ZN18QDeclarativePixmap4loadEP18QDeclarativeEngineRK4QUrlRK5QSize6QFlagsINS_6OptionEE @ 1893 NONAME + _ZN21QDeclarativeComponent12createObjectEP7QObjectRK12QScriptValue @ 1894 NONAME + _ZN22QDeclarativeExpressionC1EP23QDeclarativeContextDataP7QObjectRK12QScriptValueR29QDeclarativeExpressionPrivate @ 1895 NONAME + _ZN22QDeclarativeExpressionC2EP23QDeclarativeContextDataP7QObjectRK12QScriptValueR29QDeclarativeExpressionPrivate @ 1896 NONAME + _ZN23QDeclarativeDebugServer10addServiceEP24QDeclarativeDebugService @ 1897 NONAME + _ZN23QDeclarativeDebugServer11qt_metacallEN11QMetaObject4CallEiPPv @ 1898 NONAME + _ZN23QDeclarativeDebugServer11qt_metacastEPKc @ 1899 NONAME + _ZN23QDeclarativeDebugServer11sendMessageEP24QDeclarativeDebugServiceRK10QByteArray @ 1900 NONAME + _ZN23QDeclarativeDebugServer13removeServiceEP24QDeclarativeDebugService @ 1901 NONAME + _ZN23QDeclarativeDebugServer14receiveMessageERK10QByteArray @ 1902 NONAME + _ZN23QDeclarativeDebugServer16staticMetaObjectE @ 1903 NONAME DATA 16 + _ZN23QDeclarativeDebugServer19getStaticMetaObjectEv @ 1904 NONAME + _ZN23QDeclarativeDebugServer8instanceEv @ 1905 NONAME + _ZN23QDeclarativeDebugServerC1Ev @ 1906 NONAME + _ZN23QDeclarativeDebugServerC2Ev @ 1907 NONAME + _ZN23QDeclarativeItemPrivate20implicitWidthChangedEv @ 1908 NONAME + _ZN23QDeclarativeItemPrivate21implicitHeightChangedEv @ 1909 NONAME + _ZN24QDeclarativeCustomParser14rewriteBindingERK7QStringRK10QByteArray @ 1910 NONAME + _ZNK17QDeclarativeState17valueInRevertListEP7QObjectRK7QString @ 1911 NONAME + _ZNK17QDeclarativeState19bindingInRevertListEP7QObjectRK7QString @ 1912 NONAME + _ZNK17QDeclarativeState28containsPropertyInRevertListEP7QObjectRK7QString @ 1913 NONAME + _ZNK23QDeclarativeDebugServer10metaObjectEv @ 1914 NONAME + _ZNK23QDeclarativeDebugServer12serviceNamesEv @ 1915 NONAME + _ZNK23QDeclarativeDebugServer18hasDebuggingClientEv @ 1916 NONAME + _ZNK23QDeclarativeDebugServer8servicesEv @ 1917 NONAME + _ZNK23QDeclarativeItemPrivate13implicitWidthEv @ 1918 NONAME + _ZNK23QDeclarativeItemPrivate14implicitHeightEv @ 1919 NONAME + _ZNK7QPacket4dataEv @ 1920 NONAME + _ZTI23QDeclarativeDebugServer @ 1921 NONAME + _ZTV23QDeclarativeDebugServer @ 1922 NONAME + _ZN20QDeclarativeRefCount6addrefEv @ 1923 NONAME + _ZN20QDeclarativeRefCount7releaseEv @ 1924 NONAME + _ZN20QDeclarativeRefCountC1Ev @ 1925 NONAME + _ZN20QDeclarativeRefCountC2Ev @ 1926 NONAME + _ZN20QDeclarativeRefCountD0Ev @ 1927 NONAME + _ZN20QDeclarativeRefCountD1Ev @ 1928 NONAME + _ZN20QDeclarativeRefCountD2Ev @ 1929 NONAME + _ZTI20QDeclarativeRefCount @ 1930 NONAME + _ZTV20QDeclarativeRefCount @ 1931 NONAME diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def index 8064fa3..722dee8 100644 --- a/src/s60installs/eabi/QtGuiu.def +++ b/src/s60installs/eabi/QtGuiu.def @@ -12227,10 +12227,10 @@ EXPORTS _ZTV19QBlitterPaintEngine @ 12226 NONAME _ZTV20QBlittablePixmapData @ 12227 NONAME _Zls6QDebugPK13QSymbianEvent @ 12228 NONAME - _ZN13QS60MainAppUi25ProcessCommandParametersLE11TApaCommandR4TBufILi256EERK6TDesC8 @ 12229 NONAME ABSENT - _ZN14QFileOpenEventC1ERK5RFile @ 12230 NONAME ABSENT - _ZN14QFileOpenEventC2ERK5RFile @ 12231 NONAME ABSENT - _ZNK14QFileOpenEvent8openFileER5QFile6QFlagsIN9QIODevice12OpenModeFlagEE @ 12232 NONAME ABSENT + _ZN13QS60MainAppUi25ProcessCommandParametersLE11TApaCommandR4TBufILi256EERK6TDesC8 @ 12229 NONAME + _ZN14QFileOpenEventC1ERK5RFile @ 12230 NONAME + _ZN14QFileOpenEventC2ERK5RFile @ 12231 NONAME + _ZNK14QFileOpenEvent8openFileER5QFile6QFlagsIN9QIODevice12OpenModeFlagEE @ 12232 NONAME _ZN11QFontEngine16alphaMapForGlyphEj6QFixed @ 12233 NONAME _ZN11QFontEngine16alphaMapForGlyphEj6QFixedRK10QTransform @ 12234 NONAME _Z32qGamma_correct_back_to_linear_csP6QImage @ 12235 NONAME @@ -12333,4 +12333,8 @@ EXPORTS _ZTV19QScrollPrepareEvent @ 12332 NONAME _ZTV19QScrollerProperties @ 12333 NONAME _ZTV9QScroller @ 12334 NONAME + _ZN12QTextControl14setDragEnabledEb @ 12335 NONAME + _ZN12QTextControl23setWordSelectionEnabledEb @ 12336 NONAME + _ZNK12QTextControl13isDragEnabledEv @ 12337 NONAME + _ZNK12QTextControl22isWordSelectionEnabledEv @ 12338 NONAME diff --git a/src/s60installs/eabi/QtScriptu.def b/src/s60installs/eabi/QtScriptu.def index b26f9c7..f7da892 100644 --- a/src/s60installs/eabi/QtScriptu.def +++ b/src/s60installs/eabi/QtScriptu.def @@ -441,4 +441,6 @@ EXPORTS _ZN25QScriptEngineAgentPrivate18didReachBreakpointERKN5QTJSC17DebuggerCallFrameEii @ 440 NONAME _ZNK23QScriptDeclarativeClass12supportsCallEv @ 441 NONAME _ZNK23QScriptDeclarativeClass5Value13toScriptValueEP13QScriptEngine @ 442 NONAME + _ZN23QScriptDeclarativeClass15startsWithUpperERKPv @ 443 NONAME + _ZNK23QScriptDeclarativeClass20PersistentIdentifier8toStringEv @ 444 NONAME diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index cd3102e..1c91422 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -11,23 +11,6 @@ symbian: { isEmpty(QT_LIBINFIX) { TARGET.UID3 = 0x2001E61C - - # Sqlite3 is expected to be already found on phone if infixed configuration is built. - # It is also expected that devices newer than those based on S60 5.0 all have sqlite3.dll. - contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) { - BLD_INF_RULES.prj_exports += \ - "sqlite3.sis /epoc32/data/qt/sis/sqlite3.sis" - symbian-abld|symbian-sbsv2 { - sqlitedeployment = \ - "; Deploy sqlite onto phone that does not have it already" \ - "@\"$${EPOCROOT}epoc32/data/qt/sis/sqlite3.sis\", (0x2002af5f)" - } else { - sqlitedeployment = \ - "; Deploy sqlite onto phone that does not have it already" \ - "@\"$${PWD}/sqlite3.sis\", (0x2002af5f)" - } - qtlibraries.pkg_postrules += sqlitedeployment - } } else { # Always use experimental UID for infixed configuration to avoid UID clash TARGET.UID3 = 0xE001E61C @@ -92,7 +75,7 @@ symbian: { vendorinfo = \ "; Localised Vendor name" \ - "%{\"Nokia, Qt\"}" \ + "%{\"Nokia\"}" \ " " \ "; Unique Vendor name" \ ":\"Nokia, Qt\"" \ @@ -183,10 +166,6 @@ symbian: { contains(QT_CONFIG, openvg) { qtlibraries.files += $$QMAKE_LIBDIR_QT/QtOpenVG$${QT_LIBINFIX}.dll graphicssystems_plugins.files += $$QT_BUILD_TREE/plugins/graphicssystems/qvggraphicssystem$${QT_LIBINFIX}.dll - # OpenVG requires Symbian^3 or later - pkg_platform_dependencies = \ - "[0x20022E6D],0,0,0,{\"S60ProductID\"}" \ - "[0x20032DE7],0,0,0,{\"S60ProductID\"}" } contains(QT_CONFIG, opengl) { diff --git a/src/script/api/qscriptcontext.cpp b/src/script/api/qscriptcontext.cpp index 59ea52d..2468a46 100644 --- a/src/script/api/qscriptcontext.cpp +++ b/src/script/api/qscriptcontext.cpp @@ -299,6 +299,12 @@ QScriptValue QScriptContext::argumentsObject() const //for a js function if (frame->codeBlock() && frame->callee()) { + if (!QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { + // We have a built-in JS host call. + // codeBlock is needed by retrieveArguments(), but since it + // contains junk, we would crash. Return an invalid value for now. + return QScriptValue(); + } JSC::JSValue result = frame->interpreter()->retrieveArguments(frame, JSC::asFunction(frame->callee())); return QScript::scriptEngineFromExec(frame)->scriptValueFromJSCValue(result); } @@ -309,7 +315,8 @@ QScriptValue QScriptContext::argumentsObject() const } //for a native function - if (!frame->optionalCalleeArguments()) { + if (!frame->optionalCalleeArguments() + && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { // Make sure we don't go here for host JSFunctions Q_ASSERT(frame->argumentCount() > 0); //we need at least 'this' otherwise we'll crash later JSC::Arguments* arguments = new (&frame->globalData())JSC::Arguments(frame, JSC::Arguments::NoParameters); frame->setCalleeArguments(arguments); diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index db6b2d7..0f9de1d 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -157,7 +157,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte JSC::Instruction *returnPC = rewindContext->returnPC(); JSC::CodeBlock *codeBlock = frame->codeBlock(); - if (returnPC && codeBlock) { + if (returnPC && codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { #if ENABLE(JIT) unsigned bytecodeOffset = codeBlock->getBytecodeIndex(frame, JSC::ReturnAddressPtr(returnPC)); #else @@ -171,7 +171,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte // Get the filename and the scriptId: JSC::CodeBlock *codeBlock = frame->codeBlock(); - if (codeBlock) { + if (codeBlock && QScriptEnginePrivate::hasValidCodeBlockRegister(frame)) { JSC::SourceProvider *source = codeBlock->source(); scriptId = source->asID(); fileName = source->url(); @@ -181,7 +181,8 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte JSC::JSObject *callee = frame->callee(); if (callee && callee->inherits(&JSC::InternalFunction::info)) functionName = JSC::asInternalFunction(callee)->name(frame); - if (callee && callee->inherits(&JSC::JSFunction::info)) { + if (callee && callee->inherits(&JSC::JSFunction::info) + && !JSC::asFunction(callee)->isHostFunction()) { functionType = QScriptContextInfo::ScriptFunction; JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable(); functionStartLineNumber = body->lineNo(); diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 004e3a5..14ab2eb 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -858,7 +858,8 @@ JSC::JSValue JSC_HOST_CALL functionQsTr(JSC::ExecState *exec, JSC::JSObject*, JS { JSC::ExecState *frame = exec->callerFrame()->removeHostCallFrameFlag(); while (frame) { - if (frame->codeBlock() && frame->codeBlock()->source() + if (frame->codeBlock() && QScriptEnginePrivate::hasValidCodeBlockRegister(frame) + && frame->codeBlock()->source() && !frame->codeBlock()->source()->url().isEmpty()) { context = engine->translationContextFromUrl(frame->codeBlock()->source()->url()); break; @@ -1022,6 +1023,7 @@ QScriptEnginePrivate::~QScriptEnginePrivate() while (!ownedAgents.isEmpty()) delete ownedAgents.takeFirst(); + detachAllRegisteredScriptPrograms(); detachAllRegisteredScriptValues(); detachAllRegisteredScriptStrings(); qDeleteAll(m_qobjectData); @@ -1576,6 +1578,14 @@ bool QScriptEnginePrivate::scriptDisconnect(JSC::JSValue signal, JSC::JSValue re #endif +void QScriptEnginePrivate::detachAllRegisteredScriptPrograms() +{ + QSet<QScriptProgramPrivate*>::const_iterator it; + for (it = registeredScriptPrograms.constBegin(); it != registeredScriptPrograms.constEnd(); ++it) + (*it)->detachFromEngine(); + registeredScriptPrograms.clear(); +} + void QScriptEnginePrivate::detachAllRegisteredScriptValues() { QScriptValuePrivate *it; @@ -2078,10 +2088,10 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, JSC::ExecState* exec = d->currentFrame; JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); QScriptValue result = d->scriptValueFromJSCValue(function); - result.setProperty(QLatin1String("prototype"), prototype, QScriptValue::Undeletable); + result.setProperty(QLatin1String("prototype"), prototype, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); const_cast<QScriptValue&>(prototype) - .setProperty(QLatin1String("constructor"), result, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + .setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration); return result; } @@ -2347,9 +2357,9 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionSignature fun, in JSC::JSValue function = new (exec)QScript::FunctionWrapper(exec, length, JSC::Identifier(exec, ""), fun); QScriptValue result = d->scriptValueFromJSCValue(function); QScriptValue proto = newObject(); - result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); - proto.setProperty(QLatin1String("constructor"), result, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + result.setProperty(QLatin1String("prototype"), proto, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + proto.setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration); return result; } @@ -2365,9 +2375,9 @@ QScriptValue QScriptEngine::newFunction(QScriptEngine::FunctionWithArgSignature JSC::JSValue function = new (exec)QScript::FunctionWithArgWrapper(exec, /*length=*/0, JSC::Identifier(exec, ""), fun, arg); QScriptValue result = d->scriptValueFromJSCValue(function); QScriptValue proto = newObject(); - result.setProperty(QLatin1String("prototype"), proto, QScriptValue::Undeletable); - proto.setProperty(QLatin1String("constructor"), result, - QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + result.setProperty(QLatin1String("prototype"), proto, + QScriptValue::Undeletable | QScriptValue::SkipInEnumeration); + proto.setProperty(QLatin1String("constructor"), result, QScriptValue::SkipInEnumeration); return result; } @@ -2753,9 +2763,7 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV if (!clearScopeChain) { newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } else { - JSC::JSObject *jscObject = originalGlobalObject(); - JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), exec->lexicalGlobalObject(), jscObject); - newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee); + newCallFrame->init(0, /*vPC=*/0, globalExec()->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } } else { setContextFlags(newCallFrame, flags); diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 05a8901..94d195e 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -56,6 +56,7 @@ #include "Debugger.h" #include "ErrorInstance.h" #include "JSArray.h" +#include "Executable.h" #include "Lexer.h" #include "RefPtr.h" #include "RegExpConstructor.h" @@ -87,6 +88,7 @@ class QScriptEngineAgent; class QScriptEnginePrivate; class QScriptSyntaxCheckResult; class QScriptEngine; +class QScriptProgramPrivate; namespace QScript { @@ -230,6 +232,8 @@ public: static inline JSC::ExecState *frameForContext(QScriptContext *context); static inline const JSC::ExecState *frameForContext(const QScriptContext *context); + static inline bool hasValidCodeBlockRegister(JSC::ExecState *frame); + JSC::JSGlobalObject *originalGlobalObject() const; JSC::JSObject *getOriginalGlobalObjectProxy(); JSC::JSObject *customGlobalObject() const; @@ -273,6 +277,10 @@ public: static QScriptSyntaxCheckResult checkSyntax(const QString &program); static bool canEvaluate(const QString &program); + inline void registerScriptProgram(QScriptProgramPrivate *program); + inline void unregisterScriptProgram(QScriptProgramPrivate *program); + void detachAllRegisteredScriptPrograms(); + inline QScriptValuePrivate *allocateScriptValuePrivate(size_t); inline void freeScriptValuePrivate(QScriptValuePrivate *p); @@ -368,6 +376,7 @@ public: static const int maxFreeScriptValues = 256; int freeScriptValuesCount; QScriptStringPrivate *registeredScriptStrings; + QSet<QScriptProgramPrivate*> registeredScriptPrograms; QHash<int, QScriptTypeInfo*> m_typeInfos; int processEventsInterval; QScriptValue abortResult; @@ -566,6 +575,18 @@ inline QByteArray convertToLatin1(const JSC::UString &str) } // namespace QScript +inline void QScriptEnginePrivate::registerScriptProgram(QScriptProgramPrivate *program) +{ + Q_ASSERT(!registeredScriptPrograms.contains(program)); + registeredScriptPrograms.insert(program); +} + +inline void QScriptEnginePrivate::unregisterScriptProgram(QScriptProgramPrivate *program) +{ + Q_ASSERT(registeredScriptPrograms.contains(program)); + registeredScriptPrograms.remove(program); +} + inline QScriptValuePrivate *QScriptEnginePrivate::allocateScriptValuePrivate(size_t size) { if (freeScriptValues) { @@ -844,6 +865,21 @@ inline const JSC::ExecState *QScriptEnginePrivate::frameForContext(const QScript return reinterpret_cast<const JSC::ExecState*>(context); } +inline bool QScriptEnginePrivate::hasValidCodeBlockRegister(JSC::ExecState *frame) +{ +#if ENABLE(JIT) + // Frames created by the VM don't have their CodeBlock register + // initialized. We can detect such frames by checking if the + // callee is a host JSFunction. + JSC::JSObject *callee = frame->callee(); + return !(callee && callee->inherits(&JSC::JSFunction::info) + && JSC::asFunction(callee)->isHostFunction()); +#else + Q_UNUSED(frame); + return true; +#endif +} + inline JSC::ExecState *QScriptEnginePrivate::globalExec() const { return originalGlobalObject()->globalExec(); diff --git a/src/script/api/qscriptprogram.cpp b/src/script/api/qscriptprogram.cpp index da103bb..31af9a0 100644 --- a/src/script/api/qscriptprogram.cpp +++ b/src/script/api/qscriptprogram.cpp @@ -64,6 +64,7 @@ QScriptProgramPrivate::~QScriptProgramPrivate() if (engine) { QScript::APIShim shim(engine); _executable.clear(); + engine->unregisterScriptProgram(this); } } @@ -78,7 +79,10 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec, if (_executable) { if (eng == engine) return _executable.get(); - _executable = 0; + // "Migrating" to another engine; clean up old state + QScript::APIShim shim(engine); + _executable.clear(); + engine->unregisterScriptProgram(this); } WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider = QScript::UStringSourceProviderWithFeedback::create(sourceCode, fileName, firstLineNumber, eng); @@ -86,10 +90,19 @@ JSC::EvalExecutable *QScriptProgramPrivate::executable(JSC::ExecState *exec, JSC::SourceCode source(provider, firstLineNumber); //after construction of SourceCode provider variable will be null. _executable = JSC::EvalExecutable::create(exec, source); engine = eng; + engine->registerScriptProgram(this); isCompiled = false; return _executable.get(); } +void QScriptProgramPrivate::detachFromEngine() +{ + _executable.clear(); + sourceId = -1; + isCompiled = false; + engine = 0; +} + /*! Constructs a null QScriptProgram. */ @@ -122,9 +135,6 @@ QScriptProgram::QScriptProgram(const QScriptProgram &other) */ QScriptProgram::~QScriptProgram() { - // Q_D(QScriptProgram); - // if (d->engine && (d->ref == 1)) - // d->engine->unregisterScriptProgram(d); } /*! @@ -132,9 +142,6 @@ QScriptProgram::~QScriptProgram() */ QScriptProgram &QScriptProgram::operator=(const QScriptProgram &other) { - // if (d_func() && d_func()->engine && (d_func()->ref == 1)) - // d_func()->engine->unregisterScriptProgram(d_func()); - // } d_ptr = other.d_ptr; return *this; } diff --git a/src/script/api/qscriptprogram_p.h b/src/script/api/qscriptprogram_p.h index d2fd234..e7809ab 100644 --- a/src/script/api/qscriptprogram_p.h +++ b/src/script/api/qscriptprogram_p.h @@ -61,6 +61,7 @@ public: JSC::EvalExecutable *executable(JSC::ExecState *exec, QScriptEnginePrivate *engine); + void detachFromEngine(); QBasicAtomicInt ref; diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index 9285883..2085756 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -183,6 +183,10 @@ void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecSt JSC::PropertyNameArray &propertyNames, JSC::EnumerationMode mode) { + // For compatibility with the old back-end, normal JS properties + // are added first. + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(engine, exec); QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); @@ -195,7 +199,6 @@ void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecSt } delete it; } - QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); } JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData) diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 0dcf1ec..6126b32 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -179,6 +179,11 @@ QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentif return *this; } +QString QScriptDeclarativeClass::PersistentIdentifier::toString() const +{ + return ((JSC::Identifier &)d).ustring(); +} + QScriptDeclarativeClass::QScriptDeclarativeClass(QScriptEngine *engine) : d_ptr(new QScriptDeclarativeClassPrivate) { @@ -468,6 +473,14 @@ QString QScriptDeclarativeClass::toString(const Identifier &identifier) return QString((QChar *)r->data(), r->size()); } +bool QScriptDeclarativeClass::startsWithUpper(const Identifier &identifier) +{ + JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; + if (r->size() < 1) + return false; + return QChar::category((ushort)(r->data()[0])) == QChar::Letter_Uppercase; +} + quint32 QScriptDeclarativeClass::toArrayIndex(const Identifier &identifier, bool *ok) { JSC::UString::Rep *r = (JSC::UString::Rep *)identifier; diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index 25dc396..e4c18f5 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -107,6 +107,7 @@ public: PersistentIdentifier(const PersistentIdentifier &other); PersistentIdentifier &operator=(const PersistentIdentifier &other); + QString toString() const; private: friend class QScriptDeclarativeClass; PersistentIdentifier(QScriptEnginePrivate *e) : identifier(0), engine(e), d(0) {} @@ -126,6 +127,7 @@ public: PersistentIdentifier createPersistentIdentifier(const Identifier &); QString toString(const Identifier &); + bool startsWithUpper(const Identifier &); quint32 toArrayIndex(const Identifier &, bool *ok); virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, diff --git a/src/sql/drivers/oci/qsql_oci.h b/src/sql/drivers/oci/qsql_oci.h index 51fd14c..22bd78d 100644 --- a/src/sql/drivers/oci/qsql_oci.h +++ b/src/sql/drivers/oci/qsql_oci.h @@ -54,6 +54,9 @@ QT_BEGIN_HEADER +typedef struct OCIEnv OCIEnv; +typedef struct OCISvcCtx OCISvcCtx; + QT_BEGIN_NAMESPACE class QOCIDriver; @@ -61,9 +64,6 @@ class QOCICols; struct QOCIDriverPrivate; struct QOCIResultPrivate; -typedef struct OCIEnv OCIEnv; -typedef struct OCISvcCtx OCISvcCtx; - class Q_EXPORT_SQLDRIVER_OCI QOCIResult : public QSqlCachedResult { friend class QOCIDriver; diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index 1573d02..0b534d9 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -214,7 +214,7 @@ static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode state_, &nativeCode_, 0, - NULL, + 0, &msgLen); if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && msgLen > 0) description_.resize(msgLen+1); diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 5a32d1a..34277b3 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -1021,6 +1021,9 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from " "pg_namespace where pg_namespace.nspname = '%1') AND ").arg(schema)); break; + case QPSQLDriver::VersionUnknown: + qFatal("PSQL version is unknown"); + break; } i.exec(stmt.arg(tbl)); @@ -1110,6 +1113,9 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const stmt = stmt.arg(QString::fromLatin1("pg_class.relnamespace = (select oid from " "pg_namespace where pg_namespace.nspname = '%1')").arg(schema)); break; + case QPSQLDriver::VersionUnknown: + qFatal("PSQL version is unknown"); + break; } QSqlQuery query(createResult()); diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp index 66808c8..b0ae8d9 100644 --- a/src/sql/kernel/qsqldatabase.cpp +++ b/src/sql/kernel/qsqldatabase.cpp @@ -798,7 +798,7 @@ void QSqlDatabasePrivate::init(const QString &type) Destroys the object and frees any allocated resources. If this is the last QSqlDatabase object that uses a certain - database connection, the is automatically closed. + database connection, the database connection is automatically closed. \sa close() */ diff --git a/src/sql/kernel/qsqlquery.cpp b/src/sql/kernel/qsqlquery.cpp index 4b92a3e..3cdc8b1 100644 --- a/src/sql/kernel/qsqlquery.cpp +++ b/src/sql/kernel/qsqlquery.cpp @@ -272,7 +272,7 @@ static void qInit(QSqlQuery *q, const QString& query, QSqlDatabase db) /*! Constructs a QSqlQuery object using the SQL \a query and the - database \a db. If \a db is not specified, the application's + database \a db. If \a db is not specified, or is invalid, the application's default database is used. If \a query is not an empty string, it will be executed. @@ -286,6 +286,7 @@ QSqlQuery::QSqlQuery(const QString& query, QSqlDatabase db) /*! Constructs a QSqlQuery object using the database \a db. + If \a db is invalid, the application's default database will be used. \sa QSqlDatabase */ diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index 8730192..d1051de 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -279,7 +279,11 @@ QVariant QSqlQueryModel::headerData(int section, Qt::Orientation orientation, in val = d->headers.value(section).value(Qt::EditRole); if (val.isValid()) return val; - if (role == Qt::DisplayRole && d->rec.count() > section) + + // See if it's an inserted column (iiq.column() != -1) + QModelIndex dItem = indexInQuery(createIndex(0, section)); + + if (role == Qt::DisplayRole && d->rec.count() > section && dItem.column() != -1) return d->rec.fieldName(section); } return QAbstractItemModel::headerData(section, orientation, role); @@ -306,6 +310,8 @@ void QSqlQueryModel::queryChange() lastError() can be used to retrieve verbose information if there was an error setting the query. + \note Calling setQuery() will remove any inserted columns. + \sa query(), QSqlQuery::isActive(), QSqlQuery::setForwardOnly(), lastError() */ void QSqlQueryModel::setQuery(const QSqlQuery &query) @@ -370,7 +376,8 @@ void QSqlQueryModel::setQuery(const QSqlQuery &query) /*! \overload Executes the query \a query for the given database connection \a - db. If no database is specified, the default connection is used. + db. If no database (or an invalid database) is specified, the + default connection is used. lastError() can be used to retrieve verbose information if there was an error setting the query. diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 3bb46cc..bf7c0aa 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -393,6 +393,8 @@ QString QSqlTableModel::tableName() const specified filter and sort condition, and returns true if successful; otherwise returns false. + \note Calling select() will revert any unsubmitted changes and remove any inserted columns. + \sa setTable(), setFilter(), selectStatement() */ bool QSqlTableModel::select() @@ -423,6 +425,10 @@ QVariant QSqlTableModel::data(const QModelIndex &index, int role) const if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::EditRole)) return QVariant(); + // Problem.. we need to use QSQM::indexInQuery to handle inserted columns + // but inserted rows we need to handle + // and indexInQuery is not virtual (grrr) so any values we pass to QSQM need + // to handle the insertedRows QModelIndex item = indexInQuery(index); switch (d->strategy) { @@ -450,7 +456,9 @@ QVariant QSqlTableModel::data(const QModelIndex &index, int role) const return var; break; } } - return QSqlQueryModel::data(item, role); + + // We need to handle row mapping here, but not column mapping + return QSqlQueryModel::data(index.sibling(item.row(), index.column()), role); } /*! @@ -649,7 +657,7 @@ bool QSqlTableModel::insertRowIntoTable(const QSqlRecord &values) return false; } - return d->exec(stmt, prepStatement, rec); + return d->exec(stmt, prepStatement, rec, QSqlRecord() /* no where values */); } /*! @@ -687,7 +695,7 @@ bool QSqlTableModel::deleteRowFromTable(int row) } stmt.append(QLatin1Char(' ')).append(where); - return d->exec(stmt, prepStatement, whereValues); + return d->exec(stmt, prepStatement, QSqlRecord() /* no new values */, whereValues); } /*! @@ -1095,9 +1103,12 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent) int idx = row + i; if (idx >= rowCount()) return false; - if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert) + if (d->cache.value(idx).op == QSqlTableModelPrivate::Insert) { revertRow(idx); - else { + // Reverting a row means all the other cache entries have been adjusted downwards + // so fake this by adjusting row + --row; + } else { d->cache[idx].op = QSqlTableModelPrivate::Delete; d->cache[idx].primaryValues = d->primaryValues(indexInQuery(createIndex(idx, 0)).row()); emit headerDataChanged(Qt::Vertical, idx, idx); @@ -1225,7 +1236,7 @@ int QSqlTableModel::rowCount(const QModelIndex &parent) const QModelIndex QSqlTableModel::indexInQuery(const QModelIndex &item) const { Q_D(const QSqlTableModel); - const QModelIndex it = QSqlQueryModel::indexInQuery(item); + const QModelIndex it = QSqlQueryModel::indexInQuery(item); // this adjusts columns only if (d->strategy == OnManualSubmit) { int rowOffset = 0; QSqlTableModelPrivate::CacheMap::ConstIterator i = d->cache.constBegin(); @@ -1332,6 +1343,9 @@ bool QSqlTableModel::setRecord(int row, const QSqlRecord &record) else mrow.rec.setValue(idx, record.value(i)); } + + if (isOk) + emit dataChanged(createIndex(row, 0), createIndex(row, columnCount() - 1)); return isOk; } } return false; diff --git a/src/sql/models/qsqltablemodel_p.h b/src/sql/models/qsqltablemodel_p.h index d2b96e6..f4f3811 100644 --- a/src/sql/models/qsqltablemodel_p.h +++ b/src/sql/models/qsqltablemodel_p.h @@ -75,7 +75,7 @@ public: QSqlRecord record(const QVector<QVariant> &values) const; bool exec(const QString &stmt, bool prepStatement, - const QSqlRecord &rec, const QSqlRecord &whereValues = QSqlRecord()); + const QSqlRecord &rec, const QSqlRecord &whereValues); virtual void revertCachedRow(int row); void revertInsertedRow(); bool setRecord(int row, const QSqlRecord &record); diff --git a/src/sql/sql.pro b/src/sql/sql.pro index 54f4289..81aa3c0 100644 --- a/src/sql/sql.pro +++ b/src/sql/sql.pro @@ -20,7 +20,10 @@ include(models/models.pri) symbian: { TARGET.UID3=0x2001E61D - # Workaroud for problems with paging this dll - MMP_RULES -= PAGED - MMP_RULES *= UNPAGED + # Problems using data exports from this DLL mean that we can't page it on releases that don't support + # data exports (currently that's any release before Symbian^3) + pagingBlock = "$${LITERAL_HASH}ifndef SYMBIAN_DLL_DATA_EXPORTS_SUPPORTED" \ + "UNPAGED" \ + "$${LITERAL_HASH}endif" + MMP_RULES += pagingBlock } diff --git a/src/src.pro b/src/src.pro index 0bf3b52..0908911 100644 --- a/src/src.pro +++ b/src/src.pro @@ -113,6 +113,7 @@ src_webkit_declarative.target = sub-webkitdeclarative src_declarative.depends = src_gui src_script src_network src_plugins.depends = src_gui src_sql src_svg contains(QT_CONFIG, multimedia):src_plugins.depends += src_multimedia + contains(QT_CONFIG, declarative):src_plugins.depends += src_declarative src_s60installs.depends = $$TOOLS_SUBDIRS $$SRC_SUBDIRS src_s60installs.depends -= src_s60installs src_imports.depends = src_gui src_declarative diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 222e5f6..4df7ae5 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -181,10 +181,14 @@ void Generator::generateCode() int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count(); fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0); index += methodCount * 5; + if (cdef->revisionedMethods) + index += methodCount; fprintf(out, " %4d, %4d, // properties\n", cdef->propertyList.count(), cdef->propertyList.count() ? index : 0); index += cdef->propertyList.count() * 3; if(cdef->notifyableProperties) index += cdef->propertyList.count(); + if (cdef->revisionedProperties) + index += cdef->propertyList.count(); fprintf(out, " %4d, %4d, // enums/sets\n", cdef->enumList.count(), cdef->enumList.count() ? index : 0); int enumsIndex = index; @@ -217,6 +221,14 @@ void Generator::generateCode() // generateFunctions(cdef->methodList, "method", MethodMethod); +// +// Build method version arrays +// + if (cdef->revisionedMethods) { + generateFunctionRevisions(cdef->signalList, "signal"); + generateFunctionRevisions(cdef->slotList, "slot"); + generateFunctionRevisions(cdef->methodList, "method"); + } // // Build property array @@ -456,7 +468,7 @@ void Generator::generateFunctions(QList<FunctionDef>& list, const char *functype } sig += ')'; - char flags = type; + unsigned char flags = type; if (f.access == FunctionDef::Private) flags |= AccessPrivate; else if (f.access == FunctionDef::Public) @@ -475,11 +487,23 @@ void Generator::generateFunctions(QList<FunctionDef>& list, const char *functype flags |= MethodCloned; if (f.isScriptable) flags |= MethodScriptable; + if (f.revision > 0) + flags |= MethodRevisioned; fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n", strreg(sig), strreg(arguments), strreg(f.normalizedType), strreg(f.tag), flags); } } +void Generator::generateFunctionRevisions(QList<FunctionDef>& list, const char *functype) +{ + if (list.count()) + fprintf(out, "\n // %ss: revision\n", functype); + for (int i = 0; i < list.count(); ++i) { + const FunctionDef &f = list.at(i); + fprintf(out, " %4d,\n", f.revision); + } +} + void Generator::generateProperties() { // @@ -537,6 +561,9 @@ void Generator::generateProperties() if (p.notifyId != -1) flags |= Notify; + if (p.revision > 0) + flags |= Revisioned; + if (p.constant) flags |= Constant; if (p.final) @@ -562,6 +589,13 @@ void Generator::generateProperties() p.notifyId); } } + if (cdef->revisionedProperties) { + fprintf(out, "\n // properties: revision\n"); + for (int i = 0; i < cdef->propertyList.count(); ++i) { + const PropertyDef &p = cdef->propertyList.at(i); + fprintf(out, " %4d,\n", p.revision); + } + } } void Generator::generateEnums(int index) diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h index 63605eb..ed0980e 100644 --- a/src/tools/moc/generator.h +++ b/src/tools/moc/generator.h @@ -58,6 +58,7 @@ public: private: void generateClassInfos(); void generateFunctions(QList<FunctionDef> &list, const char *functype, int type); + void generateFunctionRevisions(QList<FunctionDef>& list, const char *functype); void generateEnums(int index); void generateProperties(); void generateMetacall(); diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index 0eca110..9a8aa41 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -43,12 +43,12 @@ // DO NOT EDIT. static const short keyword_trans[][128] = { - {0,0,0,0,0,0,0,0,0,533,530,0,0,0,0,0, + {0,0,0,0,0,0,0,0,0,541,538,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 533,252,531,534,0,38,239,532,25,26,236,234,30,235,27,237, + 541,252,539,542,0,38,239,540,25,26,236,234,30,235,27,237, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,21,8,8,8,8,8,8,8,8,8,31,535,32,238,8, + 8,21,8,8,8,8,8,8,8,8,8,31,543,32,238,8, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -190,7 +190,7 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, - 538,538,538,538,538,538,538,538,538,538,0,0,0,0,0,0, + 546,546,546,546,546,546,546,546,546,546,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -349,7 +349,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,537,0,0,0,0,536, + 0,0,0,0,0,0,0,0,0,0,545,0,0,0,0,544, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -392,7 +392,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,439,388,378,383,364,0,448,0,0,0,0,0,358, - 370,0,0,436,0,0,0,0,0,0,0,0,0,0,0,0, + 370,0,530,436,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -983,6 +983,14 @@ static const struct {CHARACTER, 0, 84, 528, CHARACTER}, {CHARACTER, 0, 89, 529, CHARACTER}, {Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 69, 531, CHARACTER}, + {CHARACTER, 0, 86, 532, CHARACTER}, + {CHARACTER, 0, 73, 533, CHARACTER}, + {CHARACTER, 0, 83, 534, CHARACTER}, + {CHARACTER, 0, 73, 535, CHARACTER}, + {CHARACTER, 0, 79, 536, CHARACTER}, + {CHARACTER, 0, 78, 537, CHARACTER}, + {Q_REVISION_TOKEN, 0, 0, 0, CHARACTER}, {NEWLINE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN}, {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 5e8b2b8..74b1ace 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -335,6 +335,23 @@ bool Moc::testFunctionAttribute(Token tok, FunctionDef *def) return false; } +bool Moc::testFunctionRevision(FunctionDef *def) +{ + if (test(Q_REVISION_TOKEN)) { + next(LPAREN); + QByteArray revision = lexemUntil(RPAREN); + revision.remove(0, 1); + revision.chop(1); + bool ok = false; + def->revision = revision.toInt(&ok); + if (!ok || def->revision < 0) + error("Invalid revision"); + return true; + } + + return false; +} + // returns false if the function should be ignored bool Moc::parseFunction(FunctionDef *def, bool inMacro) { @@ -342,7 +359,7 @@ bool Moc::parseFunction(FunctionDef *def, bool inMacro) //skip modifiers and attributes while (test(INLINE) || test(STATIC) || (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual - || testFunctionAttribute(def)) {} + || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool templateFunction = (lookup() == TEMPLATE); def->type = parseType(); if (def->type.name.isEmpty()) { @@ -433,7 +450,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def) //skip modifiers and attributes while (test(EXPLICIT) || test(INLINE) || test(STATIC) || (test(VIRTUAL) && (def->isVirtual = true)) //mark as virtual - || testFunctionAttribute(def)) {} + || testFunctionAttribute(def) || testFunctionRevision(def)) {} bool tilde = test(TILDE); def->type = parseType(); if (def->type.name.isEmpty()) @@ -697,6 +714,8 @@ void Moc::parse() funcDef.arguments.removeLast(); def.slotList += funcDef; } + if (funcDef.revision > 0) + ++def.revisionedMethods; } else if (funcDef.isSignal) { def.signalList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { @@ -704,6 +723,8 @@ void Moc::parse() funcDef.arguments.removeLast(); def.signalList += funcDef; } + if (funcDef.revision > 0) + ++def.revisionedMethods; } else if (funcDef.isInvokable) { def.methodList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { @@ -711,6 +732,8 @@ void Moc::parse() funcDef.arguments.removeLast(); def.methodList += funcDef; } + if (funcDef.revision > 0) + ++def.revisionedMethods; } } } else { @@ -809,6 +832,18 @@ QList<QMetaObject*> Moc::generate(bool ignoreProperties) void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) { + int defaultRevision = -1; + if (test(Q_REVISION_TOKEN)) { + next(LPAREN); + QByteArray revision = lexemUntil(RPAREN); + revision.remove(0, 1); + revision.chop(1); + bool ok = false; + defaultRevision = revision.toInt(&ok); + if (!ok || defaultRevision < 0) + error("Invalid revision"); + } + next(COLON); while (inClass(def) && hasNext()) { switch (next()) { @@ -834,6 +869,12 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) funcDef.access = access; if (!parseFunction(&funcDef)) continue; + if (funcDef.revision > 0) { + ++def->revisionedMethods; + } else if (defaultRevision != -1) { + funcDef.revision = defaultRevision; + ++def->revisionedMethods; + } def->slotList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; @@ -845,6 +886,18 @@ void Moc::parseSlots(ClassDef *def, FunctionDef::Access access) void Moc::parseSignals(ClassDef *def) { + int defaultRevision = -1; + if (test(Q_REVISION_TOKEN)) { + next(LPAREN); + QByteArray revision = lexemUntil(RPAREN); + revision.remove(0, 1); + revision.chop(1); + bool ok = false; + defaultRevision = revision.toInt(&ok); + if (!ok || defaultRevision < 0) + error("Invalid revision"); + } + next(COLON); while (inClass(def) && hasNext()) { switch (next()) { @@ -872,6 +925,12 @@ void Moc::parseSignals(ClassDef *def) warning("Signals cannot be declared virtual"); if (funcDef.inlineCode) error("Not a signal declaration"); + if (funcDef.revision > 0) { + ++def->revisionedMethods; + } else if (defaultRevision != -1) { + funcDef.revision = defaultRevision; + ++def->revisionedMethods; + } def->signalList += funcDef; while (funcDef.arguments.size() > 0 && funcDef.arguments.last().isDefault) { funcDef.wasCloned = true; @@ -914,7 +973,6 @@ void Moc::createPropertyDef(PropertyDef &propDef) propDef.name = lexem(); while (test(IDENTIFIER)) { QByteArray l = lexem(); - if (l[0] == 'C' && l == "CONSTANT") { propDef.constant = true; continue; @@ -926,6 +984,10 @@ void Moc::createPropertyDef(PropertyDef &propDef) QByteArray v, v2; if (test(LPAREN)) { v = lexemUntil(RPAREN); + } else if (test(INTEGER_LITERAL)) { + v = lexem(); + if (l != "REVISION") + error(1); } else { next(IDENTIFIER); v = lexem(); @@ -940,7 +1002,12 @@ void Moc::createPropertyDef(PropertyDef &propDef) propDef.read = v; else if (l == "RESET") propDef.reset = v + v2; - else + else if (l == "REVISION") { + bool ok = false; + propDef.revision = v.toInt(&ok); + if (!ok || propDef.revision < 0) + error(1); + } else error(2); break; case 'S': @@ -1005,6 +1072,8 @@ void Moc::parseProperty(ClassDef *def) if(!propDef.notify.isEmpty()) def->notifyableProperties++; + if (propDef.revision > 0) + ++def->revisionedProperties; def->propertyList += propDef; } @@ -1031,6 +1100,8 @@ void Moc::parsePrivateProperty(ClassDef *def) if(!propDef.notify.isEmpty()) def->notifyableProperties++; + if (propDef.revision > 0) + ++def->revisionedProperties; def->propertyList += propDef; } @@ -1180,6 +1251,9 @@ void Moc::parseSlotInPrivate(ClassDef *def, FunctionDef::Access access) funcDef.arguments.removeLast(); def->slotList += funcDef; } + if (funcDef.revision > 0) + ++def->revisionedMethods; + } QByteArray Moc::lexemUntil(Token target) diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 9543a05..38c3917 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -86,7 +86,7 @@ struct FunctionDef FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), inlineCode(false), wasCloned(false), isCompat(false), isInvokable(false), isScriptable(false), isSlot(false), isSignal(false), - isConstructor(false), isDestructor(false), isAbstract(false) {} + isConstructor(false), isDestructor(false), isAbstract(false), revision(0) {} Type type; QByteArray normalizedType; QByteArray tag; @@ -111,11 +111,13 @@ struct FunctionDef bool isConstructor; bool isDestructor; bool isAbstract; + + int revision; }; struct PropertyDef { - PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec){} + PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec), revision(0){} QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass; int notifyId; bool constant; @@ -128,6 +130,7 @@ struct PropertyDef s += name.mid(1); return (s == write); } + int revision; }; @@ -139,7 +142,8 @@ struct ClassInfoDef struct ClassDef { ClassDef(): - hasQObject(false), hasQGadget(false), notifyableProperties(0), begin(0), end(0){} + hasQObject(false), hasQGadget(false), notifyableProperties(0) + , revisionedMethods(0), revisionedProperties(0), begin(0), end(0){} QByteArray classname; QByteArray qualified; QList<QPair<QByteArray, FunctionDef::Access> > superclassList; @@ -164,6 +168,8 @@ struct ClassDef { QMap<QByteArray, bool> enumDeclarations; QList<EnumDef> enumList; QMap<QByteArray, QByteArray> flagAliases; + int revisionedMethods; + int revisionedProperties; int begin; int end; @@ -236,6 +242,7 @@ public: // in FunctionDef accordingly bool testFunctionAttribute(FunctionDef *def); bool testFunctionAttribute(Token tok, FunctionDef *def); + bool testFunctionRevision(FunctionDef *def); void checkSuperClasses(ClassDef *def); void checkProperties(ClassDef* cdef); diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp index 733a17e..9d07c48 100644 --- a/src/tools/moc/token.cpp +++ b/src/tools/moc/token.cpp @@ -180,6 +180,7 @@ const char *tokenTypeName(Token t) case Q_SLOT_TOKEN: return "Q_SLOT_TOKEN"; case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN"; case Q_PRIVATE_PROPERTY_TOKEN: return "Q_PRIVATE_PROPERTY_TOKEN"; + case Q_REVISION_TOKEN: return "Q_REVISION_TOKEN"; case SPECIAL_TREATMENT_MARK: return "SPECIAL_TREATMENT_MARK"; case MOC_INCLUDE_BEGIN: return "MOC_INCLUDE_BEGIN"; case MOC_INCLUDE_END: return "MOC_INCLUDE_END"; diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index edbb567..95f17c2 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -186,6 +186,7 @@ enum Token { Q_INVOKABLE_TOKEN, Q_SCRIPTABLE_TOKEN, Q_PRIVATE_PROPERTY_TOKEN, + Q_REVISION_TOKEN, Q_META_TOKEN_END, SPECIAL_TREATMENT_MARK = Q_META_TOKEN_END, MOC_INCLUDE_BEGIN, diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index 777bf3f..26f7a19 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -249,6 +249,7 @@ static const Keyword keywords[] = { { "Q_SLOT", "Q_SLOT_TOKEN" }, { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" }, { "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" }, + { "Q_REVISION", "Q_REVISION_TOKEN" }, { "\n", "NEWLINE" }, { "\"", "QUOTE" }, { "\'", "SINGLEQUOTE" }, |