summaryrefslogtreecommitdiffstats
path: root/src/gui/painting
diff options
context:
space:
mode:
authorBjoern Erik Nilsen <bjorn.nilsen@nokia.com>2009-04-29 10:55:44 (GMT)
committerBjoern Erik Nilsen <bjorn.nilsen@nokia.com>2009-04-29 11:05:11 (GMT)
commit660907a80e8a3f23f70cd5039407c0cc679af9f3 (patch)
tree1c178c08a2bb17f14d9233f6458a8669e79d7c75 /src/gui/painting
parentd07de7568cdfb1889e4b64fcbe3fcbfa120ae264 (diff)
downloadQt-660907a80e8a3f23f70cd5039407c0cc679af9f3.zip
Qt-660907a80e8a3f23f70cd5039407c0cc679af9f3.tar.gz
Qt-660907a80e8a3f23f70cd5039407c0cc679af9f3.tar.bz2
Mac: Fixes a crash in tst_QWidget::updateOnDestroyedSignal
Addendum to change 9b674ddcea7c0ff7912f185474b7d98bc83bd39f. The problem was that QWidget::paintEngine() (pure virtual) was called while being in the destructor. The use-case itself (see above change) is very very corner case, but still, it shouldn't crash. Reviewed-by: bnilsen
Diffstat (limited to 'src/gui/painting')
-rw-r--r--src/gui/painting/qbackingstore.cpp3
1 files changed, 3 insertions, 0 deletions
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 34df6c9..8fb7a12 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -1510,6 +1510,9 @@ void QWidgetPrivate::invalidateBuffer(const QRect &rect)
void QWidgetPrivate::repaint_sys(const QRegion &rgn)
{
+ if (data.in_destructor)
+ return;
+
Q_Q(QWidget);
if (q->testAttribute(Qt::WA_StaticContents)) {
if (!extra)
Row(int) const; + + mutable QOffsetVector m_rows; + const int m_count; +}; + +#endif diff --git a/examples/tools/tools.pro b/examples/tools/tools.pro index 79f0faa..424f286 100644 --- a/examples/tools/tools.pro +++ b/examples/tools/tools.pro @@ -5,6 +5,7 @@ SUBDIRS = codecs \ customcompleter \ echoplugin \ i18n \ + offsetvector \ plugandpaintplugins \ plugandpaint \ regexp \ diff --git a/src/corelib/tools/qoffsetvector.cpp b/src/corelib/tools/qoffsetvector.cpp new file mode 100644 index 0000000..32d2872 --- /dev/null +++ b/src/corelib/tools/qoffsetvector.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qoffsetvector.h" +#include + +void QOffsetVectorData::dump() const +{ + qDebug() << "capacity:" << alloc; + qDebug() << "count:" << count; + qDebug() << "start:" << start; + qDebug() << "offset:" << offset; +} + +/*! \class QOffsetVector + \brief The QOffsetVector class is a template class that provides a offset vector. + \ingroup tools + \ingroup shared + \reentrant + + The QOffsetVector class provides an efficient way of caching items for + display in a user interface view. It does this by providing a window + into a theoretical infinite sized vector. This has the advantage that + it matches how user interface views most commonly request the data, in + a set of rows localized around the current scrolled position. It also + allows the cache to use less overhead than QCache both in terms of + performance and memory. In turn, unlike a QCache, the key has to be + an int and has to be contiguous. That is to say if an item is inserted + at index 85, then if there were no previous items at 84 or 86 then the + cache will be cleared before the new item at 85 is inserted. If this + restriction is not suitable consider using QCache instead. + + The simplest way of using an offset vector is to use the append() + and prepend() functions to slide the window to where it is needed. + +\code +MyRecord record(int row) const +{ + Q_ASSERT(row >= 0 && row < count()); + + while(row > cache.lastIndex()) + cache.append(slowFetchRecord(cache.lastIndex()+1)); + while(row < cache.firstIndex()) + cache.prepend(slowFetchRecord(cache.firstIndex()-1)); + + return cache.at(row); +} +\endcode + + The append() and prepend() functions cause the vector window to move to + where the current row is requested from. This usage can be further + optimized by using the insert() function to reset the vector window to + a row in the case where the row is a long way from the current row. It + may also be worth while to fetch multiple records into the cache if + it is faster to retrieve them in a batch operation. + + See the The \l{Offset Vector Example}{Offset Vector} example. +*/ + +/*! \fn QOffsetVector::QOffsetVector(int capacity) + + Constructs a vector with the given \a capacity. + + \sa setCapacity() +*/ + +/*! \fn QOffsetVector::QOffsetVector(const QOffsetVector &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QOffsetVector is + \l{implicitly shared}. This makes returning a QOffsetVector from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QOffsetVector::~QOffsetVector() + Destorys the vector. +*/ + +/*! \fn void QOffsetVector::detach() + + \internal +*/ + +/*! \fn bool QOffsetVector::isDetached() const + + \internal +*/ + +/*! \fn void QOffsetVector::setSharable(bool sharable) + + \internal +*/ + + +/*! \fn QOffsetVector &QOffsetVector::operator=(const QOffsetVector &other) + + Assigns \a other to this vector and returns a reference to this vector. +*/ + +/*! \fn bool QOffsetVector::operator==(const QOffsetVector &other) const + + Returns true if \a other is equal to this vector; otherwise returns false. + + Two vectors are considered equal if they contain the same values at the same + indexes. This function requires the value type to implement the \c operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QOffsetVector::operator!=(const QOffsetVector &other) const + + Returns true if \a other is not equal to this vector; otherwise + returns false. + + Two vector are considered equal if they contain the same values at the same + indexes. This function requires the value type to implement the \c operator==(). + + \sa operator==() +*/ + +/*! \fn int QOffsetVector::capacity() const + + Returns the number of items the vector can store before it is full. + When a vector contains a number of items equal to its capacity, adding new + items will cause items furthest from the added item to be removed. + + \sa setCapacity(), size() +*/ + +/*! \fn int QOffsetVector::count() const + + \overload + + Same as size(). +*/ + +/*! \fn int QOffsetVector::size() const + + Returns the number of items contained within the vector. + + \sa capacity() +*/ + +/*! \fn bool QOffsetVector::isEmpty() const + + Returns true if no items are stored within the vector. + + \sa size(), capacity() +*/ + +/*! \fn bool QOffsetVector::isFull() const + + Returns true if the number of items stored within the vector is equal + to the capacity of the vector. + + \sa size(), capacity() +*/ + +/*! \fn int QOffsetVector::available() const + + Returns the number of items that can be added to the vector before it becomes full. + + \sa size(), capacity(), isFull() +*/ + +/*! \fn void QOffsetVector::clear() + + Removes all items from the vector. The capacity is unchanged. +*/ + +/*! \fn void QOffsetVector::setCapacity(int size) + + Sets the capacity of the vector to the given \a size. A vector can hold a + number of items equal to its capacity. When inserting, appending or prepending + items to the vector, if the vector is already full then the item furthest from + the added item will be removed. + + If the given \a size is smaller than the current count of items in the vector + then only the last \a size items from the vector will remain. + + \sa capacity(), isFull() +*/ + +/*! \fn const T &QOffsetVector::at(int i) const + + Returns the item at index position \a i in the vector. \a i must + be a valid index position in the vector (i.e, firstIndex() <= \a i <= lastIndex()). + + The indexes in the vector refer to number of positions the item is from the + first item appended into the vector. That is to say a vector with a capacity of + 100, that has had 150 items appended will have a valid index range of + 50 to 149. This allows inserting an retrieving items into the vector based + on a theoretical infinite list + + \sa firstIndex(), lastIndex(), insert(), operator[]() +*/ + +/*! \fn T &QOffsetVector::operator[](int i) + + Returns the item at index position \a i as a modifiable reference. If + the vector does not contain an item at the given index position \a i + then it will first insert an empty item at that position. + + In most cases it is better to use either at() or insert(). + + Note that using non-const operators can cause QOffsetVector to do a deep + copy. + + \sa insert(), at() +*/ + +/*! \fn const T &QOffsetVector::operator[](int i) const + + \overload + + Same as at(\a i). +*/ + +/*! \fn void QOffsetVector::append(const T &value) + + Inserts \a value at the end of the vector. If the vector is already full + the item at the start of the vector will be removed. + + \sa prepend(), insert(), isFull() +*/ + +/*! \fn void QOffsetVector::prepend(const T &value) + + Inserts \a value at the start of the vector. If the vector is already full + the item at the end of the vector will be removed. + + \sa append(), insert(), isFull() +*/ + +/*! \fn void QOffsetVector::insert(int i, const T &value) + + Inserts the \a value at the index position \a i. If the vector already contains + an item at \a i then that value is replaced. If \a i is either one more than + lastIndex() or one less than firstIndex() it is the equivalent to an append() + or a prepend(). + + If the given index \a i is not within the current range of the vector nor adjacent + to the bounds of the vector's index range the vector is first cleared before + inserting the item. At this point the vector will have a size of 1. It is worth + while then taking effort to insert items in an order than starts adjacent to the + current index range for the vector. + + \sa prepend(), append(), isFull(), firstIndex(), lastIndex() +*/ + +/*! \fn bool QOffsetVector::containsIndex(int i) const + + Returns true if the vector's index range includes the given index \a i. + + \sa firstIndex(), lastIndex() +*/ + +/*! \fn int QOffsetVector::firstIndex() const + Returns the first valid index in the vector. The index will be invalid if the + vector is empty. However the following code is valid even when the vector is empty: + + \code + for (int i = vector.firstIndex(); i <= vector.lastIndex(); ++i) + qDebug() << "Item" << i << "of the vector is" << vector.at(i); + \endcode + + \sa capacity(), size(), lastIndex() +*/ + +/*! \fn int QOffsetVector::lastIndex() const + + Returns the last valid index in the vector. If the vector is empty will return -1. + + \code + for (int i = vector.firstIndex(); i <= vector.lastIndex(); ++i) + qDebug() << "Item" << i << "of the vector is" << vector.at(i); + \endcode + + \sa capacity(), size(), firstIndex() +*/ + + +/*! \fn T &QOffsetVector::first() + + Returns a reference to the first item in the vector. This function + assumes that the vector isn't empty. + + \sa last(), isEmpty() +*/ + +/*! \fn T &QOffsetVector::last() + + Returns a reference to the last item in the vector. This function + assumes that the vector isn't empty. + + \sa first(), isEmpty() +*/ + +/*! \fn const T& QOffsetVector::first() const + + \overload +*/ + +/*! \fn const T& QOffsetVector::last() const + + \overload +*/ + +/*! \fn void QOffsetVector::removeFirst() + + Removes the first item from the vector. This function assumes that + the vector isn't empty. + + \sa removeLast() +*/ + +/*! \fn void QOffsetVector::removeLast() + + Removes the last item from the vector. This function assumes that + the vector isn't empty. + + \sa removeFirst() +*/ + +/*! \fn T QOffsetVector::takeFirst() + + Removes the first item in the vector and returns it. + + If you don't sue the return value, removeFirst() is more efficient. + + \sa takeLast(), removeFirst() +*/ + +/*! \fn T QOffsetVector::takeLast() + + Removes the last item in the vector and returns it. + + If you don't sue the return value, removeLast() is more efficient. + + \sa takeFirst(), removeLast() +*/ + +/*! \fn void QOffsetVector::dump() const + + \internal + + Sends information about the vector's internal structure to qDebug() +*/ diff --git a/src/corelib/tools/qoffsetvector.h b/src/corelib/tools/qoffsetvector.h new file mode 100644 index 0000000..7030862 --- /dev/null +++ b/src/corelib/tools/qoffsetvector.h @@ -0,0 +1,386 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QCIRCULARBUFFER_H +#define QCIRCULARBUFFER_H + +#include + +struct QOffsetVectorData +{ + QBasicAtomicInt ref; + int alloc; + int count; + int start; + int offset; + uint sharable : 1; + + void dump() const; +}; + +template +struct QOffsetVectorTypedData +{ + QBasicAtomicInt ref; + int alloc; + int count; + int start; + int offset; + uint sharable : 1; + + T array[1]; +}; + +class QOffsetVectorDevice; + +template +class QOffsetVector { + typedef QOffsetVectorTypedData Data; + union { QOffsetVectorData *p; QOffsetVectorTypedData *d; }; +public: + explicit QOffsetVector(int capacity = 0); + QOffsetVector(const QOffsetVector &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } + + inline ~QOffsetVector() { if (!d) return; if (!d->ref.deref()) free(d); } + + inline void detach() { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + + QOffsetVector &operator=(const QOffsetVector &other); + bool operator==(const QOffsetVector &other) const; + inline bool operator!=(const QOffsetVector &other) const { return !(*this == other); } + + inline int capacity() const {return d->alloc; } + inline int count() const { return d->count; } + inline int size() const { return d->count; } + + inline bool isEmpty() const { return d->count == 0; } + inline bool isFull() const { return d->count == d->alloc; } + inline int available() const { return d->alloc - d->count; } + + void clear(); + void setCapacity(int size); + + const T &at(int pos) const; + T &operator[](int i); + const T &operator[](int i) const; + + void append(const T &value); + void prepend(const T &value); + void insert(int pos, const T &value); + + inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; } + inline int firstIndex() const { return d->offset; } + inline int lastIndex() const { return d->offset + d->count - 1; } + + inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; } + inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; } + inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; } + inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; } + + void removeFirst(); + T takeFirst(); + void removeLast(); + T takeLast(); + + // debug + void dump() const { p->dump(); } +private: + void detach_helper(); + + QOffsetVectorData *malloc(int alloc); + void free(Data *d); + int sizeOfTypedData() { + // this is more or less the same as sizeof(Data), except that it doesn't + // count the padding at the end + return reinterpret_cast(&(reinterpret_cast(this))->array[1]) - reinterpret_cast(this); + } +}; + +template +void QOffsetVector::detach_helper() +{ + union { QOffsetVectorData *p; QOffsetVectorTypedData *d; } x; + + x.p = malloc(d->alloc); + x.d->ref = 1; + x.d->count = d->count; + x.d->start = d->start; + x.d->offset = d->offset; + x.d->alloc = d->alloc; + x.d->sharable = true; + + T *dest = x.d->array + x.d->start; + T *src = d->array + d->start; + int count = x.d->count; + while (count--) { + if (QTypeInfo::isComplex) { + new (dest) T(*src); + } else { + *dest = *src; + } + dest++; + if (dest == x.d->array + x.d->alloc) + dest = x.d->array; + src++; + if (src == d->array + d->alloc) + src = d->array; + } + + if (!d->ref.deref()) + free(d); + d = x.d; +} + +template +void QOffsetVector::setCapacity(int asize) +{ + if (asize == d->alloc) + return; + detach(); + union { QOffsetVectorData *p; QOffsetVectorTypedData *d; } x; + x.p = malloc(asize); + x.d->alloc = asize; + x.d->count = qMin(d->count, asize); + x.d->offset = d->offset + d->count - x.d->count; + x.d->start = x.d->offset % x.d->alloc; + /* deep copy - + slow way now, get unit test working, then + improve performance if need be. (e.g. memcpy) + */ + T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc; + T *src = d->array + (d->start + d->count-1) % d->alloc; + int count = x.d->count; + while (count--) { + if (QTypeInfo::isComplex) { + new (dest) T(*src); + } else { + *dest = *src; + } + if (dest == x.d->array) + dest = x.d->array + x.d->alloc; + dest--; + if (src == d->array) + src = d->array + d->alloc; + src--; + } + /* free old */ + free(d); + d = x.d; +} + +template +void QOffsetVector::clear() +{ + if (d->ref == 1) { + if (QTypeInfo::isComplex) { + int count = d->count; + T * i = d->array + d->start; + T * e = d->array + d->alloc; + while (count--) { + i->~T(); + i++; + if (i == e) + i = d->array; + } + } + d->count = d->start = d->offset = 0; + } else { + union { QOffsetVectorData *p; QOffsetVectorTypedData *d; } x; + x.p = malloc(d->alloc); + x.d->ref = 1; + x.d->alloc = d->alloc; + x.d->count = x.d->start = x.d->offset = 0; + x.d->sharable = true; + if (!d->ref.deref()) free(d); + d = x.d; + } +} + +template +inline QOffsetVectorData *QOffsetVector::malloc(int aalloc) +{ + return static_cast(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T))); +} + +template +QOffsetVector::QOffsetVector(int asize) +{ + p = malloc(asize); + d->ref = 1; + d->alloc = asize; + d->count = d->start = d->offset = 0; + d->sharable = true; +} + +template +QOffsetVector &QOffsetVector::operator=(const QOffsetVector &other) +{ + other.d->ref.ref(); + if (!d->ref.deref()) + free(d); + d = other.d; + if (!d->sharable) + detach_helper(); + return *this; +} + +template +bool QOffsetVector::operator==(const QOffsetVector &other) const +{ + if (other.d == d) + return true; + if (other.d->start != d->start + || other.d->count != d->count + || other.d->offset != d->offset + || other.d->alloc != d->alloc) + return false; + for (int i = firstIndex(); i <= lastIndex(); ++i) + if (!(at(i) == other.at(i))) + return false; + return true; +} + +template +void QOffsetVector::free(Data *x) +{ + if (QTypeInfo::isComplex) { + int count = d->count; + T * i = d->array + d->start; + T * e = d->array + d->alloc; + while (count--) { + i->~T(); + i++; + if (i == e) + i = d->array; + } + } + qFree(x); +} + +template +void QOffsetVector::append(const T &value) +{ + detach(); + if (QTypeInfo::isComplex) { + if (d->count == d->alloc) + (d->array + (d->start+d->count) % d->alloc)->~T(); + new (d->array + (d->start+d->count) % d->alloc) T(value); + } else { + d->array[(d->start+d->count) % d->alloc] = value; + } + + if (d->count == d->alloc) { + d->start++; + d->start %= d->alloc; + d->offset++; + } else { + d->count++; + } +} + +template +void QOffsetVector::prepend(const T &value) +{ + detach(); + if (d->start) + d->start--; + else + d->start = d->alloc-1; + d->offset--; + + if (d->count != d->alloc) + d->count++; + else + if (d->count == d->alloc) + (d->array + d->start)->~T(); + + if (QTypeInfo::isComplex) + new (d->array + d->start) T(value); + else + d->array[d->start] = value; +} + +template +void QOffsetVector::insert(int pos, const T &value) +{ + detach(); + if (containsIndex(pos)) { + if(QTypeInfo::isComplex) + new (d->array + pos % d->alloc) T(value); + else + d->array[pos % d->alloc] = value; + } else if (pos == d->offset-1) + prepend(value); + else if (pos == d->offset+d->count) + append(value); + else { + // we don't leave gaps. + clear(); + d->offset = d->start = pos; + d->start %= d->alloc; + d->count = 1; + if (QTypeInfo::isComplex) + new (d->array + d->start) T(value); + else + d->array[d->start] = value; + } +} + +template +inline const T &QOffsetVector::at(int pos) const +{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QOffsetVector::at", "index out of range"); return d->array[pos % d->alloc]; } +template +inline const T &QOffsetVector::operator[](int pos) const +{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QOffsetVector::at", "index out of range"); return d->array[pos % d->alloc]; } +template + +// can use the non-inline one to modify the index range. +inline T &QOffsetVector::operator[](int pos) +{ + detach(); + if (!containsIndex(pos)) + insert(pos, T()); + return d->array[pos % d->alloc]; +} + +template +inline void QOffsetVector::removeFirst() +{ + Q_ASSERT(d->count > 0); + detach(); + d->count--; + if (QTypeInfo::isComplex) + (d->array + d->start)->~T(); + d->start = (d->start + 1) % d->alloc; + d->offset++; +} + +template +inline void QOffsetVector::removeLast() +{ + Q_ASSERT(d->count > 0); + detach(); + d->count--; + if (QTypeInfo::isComplex) + (d->array + (d->start + d->count) % d->alloc)->~T(); +} + +template +inline T QOffsetVector::takeFirst() +{ T t = first(); removeFirst(); return t; } + +template +inline T QOffsetVector::takeLast() +{ T t = last(); removeLast(); return t; } + +#endif diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index e5bf7e4..626c9e5 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -19,6 +19,7 @@ HEADERS += \ tools/qlocale_p.h \ tools/qlocale_data_p.h \ tools/qmap.h \ + tools/qoffsetvector.h \ tools/qpodlist_p.h \ tools/qpoint.h \ tools/qqueue.h \ @@ -53,6 +54,7 @@ SOURCES += \ tools/qlocale.cpp \ tools/qpoint.cpp \ tools/qmap.cpp \ + tools/qoffsetvector.cpp \ tools/qrect.cpp \ tools/qregexp.cpp \ tools/qshareddata.cpp \ diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 19f6b43..5d71e79 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -209,6 +209,7 @@ SUBDIRS += bic \ qnumeric \ qobject \ qobjectrace \ + qoffsetvector \ qpaintengine \ qpainter \ qpainterpath \ diff --git a/tests/auto/qoffsetvector/qoffsetvector.pro b/tests/auto/qoffsetvector/qoffsetvector.pro new file mode 100644 index 0000000..0b801f3 --- /dev/null +++ b/tests/auto/qoffsetvector/qoffsetvector.pro @@ -0,0 +1,8 @@ +load(qttest_p4) + +QT = core + +SOURCES += tst_qoffsetvector.cpp + + + diff --git a/tests/auto/qoffsetvector/tst_qoffsetvector.cpp b/tests/auto/qoffsetvector/tst_qoffsetvector.cpp new file mode 100644 index 0000000..439ea2c --- /dev/null +++ b/tests/auto/qoffsetvector/tst_qoffsetvector.cpp @@ -0,0 +1,361 @@ +/**************************************************************************** +** +** This file is part of the $PACKAGE_NAME$. +** +** Copyright (C) $THISYEAR$ $COMPANY_NAME$. +** +** $QT_EXTENDED_DUAL_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +#if defined(FORCE_UREF) +template +inline QDebug &operator<<(QDebug debug, const QOffsetVector &offsetVector) +#else +template +inline QDebug operator<<(QDebug debug, const QOffsetVector &offsetVector) +#endif +{ + debug.nospace() << "QOffsetVector("; + for (int i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { + debug << offsetVector[i]; + if (i != offsetVector.lastIndex()) + debug << ", "; + } + debug << ")"; + return debug.space(); +} + +#if defined(NO_BENCHMARK) and defined(QBENCHMARK) +#undef QBENCHMARK +#define QBENCHMARK +#endif + +class tst_QOffsetVector : public QObject +{ + Q_OBJECT +public: + tst_QOffsetVector() {} + virtual ~tst_QOffsetVector() {} +private slots: + void empty(); + void forwardBuffer(); + void scrollingList(); + + void complexType(); + + void operatorAt(); + + void cacheBenchmark(); + void offsetVectorBenchmark(); + + void setCapacity(); +}; + +QTEST_MAIN(tst_QOffsetVector) + +void tst_QOffsetVector::empty() +{ + QOffsetVector c(10); + QCOMPARE(c.capacity(), 10); + QCOMPARE(c.count(), 0); + QVERIFY(c.isEmpty()); + c.append(1); + QVERIFY(!c.isEmpty()); + c.clear(); + QCOMPARE(c.capacity(), 10); + QCOMPARE(c.count(), 0); + QVERIFY(c.isEmpty()); + c.prepend(1); + QVERIFY(!c.isEmpty()); + c.clear(); + QCOMPARE(c.count(), 0); + QVERIFY(c.isEmpty()); + QCOMPARE(c.capacity(), 10); +} + +void tst_QOffsetVector::forwardBuffer() +{ + int i; + QOffsetVector c(10); + for(i = 1; i < 30; ++i) { + c.append(i); + QCOMPARE(c.first(), qMax(1, i-9)); + QCOMPARE(c.last(), i); + QCOMPARE(c.count(), qMin(i, 10)); + } + + c.clear(); + + for(i = 1; i < 30; ++i) { + c.prepend(i); + QCOMPARE(c.last(), qMax(1, i-9)); + QCOMPARE(c.first(), i); + QCOMPARE(c.count(), qMin(i, 10)); + } +} + +void tst_QOffsetVector::scrollingList() +{ + int i; + QOffsetVector c(10); + + // Once allocated QOffsetVector should not + // allocate any additional memory for non + // complex data types. + QBENCHMARK { + // simulate scrolling in a list of items; + for(i = 0; i < 10; ++i) + c.append(i); + + QCOMPARE(c.firstIndex(), 0); + QCOMPARE(c.lastIndex(), 9); + QVERIFY(c.containsIndex(0)); + QVERIFY(c.containsIndex(9)); + QVERIFY(!c.containsIndex(10)); + + for (i = 0; i < 10; ++i) + QCOMPARE(c.at(i), i); + + for (i = 10; i < 30; ++i) + c.append(i); + + QCOMPARE(c.firstIndex(), 20); + QCOMPARE(c.lastIndex(), 29); + QVERIFY(c.containsIndex(20)); + QVERIFY(c.containsIndex(29)); + QVERIFY(!c.containsIndex(30)); + + for (i = 20; i < 30; ++i) + QCOMPARE(c.at(i), i); + + for (i = 19; i >= 10; --i) + c.prepend(i); + + QCOMPARE(c.firstIndex(), 10); + QCOMPARE(c.lastIndex(), 19); + QVERIFY(c.containsIndex(10)); + QVERIFY(c.containsIndex(19)); + QVERIFY(!c.containsIndex(20)); + + for (i = 10; i < 20; ++i) + QCOMPARE(c.at(i), i); + + for (i = 200; i < 220; ++i) + c.insert(i, i); + + QCOMPARE(c.firstIndex(), 210); + QCOMPARE(c.lastIndex(), 219); + QVERIFY(c.containsIndex(210)); + QVERIFY(c.containsIndex(219)); + QVERIFY(!c.containsIndex(300)); + QVERIFY(!c.containsIndex(209)); + + for (i = 220; i < 220; ++i) { + QVERIFY(c.containsIndex(i)); + QCOMPARE(c.at(i), i); + } + c.clear(); // needed to reset benchmark + } + + // from a specific bug that was encountered. 100 to 299 cached, attempted to cache 250 - 205 via insert, failed. + // bug was that item at 150 would instead be item that should have been inserted at 250 + c.setCapacity(200); + for(i = 100; i < 300; ++i) + c.insert(i, i); + for (i = 250; i <= 306; ++i) + c.insert(i, 1000+i); + for (i = 107; i <= 306; ++i) { + QVERIFY(c.containsIndex(i)); + QCOMPARE(c.at(i), i < 250 ? i : 1000+i); + } +} + +struct RefCountingClassData +{ + QBasicAtomicInt ref; + static RefCountingClassData shared_null; +}; + +RefCountingClassData RefCountingClassData::shared_null = { + Q_BASIC_ATOMIC_INITIALIZER(1) +}; + +class RefCountingClass +{ +public: + RefCountingClass() : d(&RefCountingClassData::shared_null) { d->ref.ref(); } + + RefCountingClass(const RefCountingClass &other) + { + d = other.d; + d->ref.ref(); + } + + ~RefCountingClass() + { + if (!d->ref.deref()) + delete d; + } + + RefCountingClass &operator=(const RefCountingClass &other) + { + if (!d->ref.deref()) + delete d; + d = other.d; + d->ref.ref(); + return *this; + } + + int refCount() const { return d->ref; } +private: + RefCountingClassData *d; +}; + +void tst_QOffsetVector::complexType() +{ + RefCountingClass original; + + QOffsetVector offsetVector(10); + offsetVector.append(original); + QCOMPARE(original.refCount(), 3); + offsetVector.removeFirst(); + QCOMPARE(original.refCount(), 2); // shared null, 'original'. + offsetVector.append(original); + QCOMPARE(original.refCount(), 3); + offsetVector.clear(); + QCOMPARE(original.refCount(), 2); + + for(int i = 0; i < 100; ++i) + offsetVector.insert(i, original); + + QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in offsetVector. + + offsetVector.clear(); + QCOMPARE(original.refCount(), 2); + for (int i = 0; i < 100; i++) + offsetVector.append(original); + + QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in offsetVector. + offsetVector.clear(); + QCOMPARE(original.refCount(), 2); + + for (int i = 0; i < 100; i++) + offsetVector.prepend(original); + + QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in offsetVector. + offsetVector.clear(); + QCOMPARE(original.refCount(), 2); + + for (int i = 0; i < 100; i++) + offsetVector.append(original); + + offsetVector.takeLast(); + QCOMPARE(original.refCount(), 11); + + offsetVector.takeFirst(); + QCOMPARE(original.refCount(), 10); +} + +void tst_QOffsetVector::operatorAt() +{ + RefCountingClass original; + QOffsetVector offsetVector(10); + + for (int i = 25; i < 35; ++i) + offsetVector[i] = original; + + QCOMPARE(original.refCount(), 12); // shared null, orig, items in vector + + // verify const access does not copy items. + const QOffsetVector copy(offsetVector); + for (int i = 25; i < 35; ++i) + QCOMPARE(copy[i].refCount(), 12); + + // verify modifying the original increments ref count (e.g. does a detach) + offsetVector[25] = original; + QCOMPARE(original.refCount(), 22); +} + +/* + Benchmarks must be near identical in tasks to be fair. + QCache uses pointers to ints as its a requirement of QCache, + whereas QOffsetVector doesn't support pointers (won't free them). + Given the ability to use simple data types is a benefit, its + fair. Although this obviously must take into account we are + testing QOffsetVector use cases here, QCache has its own + areas where it is the more sensible class to use. +*/ +void tst_QOffsetVector::cacheBenchmark() +{ + QBENCHMARK { + QCache cache; + cache.setMaxCost(100); + + for (int i = 0; i < 1000; i++) + cache.insert(i, new int(i)); + } +} + +void tst_QOffsetVector::offsetVectorBenchmark() +{ + QBENCHMARK { + QOffsetVector offsetVector(100); + for (int i = 0; i < 1000; i++) + offsetVector.insert(i, i); + } +} + +void tst_QOffsetVector::setCapacity() +{ + int i; + QOffsetVector offsetVector(100); + for (i = 280; i < 310; ++i) + offsetVector.insert(i, i); + QCOMPARE(offsetVector.capacity(), 100); + QCOMPARE(offsetVector.count(), 30); + QCOMPARE(offsetVector.firstIndex(), 280); + QCOMPARE(offsetVector.lastIndex(), 309); + + for (i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { + QVERIFY(offsetVector.containsIndex(i)); + QCOMPARE(offsetVector.at(i), i); + } + + offsetVector.setCapacity(150); + + QCOMPARE(offsetVector.capacity(), 150); + QCOMPARE(offsetVector.count(), 30); + QCOMPARE(offsetVector.firstIndex(), 280); + QCOMPARE(offsetVector.lastIndex(), 309); + + for (i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { + QVERIFY(offsetVector.containsIndex(i)); + QCOMPARE(offsetVector.at(i), i); + } + + offsetVector.setCapacity(20); + + QCOMPARE(offsetVector.capacity(), 20); + QCOMPARE(offsetVector.count(), 20); + QCOMPARE(offsetVector.firstIndex(), 290); + QCOMPARE(offsetVector.lastIndex(), 309); + + for (i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { + QVERIFY(offsetVector.containsIndex(i)); + QCOMPARE(offsetVector.at(i), i); + } +} + +#include "tst_qoffsetvector.moc" -- cgit v0.12 From 16488d6e1073ce311c173d78c16be8da1f57f94e Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 30 Mar 2009 16:44:55 +0200 Subject: Doc: Synchronized the QTransform constructor arguments with the class documentation and updated a diagram. Task-number: 228201 Reviewed-by: TrustMe --- doc/src/diagrams/qtransform-representation.sk | 103 ++++++++++++++++++++++++++ src/gui/painting/qtransform.cpp | 19 +++-- 2 files changed, 114 insertions(+), 8 deletions(-) create mode 100644 doc/src/diagrams/qtransform-representation.sk diff --git a/doc/src/diagrams/qtransform-representation.sk b/doc/src/diagrams/qtransform-representation.sk new file mode 100644 index 0000000..17dcbfe --- /dev/null +++ b/doc/src/diagrams/qtransform-representation.sk @@ -0,0 +1,103 @@ +##Sketch 1 2 +document() +layout('A4',0) +layer('Layer 1',1,1,0,0,(0,0,0)) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,190,760) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,190,695) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,190,630) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,320,760) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,320,695) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,320,630) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,255,760) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,255,695) +lp((0,0,1)) +lw(2) +r(65,0,0,-65,255,630) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m33',(329.16,589.968)) +G() +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('dy',(274.828,577.768)) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m32',(264.16,602.768)) +G_() +G() +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m31',(199.16,602.768)) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('dx',(209.828,577.8)) +G_() +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m11',(199.16,719.968)) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m12',(264.16,719.968)) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m13',(329.16,719.968)) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m21',(199.16,654.968)) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m22',(264.16,654.968)) +fp((0,0,0)) +le() +lw(1) +Fn('Helvetica') +Fs(24) +txt('m23',(329.16,654.968)) +guidelayer('Guide Lines',1,0,0,1,(0,0,1)) +grid((0,0,5,5),1,(0,0,1),'Grid') diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp index da8c428..c70208c 100644 --- a/src/gui/painting/qtransform.cpp +++ b/src/gui/painting/qtransform.cpp @@ -168,10 +168,10 @@ QT_BEGIN_NAMESPACE \image qtransform-representation.png - A QTransform object contains a 3 x 3 matrix. The \c dx and \c dy - elements specify horizontal and vertical translation. The \c m11 - and \c m22 elements specify horizontal and vertical scaling. The - \c m21 and \c m12 elements specify horizontal and vertical \e shearing. + A QTransform object contains a 3 x 3 matrix. The \c m31 (\c dx) and + \c m32 (\c dy) elements specify horizontal and vertical translation. + The \c m11 and \c m22 elements specify horizontal and vertical scaling. + The \c m21 and \c m12 elements specify horizontal and vertical \e shearing. And finally, the \c m13 and \c m23 elements specify horizontal and vertical projection, with \c m33 as an additional projection factor. @@ -246,8 +246,10 @@ QTransform::QTransform() } /*! - Constructs a matrix with the elements, \a h11, \a h12, \a h13, - \a h21, \a h22, \a h23, \a h31, \a h32, \a h33. + \fn QTransform::QTransform(qreal m11, qreal m12, qreal m13, qreal m21, qreal m22, qreal m23, qreal m31, qreal m32, qreal m33) + + Constructs a matrix with the elements, \a m11, \a m12, \a m13, + \a m21, \a m22, \a m23, \a m31, \a m32, \a m33. \sa setMatrix() */ @@ -263,8 +265,9 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13, } /*! - Constructs a matrix with the elements, \a h11, \a h12, \a h21, \a - h22, \a dx and \a dy. + \fn QTransform::QTransform(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy) + + Constructs a matrix with the elements, \a m11, \a m12, \a m21, \a m22, \a dx and \a dy. \sa setMatrix() */ -- cgit v0.12 From 1e2fdb56ce6025b34b88b1da1386f8c79464b412 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 30 Mar 2009 16:48:26 +0200 Subject: Doc: Synchronized the QTransform constructor arguments with the class documentation and updated a diagram. Task-number: 228201 Reviewed-by: TrustMe --- doc/src/images/qtransform-representation.png | Bin 17892 -> 17385 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/src/images/qtransform-representation.png b/doc/src/images/qtransform-representation.png index 2608872..883d5dc 100644 Binary files a/doc/src/images/qtransform-representation.png and b/doc/src/images/qtransform-representation.png differ -- cgit v0.12 From 87f1ea14ae7e245dd7589b1d992f67b0058ae1b5 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 30 Mar 2009 17:03:01 +0200 Subject: Doc: Fixed typo. Reviewed-by: TrustMe --- src/corelib/kernel/qmetatype.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 4d7d309..ce10bae 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -1255,7 +1255,7 @@ void QMetaType::destroy(int type, void *data) \relates QMetaType \threadsafe - Registers the type name \a typeName to the type \c{T}. Returns + Registers the type name \a typeName for the type \c{T}. Returns the internal ID used by QMetaType. Any class or struct that has a public default constructor, a public copy constructor and a public destructor can be registered. -- cgit v0.12 From 577853b93dd4cf848abbd95abfed7e5a9d48688b Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 30 Mar 2009 18:11:04 +0200 Subject: Doc: Added a code snippet to illustrate the opening of local files. Task-number: 223087 Reviewed-by: TrustMe --- doc/src/snippets/code/src_gui_util_qdesktopservices.cpp | 5 ++++- src/gui/util/qdesktopservices.cpp | 5 +++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/src/snippets/code/src_gui_util_qdesktopservices.cpp b/doc/src/snippets/code/src_gui_util_qdesktopservices.cpp index a9c630b..5001984 100644 --- a/doc/src/snippets/code/src_gui_util_qdesktopservices.cpp +++ b/doc/src/snippets/code/src_gui_util_qdesktopservices.cpp @@ -11,7 +11,10 @@ public slots: QDesktopServices::setUrlHandler("help", helpInstance, "showHelp"); //! [0] - //! [1] mailto:user@foo.com?subject=Test&body=Just a test //! [1] + +//! [2] +QDesktopServices::openUrl(QUrl("file:///C:/Documents and Settings/All Users/Desktop", QUrl::TolerantMode)); +//! [2] diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 0fe1d69..84aa16e 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -157,6 +157,11 @@ void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler) If the URL is a reference to a local file (i.e., the URL scheme is "file") then it will be opened with a suitable application instead of a Web browser. + The following example opens a file on the Windows file system residing on a path + that contains spaces: + + \snippet doc/src/snippets/code/src_gui_util_qdesktopservices.cpp 2 + If a \c mailto URL is specified, the user's e-mail client will be used to open a composer window containing the options specified in the URL, similar to the way \c mailto links are handled by a Web browser. -- cgit v0.12 From 22ee1110301b228bbcbe9d39a9bcebe9ab4cdad0 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 31 Mar 2009 14:55:33 +0200 Subject: Doc: Removed a reference to a deprecated function. Reported by a former Doc Manager. Reviewed-by: TrustMe --- src/gui/dialogs/qcolordialog.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/dialogs/qcolordialog.cpp b/src/gui/dialogs/qcolordialog.cpp index b744dca..3aa04f6 100644 --- a/src/gui/dialogs/qcolordialog.cpp +++ b/src/gui/dialogs/qcolordialog.cpp @@ -1523,10 +1523,10 @@ static const Qt::WindowFlags DefaultWindowFlags = If you require a modeless dialog, use the QColorDialog constructor. \endomit - The static getColor() function shows the dialog, and allows the - user to specify a color. The getRgba() function does the same, but - also allows the user to specify a color with an alpha channel - (transparency) value. + The static getColor() function shows the dialog, and allows the user to + specify a color. This function can also be used to let users choose a + color with a level of transparency: pass the ShowAlphaChannel option as + an additional argument. The user can store customCount() different custom colors. The custom colors are shared by all color dialogs, and remembered -- cgit v0.12 From 94c3e15e0fd04a178c319c2bc151b492a46380ee Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 31 Mar 2009 16:53:36 +0200 Subject: Doc: Clarified that the main use case for QRegion is as a clipping primitive not as a rendering primitive. Task-number: 183493 Reviewed-by: TrustMe --- src/gui/painting/qregion.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 8169ef8..c88af7c 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -65,9 +65,17 @@ QT_BEGIN_NAMESPACE \ingroup shared QRegion is used with QPainter::setClipRegion() to limit the paint - area to what needs to be painted. There is also a - QWidget::repaint() function that takes a QRegion parameter. - QRegion is the best tool for reducing flicker. + area to what needs to be painted. There is also a QWidget::repaint() + function that takes a QRegion parameter. QRegion is the best tool for + minimizing the amount of screen area to be updated by a repaint. + + This class is not suitable for constructing shapes for rendering, especially + as outlines. Use QPainterPath to create paths and shapes for use with + QPainter. + + QRegion is an \l{implicitly shared} class. + + \section1 Creating and Using Regions A region can be created from a rectangle, an ellipse, a polygon or a bitmap. Complex regions may be created by combining simple @@ -84,8 +92,6 @@ QT_BEGIN_NAMESPACE Example of using complex regions: \snippet doc/src/snippets/code/src_gui_painting_qregion.cpp 0 - QRegion is an \l{implicitly shared} class. - \warning Due to window system limitations, the whole coordinate space for a region is limited to the points between -32767 and 32767 on Windows 95/98/ME. You can circumvent this limitation by using a QPainterPath. @@ -93,7 +99,7 @@ QT_BEGIN_NAMESPACE \section1 Additional License Information On Embedded Linux, Windows CE and X11 platforms, parts of this class rely on - code obtained under the following license: + code obtained under the following licenses: \legalese Copyright (c) 1987 X Consortium @@ -120,9 +126,7 @@ QT_BEGIN_NAMESPACE in this Software without prior written authorization from the X Consortium. \endlegalese - \raw HTML -
- \endraw + \br \legalese Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. -- cgit v0.12 From cf4d9e09afc72dfb474b497a95c872965335e341 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 31 Mar 2009 17:35:33 +0200 Subject: Doc: Noted the difference between the qLowerBound() functions. Task-number: 160621 Reviewed-by: TrustMe --- doc/src/qalgorithms.qdoc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/doc/src/qalgorithms.qdoc b/doc/src/qalgorithms.qdoc index 459fb81..b33c250 100644 --- a/doc/src/qalgorithms.qdoc +++ b/doc/src/qalgorithms.qdoc @@ -490,7 +490,10 @@ of \a value in the variable passed as a reference in argument \a n. \overload - This is the same as qLowerBound(\a{container}.begin(), \a{container}.end(), value); + For read-only iteration over containers, this function is broadly equivalent to + qLowerBound(\a{container}.begin(), \a{container}.end(), value). However, since it + returns a const iterator, you cannot use it to modify the container; for example, + to insert items. */ /*! \fn RandomAccessIterator qUpperBound(RandomAccessIterator begin, RandomAccessIterator end, const T &value) -- cgit v0.12 From 93ca19a8ff7570606b4c01cfb9953921f897aa6e Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 31 Mar 2009 17:38:40 +0200 Subject: Doc: Made it clearer that QProcess::start() only starts a new process if one is not already running. Task-number: 231513 Reviewed-by: TrustMe --- src/corelib/io/qprocess.cpp | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index a9d8ee2..18618fc 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -1476,11 +1476,15 @@ QByteArray QProcess::readAllStandardError() } /*! - Starts the program \a program in a new process, passing the - command line arguments in \a arguments. The OpenMode is set to \a - mode. QProcess will immediately enter the Starting state. If the - process starts successfully, QProcess will emit started(); - otherwise, error() will be emitted. + Starts the program \a program in a new process, if one is not already + running, passing the command line arguments in \a arguments. The OpenMode + is set to \a mode. + + The QProcess object will immediately enter the Starting state. If the + process starts successfully, QProcess will emit started(); otherwise, + error() will be emitted. If the QProcess object is already running a + process, a warning may be printed at the console, and the existing + process will continue running. Note that arguments that contain spaces are not passed to the process as separate arguments. @@ -1577,10 +1581,10 @@ static QStringList parseCombinedArgString(const QString &program) /*! \overload - Starts the program \a program in a new process. \a program is a - single string of text containing both the program name and its - arguments. The arguments are separated by one or more - spaces. For example: + Starts the program \a program in a new process, if one is not already + running. \a program is a single string of text containing both the + program name and its arguments. The arguments are separated by one or + more spaces. For example: \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 5 @@ -1589,6 +1593,9 @@ static QStringList parseCombinedArgString(const QString &program) \snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 6 + If the QProcess object is already running a process, a warning may be + printed at the console, and the existing process will continue running. + Note that, on Windows, quotes need to be both escaped and quoted. For example, the above code would be specified in the following way to ensure that \c{"My Documents"} is used as the argument to -- cgit v0.12 From 65c16391fff38e28e4a9db215758b1df6c868a32 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Tue, 31 Mar 2009 19:53:21 +0200 Subject: Doc: Fixed the screenshots and example description to match the code. Task-number: 242369 Reviewed-by: TrustMe --- doc/src/examples/extension.qdoc | 11 +++++------ doc/src/images/extension-example.png | Bin 7676 -> 9929 bytes doc/src/images/extension_more.png | Bin 9309 -> 13523 bytes 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/doc/src/examples/extension.qdoc b/doc/src/examples/extension.qdoc index 8a0ca3a..02e0698 100644 --- a/doc/src/examples/extension.qdoc +++ b/doc/src/examples/extension.qdoc @@ -80,9 +80,9 @@ user type a word to search for, we need several \l {QCheckBox}{QCheckBox}es to facilitate the search options, and we need three \l {QPushButton}{QPushButton}s: the \gui Find button to - start a search, the \gui More button to enable an advanced search, - and the \gui Close button to exit the application. Finally, we - need a QWidget representing the application's extension part. + start a search and the \gui More button to enable an advanced search. + Finally, we need a QWidget representing the application's extension + part. \section1 FindDialog Class Implementation @@ -128,8 +128,7 @@ the connection makes sure that the extension widget is shown depending on the state of \gui More button. - We also connect the \gui Close button to the QWidget::close() - slot, and we put the checkboxes associated with the advanced + We also put the check boxes associated with the advanced search options into a layout we install on the extension widget. \snippet examples/dialogs/extension/finddialog.cpp 4 @@ -137,7 +136,7 @@ Before we create the main layout, we create several child layouts for the widgets: First we allign the QLabel ans its buddy, the QLineEdit, using a QHBoxLayout. Then we vertically allign the - QLabel and QLineEdit with the checkboxes associated with the + QLabel and QLineEdit with the check boxes associated with the simple search, using a QVBoxLayout. We also create a QVBoxLayout for the buttons. In the end we lay out the two latter layouts and the extension widget using a QGridLayout. diff --git a/doc/src/images/extension-example.png b/doc/src/images/extension-example.png index dfaacc0..18fab52 100644 Binary files a/doc/src/images/extension-example.png and b/doc/src/images/extension-example.png differ diff --git a/doc/src/images/extension_more.png b/doc/src/images/extension_more.png index 2b06809..407af27 100644 Binary files a/doc/src/images/extension_more.png and b/doc/src/images/extension_more.png differ -- cgit v0.12 From 23174985c19c61fbce412965ecc1ba49c1cb5582 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 1 Apr 2009 16:36:19 +0200 Subject: Doc: Minor language fixes and tidying. Reviewed-by: TrustMe --- doc/src/phonon-api.qdoc | 2 +- doc/src/phonon.qdoc | 2 +- doc/src/qnamespace.qdoc | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/src/phonon-api.qdoc b/doc/src/phonon-api.qdoc index 147ded3..3d04c68 100644 --- a/doc/src/phonon-api.qdoc +++ b/doc/src/phonon-api.qdoc @@ -2568,7 +2568,7 @@ details. Phonon also provides EffectWidget, which lets the user modify the - parameters of an effect an the fly, e.g., with comboboxes. + parameters of an effect an the fly; e.g., with combo boxes. \sa {Phonon Module}, EffectWidget */ diff --git a/doc/src/phonon.qdoc b/doc/src/phonon.qdoc index fa84b96..9470e61 100644 --- a/doc/src/phonon.qdoc +++ b/doc/src/phonon.qdoc @@ -49,7 +49,7 @@ \section1 Introduction Qt uses the Phonon multimedia framework to provide functionality - for playback of the most common multimedia formats.The media can + for playback of the most common multimedia formats. The media can be read from files or streamed over a network, using a QURL to a file. diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index 6220795..e6a1a36 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -508,11 +508,11 @@ \value DirectConnection When emitted, the signal is immediately delivered to the slot. \value QueuedConnection When emitted, the signal is queued until the event loop is able to deliver it to the slot. - \value - BlockingQueuedConnection Same as QueuedConnection, except that the current thread blocks + \value BlockingQueuedConnection + Same as QueuedConnection, except that the current thread blocks until the slot has been delivered. This connection type should only be used for receivers in a different thread. Note that misuse - of this type can lead to dead locks in your application. + of this type can lead to deadlocks in your application. \value AutoConnection If the signal is emitted from the thread in which the receiving object lives, the slot is invoked directly, as with -- cgit v0.12 From 80293b874047c028e47d91d33c2afe157d9e6785 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 1 Apr 2009 16:37:14 +0200 Subject: Doc: Trivial fixes. Reviewed-by: TrustMe --- src/corelib/global/qglobal.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 1645279..8324d05 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2944,12 +2944,12 @@ bool QInternal::callFunction(InternalFunction func, void **args) Compares the floating point value \a p1 and \a p2 and returns \c true if they are considered equal, otherwise \c false. - + Note that comparing values where either \a p1 or \a p2 is 0.0 will not work. - The solution to this is to compare against values greater than or equal to 1.0 - + The solution to this is to compare against values greater than or equal to 1.0. + \snippet doc/src/snippets/code/src_corelib_global_qglobal.cpp 46 - + The two numbers are compared in a relative way, where the exactness is stronger the smaller the numbers are. */ -- cgit v0.12 From 244daeabfb55160387985d0ff3f057aa03d4d2da Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 1 Apr 2009 16:38:15 +0200 Subject: Doc: Updated the deployment documentation with the QtScriptTools module and references to Phonon documentation. Task-number: 212939 Reviewed-by: TrustMe --- doc/src/deployment.qdoc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/src/deployment.qdoc b/doc/src/deployment.qdoc index 7e02f1a..d9f7c1a 100644 --- a/doc/src/deployment.qdoc +++ b/doc/src/deployment.qdoc @@ -91,7 +91,7 @@ The disadvantage with the shared library approach is that you will get more files to deploy. For more information, see \l{sharedlibrary.html}{Creating Shared Libraries}. - + \section1 Deploying Qt's Libraries \table @@ -111,13 +111,14 @@ \o \l {QtNetwork} \o \l {QtOpenGL} \o \l {QtScript} - \o \l {QtSql} + \o \l {QtScriptTools} \row + \o \l {QtSql} \o \l {QtSvg} \o \l {QtWebKit} \o \l {QtXml} - \o \l {QtXmlPatterns} \row + \o \l {QtXmlPatterns} \o \l {Phonon Module}{Phonon} \o \l {Qt3Support} \endtable @@ -178,11 +179,13 @@ Please see \l{QtWebKit Module#License Information}{the QtWebKit module documentation} for more information. - \row \o Phonon \o Phonon + \row \o \l{Phonon Module}{Phonon} \o Phonon \o Phonon relies on the native multimedia engines on different platforms. Phonon itself is licensed under the GNU LGPL version 2. Please see \l{Phonon Module#License Information}{the Phonon module documentation} - for more information. + for more information on licensing and the + \l{Phonon Overview#Backends}{Phonon Overview} for details of the backends + in use on different platforms. \endtable \section1 Platform-Specific Notes -- cgit v0.12 From 10d0536fd3b08a394c41de349e67325183328ec6 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Wed, 1 Apr 2009 16:59:51 +0200 Subject: Doc: Clarified the usage of QImage::dotsPerMeterX() and QImage::dotsPerMeterY(). Task-number: 240164 Reviewed-by: Jan Erik Hanssen --- src/gui/image/qimage.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index 558d574..dc236e4 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -4937,10 +4937,12 @@ int QImage::dotsPerMeterY() const meter, to \a x. Together with dotsPerMeterY(), this number defines the intended - scale and aspect ratio of the image. + scale and aspect ratio of the image, and determines the scale + at which QPainter will draw graphics on the image. It does not + change the scale or aspect ratio of the image when it is rendered + on other paint devices. - \sa dotsPerMeterX(), {QImage#Image Information}{Image - Information} + \sa dotsPerMeterX(), {QImage#Image Information}{Image Information} */ void QImage::setDotsPerMeterX(int x) { @@ -4957,10 +4959,12 @@ void QImage::setDotsPerMeterX(int x) to \a y. Together with dotsPerMeterX(), this number defines the intended - scale and aspect ratio of the image. + scale and aspect ratio of the image, and determines the scale + at which QPainter will draw graphics on the image. It does not + change the scale or aspect ratio of the image when it is rendered + on other paint devices. - \sa dotsPerMeterY(), {QImage#Image Information}{Image - Information} + \sa dotsPerMeterY(), {QImage#Image Information}{Image Information} */ void QImage::setDotsPerMeterY(int y) { -- cgit v0.12 From 423d6052844b2026c8acc8826d6546d3afc494d3 Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Fri, 3 Apr 2009 12:44:38 +1000 Subject: Rename OffsetVector to ContiguousCache --- doc/src/examples/contiguouscache.qdoc | 69 ++++ doc/src/examples/offsetvector.qdoc | 70 ---- examples/tools/contiguouscache/contiguouscache.pro | 9 + examples/tools/contiguouscache/main.cpp | 15 + examples/tools/contiguouscache/randomlistmodel.cpp | 56 +++ examples/tools/contiguouscache/randomlistmodel.h | 26 ++ examples/tools/offsetvector/main.cpp | 15 - examples/tools/offsetvector/offsetvector.pro | 9 - examples/tools/offsetvector/randomlistmodel.cpp | 56 --- examples/tools/offsetvector/randomlistmodel.h | 26 -- examples/tools/tools.pro | 2 +- src/corelib/tools/qcontiguouscache.cpp | 359 +++++++++++++++++++ src/corelib/tools/qcontiguouscache.h | 386 +++++++++++++++++++++ src/corelib/tools/qoffsetvector.cpp | 360 ------------------- src/corelib/tools/qoffsetvector.h | 386 --------------------- src/corelib/tools/tools.pri | 4 +- tests/auto/qcontiguouscache/qcontiguouscache.pro | 8 + .../auto/qcontiguouscache/tst_qcontiguouscache.cpp | 361 +++++++++++++++++++ tests/auto/qoffsetvector/qoffsetvector.pro | 8 - tests/auto/qoffsetvector/tst_qoffsetvector.cpp | 361 ------------------- 20 files changed, 1292 insertions(+), 1294 deletions(-) create mode 100644 doc/src/examples/contiguouscache.qdoc delete mode 100644 doc/src/examples/offsetvector.qdoc create mode 100644 examples/tools/contiguouscache/contiguouscache.pro create mode 100644 examples/tools/contiguouscache/main.cpp create mode 100644 examples/tools/contiguouscache/randomlistmodel.cpp create mode 100644 examples/tools/contiguouscache/randomlistmodel.h delete mode 100644 examples/tools/offsetvector/main.cpp delete mode 100644 examples/tools/offsetvector/offsetvector.pro delete mode 100644 examples/tools/offsetvector/randomlistmodel.cpp delete mode 100644 examples/tools/offsetvector/randomlistmodel.h create mode 100644 src/corelib/tools/qcontiguouscache.cpp create mode 100644 src/corelib/tools/qcontiguouscache.h delete mode 100644 src/corelib/tools/qoffsetvector.cpp delete mode 100644 src/corelib/tools/qoffsetvector.h create mode 100644 tests/auto/qcontiguouscache/qcontiguouscache.pro create mode 100644 tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp delete mode 100644 tests/auto/qoffsetvector/qoffsetvector.pro delete mode 100644 tests/auto/qoffsetvector/tst_qoffsetvector.cpp diff --git a/doc/src/examples/contiguouscache.qdoc b/doc/src/examples/contiguouscache.qdoc new file mode 100644 index 0000000..22c97fa --- /dev/null +++ b/doc/src/examples/contiguouscache.qdoc @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +/*! + \example tools/contiguouscache + \title Contiguous Cache Example + + The Contiguous Cache example shows how to use QContiguousCache to manage memory usage for + very large models. In some environments memory is limited, and even when it + isn't users still dislike an application using + excessive memory. Using QContiguousCache to manage a list rather than loading + the entire list into memory allows the application to limit the amount + of memory it uses regardless of the size of the data set it accesses + + The simplest way to use QContiguousCache is to cache as items are requested. When + a view requests an item at row N it is also likely to ask for items at rows near + to N. + + \snippet examples/tools/contiguouscache/randomlistmodel.cpp 0 + + After getting the row the class determines if the row is in the bounds + of the contiguous cache's current range. It would have been equally valid to + simply have the following code instead. + + \code + while (row > m_words.lastIndex()) + m_words.append(fetchWord(m_words.lastIndex()+1); + while (row < m_words.firstIndex()) + m_words.prepend(fetchWord(m_words.firstIndex()-1); + \endcode + + However a list will often jump rows if the scroll bar is used directly, resulting in + the code above to cause every row between where the cache was last centered + to the requested row to be fetched before the requested row is fetched. + + Using QContiguousCache::lastIndex() and QContiguousCache::firstIndex() allows + the example to determine where in the list the cache is currently over. These values + don't represent the indexes into the cache own memory, but rather a virtual + infinite array that the cache represents. + + By using QContiguousCache::append() and QContiguousCache::prepend() the code ensures + that items that may be still on the screen are not lost when the requested row + has not moved far from the current cache range. QContiguousCache::insert() can + potentially remove more than one item from the cache as QContiguousCache does not + allow for gaps. If your cache needs to quickly jump back and forth between + rows with significant gaps between them consider using QCache instead. + + And thats it. A perfectly reasonable cache, using minimal memory for a very large + list. In this case the accessor for getting the words into cache: + + \snippet examples/tools/contiguouscache/randomlistmodel.cpp 1 + + Generates random information rather than fixed information. This allows you + to see how the cache range is kept for a local number of rows when running the + example. + + It is also worth considering pre-fetching items into the cache outside of the + applications paint routine. This can be done either with a separate thread + or using a QTimer to incrementally expand the range of the thread prior to + rows being requested out of the current cache range. +*/ diff --git a/doc/src/examples/offsetvector.qdoc b/doc/src/examples/offsetvector.qdoc deleted file mode 100644 index 256569e..0000000 --- a/doc/src/examples/offsetvector.qdoc +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -/*! - \example tools/offsetvector - \title Offset Vector Example - - The Offset Vector example shows how to use QOffsetVector to manage memory usage for - very large models. In some environments memory is limited, and even when it - isn't users still dislike an application using - excessive memory. Using QOffsetVector to manage a list rather than loading - the entire list into memory allows the application to limit the amount - of memory it uses regardless of the size of the data set it accesses - - The simplest way to use QOffsetVector is to cache as items are requested. When - a view requests an item at row N it is also likely to ask for items at rows near - to N. - - \snippet examples/tools/offsetvector/randomlistmodel.cpp 0 - - After getting the row the class determines if the row is in the bounds - of the offset vector's current range. It would have been equally valid to - simply have the following code instead. - - \code - while (row > m_words.lastIndex()) - m_words.append(fetchWord(m_words.lastIndex()+1); - while (row < m_words.firstIndex()) - m_words.prepend(fetchWord(m_words.firstIndex()-1); - \endcode - - However a list will often jump rows if the scroll bar is used directly, and - the above code would cause every row between where the cache was last centered - to where the cache is currently centered to be cached before the requested - row is reached. - - Using QOffsetVector::lastIndex() and QOffsetVector::firstIndex() allows - the example to determine where the list the vector is currently over. These values - don't represent the indexes into the vector own memory, but rather a virtual - infinite array that the vector represents. - - By using QOffsetVector::append() and QOffsetVector::prepend() the code ensures - that items that may be still on the screen are not lost when the requested row - has not moved far from the current vector range. QOffsetVector::insert() can - potentially remove more than one item from the cache as QOffsetVector does not - allow for gaps. If your cache needs to quickly jump back and forth between - rows with significant gaps between them consider using QCache instead. - - And thats it. A perfectly reasonable cache, using minimal memory for a very large - list. In this case the accessor for getting the words into cache: - - \snippet examples/tools/offsetvector/randomlistmodel.cpp 1 - - Generates random information rather than fixed information. This allows you - to see how the cache range is kept for a local number of rows when running the - example. - - It is also worth considering pre-fetching items into the cache outside of the - applications paint routine. This can be done either with a separate thread - or using a QTimer to incrementally expand the range of the thread prior to - rows being requested out of the current vector range. -*/ diff --git a/examples/tools/contiguouscache/contiguouscache.pro b/examples/tools/contiguouscache/contiguouscache.pro new file mode 100644 index 0000000..f840514 --- /dev/null +++ b/examples/tools/contiguouscache/contiguouscache.pro @@ -0,0 +1,9 @@ +HEADERS = randomlistmodel.h +SOURCES = randomlistmodel.cpp \ + main.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/tools/contiguouscache +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS contiguouscache.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/tools/contiguouscache +INSTALLS += target sources diff --git a/examples/tools/contiguouscache/main.cpp b/examples/tools/contiguouscache/main.cpp new file mode 100644 index 0000000..bdeb3f3 --- /dev/null +++ b/examples/tools/contiguouscache/main.cpp @@ -0,0 +1,15 @@ +#include "randomlistmodel.h" +#include +#include + +int main(int c, char **v) +{ + QApplication a(c, v); + + QListView view; + view.setUniformItemSizes(true); + view.setModel(new RandomListModel(&view)); + view.show(); + + return a.exec(); +} diff --git a/examples/tools/contiguouscache/randomlistmodel.cpp b/examples/tools/contiguouscache/randomlistmodel.cpp new file mode 100644 index 0000000..5c0953b --- /dev/null +++ b/examples/tools/contiguouscache/randomlistmodel.cpp @@ -0,0 +1,56 @@ +#include "randomlistmodel.h" + +static const int bufferSize(500); +static const int lookAhead(100); +static const int halfLookAhead(lookAhead/2); + +RandomListModel::RandomListModel(QObject *parent) +: QAbstractListModel(parent), m_rows(bufferSize), m_count(10000) +{ +} + +RandomListModel::~RandomListModel() +{ +} + +int RandomListModel::rowCount(const QModelIndex &) const +{ + return m_count; +} + +//! [0] +QVariant RandomListModel::data(const QModelIndex &index, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + int row = index.row(); + + if (row > m_rows.lastIndex()) { + if (row - m_rows.lastIndex() > lookAhead) + cacheRows(row-halfLookAhead, qMin(m_count, row+halfLookAhead)); + else while (row > m_rows.lastIndex()) + m_rows.append(fetchRow(m_rows.lastIndex()+1)); + } else if (row < m_rows.firstIndex()) { + if (m_rows.firstIndex() - row > lookAhead) + cacheRows(qMax(0, row-halfLookAhead), row+halfLookAhead); + else while (row < m_rows.firstIndex()) + m_rows.prepend(fetchRow(m_rows.firstIndex()-1)); + } + + return m_rows.at(row); +} + +void RandomListModel::cacheRows(int from, int to) const +{ + for (int i = from; i <= to; ++i) + m_rows.insert(i, fetchRow(i)); +} +//![0] + +//![1] +QString RandomListModel::fetchRow(int position) const +{ + return QString::number(rand() % ++position); +} +//![1] diff --git a/examples/tools/contiguouscache/randomlistmodel.h b/examples/tools/contiguouscache/randomlistmodel.h new file mode 100644 index 0000000..ad8cfad --- /dev/null +++ b/examples/tools/contiguouscache/randomlistmodel.h @@ -0,0 +1,26 @@ +#ifndef RANDOMLISTMODEL_H +#define RANDOMLISTMODEL_H + +#include +#include + +class QTimer; +class RandomListModel : public QAbstractListModel +{ + Q_OBJECT +public: + RandomListModel(QObject *parent = 0); + ~RandomListModel(); + + int rowCount(const QModelIndex & = QModelIndex()) const; + QVariant data(const QModelIndex &, int) const; + +private: + void cacheRows(int, int) const; + QString fetchRow(int) const; + + mutable QContiguousCache m_rows; + const int m_count; +}; + +#endif diff --git a/examples/tools/offsetvector/main.cpp b/examples/tools/offsetvector/main.cpp deleted file mode 100644 index bdeb3f3..0000000 --- a/examples/tools/offsetvector/main.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "randomlistmodel.h" -#include -#include - -int main(int c, char **v) -{ - QApplication a(c, v); - - QListView view; - view.setUniformItemSizes(true); - view.setModel(new RandomListModel(&view)); - view.show(); - - return a.exec(); -} diff --git a/examples/tools/offsetvector/offsetvector.pro b/examples/tools/offsetvector/offsetvector.pro deleted file mode 100644 index f329bb9..0000000 --- a/examples/tools/offsetvector/offsetvector.pro +++ /dev/null @@ -1,9 +0,0 @@ -HEADERS = randomlistmodel.h -SOURCES = randomlistmodel.cpp \ - main.cpp - -# install -target.path = $$[QT_INSTALL_EXAMPLES]/tools/offsetvector -sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS offsetvector.pro -sources.path = $$[QT_INSTALL_EXAMPLES]/tools/offsetvector -INSTALLS += target sources diff --git a/examples/tools/offsetvector/randomlistmodel.cpp b/examples/tools/offsetvector/randomlistmodel.cpp deleted file mode 100644 index 5c0953b..0000000 --- a/examples/tools/offsetvector/randomlistmodel.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include "randomlistmodel.h" - -static const int bufferSize(500); -static const int lookAhead(100); -static const int halfLookAhead(lookAhead/2); - -RandomListModel::RandomListModel(QObject *parent) -: QAbstractListModel(parent), m_rows(bufferSize), m_count(10000) -{ -} - -RandomListModel::~RandomListModel() -{ -} - -int RandomListModel::rowCount(const QModelIndex &) const -{ - return m_count; -} - -//! [0] -QVariant RandomListModel::data(const QModelIndex &index, int role) const -{ - if (role != Qt::DisplayRole) - return QVariant(); - - int row = index.row(); - - if (row > m_rows.lastIndex()) { - if (row - m_rows.lastIndex() > lookAhead) - cacheRows(row-halfLookAhead, qMin(m_count, row+halfLookAhead)); - else while (row > m_rows.lastIndex()) - m_rows.append(fetchRow(m_rows.lastIndex()+1)); - } else if (row < m_rows.firstIndex()) { - if (m_rows.firstIndex() - row > lookAhead) - cacheRows(qMax(0, row-halfLookAhead), row+halfLookAhead); - else while (row < m_rows.firstIndex()) - m_rows.prepend(fetchRow(m_rows.firstIndex()-1)); - } - - return m_rows.at(row); -} - -void RandomListModel::cacheRows(int from, int to) const -{ - for (int i = from; i <= to; ++i) - m_rows.insert(i, fetchRow(i)); -} -//![0] - -//![1] -QString RandomListModel::fetchRow(int position) const -{ - return QString::number(rand() % ++position); -} -//![1] diff --git a/examples/tools/offsetvector/randomlistmodel.h b/examples/tools/offsetvector/randomlistmodel.h deleted file mode 100644 index e102255..0000000 --- a/examples/tools/offsetvector/randomlistmodel.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef RANDOMLISTMODEL_H -#define RANDOMLISTMODEL_H - -#include -#include - -class QTimer; -class RandomListModel : public QAbstractListModel -{ - Q_OBJECT -public: - RandomListModel(QObject *parent = 0); - ~RandomListModel(); - - int rowCount(const QModelIndex & = QModelIndex()) const; - QVariant data(const QModelIndex &, int) const; - -private: - void cacheRows(int, int) const; - QString fetchRow(int) const; - - mutable QOffsetVector m_rows; - const int m_count; -}; - -#endif diff --git a/examples/tools/tools.pro b/examples/tools/tools.pro index 424f286..c694dd8 100644 --- a/examples/tools/tools.pro +++ b/examples/tools/tools.pro @@ -5,7 +5,7 @@ SUBDIRS = codecs \ customcompleter \ echoplugin \ i18n \ - offsetvector \ + contiguouscache \ plugandpaintplugins \ plugandpaint \ regexp \ diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp new file mode 100644 index 0000000..5046912 --- /dev/null +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -0,0 +1,359 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#include "qcontiguouscache.h" +#include + +void QContiguousCacheData::dump() const +{ + qDebug() << "capacity:" << alloc; + qDebug() << "count:" << count; + qDebug() << "start:" << start; + qDebug() << "offset:" << offset; +} + +/*! \class QContiguousCache + \brief The QContiguousCache class is a template class that provides a contiguous cache. + \ingroup tools + \ingroup shared + \reentrant + + The QContiguousCache class provides an efficient way of caching items for + display in a user interface view. Unlike QCache though it adds a restriction + that elements within the cache are contiguous. This has the advantage that + of matching how user interface views most commonly request data, as + a set of rows localized around the current scrolled position. It also + allows the cache to use less overhead than QCache both in terms of + performance and memory. + + The simplest way of using an contiguous cache is to use the append() + and prepend(). + +\code +MyRecord record(int row) const +{ + Q_ASSERT(row >= 0 && row < count()); + + while(row > cache.lastIndex()) + cache.append(slowFetchRecord(cache.lastIndex()+1)); + while(row < cache.firstIndex()) + cache.prepend(slowFetchRecord(cache.firstIndex()-1)); + + return cache.at(row); +} +\endcode + + If the cache is full then the item with the furthest index from where + the new item is appended or prepended is removed. + + This usage can be further optimized by using the insert() function + in the case where the requested row is a long way from the currently cached + items. If there is a is a gap between where the new item is inserted and the currently + cached items then the existing cached items are first removed to retain + the contiguous nature of the cache. Hence it is important to take some care then + when using insert() in order to avoid to unwanted clearing of the cache. + + See the The \l{Contiguous Cache Example}{Contiguous Cache} example. +*/ + +/*! \fn QContiguousCache::QContiguousCache(int capacity) + + Constructs a cache with the given \a capacity. + + \sa setCapacity() +*/ + +/*! \fn QContiguousCache::QContiguousCache(const QContiguousCache &other) + + Constructs a copy of \a other. + + This operation takes \l{constant time}, because QContiguousCache is + \l{implicitly shared}. This makes returning a QContiguousCache from a + function very fast. If a shared instance is modified, it will be + copied (copy-on-write), and that takes \l{linear time}. + + \sa operator=() +*/ + +/*! \fn QContiguousCache::~QContiguousCache() + Destroys the cache. +*/ + +/*! \fn void QContiguousCache::detach() + + \internal +*/ + +/*! \fn bool QContiguousCache::isDetached() const + + \internal +*/ + +/*! \fn void QContiguousCache::setSharable(bool sharable) + + \internal +*/ + + +/*! \fn QContiguousCache &QContiguousCache::operator=(const QContiguousCache &other) + + Assigns \a other to this cache and returns a reference to this cache. +*/ + +/*! \fn bool QContiguousCache::operator==(const QContiguousCache &other) const + + Returns true if \a other is equal to this cache; otherwise returns false. + + Two cache are considered equal if they contain the same values at the same + indexes. This function requires the value type to implement the \c operator==(). + + \sa operator!=() +*/ + +/*! \fn bool QContiguousCache::operator!=(const QContiguousCache &other) const + + Returns true if \a other is not equal to this cache; otherwise + returns false. + + Two cache are considered equal if they contain the same values at the same + indexes. This function requires the value type to implement the \c operator==(). + + \sa operator==() +*/ + +/*! \fn int QContiguousCache::capacity() const + + Returns the number of items the cache can store before it is full. + When a cache contains a number of items equal to its capacity, adding new + items will cause items furthest from the added item to be removed. + + \sa setCapacity(), size() +*/ + +/*! \fn int QContiguousCache::count() const + + \overload + + Same as size(). +*/ + +/*! \fn int QContiguousCache::size() const + + Returns the number of items contained within the cache. + + \sa capacity() +*/ + +/*! \fn bool QContiguousCache::isEmpty() const + + Returns true if no items are stored within the cache. + + \sa size(), capacity() +*/ + +/*! \fn bool QContiguousCache::isFull() const + + Returns true if the number of items stored within the cache is equal + to the capacity of the cache. + + \sa size(), capacity() +*/ + +/*! \fn int QContiguousCache::available() const + + Returns the number of items that can be added to the cache before it becomes full. + + \sa size(), capacity(), isFull() +*/ + +/*! \fn void QContiguousCache::clear() + + Removes all items from the cache. The capacity is unchanged. +*/ + +/*! \fn void QContiguousCache::setCapacity(int size) + + Sets the capacity of the cache to the given \a size. A cache can hold a + number of items equal to its capacity. When inserting, appending or prepending + items to the cache, if the cache is already full then the item furthest from + the added item will be removed. + + If the given \a size is smaller than the current count of items in the cache + then only the last \a size items from the cache will remain. + + \sa capacity(), isFull() +*/ + +/*! \fn const T &QContiguousCache::at(int i) const + + Returns the item at index position \a i in the cache. \a i must + be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()). + + The indexes in the cache refer to number of positions the item is from the + first item appended into the cache. That is to say a cache with a capacity of + 100, that has had 150 items appended will have a valid index range of + 50 to 149. This allows inserting an retrieving items into the cache based + on a theoretical infinite list + + \sa firstIndex(), lastIndex(), insert(), operator[]() +*/ + +/*! \fn T &QContiguousCache::operator[](int i) + + Returns the item at index position \a i as a modifiable reference. If + the cache does not contain an item at the given index position \a i + then it will first insert an empty item at that position. + + In most cases it is better to use either at() or insert(). + + Note that using non-const operators can cause QContiguousCache to do a deep + copy. + + \sa insert(), at() +*/ + +/*! \fn const T &QContiguousCache::operator[](int i) const + + \overload + + Same as at(\a i). +*/ + +/*! \fn void QContiguousCache::append(const T &value) + + Inserts \a value at the end of the cache. If the cache is already full + the item at the start of the cache will be removed. + + \sa prepend(), insert(), isFull() +*/ + +/*! \fn void QContiguousCache::prepend(const T &value) + + Inserts \a value at the start of the cache. If the cache is already full + the item at the end of the cache will be removed. + + \sa append(), insert(), isFull() +*/ + +/*! \fn void QContiguousCache::insert(int i, const T &value) + + Inserts the \a value at the index position \a i. If the cache already contains + an item at \a i then that value is replaced. If \a i is either one more than + lastIndex() or one less than firstIndex() it is the equivalent to an append() + or a prepend(). + + If the given index \a i is not within the current range of the cache nor adjacent + to the bounds of the cache's index range the cache is first cleared before + inserting the item. At this point the cache will have a size of 1. It is worth + while then taking effort to insert items in an order that starts adjacent to the + current index range for the cache. + + \sa prepend(), append(), isFull(), firstIndex(), lastIndex() +*/ + +/*! \fn bool QContiguousCache::containsIndex(int i) const + + Returns true if the cache's index range includes the given index \a i. + + \sa firstIndex(), lastIndex() +*/ + +/*! \fn int QContiguousCache::firstIndex() const + Returns the first valid index in the cache. The index will be invalid if the + cache is empty. However the following code is valid even when the cache is empty: + + \code + for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) + qDebug() << "Item" << i << "of the cache is" << cache.at(i); + \endcode + + \sa capacity(), size(), lastIndex() +*/ + +/*! \fn int QContiguousCache::lastIndex() const + + Returns the last valid index in the cache. If the cache is empty will return -1. + + \code + for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) + qDebug() << "Item" << i << "of the cache is" << cache.at(i); + \endcode + + \sa capacity(), size(), firstIndex() +*/ + + +/*! \fn T &QContiguousCache::first() + + Returns a reference to the first item in the cache. This function + assumes that the cache isn't empty. + + \sa last(), isEmpty() +*/ + +/*! \fn T &QContiguousCache::last() + + Returns a reference to the last item in the cache. This function + assumes that the cache isn't empty. + + \sa first(), isEmpty() +*/ + +/*! \fn const T& QContiguousCache::first() const + + \overload +*/ + +/*! \fn const T& QContiguousCache::last() const + + \overload +*/ + +/*! \fn void QContiguousCache::removeFirst() + + Removes the first item from the cache. This function assumes that + the cache isn't empty. + + \sa removeLast() +*/ + +/*! \fn void QContiguousCache::removeLast() + + Removes the last item from the cache. This function assumes that + the cache isn't empty. + + \sa removeFirst() +*/ + +/*! \fn T QContiguousCache::takeFirst() + + Removes the first item in the cache and returns it. + + If you don't sue the return value, removeFirst() is more efficient. + + \sa takeLast(), removeFirst() +*/ + +/*! \fn T QContiguousCache::takeLast() + + Removes the last item in the cache and returns it. + + If you don't sue the return value, removeLast() is more efficient. + + \sa takeFirst(), removeLast() +*/ + +/*! \fn void QContiguousCache::dump() const + + \internal + + Sends information about the cache's internal structure to qDebug() +*/ diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h new file mode 100644 index 0000000..03012a2 --- /dev/null +++ b/src/corelib/tools/qcontiguouscache.h @@ -0,0 +1,386 @@ +/**************************************************************************** +** +** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $TROLLTECH_DUAL_LICENSE$ +** +****************************************************************************/ + +#ifndef QCONTIGUOUSCACHE_H +#define QCONTIGUOUSCACHE_H + +#include + +struct QContiguousCacheData +{ + QBasicAtomicInt ref; + int alloc; + int count; + int start; + int offset; + uint sharable : 1; + + void dump() const; +}; + +template +struct QContiguousCacheTypedData +{ + QBasicAtomicInt ref; + int alloc; + int count; + int start; + int offset; + uint sharable : 1; + + T array[1]; +}; + +class QContiguousCacheDevice; + +template +class QContiguousCache { + typedef QContiguousCacheTypedData Data; + union { QContiguousCacheData *p; QContiguousCacheTypedData *d; }; +public: + explicit QContiguousCache(int capacity = 0); + QContiguousCache(const QContiguousCache &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } + + inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(d); } + + inline void detach() { if (d->ref != 1) detach_helper(); } + inline bool isDetached() const { return d->ref == 1; } + inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } + + QContiguousCache &operator=(const QContiguousCache &other); + bool operator==(const QContiguousCache &other) const; + inline bool operator!=(const QContiguousCache &other) const { return !(*this == other); } + + inline int capacity() const {return d->alloc; } + inline int count() const { return d->count; } + inline int size() const { return d->count; } + + inline bool isEmpty() const { return d->count == 0; } + inline bool isFull() const { return d->count == d->alloc; } + inline int available() const { return d->alloc - d->count; } + + void clear(); + void setCapacity(int size); + + const T &at(int pos) const; + T &operator[](int i); + const T &operator[](int i) const; + + void append(const T &value); + void prepend(const T &value); + void insert(int pos, const T &value); + + inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; } + inline int firstIndex() const { return d->offset; } + inline int lastIndex() const { return d->offset + d->count - 1; } + + inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; } + inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; } + inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; } + inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; } + + void removeFirst(); + T takeFirst(); + void removeLast(); + T takeLast(); + + // debug + void dump() const { p->dump(); } +private: + void detach_helper(); + + QContiguousCacheData *malloc(int alloc); + void free(Data *d); + int sizeOfTypedData() { + // this is more or less the same as sizeof(Data), except that it doesn't + // count the padding at the end + return reinterpret_cast(&(reinterpret_cast(this))->array[1]) - reinterpret_cast(this); + } +}; + +template +void QContiguousCache::detach_helper() +{ + union { QContiguousCacheData *p; QContiguousCacheTypedData *d; } x; + + x.p = malloc(d->alloc); + x.d->ref = 1; + x.d->count = d->count; + x.d->start = d->start; + x.d->offset = d->offset; + x.d->alloc = d->alloc; + x.d->sharable = true; + + T *dest = x.d->array + x.d->start; + T *src = d->array + d->start; + int count = x.d->count; + while (count--) { + if (QTypeInfo::isComplex) { + new (dest) T(*src); + } else { + *dest = *src; + } + dest++; + if (dest == x.d->array + x.d->alloc) + dest = x.d->array; + src++; + if (src == d->array + d->alloc) + src = d->array; + } + + if (!d->ref.deref()) + free(d); + d = x.d; +} + +template +void QContiguousCache::setCapacity(int asize) +{ + if (asize == d->alloc) + return; + detach(); + union { QContiguousCacheData *p; QContiguousCacheTypedData *d; } x; + x.p = malloc(asize); + x.d->alloc = asize; + x.d->count = qMin(d->count, asize); + x.d->offset = d->offset + d->count - x.d->count; + x.d->start = x.d->offset % x.d->alloc; + /* deep copy - + slow way now, get unit test working, then + improve performance if need be. (e.g. memcpy) + */ + T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc; + T *src = d->array + (d->start + d->count-1) % d->alloc; + int count = x.d->count; + while (count--) { + if (QTypeInfo::isComplex) { + new (dest) T(*src); + } else { + *dest = *src; + } + if (dest == x.d->array) + dest = x.d->array + x.d->alloc; + dest--; + if (src == d->array) + src = d->array + d->alloc; + src--; + } + /* free old */ + free(d); + d = x.d; +} + +template +void QContiguousCache::clear() +{ + if (d->ref == 1) { + if (QTypeInfo::isComplex) { + int count = d->count; + T * i = d->array + d->start; + T * e = d->array + d->alloc; + while (count--) { + i->~T(); + i++; + if (i == e) + i = d->array; + } + } + d->count = d->start = d->offset = 0; + } else { + union { QContiguousCacheData *p; QContiguousCacheTypedData *d; } x; + x.p = malloc(d->alloc); + x.d->ref = 1; + x.d->alloc = d->alloc; + x.d->count = x.d->start = x.d->offset = 0; + x.d->sharable = true; + if (!d->ref.deref()) free(d); + d = x.d; + } +} + +template +inline QContiguousCacheData *QContiguousCache::malloc(int aalloc) +{ + return static_cast(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T))); +} + +template +QContiguousCache::QContiguousCache(int asize) +{ + p = malloc(asize); + d->ref = 1; + d->alloc = asize; + d->count = d->start = d->offset = 0; + d->sharable = true; +} + +template +QContiguousCache &QContiguousCache::operator=(const QContiguousCache &other) +{ + other.d->ref.ref(); + if (!d->ref.deref()) + free(d); + d = other.d; + if (!d->sharable) + detach_helper(); + return *this; +} + +template +bool QContiguousCache::operator==(const QContiguousCache &other) const +{ + if (other.d == d) + return true; + if (other.d->start != d->start + || other.d->count != d->count + || other.d->offset != d->offset + || other.d->alloc != d->alloc) + return false; + for (int i = firstIndex(); i <= lastIndex(); ++i) + if (!(at(i) == other.at(i))) + return false; + return true; +} + +template +void QContiguousCache::free(Data *x) +{ + if (QTypeInfo::isComplex) { + int count = d->count; + T * i = d->array + d->start; + T * e = d->array + d->alloc; + while (count--) { + i->~T(); + i++; + if (i == e) + i = d->array; + } + } + qFree(x); +} + +template +void QContiguousCache::append(const T &value) +{ + detach(); + if (QTypeInfo::isComplex) { + if (d->count == d->alloc) + (d->array + (d->start+d->count) % d->alloc)->~T(); + new (d->array + (d->start+d->count) % d->alloc) T(value); + } else { + d->array[(d->start+d->count) % d->alloc] = value; + } + + if (d->count == d->alloc) { + d->start++; + d->start %= d->alloc; + d->offset++; + } else { + d->count++; + } +} + +template +void QContiguousCache::prepend(const T &value) +{ + detach(); + if (d->start) + d->start--; + else + d->start = d->alloc-1; + d->offset--; + + if (d->count != d->alloc) + d->count++; + else + if (d->count == d->alloc) + (d->array + d->start)->~T(); + + if (QTypeInfo::isComplex) + new (d->array + d->start) T(value); + else + d->array[d->start] = value; +} + +template +void QContiguousCache::insert(int pos, const T &value) +{ + detach(); + if (containsIndex(pos)) { + if(QTypeInfo::isComplex) + new (d->array + pos % d->alloc) T(value); + else + d->array[pos % d->alloc] = value; + } else if (pos == d->offset-1) + prepend(value); + else if (pos == d->offset+d->count) + append(value); + else { + // we don't leave gaps. + clear(); + d->offset = d->start = pos; + d->start %= d->alloc; + d->count = 1; + if (QTypeInfo::isComplex) + new (d->array + d->start) T(value); + else + d->array[d->start] = value; + } +} + +template +inline const T &QContiguousCache::at(int pos) const +{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache::at", "index out of range"); return d->array[pos % d->alloc]; } +template +inline const T &QContiguousCache::operator[](int pos) const +{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache::at", "index out of range"); return d->array[pos % d->alloc]; } +template + +// can use the non-inline one to modify the index range. +inline T &QContiguousCache::operator[](int pos) +{ + detach(); + if (!containsIndex(pos)) + insert(pos, T()); + return d->array[pos % d->alloc]; +} + +template +inline void QContiguousCache::removeFirst() +{ + Q_ASSERT(d->count > 0); + detach(); + d->count--; + if (QTypeInfo::isComplex) + (d->array + d->start)->~T(); + d->start = (d->start + 1) % d->alloc; + d->offset++; +} + +template +inline void QContiguousCache::removeLast() +{ + Q_ASSERT(d->count > 0); + detach(); + d->count--; + if (QTypeInfo::isComplex) + (d->array + (d->start + d->count) % d->alloc)->~T(); +} + +template +inline T QContiguousCache::takeFirst() +{ T t = first(); removeFirst(); return t; } + +template +inline T QContiguousCache::takeLast() +{ T t = last(); removeLast(); return t; } + +#endif diff --git a/src/corelib/tools/qoffsetvector.cpp b/src/corelib/tools/qoffsetvector.cpp deleted file mode 100644 index 32d2872..0000000 --- a/src/corelib/tools/qoffsetvector.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#include "qoffsetvector.h" -#include - -void QOffsetVectorData::dump() const -{ - qDebug() << "capacity:" << alloc; - qDebug() << "count:" << count; - qDebug() << "start:" << start; - qDebug() << "offset:" << offset; -} - -/*! \class QOffsetVector - \brief The QOffsetVector class is a template class that provides a offset vector. - \ingroup tools - \ingroup shared - \reentrant - - The QOffsetVector class provides an efficient way of caching items for - display in a user interface view. It does this by providing a window - into a theoretical infinite sized vector. This has the advantage that - it matches how user interface views most commonly request the data, in - a set of rows localized around the current scrolled position. It also - allows the cache to use less overhead than QCache both in terms of - performance and memory. In turn, unlike a QCache, the key has to be - an int and has to be contiguous. That is to say if an item is inserted - at index 85, then if there were no previous items at 84 or 86 then the - cache will be cleared before the new item at 85 is inserted. If this - restriction is not suitable consider using QCache instead. - - The simplest way of using an offset vector is to use the append() - and prepend() functions to slide the window to where it is needed. - -\code -MyRecord record(int row) const -{ - Q_ASSERT(row >= 0 && row < count()); - - while(row > cache.lastIndex()) - cache.append(slowFetchRecord(cache.lastIndex()+1)); - while(row < cache.firstIndex()) - cache.prepend(slowFetchRecord(cache.firstIndex()-1)); - - return cache.at(row); -} -\endcode - - The append() and prepend() functions cause the vector window to move to - where the current row is requested from. This usage can be further - optimized by using the insert() function to reset the vector window to - a row in the case where the row is a long way from the current row. It - may also be worth while to fetch multiple records into the cache if - it is faster to retrieve them in a batch operation. - - See the The \l{Offset Vector Example}{Offset Vector} example. -*/ - -/*! \fn QOffsetVector::QOffsetVector(int capacity) - - Constructs a vector with the given \a capacity. - - \sa setCapacity() -*/ - -/*! \fn QOffsetVector::QOffsetVector(const QOffsetVector &other) - - Constructs a copy of \a other. - - This operation takes \l{constant time}, because QOffsetVector is - \l{implicitly shared}. This makes returning a QOffsetVector from a - function very fast. If a shared instance is modified, it will be - copied (copy-on-write), and that takes \l{linear time}. - - \sa operator=() -*/ - -/*! \fn QOffsetVector::~QOffsetVector() - Destorys the vector. -*/ - -/*! \fn void QOffsetVector::detach() - - \internal -*/ - -/*! \fn bool QOffsetVector::isDetached() const - - \internal -*/ - -/*! \fn void QOffsetVector::setSharable(bool sharable) - - \internal -*/ - - -/*! \fn QOffsetVector &QOffsetVector::operator=(const QOffsetVector &other) - - Assigns \a other to this vector and returns a reference to this vector. -*/ - -/*! \fn bool QOffsetVector::operator==(const QOffsetVector &other) const - - Returns true if \a other is equal to this vector; otherwise returns false. - - Two vectors are considered equal if they contain the same values at the same - indexes. This function requires the value type to implement the \c operator==(). - - \sa operator!=() -*/ - -/*! \fn bool QOffsetVector::operator!=(const QOffsetVector &other) const - - Returns true if \a other is not equal to this vector; otherwise - returns false. - - Two vector are considered equal if they contain the same values at the same - indexes. This function requires the value type to implement the \c operator==(). - - \sa operator==() -*/ - -/*! \fn int QOffsetVector::capacity() const - - Returns the number of items the vector can store before it is full. - When a vector contains a number of items equal to its capacity, adding new - items will cause items furthest from the added item to be removed. - - \sa setCapacity(), size() -*/ - -/*! \fn int QOffsetVector::count() const - - \overload - - Same as size(). -*/ - -/*! \fn int QOffsetVector::size() const - - Returns the number of items contained within the vector. - - \sa capacity() -*/ - -/*! \fn bool QOffsetVector::isEmpty() const - - Returns true if no items are stored within the vector. - - \sa size(), capacity() -*/ - -/*! \fn bool QOffsetVector::isFull() const - - Returns true if the number of items stored within the vector is equal - to the capacity of the vector. - - \sa size(), capacity() -*/ - -/*! \fn int QOffsetVector::available() const - - Returns the number of items that can be added to the vector before it becomes full. - - \sa size(), capacity(), isFull() -*/ - -/*! \fn void QOffsetVector::clear() - - Removes all items from the vector. The capacity is unchanged. -*/ - -/*! \fn void QOffsetVector::setCapacity(int size) - - Sets the capacity of the vector to the given \a size. A vector can hold a - number of items equal to its capacity. When inserting, appending or prepending - items to the vector, if the vector is already full then the item furthest from - the added item will be removed. - - If the given \a size is smaller than the current count of items in the vector - then only the last \a size items from the vector will remain. - - \sa capacity(), isFull() -*/ - -/*! \fn const T &QOffsetVector::at(int i) const - - Returns the item at index position \a i in the vector. \a i must - be a valid index position in the vector (i.e, firstIndex() <= \a i <= lastIndex()). - - The indexes in the vector refer to number of positions the item is from the - first item appended into the vector. That is to say a vector with a capacity of - 100, that has had 150 items appended will have a valid index range of - 50 to 149. This allows inserting an retrieving items into the vector based - on a theoretical infinite list - - \sa firstIndex(), lastIndex(), insert(), operator[]() -*/ - -/*! \fn T &QOffsetVector::operator[](int i) - - Returns the item at index position \a i as a modifiable reference. If - the vector does not contain an item at the given index position \a i - then it will first insert an empty item at that position. - - In most cases it is better to use either at() or insert(). - - Note that using non-const operators can cause QOffsetVector to do a deep - copy. - - \sa insert(), at() -*/ - -/*! \fn const T &QOffsetVector::operator[](int i) const - - \overload - - Same as at(\a i). -*/ - -/*! \fn void QOffsetVector::append(const T &value) - - Inserts \a value at the end of the vector. If the vector is already full - the item at the start of the vector will be removed. - - \sa prepend(), insert(), isFull() -*/ - -/*! \fn void QOffsetVector::prepend(const T &value) - - Inserts \a value at the start of the vector. If the vector is already full - the item at the end of the vector will be removed. - - \sa append(), insert(), isFull() -*/ - -/*! \fn void QOffsetVector::insert(int i, const T &value) - - Inserts the \a value at the index position \a i. If the vector already contains - an item at \a i then that value is replaced. If \a i is either one more than - lastIndex() or one less than firstIndex() it is the equivalent to an append() - or a prepend(). - - If the given index \a i is not within the current range of the vector nor adjacent - to the bounds of the vector's index range the vector is first cleared before - inserting the item. At this point the vector will have a size of 1. It is worth - while then taking effort to insert items in an order than starts adjacent to the - current index range for the vector. - - \sa prepend(), append(), isFull(), firstIndex(), lastIndex() -*/ - -/*! \fn bool QOffsetVector::containsIndex(int i) const - - Returns true if the vector's index range includes the given index \a i. - - \sa firstIndex(), lastIndex() -*/ - -/*! \fn int QOffsetVector::firstIndex() const - Returns the first valid index in the vector. The index will be invalid if the - vector is empty. However the following code is valid even when the vector is empty: - - \code - for (int i = vector.firstIndex(); i <= vector.lastIndex(); ++i) - qDebug() << "Item" << i << "of the vector is" << vector.at(i); - \endcode - - \sa capacity(), size(), lastIndex() -*/ - -/*! \fn int QOffsetVector::lastIndex() const - - Returns the last valid index in the vector. If the vector is empty will return -1. - - \code - for (int i = vector.firstIndex(); i <= vector.lastIndex(); ++i) - qDebug() << "Item" << i << "of the vector is" << vector.at(i); - \endcode - - \sa capacity(), size(), firstIndex() -*/ - - -/*! \fn T &QOffsetVector::first() - - Returns a reference to the first item in the vector. This function - assumes that the vector isn't empty. - - \sa last(), isEmpty() -*/ - -/*! \fn T &QOffsetVector::last() - - Returns a reference to the last item in the vector. This function - assumes that the vector isn't empty. - - \sa first(), isEmpty() -*/ - -/*! \fn const T& QOffsetVector::first() const - - \overload -*/ - -/*! \fn const T& QOffsetVector::last() const - - \overload -*/ - -/*! \fn void QOffsetVector::removeFirst() - - Removes the first item from the vector. This function assumes that - the vector isn't empty. - - \sa removeLast() -*/ - -/*! \fn void QOffsetVector::removeLast() - - Removes the last item from the vector. This function assumes that - the vector isn't empty. - - \sa removeFirst() -*/ - -/*! \fn T QOffsetVector::takeFirst() - - Removes the first item in the vector and returns it. - - If you don't sue the return value, removeFirst() is more efficient. - - \sa takeLast(), removeFirst() -*/ - -/*! \fn T QOffsetVector::takeLast() - - Removes the last item in the vector and returns it. - - If you don't sue the return value, removeLast() is more efficient. - - \sa takeFirst(), removeLast() -*/ - -/*! \fn void QOffsetVector::dump() const - - \internal - - Sends information about the vector's internal structure to qDebug() -*/ diff --git a/src/corelib/tools/qoffsetvector.h b/src/corelib/tools/qoffsetvector.h deleted file mode 100644 index 7030862..0000000 --- a/src/corelib/tools/qoffsetvector.h +++ /dev/null @@ -1,386 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $TROLLTECH_DUAL_LICENSE$ -** -****************************************************************************/ - -#ifndef QCIRCULARBUFFER_H -#define QCIRCULARBUFFER_H - -#include - -struct QOffsetVectorData -{ - QBasicAtomicInt ref; - int alloc; - int count; - int start; - int offset; - uint sharable : 1; - - void dump() const; -}; - -template -struct QOffsetVectorTypedData -{ - QBasicAtomicInt ref; - int alloc; - int count; - int start; - int offset; - uint sharable : 1; - - T array[1]; -}; - -class QOffsetVectorDevice; - -template -class QOffsetVector { - typedef QOffsetVectorTypedData Data; - union { QOffsetVectorData *p; QOffsetVectorTypedData *d; }; -public: - explicit QOffsetVector(int capacity = 0); - QOffsetVector(const QOffsetVector &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); } - - inline ~QOffsetVector() { if (!d) return; if (!d->ref.deref()) free(d); } - - inline void detach() { if (d->ref != 1) detach_helper(); } - inline bool isDetached() const { return d->ref == 1; } - inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; } - - QOffsetVector &operator=(const QOffsetVector &other); - bool operator==(const QOffsetVector &other) const; - inline bool operator!=(const QOffsetVector &other) const { return !(*this == other); } - - inline int capacity() const {return d->alloc; } - inline int count() const { return d->count; } - inline int size() const { return d->count; } - - inline bool isEmpty() const { return d->count == 0; } - inline bool isFull() const { return d->count == d->alloc; } - inline int available() const { return d->alloc - d->count; } - - void clear(); - void setCapacity(int size); - - const T &at(int pos) const; - T &operator[](int i); - const T &operator[](int i) const; - - void append(const T &value); - void prepend(const T &value); - void insert(int pos, const T &value); - - inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; } - inline int firstIndex() const { return d->offset; } - inline int lastIndex() const { return d->offset + d->count - 1; } - - inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; } - inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; } - inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; } - inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; } - - void removeFirst(); - T takeFirst(); - void removeLast(); - T takeLast(); - - // debug - void dump() const { p->dump(); } -private: - void detach_helper(); - - QOffsetVectorData *malloc(int alloc); - void free(Data *d); - int sizeOfTypedData() { - // this is more or less the same as sizeof(Data), except that it doesn't - // count the padding at the end - return reinterpret_cast(&(reinterpret_cast(this))->array[1]) - reinterpret_cast(this); - } -}; - -template -void QOffsetVector::detach_helper() -{ - union { QOffsetVectorData *p; QOffsetVectorTypedData *d; } x; - - x.p = malloc(d->alloc); - x.d->ref = 1; - x.d->count = d->count; - x.d->start = d->start; - x.d->offset = d->offset; - x.d->alloc = d->alloc; - x.d->sharable = true; - - T *dest = x.d->array + x.d->start; - T *src = d->array + d->start; - int count = x.d->count; - while (count--) { - if (QTypeInfo::isComplex) { - new (dest) T(*src); - } else { - *dest = *src; - } - dest++; - if (dest == x.d->array + x.d->alloc) - dest = x.d->array; - src++; - if (src == d->array + d->alloc) - src = d->array; - } - - if (!d->ref.deref()) - free(d); - d = x.d; -} - -template -void QOffsetVector::setCapacity(int asize) -{ - if (asize == d->alloc) - return; - detach(); - union { QOffsetVectorData *p; QOffsetVectorTypedData *d; } x; - x.p = malloc(asize); - x.d->alloc = asize; - x.d->count = qMin(d->count, asize); - x.d->offset = d->offset + d->count - x.d->count; - x.d->start = x.d->offset % x.d->alloc; - /* deep copy - - slow way now, get unit test working, then - improve performance if need be. (e.g. memcpy) - */ - T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc; - T *src = d->array + (d->start + d->count-1) % d->alloc; - int count = x.d->count; - while (count--) { - if (QTypeInfo::isComplex) { - new (dest) T(*src); - } else { - *dest = *src; - } - if (dest == x.d->array) - dest = x.d->array + x.d->alloc; - dest--; - if (src == d->array) - src = d->array + d->alloc; - src--; - } - /* free old */ - free(d); - d = x.d; -} - -template -void QOffsetVector::clear() -{ - if (d->ref == 1) { - if (QTypeInfo::isComplex) { - int count = d->count; - T * i = d->array + d->start; - T * e = d->array + d->alloc; - while (count--) { - i->~T(); - i++; - if (i == e) - i = d->array; - } - } - d->count = d->start = d->offset = 0; - } else { - union { QOffsetVectorData *p; QOffsetVectorTypedData *d; } x; - x.p = malloc(d->alloc); - x.d->ref = 1; - x.d->alloc = d->alloc; - x.d->count = x.d->start = x.d->offset = 0; - x.d->sharable = true; - if (!d->ref.deref()) free(d); - d = x.d; - } -} - -template -inline QOffsetVectorData *QOffsetVector::malloc(int aalloc) -{ - return static_cast(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T))); -} - -template -QOffsetVector::QOffsetVector(int asize) -{ - p = malloc(asize); - d->ref = 1; - d->alloc = asize; - d->count = d->start = d->offset = 0; - d->sharable = true; -} - -template -QOffsetVector &QOffsetVector::operator=(const QOffsetVector &other) -{ - other.d->ref.ref(); - if (!d->ref.deref()) - free(d); - d = other.d; - if (!d->sharable) - detach_helper(); - return *this; -} - -template -bool QOffsetVector::operator==(const QOffsetVector &other) const -{ - if (other.d == d) - return true; - if (other.d->start != d->start - || other.d->count != d->count - || other.d->offset != d->offset - || other.d->alloc != d->alloc) - return false; - for (int i = firstIndex(); i <= lastIndex(); ++i) - if (!(at(i) == other.at(i))) - return false; - return true; -} - -template -void QOffsetVector::free(Data *x) -{ - if (QTypeInfo::isComplex) { - int count = d->count; - T * i = d->array + d->start; - T * e = d->array + d->alloc; - while (count--) { - i->~T(); - i++; - if (i == e) - i = d->array; - } - } - qFree(x); -} - -template -void QOffsetVector::append(const T &value) -{ - detach(); - if (QTypeInfo::isComplex) { - if (d->count == d->alloc) - (d->array + (d->start+d->count) % d->alloc)->~T(); - new (d->array + (d->start+d->count) % d->alloc) T(value); - } else { - d->array[(d->start+d->count) % d->alloc] = value; - } - - if (d->count == d->alloc) { - d->start++; - d->start %= d->alloc; - d->offset++; - } else { - d->count++; - } -} - -template -void QOffsetVector::prepend(const T &value) -{ - detach(); - if (d->start) - d->start--; - else - d->start = d->alloc-1; - d->offset--; - - if (d->count != d->alloc) - d->count++; - else - if (d->count == d->alloc) - (d->array + d->start)->~T(); - - if (QTypeInfo::isComplex) - new (d->array + d->start) T(value); - else - d->array[d->start] = value; -} - -template -void QOffsetVector::insert(int pos, const T &value) -{ - detach(); - if (containsIndex(pos)) { - if(QTypeInfo::isComplex) - new (d->array + pos % d->alloc) T(value); - else - d->array[pos % d->alloc] = value; - } else if (pos == d->offset-1) - prepend(value); - else if (pos == d->offset+d->count) - append(value); - else { - // we don't leave gaps. - clear(); - d->offset = d->start = pos; - d->start %= d->alloc; - d->count = 1; - if (QTypeInfo::isComplex) - new (d->array + d->start) T(value); - else - d->array[d->start] = value; - } -} - -template -inline const T &QOffsetVector::at(int pos) const -{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QOffsetVector::at", "index out of range"); return d->array[pos % d->alloc]; } -template -inline const T &QOffsetVector::operator[](int pos) const -{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QOffsetVector::at", "index out of range"); return d->array[pos % d->alloc]; } -template - -// can use the non-inline one to modify the index range. -inline T &QOffsetVector::operator[](int pos) -{ - detach(); - if (!containsIndex(pos)) - insert(pos, T()); - return d->array[pos % d->alloc]; -} - -template -inline void QOffsetVector::removeFirst() -{ - Q_ASSERT(d->count > 0); - detach(); - d->count--; - if (QTypeInfo::isComplex) - (d->array + d->start)->~T(); - d->start = (d->start + 1) % d->alloc; - d->offset++; -} - -template -inline void QOffsetVector::removeLast() -{ - Q_ASSERT(d->count > 0); - detach(); - d->count--; - if (QTypeInfo::isComplex) - (d->array + (d->start + d->count) % d->alloc)->~T(); -} - -template -inline T QOffsetVector::takeFirst() -{ T t = first(); removeFirst(); return t; } - -template -inline T QOffsetVector::takeLast() -{ T t = last(); removeLast(); return t; } - -#endif diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index 626c9e5..aaf3f21 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -19,7 +19,7 @@ HEADERS += \ tools/qlocale_p.h \ tools/qlocale_data_p.h \ tools/qmap.h \ - tools/qoffsetvector.h \ + tools/qcontiguouscache.h \ tools/qpodlist_p.h \ tools/qpoint.h \ tools/qqueue.h \ @@ -54,7 +54,7 @@ SOURCES += \ tools/qlocale.cpp \ tools/qpoint.cpp \ tools/qmap.cpp \ - tools/qoffsetvector.cpp \ + tools/qcontiguouscache.cpp \ tools/qrect.cpp \ tools/qregexp.cpp \ tools/qshareddata.cpp \ diff --git a/tests/auto/qcontiguouscache/qcontiguouscache.pro b/tests/auto/qcontiguouscache/qcontiguouscache.pro new file mode 100644 index 0000000..618efed --- /dev/null +++ b/tests/auto/qcontiguouscache/qcontiguouscache.pro @@ -0,0 +1,8 @@ +load(qttest_p4) + +QT = core + +SOURCES += tst_qcontiguouscache.cpp + + + diff --git a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp new file mode 100644 index 0000000..493032a --- /dev/null +++ b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp @@ -0,0 +1,361 @@ +/**************************************************************************** +** +** This file is part of the $PACKAGE_NAME$. +** +** Copyright (C) $THISYEAR$ $COMPANY_NAME$. +** +** $QT_EXTENDED_DUAL_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +#if defined(FORCE_UREF) +template +inline QDebug &operator<<(QDebug debug, const QContiguousCache &contiguousCache) +#else +template +inline QDebug operator<<(QDebug debug, const QContiguousCache &contiguousCache) +#endif +{ + debug.nospace() << "QContiguousCache("; + for (int i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) { + debug << contiguousCache[i]; + if (i != contiguousCache.lastIndex()) + debug << ", "; + } + debug << ")"; + return debug.space(); +} + +#if defined(NO_BENCHMARK) and defined(QBENCHMARK) +#undef QBENCHMARK +#define QBENCHMARK +#endif + +class tst_QContiguousCache : public QObject +{ + Q_OBJECT +public: + tst_QContiguousCache() {} + virtual ~tst_QContiguousCache() {} +private slots: + void empty(); + void forwardBuffer(); + void scrollingList(); + + void complexType(); + + void operatorAt(); + + void cacheBenchmark(); + void contiguousCacheBenchmark(); + + void setCapacity(); +}; + +QTEST_MAIN(tst_QContiguousCache) + +void tst_QContiguousCache::empty() +{ + QContiguousCache c(10); + QCOMPARE(c.capacity(), 10); + QCOMPARE(c.count(), 0); + QVERIFY(c.isEmpty()); + c.append(1); + QVERIFY(!c.isEmpty()); + c.clear(); + QCOMPARE(c.capacity(), 10); + QCOMPARE(c.count(), 0); + QVERIFY(c.isEmpty()); + c.prepend(1); + QVERIFY(!c.isEmpty()); + c.clear(); + QCOMPARE(c.count(), 0); + QVERIFY(c.isEmpty()); + QCOMPARE(c.capacity(), 10); +} + +void tst_QContiguousCache::forwardBuffer() +{ + int i; + QContiguousCache c(10); + for(i = 1; i < 30; ++i) { + c.append(i); + QCOMPARE(c.first(), qMax(1, i-9)); + QCOMPARE(c.last(), i); + QCOMPARE(c.count(), qMin(i, 10)); + } + + c.clear(); + + for(i = 1; i < 30; ++i) { + c.prepend(i); + QCOMPARE(c.last(), qMax(1, i-9)); + QCOMPARE(c.first(), i); + QCOMPARE(c.count(), qMin(i, 10)); + } +} + +void tst_QContiguousCache::scrollingList() +{ + int i; + QContiguousCache c(10); + + // Once allocated QContiguousCache should not + // allocate any additional memory for non + // complex data types. + QBENCHMARK { + // simulate scrolling in a list of items; + for(i = 0; i < 10; ++i) + c.append(i); + + QCOMPARE(c.firstIndex(), 0); + QCOMPARE(c.lastIndex(), 9); + QVERIFY(c.containsIndex(0)); + QVERIFY(c.containsIndex(9)); + QVERIFY(!c.containsIndex(10)); + + for (i = 0; i < 10; ++i) + QCOMPARE(c.at(i), i); + + for (i = 10; i < 30; ++i) + c.append(i); + + QCOMPARE(c.firstIndex(), 20); + QCOMPARE(c.lastIndex(), 29); + QVERIFY(c.containsIndex(20)); + QVERIFY(c.containsIndex(29)); + QVERIFY(!c.containsIndex(30)); + + for (i = 20; i < 30; ++i) + QCOMPARE(c.at(i), i); + + for (i = 19; i >= 10; --i) + c.prepend(i); + + QCOMPARE(c.firstIndex(), 10); + QCOMPARE(c.lastIndex(), 19); + QVERIFY(c.containsIndex(10)); + QVERIFY(c.containsIndex(19)); + QVERIFY(!c.containsIndex(20)); + + for (i = 10; i < 20; ++i) + QCOMPARE(c.at(i), i); + + for (i = 200; i < 220; ++i) + c.insert(i, i); + + QCOMPARE(c.firstIndex(), 210); + QCOMPARE(c.lastIndex(), 219); + QVERIFY(c.containsIndex(210)); + QVERIFY(c.containsIndex(219)); + QVERIFY(!c.containsIndex(300)); + QVERIFY(!c.containsIndex(209)); + + for (i = 220; i < 220; ++i) { + QVERIFY(c.containsIndex(i)); + QCOMPARE(c.at(i), i); + } + c.clear(); // needed to reset benchmark + } + + // from a specific bug that was encountered. 100 to 299 cached, attempted to cache 250 - 205 via insert, failed. + // bug was that item at 150 would instead be item that should have been inserted at 250 + c.setCapacity(200); + for(i = 100; i < 300; ++i) + c.insert(i, i); + for (i = 250; i <= 306; ++i) + c.insert(i, 1000+i); + for (i = 107; i <= 306; ++i) { + QVERIFY(c.containsIndex(i)); + QCOMPARE(c.at(i), i < 250 ? i : 1000+i); + } +} + +struct RefCountingClassData +{ + QBasicAtomicInt ref; + static RefCountingClassData shared_null; +}; + +RefCountingClassData RefCountingClassData::shared_null = { + Q_BASIC_ATOMIC_INITIALIZER(1) +}; + +class RefCountingClass +{ +public: + RefCountingClass() : d(&RefCountingClassData::shared_null) { d->ref.ref(); } + + RefCountingClass(const RefCountingClass &other) + { + d = other.d; + d->ref.ref(); + } + + ~RefCountingClass() + { + if (!d->ref.deref()) + delete d; + } + + RefCountingClass &operator=(const RefCountingClass &other) + { + if (!d->ref.deref()) + delete d; + d = other.d; + d->ref.ref(); + return *this; + } + + int refCount() const { return d->ref; } +private: + RefCountingClassData *d; +}; + +void tst_QContiguousCache::complexType() +{ + RefCountingClass original; + + QContiguousCache contiguousCache(10); + contiguousCache.append(original); + QCOMPARE(original.refCount(), 3); + contiguousCache.removeFirst(); + QCOMPARE(original.refCount(), 2); // shared null, 'original'. + contiguousCache.append(original); + QCOMPARE(original.refCount(), 3); + contiguousCache.clear(); + QCOMPARE(original.refCount(), 2); + + for(int i = 0; i < 100; ++i) + contiguousCache.insert(i, original); + + QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in contiguousCache. + + contiguousCache.clear(); + QCOMPARE(original.refCount(), 2); + for (int i = 0; i < 100; i++) + contiguousCache.append(original); + + QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in contiguousCache. + contiguousCache.clear(); + QCOMPARE(original.refCount(), 2); + + for (int i = 0; i < 100; i++) + contiguousCache.prepend(original); + + QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in contiguousCache. + contiguousCache.clear(); + QCOMPARE(original.refCount(), 2); + + for (int i = 0; i < 100; i++) + contiguousCache.append(original); + + contiguousCache.takeLast(); + QCOMPARE(original.refCount(), 11); + + contiguousCache.takeFirst(); + QCOMPARE(original.refCount(), 10); +} + +void tst_QContiguousCache::operatorAt() +{ + RefCountingClass original; + QContiguousCache contiguousCache(10); + + for (int i = 25; i < 35; ++i) + contiguousCache[i] = original; + + QCOMPARE(original.refCount(), 12); // shared null, orig, items in cache + + // verify const access does not copy items. + const QContiguousCache copy(contiguousCache); + for (int i = 25; i < 35; ++i) + QCOMPARE(copy[i].refCount(), 12); + + // verify modifying the original increments ref count (e.g. does a detach) + contiguousCache[25] = original; + QCOMPARE(original.refCount(), 22); +} + +/* + Benchmarks must be near identical in tasks to be fair. + QCache uses pointers to ints as its a requirement of QCache, + whereas QContiguousCache doesn't support pointers (won't free them). + Given the ability to use simple data types is a benefit, its + fair. Although this obviously must take into account we are + testing QContiguousCache use cases here, QCache has its own + areas where it is the more sensible class to use. +*/ +void tst_QContiguousCache::cacheBenchmark() +{ + QBENCHMARK { + QCache cache; + cache.setMaxCost(100); + + for (int i = 0; i < 1000; i++) + cache.insert(i, new int(i)); + } +} + +void tst_QContiguousCache::contiguousCacheBenchmark() +{ + QBENCHMARK { + QContiguousCache contiguousCache(100); + for (int i = 0; i < 1000; i++) + contiguousCache.insert(i, i); + } +} + +void tst_QContiguousCache::setCapacity() +{ + int i; + QContiguousCache contiguousCache(100); + for (i = 280; i < 310; ++i) + contiguousCache.insert(i, i); + QCOMPARE(contiguousCache.capacity(), 100); + QCOMPARE(contiguousCache.count(), 30); + QCOMPARE(contiguousCache.firstIndex(), 280); + QCOMPARE(contiguousCache.lastIndex(), 309); + + for (i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) { + QVERIFY(contiguousCache.containsIndex(i)); + QCOMPARE(contiguousCache.at(i), i); + } + + contiguousCache.setCapacity(150); + + QCOMPARE(contiguousCache.capacity(), 150); + QCOMPARE(contiguousCache.count(), 30); + QCOMPARE(contiguousCache.firstIndex(), 280); + QCOMPARE(contiguousCache.lastIndex(), 309); + + for (i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) { + QVERIFY(contiguousCache.containsIndex(i)); + QCOMPARE(contiguousCache.at(i), i); + } + + contiguousCache.setCapacity(20); + + QCOMPARE(contiguousCache.capacity(), 20); + QCOMPARE(contiguousCache.count(), 20); + QCOMPARE(contiguousCache.firstIndex(), 290); + QCOMPARE(contiguousCache.lastIndex(), 309); + + for (i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) { + QVERIFY(contiguousCache.containsIndex(i)); + QCOMPARE(contiguousCache.at(i), i); + } +} + +#include "tst_qcontiguouscache.moc" diff --git a/tests/auto/qoffsetvector/qoffsetvector.pro b/tests/auto/qoffsetvector/qoffsetvector.pro deleted file mode 100644 index 0b801f3..0000000 --- a/tests/auto/qoffsetvector/qoffsetvector.pro +++ /dev/null @@ -1,8 +0,0 @@ -load(qttest_p4) - -QT = core - -SOURCES += tst_qoffsetvector.cpp - - - diff --git a/tests/auto/qoffsetvector/tst_qoffsetvector.cpp b/tests/auto/qoffsetvector/tst_qoffsetvector.cpp deleted file mode 100644 index 439ea2c..0000000 --- a/tests/auto/qoffsetvector/tst_qoffsetvector.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/**************************************************************************** -** -** This file is part of the $PACKAGE_NAME$. -** -** Copyright (C) $THISYEAR$ $COMPANY_NAME$. -** -** $QT_EXTENDED_DUAL_LICENSE$ -** -****************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include -#include - - -#if defined(FORCE_UREF) -template -inline QDebug &operator<<(QDebug debug, const QOffsetVector &offsetVector) -#else -template -inline QDebug operator<<(QDebug debug, const QOffsetVector &offsetVector) -#endif -{ - debug.nospace() << "QOffsetVector("; - for (int i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { - debug << offsetVector[i]; - if (i != offsetVector.lastIndex()) - debug << ", "; - } - debug << ")"; - return debug.space(); -} - -#if defined(NO_BENCHMARK) and defined(QBENCHMARK) -#undef QBENCHMARK -#define QBENCHMARK -#endif - -class tst_QOffsetVector : public QObject -{ - Q_OBJECT -public: - tst_QOffsetVector() {} - virtual ~tst_QOffsetVector() {} -private slots: - void empty(); - void forwardBuffer(); - void scrollingList(); - - void complexType(); - - void operatorAt(); - - void cacheBenchmark(); - void offsetVectorBenchmark(); - - void setCapacity(); -}; - -QTEST_MAIN(tst_QOffsetVector) - -void tst_QOffsetVector::empty() -{ - QOffsetVector c(10); - QCOMPARE(c.capacity(), 10); - QCOMPARE(c.count(), 0); - QVERIFY(c.isEmpty()); - c.append(1); - QVERIFY(!c.isEmpty()); - c.clear(); - QCOMPARE(c.capacity(), 10); - QCOMPARE(c.count(), 0); - QVERIFY(c.isEmpty()); - c.prepend(1); - QVERIFY(!c.isEmpty()); - c.clear(); - QCOMPARE(c.count(), 0); - QVERIFY(c.isEmpty()); - QCOMPARE(c.capacity(), 10); -} - -void tst_QOffsetVector::forwardBuffer() -{ - int i; - QOffsetVector c(10); - for(i = 1; i < 30; ++i) { - c.append(i); - QCOMPARE(c.first(), qMax(1, i-9)); - QCOMPARE(c.last(), i); - QCOMPARE(c.count(), qMin(i, 10)); - } - - c.clear(); - - for(i = 1; i < 30; ++i) { - c.prepend(i); - QCOMPARE(c.last(), qMax(1, i-9)); - QCOMPARE(c.first(), i); - QCOMPARE(c.count(), qMin(i, 10)); - } -} - -void tst_QOffsetVector::scrollingList() -{ - int i; - QOffsetVector c(10); - - // Once allocated QOffsetVector should not - // allocate any additional memory for non - // complex data types. - QBENCHMARK { - // simulate scrolling in a list of items; - for(i = 0; i < 10; ++i) - c.append(i); - - QCOMPARE(c.firstIndex(), 0); - QCOMPARE(c.lastIndex(), 9); - QVERIFY(c.containsIndex(0)); - QVERIFY(c.containsIndex(9)); - QVERIFY(!c.containsIndex(10)); - - for (i = 0; i < 10; ++i) - QCOMPARE(c.at(i), i); - - for (i = 10; i < 30; ++i) - c.append(i); - - QCOMPARE(c.firstIndex(), 20); - QCOMPARE(c.lastIndex(), 29); - QVERIFY(c.containsIndex(20)); - QVERIFY(c.containsIndex(29)); - QVERIFY(!c.containsIndex(30)); - - for (i = 20; i < 30; ++i) - QCOMPARE(c.at(i), i); - - for (i = 19; i >= 10; --i) - c.prepend(i); - - QCOMPARE(c.firstIndex(), 10); - QCOMPARE(c.lastIndex(), 19); - QVERIFY(c.containsIndex(10)); - QVERIFY(c.containsIndex(19)); - QVERIFY(!c.containsIndex(20)); - - for (i = 10; i < 20; ++i) - QCOMPARE(c.at(i), i); - - for (i = 200; i < 220; ++i) - c.insert(i, i); - - QCOMPARE(c.firstIndex(), 210); - QCOMPARE(c.lastIndex(), 219); - QVERIFY(c.containsIndex(210)); - QVERIFY(c.containsIndex(219)); - QVERIFY(!c.containsIndex(300)); - QVERIFY(!c.containsIndex(209)); - - for (i = 220; i < 220; ++i) { - QVERIFY(c.containsIndex(i)); - QCOMPARE(c.at(i), i); - } - c.clear(); // needed to reset benchmark - } - - // from a specific bug that was encountered. 100 to 299 cached, attempted to cache 250 - 205 via insert, failed. - // bug was that item at 150 would instead be item that should have been inserted at 250 - c.setCapacity(200); - for(i = 100; i < 300; ++i) - c.insert(i, i); - for (i = 250; i <= 306; ++i) - c.insert(i, 1000+i); - for (i = 107; i <= 306; ++i) { - QVERIFY(c.containsIndex(i)); - QCOMPARE(c.at(i), i < 250 ? i : 1000+i); - } -} - -struct RefCountingClassData -{ - QBasicAtomicInt ref; - static RefCountingClassData shared_null; -}; - -RefCountingClassData RefCountingClassData::shared_null = { - Q_BASIC_ATOMIC_INITIALIZER(1) -}; - -class RefCountingClass -{ -public: - RefCountingClass() : d(&RefCountingClassData::shared_null) { d->ref.ref(); } - - RefCountingClass(const RefCountingClass &other) - { - d = other.d; - d->ref.ref(); - } - - ~RefCountingClass() - { - if (!d->ref.deref()) - delete d; - } - - RefCountingClass &operator=(const RefCountingClass &other) - { - if (!d->ref.deref()) - delete d; - d = other.d; - d->ref.ref(); - return *this; - } - - int refCount() const { return d->ref; } -private: - RefCountingClassData *d; -}; - -void tst_QOffsetVector::complexType() -{ - RefCountingClass original; - - QOffsetVector offsetVector(10); - offsetVector.append(original); - QCOMPARE(original.refCount(), 3); - offsetVector.removeFirst(); - QCOMPARE(original.refCount(), 2); // shared null, 'original'. - offsetVector.append(original); - QCOMPARE(original.refCount(), 3); - offsetVector.clear(); - QCOMPARE(original.refCount(), 2); - - for(int i = 0; i < 100; ++i) - offsetVector.insert(i, original); - - QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in offsetVector. - - offsetVector.clear(); - QCOMPARE(original.refCount(), 2); - for (int i = 0; i < 100; i++) - offsetVector.append(original); - - QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in offsetVector. - offsetVector.clear(); - QCOMPARE(original.refCount(), 2); - - for (int i = 0; i < 100; i++) - offsetVector.prepend(original); - - QCOMPARE(original.refCount(), 12); // shared null, 'original', + 10 in offsetVector. - offsetVector.clear(); - QCOMPARE(original.refCount(), 2); - - for (int i = 0; i < 100; i++) - offsetVector.append(original); - - offsetVector.takeLast(); - QCOMPARE(original.refCount(), 11); - - offsetVector.takeFirst(); - QCOMPARE(original.refCount(), 10); -} - -void tst_QOffsetVector::operatorAt() -{ - RefCountingClass original; - QOffsetVector offsetVector(10); - - for (int i = 25; i < 35; ++i) - offsetVector[i] = original; - - QCOMPARE(original.refCount(), 12); // shared null, orig, items in vector - - // verify const access does not copy items. - const QOffsetVector copy(offsetVector); - for (int i = 25; i < 35; ++i) - QCOMPARE(copy[i].refCount(), 12); - - // verify modifying the original increments ref count (e.g. does a detach) - offsetVector[25] = original; - QCOMPARE(original.refCount(), 22); -} - -/* - Benchmarks must be near identical in tasks to be fair. - QCache uses pointers to ints as its a requirement of QCache, - whereas QOffsetVector doesn't support pointers (won't free them). - Given the ability to use simple data types is a benefit, its - fair. Although this obviously must take into account we are - testing QOffsetVector use cases here, QCache has its own - areas where it is the more sensible class to use. -*/ -void tst_QOffsetVector::cacheBenchmark() -{ - QBENCHMARK { - QCache cache; - cache.setMaxCost(100); - - for (int i = 0; i < 1000; i++) - cache.insert(i, new int(i)); - } -} - -void tst_QOffsetVector::offsetVectorBenchmark() -{ - QBENCHMARK { - QOffsetVector offsetVector(100); - for (int i = 0; i < 1000; i++) - offsetVector.insert(i, i); - } -} - -void tst_QOffsetVector::setCapacity() -{ - int i; - QOffsetVector offsetVector(100); - for (i = 280; i < 310; ++i) - offsetVector.insert(i, i); - QCOMPARE(offsetVector.capacity(), 100); - QCOMPARE(offsetVector.count(), 30); - QCOMPARE(offsetVector.firstIndex(), 280); - QCOMPARE(offsetVector.lastIndex(), 309); - - for (i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { - QVERIFY(offsetVector.containsIndex(i)); - QCOMPARE(offsetVector.at(i), i); - } - - offsetVector.setCapacity(150); - - QCOMPARE(offsetVector.capacity(), 150); - QCOMPARE(offsetVector.count(), 30); - QCOMPARE(offsetVector.firstIndex(), 280); - QCOMPARE(offsetVector.lastIndex(), 309); - - for (i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { - QVERIFY(offsetVector.containsIndex(i)); - QCOMPARE(offsetVector.at(i), i); - } - - offsetVector.setCapacity(20); - - QCOMPARE(offsetVector.capacity(), 20); - QCOMPARE(offsetVector.count(), 20); - QCOMPARE(offsetVector.firstIndex(), 290); - QCOMPARE(offsetVector.lastIndex(), 309); - - for (i = offsetVector.firstIndex(); i <= offsetVector.lastIndex(); ++i) { - QVERIFY(offsetVector.containsIndex(i)); - QCOMPARE(offsetVector.at(i), i); - } -} - -#include "tst_qoffsetvector.moc" -- cgit v0.12 From f7516971028d4637eeff6899fbbc6f3e8b8b5c79 Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Tue, 7 Apr 2009 16:37:51 +1000 Subject: Update licensing headers. Update files to have consistent licencesing with the rest of Qt. --- doc/src/examples/contiguouscache.qdoc | 34 +++++++++++++++- examples/tools/contiguouscache/main.cpp | 41 +++++++++++++++++++ examples/tools/contiguouscache/randomlistmodel.cpp | 40 +++++++++++++++++++ examples/tools/contiguouscache/randomlistmodel.h | 40 +++++++++++++++++++ src/corelib/tools/qcontiguouscache.cpp | 40 +++++++++++++++++-- src/corelib/tools/qcontiguouscache.h | 46 ++++++++++++++++++++-- .../auto/qcontiguouscache/tst_qcontiguouscache.cpp | 37 +++++++++++++++-- 7 files changed, 267 insertions(+), 11 deletions(-) diff --git a/doc/src/examples/contiguouscache.qdoc b/doc/src/examples/contiguouscache.qdoc index 22c97fa..6c67d77 100644 --- a/doc/src/examples/contiguouscache.qdoc +++ b/doc/src/examples/contiguouscache.qdoc @@ -3,9 +3,39 @@ ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the documentation of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ diff --git a/examples/tools/contiguouscache/main.cpp b/examples/tools/contiguouscache/main.cpp index bdeb3f3..291aaf4 100644 --- a/examples/tools/contiguouscache/main.cpp +++ b/examples/tools/contiguouscache/main.cpp @@ -1,3 +1,44 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + #include "randomlistmodel.h" #include #include diff --git a/examples/tools/contiguouscache/randomlistmodel.cpp b/examples/tools/contiguouscache/randomlistmodel.cpp index 5c0953b..0f58c0e 100644 --- a/examples/tools/contiguouscache/randomlistmodel.cpp +++ b/examples/tools/contiguouscache/randomlistmodel.cpp @@ -1,3 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ #include "randomlistmodel.h" static const int bufferSize(500); diff --git a/examples/tools/contiguouscache/randomlistmodel.h b/examples/tools/contiguouscache/randomlistmodel.h index ad8cfad..d32bf16 100644 --- a/examples/tools/contiguouscache/randomlistmodel.h +++ b/examples/tools/contiguouscache/randomlistmodel.h @@ -1,3 +1,43 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ #ifndef RANDOMLISTMODEL_H #define RANDOMLISTMODEL_H diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp index 5046912..1bcac96 100644 --- a/src/corelib/tools/qcontiguouscache.cpp +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -1,17 +1,49 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore module of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qcontiguouscache.h" #include +QT_BEGIN_NAMESPACE + void QContiguousCacheData::dump() const { qDebug() << "capacity:" << alloc; @@ -357,3 +389,5 @@ MyRecord record(int row) const Sends information about the cache's internal structure to qDebug() */ + +QT_END_NAMESPACE diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 03012a2..5250a79 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -1,11 +1,41 @@ /**************************************************************************** ** -** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** Contact: Qt Software Information (qt-info@nokia.com) ** -** This file is part of the $MODULE$ of the Qt Toolkit. +** This file is part of the QtCore module of the Qt Toolkit. ** -** $TROLLTECH_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -14,6 +44,12 @@ #include +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + struct QContiguousCacheData { QBasicAtomicInt ref; @@ -383,4 +419,8 @@ template inline T QContiguousCache::takeLast() { T t = last(); removeLast(); return t; } +QT_END_NAMESPACE + +QT_END_HEADER + #endif diff --git a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp index 493032a..6580f87 100644 --- a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp +++ b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp @@ -1,10 +1,41 @@ /**************************************************************************** ** -** This file is part of the $PACKAGE_NAME$. +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) ** -** Copyright (C) $THISYEAR$ $COMPANY_NAME$. +** This file is part of the test suite of the Qt Toolkit. ** -** $QT_EXTENDED_DUAL_LICENSE$ +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ ** ****************************************************************************/ -- cgit v0.12 From 21f15b50777ab3507f79061e749c5cee9acecb3b Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Wed, 8 Apr 2009 10:05:27 +1000 Subject: Move qDebug code to correct location --- src/corelib/io/qdebug.h | 19 +++++++++++++++++ .../auto/qcontiguouscache/tst_qcontiguouscache.cpp | 24 ---------------------- 2 files changed, 19 insertions(+), 24 deletions(-) diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 8334146..6c05756 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -51,6 +51,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -232,6 +233,24 @@ inline QDebug operator<<(QDebug debug, const QSet &set) return operator<<(debug, set.toList()); } +#if defined(FORCE_UREF) +template +inline QDebug &operator<<(QDebug debug, const QContiguousCache &contiguousCache) +#else +template +inline QDebug operator<<(QDebug debug, const QContiguousCache &cache) +#endif +{ + debug.nospace() << "QContiguousCache("; + for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) { + debug << cache[i]; + if (i != cache.lastIndex()) + debug << ", "; + } + debug << ")"; + return debug.space(); +} + #if !defined(QT_NO_DEBUG_STREAM) Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); } diff --git a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp index 6580f87..91f6a9c 100644 --- a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp +++ b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp @@ -49,30 +49,6 @@ #include #include - -#if defined(FORCE_UREF) -template -inline QDebug &operator<<(QDebug debug, const QContiguousCache &contiguousCache) -#else -template -inline QDebug operator<<(QDebug debug, const QContiguousCache &contiguousCache) -#endif -{ - debug.nospace() << "QContiguousCache("; - for (int i = contiguousCache.firstIndex(); i <= contiguousCache.lastIndex(); ++i) { - debug << contiguousCache[i]; - if (i != contiguousCache.lastIndex()) - debug << ", "; - } - debug << ")"; - return debug.space(); -} - -#if defined(NO_BENCHMARK) and defined(QBENCHMARK) -#undef QBENCHMARK -#define QBENCHMARK -#endif - class tst_QContiguousCache : public QObject { Q_OBJECT -- cgit v0.12 From 142c059031f42f1f4cb64873c634e655f3b7a46d Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Mon, 11 May 2009 10:26:10 +1000 Subject: Documentation patch from Jason A bunch of minor doc fixes. --- doc/src/examples/contiguouscache.qdoc | 34 ++++++++--------- src/corelib/tools/qcontiguouscache.cpp | 67 ++++++++++++++++++---------------- 2 files changed, 51 insertions(+), 50 deletions(-) diff --git a/doc/src/examples/contiguouscache.qdoc b/doc/src/examples/contiguouscache.qdoc index 6c67d77..71e7740 100644 --- a/doc/src/examples/contiguouscache.qdoc +++ b/doc/src/examples/contiguouscache.qdoc @@ -44,11 +44,11 @@ \title Contiguous Cache Example The Contiguous Cache example shows how to use QContiguousCache to manage memory usage for - very large models. In some environments memory is limited, and even when it - isn't users still dislike an application using - excessive memory. Using QContiguousCache to manage a list rather than loading - the entire list into memory allows the application to limit the amount - of memory it uses regardless of the size of the data set it accesses + very large models. In some environments memory is limited and, even when it + isn't, users still dislike an application using excessive memory. + Using QContiguousCache to manage a list, rather than loading + the entire list into memory, allows the application to limit the amount + of memory it uses, regardless of the size of the data set it accesses The simplest way to use QContiguousCache is to cache as items are requested. When a view requests an item at row N it is also likely to ask for items at rows near @@ -56,7 +56,7 @@ \snippet examples/tools/contiguouscache/randomlistmodel.cpp 0 - After getting the row the class determines if the row is in the bounds + After getting the row, the class determines if the row is in the bounds of the contiguous cache's current range. It would have been equally valid to simply have the following code instead. @@ -68,13 +68,12 @@ \endcode However a list will often jump rows if the scroll bar is used directly, resulting in - the code above to cause every row between where the cache was last centered - to the requested row to be fetched before the requested row is fetched. + the code above causing every row between the old and new rows to be fetched. Using QContiguousCache::lastIndex() and QContiguousCache::firstIndex() allows - the example to determine where in the list the cache is currently over. These values - don't represent the indexes into the cache own memory, but rather a virtual - infinite array that the cache represents. + the example to determine what part of the list the cache is currently caching. + These values don't represent the indexes into the cache's own memory, but rather + a virtual infinite array that the cache represents. By using QContiguousCache::append() and QContiguousCache::prepend() the code ensures that items that may be still on the screen are not lost when the requested row @@ -84,16 +83,15 @@ rows with significant gaps between them consider using QCache instead. And thats it. A perfectly reasonable cache, using minimal memory for a very large - list. In this case the accessor for getting the words into cache: - - \snippet examples/tools/contiguouscache/randomlistmodel.cpp 1 - - Generates random information rather than fixed information. This allows you + list. In this case the accessor for getting the words into the cache + generates random information rather than fixed information. This allows you to see how the cache range is kept for a local number of rows when running the example. + \snippet examples/tools/contiguouscache/randomlistmodel.cpp 1 + It is also worth considering pre-fetching items into the cache outside of the - applications paint routine. This can be done either with a separate thread - or using a QTimer to incrementally expand the range of the thread prior to + application's paint routine. This can be done either with a separate thread + or using a QTimer to incrementally expand the range of the cache prior to rows being requested out of the current cache range. */ diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp index 1bcac96..95fa9e7 100644 --- a/src/corelib/tools/qcontiguouscache.cpp +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -59,14 +59,14 @@ void QContiguousCacheData::dump() const \reentrant The QContiguousCache class provides an efficient way of caching items for - display in a user interface view. Unlike QCache though it adds a restriction - that elements within the cache are contiguous. This has the advantage that + display in a user interface view. Unlike QCache, it adds a restriction + that elements within the cache are contiguous. This has the advantage of matching how user interface views most commonly request data, as a set of rows localized around the current scrolled position. It also - allows the cache to use less overhead than QCache both in terms of - performance and memory. + allows the cache to consume less memory and processor cycles than QCache + for this use-case. - The simplest way of using an contiguous cache is to use the append() + The simplest way of using a contiguous cache is to use the append() and prepend(). \code @@ -82,18 +82,18 @@ MyRecord record(int row) const return cache.at(row); } \endcode - - If the cache is full then the item with the furthest index from where - the new item is appended or prepended is removed. + + If the cache is full then the item at the opposite end of the cache from where + the new item is appended or prepended will be removed. This usage can be further optimized by using the insert() function - in the case where the requested row is a long way from the currently cached - items. If there is a is a gap between where the new item is inserted and the currently + in the case where the requested row is a long way from the currently cached + items. If there is a gap between where the new item is inserted and the currently cached items then the existing cached items are first removed to retain the contiguous nature of the cache. Hence it is important to take some care then - when using insert() in order to avoid to unwanted clearing of the cache. + when using insert() in order to avoid unwanted clearing of the cache. - See the The \l{Contiguous Cache Example}{Contiguous Cache} example. + See the \l{Contiguous Cache Example}{Contiguous Cache} example. */ /*! \fn QContiguousCache::QContiguousCache(int capacity) @@ -116,6 +116,7 @@ MyRecord record(int row) const */ /*! \fn QContiguousCache::~QContiguousCache() + Destroys the cache. */ @@ -134,7 +135,6 @@ MyRecord record(int row) const \internal */ - /*! \fn QContiguousCache &QContiguousCache::operator=(const QContiguousCache &other) Assigns \a other to this cache and returns a reference to this cache. @@ -144,7 +144,7 @@ MyRecord record(int row) const Returns true if \a other is equal to this cache; otherwise returns false. - Two cache are considered equal if they contain the same values at the same + Two caches are considered equal if they contain the same values at the same indexes. This function requires the value type to implement the \c operator==(). \sa operator!=() @@ -155,17 +155,17 @@ MyRecord record(int row) const Returns true if \a other is not equal to this cache; otherwise returns false. - Two cache are considered equal if they contain the same values at the same + Two caches are considered equal if they contain the same values at the same indexes. This function requires the value type to implement the \c operator==(). \sa operator==() */ /*! \fn int QContiguousCache::capacity() const - + Returns the number of items the cache can store before it is full. When a cache contains a number of items equal to its capacity, adding new - items will cause items furthest from the added item to be removed. + items will cause items farthest from the added item to be removed. \sa setCapacity(), size() */ @@ -215,7 +215,7 @@ MyRecord record(int row) const Sets the capacity of the cache to the given \a size. A cache can hold a number of items equal to its capacity. When inserting, appending or prepending - items to the cache, if the cache is already full then the item furthest from + items to the cache, if the cache is already full then the item farthest from the added item will be removed. If the given \a size is smaller than the current count of items in the cache @@ -229,10 +229,10 @@ MyRecord record(int row) const Returns the item at index position \a i in the cache. \a i must be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()). - The indexes in the cache refer to number of positions the item is from the + The indexes in the cache refer to the number of positions the item is from the first item appended into the cache. That is to say a cache with a capacity of 100, that has had 150 items appended will have a valid index range of - 50 to 149. This allows inserting an retrieving items into the cache based + 50 to 149. This allows inserting and retrieving items into the cache based on a theoretical infinite list \sa firstIndex(), lastIndex(), insert(), operator[]() @@ -283,10 +283,10 @@ MyRecord record(int row) const or a prepend(). If the given index \a i is not within the current range of the cache nor adjacent - to the bounds of the cache's index range the cache is first cleared before - inserting the item. At this point the cache will have a size of 1. It is worth - while then taking effort to insert items in an order that starts adjacent to the - current index range for the cache. + to the bounds of the cache's index range, the cache is first cleared before + inserting the item. At this point the cache will have a size of 1. It is + worthwhile taking effort to insert items in an order that starts adjacent + to the current index range for the cache. \sa prepend(), append(), isFull(), firstIndex(), lastIndex() */ @@ -299,6 +299,7 @@ MyRecord record(int row) const */ /*! \fn int QContiguousCache::firstIndex() const + Returns the first valid index in the cache. The index will be invalid if the cache is empty. However the following code is valid even when the cache is empty: @@ -350,7 +351,7 @@ MyRecord record(int row) const */ /*! \fn void QContiguousCache::removeFirst() - + Removes the first item from the cache. This function assumes that the cache isn't empty. @@ -358,7 +359,7 @@ MyRecord record(int row) const */ /*! \fn void QContiguousCache::removeLast() - + Removes the last item from the cache. This function assumes that the cache isn't empty. @@ -366,19 +367,21 @@ MyRecord record(int row) const */ /*! \fn T QContiguousCache::takeFirst() - - Removes the first item in the cache and returns it. - If you don't sue the return value, removeFirst() is more efficient. + Removes the first item in the cache and returns it. This function + assumes that the cache isn't empty. + + If you don't use the return value, removeFirst() is more efficient. \sa takeLast(), removeFirst() */ /*! \fn T QContiguousCache::takeLast() - - Removes the last item in the cache and returns it. - If you don't sue the return value, removeLast() is more efficient. + Removes the last item in the cache and returns it. This function + assumes that the cache isn't empty. + + If you don't use the return value, removeLast() is more efficient. \sa takeFirst(), removeLast() */ -- cgit v0.12 From e9c8a4cf013906a54b1b05796d6007d878e85398 Mon Sep 17 00:00:00 2001 From: Frederik Schwarzer Date: Mon, 11 May 2009 15:55:59 +0200 Subject: typos in docs: double "the" --- doc/src/accessible.qdoc | 2 +- doc/src/deployment.qdoc | 2 +- doc/src/examples/codeeditor.qdoc | 2 +- doc/src/examples/containerextension.qdoc | 2 +- doc/src/examples/fortuneserver.qdoc | 2 +- doc/src/examples/ftp.qdoc | 4 ++-- doc/src/examples/icons.qdoc | 2 +- doc/src/examples/musicplayerexample.qdoc | 2 +- doc/src/examples/qobjectxmlmodel.qdoc | 2 +- doc/src/examples/tabdialog.qdoc | 2 +- doc/src/examples/tooltips.qdoc | 2 +- doc/src/examples/transformations.qdoc | 2 +- doc/src/examples/trollprint.qdoc | 2 +- doc/src/licenses.qdoc | 2 +- doc/src/mac-differences.qdoc | 2 +- doc/src/phonon-api.qdoc | 2 +- doc/src/q3valuelist.qdoc | 2 +- doc/src/qalgorithms.qdoc | 2 +- doc/src/qtdesigner.qdoc | 2 +- doc/src/qtscriptdebugger-manual.qdoc | 2 +- doc/src/stylesheet.qdoc | 8 ++++---- doc/src/tech-preview/known-issues.html | 2 +- doc/src/timers.qdoc | 4 ++-- doc/src/xquery-introduction.qdoc | 2 +- 24 files changed, 29 insertions(+), 29 deletions(-) diff --git a/doc/src/accessible.qdoc b/doc/src/accessible.qdoc index 090da86..ad9f4f1 100644 --- a/doc/src/accessible.qdoc +++ b/doc/src/accessible.qdoc @@ -527,7 +527,7 @@ on plugins, consult the plugins \l{How to Create Qt Plugins}{overview document}. - You can omit the the first macro unless you want the plugin + You can omit the first macro unless you want the plugin to be statically linked with the application. \section2 Implementing Interface Factories diff --git a/doc/src/deployment.qdoc b/doc/src/deployment.qdoc index bcfa93d..446c91b 100644 --- a/doc/src/deployment.qdoc +++ b/doc/src/deployment.qdoc @@ -1247,7 +1247,7 @@ \snippet doc/src/snippets/code/doc_src_deployment.qdoc 48 Then we update the source code in \c tools/plugandpaint/main.cpp - to look for the the new plugins. After constructing the + to look for the new plugins. After constructing the QApplication, we add the following code: \snippet doc/src/snippets/code/doc_src_deployment.qdoc 49 diff --git a/doc/src/examples/codeeditor.qdoc b/doc/src/examples/codeeditor.qdoc index 669ab45..d218d0d 100644 --- a/doc/src/examples/codeeditor.qdoc +++ b/doc/src/examples/codeeditor.qdoc @@ -67,7 +67,7 @@ QTextEdit because it is optimized for handling plain text. See the QPlainTextEdit class description for details. - QPlainTextEdit lets us add selections in addition to the the + QPlainTextEdit lets us add selections in addition to the selection the user can make with the mouse or keyboard. We use this functionality to highlight the current line. More on this later. diff --git a/doc/src/examples/containerextension.qdoc b/doc/src/examples/containerextension.qdoc index a4fbcea..6d29cf6 100644 --- a/doc/src/examples/containerextension.qdoc +++ b/doc/src/examples/containerextension.qdoc @@ -305,7 +305,7 @@ MultiPageWidget class \l {designer/containerextension/multipagewidget.cpp}{implementation}). Finally, we implicitly force an update of the page's property - sheet by calling the the + sheet by calling the QDesignerPropertySheetExtension::setChanged() function. \snippet examples/designer/containerextension/multipagewidgetplugin.cpp 4 diff --git a/doc/src/examples/fortuneserver.qdoc b/doc/src/examples/fortuneserver.qdoc index e6a7f85..848a3a3 100644 --- a/doc/src/examples/fortuneserver.qdoc +++ b/doc/src/examples/fortuneserver.qdoc @@ -45,7 +45,7 @@ The Fortune Server example shows how to create a server for a simple network service. It is intended to be run alongside the - \l{network/fortuneclient}{Fortune Client} example or the the + \l{network/fortuneclient}{Fortune Client} example or the \l{network/blockingfortuneclient}{Blocking Fortune Client} example. \image fortuneserver-example.png Screenshot of the Fortune Server example diff --git a/doc/src/examples/ftp.qdoc b/doc/src/examples/ftp.qdoc index 9cc9cd1..7a74a37 100644 --- a/doc/src/examples/ftp.qdoc +++ b/doc/src/examples/ftp.qdoc @@ -172,7 +172,7 @@ no entries were found (in which case our \c addToList() function would not have been called). - Let's continue with the the \c addToList() slot: + Let's continue with the \c addToList() slot: \snippet examples/network/ftp/ftpwindow.cpp 10 @@ -190,7 +190,7 @@ \snippet examples/network/ftp/ftpwindow.cpp 12 - \c cdToParent() is invoked when the the user requests to go to the + \c cdToParent() is invoked when the user requests to go to the parent directory of the one displayed in the file list. After changing the directory, we QFtp::List its contents. diff --git a/doc/src/examples/icons.qdoc b/doc/src/examples/icons.qdoc index 750ef2e..a81ddb9 100644 --- a/doc/src/examples/icons.qdoc +++ b/doc/src/examples/icons.qdoc @@ -479,7 +479,7 @@ QTableWidget::openPersistentEditor() function to create comboboxes for the mode and state columns of the items. - Due to the the connection between the table widget's \l + Due to the connection between the table widget's \l {QTableWidget::itemChanged()}{itemChanged()} signal and the \c changeIcon() slot, the new image is automatically converted into a pixmap and made part of the set of pixmaps available to the icon diff --git a/doc/src/examples/musicplayerexample.qdoc b/doc/src/examples/musicplayerexample.qdoc index d23c1f1..9f04bf6 100644 --- a/doc/src/examples/musicplayerexample.qdoc +++ b/doc/src/examples/musicplayerexample.qdoc @@ -154,7 +154,7 @@ \snippet examples/phonon/musicplayer/mainwindow.cpp 5 - We move on to the the slots of \c MainWindow, starting with \c + We move on to the slots of \c MainWindow, starting with \c addFiles(): \snippet examples/phonon/musicplayer/mainwindow.cpp 6 diff --git a/doc/src/examples/qobjectxmlmodel.qdoc b/doc/src/examples/qobjectxmlmodel.qdoc index ce1dab6..37c66bc 100644 --- a/doc/src/examples/qobjectxmlmodel.qdoc +++ b/doc/src/examples/qobjectxmlmodel.qdoc @@ -71,7 +71,7 @@ The query engine can only traverse two dimensional trees, because an XML document is always a two dimensional tree. If we want to add the QMetaObject tree to the node model, we have to somehow flatten it - into the the same plane as the QObject tree. This requires that the + into the same plane as the QObject tree. This requires that the node model class must build an auxiliary data structure and make it part of the two dimensional QObject node model. How to do this is explained in \l{Including The QMetaObject Tree}. diff --git a/doc/src/examples/tabdialog.qdoc b/doc/src/examples/tabdialog.qdoc index c9500af..5394b82 100644 --- a/doc/src/examples/tabdialog.qdoc +++ b/doc/src/examples/tabdialog.qdoc @@ -91,7 +91,7 @@ \snippet examples/dialogs/tabdialog/tabdialog.cpp 1 \snippet examples/dialogs/tabdialog/tabdialog.cpp 3 - We arrange the the tab widget above the buttons in the dialog: + We arrange the tab widget above the buttons in the dialog: \snippet examples/dialogs/tabdialog/tabdialog.cpp 4 diff --git a/doc/src/examples/tooltips.qdoc b/doc/src/examples/tooltips.qdoc index 5daa2b2..78b350b 100644 --- a/doc/src/examples/tooltips.qdoc +++ b/doc/src/examples/tooltips.qdoc @@ -353,7 +353,7 @@ Whenever the user creates a new shape item, we want the new item to appear at a random position, and we use the \c randomItemPosition() function to calculate such a position. We - make sure that the item appears within the the visible area of the + make sure that the item appears within the visible area of the \c SortingBox widget, using the widget's current width and heigth when calculating the random coordinates. diff --git a/doc/src/examples/transformations.qdoc b/doc/src/examples/transformations.qdoc index eabb803..58c8b80 100644 --- a/doc/src/examples/transformations.qdoc +++ b/doc/src/examples/transformations.qdoc @@ -208,7 +208,7 @@ After transforming the coordinate system, we draw the \c RenderArea's shape, and then we restore the painter state using - the the QPainter::restore() function (i.e. popping the saved state off + the QPainter::restore() function (i.e. popping the saved state off the stack). \snippet examples/painting/transformations/renderarea.cpp 7 diff --git a/doc/src/examples/trollprint.qdoc b/doc/src/examples/trollprint.qdoc index 38251ee..489012e 100644 --- a/doc/src/examples/trollprint.qdoc +++ b/doc/src/examples/trollprint.qdoc @@ -142,7 +142,7 @@ We can easily determine which file must be changed because the translator's "context" is in fact the class name for the class where the texts that must be changed appears. In this case the file is \c - printpanel.cpp, where the there are four lines to change. Add the + printpanel.cpp, where there are four lines to change. Add the second argument "two-sided" in the appropriate \c tr() calls to the first pair of radio buttons: diff --git a/doc/src/licenses.qdoc b/doc/src/licenses.qdoc index 1c3f6d2..a11c071 100644 --- a/doc/src/licenses.qdoc +++ b/doc/src/licenses.qdoc @@ -45,7 +45,7 @@ \ingroup licensing \brief Information about other licenses used for Qt components and third-party code. - Qt contains some code that is not provided under the the + Qt contains some code that is not provided under the \l{GNU General Public License (GPL)}, \l{GNU Lesser General Public License (LGPL)} or the \l{Qt Commercial Editions}{Qt Commercial License Agreement}, but rather under diff --git a/doc/src/mac-differences.qdoc b/doc/src/mac-differences.qdoc index 573e62d..5849850 100644 --- a/doc/src/mac-differences.qdoc +++ b/doc/src/mac-differences.qdoc @@ -128,7 +128,7 @@ If you want to build a new dynamic library combining the Qt 4 dynamic libraries, you need to introduce the \c{ld -r} flag. Then - relocation information is stored in the the output file, so that + relocation information is stored in the output file, so that this file could be the subject of another \c ld run. This is done by setting the \c -r flag in the \c .pro file, and the \c LFLAGS settings. diff --git a/doc/src/phonon-api.qdoc b/doc/src/phonon-api.qdoc index 501b5a5..dd37fe2 100644 --- a/doc/src/phonon-api.qdoc +++ b/doc/src/phonon-api.qdoc @@ -2973,7 +2973,7 @@ \value ToggledHint If this hint is set it means that - the the control has only two states: zero and non-zero + the control has only two states: zero and non-zero (see isToggleControl()). \value LogarithmicHint diff --git a/doc/src/q3valuelist.qdoc b/doc/src/q3valuelist.qdoc index be315c2..e3681af 100644 --- a/doc/src/q3valuelist.qdoc +++ b/doc/src/q3valuelist.qdoc @@ -108,7 +108,7 @@ pointing to the removed member become invalid. Inserting into the list does not invalidate any iterator. For convenience, the function last() returns a reference to the last item in the list, - and first() returns a reference to the the first item. If the + and first() returns a reference to the first item. If the list is empty(), both last() and first() have undefined behavior (your application will crash or do unpredictable things). Use last() and first() with caution, for example: diff --git a/doc/src/qalgorithms.qdoc b/doc/src/qalgorithms.qdoc index b33c250..90289f9 100644 --- a/doc/src/qalgorithms.qdoc +++ b/doc/src/qalgorithms.qdoc @@ -59,7 +59,7 @@ If STL is available on all your target platforms, you can use the STL algorithms instead of their Qt counterparts. One reason why - you might want to use the the STL algorithms is that STL provides + you might want to use the STL algorithms is that STL provides dozens and dozens of algorithms, whereas Qt only provides the most important ones, making no attempt to duplicate functionality that is already provided by the C++ standard. diff --git a/doc/src/qtdesigner.qdoc b/doc/src/qtdesigner.qdoc index 7e3b619..9699c5b 100644 --- a/doc/src/qtdesigner.qdoc +++ b/doc/src/qtdesigner.qdoc @@ -632,7 +632,7 @@ /*! \fn void QDesignerContainerExtension::setCurrentIndex(int index) - Sets the the currently selected page in the container to be the + Sets the currently selected page in the container to be the page at the given \a index in the extension's list of pages. \sa currentIndex() diff --git a/doc/src/qtscriptdebugger-manual.qdoc b/doc/src/qtscriptdebugger-manual.qdoc index 3dfe879..75d87f8 100644 --- a/doc/src/qtscriptdebugger-manual.qdoc +++ b/doc/src/qtscriptdebugger-manual.qdoc @@ -367,7 +367,7 @@ \section3 continue Continues execution normally, i.e, gives the execution control over - the script back the the QScriptEngine. + the script back to the QScriptEngine. \section3 eval diff --git a/doc/src/stylesheet.qdoc b/doc/src/stylesheet.qdoc index c0d13da..7d4b05d 100644 --- a/doc/src/stylesheet.qdoc +++ b/doc/src/stylesheet.qdoc @@ -332,7 +332,7 @@ respect to the reference element. Once positioned, they are treated the same as widgets and can be styled - using the the \l{box model}. + using the \l{box model}. See the \l{List of Sub-Controls} below for a list of supported sub-controls, and \l{Customizing the QPushButton's Menu Indicator @@ -671,7 +671,7 @@ \l{Qt Style Sheets Reference#subcontrol-origin-prop}{subcontrol-origin} properties. - Once positioned, sub-controls can be styled using the the \l{box model}. + Once positioned, sub-controls can be styled using the \l{box model}. \note With complex widgets such as QComboBox and QScrollBar, if one property or sub-control is customized, \bold{all} the other properties or @@ -1154,7 +1154,7 @@ \l{#pane-sub}{::pane} subcontrol. The left and right corners are styled using the \l{#left-corner-sub}{::left-corner} and \l{#right-corner-sub}{::right-corner} respectively. - The position of the the tab bar is controlled using the + The position of the tab bar is controlled using the \l{#tab-bar-sub}{::tab-bar} subcontrol. By default, the subcontrols have positions of a QTabWidget in @@ -1254,7 +1254,7 @@ the \l{#menu-button-sub}{::menu-button} subcontrol is used to draw the menu button. \l{#menu-arrow-sub}{::menu-arrow} subcontrol is used to draw the menu arrow inside the menu-button. By default, it is - positioned in the center of the Contents rectangle of the the + positioned in the center of the Contents rectangle of the menu-button subcontrol. When the QToolButton displays arrows, the \l{#up-arrow-sub}{::up-arrow}, diff --git a/doc/src/tech-preview/known-issues.html b/doc/src/tech-preview/known-issues.html index 05df69e..885104e 100644 --- a/doc/src/tech-preview/known-issues.html +++ b/doc/src/tech-preview/known-issues.html @@ -16,7 +16,7 @@

Known Issues: Qt 4.0.0 Technology Preview 1

- This is the list of known and reported issues for the the Qt 4.0.0 + This is the list of known and reported issues for the Qt 4.0.0 Technology Preview 1. This list is updated daily.



diff --git a/doc/src/timers.qdoc b/doc/src/timers.qdoc index 4f54343..1b48d7d 100644 --- a/doc/src/timers.qdoc +++ b/doc/src/timers.qdoc @@ -62,7 +62,7 @@ In multithreaded applications, you can use the timer mechanism in any thread that has an event loop. To start an event loop from a - non-GUI thread, use QThread::exec(). Qt uses the the object's + non-GUI thread, use QThread::exec(). Qt uses the object's \l{QObject::thread()}{thread affinity} to determine which thread will deliver the QTimerEvent. Because of this, you must start and stop all timers in the object's thread; it is not possible to @@ -105,7 +105,7 @@ In multithreaded applications, you can use QTimer in any thread that has an event loop. To start an event loop from a non-GUI - thread, use QThread::exec(). Qt uses the the timer's + thread, use QThread::exec(). Qt uses the timer's \l{QObject::thread()}{thread affinity} to determine which thread will emit the \l{QTimer::}{timeout()} signal. Because of this, you must start and stop the timer in its thread; it is not possible to diff --git a/doc/src/xquery-introduction.qdoc b/doc/src/xquery-introduction.qdoc index 37a45ac..fe541e2 100644 --- a/doc/src/xquery-introduction.qdoc +++ b/doc/src/xquery-introduction.qdoc @@ -347,7 +347,7 @@ has a more detailed section on the shorthand form, which it calls the \l{http://www.w3.org/TR/xquery/#abbrev} {abbreviated syntax}. More examples of path expressions written in the shorthand form are found there. There is also a section listing examples of path expressions -written in the the \l{http://www.w3.org/TR/xquery/#unabbrev} {longhand +written in the \l{http://www.w3.org/TR/xquery/#unabbrev} {longhand form}. \target Name Tests -- cgit v0.12 From 17e1bca1ce366395f8331e16aa96b7176ca1abac Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Mon, 11 May 2009 15:21:14 -0400 Subject: Optimize rendering in the GL engine By using REPLACE we don't have to clean the stencil on every draw, effectively optimizing the rendering by 200%. --- src/opengl/qpaintengine_opengl.cpp | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index aee351d..4259a5c 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -2233,7 +2233,7 @@ void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule) // Enable color writes. glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glStencilMask(0); + glStencilMask(stencilMask); setGradientOps(cbrush, QRectF(QPointF(min_x, min_y), QSizeF(max_x - min_x, max_y - min_y))); @@ -2245,12 +2245,14 @@ void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule) // Enable stencil func. glStencilFunc(GL_NOTEQUAL, 0, stencilMask); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); composite(rect); } else { DEBUG_ONCE qDebug() << "QOpenGLPaintEnginePrivate: Drawing polygon using stencil method (no fragment programs)"; // Enable stencil func. glStencilFunc(GL_NOTEQUAL, 0, stencilMask); + glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); #ifndef QT_OPENGL_ES glBegin(GL_QUADS); glVertex2f(min_x, min_y); @@ -2261,24 +2263,6 @@ void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule) #endif } - glStencilMask(~0); - glStencilFunc(GL_ALWAYS, 0, 0); - glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); - - // clear all stencil values to 0 - glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); - -#ifndef QT_OPENGL_ES - glBegin(GL_QUADS); - glVertex2f(min_x, min_y); - glVertex2f(max_x, min_y); - glVertex2f(max_x, max_y); - glVertex2f(min_x, max_y); - glEnd(); -#endif - - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - // Disable stencil writes. glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); glStencilMask(0); -- cgit v0.12 From ee533dd0818c3bf7c940cd2d543adb1c6807dd1c Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Tue, 12 May 2009 10:09:23 +1000 Subject: Various fixes resulting from QA code review. Some documentation fixes. More clear handling of what is and isn't a valid indexes. Added functions for the 'really long lived circular buffer use case' Improved unit tests. --- doc/src/examples/contiguouscache.qdoc | 8 +- src/corelib/io/qdebug.h | 2 +- src/corelib/tools/qcontiguouscache.cpp | 73 ++++++--- src/corelib/tools/qcontiguouscache.h | 32 ++-- tests/auto/auto.pro | 2 +- .../auto/qcontiguouscache/tst_qcontiguouscache.cpp | 169 +++++++++++++++++---- 6 files changed, 217 insertions(+), 69 deletions(-) diff --git a/doc/src/examples/contiguouscache.qdoc b/doc/src/examples/contiguouscache.qdoc index 71e7740..fbfde3f 100644 --- a/doc/src/examples/contiguouscache.qdoc +++ b/doc/src/examples/contiguouscache.qdoc @@ -61,10 +61,10 @@ simply have the following code instead. \code - while (row > m_words.lastIndex()) - m_words.append(fetchWord(m_words.lastIndex()+1); - while (row < m_words.firstIndex()) - m_words.prepend(fetchWord(m_words.firstIndex()-1); + while (row > m_rows.lastIndex()) + m_rows.append(fetchWord(m_rows.lastIndex()+1); + while (row < m_rows.firstIndex()) + m_rows.prepend(fetchWord(m_rows.firstIndex()-1); \endcode However a list will often jump rows if the scroll bar is used directly, resulting in diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 6c05756..9b0fbe5 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -235,7 +235,7 @@ inline QDebug operator<<(QDebug debug, const QSet &set) #if defined(FORCE_UREF) template -inline QDebug &operator<<(QDebug debug, const QContiguousCache &contiguousCache) +inline QDebug &operator<<(QDebug debug, const QContiguousCache &cache) #else template inline QDebug operator<<(QDebug debug, const QContiguousCache &cache) diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp index 95fa9e7..6671982 100644 --- a/src/corelib/tools/qcontiguouscache.cpp +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -62,9 +62,10 @@ void QContiguousCacheData::dump() const display in a user interface view. Unlike QCache, it adds a restriction that elements within the cache are contiguous. This has the advantage of matching how user interface views most commonly request data, as - a set of rows localized around the current scrolled position. It also - allows the cache to consume less memory and processor cycles than QCache - for this use-case. + a set of rows localized around the current scrolled position. This + restriction allows the cache to consume less memory and processor + cycles than QCache. The QContiguousCache class also can provide + an upper bound on memory usage via setCapacity(). The simplest way of using a contiguous cache is to use the append() and prepend(). @@ -83,8 +84,8 @@ MyRecord record(int row) const } \endcode - If the cache is full then the item at the opposite end of the cache from where - the new item is appended or prepended will be removed. + If the cache is full then the item at the opposite end of the cache from + where the new item is appended or prepended will be removed. This usage can be further optimized by using the insert() function in the case where the requested row is a long way from the currently cached @@ -93,6 +94,19 @@ MyRecord record(int row) const the contiguous nature of the cache. Hence it is important to take some care then when using insert() in order to avoid unwanted clearing of the cache. + The range of valid indexes for the QContiguousCache class are from + 0 to INT_MAX. Calling prepend() such that the first index would become less + than 0 or append() such that the last index would become greater + than INT_MAX can result in the indexes of the cache being invalid. + When the cache indexes are invalid it is important to call + normalizeIndexes() before calling any of containsIndex(), firstIndex(), + lastIndex(), at() or the [] operator. Calling these + functions when the cache has invalid indexes will result in undefined + behavior. The indexes can be checked by using areIndexesValid() + + In most cases the indexes will not exceed 0 to INT_MAX, and + normalizeIndexes() will not need to be be used. + See the \l{Contiguous Cache Example}{Contiguous Cache} example. */ @@ -288,6 +302,10 @@ MyRecord record(int row) const worthwhile taking effort to insert items in an order that starts adjacent to the current index range for the cache. + The range of valid indexes for the QContiguousCache class are from + 0 to INT_MAX. Inserting outside of this range has undefined behavior. + + \sa prepend(), append(), isFull(), firstIndex(), lastIndex() */ @@ -301,24 +319,14 @@ MyRecord record(int row) const /*! \fn int QContiguousCache::firstIndex() const Returns the first valid index in the cache. The index will be invalid if the - cache is empty. However the following code is valid even when the cache is empty: - - \code - for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) - qDebug() << "Item" << i << "of the cache is" << cache.at(i); - \endcode + cache is empty. \sa capacity(), size(), lastIndex() */ /*! \fn int QContiguousCache::lastIndex() const - Returns the last valid index in the cache. If the cache is empty will return -1. - - \code - for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) - qDebug() << "Item" << i << "of the cache is" << cache.at(i); - \endcode + Returns the last valid index in the cache. The index will be invalid if the cache is empty. \sa capacity(), size(), firstIndex() */ @@ -386,6 +394,37 @@ MyRecord record(int row) const \sa takeFirst(), removeLast() */ +/*! \fn void QContiguousCache::normalizeIndexes() + + Moves the first index and last index of the cache + such that they point to valid indexes. The function does not modify + the contents of the cache or the ordering of elements within the cache. + + It is provided so that index overflows can be corrected when using the + cache as a circular buffer. + + \code + QContiguousCache cache(10); + cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX + cache.append(2); // cache contains two values but does not have valid indexes. + cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity(). + \endcode + + \sa areIndexesValid(), append(), prepend() +*/ + +/*! \fn bool QContiguousCache::areIndexesValid() const + + Returns whether the indexes for items stored in the cache are valid. + Indexes can become invalid if items are appended after the index position + INT_MAX or prepended before the index position 0. This is only expected + to occur in very long lived circular buffer style usage of the + contiguous cache. Indexes can be made valid again by calling + normalizeIndexs(). + + \sa normalizeIndexes(), append(), prepend() +*/ + /*! \fn void QContiguousCache::dump() const \internal diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h index 5250a79..5cd1582 100644 --- a/src/corelib/tools/qcontiguouscache.h +++ b/src/corelib/tools/qcontiguouscache.h @@ -43,6 +43,7 @@ #define QCONTIGUOUSCACHE_H #include +#include QT_BEGIN_HEADER @@ -50,7 +51,7 @@ QT_BEGIN_NAMESPACE QT_MODULE(Core) -struct QContiguousCacheData +struct Q_CORE_EXPORT QContiguousCacheData { QBasicAtomicInt ref; int alloc; @@ -75,8 +76,6 @@ struct QContiguousCacheTypedData T array[1]; }; -class QContiguousCacheDevice; - template class QContiguousCache { typedef QContiguousCacheTypedData Data; @@ -128,13 +127,17 @@ public: void removeLast(); T takeLast(); + inline bool areIndexesValid() const + { return d->offset >= 0 && d->offset < INT_MAX - d->count && (d->offset % d->alloc) == d->start; } + + inline void normalizeIndexes() { d->offset = d->start; } // debug void dump() const { p->dump(); } private: void detach_helper(); - QContiguousCacheData *malloc(int alloc); - void free(Data *d); + QContiguousCacheData *malloc(int aalloc); + void free(Data *x); int sizeOfTypedData() { // this is more or less the same as sizeof(Data), except that it doesn't // count the padding at the end @@ -189,10 +192,6 @@ void QContiguousCache::setCapacity(int asize) x.d->count = qMin(d->count, asize); x.d->offset = d->offset + d->count - x.d->count; x.d->start = x.d->offset % x.d->alloc; - /* deep copy - - slow way now, get unit test working, then - improve performance if need be. (e.g. memcpy) - */ T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc; T *src = d->array + (d->start + d->count-1) % d->alloc; int count = x.d->count; @@ -249,11 +248,11 @@ inline QContiguousCacheData *QContiguousCache::malloc(int aalloc) } template -QContiguousCache::QContiguousCache(int asize) +QContiguousCache::QContiguousCache(int capacity) { - p = malloc(asize); + p = malloc(capacity); d->ref = 1; - d->alloc = asize; + d->alloc = capacity; d->count = d->start = d->offset = 0; d->sharable = true; } @@ -302,7 +301,6 @@ void QContiguousCache::free(Data *x) } qFree(x); } - template void QContiguousCache::append(const T &value) { @@ -349,6 +347,7 @@ void QContiguousCache::prepend(const T &value) template void QContiguousCache::insert(int pos, const T &value) { + Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache::insert", "index out of range"); detach(); if (containsIndex(pos)) { if(QTypeInfo::isComplex) @@ -362,8 +361,8 @@ void QContiguousCache::insert(int pos, const T &value) else { // we don't leave gaps. clear(); - d->offset = d->start = pos; - d->start %= d->alloc; + d->offset = pos; + d->start = pos % d->alloc; d->count = 1; if (QTypeInfo::isComplex) new (d->array + d->start) T(value); @@ -378,9 +377,8 @@ inline const T &QContiguousCache::at(int pos) const template inline const T &QContiguousCache::operator[](int pos) const { Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache::at", "index out of range"); return d->array[pos % d->alloc]; } -template -// can use the non-inline one to modify the index range. +template inline T &QContiguousCache::operator[](int pos) { detach(); diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index cfd9525..1f972bf 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -209,7 +209,7 @@ SUBDIRS += bic \ qnumeric \ qobject \ qobjectrace \ - qoffsetvector \ + qcontiguouscache \ qpaintengine \ qpainter \ qpainterpath \ diff --git a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp index 91f6a9c..6d59390 100644 --- a/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp +++ b/tests/auto/qcontiguouscache/tst_qcontiguouscache.cpp @@ -41,8 +41,6 @@ #include #include -#include -#include #include #include @@ -57,8 +55,13 @@ public: virtual ~tst_QContiguousCache() {} private slots: void empty(); - void forwardBuffer(); - void scrollingList(); + void append_data(); + void append(); + + void prepend_data(); + void prepend(); + + void asScrollingList(); void complexType(); @@ -79,12 +82,14 @@ void tst_QContiguousCache::empty() QCOMPARE(c.count(), 0); QVERIFY(c.isEmpty()); c.append(1); + QCOMPARE(c.count(), 1); QVERIFY(!c.isEmpty()); c.clear(); QCOMPARE(c.capacity(), 10); QCOMPARE(c.count(), 0); QVERIFY(c.isEmpty()); c.prepend(1); + QCOMPARE(c.count(), 1); QVERIFY(!c.isEmpty()); c.clear(); QCOMPARE(c.count(), 0); @@ -92,28 +97,111 @@ void tst_QContiguousCache::empty() QCOMPARE(c.capacity(), 10); } -void tst_QContiguousCache::forwardBuffer() +void tst_QContiguousCache::append_data() { - int i; - QContiguousCache c(10); - for(i = 1; i < 30; ++i) { + QTest::addColumn("start"); + QTest::addColumn("count"); + QTest::addColumn("cacheSize"); + QTest::addColumn("invalidIndexes"); + + QTest::newRow("0+30[10]") << 0 << 30 << 10 << false; + QTest::newRow("300+30[10]") << 300 << 30 << 10 << false; + QTest::newRow("MAX-10+30[10]") << INT_MAX-10 << 30 << 10 << true; +} + +void tst_QContiguousCache::append() +{ + QFETCH(int, start); + QFETCH(int, count); + QFETCH(int, cacheSize); + QFETCH(bool, invalidIndexes); + + int i, j; + QContiguousCache c(cacheSize); + + i = 1; + QCOMPARE(c.available(), cacheSize); + if (start == 0) + c.append(i++); + else + c.insert(start, i++); + while (i < count) { c.append(i); - QCOMPARE(c.first(), qMax(1, i-9)); + QCOMPARE(c.available(), qMax(0, cacheSize - i)); + QCOMPARE(c.first(), qMax(1, i-cacheSize+1)); QCOMPARE(c.last(), i); - QCOMPARE(c.count(), qMin(i, 10)); + QCOMPARE(c.count(), qMin(i, cacheSize)); + QCOMPARE(c.isFull(), i >= cacheSize); + i++; } - c.clear(); + QCOMPARE(c.areIndexesValid(), !invalidIndexes); + if (invalidIndexes) + c.normalizeIndexes(); + QVERIFY(c.areIndexesValid()); + + // test taking from end until empty. + for (j = 0; j < cacheSize; j++, i--) { + QCOMPARE(c.takeLast(), i-1); + QCOMPARE(c.count(), cacheSize-j-1); + QCOMPARE(c.available(), j+1); + QVERIFY(!c.isFull()); + QCOMPARE(c.isEmpty(), j==cacheSize-1); + } + +} + +void tst_QContiguousCache::prepend_data() +{ + QTest::addColumn("start"); + QTest::addColumn("count"); + QTest::addColumn("cacheSize"); + QTest::addColumn("invalidIndexes"); + + QTest::newRow("30-30[10]") << 30 << 30 << 10 << false; + QTest::newRow("300-30[10]") << 300 << 30 << 10 << false; + QTest::newRow("10-30[10]") << 10 << 30 << 10 << true; +} - for(i = 1; i < 30; ++i) { +void tst_QContiguousCache::prepend() +{ + QFETCH(int, start); + QFETCH(int, count); + QFETCH(int, cacheSize); + QFETCH(bool, invalidIndexes); + + int i, j; + QContiguousCache c(cacheSize); + + i = 1; + QCOMPARE(c.available(), cacheSize); + c.insert(start, i++); + while(i < count) { c.prepend(i); - QCOMPARE(c.last(), qMax(1, i-9)); + QCOMPARE(c.available(), qMax(0, cacheSize - i)); + QCOMPARE(c.last(), qMax(1, i-cacheSize+1)); QCOMPARE(c.first(), i); - QCOMPARE(c.count(), qMin(i, 10)); + QCOMPARE(c.count(), qMin(i, cacheSize)); + QCOMPARE(c.isFull(), i >= cacheSize); + i++; + } + + QCOMPARE(c.areIndexesValid(), !invalidIndexes); + if (invalidIndexes) + c.normalizeIndexes(); + QVERIFY(c.areIndexesValid()); + + // test taking from start until empty. + for (j = 0; j < cacheSize; j++, i--) { + QCOMPARE(c.takeFirst(), i-1); + QCOMPARE(c.count(), cacheSize-j-1); + QCOMPARE(c.available(), j+1); + QVERIFY(!c.isFull()); + QCOMPARE(c.isEmpty(), j==cacheSize-1); } } -void tst_QContiguousCache::scrollingList() +void tst_QContiguousCache::asScrollingList() { int i; QContiguousCache c(10); @@ -123,55 +211,78 @@ void tst_QContiguousCache::scrollingList() // complex data types. QBENCHMARK { // simulate scrolling in a list of items; - for(i = 0; i < 10; ++i) + for(i = 0; i < 10; ++i) { + QCOMPARE(c.available(), 10-i); c.append(i); + } QCOMPARE(c.firstIndex(), 0); QCOMPARE(c.lastIndex(), 9); - QVERIFY(c.containsIndex(0)); - QVERIFY(c.containsIndex(9)); + QCOMPARE(c.first(), 0); + QCOMPARE(c.last(), 9); + QVERIFY(!c.containsIndex(-1)); QVERIFY(!c.containsIndex(10)); + QCOMPARE(c.available(), 0); - for (i = 0; i < 10; ++i) + for (i = 0; i < 10; ++i) { + QVERIFY(c.containsIndex(i)); QCOMPARE(c.at(i), i); + QCOMPARE(c[i], i); + QCOMPARE(((const QContiguousCache)c)[i], i); + } for (i = 10; i < 30; ++i) c.append(i); QCOMPARE(c.firstIndex(), 20); QCOMPARE(c.lastIndex(), 29); - QVERIFY(c.containsIndex(20)); - QVERIFY(c.containsIndex(29)); + QCOMPARE(c.first(), 20); + QCOMPARE(c.last(), 29); + QVERIFY(!c.containsIndex(19)); QVERIFY(!c.containsIndex(30)); + QCOMPARE(c.available(), 0); - for (i = 20; i < 30; ++i) + for (i = 20; i < 30; ++i) { + QVERIFY(c.containsIndex(i)); QCOMPARE(c.at(i), i); + QCOMPARE(c[i], i); + QCOMPARE(((const QContiguousCache )c)[i], i); + } for (i = 19; i >= 10; --i) c.prepend(i); QCOMPARE(c.firstIndex(), 10); QCOMPARE(c.lastIndex(), 19); - QVERIFY(c.containsIndex(10)); - QVERIFY(c.containsIndex(19)); + QCOMPARE(c.first(), 10); + QCOMPARE(c.last(), 19); + QVERIFY(!c.containsIndex(9)); QVERIFY(!c.containsIndex(20)); + QCOMPARE(c.available(), 0); - for (i = 10; i < 20; ++i) + for (i = 10; i < 20; ++i) { + QVERIFY(c.containsIndex(i)); QCOMPARE(c.at(i), i); + QCOMPARE(c[i], i); + QCOMPARE(((const QContiguousCache )c)[i], i); + } for (i = 200; i < 220; ++i) c.insert(i, i); QCOMPARE(c.firstIndex(), 210); QCOMPARE(c.lastIndex(), 219); - QVERIFY(c.containsIndex(210)); - QVERIFY(c.containsIndex(219)); - QVERIFY(!c.containsIndex(300)); + QCOMPARE(c.first(), 210); + QCOMPARE(c.last(), 219); QVERIFY(!c.containsIndex(209)); + QVERIFY(!c.containsIndex(300)); + QCOMPARE(c.available(), 0); - for (i = 220; i < 220; ++i) { + for (i = 210; i < 220; ++i) { QVERIFY(c.containsIndex(i)); QCOMPARE(c.at(i), i); + QCOMPARE(c[i], i); + QCOMPARE(((const QContiguousCache )c)[i], i); } c.clear(); // needed to reset benchmark } -- cgit v0.12 From 56191830cdad9cbaa81c2ed8f22f1b2650a5608a Mon Sep 17 00:00:00 2001 From: Marius Storm-Olsen Date: Wed, 13 May 2009 13:58:18 +0200 Subject: Turn off Link Time Code Generation (/LTCG) by default Turning on LTCG affected too many projects, where customers applications would take a long time linking, severly affecting their development time (even though it was only added for release builds) We turn it off by default, and add a -ltcg configuration option, and the possibility to also do CONFIG+=ltcg in projects, should they not want it for Qt, but in their own projects. (Same, they can build Qt with it, and do CONFIG-=ltcg for their project) Reviewed-by: andy --- configure.exe | Bin 860160 -> 856064 bytes mkspecs/features/win32/ltcg.prf | 5 +++++ mkspecs/win32-msvc2005/qmake.conf | 7 +++++-- mkspecs/win32-msvc2008/qmake.conf | 7 +++++-- tools/configure/configureapp.cpp | 13 +++++++++++++ 5 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 mkspecs/features/win32/ltcg.prf diff --git a/configure.exe b/configure.exe index ff71f08..40843b4 100644 Binary files a/configure.exe and b/configure.exe differ diff --git a/mkspecs/features/win32/ltcg.prf b/mkspecs/features/win32/ltcg.prf new file mode 100644 index 0000000..f6f1299 --- /dev/null +++ b/mkspecs/features/win32/ltcg.prf @@ -0,0 +1,5 @@ +CONFIG(release, debug|release) { + QMAKE_CFLAGS *= $$QMAKE_CFLAGS_LTCG + QMAKE_CXXFLAGS *= $$QMAKE_CXXFLAGS_LTCG + QMAKE_LFLAGS *= $$QMAKE_LFLAGS_LTCG +} diff --git a/mkspecs/win32-msvc2005/qmake.conf b/mkspecs/win32-msvc2005/qmake.conf index 00287cb..5ed8e01 100644 --- a/mkspecs/win32-msvc2005/qmake.conf +++ b/mkspecs/win32-msvc2005/qmake.conf @@ -19,9 +19,10 @@ QMAKE_YACCFLAGS = -d QMAKE_CFLAGS = -nologo -Zm200 -Zc:wchar_t- QMAKE_CFLAGS_WARN_ON = -W3 QMAKE_CFLAGS_WARN_OFF = -W0 -QMAKE_CFLAGS_RELEASE = -O2 -MD -GL +QMAKE_CFLAGS_RELEASE = -O2 -MD QMAKE_CFLAGS_DEBUG = -Zi -MDd QMAKE_CFLAGS_YACC = +QMAKE_CFLAGS_LTCG = -GL QMAKE_CXX = $$QMAKE_CC QMAKE_CXXFLAGS = $$QMAKE_CFLAGS @@ -30,6 +31,7 @@ QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC +QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_CXXFLAGS_STL_ON = -EHsc QMAKE_CXXFLAGS_STL_OFF = QMAKE_CXXFLAGS_RTTI_ON = -GR @@ -50,11 +52,12 @@ QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<< QMAKE_LINK = link QMAKE_LFLAGS = /NOLOGO -QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /LTCG +QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" QMAKE_LFLAGS_DLL = /DLL +QMAKE_LFLAGS_LTCG = /LTCG QMAKE_LIBS_CORE = kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib ws2_32.lib QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib winspool.lib ws2_32.lib ole32.lib user32.lib advapi32.lib diff --git a/mkspecs/win32-msvc2008/qmake.conf b/mkspecs/win32-msvc2008/qmake.conf index b56b41c..373a36d 100644 --- a/mkspecs/win32-msvc2008/qmake.conf +++ b/mkspecs/win32-msvc2008/qmake.conf @@ -19,9 +19,10 @@ QMAKE_YACCFLAGS = -d QMAKE_CFLAGS = -nologo -Zm200 -Zc:wchar_t- QMAKE_CFLAGS_WARN_ON = -W3 QMAKE_CFLAGS_WARN_OFF = -W0 -QMAKE_CFLAGS_RELEASE = -O2 -MD -GL +QMAKE_CFLAGS_RELEASE = -O2 -MD QMAKE_CFLAGS_DEBUG = -Zi -MDd QMAKE_CFLAGS_YACC = +QMAKE_CFLAGS_LTCG = -GL QMAKE_CXX = $$QMAKE_CC QMAKE_CXXFLAGS = $$QMAKE_CFLAGS @@ -30,6 +31,7 @@ QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC +QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_CXXFLAGS_STL_ON = -EHsc QMAKE_CXXFLAGS_STL_OFF = QMAKE_CXXFLAGS_RTTI_ON = -GR @@ -50,11 +52,12 @@ QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<< QMAKE_LINK = link QMAKE_LFLAGS = /NOLOGO -QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO /LTCG +QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO QMAKE_LFLAGS_DEBUG = /DEBUG QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\" QMAKE_LFLAGS_DLL = /DLL +QMAKE_LFLAGS_LTCG = /LTCG QMAKE_LIBS_CORE = kernel32.lib user32.lib shell32.lib uuid.lib ole32.lib advapi32.lib ws2_32.lib QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib winspool.lib ws2_32.lib ole32.lib user32.lib advapi32.lib diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index bcbf557..91344c8 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -351,6 +351,7 @@ Configure::Configure( int& argc, char** argv ) dictionary[ "QMAKESPEC" ] = tmp; dictionary[ "INCREDIBUILD_XGE" ] = "auto"; + dictionary[ "LTCG" ] = "no"; } Configure::~Configure() @@ -487,6 +488,12 @@ void Configure::parseCmdLine() else if( configCmdLine.at(i) == "-commercial" ) { dictionary[ "BUILDTYPE" ] = "commercial"; } + else if( configCmdLine.at(i) == "-ltcg" ) { + dictionary[ "LTCG" ] = "yes"; + } + else if( configCmdLine.at(i) == "-no-ltcg" ) { + dictionary[ "LTCG" ] = "no"; + } #endif else if( configCmdLine.at(i) == "-platform" ) { @@ -1465,6 +1472,9 @@ bool Configure::displayHelp() desc("SHARED", "yes", "-shared", "Create and use shared Qt libraries."); desc("SHARED", "no", "-static", "Create and use static Qt libraries.\n"); + desc("LTCG", "yes", "-ltcg", "Use Link Time Code Generation. (Release builds only)"); + desc("LTCG", "no", "-no-ltcg", "Do not use Link Time Code Generation.\n"); + desc("FAST", "no", "-no-fast", "Configure Qt normally by generating Makefiles for all project files."); desc("FAST", "yes", "-fast", "Configure Qt quickly by generating Makefiles only for library and " "subdirectory targets. All other Makefiles are created as wrappers " @@ -2494,6 +2504,8 @@ void Configure::generateCachefile() else configStream << " static"; + if( dictionary[ "LTCG" ] == "yes" ) + configStream << " ltcg"; if( dictionary[ "STL" ] == "yes" ) configStream << " stl"; if ( dictionary[ "EXCEPTIONS" ] == "yes" ) @@ -2916,6 +2928,7 @@ void Configure::displayConfig() cout << "Architecture................" << dictionary[ "ARCHITECTURE" ] << endl; cout << "Maketool...................." << dictionary[ "MAKE" ] << endl; cout << "Debug symbols..............." << (dictionary[ "BUILD" ] == "debug" ? "yes" : "no") << endl; + cout << "Link Time Code Generation..." << dictionary[ "LTCG" ] << endl; cout << "Accessibility support......." << dictionary[ "ACCESSIBILITY" ] << endl; cout << "STL support................." << dictionary[ "STL" ] << endl; cout << "Exception support..........." << dictionary[ "EXCEPTIONS" ] << endl; -- cgit v0.12 From bb000e03fc1e876eb6ee0d02de15a0bc9a6ea1b8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 13 May 2009 14:53:24 +0200 Subject: Added API for quietly saving a form. Task-number: 163220 Added to FormWindowBase. Required among other things for Qt Creator code completion for uic-generated-headers. Acked-by: dt --- tools/designer/src/lib/shared/formwindowbase.cpp | 10 +++++++++- tools/designer/src/lib/shared/formwindowbase_p.h | 3 +++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/designer/src/lib/shared/formwindowbase.cpp b/tools/designer/src/lib/shared/formwindowbase.cpp index 3e7e17b..b569b51 100644 --- a/tools/designer/src/lib/shared/formwindowbase.cpp +++ b/tools/designer/src/lib/shared/formwindowbase.cpp @@ -55,7 +55,7 @@ TRANSLATOR qdesigner_internal::FormWindowBase #include "deviceprofile_p.h" #include "qdesigner_utils_p.h" -#include +#include "qsimpleresource_p.h" #include #include @@ -482,6 +482,14 @@ void FormWindowBase::setupDefaultAction(QDesignerFormWindowInterface *fw) QObject::connect(fw, SIGNAL(activated(QWidget*)), fw, SLOT(triggerDefaultAction(QWidget*))); } +QString FormWindowBase::fileContents() const +{ + const bool oldValue = QSimpleResource::setWarningsEnabled(false); + const QString rc = contents(); + QSimpleResource::setWarningsEnabled(oldValue); + return rc; +} + } // namespace qdesigner_internal QT_END_NAMESPACE diff --git a/tools/designer/src/lib/shared/formwindowbase_p.h b/tools/designer/src/lib/shared/formwindowbase_p.h index 68e977e..0891f6e 100644 --- a/tools/designer/src/lib/shared/formwindowbase_p.h +++ b/tools/designer/src/lib/shared/formwindowbase_p.h @@ -90,6 +90,9 @@ public: QVariantMap formData(); void setFormData(const QVariantMap &vm); + // Return contents without warnings. Should be 'contents(bool quiet)' + QString fileContents() const; + // Return the widget containing the form. This is used to // apply embedded design settings to that are inherited (for example font). // These are meant to be applied to the form only and not to the other editors -- cgit v0.12 From 960d2a7639062b6582d460aaae140b4d2e0a8b70 Mon Sep 17 00:00:00 2001 From: Morten Engvoldsen Date: Wed, 13 May 2009 14:59:52 +0200 Subject: Adding details to QVariant docs Adding note about requriements for converting QVariants Task-number: 192607 Rev-by: David Boddie --- src/corelib/kernel/qvariant.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index b4427c0..0a0500d 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -1187,8 +1187,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler; and versatile, but may prove less memory and speed efficient than storing specific types in standard data structures. - QVariant also supports the notion of null values, where you have - a defined type with no value set. + QVariant also supports the notion of null values, where you can + have a defined type with no value set. However, note that QVariant + types can only be cast when they have had a value set. \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 1 -- cgit v0.12 From 62677589caf8b2f45f369cfc9df30ded323c4155 Mon Sep 17 00:00:00 2001 From: Morten Engvoldsen Date: Wed, 13 May 2009 15:13:10 +0200 Subject: Cleaning docs Highlight part of the general description in QTimeLine Task-number: 218487 Rev-by: Geir Vattekar --- src/corelib/tools/qtimeline.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp index 2979a09..3a03558 100644 --- a/src/corelib/tools/qtimeline.cpp +++ b/src/corelib/tools/qtimeline.cpp @@ -225,7 +225,9 @@ void QTimeLinePrivate::setCurrentTime(int msecs) valueForTime() and emitting valueChanged(). By default, valueForTime() applies an interpolation algorithm to generate these value. You can choose from a set of predefined timeline algorithms by calling - setCurveShape(). By default, QTimeLine uses the EaseInOut curve shape, + setCurveShape(). + + Note that by default, QTimeLine uses the EaseInOut curve shape, which provides a value that grows slowly, then grows steadily, and finally grows slowly. For a custom timeline, you can reimplement valueForTime(), in which case QTimeLine's curveShape property is ignored. -- cgit v0.12 From 9820412d2551b655fec24ffde7b2a56e3ad168ea Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Wed, 13 May 2009 15:34:34 +0200 Subject: Ensure that sheets are hidden if the parents are hidden in Carbon. Seems to work correctly in Cocoa, but we need to handle this special case in Carbon ourselves. Task-number: 253324 Reviewed-by: Richard Moe Gustavsen --- src/gui/kernel/qwidget_mac.mm | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index 6d3da61..6524bc9 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -728,6 +728,7 @@ static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAtt static EventTypeSpec window_events[] = { { kEventClassWindow, kEventWindowClose }, { kEventClassWindow, kEventWindowExpanded }, + { kEventClassWindow, kEventWindowHidden }, { kEventClassWindow, kEventWindowZoomed }, { kEventClassWindow, kEventWindowCollapsed }, { kEventClassWindow, kEventWindowToolbarSwitchMode }, @@ -997,6 +998,19 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, } } } + } else if (ekind == kEventWindowHidden) { + // Make sure that we also hide any visible sheets on our window. + // Cocoa does the right thing for us. + const QObjectList children = widget->children(); + const int childCount = children.count(); + for (int i = 0; i < childCount; ++i) { + QObject *obj = children.at(i); + if (obj->isWidgetType()) { + QWidget *widget = static_cast(obj); + if (qt_mac_is_macsheet(widget) && widget->isVisible()) + widget->hide(); + } + } } else { handled_event = false; } -- cgit v0.12 From 1c22d96f15d46c222bf5f1720e3e49e202a6c941 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Tue, 12 May 2009 17:58:27 +0200 Subject: HTTP backend / network cache: only cache responses to GET by default responses to POST might be cacheable, but are not cacheable by default; responses to PUT or DELETE are never cacheable. Reviewed-by: Thiago Macieira Task-number: 252281 --- src/network/access/qnetworkaccesshttpbackend.cpp | 42 +++++++++++++++++------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp index a52b5a0..f214699 100644 --- a/src/network/access/qnetworkaccesshttpbackend.cpp +++ b/src/network/access/qnetworkaccesshttpbackend.cpp @@ -1036,21 +1036,39 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo if (it != cacheHeaders.rawHeaders.constEnd()) metaData.setLastModified(QNetworkHeadersPrivate::fromHttpDate(it->second)); - bool canDiskCache = true; // Everything defaults to being cacheable on disk - - // 14.32 - // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client - // had sent "Cache-Control: no-cache". - it = cacheHeaders.findRawHeader("pragma"); - if (it != cacheHeaders.rawHeaders.constEnd() - && it->second == "no-cache") - canDiskCache = false; + bool canDiskCache; + // only cache GET replies by default, all other replies (POST, PUT, DELETE) + // are not cacheable by default (according to RFC 2616 section 9) + if (httpReply->request().operation() == QHttpNetworkRequest::Get) { + + canDiskCache = true; + // 14.32 + // HTTP/1.1 caches SHOULD treat "Pragma: no-cache" as if the client + // had sent "Cache-Control: no-cache". + it = cacheHeaders.findRawHeader("pragma"); + if (it != cacheHeaders.rawHeaders.constEnd() + && it->second == "no-cache") + canDiskCache = false; + + // HTTP/1.1. Check the Cache-Control header + if (cacheControl.contains("no-cache")) + canDiskCache = false; + else if (cacheControl.contains("no-store")) + canDiskCache = false; + + // responses to POST might be cacheable + } else if (httpReply->request().operation() == QHttpNetworkRequest::Post) { - // HTTP/1.1. Check the Cache-Control header - if (cacheControl.contains("no-cache")) canDiskCache = false; - else if (cacheControl.contains("no-store")) + // some pages contain "expires:" and "cache-control: no-cache" field, + // so we only might cache POST requests if we get "cache-control: max-age ..." + if (cacheControl.contains("max-age")) + canDiskCache = true; + + // responses to PUT and DELETE are not cacheable + } else { canDiskCache = false; + } metaData.setSaveToDisk(canDiskCache); int statusCode = httpReply->statusCode(); -- cgit v0.12 From 484ad0eccc84488b57d58a1223760623c70389a5 Mon Sep 17 00:00:00 2001 From: Morten Engvoldsen Date: Wed, 13 May 2009 17:10:43 +0200 Subject: Correcting bug in cardLayout example Adding the count() function to the example. Task-number: 220766 Rev-by: Geir Vattekar --- doc/src/layout.qdoc | 16 +++++++----- doc/src/snippets/code/doc_src_layout.qdoc | 41 +++++++++++++++++-------------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/doc/src/layout.qdoc b/doc/src/layout.qdoc index 55dfd8b..196999b 100644 --- a/doc/src/layout.qdoc +++ b/doc/src/layout.qdoc @@ -315,7 +315,11 @@ \snippet doc/src/snippets/code/doc_src_layout.qdoc 1 - First we define two functions that iterate over the layout: \c{itemAt()} + First we define \c{count()} to fetch the number of items in the list. + + \snippet doc/src/snippets/code/doc_src_layout.qdoc 2 + + Then we define two functions that iterate over the layout: \c{itemAt()} and \c{takeAt()}. These functions are used internally by the layout system to handle deletion of widgets. They are also available for application programmers. @@ -326,7 +330,7 @@ structure, we may have to spend more effort defining a linear order for the items. - \snippet doc/src/snippets/code/doc_src_layout.qdoc 2 + \snippet doc/src/snippets/code/doc_src_layout.qdoc 3 \c{addItem()} implements the default placement strategy for layout items. This function must be implemented. It is used by QLayout::add(), by the @@ -336,26 +340,26 @@ QGridLayout::addItem(), QGridLayout::addWidget(), and QGridLayout::addLayout(). - \snippet doc/src/snippets/code/doc_src_layout.qdoc 3 + \snippet doc/src/snippets/code/doc_src_layout.qdoc 4 The layout takes over responsibility of the items added. Since QLayoutItem does not inherit QObject, we must delete the items manually. The function QLayout::deleteAllItems() uses \c{takeAt()} defined above to delete all the items in the layout. - \snippet doc/src/snippets/code/doc_src_layout.qdoc 4 + \snippet doc/src/snippets/code/doc_src_layout.qdoc 5 The \c{setGeometry()} function actually performs the layout. The rectangle supplied as an argument does not include \c{margin()}. If relevant, use \c{spacing()} as the distance between items. - \snippet doc/src/snippets/code/doc_src_layout.qdoc 5 + \snippet doc/src/snippets/code/doc_src_layout.qdoc 6 \c{sizeHint()} and \c{minimumSize()} are normally very similar in implementation. The sizes returned by both functions should include \c{spacing()}, but not \c{margin()}. - \snippet doc/src/snippets/code/doc_src_layout.qdoc 6 + \snippet doc/src/snippets/code/doc_src_layout.qdoc 7 \section2 Further Notes diff --git a/doc/src/snippets/code/doc_src_layout.qdoc b/doc/src/snippets/code/doc_src_layout.qdoc index 48e10e9..fedcf0c 100644 --- a/doc/src/snippets/code/doc_src_layout.qdoc +++ b/doc/src/snippets/code/doc_src_layout.qdoc @@ -2,23 +2,21 @@ #ifndef CARD_H #define CARD_H -#include +#include #include class CardLayout : public QLayout { public: - CardLayout(QWidget *parent, int dist) - : QLayout(parent, 0, dist) {} - CardLayout(QLayout *parent, int dist) - : QLayout(parent, dist) {} - CardLayout(int dist) - : QLayout(dist) {} + CardLayout(QWidget *parent, int dist): QLayout(parent, 0, dist) {} + CardLayout(QLayout *parent, int dist): QLayout(parent, dist) {} + CardLayout(int dist): QLayout(dist) {} ~CardLayout(); void addItem(QLayoutItem *item); QSize sizeHint() const; QSize minimumSize() const; + QLayoutItem *count() const; QLayoutItem *itemAt(int) const; QLayoutItem *takeAt(int); void setGeometry(const QRect &rect); @@ -31,11 +29,18 @@ private: //! [1] -#include "card.h" +//#include "card.h" //! [1] - //! [2] +QLayoutItem *CardLayout::count() const +{ + // QList::size() returns the number of QLayoutItems in the list + return list.size(); +} +//! [2] + +//! [3] QLayoutItem *CardLayout::itemAt(int idx) const { // QList::value() performs index checking, and returns 0 if we are @@ -48,26 +53,26 @@ QLayoutItem *CardLayout::takeAt(int idx) // QList::take does not do index checking return idx >= 0 && idx < list.size() ? list.takeAt(idx) : 0; } -//! [2] +//! [3] -//! [3] +//! [4] void CardLayout::addItem(QLayoutItem *item) { list.append(item); } -//! [3] +//! [4] -//! [4] +//! [5] CardLayout::~CardLayout() { deleteAllItems(); } -//! [4] +//! [5] -//! [5] +//! [6] void CardLayout::setGeometry(const QRect &r) { QLayout::setGeometry(r); @@ -85,10 +90,10 @@ void CardLayout::setGeometry(const QRect &r) ++i; } } -//! [5] +//! [6] -//! [6] +//! [7] QSize CardLayout::sizeHint() const { QSize s(0,0); @@ -116,4 +121,4 @@ QSize CardLayout::minimumSize() const } return s + n*QSize(spacing(), spacing()); } -//! [6] +//! [7] \ No newline at end of file -- cgit v0.12 From 54ad50c99fee0db0dc9a64ee16dfcc4315b9d86d Mon Sep 17 00:00:00 2001 From: Jason McDonald Date: Thu, 14 May 2009 09:41:08 +1000 Subject: Fix broken wince build. The WinCE build was failing due to a spelling error in an #ifdef directive. Reviewed-by: Trust Me --- src/gui/widgets/qmenu_wince.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp index fbe54fe..42a4e0b 100644 --- a/src/gui/widgets/qmenu_wince.cpp +++ b/src/gui/widgets/qmenu_wince.cpp @@ -214,7 +214,7 @@ static HWND qt_wce_create_menubar(HWND parentHandle, HINSTANCE resourceHandle, i mbi.nToolBarId = toolbarID; if (ptrCreateMenuBar(&mbi)) { -#ifdef Q_WS_WINCE_WM +#ifdef Q_OS_WINCE_WM // Tell the menu bar that we want to override hot key behaviour. LPARAM lparam = MAKELPARAM(SHMBOF_NODEFAULT | SHMBOF_NOTIFY, SHMBOF_NODEFAULT | SHMBOF_NOTIFY); -- cgit v0.12 From 594bc93fc36e2d0aada9c11a7957db7fd4b11c15 Mon Sep 17 00:00:00 2001 From: Andre Haupt Date: Thu, 14 May 2009 04:34:01 +0200 Subject: doc: fix two typos in tthe style sheet documentation Signed-off-by: Andre Haupt --- doc/src/stylesheet.qdoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/stylesheet.qdoc b/doc/src/stylesheet.qdoc index c0d13da..0f99688 100644 --- a/doc/src/stylesheet.qdoc +++ b/doc/src/stylesheet.qdoc @@ -398,7 +398,7 @@ (usually) refers to a single object, not to all instances of a class. - Similarly, selectors with pseudo-states are more specific that + Similarly, selectors with pseudo-states are more specific than ones that do not specify pseudo-states. Thus, the following style sheet specifies that a \l{QPushButton} should have white text when the mouse is hovering over it, otherwise red text: @@ -653,7 +653,7 @@ \target sub controls \section1 Sub-controls - A widget is considered as a heirarchy (tree) of subcontrols drawn on top + A widget is considered as a hierarchy (tree) of subcontrols drawn on top of each other. For example, the QComboBox draws the drop-down sub-control followed by the down-arrow sub-control. A QComboBox is thus rendered as follows: -- cgit v0.12 From dd20c403fa6ec99cf4aec02655a16a97320734c3 Mon Sep 17 00:00:00 2001 From: Andre Haupt Date: Thu, 14 May 2009 04:44:19 +0200 Subject: replace all occurences of "heirarchy" with "hierarchy" Signed-off-by: Andre Haupt --- src/corelib/io/qresource.cpp | 2 +- src/gui/widgets/qmenu_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 779a742..3b704f6 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -449,7 +449,7 @@ QString QResource::absoluteFilePath() const } /*! - Returns true if the resource really exists in the resource heirarchy, + Returns true if the resource really exists in the resource hierarchy, false otherwise. */ diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h index dddd83e..edfeee7 100644 --- a/src/gui/widgets/qmenu_p.h +++ b/src/gui/widgets/qmenu_p.h @@ -208,7 +208,7 @@ public: QString searchBuffer; QBasicTimer searchBufferTimer; - //passing of mouse events up the parent heirarchy + //passing of mouse events up the parent hierarchy QPointer activeMenu; bool mouseEventTaken(QMouseEvent *); -- cgit v0.12 From 4cfe2b57d97488b4f312ad2ec2985f619b4984b6 Mon Sep 17 00:00:00 2001 From: Bill King Date: Thu, 14 May 2009 14:15:21 +1000 Subject: Use newer safer error function if available. Uses fb_interpret instead of isc_interprete if using firebird. Closes a potential security hole/buffer overrun. Reviewed-by: Justin McPherson --- src/sql/drivers/ibase/qsql_ibase.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index 6834d9a..4f3d79d 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -66,8 +66,11 @@ QT_BEGIN_NAMESPACE enum { QIBaseChunkSize = SHRT_MAX / 2 }; -static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode, - QTextCodec *tc) +#if defined(FB_API_VER) && FB_API_VER >= 20 +static bool getIBaseError(QString& msg, const ISC_STATUS* status, ISC_LONG &sqlcode, QTextCodec *tc) +#else +static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode, QTextCodec *tc) +#endif { if (status[0] != 1 || status[1] <= 0) return false; @@ -75,7 +78,11 @@ static bool getIBaseError(QString& msg, ISC_STATUS* status, ISC_LONG &sqlcode, msg.clear(); sqlcode = isc_sqlcode(status); char buf[512]; +#if defined(FB_API_VER) && FB_API_VER >= 20 + while(fb_interpret(buf, 512, &status)) { +#else while(isc_interprete(buf, &status)) { +#endif if(!msg.isEmpty()) msg += QLatin1String(" - "); if (tc) -- cgit v0.12 From df69dfe0ec549a259ed78cf48dff898d8a044c41 Mon Sep 17 00:00:00 2001 From: Ian Walters Date: Thu, 14 May 2009 14:23:40 +1000 Subject: Grammer fix, 'be be' to 'be' --- src/corelib/tools/qcontiguouscache.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp index 6671982..7db3a5a 100644 --- a/src/corelib/tools/qcontiguouscache.cpp +++ b/src/corelib/tools/qcontiguouscache.cpp @@ -105,7 +105,7 @@ MyRecord record(int row) const behavior. The indexes can be checked by using areIndexesValid() In most cases the indexes will not exceed 0 to INT_MAX, and - normalizeIndexes() will not need to be be used. + normalizeIndexes() will not need to be used. See the \l{Contiguous Cache Example}{Contiguous Cache} example. */ -- cgit v0.12 From 572d57b255227f74c7ce61ab67476d4971955ea9 Mon Sep 17 00:00:00 2001 From: Jens Bache-Wiig Date: Thu, 14 May 2009 10:03:42 +0200 Subject: Fixes missing translations in QFileIconProvider While lupdate ignores ifdefs, it cannot handle ifdefs inside the translate statement itself. Task-number: 188337 Reviewed-by: janarve --- src/gui/itemviews/qfileiconprovider.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp index 9f33af3..054f4cf 100644 --- a/src/gui/itemviews/qfileiconprovider.cpp +++ b/src/gui/itemviews/qfileiconprovider.cpp @@ -416,26 +416,22 @@ QString QFileIconProvider::type(const QFileInfo &info) const } if (info.isDir()) - return QApplication::translate("QFileDialog", #ifdef Q_WS_WIN - "File Folder", "Match Windows Explorer" + return QApplication::translate("QFileDialog", "File Folder", "Match Windows Explorer"); #else - "Folder", "All other platforms" + return QApplication::translate("QFileDialog", "Folder", "All other platforms"); #endif - ); // Windows - "File Folder" // OS X - "Folder" // Konqueror - "Folder" // Nautilus - "folder" if (info.isSymLink()) - return QApplication::translate("QFileDialog", #ifdef Q_OS_MAC - "Alias", "Mac OS X Finder" + return QApplication::translate("QFileDialog", "Alias", "Mac OS X Finder"); #else - "Shortcut", "All other platforms" + return QApplication::translate("QFileDialog", "Shortcut", "All other platforms"); #endif - ); // OS X - "Alias" // Windows - "Shortcut" // Konqueror - "Folder" or "TXT File" i.e. what it is pointing to -- cgit v0.12 From ffecdf0bf9f25f7ab9aa4f69e37507dd595fecea Mon Sep 17 00:00:00 2001 From: Thomas Zander Date: Tue, 12 May 2009 14:18:58 +0200 Subject: Makes the layout of many of the areas be in aligned columns to immensely increase readability Unfortunately the patch causes quite some regressions and I think some refectoring of this class would be needed. I didn't do that since there is no API docs, the variable naming is not very clarifying and the code is hard to read due to it not using the coding style and mixing tabs as well as spaces. --- tools/qdoc3/htmlgenerator.cpp | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp index 13d52bf..7702628 100644 --- a/tools/qdoc3/htmlgenerator.cpp +++ b/tools/qdoc3/htmlgenerator.cpp @@ -2079,17 +2079,7 @@ void HtmlGenerator::generateSectionList(const Section& section, const Node *rela CodeMarker *marker, CodeMarker::SynopsisStyle style) { if (!section.members.isEmpty()) { - bool twoColumn = false; - if (style == CodeMarker::SeparateList) { - twoColumn = (section.members.count() >= 16); - } else if (section.members.first()->type() == Node::Property) { - twoColumn = (section.members.count() >= 5); - } - if (twoColumn) - out() << "

