diff options
author | Jerome Pasion <jerome.pasion@nokia.com> | 2011-02-04 11:28:14 (GMT) |
---|---|---|
committer | Jerome Pasion <jerome.pasion@nokia.com> | 2011-02-04 11:28:14 (GMT) |
commit | ce0fc2ebeaf195368c31b143a40850f01ada450a (patch) | |
tree | 3c46a405766b4ec5a5676fca15df5d4e13ca2342 /src | |
parent | 39e7c4de155a150a0e7da6e40f59aadecaea0a8a (diff) | |
parent | 74ad5ce57adedc91717ffd67e3e65b8f76d12052 (diff) | |
download | Qt-ce0fc2ebeaf195368c31b143a40850f01ada450a.zip Qt-ce0fc2ebeaf195368c31b143a40850f01ada450a.tar.gz Qt-ce0fc2ebeaf195368c31b143a40850f01ada450a.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/qt-doc-team into 4.7
Conflicts:
doc/src/declarative/extending.qdoc
doc/src/external-resources.qdoc
src/declarative/util/qdeclarativeanimation.cpp
src/declarative/util/qdeclarativetransition.cpp
Diffstat (limited to 'src')
99 files changed, 1946 insertions, 530 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog index fd6c3f7..c2b1155 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog +++ b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog @@ -232,6 +232,34 @@ without using doubles, but the code would be much more complicated, and there is no important reason to stick to integers here. +2010-03-22 Siddharth Mathur <siddharth.mathur@nokia.com> + + Reviewed by Laszlo Gombos. + + [Symbian] More efficient aligned memory allocation for JSC Collector + https://bugs.webkit.org/show_bug.cgi?id=34350 + + * JavaScriptCore.pri: Added 2 new Symbian source files and HAL linkage + + * runtime/Collector.cpp: Reduced port-specific code and added private data member + (JSC::Heap::Heap): + (JSC::Heap::~Heap): + (JSC::Heap::destroy): + (JSC::Heap::allocateBlock): + (JSC::Heap::freeBlockPtr): + + * runtime/Collector.h: Added private data member + + * wtf/symbian: Added. + * wtf/symbian/BlockAllocatorSymbian.cpp: Added. + (WTF::AlignedBlockAllocator::AlignedBlockAllocator): Helper class to allocate + aligned blocks more efficiently as required by Collector + (WTF::AlignedBlockAllocator::alloc): + (WTF::AlignedBlockAllocator::free): + (WTF::AlignedBlockAllocator::destroy): + (WTF::AlignedBlockAllocator::~AlignedBlockAllocator): + * wtf/symbian/BlockAllocatorSymbian.h: Added. + 2010-03-22 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri index d75bd31..b061321 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri +++ b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri @@ -16,6 +16,7 @@ CONFIG(debug, debug|release) { symbian: { # Need to guarantee this comes before system includes of /epoc32/include MMP_RULES += "USERINCLUDE ../JavaScriptCore/profiler" + LIBS += -lhal } INCLUDEPATH = \ @@ -33,6 +34,7 @@ INCLUDEPATH = \ $$PWD/runtime \ $$PWD/wrec \ $$PWD/wtf \ + $$PWD/wtf/symbian \ $$PWD/wtf/unicode \ $$PWD/yarr \ $$PWD/API \ @@ -211,6 +213,7 @@ SOURCES += \ wtf/qt/ThreadingQt.cpp \ wtf/RandomNumber.cpp \ wtf/RefCountedLeakCounter.cpp \ + wtf/symbian/BlockAllocatorSymbian.cpp \ wtf/symbian/RegisterFileAllocatorSymbian.cpp \ wtf/ThreadingNone.cpp \ wtf/Threading.cpp \ diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp index 24873c8..42e2a35 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp @@ -53,11 +53,6 @@ #include <mach/thread_act.h> #include <mach/vm_map.h> -#elif OS(SYMBIAN) -#include <e32std.h> -#include <e32cmn.h> -#include <unistd.h> - #elif OS(WINDOWS) #include <windows.h> @@ -109,11 +104,6 @@ const size_t ALLOCATIONS_PER_COLLECTION = 3600; // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. #define MIN_ARRAY_SIZE (static_cast<size_t>(14)) -#if OS(SYMBIAN) -const size_t MAX_NUM_BLOCKS = 256; // Max size of collector heap set to 16 MB -static RHeap* userChunk = 0; -#endif - #if ENABLE(JSC_MULTIPLE_THREADS) #if OS(DARWIN) @@ -146,29 +136,11 @@ Heap::Heap(JSGlobalData* globalData) , m_currentThreadRegistrar(0) #endif , m_globalData(globalData) +#if OS(SYMBIAN) + , m_blockallocator(JSCCOLLECTOR_VIRTUALMEM_RESERVATION, BLOCK_SIZE) +#endif { ASSERT(globalData); - -#if OS(SYMBIAN) - // Symbian OpenC supports mmap but currently not the MAP_ANON flag. - // Using fastMalloc() does not properly align blocks on 64k boundaries - // and previous implementation was flawed/incomplete. - // UserHeap::ChunkHeap allows allocation of continuous memory and specification - // of alignment value for (symbian) cells within that heap. - // - // Clarification and mapping of terminology: - // RHeap (created by UserHeap::ChunkHeap below) is continuos memory chunk, - // which can dynamically grow up to 8 MB, - // that holds all CollectorBlocks of this session (static). - // Each symbian cell within RHeap maps to a 64kb aligned CollectorBlock. - // JSCell objects are maintained as usual within CollectorBlocks. - if (!userChunk) { - userChunk = UserHeap::ChunkHeap(0, 0, MAX_NUM_BLOCKS * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); - if (!userChunk) - CRASH(); - } -#endif // OS(SYMBIAN) - memset(&m_heap, 0, sizeof(CollectorHeap)); allocateBlock(); } @@ -211,7 +183,9 @@ void Heap::destroy() t = next; } #endif - +#if OS(SYMBIAN) + m_blockallocator.destroy(); +#endif m_globalData = 0; } @@ -221,11 +195,9 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock() vm_address_t address = 0; vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT); #elif OS(SYMBIAN) - // Allocate a 64 kb aligned CollectorBlock - unsigned char* mask = reinterpret_cast<unsigned char*>(userChunk->Alloc(BLOCK_SIZE)); - if (!mask) + void* address = m_blockallocator.alloc(); + if (!address) CRASH(); - uintptr_t address = reinterpret_cast<uintptr_t>(mask); #elif OS(WINCE) void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #elif OS(WINDOWS) @@ -316,7 +288,7 @@ NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block) #if OS(DARWIN) vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE); #elif OS(SYMBIAN) - userChunk->Free(reinterpret_cast<TAny*>(block)); + m_blockallocator.free(reinterpret_cast<void*>(block)); #elif OS(WINCE) VirtualFree(block, 0, MEM_RELEASE); #elif OS(WINDOWS) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h index 7f7a679..d3616dc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h @@ -35,6 +35,10 @@ #include <pthread.h> #endif +#if OS(SYMBIAN) +#include <wtf/symbian/BlockAllocatorSymbian.h> +#endif + #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell) namespace JSC { @@ -167,6 +171,11 @@ namespace JSC { pthread_key_t m_currentThreadRegistrar; #endif +#if OS(SYMBIAN) + // Allocates collector blocks with correct alignment + WTF::AlignedBlockAllocator m_blockallocator; +#endif + JSGlobalData* m_globalData; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp new file mode 100644 index 0000000..6a28e9e --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#if OS(SYMBIAN) + +#include "BlockAllocatorSymbian.h" + + +namespace WTF { + +/** Efficiently allocates blocks of size blockSize with blockSize alignment. + * Primarly designed for JSC Collector's needs. + * Not thread-safe. + */ +AlignedBlockAllocator::AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize ) + : m_reservation(reservationSize), + m_blockSize(blockSize) +{ + + // Get system's page size value. + SYMBIAN_PAGESIZE(m_pageSize); + + // We only accept multiples of system page size for both initial reservation and the alignment/block size + m_reservation = SYMBIAN_ROUNDUPTOMULTIPLE(m_reservation, m_pageSize); + __ASSERT_ALWAYS(SYMBIAN_ROUNDUPTOMULTIPLE(m_blockSize, m_pageSize), User::Panic(_L("AlignedBlockAllocator1"), KErrArgument)); + + // Calculate max. bit flags we need to carve a reservationSize range into blockSize-sized blocks + m_map.numBits = m_reservation / m_blockSize; + const TUint32 bitsPerWord = 8*sizeof(TUint32); + const TUint32 numWords = (m_map.numBits + bitsPerWord -1) / bitsPerWord; + + m_map.bits = new TUint32[numWords]; + __ASSERT_ALWAYS(m_map.bits, User::Panic(_L("AlignedBlockAllocator2"), KErrNoMemory)); + m_map.clearAll(); + + // Open a Symbian RChunk, and reserve requested virtual address range + // Any thread in this process can operate this rchunk due to EOwnerProcess access rights. + TInt ret = m_chunk.CreateDisconnectedLocal(0 , 0, (TInt)m_reservation , EOwnerProcess); + if (ret != KErrNone) + User::Panic(_L("AlignedBlockAllocator3"), ret); + + // This is the offset to m_chunk.Base() required to make it m_blockSize-aligned + m_offset = SYMBIAN_ROUNDUPTOMULTIPLE(TUint32(m_chunk.Base()), m_blockSize) - TUint(m_chunk.Base()); + +} + +void* AlignedBlockAllocator::alloc() +{ + + TInt freeRam = 0; + void* address = 0; + + // Look up first free slot in bit map + const TInt freeIdx = m_map.findFree(); + + // Pseudo OOM: We ate up the address space we reserved.. + // ..even though the device may have free RAM left + if (freeIdx < 0) + return 0; + + TInt ret = m_chunk.Commit(m_offset + (m_blockSize * freeIdx), m_blockSize); + if (ret != KErrNone) + return 0; // True OOM: Device didn't have physical RAM to spare + + // Updated bit to mark region as in use. + m_map.set(freeIdx); + + // Calculate address of committed region (block) + address = (void*)( (m_chunk.Base() + m_offset) + (TUint)(m_blockSize * freeIdx) ); + + return address; +} + +void AlignedBlockAllocator::free(void* block) +{ + // Calculate index of block to be freed + TInt idx = TUint(static_cast<TUint8*>(block) - m_chunk.Base() - m_offset) / m_blockSize; + + __ASSERT_DEBUG(idx >= 0 && idx < m_map.numBits, User::Panic(_L("AlignedBlockAllocator4"), KErrCorrupt)); // valid index check + __ASSERT_DEBUG(m_map.get(idx), User::Panic(_L("AlignedBlockAllocator5"), KErrCorrupt)); // in-use flag check + + // Return committed region to system RAM pool (the physical RAM becomes usable by others) + TInt ret = m_chunk.Decommit(m_offset + m_blockSize * idx, m_blockSize); + + // mark this available again + m_map.clear(idx); +} + +void AlignedBlockAllocator::destroy() +{ + // release everything! + m_chunk.Decommit(0, m_chunk.MaxSize()); + m_map.clearAll(); +} + +AlignedBlockAllocator::~AlignedBlockAllocator() +{ + destroy(); + m_chunk.Close(); + delete [] m_map.bits; +} + +} // end of namespace + +#endif // SYMBIAN diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h new file mode 100644 index 0000000..21422f6 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef BlockAllocatorSymbian_h +#define BlockAllocatorSymbian_h + +#include <e32cmn.h> +#include <e32std.h> +#include <hal.h> + + +#define SYMBIAN_PAGESIZE(x) (HAL::Get(HALData::EMemoryPageSize, x)); +#define SYMBIAN_FREERAM(x) (HAL::Get(HALData::EMemoryRAMFree, x)); +#define SYMBIAN_ROUNDUPTOMULTIPLE(x, multipleof) ( (x + multipleof - 1) & ~(multipleof - 1) ) + +// Set sane defaults if -D<flagname=value> wasn't provided via compiler args +#ifndef JSCCOLLECTOR_VIRTUALMEM_RESERVATION +#if defined(__WINS__) + // Emulator has limited virtual address space + #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (4*1024*1024) +#else + // HW has plenty of virtual addresses + #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (128*1024*1024) +#endif +#endif + +namespace WTF { + +/** + * Allocates contiguous region of size blockSize with blockSize-aligned address. + * blockSize must be a multiple of system page size (typically 4K on Symbian/ARM) + * + * @param reservationSize Virtual address range to be reserved upon creation of chunk (bytes). + * @param blockSize Size of a single allocation. Returned address will also be blockSize-aligned. + */ +class AlignedBlockAllocator { + public: + AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize); + ~AlignedBlockAllocator(); + void destroy(); + void* alloc(); + void free(void* data); + + private: + RChunk m_chunk; // Symbian chunk that lets us reserve/commit/decommit + TUint m_offset; // offset of first committed region from base + TInt m_pageSize; // cached value of system page size, typically 4K on Symbian + TUint32 m_reservation; + TUint32 m_blockSize; + + // Tracks comitted/decommitted state of a blockSize region + struct { + + TUint32 *bits; // array of bit flags + TUint32 numBits; // number of regions to keep track of + + bool get(TUint32 n) const + { + return !!(bits[n >> 5] & (1 << (n & 0x1F))); + } + + void set(TUint32 n) + { + bits[n >> 5] |= (1 << (n & 0x1F)); + } + + void clear(TUint32 n) + { + bits[n >> 5] &= ~(1 << (n & 0x1F)); + } + + void clearAll() + { + for (TUint32 i = 0; i < numBits; i++) + clear(i); + } + + TInt findFree() const + { + for (TUint32 i = 0; i < numBits; i++) { + if (!get(i)) + return i; + } + return -1; + } + + } m_map; + +}; + +} + +#endif // end of BlockAllocatorSymbian_h + + diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/RegisterFileAllocatorSymbian.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/RegisterFileAllocatorSymbian.cpp index da5cc99..e89dd7a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/RegisterFileAllocatorSymbian.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/symbian/RegisterFileAllocatorSymbian.cpp @@ -83,10 +83,16 @@ void RegisterFileAllocator::grow(void* newEnd) TInt nBytes = (TInt)(newEnd) - (TInt)(m_comEnd); nBytes = SYMBIAN_ROUNDUPTOMULTIPLE(nBytes, m_poolSize); TInt offset = (TInt)m_comEnd - (TInt)m_buffer; + // The reserved size is not guaranteed to be a multiple of the pool size. + TInt maxBytes = (TInt)m_resEnd - (TInt)m_comEnd; + if (nBytes > maxBytes) + nBytes = maxBytes; TInt ret = m_chunk.Commit(offset, nBytes); if (ret == KErrNone) m_comEnd = (void*)(m_chunk.Base() + m_chunk.Size()); + else + CRASH(); } } diff --git a/src/3rdparty/javascriptcore/VERSION b/src/3rdparty/javascriptcore/VERSION index 9991ac0..b4744b7 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-05102010 branch/tag + javascriptcore-snapshot-24012011 branch/tag and has the sha1 checksum - 82ead85cfea5859044eeb25b33314dcc0fa5eea1 + d143bde5ae8cff229aebd43487a2fce5e713e990 diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp index 2785dff..b5e565b 100644 --- a/src/3rdparty/phonon/phonon/factory.cpp +++ b/src/3rdparty/phonon/phonon/factory.cpp @@ -137,21 +137,15 @@ bool FactoryPrivate::createBackend() QStringList plugins(dir.entryList(QDir::Files)); #ifdef Q_OS_SYMBIAN - /* On Symbian OS we might have two plugins, one which uses Symbian - * MMF framework("mmf"), and one which uses Real Networks's - * Helix("hxphonon"). We prefer the latter because it's more - * sophisticated, so we make sure the Helix backend is attempted - * to be loaded first, and the MMF backend is used for backup. */ - { - const int helix = plugins.indexOf(QLatin1String("hxphonon")); - if (helix != -1) - plugins.move(helix, 0); - } + static const QString preferredPluginName = QLatin1String("phonon_mmf"); + const int preferredPluginIndex = plugins.indexOf(preferredPluginName + ".qtplugin"); + if (preferredPluginIndex != -1) + plugins.move(preferredPluginIndex, 0); #endif const QStringList files = dir.entryList(QDir::Files); - for (int i = 0; i < files.count(); ++i) { - QPluginLoader pluginLoader(libPath + files.at(i)); + for (int i = 0; i < plugins.count(); ++i) { + QPluginLoader pluginLoader(libPath + plugins.at(i)); if (!pluginLoader.load()) { pDebug() << Q_FUNC_INFO << " load failed:" << pluginLoader.errorString(); 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/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/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp index e79f87a..cc08f092 100644 --- a/src/corelib/kernel/qabstracteventdispatcher.cpp +++ b/src/corelib/kernel/qabstracteventdispatcher.cpp @@ -137,6 +137,12 @@ void QAbstractEventDispatcherPrivate::init() // free list). As an added protection, we use the cell to store an invalid // (negative) value that we can later check for integrity. // +// ABA prevention simply adds a value to 7 of the top 8 bits when resetting +// nextFreeTimerId. +// +// The extra code is the bucket allocation which allows us to start with a +// very small bucket size and grow as needed. +// // (continues below). int QAbstractEventDispatcherPrivate::allocateTimerId() { @@ -164,6 +170,8 @@ int QAbstractEventDispatcherPrivate::allocateTimerId() newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]); } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId)); + timerId &= TimerIdMask; + timerId |= b[at] & TimerSerialMask; b[at] = -timerId; return timerId; @@ -174,12 +182,13 @@ int QAbstractEventDispatcherPrivate::allocateTimerId() // X[timerId] = nextFreeTimerId; // then we update nextFreeTimerId to the timer we've just released // -// The extra code in allocateTimerId and releaseTimerId are ABA prevention -// and bucket memory. The buckets are simply to make sure we allocate only -// the necessary number of timers. See above. -// // ABA prevention simply adds a value to 7 of the top 8 bits when resetting // nextFreeTimerId. +// +// In addition to that, we update the same 7 bits in each entry in the bucket +// as a counter. That way, a timer ID allocated and released will always be +// returned with a different ID. This reduces the chances of timers being released +// erroneously by application code. void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId) { int which = timerId & TimerIdMask; @@ -187,12 +196,21 @@ void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId) int at = bucketIndex(bucket, which); int *b = timerIds[bucket]; - Q_ASSERT(b[at] == -timerId); +#ifndef QT_NO_DEBUG + // debug code + Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId", "Timer ID was not found, fix application"); +#else + if (timerId != -b[at]) { + // release code + qWarning("Timer ID %d was not found, fix application", timerId); + return; + } +#endif int freeId, newTimerId; do { freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics - b[at] = freeId & TimerIdMask; + b[at] = prepareNewValueWithSerialNumber(-b[at], freeId); newTimerId = prepareNewValueWithSerialNumber(freeId, timerId); } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId)); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 381be34..7d88b10 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -462,10 +462,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 diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index 14e8991..050805f 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -501,7 +501,6 @@ bool QTimerInfoList::unregisterTimer(int timerId) } } // id not found - qWarning("Application asked to unregister timer 0x%x which is not registered in this thread. Fix application.", timerId); return false; } diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index 2fd6c50..85b37d0 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -399,11 +399,7 @@ bool QSharedMemory::detach() return false; #endif - if (d->detach()) { - d->size = 0; - return true; - } - return false; + return d->detach(); } /*! diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index bea5b63..ddb0e34 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -199,7 +199,7 @@ bool QSharedMemoryPrivate::create(int size) } // create - if (-1 == shmget(handle(), size, 0666 | IPC_CREAT | IPC_EXCL)) { + if (-1 == shmget(unix_key, size, 0666 | IPC_CREAT | IPC_EXCL)) { QString function = QLatin1String("QSharedMemory::create"); switch (errno) { case EINVAL: @@ -220,10 +220,7 @@ bool QSharedMemoryPrivate::create(int size) bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) { // grab the shared memory segment id - if (!handle()) - return false; - - int id = shmget(handle(), 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660)); + int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660)); if (-1 == id) { setErrorString(QLatin1String("QSharedMemory::attach (shmget)")); return false; @@ -265,12 +262,11 @@ bool QSharedMemoryPrivate::detach() return false; } memory = 0; + size = 0; // Get the number of current attachments - if (!handle()) - return false; - int id = shmget(handle(), 0, 0444); - unix_key = 0; + int id = shmget(unix_key, 0, 0444); + cleanHandle(); struct shmid_ds shmid_ds; if (0 != shmctl(id, IPC_STAT, &shmid_ds)) { diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp index 85600a2..ac9c86a 100644 --- a/src/corelib/kernel/qsharedmemory_win.cpp +++ b/src/corelib/kernel/qsharedmemory_win.cpp @@ -124,8 +124,8 @@ bool QSharedMemoryPrivate::cleanHandle() { if (hand != 0 && !CloseHandle(hand)) { hand = 0; - return false; setErrorString(QLatin1String("QSharedMemory::cleanHandle")); + return false; } hand = 0; return true; @@ -186,6 +186,7 @@ bool QSharedMemoryPrivate::detach() return false; } memory = 0; + size = 0; // close handle return cleanHandle(); diff --git a/src/corelib/kernel/qsystemsemaphore_symbian.cpp b/src/corelib/kernel/qsystemsemaphore_symbian.cpp index a25a119..0d257b8 100644 --- a/src/corelib/kernel/qsystemsemaphore_symbian.cpp +++ b/src/corelib/kernel/qsystemsemaphore_symbian.cpp @@ -73,6 +73,10 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function, int err) case KErrInUse: errorString = QCoreApplication::tr("%1: out of resources", "QSystemSemaphore").arg(function); error = QSystemSemaphore::OutOfResources; + break; + case KErrPermissionDenied: + errorString = QCoreApplication::tr("%1: permission denied", "QSystemSemaphore").arg(function); + error = QSystemSemaphore::PermissionDenied; break; default: errorString = QCoreApplication::tr("%1: unknown error %2", "QSystemSemaphore").arg(function).arg(err); @@ -86,15 +90,23 @@ default: int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode) { + if (semaphore.Handle()) { + return semaphore.Handle(); + } + // don't allow making handles on empty keys if (key.isEmpty()) return 0; - QString safeName = makeKeyFileName(); - TPtrC name(qt_QString2TPtrC(safeName)); - int err; - err = semaphore.OpenGlobal(name,EOwnerProcess); - if (err == KErrNotFound){ - err = semaphore.CreateGlobal(name,initialValue, EOwnerProcess); + + TPtrC name(qt_QString2TPtrC(fileName)); + int err = KErrAlreadyExists; + int tryCount = 10; + // Sort out race conditions by retrying several times until existing handle is acquired. + // Sometimes opening can fail inexplicably with KErrPermissionDenied many times in a row. + while (err != KErrNoMemory && err != KErrNone && tryCount-- >= 0) { + err = semaphore.CreateGlobal(name, initialValue, EOwnerProcess); + if (err != KErrNoMemory && err != KErrNone) + err = semaphore.OpenGlobal(name,EOwnerProcess); } if (err){ setErrorString(QLatin1String("QSystemSemaphore::handle"),err); diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp index 7f002f8..fad50f2 100644 --- a/src/corelib/kernel/qsystemsemaphore_win.cpp +++ b/src/corelib/kernel/qsystemsemaphore_win.cpp @@ -86,8 +86,7 @@ HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode) // Create it if it doesn't already exists. if (semaphore == 0) { - QString safeName = makeKeyFileName(); - semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)safeName.utf16()); + semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16()); if (semaphore == NULL) setErrorString(QLatin1String("QSystemSemaphore::handle")); } diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index b1bac9d..568293d 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/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/dbus/qdbusconnection.cpp b/src/dbus/qdbusconnection.cpp index eb312d2..3fb63eb 100644 --- a/src/dbus/qdbusconnection.cpp +++ b/src/dbus/qdbusconnection.cpp @@ -632,10 +632,26 @@ bool QDBusConnection::connect(const QString &service, const QString &path, const if (!receiver || !slot || !d || !d->connection) return false; - if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) - return false; if (interface.isEmpty() && name.isEmpty()) return false; + if (!interface.isEmpty() && !QDBusUtil::isValidInterfaceName(interface)) { +#ifndef QT_NO_DEBUG + qWarning("QDBusConnection::connect: interface name '%s' is not valid", interface.toLatin1().constData()); +#endif + return false; + } + if (!service.isEmpty() && !QDBusUtil::isValidBusName(service)) { +#ifndef QT_NO_DEBUG + qWarning("QDBusConnection::connect: service name '%s' is not valid", service.toLatin1().constData()); +#endif + return false; + } + if (!path.isEmpty() && !QDBusUtil::isValidObjectPath(path)) { +#ifndef QT_NO_DEBUG + qWarning("QDBusConnection::connect: object path '%s' is not valid", path.toLatin1().constData()); +#endif + return false; + } QDBusWriteLocker locker(ConnectAction, d); return d->connectSignal(service, path, interface, name, argumentMatch, signature, receiver, slot); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index adc3408..2e7b052 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; diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp index 16fb376..a851864 100644 --- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp +++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp @@ -215,11 +215,13 @@ 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. @@ -337,7 +339,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 diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index a2616dd..14388b3 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -299,7 +299,7 @@ void QDeclarativeFlickablePrivate::fixup(AxisData &data, qreal minExtent, qreal timeline.move(data.move, maxExtent - dist/2, QEasingCurve(QEasingCurve::InQuad), fixupDuration/4); timeline.move(data.move, maxExtent, QEasingCurve(QEasingCurve::OutExpo), 3*fixupDuration/4); } else { - timeline.set(data.move, minExtent); + timeline.set(data.move, maxExtent); } } vTime = timeline.time(); diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp index ba2523b..9e101b0 100644 --- a/src/declarative/graphicsitems/qdeclarativegridview.cpp +++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp @@ -2165,6 +2165,7 @@ void QDeclarativeGridView::positionViewAtIndex(int index, int mode) 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); @@ -2172,7 +2173,7 @@ void QDeclarativeGridView::positionViewAtIndex(int index, int mode) QList<FxGridItem*> oldVisible = d->visibleItems; d->visibleItems.clear(); d->visibleIndex = index - index % d->columns; - d->setPosition(itemPos); + 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)); @@ -2202,7 +2203,6 @@ void QDeclarativeGridView::positionViewAtIndex(int index, int mode) if (itemPos < pos) pos = itemPos; } - qreal maxExtent = d->flow == QDeclarativeGridView::LeftToRight ? -maxYExtent() : -maxXExtent(); pos = qMin(pos, maxExtent); qreal minExtent = d->flow == QDeclarativeGridView::LeftToRight ? -minYExtent() : -minXExtent(); pos = qMax(pos, minExtent); diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index 2e3a5a2..a99d918 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -799,10 +799,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 */ @@ -2116,13 +2124,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 +2145,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 @@ -2452,11 +2470,15 @@ QDeclarativeListProperty<QObject> QDeclarativeItemPrivate::resources() \qml Item { - states: [ - State { ... }, - State { ... } - ... - ] + states: [ + State { + // ... + }, + State { + // ... + } + // ... + ] } \endqml @@ -2474,11 +2496,15 @@ QDeclarativeListProperty<QDeclarativeState> QDeclarativeItemPrivate::states() \qml Item { - transitions: [ - Transition { ... }, - Transition { ... } - ... - ] + transitions: [ + Transition { + // ... + }, + Transition { + // ... + } + // ... + ] } \endqml @@ -2503,11 +2529,15 @@ QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeItemPrivate::transi \qml Item { - filter: [ - Blur { ... }, - Reflection { ... } - ... - ] + filter: [ + Blur { + // ... + }, + Reflection { + // ... + } + // ... + ] } \endqml */ @@ -2542,14 +2572,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 diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp index b4fd571..b4b3fa7 100644 --- a/src/declarative/graphicsitems/qdeclarativelistview.cpp +++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp @@ -2603,6 +2603,7 @@ void QDeclarativeListView::positionViewAtIndex(int index, int mode) 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 @@ -2610,7 +2611,7 @@ void QDeclarativeListView::positionViewAtIndex(int index, int mode) d->visibleItems.clear(); d->visiblePos = itemPos; d->visibleIndex = index; - d->setPosition(itemPos); + 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)); @@ -2640,7 +2641,6 @@ void QDeclarativeListView::positionViewAtIndex(int index, int mode) if (itemPos < pos) pos = itemPos; } - qreal maxExtent = d->orient == QDeclarativeListView::Vertical ? -maxYExtent() : -maxXExtent(); pos = qMin(pos, maxExtent); qreal minExtent = d->orient == QDeclarativeListView::Vertical ? -minYExtent() : -minXExtent(); pos = qMax(pos, minExtent); diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp index 86e438f..ded2be3 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader.cpp +++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp @@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE QDeclarativeLoaderPrivate::QDeclarativeLoaderPrivate() - : item(0), component(0), ownComponent(false), isComponentComplete(false) + : item(0), component(0), ownComponent(false) { } @@ -262,7 +262,6 @@ void QDeclarativeLoader::setSource(const QUrl &url) d->clear(); d->source = url; - if (d->source.isEmpty()) { emit sourceChanged(); emit statusChanged(); @@ -273,9 +272,18 @@ void QDeclarativeLoader::setSource(const QUrl &url) d->component = new QDeclarativeComponent(qmlEngine(this), d->source, this); d->ownComponent = true; - - if (d->isComponentComplete) - d->load(); + 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(); + } } /*! @@ -316,7 +324,6 @@ void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp) d->component = comp; d->ownComponent = false; - if (!d->component) { emit sourceChanged(); emit statusChanged(); @@ -325,8 +332,18 @@ void QDeclarativeLoader::setSourceComponent(QDeclarativeComponent *comp) return; } - if (d->isComponentComplete) - d->load(); + 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(); + } } void QDeclarativeLoader::resetSourceComponent() @@ -334,27 +351,6 @@ void QDeclarativeLoader::resetSourceComponent() setSourceComponent(0); } -void QDeclarativeLoaderPrivate::load() -{ - Q_Q(QDeclarativeLoader); - - if (!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); @@ -469,11 +465,9 @@ QDeclarativeLoader::Status QDeclarativeLoader::status() const void QDeclarativeLoader::componentComplete() { - Q_D(QDeclarativeLoader); - QDeclarativeItem::componentComplete(); - d->isComponentComplete = true; - d->load(); + if (status() == Ready) + emit loaded(); } diff --git a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h index 81ca66d..45ab595 100644 --- a/src/declarative/graphicsitems/qdeclarativeloader_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativeloader_p_p.h @@ -72,13 +72,11 @@ 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 isComponentComplete : 1; void _q_sourceLoaded(); void _q_updateSize(bool loaderGeometryChanged = true); 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..306575e 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 */ diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp index 4e049c7..e0bd2ff 100644 --- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp +++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp @@ -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 diff --git a/src/declarative/graphicsitems/qdeclarativerectangle.cpp b/src/declarative/graphicsitems/qdeclarativerectangle.cpp index 403f12c..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 */ diff --git a/src/declarative/graphicsitems/qdeclarativescalegrid.cpp b/src/declarative/graphicsitems/qdeclarativescalegrid.cpp index 804e91d..3ad0da6 100644 --- a/src/declarative/graphicsitems/qdeclarativescalegrid.cpp +++ b/src/declarative/graphicsitems/qdeclarativescalegrid.cpp @@ -136,12 +136,12 @@ QDeclarativeGridScaledImage::QDeclarativeGridScaledImage(QIODevice *data) if (line.isEmpty() || line.startsWith(QLatin1Char('#'))) continue; - QStringList list = line.split(QLatin1Char(':')); - if (list.count() != 2) + int colonId = line.indexOf(QLatin1Char(':')); + if (colonId <= 0) return; - - list[0] = list[0].trimmed(); - list[1] = list[1].trimmed(); + QStringList list; + list.append(line.left(colonId).trimmed()); + list.append(line.mid(colonId+1).trimmed()); if (list[0] == QLatin1String("border.left")) l = list[1].toInt(); diff --git a/src/declarative/graphicsitems/qdeclarativetext.cpp b/src/declarative/graphicsitems/qdeclarativetext.cpp index 2f3c8e5..d56035e 100644 --- a/src/declarative/graphicsitems/qdeclarativetext.cpp +++ b/src/declarative/graphicsitems/qdeclarativetext.cpp @@ -558,11 +558,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 @@ -736,19 +749,28 @@ QDeclarativeText::~QDeclarativeText() QFont QDeclarativeText::font() const { Q_D(const QDeclarativeText); - return d->font; + return d->sourceFont; } void QDeclarativeText::setFont(const QFont &font) { Q_D(QDeclarativeText); - if (d->font == font) + if (d->sourceFont == font) return; + d->sourceFont = font; + QFont oldFont = d->font; d->font = font; - d->updateLayout(); + if (d->font.pointSizeF() != -1) { + // 0.5pt resolution + qreal size = qRound(d->font.pointSizeF()*2.0); + d->font.setPointSizeF(size/2.0); + } - emit fontChanged(d->font); + if (oldFont != d->font) + d->updateLayout(); + + emit fontChanged(d->sourceFont); } /*! @@ -789,12 +811,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 diff --git a/src/declarative/graphicsitems/qdeclarativetext_p_p.h b/src/declarative/graphicsitems/qdeclarativetext_p_p.h index 67f2289..e749bc9 100644 --- a/src/declarative/graphicsitems/qdeclarativetext_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetext_p_p.h @@ -79,6 +79,7 @@ public: QString text; QFont font; + QFont sourceFont; QColor color; QDeclarativeText::TextStyle style; QColor styleColor; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp index 675f8d9..19c0f2d 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp @@ -326,22 +326,35 @@ void QDeclarativeTextEdit::setTextFormat(TextFormat format) QFont QDeclarativeTextEdit::font() const { Q_D(const QDeclarativeTextEdit); - return d->font; + return d->sourceFont; } void QDeclarativeTextEdit::setFont(const QFont &font) { Q_D(QDeclarativeTextEdit); + if (d->sourceFont == font) + return; + + d->sourceFont = font; + QFont oldFont = d->font; d->font = font; + if (d->font.pointSizeF() != -1) { + // 0.5pt resolution + qreal size = qRound(d->font.pointSizeF()*2.0); + d->font.setPointSizeF(size/2.0); + } - clearCache(); - d->document->setDefaultFont(d->font); - if(d->cursor){ - d->cursor->setHeight(QFontMetrics(d->font).height()); - moveCursorDelegate(); + if (oldFont != d->font) { + clearCache(); + d->document->setDefaultFont(d->font); + if(d->cursor){ + d->cursor->setHeight(QFontMetrics(d->font).height()); + moveCursorDelegate(); + } + updateSize(); + update(); } - updateSize(); - update(); + emit fontChanged(d->sourceFont); } /*! @@ -350,11 +363,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 @@ -1352,8 +1367,12 @@ void QDeclarativeTextEdit::updateSize() int dy = height(); // ### assumes that if the width is set, the text will fill to edges // ### (unless wrap is false, then clipping will occur) - if (widthValid() && d->document->textWidth() != width()) - d->document->setTextWidth(width()); + if (widthValid()) { + if (d->document->textWidth() != width()) + d->document->setTextWidth(width()); + } else { + d->document->setTextWidth(-1); + } dy -= (int)d->document->size().height(); int nyoff; diff --git a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h index 68a9cc8..3a45541 100644 --- a/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextedit_p_p.h @@ -92,6 +92,7 @@ public: QString text; QFont font; + QFont sourceFont; QColor color; QColor selectionColor; QColor selectedTextColor; diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp index 57a2177..6f02471 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp +++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp @@ -213,24 +213,33 @@ void QDeclarativeTextInput::setText(const QString &s) QFont QDeclarativeTextInput::font() const { Q_D(const QDeclarativeTextInput); - return d->font; + return d->sourceFont; } void QDeclarativeTextInput::setFont(const QFont &font) { Q_D(QDeclarativeTextInput); - if (d->font == font) + if (d->sourceFont == font) return; + d->sourceFont = font; + QFont oldFont = d->font; d->font = font; + if (d->font.pointSizeF() != -1) { + // 0.5pt resolution + qreal size = qRound(d->font.pointSizeF()*2.0); + d->font.setPointSizeF(size/2.0); + } - d->control->setFont(d->font); - if(d->cursorItem){ - d->cursorItem->setHeight(QFontMetrics(d->font).height()); - moveCursor(); + if (oldFont != d->font) { + d->control->setFont(d->font); + if(d->cursorItem){ + d->cursorItem->setHeight(QFontMetrics(d->font).height()); + moveCursor(); + } + updateSize(); } - updateSize(); - emit fontChanged(d->font); + emit fontChanged(d->sourceFont); } /*! @@ -520,10 +529,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 { diff --git a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h index 18e9c81..16827b3 100644 --- a/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h +++ b/src/declarative/graphicsitems/qdeclarativetextinput_p_p.h @@ -107,6 +107,7 @@ public: QLineControl* control; QFont font; + QFont sourceFont; QColor color; QColor selectionColor; QColor selectedTextColor; diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index af955a4..4dfef45 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -619,7 +619,7 @@ int Lexer::lex() } else { setDone(Bad); err = IllegalEscapeSequence; - errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal escape squence"); + errmsg = QCoreApplication::translate("QDeclarativeParser", "Illegal escape sequence"); } } else if (current == 'x') state = InHexEscape; diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp index e2cbdcf..f716f85 100644 --- a/src/declarative/qml/qdeclarativecomponent.cpp +++ b/src/declarative/qml/qdeclarativecomponent.cpp @@ -627,6 +627,10 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q must provide a valid \a parent value or set the returned object's \l{Item::parent}{parent} property, or else the object will not be visible. + If a \a parent is not provided to createObject(), a reference to the returned object must be held so that + 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. + Dynamically created instances can be deleted with the \c destroy() method. See \l {Dynamic Object Management in QML} for more information. */ 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 e0c6e1a..e602781 100644 --- a/src/declarative/qml/qdeclarativeengine.cpp +++ b/src/declarative/qml/qdeclarativeengine.cpp @@ -1872,14 +1872,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 diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index e7dae98..8210314 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -665,7 +665,7 @@ QDeclarativePropertyPrivate::binding(QObject *object, int coreIndex, int valueTy static_cast<const QDeclarativeVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex)); QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1; - if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) + if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1) return 0; // This will either be a value type sub-reference or an alias to a value-type sub-reference not both diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 6d49625..fb07bef 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -938,8 +938,13 @@ QObject *QDeclarativeVME::run(QDeclarativeVMEStack<QObject *> &stack, if (bindValues.count) ep->bindValues << bindValues; + else if (bindValues.values) + bindValues.clear(); + if (parserStatus.count) ep->parserStatus << parserStatus; + else if (parserStatus.values) + parserStatus.clear(); Q_ASSERT(stack.count() == 1); return stack.top(); diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp index ac13c68..6283f92 100644 --- a/src/declarative/qml/qdeclarativeworkerscript.cpp +++ b/src/declarative/qml/qdeclarativeworkerscript.cpp @@ -544,12 +544,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 diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 2e0bcf4..a9a639b 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 and Transitions}, 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/qdeclarativeconnections.cpp b/src/declarative/util/qdeclarativeconnections.cpp index 9604901..e986ac9 100644 --- a/src/declarative/util/qdeclarativeconnections.cpp +++ b/src/declarative/util/qdeclarativeconnections.cpp @@ -71,8 +71,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. 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/qdeclarativestate.cpp b/src/declarative/util/qdeclarativestate.cpp index bb1a0b8..c41d39a 100644 --- a/src/declarative/util/qdeclarativestate.cpp +++ b/src/declarative/util/qdeclarativestate.cpp @@ -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 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 dd49dde..9a5aa66 100644 --- a/src/declarative/util/qdeclarativestateoperations.cpp +++ b/src/declarative/util/qdeclarativestateoperations.cpp @@ -634,7 +634,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 { diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/declarative/util/qdeclarativetransition.cpp index 47855f6..1a574b8 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/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp index 7da4ecd..6b13e88 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 } @@ -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/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a892094..52e4d79 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5592,9 +5592,8 @@ void QGraphicsItemPrivate::clearSubFocus(QGraphicsItem *rootItem, QGraphicsItem if (parent->d_ptr->subFocusItem != q_ptr) break; parent->d_ptr->subFocusItem = 0; - if (parent == stopItem) - break; - parent->d_ptr->subFocusItemChange(); + if (parent != stopItem && !parent->isAncestorOf(stopItem)) + parent->d_ptr->subFocusItemChange(); } while (!parent->isPanel() && (parent = parent->d_ptr->parent)); } diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp index 8f833f8..cd30dfb 100644 --- a/src/gui/graphicsview/qgridlayoutengine.cpp +++ b/src/gui/graphicsview/qgridlayoutengine.cpp @@ -194,7 +194,8 @@ void QGridLayoutRowData::distributeMultiCells(const QGridLayoutRowInfo &rowInfo) for (int k = 0; k < span; ++k) { boxes[start + k].combine(extras[k]); - stretches[start + k] = qMax(stretches[start + k], stretch); + if (stretch != 0) + stretches[start + k] = qMax(stretches[start + k], stretch); } } multiCellMap.clear(); @@ -1472,7 +1473,7 @@ void QGridLayoutEngine::fillRowData(QGridLayoutRowData *rowData, const QLayoutSt QGridLayoutBox *box; if (effectiveRowSpan == 1) { box = &rowBox; - if (!userRowStretch) + if (!userRowStretch && itemStretch != 0) rowStretch = qMax(rowStretch, itemStretch); } else { QGridLayoutMultiCellData &multiCell = diff --git a/src/gui/image/qgifhandler.cpp b/src/gui/image/qgifhandler.cpp index 4dd4743..7cb7373 100644 --- a/src/gui/image/qgifhandler.cpp +++ b/src/gui/image/qgifhandler.cpp @@ -1046,7 +1046,7 @@ QGifHandler::QGifHandler() { gifFormat = new QGIFFormat; nextDelay = 100; - loopCnt = 1; + loopCnt = -1; frameNumber = -1; scanIsCached = false; } @@ -1192,7 +1192,13 @@ int QGifHandler::loopCount() const QGIFFormat::scan(device(), &imageSizes, &loopCnt); scanIsCached = true; } - return loopCnt-1; // In GIF, loop count is iteration count, so subtract one + + if (loopCnt == 0) + return -1; + else if (loopCnt == -1) + return 0; + else + return loopCnt; } int QGifHandler::currentImageNumber() const diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index ff199b1..1bef64d 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -706,6 +706,7 @@ void QCoeFepInputContext::CancelFepInlineEdit() QInputMethodEvent event(QLatin1String(""), attributes); event.setCommitString(QLatin1String(""), 0, 0); m_preeditString.clear(); + m_inlinePosition = 0; sendEvent(event); } @@ -853,6 +854,7 @@ void QCoeFepInputContext::commitCurrentString(bool cancelFepTransaction) QInputMethodEvent event(QLatin1String(""), attributes); event.setCommitString(m_preeditString, 0, 0); m_preeditString.clear(); + m_inlinePosition = 0; sendEvent(event); m_hasTempPreeditString = false; diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 37507dd..081a6d9 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -622,9 +622,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 789f198..40a7ec6 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -1616,7 +1616,7 @@ void qt_init(QApplicationPrivate * /* priv */, int) qRegisterMetaType<WId>("WId"); } -extern void qt_cleanup_symbianFontDatabaseExtras(); // qfontdatabase_s60.cpp +extern void qt_cleanup_symbianFontDatabase(); // qfontdatabase_s60.cpp /***************************************************************************** qt_cleanup() - cleans up when the application is finished @@ -1630,7 +1630,7 @@ 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 - qt_cleanup_symbianFontDatabaseExtras(); + qt_cleanup_symbianFontDatabase(); // 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 @@ -2016,6 +2016,9 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent S60->wsSession().SetPointerCursorMode(EPointerCursorNormal); } #endif +#ifdef QT_SOFTKEYS_ENABLED + QSoftKeyManager::updateSoftKeys(); +#endif break; case EEventFocusLost: if (callSymbianEventFilters(symbianEvent)) diff --git a/src/gui/kernel/qkeymapper_x11_p.cpp b/src/gui/kernel/qkeymapper_x11_p.cpp index 1fad4b0..2dbe1e7 100644 --- a/src/gui/kernel/qkeymapper_x11_p.cpp +++ b/src/gui/kernel/qkeymapper_x11_p.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ // This file is auto-generated, do not edit! +// (Generated using util/xkbdatagen) static struct { const char *layout; 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 462b30b..3820bfc 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -994,6 +994,7 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev Qt::KeyboardModifiers keyMods = qt_cocoaModifiers2QtModifiers([theEvent modifierFlags]); NSInteger clickCount = [theEvent clickCount]; Qt::MouseButtons buttons = 0; + static Qt::MouseButton previousButton = Qt::NoButton; { UInt32 mac_buttons; if (GetEventParameter(carbonEvent, kEventParamMouseChord, typeUInt32, 0, @@ -1012,7 +1013,7 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev #ifndef QT_NAMESPACE Q_ASSERT(clickCount > 0); #endif - if (clickCount % 2 == 0 && buttons == button) + if (clickCount % 2 == 0 && (previousButton == Qt::NoButton || previousButton == button)) eventType = QEvent::MouseButtonDblClick; if (button == Qt::LeftButton && (keyMods & Qt::MetaModifier)) { button = Qt::RightButton; @@ -1046,6 +1047,7 @@ bool qt_mac_handleMouseEvent(void * /* NSView * */view, void * /* NSEvent * */ev QContextMenuEvent qcme(QContextMenuEvent::Mouse, qlocalPoint, qglobalPoint, keyMods); qt_sendSpontaneousEvent(widgetToGetMouse, &qcme); } + previousButton = button; return true; #endif } diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 693984a..3759dd1 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -767,6 +767,8 @@ public: void x11UpdateIsOpaque(); bool isBackgroundInherited() const; void updateX11AcceptFocus(); + QPoint mapToGlobal(const QPoint &pos) const; + QPoint mapFromGlobal(const QPoint &pos) const; #elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine() #ifndef QT_NO_GESTURES diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index a93c545..9893478 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -1280,39 +1280,77 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f) #endif } - -QPoint QWidget::mapToGlobal(const QPoint &pos) const +QPoint QWidgetPrivate::mapToGlobal(const QPoint &pos) const { - Q_D(const QWidget); - if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { - QPoint p = pos + data->crect.topLeft(); + Q_Q(const QWidget); + if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) { + QPoint p = pos + q->data->crect.topLeft(); //cannot trust that !isWindow() implies parentWidget() before create - return (isWindow() || !parentWidget()) ? p : parentWidget()->mapToGlobal(p); + return (q->isWindow() || !q->parentWidget()) ? p : q->parentWidget()->d_func()->mapToGlobal(p); } - int x, y; + int x, y; Window child; - QPoint p = d->mapToWS(pos); - XTranslateCoordinates(X11->display, internalWinId(), - QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(), + QPoint p = mapToWS(pos); + XTranslateCoordinates(X11->display, q->internalWinId(), + QApplication::desktop()->screen(xinfo.screen())->internalWinId(), p.x(), p.y(), &x, &y, &child); return QPoint(x, y); } - -QPoint QWidget::mapFromGlobal(const QPoint &pos) const +QPoint QWidgetPrivate::mapFromGlobal(const QPoint &pos) const { - Q_D(const QWidget); - if (!testAttribute(Qt::WA_WState_Created) || !internalWinId()) { + Q_Q(const QWidget); + if (!q->testAttribute(Qt::WA_WState_Created) || !q->internalWinId()) { //cannot trust that !isWindow() implies parentWidget() before create - QPoint p = (isWindow() || !parentWidget()) ? pos : parentWidget()->mapFromGlobal(pos); - return p - data->crect.topLeft(); + QPoint p = (q->isWindow() || !q->parentWidget()) ? pos : q->parentWidget()->d_func()->mapFromGlobal(pos); + return p - q->data->crect.topLeft(); } - int x, y; + int x, y; Window child; XTranslateCoordinates(X11->display, - QApplication::desktop()->screen(d->xinfo.screen())->internalWinId(), - internalWinId(), pos.x(), pos.y(), &x, &y, &child); - return d->mapFromWS(QPoint(x, y)); + QApplication::desktop()->screen(xinfo.screen())->internalWinId(), + q->internalWinId(), pos.x(), pos.y(), &x, &y, &child); + return mapFromWS(QPoint(x, y)); +} + +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); } void QWidgetPrivate::updateSystemBackground() diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 9928dea..5904296 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -43,7 +43,9 @@ #include <private/qpaintengine_raster_p.h> #include <private/qpainter_p.h> #include <private/qdrawhelper_x86_p.h> +#ifdef QT_HAVE_ARM_SIMD #include <private/qdrawhelper_arm_simd_p.h> +#endif #include <private/qdrawhelper_neon_p.h> #include <private/qmath_p.h> #include <qmath.h> diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index bf3a240..38a4b7c 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -96,7 +96,8 @@ const layoutHeader QS60StylePrivate::m_layoutHeaders[] = { {320,240,1,19,"QVGA Portrait"}, {360,640,1,19,"NHD Landscape"}, {640,360,1,19,"NHD Portrait"}, -{352,800,1,12,"E90 Landscape"} +{352,800,1,12,"E90 Landscape"}, +{480,640,1,19,"VGA Landscape"} // *** End of generated data *** }; const int QS60StylePrivate::m_numberOfLayouts = @@ -108,7 +109,8 @@ const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = { {5,0,-909,0,0,1,0,2,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,28,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1,106}, {7,0,-909,0,0,2,0,5,-1,25,69,46,37,37,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,44,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,3,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1,135}, {7,0,-909,0,0,2,0,5,-1,25,68,46,37,37,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,52,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,3,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1,135}, -{7,0,-909,0,0,2,0,2,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,30,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1,106} +{7,0,-909,0,0,2,0,2,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,30,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1,106}, +{9,0,-909,0,0,2,0,5,-1,34,99,76,51,51,25,352,-909,-909,-909,29,25,7,0,0,43,34,42,76,7,7,2,-909,-909,0,9,14,0,23,39,30,30,37,37,9,391,40,0,-909,-909,-909,-909,0,0,29,2,-909,0,0,-909,29,-909,-909,-909,-909,115,37,96,48,96,19,19,9,1,25,-909,9,101,24,9,0,7,7,7,16,7,7,-909,3,-909,-909,-909,-909,9,9,3,1,184} // *** End of generated data *** }; diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index 04c40aa..605872e 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -1378,12 +1378,13 @@ QPixmap QS60StylePrivate::frame(SkinFrameElements frame, const QSize &size, Skin QPixmap QS60StylePrivate::backgroundTexture() { bool createNewBackground = false; + TRect applicationRect = (static_cast<CEikAppUi*>(S60->appUi())->ApplicationRect()); if (!m_background) { createNewBackground = true; } else { //if background brush does not match screensize, re-create it - if (m_background->width() != S60->screenWidthInPixels || - m_background->height() != S60->screenHeightInPixels) { + if (m_background->width() != applicationRect.Width() || + m_background->height() != applicationRect.Height()) { delete m_background; createNewBackground = true; } @@ -1391,7 +1392,7 @@ QPixmap QS60StylePrivate::backgroundTexture() if (createNewBackground) { QPixmap background = part(QS60StyleEnums::SP_QsnBgScreen, - QSize(S60->screenWidthInPixels, S60->screenHeightInPixels), 0, SkinElementFlags()); + QSize(applicationRect.Width(), applicationRect.Height()), 0, SkinElementFlags()); m_background = new QPixmap(background); } return *m_background; @@ -1411,7 +1412,6 @@ QS60Style::QS60Style() void QS60StylePrivate::handleDynamicLayoutVariantSwitch() { clearCaches(QS60StylePrivate::CC_LayoutChange); - setBackgroundTexture(qApp); setActiveLayout(); refreshUI(); foreach (QWidget *widget, QApplication::allWidgets()) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 5cecf08..6b612eb 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -624,6 +624,10 @@ public: { } ~QFontDatabasePrivate() { free(); +#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) + if (symbianExtras) + delete symbianExtras; +#endif } QtFontFamily *family(const QString &f, bool = false); void free() { @@ -632,12 +636,6 @@ public: ::free(families); families = 0; count = 0; -#if defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) - if (symbianExtras) { - delete symbianExtras; - symbianExtras = 0; - } -#endif // don't clear the memory fonts! } @@ -653,6 +651,10 @@ public: QVector<FONTSIGNATURE> signatures; #elif defined(Q_WS_MAC) ATSFontContainerRef handle; +#elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) + QString temporaryFileName; + TInt screenDeviceFontFileId; + TUid fontStoreFontFileUid; #endif QStringList families; }; @@ -680,7 +682,7 @@ public: QDataStream *stream; QStringList fallbackFamilies; #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) - const QSymbianFontDatabaseExtras *symbianExtras; + QSymbianFontDatabaseExtras *symbianExtras; #endif }; @@ -2541,6 +2543,8 @@ bool QFontDatabasePrivate::isApplicationFont(const QString &fileName) \note Adding application fonts on Unix/X11 platforms without fontconfig is currently not supported. + \note On Symbian, the font family names get truncated to a length of 20 characters. + \sa addApplicationFontFromData(), applicationFontFamilies(), removeApplicationFont() */ int QFontDatabase::addApplicationFont(const QString &fileName) @@ -2571,6 +2575,8 @@ int QFontDatabase::addApplicationFont(const QString &fileName) \bold{Note:} Adding application fonts on Unix/X11 platforms without fontconfig is currently not supported. + \note On Symbian, the font family names get truncated to a length of 20 characters. + \sa addApplicationFont(), applicationFontFamilies(), removeApplicationFont() */ int QFontDatabase::addApplicationFontFromData(const QByteArray &fontData) diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp index 6ba035e..97426a8 100644 --- a/src/gui/text/qfontdatabase_s60.cpp +++ b/src/gui/text/qfontdatabase_s60.cpp @@ -45,6 +45,8 @@ #include "qfontengine_s60_p.h" #include "qabstractfileengine.h" #include "qdesktopservices.h" +#include "qtemporaryfile.h" +#include "qtextcodec.h" #include <private/qpixmap_s60_p.h> #include <private/qt_s60_p.h> #include "qendian.h" @@ -114,7 +116,14 @@ public: ~QSymbianFontDatabaseExtrasImplementation(); const QSymbianTypeFaceExtras *extras(const QString &typeface, bool bold, bool italic) const; - void addFontFileToFontStore(const QFileInfo &fontFileInfo); + void removeAppFontData(QFontDatabasePrivate::ApplicationFont *fnt); + static inline bool appFontLimitReached(); + TUid addFontFileToFontStore(const QFileInfo &fontFileInfo); + static void clear(); + + static inline QString tempAppFontFolder(); + static const QString appFontMarkerPrefix; + static QString appFontMarker(); // 'qaf<shortUid[+shortPid]>' struct CFontFromFontStoreReleaser { static inline void cleanup(CFont *font) @@ -144,8 +153,75 @@ public: mutable QList<const QSymbianTypeFaceExtras *> m_extras; mutable QHash<QString, const QSymbianTypeFaceExtras *> m_extrasHash; + mutable QSet<QString> m_applicationFontFamilies; }; +const QString QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix = + QLatin1String("Q"); + +inline QString QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() +{ + return QDir::toNativeSeparators(QDir::tempPath()) + QLatin1Char('\\'); +} + +QString QSymbianFontDatabaseExtrasImplementation::appFontMarker() +{ + static QString result; + if (result.isEmpty()) { + quint16 id = 0; + if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { + // We are allowed to load app fonts even from previous, crashed runs + // of this application, since we can access the font tables. + const quint32 uid = RProcess().Type().MostDerived().iUid; + id = static_cast<quint16>(uid + (uid >> 16)); + } else { + // If no font table Api is available, we must not even load a font + // from a previous (crashed) run of this application. Reason: we + // won't get the font tables, they are not in the CFontStore. + // So, we use the pid, for more uniqueness. + id = static_cast<quint16>(RProcess().Id().Id()); + } + result = appFontMarkerPrefix + QString::fromLatin1("%1").arg(id & 0x7fff, 3, 32, QLatin1Char('0')); + Q_ASSERT(appFontMarkerPrefix.length() == 1 && result.length() == 4); + } + return result; +} + +static inline bool qt_symbian_fontNameHasAppFontMarker(const QString &fontName) +{ + const int idLength = 3; // Keep in sync with id length in appFontMarker(). + const QString &prefix = QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix; + if (fontName.length() < prefix.length() + idLength + || fontName.mid(fontName.length() - idLength - prefix.length(), prefix.length()) != prefix) + return false; + // Testing if the the id is base32 data + for (int i = fontName.length() - idLength; i < fontName.length(); ++i) { + const QChar &c = fontName.at(i); + if (!(c >= QLatin1Char('0') && c <= QLatin1Char('9') + || c >= QLatin1Char('a') && c <= QLatin1Char('v'))) + return false; + } + return true; +} + +// If fontName is an application font of this app, prepend the app font marker +QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName) +{ + QFontDatabasePrivate *db = privateDb(); + Q_ASSERT(db); + const QSymbianFontDatabaseExtrasImplementation *dbExtras = + static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); + return dbExtras->m_applicationFontFamilies.contains(fontName) ? + fontName + QSymbianFontDatabaseExtrasImplementation::appFontMarker() + : fontName; +} + +static inline QString qt_symbian_appFontNameWithoutMarker(const QString &markedFontName) +{ + return markedFontName.left(markedFontName.length() + - QSymbianFontDatabaseExtrasImplementation::appFontMarker().length()); +} + QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementation() { if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { @@ -170,10 +246,13 @@ QSymbianFontDatabaseExtrasImplementation::QSymbianFontDatabaseExtrasImplementati } } -void qt_cleanup_symbianFontDatabaseExtras() +void QSymbianFontDatabaseExtrasImplementation::clear() { + QFontDatabasePrivate *db = privateDb(); + if (!db) + return; const QSymbianFontDatabaseExtrasImplementation *dbExtras = - static_cast<const QSymbianFontDatabaseExtrasImplementation*>(privateDb()->symbianExtras); + static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); if (!dbExtras) return; // initializeDb() has never been called if (QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { @@ -189,9 +268,32 @@ void qt_cleanup_symbianFontDatabaseExtras() dbExtras->m_extrasHash.clear(); } +void qt_cleanup_symbianFontDatabase() +{ + QFontDatabasePrivate *db = privateDb(); + if (!db) + return; + + QSymbianFontDatabaseExtrasImplementation::clear(); + + if (!db->applicationFonts.isEmpty()) { + QFontDatabase::removeAllApplicationFonts(); + // We remove the left over temporary font files of Qt application. + // Active fonts are undeletable since the font server holds a handle + // on them, so we do not need to worry to delete other running + // applications' fonts. + const QDir dir(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder()); + const QStringList filter( + QSymbianFontDatabaseExtrasImplementation::appFontMarkerPrefix + QLatin1String("*.ttf")); + foreach (const QFileInfo &ttfFile, dir.entryInfoList(filter)) + QFile(ttfFile.absoluteFilePath()).remove(); + db->applicationFonts.clear(); + } +} + QSymbianFontDatabaseExtrasImplementation::~QSymbianFontDatabaseExtrasImplementation() { - qt_cleanup_symbianFontDatabaseExtras(); + qt_cleanup_symbianFontDatabase(); if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) { delete m_store; m_heap->Close(); @@ -215,9 +317,10 @@ COpenFont* OpenFontFromBitmapFont(const CBitmapFont* aBitmapFont) } #endif // FNTSTORE_H_INLINES_SUPPORT_FMM -const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &typeface, +const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(const QString &aTypeface, bool bold, bool italic) const { + const QString typeface = qt_symbian_fontNameWithAppFontMarker(aTypeface); const QString searchKey = typeface + QString::number(int(bold)) + QString::number(int(italic)); if (!m_extrasHash.contains(searchKey)) { TFontSpec searchSpec(qt_QString2TPtrC(typeface), 1); @@ -263,12 +366,42 @@ const QSymbianTypeFaceExtras *QSymbianFontDatabaseExtrasImplementation::extras(c return m_extrasHash.value(searchKey); } -void QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo) +void QSymbianFontDatabaseExtrasImplementation::removeAppFontData( + QFontDatabasePrivate::ApplicationFont *fnt) +{ + clear(); + if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable() + && fnt->fontStoreFontFileUid.iUid != 0) + m_store->RemoveFile(fnt->fontStoreFontFileUid); + if (!fnt->families.isEmpty()) + m_applicationFontFamilies.remove(fnt->families.first()); + if (fnt->screenDeviceFontFileId != 0) + S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); + QFile::remove(fnt->temporaryFileName); + *fnt = QFontDatabasePrivate::ApplicationFont(); +} + +bool QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() +{ + QFontDatabasePrivate *db = privateDb(); + if (!db) + return false; + const int maxAppFonts = 5; + int registeredAppFonts = 0; + foreach (const QFontDatabasePrivate::ApplicationFont &appFont, db->applicationFonts) + if (!appFont.families.isEmpty() && ++registeredAppFonts == maxAppFonts) + return true; + return false; +} + +TUid QSymbianFontDatabaseExtrasImplementation::addFontFileToFontStore(const QFileInfo &fontFileInfo) { Q_ASSERT(!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()); const QString fontFile = QDir::toNativeSeparators(fontFileInfo.absoluteFilePath()); - TPtrC fontFilePtr(qt_QString2TPtrC(fontFile)); - QT_TRAP_THROWING(m_store->AddFileL(fontFilePtr)); + const TPtrC fontFilePtr(qt_QString2TPtrC(fontFile)); + TUid fontUid = {0}; + TRAP_IGNORE(fontUid = m_store->AddFileL(fontFilePtr)); + return fontUid; } #else // QT_NO_FREETYPE @@ -331,11 +464,23 @@ void QFontEngineMultiS60::loadEngine(int at) Q_ASSERT(engines[at]); } -static bool addFontToScreenDevice(int screenDeviceFontIndex, - const QSymbianFontDatabaseExtrasImplementation *dbExtras) -{ +static bool registerScreenDeviceFont(int screenDeviceFontIndex, + const QSymbianFontDatabaseExtrasImplementation *dbExtras) +{ TTypefaceSupport typefaceSupport; S60->screenDevice()->TypefaceSupport(typefaceSupport, screenDeviceFontIndex); + + QString familyName((const QChar*)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); + if (qt_symbian_fontNameHasAppFontMarker(familyName)) { + const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); + if (familyName.endsWith(marker)) { + familyName = qt_symbian_appFontNameWithoutMarker(familyName); + dbExtras->m_applicationFontFamilies.insert(familyName); + } else { + return false; // This was somebody else's application font. Skip it. + } + } + CFont *font; // We have to get a font instance in order to know all the details TFontSpec fontSpec(typefaceSupport.iTypeface.iName, 11); if (S60->screenDevice()->GetNearestFontInPixels(font, fontSpec) != KErrNone) @@ -351,7 +496,6 @@ static bool addFontToScreenDevice(int screenDeviceFontIndex, styleKey.style = faceAttrib.IsItalic()?QFont::StyleItalic:QFont::StyleNormal; styleKey.weight = faceAttrib.IsBold()?QFont::Bold:QFont::Normal; - QString familyName((const QChar *)typefaceSupport.iTypeface.iName.Ptr(), typefaceSupport.iTypeface.iName.Length()); QtFontFamily *family = privateDb()->family(familyName, true); family->fixedPitch = faceAttrib.IsMonoWidth(); QtFontFoundry *foundry = family->foundry(QString(), true); @@ -398,7 +542,12 @@ static void initializeDb() const QSymbianFontDatabaseExtrasImplementation *dbExtras = static_cast<const QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); for (int i = 0; i < numTypeFaces; i++) - addFontToScreenDevice(i, dbExtras); + registerScreenDeviceFont(i, dbExtras); + + // We have to clear/release all CFonts, here, in case one of the fonts is + // an application font of another running Qt app. Otherwise the other Qt app + // cannot remove it's application font, anymore -> "Zombie Font". + QSymbianFontDatabaseExtrasImplementation::clear(); lock.relock(); @@ -421,20 +570,386 @@ static inline void load(const QString &family = QString(), int script = -1) initializeDb(); } +struct OffsetTable { + quint32 sfntVersion; + quint16 numTables, searchRange, entrySelector, rangeShift; +}; + +struct TableRecord { + quint32 tag, checkSum, offset, length; +}; + +struct NameTableHead { + quint16 format, count, stringOffset; +}; + +struct NameRecord { + quint16 platformID, encodingID, languageID, nameID, length, offset; +}; + +static quint32 ttfCalcChecksum(const char *data, quint32 bytesCount) +{ + quint32 result = 0; + const quint32 *ptr = reinterpret_cast<const quint32*>(data); + const quint32 *endPtr = + ptr + (bytesCount + sizeof(quint32) - 1) / sizeof(quint32); + while (ptr < endPtr) { + const quint32 unit32Value = *ptr++; + result += qFromBigEndian(unit32Value); + } + return result; +} + +static inline quint32 toDWordBoundary(quint32 value) +{ + return (value + 3) & ~3; +} + +static inline quint32 dWordPadding(quint32 value) +{ + return (4 - (value & 3)) & 3; +} + +static inline bool ttfMarkNameTable(QByteArray &table, const QString &marker) +{ + const quint32 tableLength = static_cast<quint32>(table.size()); + + if (tableLength > 50000 // hard limit + || tableLength < sizeof(NameTableHead)) // corrupt name table + return false; + + const NameTableHead *head = reinterpret_cast<const NameTableHead*>(table.constData()); + const quint16 count = qFromBigEndian(head->count); + const quint16 stringOffset = qFromBigEndian(head->stringOffset); + if (count > 200 // hard limit + || stringOffset >= tableLength // corrupt name table + || sizeof(NameTableHead) + count * sizeof(NameRecord) >= tableLength) // corrupt name table + return false; + + QTextEncoder encoder(QTextCodec::codecForName("UTF-16BE"), QTextCodec::IgnoreHeader); + const QByteArray markerUtf16BE = encoder.fromUnicode(marker); + const QByteArray markerAscii = marker.toAscii(); + + QByteArray markedTable; + markedTable.reserve(tableLength + marker.length() * 20); // Original size plus some extra + markedTable.append(table, stringOffset); + QByteArray markedStrings; + quint32 stringDataCount = stringOffset; + for (quint16 i = 0; i < count; ++i) { + const quint32 nameRecordOffset = sizeof(NameTableHead) + sizeof(NameRecord) * i; + NameRecord *nameRecord = + reinterpret_cast<NameRecord*>(markedTable.data() + nameRecordOffset); + const quint16 nameID = qFromBigEndian(nameRecord->nameID); + const quint16 platformID = qFromBigEndian(nameRecord->platformID); + const quint16 encodingID = qFromBigEndian(nameRecord->encodingID); + const quint16 offset = qFromBigEndian(nameRecord->offset); + const quint16 length = qFromBigEndian(nameRecord->length); + stringDataCount += length; + if (stringDataCount > 80000 // hard limit. String data may be > name table size. Multiple records can reference the same string. + || static_cast<quint32>(stringOffset + offset + length) > tableLength) // String outside bounds + return false; + const bool needsMarker = + nameID == 1 || nameID == 3 || nameID == 4 || nameID == 16 || nameID == 21; + const bool isUnicode = + platformID == 0 || platformID == 3 && encodingID == 1; + const QByteArray originalString = + QByteArray::fromRawData(table.constData() + stringOffset + offset, length); + QByteArray markedString; + if (needsMarker) { + const int maxBytesLength = (KMaxTypefaceNameLength - marker.length()) * (isUnicode ? 2 : 1); + markedString = originalString.left(maxBytesLength) + (isUnicode ? markerUtf16BE : markerAscii); + } else { + markedString = originalString; + } + nameRecord->offset = qToBigEndian(static_cast<quint16>(markedStrings.length())); + nameRecord->length = qToBigEndian(static_cast<quint16>(markedString.length())); + markedStrings.append(markedString); + } + markedTable.append(markedStrings); + table = markedTable; + return true; +} + +const quint32 ttfMaxFileSize = 3500000; + +static inline bool ttfMarkAppFont(QByteArray &ttf, const QString &marker) +{ + const quint32 ttfChecksumNumber = 0xb1b0afba; + const quint32 alignment = 4; + const quint32 ttfLength = static_cast<quint32>(ttf.size()); + if (ttfLength > ttfMaxFileSize // hard limit + || ttfLength % alignment != 0 // ttf sizes are always factors of 4 + || ttfLength <= sizeof(OffsetTable) // ttf too short + || ttfCalcChecksum(ttf.constData(), ttf.size()) != ttfChecksumNumber) // ttf checksum is invalid + return false; + + const OffsetTable *offsetTable = reinterpret_cast<const OffsetTable*>(ttf.constData()); + const quint16 numTables = qFromBigEndian(offsetTable->numTables); + const quint32 recordsLength = + toDWordBoundary(sizeof(OffsetTable) + numTables * sizeof(TableRecord)); + if (numTables > 30 // hard limit + || recordsLength + numTables * alignment > ttfLength) // Corrupt ttf. Tables would not fit, even if empty. + return false; + + QByteArray markedTtf; + markedTtf.reserve(ttfLength + marker.length() * 20); // Original size plus some extra + markedTtf.append(ttf.constData(), recordsLength); + + const quint32 ttfCheckSumAdjustmentOffset = 8; // Offset from the start of 'head' + int indexOfHeadTable = -1; + quint32 ttfDataSize = recordsLength; + typedef QPair<quint32, quint32> Range; + QList<Range> memoryRanges; + memoryRanges.reserve(numTables); + for (int i = 0; i < numTables; ++i) { + TableRecord *tableRecord = + reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); + const quint32 offset = qFromBigEndian(tableRecord->offset); + const quint32 length = qFromBigEndian(tableRecord->length); + const quint32 lengthAligned = toDWordBoundary(length); + ttfDataSize += lengthAligned; + if (offset < recordsLength // must not intersect ttf header/records + || offset % alignment != 0 // must be aligned + || offset > ttfLength - alignment // table out of bounds + || offset + lengthAligned > ttfLength // table out of bounds + || ttfDataSize > ttfLength) // tables would not fit into the ttf + return false; + + foreach (const Range &range, memoryRanges) + if (offset < range.first + range.second && offset + lengthAligned > range.first) + return false; // Overlaps with another table + memoryRanges.append(Range(offset, lengthAligned)); + + quint32 checkSum = qFromBigEndian(tableRecord->checkSum); + if (tableRecord->tag == qToBigEndian(static_cast<quint32>('head'))) { + if (length < ttfCheckSumAdjustmentOffset + sizeof(quint32)) + return false; // Invalid 'head' table + const quint32 *checkSumAdjustmentTag = + reinterpret_cast<const quint32*>(ttf.constData() + offset + ttfCheckSumAdjustmentOffset); + const quint32 checkSumAdjustment = qFromBigEndian(*checkSumAdjustmentTag); + checkSum += checkSumAdjustment; + indexOfHeadTable = i; // For the ttf checksum re-calculation, later + } + if (checkSum != ttfCalcChecksum(ttf.constData() + offset, length)) + return false; // Table checksum is invalid + + bool updateTableChecksum = false; + QByteArray table; + if (tableRecord->tag == qToBigEndian(static_cast<quint32>('name'))) { + table = QByteArray(ttf.constData() + offset, length); + if (!ttfMarkNameTable(table, marker)) + return false; // Name table was not markable. + updateTableChecksum = true; + } else { + table = QByteArray::fromRawData(ttf.constData() + offset, length); + } + + tableRecord->offset = qToBigEndian(markedTtf.size()); + tableRecord->length = qToBigEndian(table.size()); + markedTtf.append(table); + markedTtf.append(QByteArray(dWordPadding(table.size()), 0)); // 0-padding + if (updateTableChecksum) { + TableRecord *tableRecord = // Need to recalculate, since markedTtf changed + reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + i * sizeof(TableRecord)); + const quint32 offset = qFromBigEndian(tableRecord->offset); + const quint32 length = qFromBigEndian(tableRecord->length); + tableRecord->checkSum = qToBigEndian(ttfCalcChecksum(markedTtf.constData() + offset, length)); + } + } + if (indexOfHeadTable == -1 // 'head' table is mandatory + || ttfDataSize != ttfLength) // We do not allow ttf data "holes". Neither does Symbian. + return false; + TableRecord *headRecord = + reinterpret_cast<TableRecord*>(markedTtf.data() + sizeof(OffsetTable) + indexOfHeadTable * sizeof(TableRecord)); + quint32 *checkSumAdjustmentTag = + reinterpret_cast<quint32*>(markedTtf.data() + qFromBigEndian(headRecord->offset) + ttfCheckSumAdjustmentOffset); + *checkSumAdjustmentTag = 0; + const quint32 ttfChecksum = ttfCalcChecksum(markedTtf.constData(), markedTtf.count()); + *checkSumAdjustmentTag = qToBigEndian(ttfChecksumNumber - ttfChecksum); + ttf = markedTtf; + return true; +} + +static inline bool ttfCanSymbianLoadFont(const QByteArray &data, const QString &fileName) +{ + bool result = false; + QString ttfFileName; + QFile tempFileGuard; + QFileInfo info(fileName); + if (!data.isEmpty()) { + QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() + + QSymbianFontDatabaseExtrasImplementation::appFontMarker() + + QLatin1String("XXXXXX.ttf")); + if (!tempfile.open() || tempfile.write(data) == -1) + return false; + ttfFileName = QDir::toNativeSeparators(QFileInfo(tempfile).canonicalFilePath()); + tempfile.setAutoRemove(false); + tempfile.close(); + tempFileGuard.setFileName(ttfFileName); + if (!tempFileGuard.open(QIODevice::ReadOnly)) + return false; + } else if (info.isFile()) { + ttfFileName = QDir::toNativeSeparators(info.canonicalFilePath()); + } else { + return false; + } + + CFontStore *store = 0; + RHeap* heap = User::ChunkHeap(NULL, 0x1000, 0x20000); + if (heap) { + QT_TRAP_THROWING( + CleanupClosePushL(*heap); + store = CFontStore::NewL(heap); + CleanupStack::PushL(store); + COpenFontRasterizer *rasterizer = COpenFontRasterizer::NewL(TUid::Uid(0x101F7F5E)); + CleanupStack::PushL(rasterizer); + store->InstallRasterizerL(rasterizer); + CleanupStack::Pop(rasterizer); + TUid fontUid = {-1}; + TRAP_IGNORE(fontUid = store->AddFileL(qt_QString2TPtrC(ttfFileName))); + if (fontUid.iUid != -1) + result = true; + CleanupStack::PopAndDestroy(2, heap); // heap, store + ); + } + + if (tempFileGuard.isOpen()) + tempFileGuard.remove(); + + return result; +} + static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) { - Q_UNUSED(fnt); + if (QSymbianFontDatabaseExtrasImplementation::appFontLimitReached() + || fnt->data.size() > ttfMaxFileSize // hard limit + || fnt->data.isEmpty() && (!fnt->fileName.endsWith(QLatin1String(".ttf"), Qt::CaseInsensitive) // Only buffer or .ttf + || QFileInfo(fnt->fileName).size() > ttfMaxFileSize)) // hard limit + return; + +// Using ttfCanSymbianLoadFont() causes crashes on app destruction (Symbian^3|PR1 and lower). +// Therefore, not using it for now, but eventually in a later version. +// if (!ttfCanSymbianLoadFont(fnt->data, fnt->fileName)) +// return; + + QFontDatabasePrivate *db = privateDb(); + if (!db) + return; + + if (!db->count) + initializeDb(); + + QSymbianFontDatabaseExtrasImplementation *dbExtras = + static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); + if (!dbExtras) + return; + + const QString &marker = QSymbianFontDatabaseExtrasImplementation::appFontMarker(); + + // The QTemporaryFile object being used in the following section must be + // destructed before letting Symbian load the TTF file. Symbian would not + // load it otherwise, because QTemporaryFile will still keep some handle + // on it. The scope is used to reduce the life time of the QTemporaryFile. + // In order to prevent other processes from modifying the file between the + // moment where the QTemporaryFile is destructed and the file is loaded by + // Symbian, we have a QFile "tempFileGuard" outside the scope which opens + // the file in ReadOnly mode while the QTemporaryFile is still alive. + QFile tempFileGuard; + { + QTemporaryFile tempfile(QSymbianFontDatabaseExtrasImplementation::tempAppFontFolder() + + marker + QLatin1String("XXXXXX.ttf")); + if (!tempfile.open()) + return; + const QString tempFileName = QFileInfo(tempfile).canonicalFilePath(); + if (fnt->data.isEmpty()) { + QFile sourceFile(fnt->fileName); + if (!sourceFile.open(QIODevice::ReadOnly)) + return; + fnt->data = sourceFile.readAll(); + } + if (!ttfMarkAppFont(fnt->data, marker) || tempfile.write(fnt->data) == -1) + return; + tempfile.setAutoRemove(false); + tempfile.close(); // Tempfile still keeps a file handle, forbidding write access + fnt->data.clear(); // The TTF data was marked and saved. Not needed in memory, anymore. + tempFileGuard.setFileName(tempFileName); + if (!tempFileGuard.open(QIODevice::ReadOnly)) + return; + fnt->temporaryFileName = tempFileName; + } + + const QString fullFileName = QDir::toNativeSeparators(fnt->temporaryFileName); + QSymbianFbsHeapLock lock(QSymbianFbsHeapLock::Unlock); + const QStringList fontsOnServerBefore = qt_symbian_fontFamiliesOnFontServer(); + const TInt err = + S60->screenDevice()->AddFile(qt_QString2TPtrC(fullFileName), fnt->screenDeviceFontFileId); + tempFileGuard.close(); // Did its job + const QStringList fontsOnServerAfter = qt_symbian_fontFamiliesOnFontServer(); + if (err == KErrNone && fontsOnServerBefore.count() < fontsOnServerAfter.count()) { // Added to screen device? + int fontOnServerIndex = fontsOnServerAfter.count() - 1; + for (int i = 0; i < fontsOnServerBefore.count(); i++) { + if (fontsOnServerBefore.at(i) != fontsOnServerAfter.at(i)) { + fontOnServerIndex = i; + break; + } + } + + // Must remove all font engines with their CFonts, first. + QFontCache::instance()->clear(); + db->free(); + QSymbianFontDatabaseExtrasImplementation::clear(); + + if (!QSymbianTypeFaceExtras::symbianFontTableApiAvailable()) + fnt->fontStoreFontFileUid = dbExtras->addFontFileToFontStore(QFileInfo(fullFileName)); + + const QString &appFontName = fontsOnServerAfter.at(fontOnServerIndex); + fnt->families.append(qt_symbian_appFontNameWithoutMarker(appFontName)); + if (!qt_symbian_fontNameHasAppFontMarker(appFontName) + || !registerScreenDeviceFont(fontOnServerIndex, dbExtras)) + dbExtras->removeAppFontData(fnt); + } else { + if (fnt->screenDeviceFontFileId > 0) + S60->screenDevice()->RemoveFile(fnt->screenDeviceFontFileId); // May still have the file open! + QFile::remove(fnt->temporaryFileName); + *fnt = QFontDatabasePrivate::ApplicationFont(); + } + lock.relock(); } bool QFontDatabase::removeApplicationFont(int handle) { - Q_UNUSED(handle); - return false; + QMutexLocker locker(fontDatabaseMutex()); + + QFontDatabasePrivate *db = privateDb(); + if (!db || handle < 0 || handle >= db->applicationFonts.count()) + return false; + QSymbianFontDatabaseExtrasImplementation *dbExtras = + static_cast<QSymbianFontDatabaseExtrasImplementation*>(db->symbianExtras); + if (!dbExtras) + return false; + + QFontDatabasePrivate::ApplicationFont *fnt = &db->applicationFonts[handle]; + if (fnt->families.isEmpty()) + return true; // Nothing to remove. Return peacefully. + + // Must remove all font engines with their CFonts, first + QFontCache::instance()->clear(); + db->free(); + dbExtras->removeAppFontData(fnt); + + db->invalidate(); // This will just emit 'fontDatabaseChanged()' + return true; } bool QFontDatabase::removeAllApplicationFonts() { - return false; + QMutexLocker locker(fontDatabaseMutex()); + + const int applicationFontsCount = privateDb()->applicationFonts.count(); + for (int i = 0; i < applicationFontsCount; ++i) + if (!removeApplicationFont(i)) + return false; + return true; } bool QFontDatabase::supportsThreadedFontRendering() @@ -467,7 +982,7 @@ QFontEngine *QFontDatabase::findFont(int script, const QFontPrivate *d, const QF QFontDatabasePrivate *db = privateDb(); QtFontDesc desc; QList<int> blacklistedFamilies; - match(script, req, req.family, QString(), -1, &desc, blacklistedFamilies); + match(script, key.def, key.def.family, QString(), -1, &desc, blacklistedFamilies); if (!desc.family) // falling back to application font desc.family = db->family(QApplication::font().defaultFamily()); Q_ASSERT(desc.family); diff --git a/src/gui/text/qfontengine_s60.cpp b/src/gui/text/qfontengine_s60.cpp index b572cdd..f2b6f5c 100644 --- a/src/gui/text/qfontengine_s60.cpp +++ b/src/gui/text/qfontengine_s60.cpp @@ -243,10 +243,13 @@ static inline unsigned int getChar(const QChar *str, int &i, const int len) return uc; } +extern QString qt_symbian_fontNameWithAppFontMarker(const QString &fontName); // qfontdatabase_s60.cpp + CFont *QFontEngineS60::fontWithSize(qreal size) const { CFont *result = 0; - TFontSpec fontSpec(qt_QString2TPtrC(QFontEngine::fontDef.family), TInt(size)); + const QString family = qt_symbian_fontNameWithAppFontMarker(QFontEngine::fontDef.family); + TFontSpec fontSpec(qt_QString2TPtrC(family), TInt(size)); fontSpec.iFontStyle.SetBitmapType(EAntiAliasedGlyphBitmap); fontSpec.iFontStyle.SetPosture(QFontEngine::fontDef.style == QFont::StyleNormal?EPostureUpright:EPostureItalic); fontSpec.iFontStyle.SetStrokeWeight(QFontEngine::fontDef.weight > QFont::Normal?EStrokeWeightBold:EStrokeWeightNormal); diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 498a432..2172f74 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -663,7 +663,8 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O Q_ASSERT(blocks.length() == fragments.length()); - finishEdit(); + if (!blockCursorAdjustment) + finishEdit(); } void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op) @@ -678,6 +679,7 @@ void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operati curs->changed = true; } } + finishEdit(); } void QTextDocumentPrivate::setCharFormat(int pos, int length, const QTextCharFormat &newFormat, FormatChangeMode mode) diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp index 3e5f1b3..dbbf49a 100644 --- a/src/gui/widgets/qcombobox.cpp +++ b/src/gui/widgets/qcombobox.cpp @@ -2476,10 +2476,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/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/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp index 42d2955..b0303aa 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 5ceaed0..ea18367 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -48,6 +48,7 @@ #include "qabstractnetworkcache.h" #include "QtNetwork/qnetworksession.h" +#include "QtNetwork/private/qsharednetworksession_p.h" #include "qnetworkaccesshttpbackend_p.h" #include "qnetworkaccessftpbackend_p.h" @@ -1354,11 +1355,8 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co initializeSession = false; - if (networkSession) - delete networkSession; - if (!config.isValid()) { - networkSession = 0; + networkSession.clear(); online = false; if (networkAccessible == QNetworkAccessManager::NotAccessible) @@ -1369,18 +1367,12 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co return; } - networkSession = new QNetworkSession(config, q); + networkSession = QSharedNetworkSessionManager::getSession(config); - QObject::connect(networkSession, SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); - QObject::connect(networkSession, SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); - QObject::connect(networkSession, SIGNAL(stateChanged(QNetworkSession::State)), + QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); + QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); - QObject::connect(networkSession, SIGNAL(newConfigurationActivated()), - q, SLOT(_q_networkSessionNewConfigurationActivated())); - QObject::connect(networkSession, - SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)), - q, - SLOT(_q_networkSessionPreferredConfigurationChanged(QNetworkConfiguration,bool))); _q_networkSessionStateChanged(networkSession->state()); } @@ -1390,32 +1382,16 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed() if (networkSession) { networkConfiguration = networkSession->configuration().identifier(); - networkSession->deleteLater(); - networkSession = 0; - } -} - -void QNetworkAccessManagerPrivate::_q_networkSessionNewConfigurationActivated() -{ - Q_Q(QNetworkAccessManager); - - if (networkSession) { - networkSession->accept(); - - emit q->networkSessionConnected(); + networkSession.clear(); } } -void QNetworkAccessManagerPrivate::_q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &, bool) -{ - if (networkSession) - networkSession->migrate(); -} - void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state) { Q_Q(QNetworkAccessManager); + if (state == QNetworkSession::Connected) + emit q->networkSessionConnected(); if (online) { if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) { online = false; diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index f3e502c..7ef009f 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -161,8 +161,6 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>)) #if !defined(QT_NO_BEARERMANAGEMENT) && !defined(QT_MOBILITY_BEARER) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) - Q_PRIVATE_SLOT(d_func(), void _q_networkSessionNewConfigurationActivated()) - Q_PRIVATE_SLOT(d_func(), void _q_networkSessionPreferredConfigurationChanged(QNetworkConfiguration,bool)) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionStateChanged(QNetworkSession::State)) #endif }; diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index ee16c25..cf4d2f3 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -128,7 +128,7 @@ public: #endif #ifndef QT_NO_BEARERMANAGEMENT - QNetworkSession *networkSession; + QSharedPointer<QNetworkSession> networkSession; QString networkConfiguration; QNetworkAccessManager::NetworkAccessibility networkAccessible; bool online; diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 53d3b11..9d7082c 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -91,7 +91,7 @@ void QNetworkReplyImplPrivate::_q_startOperation() // state changes. state = WaitingForSession; - QNetworkSession *session = manager->d_func()->networkSession; + QNetworkSession *session = manager->d_func()->networkSession.data(); if (session) { Q_Q(QNetworkReplyImpl); @@ -246,7 +246,7 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() if (manager.isNull()) return; - QNetworkSession *session = manager->d_func()->networkSession; + QNetworkSession *session = manager->d_func()->networkSession.data(); if (!session) return; @@ -633,7 +633,7 @@ void QNetworkReplyImplPrivate::finished() if (!manager.isNull()) { #ifndef QT_NO_BEARERMANAGEMENT - QNetworkSession *session = manager->d_func()->networkSession; + QNetworkSession *session = manager->d_func()->networkSession.data(); if (session && session->state() == QNetworkSession::Roaming && state == Working && errorCode != QNetworkReply::OperationCanceledError) { // only content with a known size will fail with a temporary network failure error diff --git a/src/network/bearer/bearer.pri b/src/network/bearer/bearer.pri index 44e97fd..684e02b 100644 --- a/src/network/bearer/bearer.pri +++ b/src/network/bearer/bearer.pri @@ -7,12 +7,14 @@ HEADERS += bearer/qnetworkconfiguration.h \ bearer/qnetworkconfiguration_p.h \ bearer/qnetworksession_p.h \ bearer/qbearerengine_p.h \ - bearer/qbearerplugin_p.h + bearer/qbearerplugin_p.h \ + bearer/qsharednetworksession_p.h SOURCES += bearer/qnetworksession.cpp \ bearer/qnetworkconfigmanager.cpp \ bearer/qnetworkconfiguration.cpp \ bearer/qnetworkconfigmanager_p.cpp \ bearer/qbearerengine.cpp \ - bearer/qbearerplugin.cpp + bearer/qbearerplugin.cpp \ + bearer/qsharednetworksession.cpp diff --git a/src/network/bearer/qsharednetworksession.cpp b/src/network/bearer/qsharednetworksession.cpp new file mode 100644 index 0000000..51b3a32 --- /dev/null +++ b/src/network/bearer/qsharednetworksession.cpp @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 QtNetwork 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 "qsharednetworksession_p.h" +#include "qbearerengine_p.h" +#include <QThreadStorage> + +#ifndef QT_NO_BEARERMANAGEMENT + +QT_BEGIN_NAMESPACE + +QThreadStorage<QSharedNetworkSessionManager *> tls; + +inline QSharedNetworkSessionManager* sharedNetworkSessionManager() +{ + QSharedNetworkSessionManager* rv = tls.localData(); + if (!rv) { + rv = new QSharedNetworkSessionManager; + tls.setLocalData(rv); + } + return rv; +} + +QSharedPointer<QNetworkSession> QSharedNetworkSessionManager::getSession(QNetworkConfiguration config) +{ + QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); + //if already have a session, return it + if (m->sessions.contains(config)) { + QSharedPointer<QNetworkSession> p = m->sessions.value(config).toStrongRef(); + if (!p.isNull()) + return p; + } + //otherwise make one + QSharedPointer<QNetworkSession> session(new QNetworkSession(config)); + m->sessions[config] = session; + return session; +} + +void QSharedNetworkSessionManager::setSession(QNetworkConfiguration config, QSharedPointer<QNetworkSession> session) +{ + QSharedNetworkSessionManager *m(sharedNetworkSessionManager()); + m->sessions[config] = session; +} + +uint qHash(const QNetworkConfiguration& config) +{ + return ((uint)config.type()) | (((uint)config.bearerType()) << 8) | (((uint)config.purpose()) << 16); +} + +QT_END_NAMESPACE + +#endif // QT_NO_BEARERMANAGEMENT diff --git a/src/network/bearer/qsharednetworksession_p.h b/src/network/bearer/qsharednetworksession_p.h new file mode 100644 index 0000000..dc84166 --- /dev/null +++ b/src/network/bearer/qsharednetworksession_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** 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 QtNetwork 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 QSHAREDNETWORKSESSIONPRIVATE_H +#define QSHAREDNETWORKSESSIONPRIVATE_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 "qnetworksession.h" +#include "qnetworkconfiguration.h" +#include <QHash> +#include <QSharedPointer> +#include <QWeakPointer> +#include <QMutex> + +#ifndef QT_NO_BEARERMANAGEMENT + +QT_BEGIN_NAMESPACE + +class QSharedNetworkSessionManager +{ +public: + static QSharedPointer<QNetworkSession> getSession(QNetworkConfiguration config); + static void setSession(QNetworkConfiguration config, QSharedPointer<QNetworkSession> session); +private: + QHash<QNetworkConfiguration, QWeakPointer<QNetworkSession> > sessions; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_BEARERMANAGEMENT + +#endif //QSHAREDNETWORKSESSIONPRIVATE_H + diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri index 6145c43..66e87c9 100644 --- a/src/network/kernel/kernel.pri +++ b/src/network/kernel/kernel.pri @@ -27,5 +27,7 @@ win32:SOURCES += kernel/qhostinfo_win.cpp kernel/qnetworkinterface_win.cpp mac:LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation mac:SOURCES += kernel/qnetworkproxy_mac.cpp else:win32:SOURCES += kernel/qnetworkproxy_win.cpp +else:symbian:SOURCES += kernel/qnetworkproxy_symbian.cpp else:SOURCES += kernel/qnetworkproxy_generic.cpp +symbian: LIBS += -lcommsdat diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 73143e1..d61d3b7 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -213,24 +213,6 @@ void QAuthenticator::setUser(const QString &user) int separatorPosn = 0; switch(d->method) { - case QAuthenticatorPrivate::DigestMd5: - if((separatorPosn = user.indexOf(QLatin1String("\\"))) != -1) { - //domain name is present - d->userDomain.clear(); - d->realm = user.left(separatorPosn); - d->user = user.mid(separatorPosn + 1); - } else if((separatorPosn = user.indexOf(QLatin1String("@"))) != -1) { - //domain name is present - d->userDomain.clear(); - d->realm = user.mid(separatorPosn + 1); - d->user = user.left(separatorPosn); - } else { - d->user = user; - d->realm.clear(); - d->userDomain.clear(); - } - break; - case QAuthenticatorPrivate::Ntlm: if((separatorPosn = user.indexOf(QLatin1String("\\"))) != -1) { //domain name is present @@ -253,6 +235,7 @@ void QAuthenticator::setUser(const QString &user) break; default: d->user = user; + d->userDomain.clear(); break; } } diff --git a/src/network/kernel/qnetworkproxy_symbian.cpp b/src/network/kernel/qnetworkproxy_symbian.cpp new file mode 100644 index 0000000..79dfb27 --- /dev/null +++ b/src/network/kernel/qnetworkproxy_symbian.cpp @@ -0,0 +1,267 @@ +/**************************************************************************** +** +** 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 FOO 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$ +** +****************************************************************************/ + +/** + * Some notes about the code: + * + * ** It is assumed that the system proxies are for url based requests + * ie. HTTP/HTTPS based. + * ** It is assumed that proxies don't use authentication. + * ** It is assumed that there is no exceptions to proxy use (Symbian side + * does have the field for it but it is not user modifiable by default). + * ** There is no checking for protocol name. + */ + +#include <QtNetwork/qnetworkproxy.h> + +#ifndef QT_NO_NETWORKPROXY + +#include <metadatabase.h> // CMDBSession +#include <commsdattypeinfov1_1.h> // CCDIAPRecord, CCDProxiesRecord +#include <commsdattypesv1_1.h> // KCDTIdIAPRecord, KCDTIdProxiesRecord +#include <QtNetwork/QNetworkConfigurationManager> +#include <QFlags> + +using namespace CommsDat; + +QT_BEGIN_NAMESPACE + +class SymbianIapId +{ +public: + enum State{ + NotValid, + Valid + }; + Q_DECLARE_FLAGS(States, State) + SymbianIapId() {} + ~SymbianIapId() {} + void setIapId(TUint32 iapId) { iapState |= Valid; id = iapId; } + bool isValid() { return iapState == Valid; } + TUint32 iapId() { return id; } +private: + QFlags<States> iapState; + TUint32 id; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(SymbianIapId::States) + +class SymbianProxyQuery +{ +public: + static QNetworkConfiguration findCurrentConfiguration(QNetworkConfigurationManager& configurationManager); + static SymbianIapId getIapId(QNetworkConfigurationManager& configurationManager); + static CCDIAPRecord *getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb); + static CMDBRecordSet<CCDProxiesRecord> *prepareQueryLC(TUint32 serviceId, TDesC& serviceType); + static QList<QNetworkProxy> proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query); +}; + +QNetworkConfiguration SymbianProxyQuery::findCurrentConfiguration(QNetworkConfigurationManager& configurationManager) +{ + QList<QNetworkConfiguration> activeConfigurations = configurationManager.allConfigurations( + QNetworkConfiguration::Active); + QNetworkConfiguration currentConfig; + if (activeConfigurations.count() > 0) { + currentConfig = activeConfigurations.at(0); + } else { + // No active configurations, try default one + QNetworkConfiguration defaultConfiguration = configurationManager.defaultConfiguration(); + if (defaultConfiguration.isValid()) { + switch (defaultConfiguration.type()) { + case QNetworkConfiguration::InternetAccessPoint: + currentConfig = defaultConfiguration; + break; + case QNetworkConfiguration::ServiceNetwork: + { + // Note: This code assumes that the only unambigious way to + // find current proxy config is if there is only one access point + // or if the found access point is immediately usable. + QList<QNetworkConfiguration> childConfigurations = defaultConfiguration.children(); + if (childConfigurations.count() == 1) { + currentConfig = childConfigurations.at(0); + } else { + for (int index = 0; index < childConfigurations.count(); index++) { + QNetworkConfiguration childConfig = childConfigurations.at(index); + if (childConfig.isValid() && childConfig.state() == QNetworkConfiguration::Discovered) { + currentConfig = childConfig; + break; + } + } + } + } + break; + case QNetworkConfiguration::UserChoice: + // User choice is not a valid configuration for proxy discovery + break; + } + } + } + return currentConfig; +} + +SymbianIapId SymbianProxyQuery::getIapId(QNetworkConfigurationManager& configurationManager) +{ + SymbianIapId iapId; + + QNetworkConfiguration currentConfig = findCurrentConfiguration(configurationManager); + if (currentConfig.isValid()) { + // Note: the following code assumes that the identifier is in format + // I_xxxx where xxxx is the identifier of IAP. This is meant as a + // temporary solution until there is a support for returning + // implementation specific identifier. + const int generalPartLength = 2; + const int identifierNumberLength = currentConfig.identifier().length() - generalPartLength; + QString idString(currentConfig.identifier().right(identifierNumberLength)); + bool success; + uint id = idString.toUInt(&success); + if (success) + iapId.setIapId(id); + else + qWarning() << "Failed to convert identifier to access point identifier: " + << currentConfig.identifier(); + } + + return iapId; +} + +CCDIAPRecord *SymbianProxyQuery::getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb) +{ + CCDIAPRecord *iap = static_cast<CCDIAPRecord*> (CCDRecordBase::RecordFactoryL(KCDTIdIAPRecord)); + CleanupStack::PushL(iap); + iap->SetRecordId(aIAPId); + iap->LoadL(aDb); + return iap; +} + +CMDBRecordSet<CCDProxiesRecord> *SymbianProxyQuery::prepareQueryLC(TUint32 serviceId, TDesC& serviceType) +{ + // Create a recordset of type CCDProxiesRecord + // for priming search. + // This will ultimately contain record(s) + // matching the priming record attributes + CMDBRecordSet<CCDProxiesRecord> *proxyRecords = new (ELeave) CMDBRecordSet<CCDProxiesRecord> ( + KCDTIdProxiesRecord); + CleanupStack::PushL(proxyRecords); + + CCDProxiesRecord *primingProxyRecord = + static_cast<CCDProxiesRecord *> (CCDRecordBase::RecordFactoryL(KCDTIdProxiesRecord)); + CleanupStack::PushL(primingProxyRecord); + + primingProxyRecord->iServiceType.SetMaxLengthL(serviceType.Length()); + primingProxyRecord->iServiceType = serviceType; + primingProxyRecord->iService = serviceId; + primingProxyRecord->iUseProxyServer = ETrue; + + proxyRecords->iRecords.AppendL(primingProxyRecord); + // Ownership of primingProxyRecord is transferred to + // proxyRecords, just remove it from the CleanupStack + CleanupStack::Pop(primingProxyRecord); + return proxyRecords; +} + +QList<QNetworkProxy> SymbianProxyQuery::proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query) +{ + QList<QNetworkProxy> foundProxies; + if (query.queryType() != QNetworkProxyQuery::UrlRequest) { + return foundProxies; + } + + CMDBSession *iDb = CMDBSession::NewLC(KCDVersion1_1); + CCDIAPRecord *iap = getIapRecordLC(aIAPId, *iDb); + + // Read service table id and service type + // from the IAP record found + TUint32 serviceId = iap->iService; + RBuf serviceType; + serviceType.CreateL(iap->iServiceType); + CleanupStack::PopAndDestroy(iap); + CleanupClosePushL(serviceType); + + CMDBRecordSet<CCDProxiesRecord> *proxyRecords = prepareQueryLC(serviceId, serviceType); + + // Now to find a proxy table matching our criteria + if (proxyRecords->FindL(*iDb)) { + TInt count = proxyRecords->iRecords.Count(); + for(TInt index = 0; index < count; index++) { + CCDProxiesRecord *proxyRecord = static_cast<CCDProxiesRecord *> (proxyRecords->iRecords[index]); + RBuf serverName; + serverName.CreateL(proxyRecord->iServerName); + CleanupClosePushL(serverName); + if (serverName.Length() == 0) + User::Leave(KErrNotFound); + QString serverNameQt((const QChar*)serverName.Ptr(), serverName.Length()); + CleanupStack::Pop(); // serverName + TUint32 port = proxyRecord->iPortNumber; + + QNetworkProxy proxy(QNetworkProxy::HttpProxy, serverNameQt, port); + foundProxies.append(proxy); + } + } + + CleanupStack::PopAndDestroy(proxyRecords); + CleanupStack::Pop(); // serviceType + CleanupStack::PopAndDestroy(iDb); + + return foundProxies; +} + +QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query) +{ + QList<QNetworkProxy> proxies; + SymbianIapId iapId; + TInt error; + QNetworkConfigurationManager manager; + iapId = SymbianProxyQuery::getIapId(manager); + if (iapId.isValid()) { + TRAP(error, proxies = SymbianProxyQuery::proxyQueryL(iapId.iapId(), query)) + if (error != KErrNone) { + qWarning() << "Error while retrieving proxies: '" << error << '"'; + proxies.clear(); + } + } + proxies << QNetworkProxy::NoProxy; + + return proxies; +} + +QT_END_NAMESPACE + +#endif diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 9ab8d2e..ad2852e 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -102,7 +102,7 @@ extern Q_GUI_EXPORT bool qt_cleartype_enabled; extern bool qt_applefontsmoothing_enabled; #endif -Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); +Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert); ////////////////////////////////// Private Methods ////////////////////////////////////////// @@ -1154,7 +1154,7 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush) d->fill(path); } -extern Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp +Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // qtransform.cpp void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp index adf3ceb..6161d9b 100644 --- a/src/opengl/qglframebufferobject.cpp +++ b/src/opengl/qglframebufferobject.cpp @@ -1171,8 +1171,8 @@ void QGLFramebufferObject::drawTexture(const QPointF &point, QMacCompatGLuint te } #endif -Q_DECL_IMPORT extern int qt_defaultDpiX(); -Q_DECL_IMPORT extern int qt_defaultDpiY(); +Q_GUI_EXPORT int qt_defaultDpiX(); +Q_GUI_EXPORT int qt_defaultDpiY(); /*! \reimp */ int QGLFramebufferObject::metric(PaintDeviceMetric metric) const diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 735590f..61bce23 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -416,8 +416,8 @@ QPaintEngine *QGLPixelBuffer::paintEngine() const #endif } -Q_DECL_IMPORT extern int qt_defaultDpiX(); -Q_DECL_IMPORT extern int qt_defaultDpiY(); +Q_GUI_EXPORT int qt_defaultDpiX(); +Q_GUI_EXPORT int qt_defaultDpiY(); /*! \reimp */ int QGLPixelBuffer::metric(PaintDeviceMetric metric) const diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index 0369d56..2187deb 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -63,8 +63,8 @@ QT_BEGIN_NAMESPACE // qpixmapfilter.cpp -Q_DECL_IMPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); -Q_DECL_IMPORT QImage qt_halfScaled(const QImage &source); +Q_GUI_EXPORT void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed = 0); +Q_GUI_EXPORT QImage qt_halfScaled(const QImage &source); void QGLPixmapFilterBase::bindTexture(const QPixmap &src) const { @@ -436,7 +436,7 @@ static inline uint nextMultiple(uint x, uint multiplier) return x + multiplier - mod; } -Q_DECL_IMPORT void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride, +Q_GUI_EXPORT void qt_memrotate90_gl(const quint32 *src, int srcWidth, int srcHeight, int srcStride, quint32 *dest, int dstStride); bool QGLPixmapBlurFilter::processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &) const diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 2f1b8fd..2c01ac4 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE -Q_DECL_IMPORT extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp +Q_GUI_EXPORT QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp #ifdef QT_MAC_USE_COCOA extern void *qt_current_nsopengl_context(); // qgl_mac.mm #endif diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp index 3549f9d..9980f2d 100644 --- a/src/opengl/qpixmapdata_gl.cpp +++ b/src/opengl/qpixmapdata_gl.cpp @@ -739,8 +739,8 @@ QGLTexture* QGLPixmapData::texture() const return &m_texture; } -Q_DECL_IMPORT extern int qt_defaultDpiX(); -Q_DECL_IMPORT extern int qt_defaultDpiY(); +Q_GUI_EXPORT int qt_defaultDpiX(); +Q_GUI_EXPORT int qt_defaultDpiY(); int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const { diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp index 09cbc36..a15f0c3 100644 --- a/src/openvg/qpaintengine_vg.cpp +++ b/src/openvg/qpaintengine_vg.cpp @@ -77,8 +77,8 @@ static const qreal aliasedCoordinateDelta = 0.5 - 0.015625; #if !defined(QVG_NO_DRAW_GLYPHS) -Q_DECL_IMPORT extern int qt_defaultDpiX(); -Q_DECL_IMPORT extern int qt_defaultDpiY(); +Q_GUI_EXPORT int qt_defaultDpiX(); +Q_GUI_EXPORT int qt_defaultDpiY(); class QVGPaintEnginePrivate; @@ -526,7 +526,7 @@ void QVGPaintEnginePrivate::setTransform vgLoadMatrix(mat); } -Q_DECL_IMPORT extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); +Q_GUI_EXPORT bool qt_scaleForTransform(const QTransform &transform, qreal *scale); void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev) { @@ -994,7 +994,7 @@ VGPath QVGPaintEnginePrivate::roundedRectPath(const QRectF &rect, qreal xRadius, return vgpath; } -Q_DECL_IMPORT extern QImage qt_imageForBrush(int style, bool invert); +Q_GUI_EXPORT QImage qt_imageForBrush(int style, bool invert); static QImage colorizeBitmap(const QImage &image, const QColor &color) { @@ -1472,7 +1472,7 @@ void QVGPaintEnginePrivate::draw (VGPath path, const QPen& pen, const QBrush& brush, VGint rule) { VGbitfield mode = 0; - if (pen.style() != Qt::NoPen) { + if (qpen_style(pen) != Qt::NoPen && qbrush_style(qpen_brush(pen)) != Qt::NoBrush) { ensurePen(pen); mode |= VG_STROKE_PATH; } diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp index 3f768fd..732b484 100644 --- a/src/openvg/qpixmapdata_vg.cpp +++ b/src/openvg/qpixmapdata_vg.cpp @@ -200,6 +200,9 @@ bool QVGPixmapData::fromData(const uchar *buffer, uint len, const char *format, return !isNull(); } +/*! + out-of-place conversion (inPlace == false) will always detach() + */ void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags flags, bool inPlace) { if (image.size() == QSize(w, h)) @@ -216,11 +219,16 @@ void QVGPixmapData::createPixmapForImage(QImage &image, Qt::ImageConversionFlags else format = image.hasAlphaChannel() ? sourceFormat() : QImage::Format_RGB32; - if (inPlace && image.data_ptr()->convertInPlace(format, flags)) + if (inPlace && image.data_ptr()->convertInPlace(format, flags)) { source = image; - else + } else { source = image.convertToFormat(format); + // convertToFormat won't detach the image if format stays the same. + if (image.format() == format) + source.detach(); + } + recreate = true; } @@ -404,8 +412,8 @@ void QVGPixmapData::reclaimImages() destroyImages(); } -Q_DECL_IMPORT extern int qt_defaultDpiX(); -Q_DECL_IMPORT extern int qt_defaultDpiY(); +Q_GUI_EXPORT int qt_defaultDpiX(); +Q_GUI_EXPORT int qt_defaultDpiY(); int QVGPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const { diff --git a/src/plugins/bearer/icd/dbusdispatcher.cpp b/src/plugins/bearer/icd/dbusdispatcher.cpp index 5fc2a38..5f9be74 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 diff --git a/src/script/script.pro b/src/script/script.pro index d1633d8..63917b1 100644 --- a/src/script/script.pro +++ b/src/script/script.pro @@ -81,7 +81,6 @@ include(script.pri) symbian { TARGET.UID3=0x2001B2E1 - LIBS += -lhal } symbian { diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index c91aa54..8cff61b 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -223,7 +223,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); @@ -400,7 +400,7 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni // colSize-1: remove 0 termination when there is more data to fetch int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator/sizeof(SQLTCHAR); fieldVal += fromSQLTCHAR(buf, rSize); - if (lengthIndicator < (unsigned int)colSize*sizeof(SQLTCHAR)) { + if ((unsigned)lengthIndicator < colSize*sizeof(SQLTCHAR)) { // workaround for Drivermanagers that don't return SQL_NO_DATA break; } diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 0a7d5bf..a044c7f 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()); |