summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/unix/neon/neon.cpp51
-rw-r--r--config.tests/unix/neon/neon.pro2
-rwxr-xr-xconfigure22
-rw-r--r--src/corelib/thread/qthread_p.h2
-rw-r--r--src/corelib/thread/qthreadstorage.cpp97
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp19
-rw-r--r--src/gui/image/qpixmap.cpp9
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp33
-rw-r--r--src/gui/painting/painting.pri7
-rw-r--r--src/gui/painting/qblendfunctions.cpp2
-rw-r--r--src/gui/painting/qdrawhelper.cpp16
-rw-r--r--src/gui/painting/qdrawhelper_neon.cpp260
-rw-r--r--src/gui/painting/qdrawhelper_neon_p.h76
-rw-r--r--src/gui/util/qsystemtrayicon_p.h1
-rw-r--r--tests/auto/headers/tst_headers.cpp4
-rw-r--r--tests/auto/modeltest/dynamictreemodel.cpp (renamed from tests/auto/qabstractitemmodel/dynamictreemodel.cpp)0
-rw-r--r--tests/auto/modeltest/dynamictreemodel.h (renamed from tests/auto/qabstractitemmodel/dynamictreemodel.h)0
-rw-r--r--tests/auto/modeltest/modeltest.cpp20
-rw-r--r--tests/auto/modeltest/modeltest.pro4
-rw-r--r--tests/auto/modeltest/tst_modeltest.cpp157
-rw-r--r--tests/auto/qabstractitemmodel/qabstractitemmodel.pro7
-rw-r--r--tests/auto/qgraphicsview/tst_qgraphicsview.cpp97
-rw-r--r--tests/benchmarks/benchmarks.pro3
-rw-r--r--tests/benchmarks/qthreadstorage/qthreadstorage.pro6
-rw-r--r--tests/benchmarks/qthreadstorage/tst_qthreadstorage.cpp124
25 files changed, 928 insertions, 91 deletions
diff --git a/config.tests/unix/neon/neon.cpp b/config.tests/unix/neon/neon.cpp
new file mode 100644
index 0000000..c31a9fd
--- /dev/null
+++ b/config.tests/unix/neon/neon.cpp
@@ -0,0 +1,51 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <arm_neon.h>
+
+int main(int, char**)
+{
+ int32x4_t null = vdupq_n_s32(0x0);
+
+ int result;
+ vst1q_lane_s32(&result, null, 0);
+ return result;
+}
diff --git a/config.tests/unix/neon/neon.pro b/config.tests/unix/neon/neon.pro
new file mode 100644
index 0000000..de20c4e
--- /dev/null
+++ b/config.tests/unix/neon/neon.pro
@@ -0,0 +1,2 @@
+SOURCES = neon.cpp
+CONFIG -= x11 qt
diff --git a/configure b/configure
index 2114863..22e6bd4 100755
--- a/configure
+++ b/configure
@@ -745,6 +745,7 @@ CFG_HOST_ENDIAN=auto
CFG_DOUBLEFORMAT=auto
CFG_ARMFPA=auto
CFG_IWMMXT=no
+CFG_NEON=auto
CFG_CLOCK_GETTIME=auto
CFG_CLOCK_MONOTONIC=auto
CFG_MREMAP=auto
@@ -1604,6 +1605,13 @@ while [ "$#" -gt 0 ]; do
iwmmxt)
CFG_IWMMXT="yes"
;;
+ neon)
+ if [ "$VAL" = "no" ]; then
+ CFG_NEON="$VAL"
+ else
+ UNKNOWN_OPT=yes
+ fi
+ ;;
reduce-relocations)
if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ]; then
CFG_REDUCE_RELOCATIONS="$VAL"
@@ -3889,6 +3897,7 @@ Qt for Embedded Linux only:
-iwmmxt ............ Compile using the iWMMXt instruction set
(available on some XScale CPUs).
+ -no-neon ........... Do not compile with use of NEON instructions.
EOF
fi
@@ -4509,6 +4518,15 @@ if [ "$CFG_IWMMXT" = "yes" ]; then
fi
fi
+# detect neon support
+if ([ "$CFG_ARCH" = "arm" ] || [ "$CFG_ARCH" = "armv6" ]) && [ "${CFG_NEON}" = "auto" ]; then
+ if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/neon "neon" $L_FLAGS $I_FLAGS $l_FLAGS "-mfpu=neon"; then
+ CFG_NEON=yes
+ else
+ CFG_NEON=no
+ fi
+fi
+
# detect zlib
if [ "$CFG_ZLIB" = "no" ]; then
# Note: Qt no longer support builds without zlib
@@ -6124,6 +6142,7 @@ fi
[ "$CFG_SSE" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse"
[ "$CFG_SSE2" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG sse2"
[ "$CFG_IWMMXT" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG iwmmxt"
+[ "$CFG_NEON" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG neon"
[ "$PLATFORM_MAC" = "yes" ] && QMAKE_CONFIG="$QMAKE_CONFIG $CFG_MAC_ARCHS"
if [ "$CFG_IPV6" = "yes" ]; then
QT_CONFIG="$QT_CONFIG ipv6"
@@ -7416,8 +7435,9 @@ echo "Declarative module .. $CFG_DECLARATIVE"
echo "STL support ......... $CFG_STL"
echo "PCH support ......... $CFG_PRECOMPILE"
echo "MMX/3DNOW/SSE/SSE2.. ${CFG_MMX}/${CFG_3DNOW}/${CFG_SSE}/${CFG_SSE2}"
-if [ "${CFG_ARCH}" = "arm" ]; then
+if [ "$CFG_ARCH" = "arm" ] || [ "$CFG_ARCH" = "armv6" ]; then
echo "iWMMXt support ...... ${CFG_IWMMXT}"
+ echo "NEON support ........ ${CFG_NEON}"
fi
[ "${PLATFORM_QWS}" != "yes" ] && echo "Graphics System ..... $CFG_GRAPHICS_SYSTEM"
echo "IPv6 support ........ $CFG_IPV6"
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index af68434..3db308f 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -202,7 +202,7 @@ public:
QStack<QEventLoop *> eventLoops;
QPostEventList postEventList;
bool canWait;
- QMap<int, void *> tls;
+ QVector<void *> tls;
QMutex mutex;
diff --git a/src/corelib/thread/qthreadstorage.cpp b/src/corelib/thread/qthreadstorage.cpp
index 8b1f255..a7d53d0 100644
--- a/src/corelib/thread/qthreadstorage.cpp
+++ b/src/corelib/thread/qthreadstorage.cpp
@@ -71,27 +71,32 @@ void qtsDebug(const char *fmt, ...)
# define DEBUG_MSG if(false)qDebug
#endif
-static QBasicAtomicInt idCounter = Q_BASIC_ATOMIC_INITIALIZER(INT_MAX);
Q_GLOBAL_STATIC(QMutex, mutex)
-typedef QMap<int, void (*)(void *)> DestructorMap;
+typedef QVector<void (*)(void *)> DestructorMap;
Q_GLOBAL_STATIC(DestructorMap, destructors)
QThreadStorageData::QThreadStorageData(void (*func)(void *))
- : id(idCounter.fetchAndAddRelaxed(-1))
{
QMutexLocker locker(mutex());
- destructors()->insert(id, func);
-
+ DestructorMap *destr = destructors();
+ for (id = 0; id < destr->count(); id++) {
+ if (destr->at(id) == 0)
+ break;
+ }
+ if (id == destr->count()) {
+ destr->append(func);
+ } else {
+ (*destr)[id] = func;
+ }
DEBUG_MSG("QThreadStorageData: Allocated id %d, destructor %p", id, func);
}
QThreadStorageData::~QThreadStorageData()
{
+ DEBUG_MSG("QThreadStorageData: Released id %d", id);
QMutexLocker locker(mutex());
if (destructors())
- destructors()->remove(id);
-
- DEBUG_MSG("QThreadStorageData: Released id %d", id);
+ (*destructors())[id] = 0;
}
void **QThreadStorageData::get() const
@@ -101,14 +106,17 @@ void **QThreadStorageData::get() const
qWarning("QThreadStorage::get: QThreadStorage can only be used with threads started with QThread");
return 0;
}
- QMap<int, void *>::const_iterator it = data->tls.constFind(id);
+ QVector<void *> &tls = data->tls;
+ if (tls.size() <= id)
+ tls.resize(id + 1);
+ void **v = &tls[id];
+
DEBUG_MSG("QThreadStorageData: Returning storage %d, data %p, for thread %p",
id,
- it != data->tls.end() ? it.value() : 0,
+ *v,
data->thread);
- // const_cast below is a bit evil - but we have to make sure not to detach here
- // otherwise we'll go bonkers in oom situations
- return it != data->tls.constEnd() && it.value() != 0 ? const_cast<void **>(&it.value()) : 0;
+
+ return *v ? v : 0;
}
void **QThreadStorageData::set(void *p)
@@ -118,51 +126,46 @@ void **QThreadStorageData::set(void *p)
qWarning("QThreadStorage::set: QThreadStorage can only be used with threads started with QThread");
return 0;
}
+ QVector<void *> &tls = data->tls;
+ if (tls.size() <= id)
+ tls.resize(id + 1);
+
+ void *&value = tls[id];
+ // delete any previous data
+ if (value != 0) {
+ DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p",
+ id,
+ value,
+ data->thread);
- QMap<int, void *>::iterator it = data->tls.find(id);
- if (it != data->tls.end()) {
- // delete any previous data
- if (it.value() != 0) {
- DEBUG_MSG("QThreadStorageData: Deleting previous storage %d, data %p, for thread %p",
- id,
- it.value(),
- data->thread);
-
- void *q = it.value();
- it.value() = 0;
-
- QMutexLocker locker(mutex());
- void (*destructor)(void *) = destructors()->value(id);
- locker.unlock();
+ QMutexLocker locker(mutex());
+ void (*destructor)(void *) = destructors()->value(id);
+ locker.unlock();
- destructor(q);
- }
+ void *q = value;
+ value = 0;
- // store new data
- it.value() = p;
- DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p);
- } else {
- it = data->tls.insert(id, p);
- DEBUG_MSG("QThreadStorageData: Inserted storage %d, data %p, for thread %p", id, p, data->thread);
+ destructor(q);
}
- return &it.value();
+ // store new data
+ value = p;
+ DEBUG_MSG("QThreadStorageData: Set storage %d for thread %p to %p", id, data->thread, p);
+ return &value;
}
void QThreadStorageData::finish(void **p)
{
- QMap<int, void *> *tls = reinterpret_cast<QMap<int, void *> *>(p);
+ QVector<void *> *tls = reinterpret_cast<QVector<void *> *>(p);
if (!tls || tls->isEmpty() || !mutex())
return; // nothing to do
DEBUG_MSG("QThreadStorageData: Destroying storage for thread %p", QThread::currentThread());
- QMap<int, void *>::iterator it = tls->begin();
- while (it != tls->end()) {
- int id = it.key();
- void *q = it.value();
- it.value() = 0;
- ++it;
+ for(int i = tls->size() - 1; i >= 0; i--) {
+ void *&value = (*tls)[i];
+ void *q = value;
+ value = 0;
if (!q) {
// data already deleted
@@ -170,16 +173,16 @@ void QThreadStorageData::finish(void **p)
}
QMutexLocker locker(mutex());
- void (*destructor)(void *) = destructors()->value(id);
+ void (*destructor)(void *) = destructors()->value(i);
locker.unlock();
if (!destructor) {
if (QThread::currentThread())
qWarning("QThreadStorage: Thread %p exited after QThreadStorage %d destroyed",
- QThread::currentThread(), id);
+ QThread::currentThread(), i);
continue;
}
- destructor(q);
+ destructor(q); //crash here might mean the thread exited after qthreadstorage was destroyed
}
tls->clear();
}
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index ffe64aa..3bb40fb 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -1208,6 +1208,11 @@ void QGraphicsView::setTransformationAnchor(ViewportAnchor anchor)
{
Q_D(QGraphicsView);
d->transformationAnchor = anchor;
+
+ // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse
+ // in order to have up-to-date information for centering the view.
+ if (d->transformationAnchor == AnchorUnderMouse)
+ d->viewport->setMouseTracking(true);
}
/*!
@@ -1235,6 +1240,11 @@ void QGraphicsView::setResizeAnchor(ViewportAnchor anchor)
{
Q_D(QGraphicsView);
d->resizeAnchor = anchor;
+
+ // Ensure mouse tracking is enabled in the case we are using AnchorUnderMouse
+ // in order to have up-to-date information for centering the view.
+ if (d->resizeAnchor == AnchorUnderMouse)
+ d->viewport->setMouseTracking(true);
}
/*!
@@ -2597,9 +2607,12 @@ void QGraphicsView::setupViewport(QWidget *widget)
}
// We are only interested in mouse tracking if items
- // accept hover events or use non-default cursors.
- if (d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
- || !d->scene->d_func()->allItemsUseDefaultCursor)) {
+ // accept hover events or use non-default cursors or if
+ // AnchorUnderMouse is used as transformation or resize anchor.
+ if ((d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
+ || !d->scene->d_func()->allItemsUseDefaultCursor))
+ || d->transformationAnchor == AnchorUnderMouse
+ || d->resizeAnchor == AnchorUnderMouse) {
widget->setMouseTracking(true);
}
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 617cfe5..7e4597e 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -831,14 +831,13 @@ bool QPixmap::load(const QString &fileName, const char *format, Qt::ImageConvers
if (QPixmapCache::find(key, *this))
return true;
- if (!data)
- data = QPixmapData::create(0, 0, QPixmapData::PixmapType);
-
- if (data->fromFile(fileName, format, flags)) {
+ QPixmapData *tmp = QPixmapData::create(0, 0, QPixmapData::PixmapType);
+ if (tmp->fromFile(fileName, format, flags)) {
+ data = tmp;
QPixmapCache::insert(key, *this);
return true;
}
-
+ delete tmp;
return false;
}
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index fc82f30..646a3a1 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -734,6 +734,33 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
}
}
+ if (model->rowCount(source_parent) == delta_item_count) {
+ // Items were inserted where there were none before.
+ // If it was new rows make sure to create mappings for columns so that a
+ // valid mapping can be retreived later and vice-versa.
+
+ QVector<int> &orthogonal_proxy_to_source = (orient == Qt::Horizontal) ? m->source_rows : m->source_columns;
+ QVector<int> &orthogonal_source_to_proxy = (orient == Qt::Horizontal) ? m->proxy_rows : m->proxy_columns;
+
+ if (orthogonal_source_to_proxy.isEmpty()) {
+ const int ortho_end = (orient == Qt::Horizontal) ? model->rowCount(source_parent) : model->columnCount(source_parent);
+
+ for (int ortho_item = 0; ortho_item < ortho_end; ++ortho_item) {
+ if ((orient == Qt::Horizontal) ? q->filterAcceptsRow(ortho_item, source_parent)
+ : q->filterAcceptsColumn(ortho_item, source_parent)) {
+ orthogonal_proxy_to_source.append(ortho_item);
+ }
+ }
+ orthogonal_source_to_proxy.resize(orthogonal_proxy_to_source.size());
+
+ if (orient == Qt::Horizontal) {
+ // We're reacting to columnsInserted, but we've just inserted new rows. Sort them.
+ sort_source_rows(orthogonal_proxy_to_source, source_parent);
+ }
+ build_source_to_proxy_mapping(orthogonal_proxy_to_source, orthogonal_source_to_proxy);
+ }
+ }
+
// Sort and insert the items
if (orient == Qt::Vertical) // Only sort rows
sort_source_rows(source_items, source_parent);
@@ -1171,9 +1198,10 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged()
{
Q_Q(QSortFilterProxyModel);
saved_persistent_indexes.clear();
+ emit q->layoutAboutToBeChanged();
if (persistent.indexes.isEmpty())
return;
- emit q->layoutAboutToBeChanged();
+
saved_persistent_indexes = store_persistent_indexes();
}
@@ -1181,7 +1209,8 @@ void QSortFilterProxyModelPrivate::_q_sourceLayoutChanged()
{
Q_Q(QSortFilterProxyModel);
if (saved_persistent_indexes.isEmpty()) {
- q->invalidate();
+ clear_mapping();
+ emit q->layoutChanged();
return;
}
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 628a109..0b1e79a 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -379,6 +379,13 @@ symbian {
QMAKE_CXXFLAGS.ARMCC *= -O3
}
+neon {
+ DEFINES += QT_HAVE_NEON
+ HEADERS += painting/qdrawhelper_neon_p.h
+ SOURCES += painting/qdrawhelper_neon.cpp
+ QMAKE.CXXFLAGS *= -mfpu=neon
+}
+
contains(QT_CONFIG, zlib) {
INCLUDEPATH += ../3rdparty/zlib
} else:!contains(QT_CONFIG, no-zlib) {
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 1d15dac..81d1515 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -605,7 +605,7 @@ static void qt_blend_argb32_on_argb32(uchar *destPixels, int dbpl,
}
-static void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
+void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
int w, int h,
int const_alpha)
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 23236ec..84cf5cc 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -44,6 +44,7 @@
#include <private/qpainter_p.h>
#include <private/qdrawhelper_x86_p.h>
#include <private/qdrawhelper_armv6_p.h>
+#include <private/qdrawhelper_neon_p.h>
#include <private/qmath_p.h>
#include <qmath.h>
@@ -7725,7 +7726,8 @@ enum CPUFeatures {
SSE = 0x10,
SSE2 = 0x20,
CMOV = 0x40,
- IWMMXT = 0x80
+ IWMMXT = 0x80,
+ NEON = 0x100
};
static uint detectCPUFeatures()
@@ -7751,6 +7753,9 @@ static uint detectCPUFeatures()
// runtime detection only available when running as a previlegied process
static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
return doIWMMXT ? IWMMXT : 0;
+#elif defined(QT_HAVE_NEON)
+ static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
+ return doNEON ? NEON : 0;
#else
uint features = 0;
#if defined(__x86_64__) || defined(Q_OS_WIN64)
@@ -8122,7 +8127,14 @@ void qInitDrawhelperAsm()
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_armv6;
qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_armv6;
-#endif // Q_CC_RVCT && QT_HAVE_ARMV6
+#elif defined(QT_HAVE_NEON)
+ if (features & NEON) {
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon;
+ }
+#endif
if (functionForModeSolidAsm) {
const int destinationMode = QPainter::CompositionMode_Destination;
diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp
new file mode 100644
index 0000000..7fe11bf
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_neon.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qdrawhelper_p.h>
+
+#ifdef QT_HAVE_NEON
+
+#include <private/qdrawhelper_neon_p.h>
+#include <arm_neon.h>
+
+QT_BEGIN_NAMESPACE
+
+static inline int16x8_t qvdiv_255_s16(int16x8_t x, int16x8_t half)
+{
+ // result = (x + (x >> 8) + 0x80) >> 8
+
+ const int16x8_t temp = vshrq_n_s16(x, 8); // x >> 8
+ const int16x8_t sum_part = vaddq_s16(x, half); // x + 0x80
+ const int16x8_t sum = vaddq_s16(temp, sum_part);
+
+ return vreinterpretq_s16_u16(vshrq_n_u16(vreinterpretq_u16_s16(sum), 8));
+}
+
+static inline int16x8_t qvbyte_mul_s16(int16x8_t x, int16x8_t alpha, int16x8_t half)
+{
+ // t = qRound(x * alpha / 255.0)
+
+ const int16x8_t t = vmulq_s16(x, alpha); // t
+ return qvdiv_255_s16(t, half);
+}
+
+static inline int16x8_t qvinterpolate_pixel_255(int16x8_t x, int16x8_t a, int16x8_t y, int16x8_t b, int16x8_t half)
+{
+ // t = x * a + y * b
+
+ const int16x8_t ta = vmulq_s16(x, a);
+ const int16x8_t tb = vmulq_s16(y, b);
+
+ return qvdiv_255_s16(vaddq_s16(ta, tb), half);
+}
+
+static inline int16x8_t qvsource_over_s16(int16x8_t src16, int16x8_t dst16, int16x8_t half, int16x8_t full)
+{
+ const int16x4_t alpha16_high = vdup_lane_s16(vget_high_s16(src16), 3);
+ const int16x4_t alpha16_low = vdup_lane_s16(vget_low_s16(src16), 3);
+
+ const int16x8_t alpha16 = vsubq_s16(full, vcombine_s16(alpha16_low, alpha16_high));
+
+ return vaddq_s16(src16, qvbyte_mul_s16(dst16, alpha16, half));
+}
+
+void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ int16x8_t half = vdupq_n_s16(0x80);
+ int16x8_t full = vdupq_n_s16(0xff);
+ if (const_alpha == 256) {
+ for (int y = 0; y < h; ++y) {
+ int x = 0;
+ for (; x < w-3; x += 4) {
+ int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
+ if ((src[x] & src[x+1] & src[x+2] & src[x+3]) >= 0xff000000) {
+ // all opaque
+ vst1q_s32((int32_t *)&dst[x], src32);
+ } else if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
+ int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
+
+ const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
+ const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
+
+ const uint8x8_t src8_low = vget_low_u8(src8);
+ const uint8x8_t dst8_low = vget_low_u8(dst8);
+
+ const uint8x8_t src8_high = vget_high_u8(src8);
+ const uint8x8_t dst8_high = vget_high_u8(dst8);
+
+ const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
+ const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
+
+ const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
+ const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
+
+ const int16x8_t result16_low = qvsource_over_s16(src16_low, dst16_low, half, full);
+ const int16x8_t result16_high = qvsource_over_s16(src16_high, dst16_high, half, full);
+
+ const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
+ const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
+
+ vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
+ }
+ }
+ for (; x<w; ++x) {
+ uint s = src[x];
+ if (s >= 0xff000000)
+ dst[x] = s;
+ else if (s != 0)
+ dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ } else if (const_alpha != 0) {
+ const_alpha = (const_alpha * 255) >> 8;
+ int16x8_t const_alpha16 = vdupq_n_s16(const_alpha);
+ for (int y = 0; y < h; ++y) {
+ int x = 0;
+ for (; x < w-3; x += 4) {
+ if (src[x] | src[x+1] | src[x+2] | src[x+3]) {
+ int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
+ int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
+
+ const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
+ const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
+
+ const uint8x8_t src8_low = vget_low_u8(src8);
+ const uint8x8_t dst8_low = vget_low_u8(dst8);
+
+ const uint8x8_t src8_high = vget_high_u8(src8);
+ const uint8x8_t dst8_high = vget_high_u8(dst8);
+
+ const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
+ const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
+
+ const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
+ const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
+
+ const int16x8_t srcalpha16_low = qvbyte_mul_s16(src16_low, const_alpha16, half);
+ const int16x8_t srcalpha16_high = qvbyte_mul_s16(src16_high, const_alpha16, half);
+
+ const int16x8_t result16_low = qvsource_over_s16(srcalpha16_low, dst16_low, half, full);
+ const int16x8_t result16_high = qvsource_over_s16(srcalpha16_high, dst16_high, half, full);
+
+ const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
+ const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
+
+ vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
+ }
+ }
+ for (; x<w; ++x) {
+ uint s = src[x];
+ if (s != 0) {
+ s = BYTE_MUL(s, const_alpha);
+ dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
+ }
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ }
+}
+
+// qblendfunctions.cpp
+void qt_blend_rgb32_on_rgb32(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
+{
+ if (const_alpha != 256) {
+ if (const_alpha != 0) {
+ const uint *src = (const uint *) srcPixels;
+ uint *dst = (uint *) destPixels;
+ int16x8_t half = vdupq_n_s16(0x80);
+ const_alpha = (const_alpha * 255) >> 8;
+ int one_minus_const_alpha = 255 - const_alpha;
+ int16x8_t const_alpha16 = vdupq_n_s16(const_alpha);
+ int16x8_t one_minus_const_alpha16 = vdupq_n_s16(255 - const_alpha);
+ for (int y = 0; y < h; ++y) {
+ int x = 0;
+ for (; x < w-3; x += 4) {
+ int32x4_t src32 = vld1q_s32((int32_t *)&src[x]);
+ int32x4_t dst32 = vld1q_s32((int32_t *)&dst[x]);
+
+ const uint8x16_t src8 = vreinterpretq_u8_s32(src32);
+ const uint8x16_t dst8 = vreinterpretq_u8_s32(dst32);
+
+ const uint8x8_t src8_low = vget_low_u8(src8);
+ const uint8x8_t dst8_low = vget_low_u8(dst8);
+
+ const uint8x8_t src8_high = vget_high_u8(src8);
+ const uint8x8_t dst8_high = vget_high_u8(dst8);
+
+ const int16x8_t src16_low = vreinterpretq_s16_u16(vmovl_u8(src8_low));
+ const int16x8_t dst16_low = vreinterpretq_s16_u16(vmovl_u8(dst8_low));
+
+ const int16x8_t src16_high = vreinterpretq_s16_u16(vmovl_u8(src8_high));
+ const int16x8_t dst16_high = vreinterpretq_s16_u16(vmovl_u8(dst8_high));
+
+ const int16x8_t result16_low = qvinterpolate_pixel_255(src16_low, const_alpha16, dst16_low, one_minus_const_alpha16, half);
+ const int16x8_t result16_high = qvinterpolate_pixel_255(src16_high, const_alpha16, dst16_high, one_minus_const_alpha16, half);
+
+ const int32x2_t result32_low = vreinterpret_s32_s8(vmovn_s16(result16_low));
+ const int32x2_t result32_high = vreinterpret_s32_s8(vmovn_s16(result16_high));
+
+ vst1q_s32((int32_t *)&dst[x], vcombine_s32(result32_low, result32_high));
+ }
+ for (; x<w; ++x) {
+ uint s = src[x];
+ s = BYTE_MUL(s, const_alpha);
+ dst[x] = INTERPOLATE_PIXEL_255(src[x], const_alpha, dst[x], one_minus_const_alpha);
+ }
+ dst = (quint32 *)(((uchar *) dst) + dbpl);
+ src = (const quint32 *)(((const uchar *) src) + sbpl);
+ }
+ }
+ } else {
+ qt_blend_rgb32_on_rgb32(destPixels, dbpl, srcPixels, sbpl, w, h, const_alpha);
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_HAVE_NEON
+
diff --git a/src/gui/painting/qdrawhelper_neon_p.h b/src/gui/painting/qdrawhelper_neon_p.h
new file mode 100644
index 0000000..cb9a0d6
--- /dev/null
+++ b/src/gui/painting/qdrawhelper_neon_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDRAWHELPER_NEON_P_H
+#define QDRAWHELPER_NEON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qdrawhelper_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_HAVE_NEON
+
+void qt_blend_argb32_on_argb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+void qt_blend_rgb32_on_rgb32_neon(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha);
+
+#endif // QT_HAVE_NEON
+
+QT_END_NAMESPACE
+
+#endif // QDRAWHELPER_NEON_P_H
diff --git a/src/gui/util/qsystemtrayicon_p.h b/src/gui/util/qsystemtrayicon_p.h
index 86de366..029a259 100644
--- a/src/gui/util/qsystemtrayicon_p.h
+++ b/src/gui/util/qsystemtrayicon_p.h
@@ -94,6 +94,7 @@ public:
class QBalloonTip : public QWidget
{
+ Q_OBJECT
public:
static void showBalloon(QSystemTrayIcon::MessageIcon icon, const QString& title,
const QString& msg, QSystemTrayIcon *trayIcon,
diff --git a/tests/auto/headers/tst_headers.cpp b/tests/auto/headers/tst_headers.cpp
index 36d25fe..329143d 100644
--- a/tests/auto/headers/tst_headers.cpp
+++ b/tests/auto/headers/tst_headers.cpp
@@ -217,8 +217,8 @@ void tst_Headers::licenseCheck()
QCOMPARE(content.at(i++), QString("/****************************************************************************"));
if (licenseType != "3RDPARTY") {
QCOMPARE(content.at(i++), QString("**"));
- if (sourceFile.endsWith("/tests/auto/qabstractitemmodel/dynamictreemodel.cpp")
- || sourceFile.endsWith("/tests/auto/qabstractitemmodel/dynamictreemodel.h")
+ if (sourceFile.endsWith("/tests/auto/modeltest/dynamictreemodel.cpp")
+ || sourceFile.endsWith("/tests/auto/modeltest/dynamictreemodel.h")
|| sourceFile.endsWith("/src/network/kernel/qnetworkproxy_p.h"))
{
// These files are not copyrighted by Nokia.
diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.cpp b/tests/auto/modeltest/dynamictreemodel.cpp
index 24d3ab3..24d3ab3 100644
--- a/tests/auto/qabstractitemmodel/dynamictreemodel.cpp
+++ b/tests/auto/modeltest/dynamictreemodel.cpp
diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.h b/tests/auto/modeltest/dynamictreemodel.h
index 3f0d90d..3f0d90d 100644
--- a/tests/auto/qabstractitemmodel/dynamictreemodel.h
+++ b/tests/auto/modeltest/dynamictreemodel.h
diff --git a/tests/auto/modeltest/modeltest.cpp b/tests/auto/modeltest/modeltest.cpp
index 39d00f6..0ca9e14 100644
--- a/tests/auto/modeltest/modeltest.cpp
+++ b/tests/auto/modeltest/modeltest.cpp
@@ -475,8 +475,8 @@ void ModelTest::data()
void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end )
{
// Q_UNUSED(end);
- qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
- << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
+// qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
+// << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
// qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
Changing c;
c.parent = parent;
@@ -495,14 +495,14 @@ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
{
Changing c = insert.pop();
Q_ASSERT ( c.parent == parent );
- qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
- << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent );
-
- for (int ii=start; ii <= end; ii++)
- {
- qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent ));
- }
- qDebug();
+// qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
+// << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent );
+
+// for (int ii=start; ii <= end; ii++)
+// {
+// qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent ));
+// }
+// qDebug();
Q_ASSERT ( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) );
Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
diff --git a/tests/auto/modeltest/modeltest.pro b/tests/auto/modeltest/modeltest.pro
index 6655d85..f157da0 100644
--- a/tests/auto/modeltest/modeltest.pro
+++ b/tests/auto/modeltest/modeltest.pro
@@ -1,6 +1,6 @@
load(qttest_p4)
-SOURCES += tst_modeltest.cpp modeltest.cpp
-HEADERS += modeltest.h
+SOURCES += tst_modeltest.cpp modeltest.cpp dynamictreemodel.cpp
+HEADERS += modeltest.h dynamictreemodel.h
diff --git a/tests/auto/modeltest/tst_modeltest.cpp b/tests/auto/modeltest/tst_modeltest.cpp
index a719168..262b966 100644
--- a/tests/auto/modeltest/tst_modeltest.cpp
+++ b/tests/auto/modeltest/tst_modeltest.cpp
@@ -44,6 +44,7 @@
#include <QtGui/QtGui>
#include "modeltest.h"
+#include "dynamictreemodel.h"
class tst_ModelTest : public QObject
@@ -64,6 +65,8 @@ private slots:
void stringListModel();
void treeWidgetModel();
void standardItemModel();
+ void testInsertThroughProxy();
+ void moveSourceItems();
};
@@ -92,15 +95,15 @@ void tst_ModelTest::stringListModel()
{
QStringListModel model;
QSortFilterProxyModel proxy;
-
+
ModelTest t1(&model);
ModelTest t2(&proxy);
-
+
proxy.setSourceModel(&model);
-
+
model.setStringList(QStringList() << "2" << "3" << "1");
model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c" );
-
+
proxy.setDynamicSortFilter(true);
proxy.setFilterRegExp(QRegExp("[^b]"));
}
@@ -110,7 +113,7 @@ void tst_ModelTest::treeWidgetModel()
QTreeWidget widget;
ModelTest t1(widget.model());
-
+
QTreeWidgetItem *root = new QTreeWidgetItem(&widget, QStringList("root"));
for (int i = 0; i < 20; ++i) {
new QTreeWidgetItem(root, QStringList(QString::number(i)));
@@ -120,7 +123,7 @@ void tst_ModelTest::treeWidgetModel()
QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent"));
new QTreeWidgetItem(parent, QStringList("child"));
widget.setItemHidden(parent, true);
-
+
widget.sortByColumn(0);
}
@@ -128,23 +131,153 @@ void tst_ModelTest::standardItemModel()
{
QStandardItemModel model(10,10);
QSortFilterProxyModel proxy;
-
-
+
+
ModelTest t1(&model);
ModelTest t2(&proxy);
-
+
proxy.setSourceModel(&model);
-
+
model.insertRows(2, 5);
model.removeRows(4, 5);
model.insertColumns(2, 5);
model.removeColumns(4, 5);
-
+
model.insertRows(0,5, model.index(1,1));
model.insertColumns(0,5, model.index(1,3));
-
}
+void tst_ModelTest::testInsertThroughProxy()
+{
+ DynamicTreeModel *model = new DynamicTreeModel(this);
+
+ QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
+ proxy->setSourceModel(model);
+
+ new ModelTest(proxy, this);
+
+ ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
+ insertCommand->setNumCols(4);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(9);
+ // Parent is QModelIndex()
+ insertCommand->doCommand();
+
+ insertCommand = new ModelInsertCommand(model, this);
+ insertCommand->setNumCols(4);
+ insertCommand->setAncestorRowNumbers(QList<int>() << 5);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(9);
+ insertCommand->doCommand();
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(0);
+ moveCommand->setEndRow(0);
+ moveCommand->setDestRow(9);
+ moveCommand->setDestAncestors(QList<int>() << 5);
+ moveCommand->doCommand();
+}
+
+/**
+ Makes the persistent index list publicly accessible
+*/
+class AccessibleProxyModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {}
+
+ QModelIndexList persistent()
+ {
+ return persistentIndexList();
+ }
+};
+
+class ObservingObject : public QObject
+{
+ Q_OBJECT
+public:
+ ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0)
+ : QObject(parent),
+ m_proxy(proxy)
+ {
+ connect(m_proxy, SIGNAL(layoutAboutToBeChanged()), SLOT(storePersistent()));
+ connect(m_proxy, SIGNAL(layoutChanged()), SLOT(checkPersistent()));
+ }
+
+public slots:
+
+ void storePersistent(const QModelIndex &parent)
+ {
+ for (int row = 0; row < m_proxy->rowCount(parent); ++row) {
+ QModelIndex proxyIndex = m_proxy->index(row, 0, parent);
+ QModelIndex sourceIndex = m_proxy->mapToSource(proxyIndex);
+ Q_ASSERT(proxyIndex.isValid());
+ Q_ASSERT(sourceIndex.isValid());
+ m_persistentSourceIndexes.append(sourceIndex);
+ m_persistentProxyIndexes.append(proxyIndex);
+ if (m_proxy->hasChildren(proxyIndex))
+ storePersistent(proxyIndex);
+ }
+ }
+
+ void storePersistent()
+ {
+ m_persistentSourceIndexes.clear();
+ m_persistentProxyIndexes.clear();
+ Q_ASSERT(m_proxy->persistent().isEmpty());
+ storePersistent(QModelIndex());
+ Q_ASSERT(!m_proxy->persistent().isEmpty());
+ }
+
+ void checkPersistent()
+ {
+ for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) {
+ QModelIndex updatedProxy = m_persistentProxyIndexes.at(row);
+ QModelIndex updatedSource = m_persistentSourceIndexes.at(row);
+ }
+ for (int row = 0; row < m_persistentProxyIndexes.size(); ++row) {
+ QModelIndex updatedProxy = m_persistentProxyIndexes.at(row);
+ QModelIndex updatedSource = m_persistentSourceIndexes.at(row);
+ QCOMPARE(m_proxy->mapToSource(updatedProxy), updatedSource);
+ }
+ }
+
+private:
+ AccessibleProxyModel *m_proxy;
+ QList<QPersistentModelIndex> m_persistentSourceIndexes;
+ QList<QPersistentModelIndex> m_persistentProxyIndexes;
+};
+
+void tst_ModelTest::moveSourceItems()
+{
+ DynamicTreeModel *model = new DynamicTreeModel(this);
+ AccessibleProxyModel *proxy = new AccessibleProxyModel(this);
+ proxy->setSourceModel(model);
+
+ ModelInsertCommand *insertCommand = new ModelInsertCommand(model, this);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(2);
+ insertCommand->doCommand();
+
+ insertCommand = new ModelInsertCommand(model, this);
+ insertCommand->setAncestorRowNumbers(QList<int>() << 1);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(2);
+ insertCommand->doCommand();
+
+ ObservingObject observer(proxy);
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(model, this);
+ moveCommand->setStartRow(0);
+ moveCommand->setEndRow(0);
+ moveCommand->setDestAncestors(QList<int>() << 1);
+ moveCommand->setDestRow(0);
+ moveCommand->doCommand();
+}
+
+
QTEST_MAIN(tst_ModelTest)
#include "tst_modeltest.moc"
diff --git a/tests/auto/qabstractitemmodel/qabstractitemmodel.pro b/tests/auto/qabstractitemmodel/qabstractitemmodel.pro
index a31868b..52c4e96 100644
--- a/tests/auto/qabstractitemmodel/qabstractitemmodel.pro
+++ b/tests/auto/qabstractitemmodel/qabstractitemmodel.pro
@@ -1,6 +1,9 @@
load(qttest_p4)
-SOURCES += tst_qabstractitemmodel.cpp dynamictreemodel.cpp
-HEADERS += dynamictreemodel.h
+
+INCLUDEPATH += $$PWD/../modeltest
+
+SOURCES += tst_qabstractitemmodel.cpp ../modeltest/dynamictreemodel.cpp ../modeltest/modeltest.cpp
+HEADERS += ../modeltest/dynamictreemodel.h ../modeltest/modeltest.h
diff --git a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
index 69df39b..9e4321b 100644
--- a/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/qgraphicsview/tst_qgraphicsview.cpp
@@ -211,6 +211,7 @@ private slots:
void centerOnDirtyItem();
void mouseTracking();
void mouseTracking2();
+ void mouseTracking3();
void render();
void exposeRegion();
void update_data();
@@ -3403,6 +3404,102 @@ void tst_QGraphicsView::mouseTracking2()
QCOMPARE(spy.count(), 1);
}
+void tst_QGraphicsView::mouseTracking3()
+{
+ // Mouse tracking should be automatically enabled if AnchorUnderMouse is used for
+ // view transform or resize. We never disable mouse tracking if it is already enabled.
+
+ { // Make sure we enable mouse tracking when using AnchorUnderMouse for view transformation.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we enable mouse tracking when using AnchorUnderMouse for view resizing.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ QVERIFY(!view.viewport()->hasMouseTracking());
+
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setViewport/setScene (transformation anchor).
+ QGraphicsView view;
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ QWidget *viewport = new QWidget;
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ { // Make sure we don't disable mouse tracking in setViewport/setScene (resize anchor).
+ QGraphicsView view;
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ QVERIFY(view.viewport()->hasMouseTracking());
+
+ QWidget *viewport = new QWidget;
+ view.setViewport(viewport);
+ QVERIFY(viewport->hasMouseTracking());
+
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ view.setScene(&scene);
+ QVERIFY(viewport->hasMouseTracking());
+ }
+
+ // Make sure we don't disable mouse tracking when adding an item (transformation anchor).
+ { // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+
+ QGraphicsView view;
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+ view.setScene(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ view.setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ // Make sure we don't disable mouse tracking when adding an item (resize anchor).
+ { // Adding an item to the scene before the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+
+ QGraphicsView view;
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+ view.setScene(&scene);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+
+ { // Adding an item to the scene after the scene is set on the view.
+ QGraphicsScene scene(-10000, -10000, 20000, 20000);
+ QGraphicsView view(&scene);
+ view.setResizeAnchor(QGraphicsView::AnchorUnderMouse);
+
+ QGraphicsRectItem *item = new QGraphicsRectItem(10, 10, 10, 10);
+ scene.addItem(item);
+ QVERIFY(view.viewport()->hasMouseTracking());
+ }
+}
+
class RenderTester : public QGraphicsRectItem
{
public:
diff --git a/tests/benchmarks/benchmarks.pro b/tests/benchmarks/benchmarks.pro
index bffa009..bb20dcf 100644
--- a/tests/benchmarks/benchmarks.pro
+++ b/tests/benchmarks/benchmarks.pro
@@ -36,7 +36,8 @@ SUBDIRS = containers-associative \
qstringbuilder \
qstylesheetstyle \
qsvgrenderer \
- qtableview
+ qtableview \
+ qthreadstorage
diff --git a/tests/benchmarks/qthreadstorage/qthreadstorage.pro b/tests/benchmarks/qthreadstorage/qthreadstorage.pro
new file mode 100644
index 0000000..f9c1978
--- /dev/null
+++ b/tests/benchmarks/qthreadstorage/qthreadstorage.pro
@@ -0,0 +1,6 @@
+load(qttest_p4)
+TEMPLATE = app
+TARGET = tst_qthreadstorage
+
+SOURCES += tst_qthreadstorage.cpp
+
diff --git a/tests/benchmarks/qthreadstorage/tst_qthreadstorage.cpp b/tests/benchmarks/qthreadstorage/tst_qthreadstorage.cpp
new file mode 100644
index 0000000..c00bf5a
--- /dev/null
+++ b/tests/benchmarks/qthreadstorage/tst_qthreadstorage.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qtest.h>
+#include <QtCore>
+
+//TESTED_FILES=
+
+QThreadStorage<int *> dummy[8];
+
+QThreadStorage<QString *> tls1;
+
+class tst_QThreadStorage : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QThreadStorage();
+ virtual ~tst_QThreadStorage();
+
+public slots:
+ void init();
+ void cleanup();
+
+private slots:
+ void construct();
+ void get();
+ void set();
+};
+
+tst_QThreadStorage::tst_QThreadStorage()
+{
+}
+
+tst_QThreadStorage::~tst_QThreadStorage()
+{
+}
+
+void tst_QThreadStorage::init()
+{
+ dummy[1].setLocalData(new int(5));
+ dummy[2].setLocalData(new int(4));
+ dummy[3].setLocalData(new int(3));
+ tls1.setLocalData(new QString());
+}
+
+void tst_QThreadStorage::cleanup()
+{
+}
+
+void tst_QThreadStorage::construct()
+{
+ QBENCHMARK {
+ QThreadStorage<int *> ts;
+ }
+}
+
+
+void tst_QThreadStorage::get()
+{
+ QThreadStorage<int *> ts;
+ ts.setLocalData(new int(45));
+
+ int count = 0;
+ QBENCHMARK {
+ int *i = ts.localData();
+ count += *i;
+ }
+ ts.setLocalData(0);
+}
+
+void tst_QThreadStorage::set()
+{
+ QThreadStorage<int *> ts;
+
+ int count = 0;
+ QBENCHMARK {
+ ts.setLocalData(new int(count));
+ count++;
+ }
+ ts.setLocalData(0);
+}
+
+
+QTEST_MAIN(tst_QThreadStorage)
+#include "tst_qthreadstorage.moc"