\n" - << "
"; - out() << "
    \n"; + out() << "\n"; int i = 0; NodeList::ConstIterator m = section.members.begin(); @@ -2099,22 +2089,17 @@ void HtmlGenerator::generateSectionList(const Section& section, const Node *rela continue; } - if (twoColumn && i == (int) (section.members.count() + 1) / 2) - out() << "\n"; i++; ++m; } - out() << "\n"; - if (twoColumn) - out() << "\n
      \n"; - - out() << "
    • "; + out() << "
    "; if (style == CodeMarker::Accessors) out() << ""; generateSynopsis(*m, relative, marker, style); if (style == CodeMarker::Accessors) out() << ""; - out() << "\n"; + out() << "

    \n"; + out() << "
\n"; } if (style == CodeMarker::Summary && !section.inherited.isEmpty()) { @@ -2129,7 +2114,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section, const N { QList >::ConstIterator p = section.inherited.begin(); while (p != section.inherited.end()) { - out() << "
  • "; + out() << "
  • "; out() << (*p).second << " "; if ((*p).second == 1) { out() << section.singularMember; @@ -2425,7 +2410,9 @@ QString HtmlGenerator::highlightedCode(const QString& markedCode, // replace all <@link> tags: "(<@link node=\"([^\"]+)\">).*()" static const QString linkTag("link"); for (int i = 0, n = src.size(); i < n;) { - if (src.at(i) == charLangle && src.at(i + 1) == charAt) { + if (src.at(i) == charLangle && src.at(i + 1).unicode() == '@') { + if (i != 0) + html += " "; i += 2; if (parseArg(src, linkTag, &i, n, &arg, &par1)) { QString link = linkForNode( -- cgit v0.12 From 8a97b3b9e506580b4a89c1277068b274794a858c Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Thu, 14 May 2009 10:37:37 +0200 Subject: Sheets misbehaviour on Carbon - Mac OS X Seems like some old legacy code was left behind when sheets behaved as application modal. This is not the case anymore, so this patch just removes the special case code for enforcing the old behaviour, and let carbon do the correct thing instead. Task-number: 252379 Reviewed-by: Trenton Schulz --- src/gui/kernel/qwidget_mac.mm | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index b315eaf..0e021dc 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -786,16 +786,6 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event, // By also setting the current modal window back into the event, we // help Carbon determining which window is supposed to be raised. handled_event = qApp->activePopupWidget() ? true : false; - QWidget *top = 0; - if (!QApplicationPrivate::tryModalHelper(widget, &top) && top && top != widget){ - if(!qt_mac_is_macsheet(top) || top->parentWidget() != widget) { - handled_event = true; - WindowPtr topWindowRef = qt_mac_window_for(top); - SetEventParameter(event, kEventParamModalWindow, typeWindowRef, sizeof(topWindowRef), &topWindowRef); - HIModalClickResult clickResult = kHIModalClickIsModal; - SetEventParameter(event, kEventParamModalClickResult, typeModalClickResult, sizeof(clickResult), &clickResult); - } - } #endif } else if(ekind == kEventWindowClose) { widget->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); -- cgit v0.12 From 8a0272a37aa44ed7583cce40eeff1b030c07741e Mon Sep 17 00:00:00 2001 From: Norwegian Rock Cat Date: Thu, 14 May 2009 10:57:22 +0200 Subject: Small updates to the .hgignore file. This is handy in cases where you are maybe using something like the hg-git extension in Mercurial or just storing release in Mercurial for patch queues or what have you. --- .hgignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.hgignore b/.hgignore index 784d507..eb6ff05 100755 --- a/.hgignore +++ b/.hgignore @@ -5,6 +5,8 @@ syntax: glob *~ *.a +*.la +*.pc *.core *.moc *.o @@ -45,7 +47,9 @@ bin/rcc* bin/uic* bin/qcollectiongenerator bin/qhelpgenerator +bin/macdeployqt tools/qdoc3/qdoc3* +tools/macdeployqt/macchangeqt/macchangeqt #configure.cache mkspecs/default mkspecs/qconfig.pri -- cgit v0.12 From e7ea80161aa91369cf700b79e96e97367ecf0ff6 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 14 May 2009 11:03:35 +0200 Subject: Fix Toolbutton font with pseudo-states So now QToolButton:pressed {text-decoration: underline} will works The change in QCommonStyle is to make it consistant with the setFont few lines later. Reveiwed-by: jbache --- src/gui/styles/qcommonstyle.cpp | 1 + src/gui/styles/qstylesheetstyle.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp index c0899f8..6972803 100644 --- a/src/gui/styles/qcommonstyle.cpp +++ b/src/gui/styles/qcommonstyle.cpp @@ -1664,6 +1664,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, if (!styleHint(SH_UnderlineShortcut, opt, widget)) alignment |= Qt::TextHideMnemonic; rect.translate(shiftX, shiftY); + p->setFont(toolbutton->font); drawItemText(p, rect, alignment, toolbutton->palette, opt->state & State_Enabled, toolbutton->text, QPalette::ButtonText); diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp index dcc11b8..cd44bfd 100644 --- a/src/gui/styles/qstylesheetstyle.cpp +++ b/src/gui/styles/qstylesheetstyle.cpp @@ -3030,6 +3030,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC if (const QStyleOptionToolButton *tool = qstyleoption_cast(opt)) { QStyleOptionToolButton toolOpt(*tool); rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button); + toolOpt.font = rule.font.resolve(toolOpt.font); toolOpt.rect = rule.borderRect(opt->rect); bool customArrow = (tool->features & (QStyleOptionToolButton::HasMenu | QStyleOptionToolButton::MenuButtonPopup)); bool customDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup; -- cgit v0.12 From cf9277b5e9e20d47681ab084e4410c3566425c3c Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 14 May 2009 11:19:46 +0200 Subject: Remove useless code and comment in QTreeView In 8cd19116ae81c99fe28fbf91aa7f4c1c08163fe0 we changed viewItems to always contains the index to the columns 0, even if this columns is hidden. So this code and comment are now useless. --- src/gui/itemviews/qtreeview.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index f6c5cf0..d742698 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -3086,10 +3086,6 @@ void QTreeViewPrivate::layout(int i) Q_Q(QTreeView); QModelIndex current; QModelIndex parent = (i < 0) ? (QModelIndex)root : modelIndex(i); - // modelIndex() will return an index that don't have a parent if column 0 is hidden, - // so we must make sure that parent points to the actual parent that has children. - if (parent != root) - parent = model->index(parent.row(), 0, parent.parent()); if (i>=0 && !parent.isValid()) { //modelIndex() should never return something invalid for the real items. -- cgit v0.12 From 5db3e40ca796f29cbd7bfc5f7f88823f6e27c16f Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Thu, 14 May 2009 11:04:42 +0200 Subject: Fix sending of double-click events after explicit grab-ungrab. The bug report came from the Declarative UI project as part of Kinetic. In FxFlickable the mouse is explicitly grabbed inside the mouse press event handler, and it's (explicitly) released in the release handler. When doing this, lastMouseGrabber is 0, and the double-click is delivered as a press. The fix is to not convert the double-click to a press if the receiver is the first and only mouse grabber (i.e., lastMouseGrabber is 0). The fix isn't entirely correct, as it can in theory allow an item to receive a double-click event as the first received event. This seems to only be possible in the case of using explicit mouse grabbing in combinations