summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri164
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp556
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h107
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher_p.h79
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp3454
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h410
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h176
-rw-r--r--src/corelib/kernel/qbasictimer.cpp138
-rw-r--r--src/corelib/kernel/qbasictimer.h74
-rw-r--r--src/corelib/kernel/qcore_mac.cpp82
-rw-r--r--src/corelib/kernel/qcore_mac_p.h163
-rw-r--r--src/corelib/kernel/qcore_symbian_p.cpp317
-rw-r--r--src/corelib/kernel/qcore_symbian_p.h282
-rw-r--r--src/corelib/kernel/qcore_unix.cpp106
-rw-r--r--src/corelib/kernel/qcore_unix_p.h333
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2730
-rw-r--r--src/corelib/kernel/qcoreapplication.h297
-rw-r--r--src/corelib/kernel/qcoreapplication_mac.cpp66
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h146
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp1060
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h171
-rw-r--r--src/corelib/kernel/qcoreevent.cpp612
-rw-r--r--src/corelib/kernel/qcoreevent.h396
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp53
-rw-r--r--src/corelib/kernel/qcoreglobaldata_p.h72
-rw-r--r--src/corelib/kernel/qcrashhandler.cpp423
-rw-r--r--src/corelib/kernel/qcrashhandler_p.h81
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp601
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h119
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp1310
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian_p.h327
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp979
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h208
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp1158
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h110
-rw-r--r--src/corelib/kernel/qeventloop.cpp329
-rw-r--r--src/corelib/kernel/qeventloop.h101
-rw-r--r--src/corelib/kernel/qfunctions_nacl.cpp156
-rw-r--r--src/corelib/kernel/qfunctions_nacl.h97
-rw-r--r--src/corelib/kernel/qfunctions_p.h79
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.cpp202
-rw-r--r--src/corelib/kernel/qfunctions_vxworks.h153
-rw-r--r--src/corelib/kernel/qfunctions_wince.cpp451
-rw-r--r--src/corelib/kernel/qfunctions_wince.h397
-rw-r--r--src/corelib/kernel/qmath.cpp305
-rw-r--r--src/corelib/kernel/qmath.h288
-rw-r--r--src/corelib/kernel/qmath.qdoc155
-rw-r--r--src/corelib/kernel/qmetaobject.cpp2778
-rw-r--r--src/corelib/kernel/qmetaobject.h242
-rw-r--r--src/corelib/kernel/qmetaobject_p.h326
-rw-r--r--src/corelib/kernel/qmetatype.cpp1509
-rw-r--r--src/corelib/kernel/qmetatype.h416
-rw-r--r--src/corelib/kernel/qmimedata.cpp627
-rw-r--r--src/corelib/kernel/qmimedata.h104
-rw-r--r--src/corelib/kernel/qobject.cpp4310
-rw-r--r--src/corelib/kernel/qobject.h411
-rw-r--r--src/corelib/kernel/qobject_p.h305
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.cpp148
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.h78
-rw-r--r--src/corelib/kernel/qobjectdefs.h506
-rw-r--r--src/corelib/kernel/qpointer.cpp270
-rw-r--r--src/corelib/kernel/qpointer.h168
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp612
-rw-r--r--src/corelib/kernel/qsharedmemory.h121
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h179
-rw-r--r--src/corelib/kernel/qsharedmemory_symbian.cpp173
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp302
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp195
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp321
-rw-r--r--src/corelib/kernel/qsignalmapper.h100
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp323
-rw-r--r--src/corelib/kernel/qsocketnotifier.h93
-rw-r--r--src/corelib/kernel/qsystemerror.cpp220
-rw-r--r--src/corelib/kernel/qsystemerror_p.h107
-rw-r--r--src/corelib/kernel/qsystemsemaphore.cpp363
-rw-r--r--src/corelib/kernel/qsystemsemaphore.h103
-rw-r--r--src/corelib/kernel/qsystemsemaphore_p.h118
-rw-r--r--src/corelib/kernel/qsystemsemaphore_symbian.cpp138
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp238
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp135
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp571
-rw-r--r--src/corelib/kernel/qtimer.cpp394
-rw-r--r--src/corelib/kernel/qtimer.h116
-rw-r--r--src/corelib/kernel/qtranslator.cpp979
-rw-r--r--src/corelib/kernel/qtranslator.h104
-rw-r--r--src/corelib/kernel/qtranslator_p.h79
-rw-r--r--src/corelib/kernel/qvariant.cpp3237
-rw-r--r--src/corelib/kernel/qvariant.h618
-rw-r--r--src/corelib/kernel/qvariant_p.h153
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.cpp134
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h94
91 files changed, 42591 insertions, 0 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
new file mode 100644
index 0000000000..a3628b1be5
--- /dev/null
+++ b/src/corelib/kernel/kernel.pri
@@ -0,0 +1,164 @@
+# Qt core object module
+
+HEADERS += \
+ kernel/qabstracteventdispatcher.h \
+ kernel/qabstractitemmodel.h \
+ kernel/qabstractitemmodel_p.h \
+ kernel/qbasictimer.h \
+ kernel/qeventloop.h\
+ kernel/qpointer.h \
+ kernel/qcorecmdlineargs_p.h \
+ kernel/qcoreapplication.h \
+ kernel/qcoreevent.h \
+ kernel/qmetaobject.h \
+ kernel/qmetatype.h \
+ kernel/qmimedata.h \
+ kernel/qobject.h \
+ kernel/qobjectdefs.h \
+ kernel/qsignalmapper.h \
+ kernel/qsocketnotifier.h \
+ kernel/qtimer.h \
+ kernel/qtranslator.h \
+ kernel/qtranslator_p.h \
+ kernel/qvariant.h \
+ kernel/qabstracteventdispatcher_p.h \
+ kernel/qcoreapplication_p.h \
+ kernel/qobjectcleanuphandler.h \
+ kernel/qvariant_p.h \
+ kernel/qmetaobject_p.h \
+ kernel/qobject_p.h \
+ kernel/qcoreglobaldata_p.h \
+ kernel/qsharedmemory.h \
+ kernel/qsharedmemory_p.h \
+ kernel/qsystemsemaphore.h \
+ kernel/qsystemsemaphore_p.h \
+ kernel/qfunctions_p.h \
+ kernel/qmath.h \
+ kernel/qsystemerror_p.h
+
+SOURCES += \
+ kernel/qabstracteventdispatcher.cpp \
+ kernel/qabstractitemmodel.cpp \
+ kernel/qbasictimer.cpp \
+ kernel/qeventloop.cpp \
+ kernel/qcoreapplication.cpp \
+ kernel/qcoreevent.cpp \
+ kernel/qmetaobject.cpp \
+ kernel/qmetatype.cpp \
+ kernel/qmimedata.cpp \
+ kernel/qobject.cpp \
+ kernel/qobjectcleanuphandler.cpp \
+ kernel/qsignalmapper.cpp \
+ kernel/qsocketnotifier.cpp \
+ kernel/qtimer.cpp \
+ kernel/qtranslator.cpp \
+ kernel/qvariant.cpp \
+ kernel/qcoreglobaldata.cpp \
+ kernel/qsharedmemory.cpp \
+ kernel/qsystemsemaphore.cpp \
+ kernel/qpointer.cpp \
+ kernel/qmath.cpp \
+ kernel/qsystemerror.cpp
+
+win32 {
+ SOURCES += \
+ kernel/qeventdispatcher_win.cpp \
+ kernel/qcoreapplication_win.cpp \
+ kernel/qwineventnotifier_p.cpp \
+ kernel/qsharedmemory_win.cpp \
+ kernel/qsystemsemaphore_win.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_win_p.h \
+ kernel/qwineventnotifier_p.h
+}
+
+
+wince*: {
+ SOURCES += \
+ kernel/qfunctions_wince.cpp
+ HEADERS += \
+ kernel/qfunctions_wince.h
+}
+
+mac:!embedded:!qpa{
+ SOURCES += \
+ kernel/qcoreapplication_mac.cpp
+}
+
+mac:!nacl {
+ SOURCES += \
+ kernel/qcore_mac.cpp
+}
+
+nacl {
+ SOURCES += \
+ kernel/qfunctions_nacl.cpp
+ HEADERS += \
+ kernel/qfunctions_nacl.h
+}
+
+unix:!symbian {
+ SOURCES += \
+ kernel/qcore_unix.cpp \
+ kernel/qcrashhandler.cpp \
+ kernel/qsharedmemory_unix.cpp \
+ kernel/qsystemsemaphore_unix.cpp
+ HEADERS += \
+ kernel/qcore_unix_p.h \
+ kernel/qcrashhandler_p.h
+
+ contains(QT_CONFIG, glib) {
+ SOURCES += \
+ kernel/qeventdispatcher_glib.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_glib_p.h
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB
+ LIBS_PRIVATE +=$$QT_LIBS_GLIB
+ }
+ SOURCES += \
+ kernel/qeventdispatcher_unix.cpp
+ HEADERS += \
+ kernel/qeventdispatcher_unix_p.h
+
+ contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
+}
+
+symbian {
+ SOURCES += \
+ kernel/qcore_unix.cpp \
+ kernel/qcrashhandler.cpp \
+ kernel/qeventdispatcher_symbian.cpp \
+ kernel/qcore_symbian_p.cpp \
+ kernel/qsharedmemory_symbian.cpp \
+ kernel/qsystemsemaphore_symbian.cpp
+
+ HEADERS += \
+ kernel/qcore_unix_p.h \
+ kernel/qcrashhandler_p.h \
+ kernel/qeventdispatcher_symbian_p.h \
+ kernel/qcore_symbian_p.h
+}
+
+vxworks {
+ SOURCES += \
+ kernel/qfunctions_vxworks.cpp
+ HEADERS += \
+ kernel/qfunctions_vxworks.h
+}
+
+
+integrity {
+ SOURCES += \
+ kernel/qcore_unix.cpp \
+ kernel/qcrashhandler.cpp \
+ kernel/qsharedmemory_unix.cpp \
+ kernel/qsystemsemaphore_unix.cpp \
+ kernel/qeventdispatcher_unix.cpp
+ HEADERS += \
+ kernel/qcore_unix_p.h \
+ kernel/qcrashhandler_p.h \
+ kernel/qeventdispatcher_unix_p.h
+
+ contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
+}
+
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
new file mode 100644
index 0000000000..2949cd0d3a
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -0,0 +1,556 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qabstracteventdispatcher.h"
+#include "qabstracteventdispatcher_p.h"
+
+#include "qthread.h"
+#include <private/qthread_p.h>
+#include <private/qcoreapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// we allow for 2^24 = 8^8 = 16777216 simultaneously running timers
+static const int TimerIdMask = 0x00ffffff;
+static const int TimerSerialMask = ~TimerIdMask & ~0x80000000;
+static const int TimerSerialCounter = TimerIdMask + 1;
+static const int MaxTimerId = TimerIdMask;
+
+static int FirstBucket[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
+};
+
+enum {
+ FirstBucketOffset = 0,
+ SecondBucketOffset = sizeof(FirstBucket) / sizeof(FirstBucket[0]),
+ ThirdBucketOffset = 0x100,
+ FourthBucketOffset = 0x1000,
+ FifthBucketOffset = 0x10000,
+ SixthBucketOffset = 0x100000
+};
+
+enum {
+ FirstBucketSize = SecondBucketOffset,
+ SecondBucketSize = ThirdBucketOffset - SecondBucketOffset,
+ ThirdBucketSize = FourthBucketOffset - ThirdBucketOffset,
+ FourthBucketSize = FifthBucketOffset - FourthBucketOffset,
+ FifthBucketSize = SixthBucketOffset - FifthBucketOffset,
+ SixthBucketSize = MaxTimerId - SixthBucketOffset
+};
+
+static const int BucketSize[] = {
+ FirstBucketSize, SecondBucketSize, ThirdBucketSize,
+ FourthBucketSize, FifthBucketSize, SixthBucketSize
+};
+enum { NumberOfBuckets = sizeof(BucketSize) / sizeof(BucketSize[0]) };
+
+static const int BucketOffset[] = {
+ FirstBucketOffset, SecondBucketOffset, ThirdBucketOffset,
+ FourthBucketOffset, FifthBucketOffset, SixthBucketOffset
+};
+
+static QBasicAtomicPointer<int> timerIds[] =
+ { Q_BASIC_ATOMIC_INITIALIZER(FirstBucket),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0),
+ Q_BASIC_ATOMIC_INITIALIZER(0) };
+
+static void timerIdsDestructorFunction()
+{
+ // start at one, the first bucket is pre-allocated
+ for (int i = 1; i < NumberOfBuckets; ++i)
+ delete [] static_cast<int *>(timerIds[i]);
+}
+Q_DESTRUCTOR_FUNCTION(timerIdsDestructorFunction)
+
+static QBasicAtomicInt nextFreeTimerId = Q_BASIC_ATOMIC_INITIALIZER(1);
+
+// avoid the ABA-problem by using 7 of the top 8 bits of the timerId as a serial number
+static inline int prepareNewValueWithSerialNumber(int oldId, int newId)
+{
+ return (newId & TimerIdMask) | ((oldId + TimerSerialCounter) & TimerSerialMask);
+}
+
+namespace {
+ template<bool> struct QStaticAssertType;
+ template<> struct QStaticAssertType<true> { enum { Value = 1 }; };
+}
+#define q_static_assert(expr) (void)QStaticAssertType<expr>::Value
+
+static inline int bucketOffset(int timerId)
+{
+ q_static_assert(sizeof BucketSize == sizeof BucketOffset);
+ q_static_assert(sizeof(timerIds) / sizeof(timerIds[0]) == NumberOfBuckets);
+
+ for (int i = 0; i < NumberOfBuckets; ++i) {
+ if (timerId < BucketSize[i])
+ return i;
+ timerId -= BucketSize[i];
+ }
+ qFatal("QAbstractEventDispatcher: INTERNAL ERROR, timer ID %d is too large", timerId);
+ return -1;
+}
+
+static inline int bucketIndex(int bucket, int timerId)
+{
+ return timerId - BucketOffset[bucket];
+}
+
+static inline int *allocateBucket(int bucket)
+{
+ // allocate a new bucket
+ const int size = BucketSize[bucket];
+ const int offset = BucketOffset[bucket];
+ int *b = new int[size];
+ for (int i = 0; i != size; ++i)
+ b[i] = offset + i + 1;
+ return b;
+}
+
+void QAbstractEventDispatcherPrivate::init()
+{
+ Q_Q(QAbstractEventDispatcher);
+ if (threadData->eventDispatcher != 0) {
+ qWarning("QAbstractEventDispatcher: An event dispatcher has already been created for this thread");
+ } else {
+ threadData->eventDispatcher = q;
+ }
+}
+
+// Timer IDs are implemented using a free-list;
+// there's a vector initialized with:
+// X[i] = i + 1
+// and nextFreeTimerId starts with 1.
+//
+// Allocating a timer ID involves taking the ID from
+// X[nextFreeTimerId]
+// updating nextFreeTimerId to this value and returning the old value
+//
+// When the timer ID is allocated, its cell in the vector is unused (it's a
+// free list). As an added protection, we use the cell to store an invalid
+// (negative) value that we can later check for integrity.
+//
+// (continues below).
+int QAbstractEventDispatcherPrivate::allocateTimerId()
+{
+ int timerId, newTimerId;
+ int at, *b;
+ do {
+ timerId = nextFreeTimerId; //.loadAcquire(); // ### FIXME Proper memory ordering semantics
+
+ // which bucket are we looking in?
+ int which = timerId & TimerIdMask;
+ int bucket = bucketOffset(which);
+ at = bucketIndex(bucket, which);
+ b = timerIds[bucket];
+
+ if (!b) {
+ // allocate a new bucket
+ b = allocateBucket(bucket);
+ if (!timerIds[bucket].testAndSetRelease(0, b)) {
+ // another thread won the race to allocate the bucket
+ delete [] b;
+ b = timerIds[bucket];
+ }
+ }
+
+ newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]);
+ } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));
+
+ b[at] = -timerId;
+
+ return timerId;
+}
+
+// Releasing a timer ID requires putting the current ID back in the vector;
+// we do it by setting:
+// X[timerId] = nextFreeTimerId;
+// then we update nextFreeTimerId to the timer we've just released
+//
+// The extra code in allocateTimerId and releaseTimerId are ABA prevention
+// and bucket memory. The buckets are simply to make sure we allocate only
+// the necessary number of timers. See above.
+//
+// ABA prevention simply adds a value to 7 of the top 8 bits when resetting
+// nextFreeTimerId.
+void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
+{
+ int which = timerId & TimerIdMask;
+ int bucket = bucketOffset(which);
+ int at = bucketIndex(bucket, which);
+ int *b = timerIds[bucket];
+
+ Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId",
+ "Internal error: timer ID not found");
+
+ int freeId, newTimerId;
+ do {
+ freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics
+ b[at] = freeId & TimerIdMask;
+
+ newTimerId = prepareNewValueWithSerialNumber(freeId, timerId);
+ } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId));
+}
+
+/*!
+ \class QAbstractEventDispatcher
+ \brief The QAbstractEventDispatcher class provides an interface to manage Qt's event queue.
+
+ \ingroup events
+
+ An event dispatcher receives events from the window system and other
+ sources. It then sends them to the QCoreApplication or QApplication
+ instance for processing and delivery. QAbstractEventDispatcher provides
+ fine-grained control over event delivery.
+
+ For simple control of event processing use
+ QCoreApplication::processEvents().
+
+ For finer control of the application's event loop, call
+ instance() and call functions on the QAbstractEventDispatcher
+ object that is returned. If you want to use your own instance of
+ QAbstractEventDispatcher or of a QAbstractEventDispatcher
+ subclass, you must create your instance \e before you create the
+ QApplication object.
+
+ The main event loop is started by calling
+ QCoreApplication::exec(), and stopped by calling
+ QCoreApplication::exit(). Local event loops can be created using
+ QEventLoop.
+
+ Programs that perform long operations can call processEvents()
+ with a bitwise OR combination of various QEventLoop::ProcessEventsFlag
+ values to control which events should be delivered.
+
+ QAbstractEventDispatcher also allows the integration of an
+ external event loop with the Qt event loop. For example, the
+ \l{Qt Solutions}{Motif Extension Qt Solution} includes a
+ reimplementation of QAbstractEventDispatcher that merges Qt and
+ Motif events together.
+
+ \sa QEventLoop, QCoreApplication
+*/
+
+/*!
+ Constructs a new event dispatcher with the given \a parent.
+*/
+QAbstractEventDispatcher::QAbstractEventDispatcher(QObject *parent)
+ : QObject(*new QAbstractEventDispatcherPrivate, parent)
+{
+ Q_D(QAbstractEventDispatcher);
+ d->init();
+}
+
+/*!
+ \internal
+*/
+QAbstractEventDispatcher::QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &dd,
+ QObject *parent)
+ : QObject(dd, parent)
+{
+ Q_D(QAbstractEventDispatcher);
+ d->init();
+}
+
+/*!
+ Destroys the event dispatcher.
+*/
+QAbstractEventDispatcher::~QAbstractEventDispatcher()
+{ }
+
+/*!
+ Returns a pointer to the event dispatcher object for the specified
+ \a thread. If \a thread is zero, the current thread is used. If no
+ event dispatcher exists for the specified thread, this function
+ returns 0.
+
+ \bold{Note:} If Qt is built without thread support, the \a thread
+ argument is ignored.
+ */
+QAbstractEventDispatcher *QAbstractEventDispatcher::instance(QThread *thread)
+{
+ QThreadData *data = thread ? QThreadData::get2(thread) : QThreadData::current();
+ return data->eventDispatcher;
+}
+
+/*!
+ \fn bool QAbstractEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
+
+ Processes pending events that match \a flags until there are no
+ more events to process. Returns true if an event was processed;
+ otherwise returns false.
+
+ This function is especially useful if you have a long running
+ operation and want to show its progress without allowing user
+ input; i.e. by using the QEventLoop::ExcludeUserInputEvents flag.
+
+ If the QEventLoop::WaitForMoreEvents flag is set in \a flags, the
+ behavior of this function is as follows:
+
+ \list
+
+ \i If events are available, this function returns after processing
+ them.
+
+ \i If no events are available, this function will wait until more
+ are available and return after processing newly available events.
+
+ \endlist
+
+ If the QEventLoop::WaitForMoreEvents flag is not set in \a flags,
+ and no events are available, this function will return
+ immediately.
+
+ \bold{Note:} This function does not process events continuously; it
+ returns after all available events are processed.
+
+ \sa hasPendingEvents()
+*/
+
+/*! \fn bool QAbstractEventDispatcher::hasPendingEvents()
+
+ Returns true if there is an event waiting; otherwise returns
+ false.
+*/
+
+/*!
+ \fn void QAbstractEventDispatcher::registerSocketNotifier(QSocketNotifier *notifier)
+
+ Registers \a notifier with the event loop. Subclasses must
+ implement this method to tie a socket notifier into another
+ event loop.
+*/
+
+/*! \fn void QAbstractEventDispatcher::unregisterSocketNotifier(QSocketNotifier *notifier)
+
+ Unregisters \a notifier from the event dispatcher. Subclasses must
+ reimplement this method to tie a socket notifier into another
+ event loop. Reimplementations must call the base
+ implementation.
+*/
+
+/*!
+ \fn int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
+
+ Registers a timer with the specified \a interval for the given \a object.
+*/
+int QAbstractEventDispatcher::registerTimer(int interval, QObject *object)
+{
+ int id = QAbstractEventDispatcherPrivate::allocateTimerId();
+ registerTimer(id, interval, object);
+ return id;
+}
+
+/*!
+ \fn void QAbstractEventDispatcher::registerTimer(int timerId, int interval, QObject *object)
+
+ Register a timer with the specified \a timerId and \a interval for
+ the given \a object.
+*/
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimer(int timerId)
+
+ Unregisters the timer with the given \a timerId.
+ Returns true if successful; otherwise returns false.
+
+ \sa registerTimer(), unregisterTimers()
+*/
+
+/*!
+ \fn bool QAbstractEventDispatcher::unregisterTimers(QObject *object)
+
+ Unregisters all the timers associated with the given \a object.
+ Returns true if all timers were successful removed; otherwise returns false.
+
+ \sa unregisterTimer(), registeredTimers()
+*/
+
+/*!
+ \fn QList<TimerInfo> QAbstractEventDispatcher::registeredTimers(QObject *object) const
+
+ Returns a list of registered timers for \a object. The timer ID
+ is the first member in each pair; the interval is the second.
+*/
+
+/*! \fn void QAbstractEventDispatcher::wakeUp()
+ \threadsafe
+
+ Wakes up the event loop.
+
+ \sa awake()
+*/
+
+/*!
+ \fn void QAbstractEventDispatcher::interrupt()
+
+ Interrupts event dispatching; i.e. the event dispatcher will
+ return from processEvents() as soon as possible.
+*/
+
+/*! \fn void QAbstractEventDispatcher::flush()
+
+ Flushes the event queue. This normally returns almost
+ immediately. Does nothing on platforms other than X11.
+*/
+
+// ### DOC: Are these called when the _application_ starts/stops or just
+// when the current _event loop_ starts/stops?
+/*! \internal */
+void QAbstractEventDispatcher::startingUp()
+{ }
+
+/*! \internal */
+void QAbstractEventDispatcher::closingDown()
+{ }
+
+/*!
+ \typedef QAbstractEventDispatcher::TimerInfo
+
+ Typedef for QPair<int, int>. The first component of
+ the pair is the timer ID; the second component is
+ the interval.
+
+ \sa registeredTimers()
+*/
+
+/*!
+ \typedef QAbstractEventDispatcher::EventFilter
+
+ Typedef for a function with the signature
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstracteventdispatcher.cpp 0
+
+ Note that the type of the \a message is platform dependent. The
+ following table shows the \a {message}'s type on Windows, Mac, and
+ X11. You can do a static cast to these types.
+
+ \table
+ \header
+ \o Platform
+ \o type
+ \row
+ \o Windows
+ \o MSG
+ \row
+ \o X11
+ \o XEvent
+ \row
+ \o Mac
+ \o NSEvent
+ \endtable
+
+
+
+ \sa setEventFilter(), filterEvent()
+*/
+
+/*!
+ Replaces the event filter function for this
+ QAbstractEventDispatcher with \a filter and returns the replaced
+ event filter function. Only the current event filter function is
+ called. If you want to use both filter functions, save the
+ replaced EventFilter in a place where yours can call it.
+
+ The event filter function set here is called for all messages
+ taken from the system event loop before the event is dispatched to
+ the respective target, including the messages not meant for Qt
+ objects.
+
+ The event filter function should return true if the message should
+ be filtered, (i.e. stopped). It should return false to allow
+ processing the message to continue.
+
+ By default, no event filter function is set (i.e., this function
+ returns a null EventFilter the first time it is called).
+*/
+QAbstractEventDispatcher::EventFilter QAbstractEventDispatcher::setEventFilter(EventFilter filter)
+{
+ Q_D(QAbstractEventDispatcher);
+ EventFilter oldFilter = d->event_filter;
+ d->event_filter = filter;
+ return oldFilter;
+}
+
+/*!
+ Sends \a message through the event filter that was set by
+ setEventFilter(). If no event filter has been set, this function
+ returns false; otherwise, this function returns the result of the
+ event filter function.
+
+ Subclasses of QAbstractEventDispatcher \e must call this function
+ for \e all messages received from the system to ensure
+ compatibility with any extensions that may be used in the
+ application.
+
+ Note that the type of \a message is platform dependent. See
+ QAbstractEventDispatcher::EventFilter for details.
+
+ \sa setEventFilter()
+*/
+bool QAbstractEventDispatcher::filterEvent(void *message)
+{
+ Q_D(QAbstractEventDispatcher);
+ if (d->event_filter)
+ return d->event_filter(message);
+ return false;
+}
+
+/*! \fn void QAbstractEventDispatcher::awake()
+
+ This signal is emitted after the event loop returns from a
+ function that could block.
+
+ \sa wakeUp() aboutToBlock()
+*/
+
+/*! \fn void QAbstractEventDispatcher::aboutToBlock()
+
+ This signal is emitted before the event loop calls a function that
+ could block.
+
+ \sa awake()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h
new file mode 100644
index 0000000000..212b832ae2
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QABSTRACTEVENTDISPATCHER_H
+#define QABSTRACTEVENTDISPATCHER_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qeventloop.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QAbstractEventDispatcherPrivate;
+class QSocketNotifier;
+template <typename T1, typename T2> struct QPair;
+
+class Q_CORE_EXPORT QAbstractEventDispatcher : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAbstractEventDispatcher)
+
+public:
+ typedef QPair<int, int> TimerInfo;
+
+ explicit QAbstractEventDispatcher(QObject *parent = 0);
+ ~QAbstractEventDispatcher();
+
+ static QAbstractEventDispatcher *instance(QThread *thread = 0);
+
+ virtual bool processEvents(QEventLoop::ProcessEventsFlags flags) = 0;
+ virtual bool hasPendingEvents() = 0;
+
+ virtual void registerSocketNotifier(QSocketNotifier *notifier) = 0;
+ virtual void unregisterSocketNotifier(QSocketNotifier *notifier) = 0;
+
+ int registerTimer(int interval, QObject *object);
+ virtual void registerTimer(int timerId, int interval, QObject *object) = 0;
+ virtual bool unregisterTimer(int timerId) = 0;
+ virtual bool unregisterTimers(QObject *object) = 0;
+ virtual QList<TimerInfo> registeredTimers(QObject *object) const = 0;
+
+ virtual void wakeUp() = 0;
+ virtual void interrupt() = 0;
+ virtual void flush() = 0;
+
+ virtual void startingUp();
+ virtual void closingDown();
+
+ typedef bool(*EventFilter)(void *message);
+ EventFilter setEventFilter(EventFilter filter);
+ bool filterEvent(void *message);
+
+Q_SIGNALS:
+ void aboutToBlock();
+ void awake();
+
+protected:
+ QAbstractEventDispatcher(QAbstractEventDispatcherPrivate &,
+ QObject *parent);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTEVENTDISPATCHER_H
diff --git a/src/corelib/kernel/qabstracteventdispatcher_p.h b/src/corelib/kernel/qabstracteventdispatcher_p.h
new file mode 100644
index 0000000000..4a55dfba09
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QABSTRACTEVENTDISPATCHER_P_H
+#define QABSTRACTEVENTDISPATCHER_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 "QtCore/qabstracteventdispatcher.h"
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT uint qGlobalPostedEventsCount();
+
+class Q_CORE_EXPORT QAbstractEventDispatcherPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractEventDispatcher)
+public:
+ inline QAbstractEventDispatcherPrivate()
+ : event_filter(0)
+ { }
+ void init();
+ QAbstractEventDispatcher::EventFilter event_filter;
+
+ static int allocateTimerId();
+ static void releaseTimerId(int id);
+};
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTEVENTDISPATCHER_P_H
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
new file mode 100644
index 0000000000..9dd22dc39b
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -0,0 +1,3454 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qabstractitemmodel.h"
+#include <private/qabstractitemmodel_p.h>
+#include <qdatastream.h>
+#include <qstringlist.h>
+#include <qsize.h>
+#include <qmimedata.h>
+#include <qdebug.h>
+#include <qvector.h>
+#include <qstack.h>
+#include <qbitarray.h>
+
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+QPersistentModelIndexData *QPersistentModelIndexData::create(const QModelIndex &index)
+{
+ Q_ASSERT(index.isValid()); // we will _never_ insert an invalid index in the list
+ QPersistentModelIndexData *d = 0;
+ QAbstractItemModel *model = const_cast<QAbstractItemModel *>(index.model());
+ QHash<QModelIndex, QPersistentModelIndexData *> &indexes = model->d_func()->persistent.indexes;
+ const QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = indexes.find(index);
+ if (it != indexes.end()) {
+ d = (*it);
+ } else {
+ d = new QPersistentModelIndexData(index);
+ indexes.insert(index, d);
+ }
+ Q_ASSERT(d);
+ return d;
+}
+
+void QPersistentModelIndexData::destroy(QPersistentModelIndexData *data)
+{
+ Q_ASSERT(data);
+ Q_ASSERT(data->ref == 0);
+ QAbstractItemModel *model = const_cast<QAbstractItemModel *>(data->model);
+ // a valid persistent model index with a null model pointer can only happen if the model was destroyed
+ if (model) {
+ QAbstractItemModelPrivate *p = model->d_func();
+ Q_ASSERT(p);
+ p->removePersistentIndexData(data);
+ }
+ delete data;
+}
+
+/*!
+ \class QPersistentModelIndex
+
+ \brief The QPersistentModelIndex class is used to locate data in a data model.
+
+ \ingroup model-view
+
+ A QPersistentModelIndex is a model index that can be stored by an
+ application, and later used to access information in a model.
+ Unlike the QModelIndex class, it is safe to store a
+ QPersistentModelIndex since the model will ensure that references
+ to items will continue to be valid as long as they can be accessed
+ by the model.
+
+ It is good practice to check that persistent model indexes are valid
+ before using them.
+
+ \sa {Model/View Programming}, QModelIndex, QAbstractItemModel
+*/
+
+
+/*!
+ \fn QPersistentModelIndex::QPersistentModelIndex()
+
+ \internal
+*/
+
+QPersistentModelIndex::QPersistentModelIndex()
+ : d(0)
+{
+}
+
+/*!
+ \fn QPersistentModelIndex::QPersistentModelIndex(const QPersistentModelIndex &other)
+
+ Creates a new QPersistentModelIndex that is a copy of the \a other persistent
+ model index.
+*/
+
+QPersistentModelIndex::QPersistentModelIndex(const QPersistentModelIndex &other)
+ : d(other.d)
+{
+ if (d) d->ref.ref();
+}
+
+/*!
+ Creates a new QPersistentModelIndex that is a copy of the model \a index.
+*/
+
+QPersistentModelIndex::QPersistentModelIndex(const QModelIndex &index)
+ : d(0)
+{
+ if (index.isValid()) {
+ d = QPersistentModelIndexData::create(index);
+ d->ref.ref();
+ }
+}
+
+/*!
+ \fn QPersistentModelIndex::~QPersistentModelIndex()
+
+ \internal
+*/
+
+QPersistentModelIndex::~QPersistentModelIndex()
+{
+ if (d && !d->ref.deref()) {
+ QPersistentModelIndexData::destroy(d);
+ d = 0;
+ }
+}
+
+/*!
+ Returns true if this persistent model index is equal to the \a other
+ persistent model index; otherwise returns false.
+
+ All values in the persistent model index are used when comparing
+ with another persistent model index.
+*/
+
+bool QPersistentModelIndex::operator==(const QPersistentModelIndex &other) const
+{
+ if (d && other.d)
+ return d->index == other.d->index;
+ return d == other.d;
+}
+
+/*!
+ \since 4.1
+
+ Returns true if this persistent model index is smaller than the \a other
+ persistent model index; otherwise returns false.
+
+ All values in the persistent model index are used when comparing
+ with another persistent model index.
+*/
+
+bool QPersistentModelIndex::operator<(const QPersistentModelIndex &other) const
+{
+ if (d && other.d)
+ return d->index < other.d->index;
+
+ return d < other.d;
+}
+
+/*!
+ \fn bool QPersistentModelIndex::operator!=(const QPersistentModelIndex &other) const
+ \since 4.2
+
+ Returns true if this persistent model index is not equal to the \a
+ other persistent model index; otherwise returns false.
+*/
+
+/*!
+ Sets the persistent model index to refer to the same item in a model
+ as the \a other persistent model index.
+*/
+
+QPersistentModelIndex &QPersistentModelIndex::operator=(const QPersistentModelIndex &other)
+{
+ if (d == other.d)
+ return *this;
+ if (d && !d->ref.deref())
+ QPersistentModelIndexData::destroy(d);
+ d = other.d;
+ if (d) d->ref.ref();
+ return *this;
+}
+
+/*!
+ Sets the persistent model index to refer to the same item in a model
+ as the \a other model index.
+*/
+
+QPersistentModelIndex &QPersistentModelIndex::operator=(const QModelIndex &other)
+{
+ if (d && !d->ref.deref())
+ QPersistentModelIndexData::destroy(d);
+ if (other.isValid()) {
+ d = QPersistentModelIndexData::create(other);
+ if (d) d->ref.ref();
+ } else {
+ d = 0;
+ }
+ return *this;
+}
+
+/*!
+ \fn QPersistentModelIndex::operator const QModelIndex&() const
+
+ Cast operator that returns a const QModelIndex&.
+*/
+
+QPersistentModelIndex::operator const QModelIndex&() const
+{
+ static const QModelIndex invalid;
+ if (d)
+ return d->index;
+ return invalid;
+}
+
+/*!
+ \fn bool QPersistentModelIndex::operator==(const QModelIndex &other) const
+
+ Returns true if this persistent model index refers to the same location as
+ the \a other model index; otherwise returns false.
+
+ All values in the persistent model index are used when comparing with
+ another model index.
+*/
+
+bool QPersistentModelIndex::operator==(const QModelIndex &other) const
+{
+ if (d)
+ return d->index == other;
+ return !other.isValid();
+}
+
+/*!
+ \fn bool QPersistentModelIndex::operator!=(const QModelIndex &other) const
+
+ Returns true if this persistent model index does not refer to the same
+ location as the \a other model index; otherwise returns false.
+*/
+
+bool QPersistentModelIndex::operator!=(const QModelIndex &other) const
+{
+ if (d)
+ return d->index != other;
+ return other.isValid();
+}
+
+/*!
+ \fn int QPersistentModelIndex::row() const
+
+ Returns the row this persistent model index refers to.
+*/
+
+int QPersistentModelIndex::row() const
+{
+ if (d)
+ return d->index.row();
+ return -1;
+}
+
+/*!
+ \fn int QPersistentModelIndex::column() const
+
+ Returns the column this persistent model index refers to.
+*/
+
+int QPersistentModelIndex::column() const
+{
+ if (d)
+ return d->index.column();
+ return -1;
+}
+
+/*!
+ \fn void *QPersistentModelIndex::internalPointer() const
+
+ \internal
+
+ Returns a \c{void} \c{*} pointer used by the model to associate the index with
+ the internal data structure.
+*/
+
+void *QPersistentModelIndex::internalPointer() const
+{
+ if (d)
+ return d->index.internalPointer();
+ return 0;
+}
+
+/*!
+ \fn void *QPersistentModelIndex::internalId() const
+
+ \internal
+
+ Returns a \c{qint64} used by the model to associate the index with
+ the internal data structure.
+*/
+
+qint64 QPersistentModelIndex::internalId() const
+{
+ if (d)
+ return d->index.internalId();
+ return 0;
+}
+
+/*!
+ Returns the parent QModelIndex for this persistent index, or an invalid
+ QModelIndex if it has no parent.
+
+ \sa child() sibling() model()
+*/
+QModelIndex QPersistentModelIndex::parent() const
+{
+ if (d)
+ return d->index.parent();
+ return QModelIndex();
+}
+
+/*!
+ Returns the sibling at \a row and \a column or an invalid QModelIndex if
+ there is no sibling at this position.
+
+ \sa parent() child()
+*/
+
+QModelIndex QPersistentModelIndex::sibling(int row, int column) const
+{
+ if (d)
+ return d->index.sibling(row, column);
+ return QModelIndex();
+}
+
+/*!
+ Returns the child of the model index that is stored in the given \a row
+ and \a column.
+
+ \sa parent() sibling()
+*/
+
+QModelIndex QPersistentModelIndex::child(int row, int column) const
+{
+ if (d)
+ return d->index.child(row, column);
+ return QModelIndex();
+}
+
+/*!
+ Returns the data for the given \a role for the item referred to by the
+ index.
+
+ \sa Qt::ItemDataRole, QAbstractItemModel::setData()
+*/
+QVariant QPersistentModelIndex::data(int role) const
+{
+ if (d)
+ return d->index.data(role);
+ return QVariant();
+}
+
+/*!
+ \since 4.2
+
+ Returns the flags for the item referred to by the index.
+*/
+Qt::ItemFlags QPersistentModelIndex::flags() const
+{
+ if (d)
+ return d->index.flags();
+ return 0;
+}
+
+/*!
+ Returns the model that the index belongs to.
+*/
+const QAbstractItemModel *QPersistentModelIndex::model() const
+{
+ if (d)
+ return d->index.model();
+ return 0;
+}
+
+/*!
+ \fn bool QPersistentModelIndex::isValid() const
+
+ Returns true if this persistent model index is valid; otherwise returns
+ false.
+
+ A valid index belongs to a model, and has non-negative row and column
+ numbers.
+
+ \sa model(), row(), column()
+*/
+
+bool QPersistentModelIndex::isValid() const
+{
+ return d && d->index.isValid();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QModelIndex &idx)
+{
+#ifndef Q_BROKEN_DEBUG_STREAM
+ dbg.nospace() << "QModelIndex(" << idx.row() << ',' << idx.column()
+ << ',' << idx.internalPointer() << ',' << idx.model() << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QModelIndex to QDebug");
+ return dbg;
+ Q_UNUSED(idx);
+#endif
+}
+
+QDebug operator<<(QDebug dbg, const QPersistentModelIndex &idx)
+{
+ if (idx.d)
+ dbg << idx.d->index;
+ else
+ dbg << QModelIndex();
+ return dbg;
+}
+#endif
+
+class QEmptyItemModel : public QAbstractItemModel
+{
+public:
+ explicit QEmptyItemModel(QObject *parent = 0) : QAbstractItemModel(parent) {}
+ QModelIndex index(int, int, const QModelIndex &) const { return QModelIndex(); }
+ QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
+ int rowCount(const QModelIndex &) const { return 0; }
+ int columnCount(const QModelIndex &) const { return 0; }
+ bool hasChildren(const QModelIndex &) const { return false; }
+ QVariant data(const QModelIndex &, int) const { return QVariant(); }
+};
+
+Q_GLOBAL_STATIC(QEmptyItemModel, qEmptyModel)
+
+QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
+{
+ return qEmptyModel();
+}
+
+namespace {
+ struct DefaultRoleNames : public QHash<int, QByteArray>
+ {
+ DefaultRoleNames() {
+ (*this)[Qt::DisplayRole] = "display";
+ (*this)[Qt::DecorationRole] = "decoration";
+ (*this)[Qt::EditRole] = "edit";
+ (*this)[Qt::ToolTipRole] = "toolTip";
+ (*this)[Qt::StatusTipRole] = "statusTip";
+ (*this)[Qt::WhatsThisRole] = "whatsThis";
+ }
+ };
+}
+
+Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames)
+
+const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames()
+{
+ return *qDefaultRoleNames();
+}
+
+
+static uint typeOfVariant(const QVariant &value)
+{
+ //return 0 for integer, 1 for floating point and 2 for other
+ switch (value.userType()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Char:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ return 0;
+ case QVariant::Double:
+ case QMetaType::Float:
+ return 1;
+ default:
+ return 2;
+ }
+}
+
+/*!
+ \internal
+ return true if \a value contains a numerical type
+
+ This function is used by our Q{Tree,Widget,Table}WidgetModel classes to sort.
+*/
+bool QAbstractItemModelPrivate::variantLessThan(const QVariant &v1, const QVariant &v2)
+{
+ switch(qMax(typeOfVariant(v1), typeOfVariant(v2)))
+ {
+ case 0: //integer type
+ return v1.toLongLong() < v2.toLongLong();
+ case 1: //floating point
+ return v1.toReal() < v2.toReal();
+ default:
+ return v1.toString().localeAwareCompare(v2.toString()) < 0;
+ }
+}
+
+void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
+{
+ if (data->index.isValid()) {
+ int removed = persistent.indexes.remove(data->index);
+ Q_ASSERT_X(removed == 1, "QPersistentModelIndex::~QPersistentModelIndex",
+ "persistent model indexes corrupted"); //maybe the index was somewhat invalid?
+ // This assert may happen if the model use changePersistentIndex in a way that could result on two
+ // QPersistentModelIndex pointing to the same index.
+ Q_UNUSED(removed);
+ }
+ // make sure our optimization still works
+ for (int i = persistent.moved.count() - 1; i >= 0; --i) {
+ int idx = persistent.moved[i].indexOf(data);
+ if (idx >= 0)
+ persistent.moved[i].remove(idx);
+ }
+ // update the references to invalidated persistent indexes
+ for (int i = persistent.invalidated.count() - 1; i >= 0; --i) {
+ int idx = persistent.invalidated[i].indexOf(data);
+ if (idx >= 0)
+ persistent.invalidated[i].remove(idx);
+ }
+
+}
+
+void QAbstractItemModelPrivate::rowsAboutToBeInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ Q_Q(QAbstractItemModel);
+ Q_UNUSED(last);
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ if (first < q->rowCount(parent)) {
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ const QModelIndex &index = data->index;
+ if (index.row() >= first && index.isValid() && index.parent() == parent) {
+ persistent_moved.append(data);
+ }
+ }
+ }
+ persistent.moved.push(persistent_moved);
+}
+
+void QAbstractItemModelPrivate::rowsInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row() + count, old.column(), parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count << ',' << old.column() << ") in model" << q_func();
+ }
+ }
+}
+
+void QAbstractItemModelPrivate::itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved_explicitly;
+ QVector<QPersistentModelIndexData *> persistent_moved_in_source;
+ QVector<QPersistentModelIndexData *> persistent_moved_in_destination;
+
+ QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it;
+ const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator begin = persistent.indexes.constBegin();
+ const QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator end = persistent.indexes.constEnd();
+
+ const bool sameParent = (srcParent == destinationParent);
+ const bool movingUp = (srcFirst > destinationChild);
+
+ for ( it = begin; it != end; ++it) {
+ QPersistentModelIndexData *data = *it;
+ const QModelIndex &index = data->index;
+ const QModelIndex &parent = index.parent();
+ const bool isSourceIndex = (parent == srcParent);
+ const bool isDestinationIndex = (parent == destinationParent);
+
+ int childPosition;
+ if (orientation == Qt::Vertical)
+ childPosition = index.row();
+ else
+ childPosition = index.column();
+
+ if (!index.isValid() || !(isSourceIndex || isDestinationIndex ) )
+ continue;
+
+ if (!sameParent && isDestinationIndex) {
+ if (childPosition >= destinationChild)
+ persistent_moved_in_destination.append(data);
+ continue;
+ }
+
+ if (sameParent && movingUp && childPosition < destinationChild)
+ continue;
+
+ if (sameParent && !movingUp && childPosition < srcFirst )
+ continue;
+
+ if (!sameParent && childPosition < srcFirst)
+ continue;
+
+ if (sameParent && (childPosition > srcLast) && (childPosition >= destinationChild ))
+ continue;
+
+ if ((childPosition <= srcLast) && (childPosition >= srcFirst)) {
+ persistent_moved_explicitly.append(data);
+ } else {
+ persistent_moved_in_source.append(data);
+ }
+ }
+ persistent.moved.push(persistent_moved_explicitly);
+ persistent.moved.push(persistent_moved_in_source);
+ persistent.moved.push(persistent_moved_in_destination);
+}
+
+/*!
+ \internal
+
+ Moves persistent indexes \a indexes by amount \a change. The change will be either a change in row value or a change in
+ column value depending on the value of \a orientation. The indexes may also be moved to a different parent if \a parent
+ differs from the existing parent for the index.
+*/
+void QAbstractItemModelPrivate::movePersistentIndexes(QVector<QPersistentModelIndexData *> indexes, int change, const QModelIndex &parent, Qt::Orientation orientation)
+{
+ QVector<QPersistentModelIndexData *>::const_iterator it;
+ const QVector<QPersistentModelIndexData *>::const_iterator begin = indexes.constBegin();
+ const QVector<QPersistentModelIndexData *>::const_iterator end = indexes.constEnd();
+
+ for (it = begin; it != end; ++it)
+ {
+ QPersistentModelIndexData *data = *it;
+
+ int row = data->index.row();
+ int column = data->index.column();
+
+ if (Qt::Vertical == orientation)
+ row += change;
+ else
+ column += change;
+
+ persistent.indexes.erase(persistent.indexes.find(data->index));
+ data->index = q_func()->index(row, column, parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endMoveRows: Invalid index (" << row << "," << column << ") in model" << q_func();
+ }
+ }
+}
+
+void QAbstractItemModelPrivate::itemsMoved(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation)
+{
+ QVector<QPersistentModelIndexData *> moved_in_destination = persistent.moved.pop();
+ QVector<QPersistentModelIndexData *> moved_in_source = persistent.moved.pop();
+ QVector<QPersistentModelIndexData *> moved_explicitly = persistent.moved.pop();
+
+ const bool sameParent = (sourceParent == destinationParent);
+ const bool movingUp = (sourceFirst > destinationChild);
+
+ const int explicit_change = (!sameParent || movingUp) ? destinationChild - sourceFirst : destinationChild - sourceLast - 1 ;
+ const int source_change = (!sameParent || !movingUp) ? -1*(sourceLast - sourceFirst + 1) : sourceLast - sourceFirst + 1 ;
+ const int destination_change = sourceLast - sourceFirst + 1;
+
+ movePersistentIndexes(moved_explicitly, explicit_change, destinationParent, orientation);
+ movePersistentIndexes(moved_in_source, source_change, sourceParent, orientation);
+ movePersistentIndexes(moved_in_destination, destination_change, destinationParent, orientation);
+}
+
+void QAbstractItemModelPrivate::rowsAboutToBeRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ QVector<QPersistentModelIndexData *> persistent_invalidated;
+ // find the persistent indexes that are affected by the change, either by being in the removed subtree
+ // or by being on the same level and below the removed rows
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ bool level_changed = false;
+ QModelIndex current = data->index;
+ while (current.isValid()) {
+ QModelIndex current_parent = current.parent();
+ if (current_parent == parent) { // on the same level as the change
+ if (!level_changed && current.row() > last) // below the removed rows
+ persistent_moved.append(data);
+ else if (current.row() <= last && current.row() >= first) // in the removed subtree
+ persistent_invalidated.append(data);
+ break;
+ }
+ current = current_parent;
+ level_changed = true;
+ }
+ }
+
+ persistent.moved.push(persistent_moved);
+ persistent.invalidated.push(persistent_invalidated);
+}
+
+void QAbstractItemModelPrivate::rowsRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row() - count, old.column(), parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count << ',' << old.column() << ") in model" << q_func();
+ }
+ }
+ QVector<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_invalidated.constBegin();
+ it != persistent_invalidated.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ persistent.indexes.erase(persistent.indexes.find(data->index));
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+}
+
+void QAbstractItemModelPrivate::columnsAboutToBeInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ Q_Q(QAbstractItemModel);
+ Q_UNUSED(last);
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ if (first < q->columnCount(parent)) {
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ const QModelIndex &index = data->index;
+ if (index.column() >= first && index.isValid() && index.parent() == parent)
+ persistent_moved.append(data);
+ }
+ }
+ persistent.moved.push(persistent_moved);
+}
+
+void QAbstractItemModelPrivate::columnsInserted(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row(), old.column() + count, parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() << ',' << old.column() + count << ") in model" << q_func();
+ }
+ }
+}
+
+void QAbstractItemModelPrivate::columnsAboutToBeRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved;
+ QVector<QPersistentModelIndexData *> persistent_invalidated;
+ // find the persistent indexes that are affected by the change, either by being in the removed subtree
+ // or by being on the same level and to the right of the removed columns
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = persistent.indexes.constBegin();
+ it != persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ bool level_changed = false;
+ QModelIndex current = data->index;
+ while (current.isValid()) {
+ QModelIndex current_parent = current.parent();
+ if (current_parent == parent) { // on the same level as the change
+ if (!level_changed && current.column() > last) // right of the removed columns
+ persistent_moved.append(data);
+ else if (current.column() <= last && current.column() >= first) // in the removed subtree
+ persistent_invalidated.append(data);
+ break;
+ }
+ current = current_parent;
+ level_changed = true;
+ }
+ }
+
+ persistent.moved.push(persistent_moved);
+ persistent.invalidated.push(persistent_invalidated);
+
+}
+
+void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
+ int first, int last)
+{
+ QVector<QPersistentModelIndexData *> persistent_moved = persistent.moved.pop();
+ int count = (last - first) + 1; // it is important to only use the delta, because the change could be nested
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_moved.constBegin();
+ it != persistent_moved.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ QModelIndex old = data->index;
+ persistent.indexes.erase(persistent.indexes.find(old));
+ data->index = q_func()->index(old.row(), old.column() - count, parent);
+ if (data->index.isValid()) {
+ persistent.insertMultiAtEnd(data->index, data);
+ } else {
+ qWarning() << "QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() << ',' << old.column() - count << ") in model" << q_func();
+ }
+ }
+ QVector<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = persistent_invalidated.constBegin();
+ it != persistent_invalidated.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ persistent.indexes.erase(persistent.indexes.find(data->index));
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+}
+
+/*!
+ \class QModelIndex
+
+ \brief The QModelIndex class is used to locate data in a data model.
+
+ \ingroup model-view
+
+
+ This class is used as an index into item models derived from
+ QAbstractItemModel. The index is used by item views, delegates, and
+ selection models to locate an item in the model.
+
+ New QModelIndex objects are created by the model using the
+ QAbstractItemModel::createIndex() function. An \e invalid model index can
+ be constructed with the QModelIndex constructor. Invalid indexes are often
+ used as parent indexes when referring to top-level items in a model.
+
+ Model indexes refer to items in models, and contain all the information
+ required to specify their locations in those models. Each index is located
+ in a given row and column, and may have a parent index; use row(),
+ column(), and parent() to obtain this information. Each top-level item in a
+ model is represented by a model index that does not have a parent index -
+ in this case, parent() will return an invalid model index, equivalent to an
+ index constructed with the zero argument form of the QModelIndex()
+ constructor.
+
+ To obtain a model index that refers to an existing item in a model, call
+ QAbstractItemModel::index() with the required row and column values, and
+ the model index of the parent. When referring to top-level items in a
+ model, supply QModelIndex() as the parent index.
+
+ The model() function returns the model that the index references as a
+ QAbstractItemModel. The child() function is used to examine items held
+ under the index in the model. The sibling() function allows you to traverse
+ items in the model on the same level as the index.
+
+ \note Model indexes should be used immediately and then discarded. You
+ should not rely on indexes to remain valid after calling model functions
+ that change the structure of the model or delete items. If you need to
+ keep a model index over time use a QPersistentModelIndex.
+
+ \sa {Model/View Programming}, QPersistentModelIndex, QAbstractItemModel
+*/
+
+/*!
+ \fn QModelIndex::QModelIndex()
+
+ Creates a new empty model index. This type of model index is used to
+ indicate that the position in the model is invalid.
+
+ \sa isValid() QAbstractItemModel
+*/
+
+/*!
+ \fn QModelIndex::QModelIndex(int row, int column, void *data, const QAbstractItemModel *model)
+
+ \internal
+
+ Creates a new model index at the given \a row and \a column,
+ pointing to some \a data.
+*/
+
+/*!
+ \fn QModelIndex::QModelIndex(const QModelIndex &other)
+
+ Creates a new model index that is a copy of the \a other model
+ index.
+*/
+
+/*!
+ \fn QModelIndex::~QModelIndex()
+
+ Destroys the model index.
+*/
+
+/*!
+ \fn int QModelIndex::row() const
+
+ Returns the row this model index refers to.
+*/
+
+
+/*!
+ \fn int QModelIndex::column() const
+
+ Returns the column this model index refers to.
+*/
+
+
+/*!
+ \fn void *QModelIndex::internalPointer() const
+
+ Returns a \c{void} \c{*} pointer used by the model to associate
+ the index with the internal data structure.
+
+ \sa QAbstractItemModel::createIndex()
+*/
+
+/*!
+ \fn void *QModelIndex::internalId() const
+
+ Returns a \c{qint64} used by the model to associate
+ the index with the internal data structure.
+
+ \sa QAbstractItemModel::createIndex()
+*/
+
+/*!
+ \fn bool QModelIndex::isValid() const
+
+ Returns true if this model index is valid; otherwise returns false.
+
+ A valid index belongs to a model, and has non-negative row and column
+ numbers.
+
+ \sa model(), row(), column()
+*/
+
+/*!
+ \fn const QAbstractItemModel *QModelIndex::model() const
+
+ Returns a pointer to the model containing the item that this index
+ refers to.
+
+ A const pointer to the model is returned because calls to non-const
+ functions of the model might invalidate the model index and possibly
+ crash your application.
+*/
+
+/*!
+ \fn QModelIndex QModelIndex::sibling(int row, int column) const
+
+ Returns the sibling at \a row and \a column. If there is no sibling at this
+ position, an invalid QModelIndex is returned.
+
+ \sa parent(), child()
+*/
+
+/*!
+ \fn QModelIndex QModelIndex::child(int row, int column) const
+
+ Returns the child of the model index that is stored in the given \a row and
+ \a column.
+
+ \note This function does not work for an invalid model index which is often
+ used as the root index.
+
+ \sa parent(), sibling()
+*/
+
+/*!
+ \fn QVariant QModelIndex::data(int role) const
+
+ Returns the data for the given \a role for the item referred to by the
+ index.
+*/
+
+/*!
+ \fn Qt::ItemFlags QModelIndex::flags() const
+ \since 4.2
+
+ Returns the flags for the item referred to by the index.
+*/
+
+/*!
+ \fn bool QModelIndex::operator==(const QModelIndex &other) const
+
+ Returns true if this model index refers to the same location as the
+ \a other model index; otherwise returns false.
+
+ All values in the model index are used when comparing with another model
+ index.
+*/
+
+
+/*!
+ \fn bool QModelIndex::operator!=(const QModelIndex &other) const
+
+ Returns true if this model index does not refer to the same location as
+ the \a other model index; otherwise returns false.
+*/
+
+
+/*!
+ \fn QModelIndex QModelIndex::parent() const
+
+ Returns the parent of the model index, or QModelIndex() if it has no
+ parent.
+
+ \sa child(), sibling(), model()
+*/
+
+/*!
+ \class QAbstractItemModel
+
+ \brief The QAbstractItemModel class provides the abstract interface for
+ item model classes.
+
+ \ingroup model-view
+
+
+ The QAbstractItemModel class defines the standard interface that item
+ models must use to be able to interoperate with other components in the
+ model/view architecture. It is not supposed to be instantiated directly.
+ Instead, you should subclass it to create new models.
+
+ The QAbstractItemModel class is one of the \l{Model/View Classes}
+ and is part of Qt's \l{Model/View Programming}{model/view framework}.
+
+ If you need a model to use with a QListView or a QTableView, you should
+ consider subclassing QAbstractListModel or QAbstractTableModel instead of
+ this class.
+
+ The underlying data model is exposed to views and delegates as a hierarchy
+ of tables. If you do not make use of the hierarchy, then the model is a
+ simple table of rows and columns. Each item has a unique index specified by
+ a QModelIndex.
+
+ \image modelindex-no-parent.png
+
+ Every item of data that can be accessed via a model has an associated model
+ index. You can obtain this model index using the index() function. Each
+ index may have a sibling() index; child items have a parent() index.
+
+ Each item has a number of data elements associated with it and they can be
+ retrieved by specifying a role (see \l Qt::ItemDataRole) to the model's
+ data() function. Data for all available roles can be obtained at the same
+ time using the itemData() function.
+
+ Data for each role is set using a particular \l Qt::ItemDataRole. Data for
+ individual roles are set individually with setData(), or they can be set
+ for all roles with setItemData().
+
+ Items can be queried with flags() (see \l Qt::ItemFlag) to see if they can
+ be selected, dragged, or manipulated in other ways.
+
+ If an item has child objects, hasChildren() returns true for the
+ corresponding index.
+
+ The model has a rowCount() and a columnCount() for each level of the
+ hierarchy. Rows and columns can be inserted and removed with insertRows(),
+ insertColumns(), removeRows(), and removeColumns().
+
+ The model emits signals to indicate changes. For example, dataChanged() is
+ emitted whenever items of data made available by the model are changed.
+ Changes to the headers supplied by the model cause headerDataChanged() to
+ be emitted. If the structure of the underlying data changes, the model can
+ emit layoutChanged() to indicate to any attached views that they should
+ redisplay any items shown, taking the new structure into account.
+
+ The items available through the model can be searched for particular data
+ using the match() function.
+
+ To sort the model, you can use sort().
+
+
+ \section1 Subclassing
+
+ \note Some general guidelines for subclassing models are available in the
+ \l{Model Subclassing Reference}.
+
+ When subclassing QAbstractItemModel, at the very least you must implement
+ index(), parent(), rowCount(), columnCount(), and data(). These functions
+ are used in all read-only models, and form the basis of editable models.
+
+ You can also reimplement hasChildren() to provide special behavior for
+ models where the implementation of rowCount() is expensive. This makes it
+ possible for models to restrict the amount of data requested by views, and
+ can be used as a way to implement lazy population of model data.
+
+ To enable editing in your model, you must also implement setData(), and
+ reimplement flags() to ensure that \c ItemIsEditable is returned. You can
+ also reimplement headerData() and setHeaderData() to control the way the
+ headers for your model are presented.
+
+ The dataChanged() and headerDataChanged() signals must be emitted
+ explicitly when reimplementing the setData() and setHeaderData() functions,
+ respectively.
+
+ Custom models need to create model indexes for other components to use. To
+ do this, call createIndex() with suitable row and column numbers for the
+ item, and an identifier for it, either as a pointer or as an integer value.
+ The combination of these values must be unique for each item. Custom models
+ typically use these unique identifiers in other reimplemented functions to
+ retrieve item data and access information about the item's parents and
+ children. See the \l{Simple Tree Model Example} for more information about
+ unique identifiers.
+
+ It is not necessary to support every role defined in Qt::ItemDataRole.
+ Depending on the type of data contained within a model, it may only be
+ useful to implement the data() function to return valid information for
+ some of the more common roles. Most models provide at least a textual
+ representation of item data for the Qt::DisplayRole, and well-behaved
+ models should also provide valid information for the Qt::ToolTipRole and
+ Qt::WhatsThisRole. Supporting these roles enables models to be used with
+ standard Qt views. However, for some models that handle highly-specialized
+ data, it may be appropriate to provide data only for user-defined roles.
+
+ Models that provide interfaces to resizable data structures can provide
+ implementations of insertRows(), removeRows(), insertColumns(),and
+ removeColumns(). When implementing these functions, it is important to
+ notify any connected views about changes to the model's dimensions both
+ \e before and \e after they occur:
+
+ \list
+ \o An insertRows() implementation must call beginInsertRows() \e before
+ inserting new rows into the data structure, and endInsertRows()
+ \e{immediately afterwards}.
+ \o An insertColumns() implementation must call beginInsertColumns()
+ \e before inserting new columns into the data structure, and
+ endInsertColumns() \e{immediately afterwards}.
+ \o A removeRows() implementation must call beginRemoveRows() \e before
+ the rows are removed from the data structure, and endRemoveRows()
+ \e{immediately afterwards}.
+ \o A removeColumns() implementation must call beginRemoveColumns()
+ \e before the columns are removed from the data structure, and
+ endRemoveColumns() \e{immediately afterwards}.
+ \endlist
+
+ The \e private signals that these functions emit give attached components
+ the chance to take action before any data becomes unavailable. The
+ encapsulation of the insert and remove operations with these begin and end
+ functions also enables the model to manage \l{QPersistentModelIndex}
+ {persistent model indexes} correctly. \bold{If you want selections to be
+ handled properly, you must ensure that you call these functions.} If you
+ insert or remove an item with children, you do not need to call these
+ functions for the child items. In other words, the parent item will take
+ care of its child items.
+
+ To create models that populate incrementally, you can reimplement
+ fetchMore() and canFetchMore(). If the reimplementation of fetchMore() adds
+ rows to the model, \l{QAbstractItemModel::}{beginInsertRows()} and
+ \l{QAbstractItemModel::}{endInsertRows()} must be called.
+
+ \sa {Model Classes}, {Model Subclassing Reference}, QModelIndex,
+ QAbstractItemView, {Using drag and drop with item views},
+ {Simple DOM Model Example}, {Simple Tree Model Example},
+ {Editable Tree Model Example}, {Fetch More Example}
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::index(int row, int column, const QModelIndex &parent) const = 0
+
+ Returns the index of the item in the model specified by the given \a row,
+ \a column and \a parent index.
+
+ When reimplementing this function in a subclass, call createIndex() to
+ generate model indexes that other components can use to refer to items in
+ your model.
+
+ \sa createIndex()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::insertColumn(int column, const QModelIndex &parent)
+
+ Inserts a single column before the given \a column in the child items of
+ the \a parent specified.
+
+ Returns true if the column is inserted; otherwise returns false.
+
+ \sa insertColumns() insertRow() removeColumn()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::insertRow(int row, const QModelIndex &parent)
+
+ \note The base class implementation of this function does nothing and
+ returns false.
+
+ Inserts a single row before the given \a row in the child items of the
+ \a parent specified.
+
+ Returns true if the row is inserted; otherwise returns false.
+
+ \sa insertRows() insertColumn() removeRow()
+*/
+
+/*!
+ \fn QObject *QAbstractItemModel::parent() const
+ \internal
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::parent(const QModelIndex &index) const = 0
+
+ Returns the parent of the model item with the given \a index. If the item
+ has no parent, an invalid QModelIndex is returned.
+
+ A common convention used in models that expose tree data structures is that
+ only items in the first column have children. For that case, when
+ reimplementing this function in a subclass the column of the returned
+ QModelIndex would be 0.
+
+ When reimplementing this function in a subclass, be careful to avoid
+ calling QModelIndex member functions, such as QModelIndex::parent(), since
+ indexes belonging to your model will simply call your implementation,
+ leading to infinite recursion.
+
+ \sa createIndex()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::removeColumn(int column, const QModelIndex &parent)
+
+ Removes the given \a column from the child items of the \a parent
+ specified.
+
+ Returns true if the column is removed; otherwise returns false.
+
+ \sa removeColumns(), removeRow(), insertColumn()
+*/
+
+/*!
+ \fn bool QAbstractItemModel::removeRow(int row, const QModelIndex &parent)
+
+ Removes the given \a row from the child items of the \a parent specified.
+
+ Returns true if the row is removed; otherwise returns false.
+
+ This is a convenience function that calls removeRows(). The
+ QAbstractItemModel implementation of removeRows() does nothing.
+
+ \sa removeRows(), removeColumn(), insertRow()
+*/
+
+/*!
+ \fn void QAbstractItemModel::headerDataChanged(Qt::Orientation orientation, int first, int last)
+
+ This signal is emitted whenever a header is changed. The \a orientation
+ indicates whether the horizontal or vertical header has changed. The
+ sections in the header from the \a first to the \a last need to be updated.
+
+ When reimplementing the setHeaderData() function, this signal must be
+ emitted explicitly.
+
+ If you are changing the number of columns or rows you do not need to emit
+ this signal, but use the begin/end functions (refer to the section on
+ subclassing in the QAbstractItemModel class description for details).
+
+ \sa headerData(), setHeaderData(), dataChanged()
+*/
+
+/*!
+ \fn void QAbstractItemModel::layoutAboutToBeChanged()
+ \since 4.2
+
+ This signal is emitted just before the layout of a model is changed.
+ Components connected to this signal use it to adapt to changes in the
+ model's layout.
+
+ Subclasses should update any persistent model indexes after emitting
+ layoutAboutToBeChanged().
+
+ \sa layoutChanged(), changePersistentIndex()
+*/
+
+/*!
+ \fn void QAbstractItemModel::layoutChanged()
+
+ This signal is emitted whenever the layout of items exposed by the model
+ has changed; for example, when the model has been sorted. When this signal
+ is received by a view, it should update the layout of items to reflect this
+ change.
+
+ When subclassing QAbstractItemModel or QAbstractProxyModel, ensure that you
+ emit layoutAboutToBeChanged() before changing the order of items or
+ altering the structure of the data you expose to views, and emit
+ layoutChanged() after changing the layout.
+
+ Subclasses should update any persistent model indexes before emitting
+ layoutChanged(). In other words, when the structure changes:
+
+ \list
+ \o emit layoutAboutToBeChanged
+ \o Remember the QModelIndex that will change
+ \o Update your internal data
+ \o Call changePersistentIndex()
+ \o emit layoutChanged
+ \endlist
+
+ \sa layoutAboutToBeChanged(), dataChanged(), headerDataChanged(), modelReset(),
+ changePersistentIndex()
+*/
+
+/*!
+ Constructs an abstract item model with the given \a parent.
+*/
+QAbstractItemModel::QAbstractItemModel(QObject *parent)
+ : QObject(*new QAbstractItemModelPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAbstractItemModel::QAbstractItemModel(QAbstractItemModelPrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Destroys the abstract item model.
+*/
+QAbstractItemModel::~QAbstractItemModel()
+{
+ d_func()->invalidatePersistentIndexes();
+}
+
+/*!
+ \fn QModelIndex QAbstractItemModel::sibling(int row, int column, const QModelIndex &index) const
+
+ Returns the sibling at \a row and \a column for the item at \a index, or an
+ invalid QModelIndex if there is no sibling at that location.
+
+ sibling() is just a convenience function that finds the item's parent, and
+ uses it to retrieve the index of the child item in the specified \a row and
+ \a column.
+
+ \sa index(), QModelIndex::row(), QModelIndex::column()
+*/
+
+
+/*!
+ \fn int QAbstractItemModel::rowCount(const QModelIndex &parent) const
+
+ Returns the number of rows under the given \a parent. When the parent is
+ valid it means that rowCount is returning the number of children of parent.
+
+ \note When implementing a table based model, rowCount() should return 0
+ when the parent is valid.
+
+ \sa columnCount()
+*/
+
+/*!
+ \fn int QAbstractItemModel::columnCount(const QModelIndex &parent) const
+
+ Returns the number of columns for the children of the given \a parent.
+
+ In most subclasses, the number of columns is independent of the \a parent.
+
+ For example:
+
+ \snippet examples/itemviews/simpledommodel/dommodel.cpp 2
+
+ \note When implementing a table based model, columnCount() should return 0
+ when the parent is valid.
+
+ \sa rowCount()
+*/
+
+/*!
+ \fn void QAbstractItemModel::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
+
+ This signal is emitted whenever the data in an existing item changes.
+
+ If the items are of the same parent, the affected ones are those between
+ \a topLeft and \a bottomRight inclusive. If the items do not have the same
+ parent, the behavior is undefined.
+
+ When reimplementing the setData() function, this signal must be emitted
+ explicitly.
+
+ \sa headerDataChanged(), setData(), layoutChanged()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after rows have been inserted into the
+ model. The new items are those between \a start and \a end
+ inclusive, under the given \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes in the
+ model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertRows(), beginInsertRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before rows are inserted into the model. The
+ new items will be positioned between \a start and \a end inclusive, under
+ the given \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes
+ in the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertRows(), beginInsertRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after rows have been removed from the model. The
+ removed items are those between \a start and \a end inclusive, under the
+ given \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes
+ in the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeRows(), beginRemoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before rows are removed from the model. The
+ items that will be removed are those between \a start and \a end inclusive,
+ under the given \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes
+ in the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeRows(), beginRemoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+ \since 4.6
+
+ This signal is emitted after rows have been moved within the
+ model. The items between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the row \a destinationRow.
+
+ \bold{Note:} Components connected to this signal use it to adapt to changes
+ in the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::rowsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+ \since 4.6
+
+ This signal is emitted just before rows are moved within the
+ model. The items that will be moved are those between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent
+ starting at the row \a destinationRow.
+
+ \bold{Note:} Components connected to this signal use it to adapt to changes
+ in the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
+ \since 4.6
+
+ This signal is emitted after columns have been moved within the
+ model. The items between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item have been moved to \a destinationParent
+ starting at the column \a destinationColumn.
+
+ \bold{Note:} Components connected to this signal use it to adapt to changes
+ in the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsAboutToBeMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn)
+ \since 4.6
+
+ This signal is emitted just before columns are moved within the
+ model. The items that will be moved are those between \a sourceStart and \a sourceEnd
+ inclusive, under the given \a sourceParent item. They will be moved to \a destinationParent
+ starting at the column \a destinationColumn.
+
+ \bold{Note:} Components connected to this signal use it to adapt to changes
+ in the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa beginMoveRows()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after columns have been inserted into the model. The
+ new items are those between \a start and \a end inclusive, under the given
+ \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes in the
+ model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertColumns(), beginInsertColumns()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsAboutToBeInserted(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before columns are inserted into the model. The
+ new items will be positioned between \a start and \a end inclusive, under
+ the given \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes in the
+ model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa insertColumns(), beginInsertColumns()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted after columns have been removed from the model.
+ The removed items are those between \a start and \a end inclusive,
+ under the given \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes in
+ the model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeColumns(), beginRemoveColumns()
+*/
+
+/*!
+ \fn void QAbstractItemModel::columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
+
+ This signal is emitted just before columns are removed from the model. The
+ items to be removed are those between \a start and \a end inclusive, under
+ the given \a parent item.
+
+ \note Components connected to this signal use it to adapt to changes in the
+ model's dimensions. It can only be emitted by the QAbstractItemModel
+ implementation, and cannot be explicitly emitted in subclass code.
+
+ \sa removeColumns(), beginRemoveColumns()
+*/
+
+/*!
+ Returns true if the model returns a valid QModelIndex for \a row and
+ \a column with \a parent, otherwise returns false.
+*/
+bool QAbstractItemModel::hasIndex(int row, int column, const QModelIndex &parent) const
+{
+ if (row < 0 || column < 0)
+ return false;
+ return row < rowCount(parent) && column < columnCount(parent);
+}
+
+
+/*!
+ Returns true if \a parent has any children; otherwise returns false.
+
+ Use rowCount() on the parent to find out the number of children.
+
+ \sa parent() index()
+*/
+bool QAbstractItemModel::hasChildren(const QModelIndex &parent) const
+{
+ return (rowCount(parent) > 0) && (columnCount(parent) > 0);
+}
+
+
+/*!
+ Returns a map with values for all predefined roles in the model for the
+ item at the given \a index.
+
+ Reimplement this function if you want to extend the default behavior of
+ this function to include custom roles in the map.
+
+ \sa Qt::ItemDataRole, data()
+*/
+QMap<int, QVariant> QAbstractItemModel::itemData(const QModelIndex &index) const
+{
+ QMap<int, QVariant> roles;
+ for (int i = 0; i < Qt::UserRole; ++i) {
+ QVariant variantData = data(index, i);
+ if (variantData.isValid())
+ roles.insert(i, variantData);
+ }
+ return roles;
+}
+
+/*!
+ Sets the \a role data for the item at \a index to \a value.
+
+ Returns true if successful; otherwise returns false.
+
+ The dataChanged() signal should be emitted if the data was successfully
+ set.
+
+ The base class implementation returns false. This function and data() must
+ be reimplemented for editable models.
+
+ \sa Qt::ItemDataRole, data(), itemData()
+*/
+bool QAbstractItemModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ Q_UNUSED(index);
+ Q_UNUSED(value);
+ Q_UNUSED(role);
+ return false;
+}
+
+/*!
+ \fn QVariant QAbstractItemModel::data(const QModelIndex &index, int role) const = 0
+
+ Returns the data stored under the given \a role for the item referred to
+ by the \a index.
+
+ \note If you do not have a value to return, return an \bold invalid
+ QVariant instead of returning 0.
+
+ \sa Qt::ItemDataRole, setData(), headerData()
+*/
+
+/*!
+ Sets the role data for the item at \a index to the associated value in
+ \a roles, for every Qt::ItemDataRole.
+
+ Returns true if successful; otherwise returns false.
+
+ Roles that are not in \a roles will not be modified.
+
+ \sa setData() data() itemData()
+*/
+bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
+{
+ bool b = true;
+ for (QMap<int, QVariant>::ConstIterator it = roles.begin(); it != roles.end(); ++it)
+ b = b && setData(index, it.value(), it.key());
+ return b;
+}
+
+/*!
+ Returns a list of MIME types that can be used to describe a list of model
+ indexes.
+
+ \sa mimeData()
+*/
+QStringList QAbstractItemModel::mimeTypes() const
+{
+ QStringList types;
+ types << QLatin1String("application/x-qabstractitemmodeldatalist");
+ return types;
+}
+
+/*!
+ Returns an object that contains serialized items of data corresponding to
+ the list of \a indexes specified. The formats used to describe the encoded
+ data is obtained from the mimeTypes() function.
+
+ If the list of indexes is empty, or there are no supported MIME types, 0 is
+ returned rather than a serialized empty list.
+
+ \sa mimeTypes(), dropMimeData()
+*/
+QMimeData *QAbstractItemModel::mimeData(const QModelIndexList &indexes) const
+{
+ if (indexes.count() <= 0)
+ return 0;
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return 0;
+ QMimeData *data = new QMimeData();
+ QString format = types.at(0);
+ QByteArray encoded;
+ QDataStream stream(&encoded, QIODevice::WriteOnly);
+ encodeData(indexes, stream);
+ data->setData(format, encoded);
+ return data;
+}
+
+/*!
+ Handles the \a data supplied by a drag and drop operation that ended with
+ the given \a action.
+
+ Returns true if the data and action can be handled by the model; otherwise
+ returns false.
+
+ Although the specified \a row, \a column and \a parent indicate the
+ location of an item in the model where the operation ended, it is the
+ responsibility of the view to provide a suitable location for where the
+ data should be inserted.
+
+ For instance, a drop action on an item in a QTreeView can result in new
+ items either being inserted as children of the item specified by \a row,
+ \a column, and \a parent, or as siblings of the item.
+
+ When row and column are -1 it means that it is up to the model to decide
+ where to place the data. This can occur in a tree when data is dropped on
+ a parent. Models will usually append the data to the parent in this case.
+
+ \sa supportedDropActions(), {Using drag and drop with item views}
+*/
+bool QAbstractItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ // check if the action is supported
+ if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
+ return false;
+ // check if the format is supported
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return false;
+ QString format = types.at(0);
+ if (!data->hasFormat(format))
+ return false;
+ if (row > rowCount(parent))
+ row = rowCount(parent);
+ if (row == -1)
+ row = rowCount(parent);
+ if (column == -1)
+ column = 0;
+ // decode and insert
+ QByteArray encoded = data->data(format);
+ QDataStream stream(&encoded, QIODevice::ReadOnly);
+ return decodeData(row, column, parent, stream);
+}
+
+/*!
+ \since 4.2
+
+ Returns the drop actions supported by this model.
+
+ The default implementation returns Qt::CopyAction. Reimplement this
+ function if you wish to support additional actions. You must also
+ reimplement the dropMimeData() function to handle the additional
+ operations.
+
+ \sa dropMimeData(), Qt::DropActions, {Using drag and drop with item
+ views}
+*/
+Qt::DropActions QAbstractItemModel::supportedDropActions() const
+{
+ return Qt::CopyAction;
+}
+
+/*!
+ Returns the actions supported by the data in this model.
+
+ The default implementation returns supportedDropActions() unless specific
+ values have been set with setSupportedDragActions().
+
+ supportedDragActions() is used by QAbstractItemView::startDrag() as the
+ default values when a drag occurs.
+
+ \sa Qt::DropActions, {Using drag and drop with item views}
+*/
+Qt::DropActions QAbstractItemModel::supportedDragActions() const
+{
+ // ### Qt 5: make this virtual or these properties
+ Q_D(const QAbstractItemModel);
+ if (d->supportedDragActions != -1)
+ return d->supportedDragActions;
+ return supportedDropActions();
+}
+
+/*!
+ \since 4.2
+
+ Sets the supported drag \a actions for the items in the model.
+
+ \sa supportedDragActions(), {Using drag and drop with item views}
+*/
+void QAbstractItemModel::setSupportedDragActions(Qt::DropActions actions)
+{
+ Q_D(QAbstractItemModel);
+ d->supportedDragActions = actions;
+}
+
+/*!
+ \note The base class implementation of this function does nothing and
+ returns false.
+
+ On models that support this, inserts \a count rows into the model before
+ the given \a row. Items in the new row will be children of the item
+ represented by the \a parent model index.
+
+ If \a row is 0, the rows are prepended to any existing rows in the parent.
+
+ If \a row is rowCount(), the rows are appended to any existing rows in the
+ parent.
+
+ If \a parent has no children, a single column with \a count rows is
+ inserted.
+
+ Returns true if the rows were successfully inserted; otherwise returns
+ false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support insertions. Alternatively, you can provide your own API for
+ altering the data. In either case, you will need to call
+ beginInsertRows() and endInsertRows() to notify other components that the
+ model has changed.
+
+ \sa insertColumns(), removeRows(), beginInsertRows(), endInsertRows()
+*/
+bool QAbstractItemModel::insertRows(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ On models that support this, inserts \a count new columns into the model
+ before the given \a column. The items in each new column will be children
+ of the item represented by the \a parent model index.
+
+ If \a column is 0, the columns are prepended to any existing columns.
+
+ If \a column is columnCount(), the columns are appended to any existing
+ columns.
+
+ If \a parent has no children, a single row with \a count columns is
+ inserted.
+
+ Returns true if the columns were successfully inserted; otherwise returns
+ false.
+
+ The base class implementation does nothing and returns false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support insertions. Alternatively, you can provide your own API for
+ altering the data.
+
+ \sa insertRows(), removeColumns(), beginInsertColumns(), endInsertColumns()
+*/
+bool QAbstractItemModel::insertColumns(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ On models that support this, removes \a count rows starting with the given
+ \a row under parent \a parent from the model.
+
+ Returns true if the rows were successfully removed; otherwise returns
+ false.
+
+ The base class implementation does nothing and returns false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support removing. Alternatively, you can provide your own API for
+ altering the data.
+
+ \sa removeRow(), removeColumns(), insertColumns(), beginRemoveRows(),
+ endRemoveRows()
+*/
+bool QAbstractItemModel::removeRows(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ On models that support this, removes \a count columns starting with the
+ given \a column under parent \a parent from the model.
+
+ Returns true if the columns were successfully removed; otherwise returns
+ false.
+
+ The base class implementation does nothing and returns false.
+
+ If you implement your own model, you can reimplement this function if you
+ want to support removing. Alternatively, you can provide your own API for
+ altering the data.
+
+ \sa removeColumn(), removeRows(), insertColumns(), beginRemoveColumns(),
+ endRemoveColumns()
+*/
+bool QAbstractItemModel::removeColumns(int, int, const QModelIndex &)
+{
+ return false;
+}
+
+/*!
+ Fetches any available data for the items with the parent specified by the
+ \a parent index.
+
+ Reimplement this if you are populating your model incrementally.
+
+ The default implementation does nothing.
+
+ \sa canFetchMore()
+*/
+void QAbstractItemModel::fetchMore(const QModelIndex &)
+{
+ // do nothing
+}
+
+/*!
+ Returns true if there is more data available for \a parent; otherwise
+ returns false.
+
+ The default implementation always returns false.
+
+ If canFetchMore() returns true, QAbstractItemView will call fetchMore().
+ However, the fetchMore() function is only called when the model is being
+ populated incrementally.
+
+ \sa fetchMore()
+*/
+bool QAbstractItemModel::canFetchMore(const QModelIndex &) const
+{
+ return false;
+}
+
+/*!
+ Returns the item flags for the given \a index.
+
+ The base class implementation returns a combination of flags that enables
+ the item (\c ItemIsEnabled) and allows it to be selected
+ (\c ItemIsSelectable).
+
+ \sa Qt::ItemFlags
+*/
+Qt::ItemFlags QAbstractItemModel::flags(const QModelIndex &index) const
+{
+ Q_D(const QAbstractItemModel);
+ if (!d->indexValid(index))
+ return 0;
+
+ return Qt::ItemIsSelectable|Qt::ItemIsEnabled;
+}
+
+/*!
+ Sorts the model by \a column in the given \a order.
+
+ The base class implementation does nothing.
+*/
+void QAbstractItemModel::sort(int column, Qt::SortOrder order)
+{
+ Q_UNUSED(column);
+ Q_UNUSED(order);
+ // do nothing
+}
+
+/*!
+ Returns a model index for the buddy of the item represented by \a index.
+ When the user wants to edit an item, the view will call this function to
+ check whether another item in the model should be edited instead. Then, the
+ view will construct a delegate using the model index returned by the buddy
+ item.
+
+ The default implementation of this function has each item as its own buddy.
+*/
+QModelIndex QAbstractItemModel::buddy(const QModelIndex &index) const
+{
+ return index;
+}
+
+/*!
+ Returns a list of indexes for the items in the column of the \a start index
+ where data stored under the given \a role matches the specified \a value.
+ The way the search is performed is defined by the \a flags given. The list
+ that is returned may be empty.
+
+ The search begins from the \a start index, and continues until the number
+ of matching data items equals \a hits, the search reaches the last row, or
+ the search reaches \a start again - depending on whether \c MatchWrap is
+ specified in \a flags. If you want to search for all matching items, use
+ \a hits = -1.
+
+ By default, this function will perform a wrapping, string-based comparison
+ on all items, searching for items that begin with the search term specified
+ by \a value.
+
+ \note The default implementation of this function only searches columns.
+ Reimplement this function to include a different search behavior.
+*/
+QModelIndexList QAbstractItemModel::match(const QModelIndex &start, int role,
+ const QVariant &value, int hits,
+ Qt::MatchFlags flags) const
+{
+ QModelIndexList result;
+ uint matchType = flags & 0x0F;
+ Qt::CaseSensitivity cs = flags & Qt::MatchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
+ bool recurse = flags & Qt::MatchRecursive;
+ bool wrap = flags & Qt::MatchWrap;
+ bool allHits = (hits == -1);
+ QString text; // only convert to a string if it is needed
+ QModelIndex p = parent(start);
+ int from = start.row();
+ int to = rowCount(p);
+
+ // iterates twice if wrapping
+ for (int i = 0; (wrap && i < 2) || (!wrap && i < 1); ++i) {
+ for (int r = from; (r < to) && (allHits || result.count() < hits); ++r) {
+ QModelIndex idx = index(r, start.column(), p);
+ if (!idx.isValid())
+ continue;
+ QVariant v = data(idx, role);
+ // QVariant based matching
+ if (matchType == Qt::MatchExactly) {
+ if (value == v)
+ result.append(idx);
+ } else { // QString based matching
+ if (text.isEmpty()) // lazy conversion
+ text = value.toString();
+ QString t = v.toString();
+ switch (matchType) {
+ case Qt::MatchRegExp:
+ if (QRegExp(text, cs).exactMatch(t))
+ result.append(idx);
+ break;
+ case Qt::MatchWildcard:
+ if (QRegExp(text, cs, QRegExp::Wildcard).exactMatch(t))
+ result.append(idx);
+ break;
+ case Qt::MatchStartsWith:
+ if (t.startsWith(text, cs))
+ result.append(idx);
+ break;
+ case Qt::MatchEndsWith:
+ if (t.endsWith(text, cs))
+ result.append(idx);
+ break;
+ case Qt::MatchFixedString:
+ if (t.compare(text, cs) == 0)
+ result.append(idx);
+ break;
+ case Qt::MatchContains:
+ default:
+ if (t.contains(text, cs))
+ result.append(idx);
+ }
+ }
+ if (recurse && hasChildren(idx)) { // search the hierarchy
+ result += match(index(0, idx.column(), idx), role,
+ (text.isEmpty() ? value : text),
+ (allHits ? -1 : hits - result.count()), flags);
+ }
+ }
+ // prepare for the next iteration
+ from = 0;
+ to = start.row();
+ }
+ return result;
+}
+
+/*!
+ Returns the row and column span of the item represented by \a index.
+
+ \note Currently, span is not used.
+*/
+
+QSize QAbstractItemModel::span(const QModelIndex &) const
+{
+ return QSize(1, 1);
+}
+
+/*!
+ \since 4.6
+
+ Sets the model's role names to \a roleNames.
+
+ This function allows mapping of role identifiers to role property names in
+ Declarative UI. This function must be called before the model is used.
+ Modifying the role names after the model has been set may result in
+ undefined behaviour.
+
+ \sa roleNames()
+*/
+void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames)
+{
+ Q_D(QAbstractItemModel);
+ d->roleNames = roleNames;
+}
+
+/*!
+ \since 4.6
+
+ Returns the model's role names.
+
+ \sa setRoleNames()
+*/
+const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const
+{
+ Q_D(const QAbstractItemModel);
+ return d->roleNames;
+}
+
+/*!
+ Lets the model know that it should submit cached information to permanent
+ storage. This function is typically used for row editing.
+
+ Returns true if there is no error; otherwise returns false.
+
+ \sa revert()
+*/
+
+bool QAbstractItemModel::submit()
+{
+ return true;
+}
+
+/*!
+ Lets the model know that it should discard cached information. This
+ function is typically used for row editing.
+
+ \sa submit()
+*/
+
+void QAbstractItemModel::revert()
+{
+ // do nothing
+}
+
+/*!
+ Returns the data for the given \a role and \a section in the header with
+ the specified \a orientation.
+
+ For horizontal headers, the section number corresponds to the column
+ number. Similarly, for vertical headers, the section number corresponds to
+ the row number.
+
+ \sa Qt::ItemDataRole, setHeaderData(), QHeaderView
+*/
+
+QVariant QAbstractItemModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ Q_UNUSED(orientation);
+ if (role == Qt::DisplayRole)
+ return section + 1;
+ return QVariant();
+}
+
+/*!
+ Sets the data for the given \a role and \a section in the header with the
+ specified \a orientation to the \a value supplied.
+
+ Returns true if the header's data was updated; otherwise returns false.
+
+ When reimplementing this function, the headerDataChanged() signal must be
+ emitted explicitly.
+
+ \sa Qt::ItemDataRole, headerData()
+*/
+
+bool QAbstractItemModel::setHeaderData(int section, Qt::Orientation orientation,
+ const QVariant &value, int role)
+{
+ Q_UNUSED(section);
+ Q_UNUSED(orientation);
+ Q_UNUSED(value);
+ Q_UNUSED(role);
+ return false;
+}
+
+/*!
+ \fn QModelIndex QAbstractItemModel::createIndex(int row, int column, void *ptr) const
+
+ Creates a model index for the given \a row and \a column with the internal
+ pointer \a ptr.
+
+ When using a QSortFilterProxyModel, its indexes have their own internal
+ pointer. It is not advisable to access this internal pointer outside of the
+ model. Use the data() function instead.
+
+ This function provides a consistent interface that model subclasses must
+ use to create model indexes.
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::createIndex(int row, int column, int id) const
+ \obsolete
+
+ Use QModelIndex
+ QAbstractItemModel::createIndex(int row, int column, quint32 id) instead.
+*/
+
+/*!
+ \fn QModelIndex QAbstractItemModel::createIndex(int row, int column, quint32 id) const
+
+ Creates a model index for the given \a row and \a column with the internal
+ identifier, \a id.
+
+ This function provides a consistent interface that model subclasses must
+ use to create model indexes.
+
+ \sa QModelIndex::internalId()
+*/
+
+/*!
+ \internal
+*/
+void QAbstractItemModel::encodeData(const QModelIndexList &indexes, QDataStream &stream) const
+{
+ QModelIndexList::ConstIterator it = indexes.begin();
+ for (; it != indexes.end(); ++it)
+ stream << (*it).row() << (*it).column() << itemData(*it);
+}
+
+/*!
+ \internal
+ */
+bool QAbstractItemModel::decodeData(int row, int column, const QModelIndex &parent,
+ QDataStream &stream)
+{
+ int top = INT_MAX;
+ int left = INT_MAX;
+ int bottom = 0;
+ int right = 0;
+ QVector<int> rows, columns;
+ QVector<QMap<int, QVariant> > data;
+
+ while (!stream.atEnd()) {
+ int r, c;
+ QMap<int, QVariant> v;
+ stream >> r >> c >> v;
+ rows.append(r);
+ columns.append(c);
+ data.append(v);
+ top = qMin(r, top);
+ left = qMin(c, left);
+ bottom = qMax(r, bottom);
+ right = qMax(c, right);
+ }
+
+ // insert the dragged items into the table, use a bit array to avoid overwriting items,
+ // since items from different tables can have the same row and column
+ int dragRowCount = 0;
+ int dragColumnCount = right - left + 1;
+
+ // Compute the number of continuous rows upon insertion and modify the rows to match
+ QVector<int> rowsToInsert(bottom + 1);
+ for (int i = 0; i < rows.count(); ++i)
+ rowsToInsert[rows.at(i)] = 1;
+ for (int i = 0; i < rowsToInsert.count(); ++i) {
+ if (rowsToInsert[i] == 1){
+ rowsToInsert[i] = dragRowCount;
+ ++dragRowCount;
+ }
+ }
+ for (int i = 0; i < rows.count(); ++i)
+ rows[i] = top + rowsToInsert[rows[i]];
+
+ QBitArray isWrittenTo(dragRowCount * dragColumnCount);
+
+ // make space in the table for the dropped data
+ int colCount = columnCount(parent);
+ if (colCount == 0) {
+ insertColumns(colCount, dragColumnCount - colCount, parent);
+ colCount = columnCount(parent);
+ }
+ insertRows(row, dragRowCount, parent);
+
+ row = qMax(0, row);
+ column = qMax(0, column);
+
+ QVector<QPersistentModelIndex> newIndexes(data.size());
+ // set the data in the table
+ for (int j = 0; j < data.size(); ++j) {
+ int relativeRow = rows.at(j) - top;
+ int relativeColumn = columns.at(j) - left;
+ int destinationRow = relativeRow + row;
+ int destinationColumn = relativeColumn + column;
+ int flat = (relativeRow * dragColumnCount) + relativeColumn;
+ // if the item was already written to, or we just can't fit it in the table, create a new row
+ if (destinationColumn >= colCount || isWrittenTo.testBit(flat)) {
+ destinationColumn = qBound(column, destinationColumn, colCount - 1);
+ destinationRow = row + dragRowCount;
+ insertRows(row + dragRowCount, 1, parent);
+ flat = (dragRowCount * dragColumnCount) + relativeColumn;
+ isWrittenTo.resize(++dragRowCount * dragColumnCount);
+ }
+ if (!isWrittenTo.testBit(flat)) {
+ newIndexes[j] = index(destinationRow, destinationColumn, parent);
+ isWrittenTo.setBit(flat);
+ }
+ }
+
+ for(int k = 0; k < newIndexes.size(); k++) {
+ if (newIndexes.at(k).isValid())
+ setItemData(newIndexes.at(k), data.at(k));
+ }
+
+ return true;
+}
+
+/*!
+ Begins a row insertion operation.
+
+ When reimplementing insertRows() in a subclass, you must call this function
+ \e before inserting data into the model's underlying data store.
+
+ The \a parent index corresponds to the parent into which the new rows are
+ inserted; \a first and \a last are the row numbers that the new rows will
+ have after they have been inserted.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-insert-rows.png Inserting rows
+ \o Specify the first and last row numbers for the span of rows you
+ want to insert into an item in a model.
+
+ For example, as shown in the diagram, we insert three rows before
+ row 2, so \a first is 2 and \a last is 4:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 0
+
+ This inserts the three new rows as rows 2, 3, and 4.
+ \row
+ \o \inlineimage modelview-begin-append-rows.png Appending rows
+ \o To append rows, insert them after the last row.
+
+ For example, as shown in the diagram, we append two rows to a
+ collection of 4 existing rows (ending in row 3), so \a first is 4
+ and \a last is 5:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 1
+
+ This appends the two new rows as rows 4 and 5.
+ \endtable
+
+ \note This function emits the rowsAboutToBeInserted() signal which
+ connected views (or proxies) must handle before the data is inserted.
+ Otherwise, the views may end up in an invalid state.
+ \sa endInsertRows()
+*/
+void QAbstractItemModel::beginInsertRows(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit rowsAboutToBeInserted(parent, first, last);
+ d->rowsAboutToBeInserted(parent, first, last);
+}
+
+/*!
+ Ends a row insertion operation.
+
+ When reimplementing insertRows() in a subclass, you must call this function
+ \e after inserting data into the model's underlying data store.
+
+ \sa beginInsertRows()
+*/
+void QAbstractItemModel::endInsertRows()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->rowsInserted(change.parent, change.first, change.last);
+ emit rowsInserted(change.parent, change.first, change.last);
+}
+
+/*!
+ Begins a row removal operation.
+
+ When reimplementing removeRows() in a subclass, you must call this
+ function \e before removing data from the model's underlying data store.
+
+ The \a parent index corresponds to the parent from which the new rows are
+ removed; \a first and \a last are the row numbers of the rows to be
+ removed.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-remove-rows.png Removing rows
+ \o Specify the first and last row numbers for the span of rows you
+ want to remove from an item in a model.
+
+ For example, as shown in the diagram, we remove the two rows from
+ row 2 to row 3, so \a first is 2 and \a last is 3:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 2
+ \endtable
+
+ \note This function emits the rowsAboutToBeRemoved() signal which connected
+ views (or proxies) must handle before the data is removed. Otherwise, the
+ views may end up in an invalid state.
+
+ \sa endRemoveRows()
+*/
+void QAbstractItemModel::beginRemoveRows(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit rowsAboutToBeRemoved(parent, first, last);
+ d->rowsAboutToBeRemoved(parent, first, last);
+}
+
+/*!
+ Ends a row removal operation.
+
+ When reimplementing removeRows() in a subclass, you must call this function
+ \e after removing data from the model's underlying data store.
+
+ \sa beginRemoveRows()
+*/
+void QAbstractItemModel::endRemoveRows()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->rowsRemoved(change.parent, change.first, change.last);
+ emit rowsRemoved(change.parent, change.first, change.last);
+}
+
+/*!
+ Returns whether a move operation is valid.
+
+ A move operation is not allowed if it moves a continuous range of rows to a destination within
+ itself, or if it attempts to move a row to one of its own descendants.
+
+ \internal
+*/
+bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int start, int end, const QModelIndex &destinationParent, int destinationStart, Qt::Orientation orientation)
+{
+ // Don't move the range within itself.
+ if (destinationParent == srcParent)
+ return !(destinationStart >= start && destinationStart <= end + 1);
+
+ QModelIndex destinationAncestor = destinationParent;
+ int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
+ forever {
+ if (destinationAncestor == srcParent) {
+ if (pos >= start && pos <= end)
+ return false;
+ break;
+ }
+
+ if (!destinationAncestor.isValid())
+ break;
+
+ pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column();
+ destinationAncestor = destinationAncestor.parent();
+ }
+
+ return true;
+}
+
+/*!
+ \since 4.6
+
+ Begins a row move operation.
+
+ When reimplementing a subclass, this method simplifies moving
+ entities in your model. This method is responsible for moving
+ persistent indexes in the model, which you would otherwise be
+ required to do yourself. Using beginMoveRows and endMoveRows
+ is an alternative to emitting layoutAboutToBeChanged and
+ layoutChanged directly along with changePersistentIndexes.
+ layoutAboutToBeChanged is emitted by this method for compatibility
+ reasons.
+
+ The \a sourceParent index corresponds to the parent from which the
+ rows are moved; \a sourceFirst and \a sourceLast are the first and last
+ row numbers of the rows to be moved. The \a destinationParent index
+ corresponds to the parent into which those rows are moved. The \a
+ destinationChild is the row to which the rows will be moved. That
+ is, the index at row \a sourceFirst in \a sourceParent will become
+ row \a destinationChild in \a destinationParent, followed by all other
+ rows up to \a sourceLast.
+
+ However, when moving rows down in the same parent (\a sourceParent
+ and \a destinationParent are equal), the rows will be placed before the
+ \a destinationChild index. That is, if you wish to move rows 0 and 1 so
+ they will become rows 1 and 2, \a destinationChild should be 3. In this
+ case, the new index for the source row \c i (which is between
+ \a sourceFirst and \a sourceLast) is equal to
+ \c {(destinationChild-sourceLast-1+i)}.
+
+ Note that if \a sourceParent and \a destinationParent are the same,
+ you must ensure that the \a destinationChild is not within the range
+ of \a sourceFirst and \a sourceLast + 1. You must also ensure that you
+ do not attempt to move a row to one of its own children or ancestors.
+ This method returns false if either condition is true, in which case you
+ should abort your move operation.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-move-rows-1.png Moving rows to another parent
+ \o Specify the first and last row numbers for the span of rows in
+ the source parent you want to move in the model. Also specify
+ the row in the destination parent to move the span to.
+
+ For example, as shown in the diagram, we move three rows from
+ row 2 to 4 in the source, so \a sourceFirst is 2 and \a sourceLast is 4.
+ We move those items to above row 2 in the destination, so \a destinationChild is 2.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 6
+
+ This moves the three rows rows 2, 3, and 4 in the source to become 2, 3 and 4 in
+ the destination. Other affected siblings are displaced accordingly.
+ \row
+ \o \inlineimage modelview-move-rows-2.png Moving rows to append to another parent
+ \o To append rows to another parent, move them to after the last row.
+
+ For example, as shown in the diagram, we move three rows to a
+ collection of 6 existing rows (ending in row 5), so \a destinationChild is 6:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 7
+
+ This moves the target rows to the end of the target parent as 6, 7 and 8.
+ \row
+ \o \inlineimage modelview-move-rows-3.png Moving rows in the same parent up
+ \o To move rows within the same parent, specify the row to move them to.
+
+ For example, as shown in the diagram, we move one item from row 2 to row 0,
+ so \a sourceFirst and \a sourceLast are 2 and \a destinationChild is 0.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 8
+
+ Note that other rows may be displaced accordingly. Note also that when moving
+ items within the same parent you should not attempt invalid or no-op moves. In
+ the above example, item 2 is at row 2 before the move, so it can not be moved
+ to row 2 (where it is already) or row 3 (no-op as row 3 means above row 3, where
+ it is already)
+
+ \row
+ \o \inlineimage modelview-move-rows-4.png Moving rows in the same parent down
+ \o To move rows within the same parent, specify the row to move them to.
+
+ For example, as shown in the diagram, we move one item from row 2 to row 4,
+ so \a sourceFirst and \a sourceLast are 2 and \a destinationChild is 4.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 9
+
+ Note that other rows may be displaced accordingly.
+ \endtable
+
+ \sa endMoveRows()
+*/
+bool QAbstractItemModel::beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_ASSERT(sourceFirst >= 0);
+ Q_ASSERT(sourceLast >= sourceFirst);
+ Q_ASSERT(destinationChild >= 0);
+ Q_D(QAbstractItemModel);
+
+ if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical)) {
+ return false;
+ }
+
+ QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
+ sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
+ d->changes.push(sourceChange);
+ int destinationLast = destinationChild + (sourceLast - sourceFirst);
+ QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
+ destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
+ d->changes.push(destinationChange);
+
+ emit rowsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild);
+ emit layoutAboutToBeChanged();
+ d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Vertical);
+ return true;
+}
+
+/*!
+ Ends a row move operation.
+
+ When implementing a subclass, you must call this
+ function \e after moving data within the model's underlying data
+ store.
+
+ layoutChanged is emitted by this method for compatibility reasons.
+
+ \sa beginMoveRows()
+
+ \since 4.6
+*/
+void QAbstractItemModel::endMoveRows()
+{
+ Q_D(QAbstractItemModel);
+
+ QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
+ QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
+
+ QModelIndex adjustedSource = removeChange.parent;
+ QModelIndex adjustedDestination = insertChange.parent;
+
+ const int numMoved = removeChange.last - removeChange.first + 1;
+ if (insertChange.needsAdjust)
+ adjustedDestination = createIndex(adjustedDestination.row() - numMoved, adjustedDestination.column(), adjustedDestination.internalPointer());
+
+ if (removeChange.needsAdjust)
+ adjustedSource = createIndex(adjustedSource.row() + numMoved, adjustedSource.column(), adjustedSource.internalPointer());
+
+ d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Vertical);
+
+ emit rowsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first);
+ emit layoutChanged();
+}
+
+/*!
+ Begins a column insertion operation.
+
+ When reimplementing insertColumns() in a subclass, you must call this
+ function \e before inserting data into the model's underlying data store.
+
+ The \a parent index corresponds to the parent into which the new columns
+ are inserted; \a first and \a last are the column numbers of the new
+ columns will have after they have been inserted.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-insert-columns.png Inserting columns
+ \o Specify the first and last column numbers for the span of columns
+ you want to insert into an item in a model.
+
+ For example, as shown in the diagram, we insert three columns
+ before column 4, so \a first is 4 and \a last is 6:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 3
+
+ This inserts the three new columns as columns 4, 5, and 6.
+ \row
+ \o \inlineimage modelview-begin-append-columns.png Appending columns
+ \o To append columns, insert them after the last column.
+
+ For example, as shown in the diagram, we append three columns to a
+ collection of six existing columns (ending in column 5), so
+ \a first is 6 and \a last is 8:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 4
+
+ This appends the two new columns as columns 6, 7, and 8.
+ \endtable
+
+ \note This function emits the columnsAboutToBeInserted() signal which
+ connected views (or proxies) must handle before the data is inserted.
+ Otherwise, the views may end up in an invalid state.
+
+ \sa endInsertColumns()
+*/
+void QAbstractItemModel::beginInsertColumns(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit columnsAboutToBeInserted(parent, first, last);
+ d->columnsAboutToBeInserted(parent, first, last);
+}
+
+/*!
+ Ends a column insertion operation.
+
+ When reimplementing insertColumns() in a subclass, you must call this
+ function \e after inserting data into the model's underlying data
+ store.
+
+ \sa beginInsertColumns()
+*/
+void QAbstractItemModel::endInsertColumns()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->columnsInserted(change.parent, change.first, change.last);
+ emit columnsInserted(change.parent, change.first, change.last);
+}
+
+/*!
+ Begins a column removal operation.
+
+ When reimplementing removeColumns() in a subclass, you must call this
+ function \e before removing data from the model's underlying data store.
+
+ The \a parent index corresponds to the parent from which the new columns
+ are removed; \a first and \a last are the column numbers of the first and
+ last columns to be removed.
+
+ \table 80%
+ \row
+ \o \inlineimage modelview-begin-remove-columns.png Removing columns
+ \o Specify the first and last column numbers for the span of columns
+ you want to remove from an item in a model.
+
+ For example, as shown in the diagram, we remove the three columns
+ from column 4 to column 6, so \a first is 4 and \a last is 6:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 5
+ \endtable
+
+ \note This function emits the columnsAboutToBeRemoved() signal which
+ connected views (or proxies) must handle before the data is removed.
+ Otherwise, the views may end up in an invalid state.
+
+ \sa endRemoveColumns()
+*/
+void QAbstractItemModel::beginRemoveColumns(const QModelIndex &parent, int first, int last)
+{
+ Q_ASSERT(first >= 0);
+ Q_ASSERT(last >= first);
+ Q_D(QAbstractItemModel);
+ d->changes.push(QAbstractItemModelPrivate::Change(parent, first, last));
+ emit columnsAboutToBeRemoved(parent, first, last);
+ d->columnsAboutToBeRemoved(parent, first, last);
+}
+
+/*!
+ Ends a column removal operation.
+
+ When reimplementing removeColumns() in a subclass, you must call this
+ function \e after removing data from the model's underlying data store.
+
+ \sa beginRemoveColumns()
+*/
+void QAbstractItemModel::endRemoveColumns()
+{
+ Q_D(QAbstractItemModel);
+ QAbstractItemModelPrivate::Change change = d->changes.pop();
+ d->columnsRemoved(change.parent, change.first, change.last);
+ emit columnsRemoved(change.parent, change.first, change.last);
+}
+
+/*!
+ Begins a column move operation.
+
+ When reimplementing a subclass, this method simplifies moving
+ entities in your model. This method is responsible for moving
+ persistent indexes in the model, which you would otherwise be
+ required to do yourself. Using beginMoveRows and endMoveRows
+ is an alternative to emitting layoutAboutToBeChanged and
+ layoutChanged directly along with changePersistentIndexes.
+ layoutAboutToBeChanged is emitted by this method for compatibility
+ reasons.
+
+ The \a sourceParent index corresponds to the parent from which the
+ columns are moved; \a sourceFirst and \a sourceLast are the first and last
+ column numbers of the columns to be moved. The \a destinationParent index
+ corresponds to the parent into which those columns are moved. The \a
+ destinationChild is the column to which the columns will be moved. That
+ is, the index at column \a sourceFirst in \a sourceParent will become
+ column \a destinationChild in \a destinationParent, followed by all other
+ columns up to \a sourceLast.
+
+ However, when moving columns down in the same parent (\a sourceParent
+ and \a destinationParent are equal), the columnss will be placed before the
+ \a destinationChild index. That is, if you wish to move columns 0 and 1 so
+ they will become columns 1 and 2, \a destinationChild should be 3. In this
+ case, the new index for the source column \c i (which is between
+ \a sourceFirst and \a sourceLast) is equal to
+ \c {(destinationChild-sourceLast-1+i)}.
+
+ Note that if \a sourceParent and \a destinationParent are the same,
+ you must ensure that the \a destinationChild is not within the range
+ of \a sourceFirst and \a sourceLast + 1. You must also ensure that you
+ do not attempt to move a column to one of its own children or ancestors.
+ This method returns false if either condition is true, in which case you
+ should abort your move operation.
+
+ \sa endMoveColumns()
+
+ \since 4.6
+*/
+bool QAbstractItemModel::beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationChild)
+{
+ Q_ASSERT(sourceFirst >= 0);
+ Q_ASSERT(sourceLast >= sourceFirst);
+ Q_ASSERT(destinationChild >= 0);
+ Q_D(QAbstractItemModel);
+
+ if (!d->allowMove(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal)) {
+ return false;
+ }
+
+ QAbstractItemModelPrivate::Change sourceChange(sourceParent, sourceFirst, sourceLast);
+ sourceChange.needsAdjust = sourceParent.isValid() && sourceParent.row() >= destinationChild && sourceParent.parent() == destinationParent;
+ d->changes.push(sourceChange);
+ int destinationLast = destinationChild + (sourceLast - sourceFirst);
+ QAbstractItemModelPrivate::Change destinationChange(destinationParent, destinationChild, destinationLast);
+ destinationChange.needsAdjust = destinationParent.isValid() && destinationParent.row() >= sourceLast && destinationParent.parent() == sourceParent;
+ d->changes.push(destinationChange);
+
+ d->itemsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild, Qt::Horizontal);
+
+ emit columnsAboutToBeMoved(sourceParent, sourceFirst, sourceLast, destinationParent, destinationChild);
+ emit layoutAboutToBeChanged();
+ return true;
+}
+
+/*!
+ Ends a column move operation.
+
+ When implementing a subclass, you must call this
+ function \e after moving data within the model's underlying data
+ store.
+
+ layoutChanged is emitted by this method for compatibility reasons.
+
+ \sa beginMoveColumns()
+
+ \since 4.6
+*/
+void QAbstractItemModel::endMoveColumns()
+{
+ Q_D(QAbstractItemModel);
+
+ QAbstractItemModelPrivate::Change insertChange = d->changes.pop();
+ QAbstractItemModelPrivate::Change removeChange = d->changes.pop();
+
+ QModelIndex adjustedSource = removeChange.parent;
+ QModelIndex adjustedDestination = insertChange.parent;
+
+ const int numMoved = removeChange.last - removeChange.first + 1;
+ if (insertChange.needsAdjust)
+ adjustedDestination = createIndex(adjustedDestination.row(), adjustedDestination.column() - numMoved, adjustedDestination.internalPointer());
+
+ if (removeChange.needsAdjust)
+ adjustedSource = createIndex(adjustedSource.row(), adjustedSource.column() + numMoved, adjustedSource.internalPointer());
+
+ d->itemsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first, Qt::Horizontal);
+
+ emit columnsMoved(adjustedSource, removeChange.first, removeChange.last, adjustedDestination, insertChange.first);
+ emit layoutChanged();
+}
+
+/*!
+ Resets the model to its original state in any attached views.
+
+ \note Use beginResetModel() and endResetModel() instead whenever possible.
+ Use this method only if there is no way to call beginResetModel() before invalidating the model.
+ Otherwise it could lead to unexpected behaviour, especially when used with proxy models.
+*/
+void QAbstractItemModel::reset()
+{
+ Q_D(QAbstractItemModel);
+ emit modelAboutToBeReset();
+ d->invalidatePersistentIndexes();
+ emit modelReset();
+}
+
+/*!
+ Begins a model reset operation.
+
+ A reset operation resets the model to its current state in any attached views.
+
+ \note Any views attached to this model will be reset as well.
+
+ When a model is reset it means that any previous data reported from the
+ model is now invalid and has to be queried for again. This also means that
+ the current item and any selected items will become invalid.
+
+ When a model radically changes its data it can sometimes be easier to just
+ call this function rather than emit dataChanged() to inform other
+ components when the underlying data source, or its structure, has changed.
+
+ You must call this function before resetting any internal data structures in your model
+ or proxy model.
+
+ \sa modelAboutToBeReset(), modelReset(), endResetModel()
+ \since 4.6
+*/
+void QAbstractItemModel::beginResetModel()
+{
+ emit modelAboutToBeReset();
+}
+
+/*!
+ Completes a model reset operation.
+
+ You must call this function after resetting any internal data structure in your model
+ or proxy model.
+
+ \sa beginResetModel()
+ \since 4.6
+*/
+void QAbstractItemModel::endResetModel()
+{
+ Q_D(QAbstractItemModel);
+ d->invalidatePersistentIndexes();
+ emit modelReset();
+}
+
+/*!
+ Changes the QPersistentModelIndex that is equal to the given \a from model
+ index to the given \a to model index.
+
+ If no persistent model index equal to the given \a from model index was
+ found, nothing is changed.
+
+ \sa persistentIndexList(), changePersistentIndexList()
+*/
+void QAbstractItemModel::changePersistentIndex(const QModelIndex &from, const QModelIndex &to)
+{
+ Q_D(QAbstractItemModel);
+ if (d->persistent.indexes.isEmpty())
+ return;
+ // find the data and reinsert it sorted
+ const QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = d->persistent.indexes.find(from);
+ if (it != d->persistent.indexes.end()) {
+ QPersistentModelIndexData *data = *it;
+ d->persistent.indexes.erase(it);
+ data->index = to;
+ if (to.isValid())
+ d->persistent.insertMultiAtEnd(to, data);
+ else
+ data->model = 0;
+ }
+}
+
+/*!
+ \since 4.1
+
+ Changes the QPersistentModelIndexes that is equal to the indexes in the
+ given \a from model index list to the given \a to model index list.
+
+ If no persistent model indexes equal to the indexes in the given \a from
+ model index list was found, nothing is changed.
+
+ \sa persistentIndexList(), changePersistentIndex()
+*/
+void QAbstractItemModel::changePersistentIndexList(const QModelIndexList &from,
+ const QModelIndexList &to)
+{
+ Q_D(QAbstractItemModel);
+ if (d->persistent.indexes.isEmpty())
+ return;
+ QVector<QPersistentModelIndexData *> toBeReinserted;
+ toBeReinserted.reserve(to.count());
+ for (int i = 0; i < from.count(); ++i) {
+ if (from.at(i) == to.at(i))
+ continue;
+ const QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = d->persistent.indexes.find(from.at(i));
+ if (it != d->persistent.indexes.end()) {
+ QPersistentModelIndexData *data = *it;
+ d->persistent.indexes.erase(it);
+ data->index = to.at(i);
+ if (data->index.isValid())
+ toBeReinserted << data;
+ else
+ data->model = 0;
+ }
+ }
+
+ for (QVector<QPersistentModelIndexData *>::const_iterator it = toBeReinserted.constBegin();
+ it != toBeReinserted.constEnd() ; ++it) {
+ QPersistentModelIndexData *data = *it;
+ d->persistent.insertMultiAtEnd(data->index, data);
+ }
+}
+
+/*!
+ \since 4.2
+
+ Returns the list of indexes stored as persistent indexes in the model.
+*/
+QModelIndexList QAbstractItemModel::persistentIndexList() const
+{
+ Q_D(const QAbstractItemModel);
+ QModelIndexList result;
+ for (QHash<QModelIndex, QPersistentModelIndexData *>::const_iterator it = d->persistent.indexes.constBegin();
+ it != d->persistent.indexes.constEnd(); ++it) {
+ QPersistentModelIndexData *data = *it;
+ result.append(data->index);
+ }
+ return result;
+}
+
+
+/*!
+ \class QAbstractTableModel
+ \brief The QAbstractTableModel class provides an abstract model that can be
+ subclassed to create table models.
+
+ \ingroup model-view
+
+ QAbstractTableModel provides a standard interface for models that represent
+ their data as a two-dimensional array of items. It is not used directly,
+ but must be subclassed.
+
+ Since the model provides a more specialized interface than
+ QAbstractItemModel, it is not suitable for use with tree views, although it
+ can be used to provide data to a QListView. If you need to represent a
+ simple list of items, and only need a model to contain a single column of
+ data, subclassing the QAbstractListModel may be more appropriate.
+
+ The rowCount() and columnCount() functions return the dimensions of the
+ table. To retrieve a model index corresponding to an item in the model, use
+ index() and provide only the row and column numbers.
+
+ \section1 Subclassing
+
+ When subclassing QAbstractTableModel, you must implement rowCount(),
+ columnCount(), and data(). Default implementations of the index() and
+ parent() functions are provided by QAbstractTableModel.
+ Well behaved models will also implement headerData().
+
+ Editable models need to implement setData(), and implement flags() to
+ return a value containing
+ \l{Qt::ItemFlags}{Qt::ItemIsEditable}.
+
+ Models that provide interfaces to resizable data structures can
+ provide implementations of insertRows(), removeRows(), insertColumns(),
+ and removeColumns(). When implementing these functions, it is
+ important to call the appropriate functions so that all connected views
+ are aware of any changes:
+
+ \list
+ \o An insertRows() implementation must call beginInsertRows()
+ \e before inserting new rows into the data structure, and it must
+ call endInsertRows() \e{immediately afterwards}.
+ \o An insertColumns() implementation must call beginInsertColumns()
+ \e before inserting new columns into the data structure, and it must
+ call endInsertColumns() \e{immediately afterwards}.
+ \o A removeRows() implementation must call beginRemoveRows()
+ \e before the rows are removed from the data structure, and it must
+ call endRemoveRows() \e{immediately afterwards}.
+ \o A removeColumns() implementation must call beginRemoveColumns()
+ \e before the columns are removed from the data structure, and it must
+ call endRemoveColumns() \e{immediately afterwards}.
+ \endlist
+
+ \note Some general guidelines for subclassing models are available in the
+ \l{Model Subclassing Reference}.
+
+ \note
+
+ \sa {Model Classes}, QAbstractItemModel, QAbstractListModel,
+ {Pixelator Example}
+*/
+
+/*!
+ Constructs an abstract table model for the given \a parent.
+*/
+
+QAbstractTableModel::QAbstractTableModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+
+}
+
+/*!
+ \internal
+
+ Constructs an abstract table model with \a dd and the given \a parent.
+*/
+
+QAbstractTableModel::QAbstractTableModel(QAbstractItemModelPrivate &dd, QObject *parent)
+ : QAbstractItemModel(dd, parent)
+{
+
+}
+
+/*!
+ Destroys the abstract table model.
+*/
+
+QAbstractTableModel::~QAbstractTableModel()
+{
+
+}
+
+/*!
+ \fn QModelIndex QAbstractTableModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+
+ Returns the index of the data in \a row and \a column with \a parent.
+
+ \sa parent()
+*/
+
+QModelIndex QAbstractTableModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
+}
+
+/*!
+ \fn QModelIndex QAbstractTableModel::parent(const QModelIndex &index) const
+
+ Returns the parent of the model item with the given \a index.
+
+ \sa index() hasChildren()
+*/
+
+QModelIndex QAbstractTableModel::parent(const QModelIndex &) const
+{
+ return QModelIndex();
+}
+
+bool QAbstractTableModel::hasChildren(const QModelIndex &parent) const
+{
+ if (parent.model() == this || !parent.isValid())
+ return rowCount(parent) > 0 && columnCount(parent) > 0;
+ return false;
+}
+
+/*!
+ \class QAbstractListModel
+ \brief The QAbstractListModel class provides an abstract model that can be
+ subclassed to create one-dimensional list models.
+
+ \ingroup model-view
+
+ QAbstractListModel provides a standard interface for models that represent
+ their data as a simple non-hierarchical sequence of items. It is not used
+ directly, but must be subclassed.
+
+ Since the model provides a more specialized interface than
+ QAbstractItemModel, it is not suitable for use with tree views; you will
+ need to subclass QAbstractItemModel if you want to provide a model for
+ that purpose. If you need to use a number of list models to manage data,
+ it may be more appropriate to subclass QAbstractTableModel class instead.
+
+ Simple models can be created by subclassing this class and implementing
+ the minimum number of required functions. For example, we could implement
+ a simple read-only QStringList-based model that provides a list of strings
+ to a QListView widget. In such a case, we only need to implement the
+ rowCount() function to return the number of items in the list, and the
+ data() function to retrieve items from the list.
+
+ Since the model represents a one-dimensional structure, the rowCount()
+ function returns the total number of items in the model. The columnCount()
+ function is implemented for interoperability with all kinds of views, but
+ by default informs views that the model contains only one column.
+
+ \section1 Subclassing
+
+ When subclassing QAbstractListModel, you must provide implementations
+ of the rowCount() and data() functions. Well behaved models also provide
+ a headerData() implementation.
+
+ For editable list models, you must also provide an implementation of
+ setData(), implement the flags() function so that it returns a value
+ containing \l{Qt::ItemFlags}{Qt::ItemIsEditable}.
+
+ Note that QAbstractListModel provides a default implementation of
+ columnCount() that informs views that there is only a single column
+ of items in this model.
+
+ Models that provide interfaces to resizable list-like data structures
+ can provide implementations of insertRows() and removeRows(). When
+ implementing these functions, it is important to call the appropriate
+ functions so that all connected views are aware of any changes:
+
+ \list
+ \o An insertRows() implementation must call beginInsertRows()
+ \e before inserting new rows into the data structure, and it must
+ call endInsertRows() \e{immediately afterwards}.
+ \o A removeRows() implementation must call beginRemoveRows()
+ \e before the rows are removed from the data structure, and it must
+ call endRemoveRows() \e{immediately afterwards}.
+ \endlist
+
+ \note Some general guidelines for subclassing models are available in the
+ \l{Model Subclassing Reference}.
+
+ \sa {Model Classes}, {Model Subclassing Reference}, QAbstractItemView,
+ QAbstractTableModel, {Item Views Puzzle Example}
+*/
+
+/*!
+ Constructs an abstract list model with the given \a parent.
+*/
+
+QAbstractListModel::QAbstractListModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+
+}
+
+/*!
+ \internal
+
+ Constructs an abstract list model with \a dd and the given \a parent.
+*/
+
+QAbstractListModel::QAbstractListModel(QAbstractItemModelPrivate &dd, QObject *parent)
+ : QAbstractItemModel(dd, parent)
+{
+
+}
+
+/*!
+ Destroys the abstract list model.
+*/
+
+QAbstractListModel::~QAbstractListModel()
+{
+
+}
+
+/*!
+ \fn QModelIndex QAbstractListModel::index(int row, int column, const QModelIndex &parent = QModelIndex()) const
+
+ Returns the index of the data in \a row and \a column with \a parent.
+
+ \sa parent()
+*/
+
+QModelIndex QAbstractListModel::index(int row, int column, const QModelIndex &parent) const
+{
+ return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex();
+}
+
+/*!
+ Returns the parent of the model item with the given \a index.
+
+ \sa index() hasChildren()
+*/
+
+QModelIndex QAbstractListModel::parent(const QModelIndex & /* index */) const
+{
+ return QModelIndex();
+}
+
+/*!
+ \internal
+
+ Returns the number of columns in the list with the given \a parent.
+
+ \sa rowCount()
+*/
+
+int QAbstractListModel::columnCount(const QModelIndex &parent) const
+{
+ return parent.isValid() ? 0 : 1;
+}
+
+bool QAbstractListModel::hasChildren(const QModelIndex &parent) const
+{
+ return parent.isValid() ? false : (rowCount() > 0);
+}
+
+/*!
+ \typedef QModelIndexList
+ \relates QModelIndex
+
+ Synonym for QList<QModelIndex>.
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractTableModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
+ return false;
+
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return false;
+ QString format = types.at(0);
+ if (!data->hasFormat(format))
+ return false;
+
+ QByteArray encoded = data->data(format);
+ QDataStream stream(&encoded, QIODevice::ReadOnly);
+
+ // if the drop is on an item, replace the data in the items
+ if (parent.isValid() && row == -1 && column == -1) {
+ int top = INT_MAX;
+ int left = INT_MAX;
+ QVector<int> rows, columns;
+ QVector<QMap<int, QVariant> > data;
+
+ while (!stream.atEnd()) {
+ int r, c;
+ QMap<int, QVariant> v;
+ stream >> r >> c >> v;
+ rows.append(r);
+ columns.append(c);
+ data.append(v);
+ top = qMin(r, top);
+ left = qMin(c, left);
+ }
+
+ for (int i = 0; i < data.size(); ++i) {
+ int r = (rows.at(i) - top) + parent.row();
+ int c = (columns.at(i) - left) + parent.column();
+ if (hasIndex(r, c))
+ setItemData(index(r, c), data.at(i));
+ }
+
+ return true;
+ }
+
+ // otherwise insert new rows for the data
+ return decodeData(row, column, parent, stream);
+}
+
+/*!
+ \reimp
+*/
+bool QAbstractListModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ if (!data || !(action == Qt::CopyAction || action == Qt::MoveAction))
+ return false;
+
+ QStringList types = mimeTypes();
+ if (types.isEmpty())
+ return false;
+ QString format = types.at(0);
+ if (!data->hasFormat(format))
+ return false;
+
+ QByteArray encoded = data->data(format);
+ QDataStream stream(&encoded, QIODevice::ReadOnly);
+
+ // if the drop is on an item, replace the data in the items
+ if (parent.isValid() && row == -1 && column == -1) {
+ int top = INT_MAX;
+ int left = INT_MAX;
+ QVector<int> rows, columns;
+ QVector<QMap<int, QVariant> > data;
+
+ while (!stream.atEnd()) {
+ int r, c;
+ QMap<int, QVariant> v;
+ stream >> r >> c >> v;
+ rows.append(r);
+ columns.append(c);
+ data.append(v);
+ top = qMin(r, top);
+ left = qMin(c, left);
+ }
+
+ for (int i = 0; i < data.size(); ++i) {
+ int r = (rows.at(i) - top) + parent.row();
+ if (columns.at(i) == left && hasIndex(r, 0))
+ setItemData(index(r), data.at(i));
+ }
+
+ return true;
+ }
+
+ if (row == -1)
+ row = rowCount(parent);
+
+ // otherwise insert new rows for the data
+ return decodeData(row, column, parent, stream);
+}
+
+/*!
+ \fn QAbstractItemModel::modelAboutToBeReset()
+ \since 4.2
+
+ This signal is emitted when reset() is called, before the model's internal
+ state (e.g. persistent model indexes) has been invalidated.
+
+ \sa beginResetModel(), modelReset()
+*/
+
+/*!
+ \fn QAbstractItemModel::modelReset()
+ \since 4.1
+
+ This signal is emitted when reset() is called, after the model's internal
+ state (e.g. persistent model indexes) has been invalidated.
+
+ \sa endResetModel(), modelAboutToBeReset()
+*/
+
+/*!
+ \fn bool QModelIndex::operator<(const QModelIndex &other) const
+ \since 4.1
+
+ Returns true if this model index is smaller than the \a other
+ model index; otherwise returns false.
+*/
+
+/*!
+ \fn uint qHash(const QPersistentModelIndex &index)
+ \since 4.5
+
+ Returns a hash of the QPersistentModelIndex
+ */
+
+
+/*!
+ \internal
+ QHash::insertMulti insert the value before the old value. and find() return the new value.
+ We need insertMultiAtEnd because we don't want to overwrite the old one, which should be removed later
+
+ There should be only one instance QPersistentModelIndexData per index, but in some intermediate state there may be
+ severals of PersistantModelIndex pointing to the same index, but one is already updated, and the other one is not.
+ This make sure than when updating the first one we don't overwrite the second one in the hash, and the second one
+ will be updated right later.
+ */
+void QAbstractItemModelPrivate::Persistent::insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data)
+{
+ QHash<QModelIndex,QPersistentModelIndexData *>::iterator newIt =
+ indexes.insertMulti(key, data);
+ QHash<QModelIndex,QPersistentModelIndexData *>::iterator it = newIt + 1;
+ while (it != indexes.end() && it.key() == key) {
+ qSwap(*newIt,*it);
+ newIt = it;
+ ++it;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h
new file mode 100644
index 0000000000..6de3bf5e4f
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel.h
@@ -0,0 +1,410 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QABSTRACTITEMMODEL_H
+#define QABSTRACTITEMMODEL_H
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QAbstractItemModel;
+class QPersistentModelIndex;
+
+class Q_CORE_EXPORT QModelIndex
+{
+ friend class QAbstractItemModel;
+ friend class QProxyModel;
+public:
+ inline QModelIndex() : r(-1), c(-1), p(0), m(0) {}
+ inline QModelIndex(const QModelIndex &other)
+ : r(other.r), c(other.c), p(other.p), m(other.m) {}
+ inline ~QModelIndex() { p = 0; m = 0; }
+ inline int row() const { return r; }
+ inline int column() const { return c; }
+ inline void *internalPointer() const { return p; }
+ inline qint64 internalId() const { return reinterpret_cast<qint64>(p); }
+ inline QModelIndex parent() const;
+ inline QModelIndex sibling(int row, int column) const;
+ inline QModelIndex child(int row, int column) const;
+ inline QVariant data(int role = Qt::DisplayRole) const;
+ inline Qt::ItemFlags flags() const;
+ inline const QAbstractItemModel *model() const { return m; }
+ inline bool isValid() const { return (r >= 0) && (c >= 0) && (m != 0); }
+ inline bool operator==(const QModelIndex &other) const
+ { return (other.r == r) && (other.p == p) && (other.c == c) && (other.m == m); }
+ inline bool operator!=(const QModelIndex &other) const
+ { return !(*this == other); }
+ inline bool operator<(const QModelIndex &other) const
+ {
+ if (r < other.r) return true;
+ if (r == other.r) {
+ if (c < other.c) return true;
+ if (c == other.c) {
+ if (p < other.p) return true;
+ if (p == other.p) return m < other.m;
+ }
+ }
+ return false; }
+private:
+ inline QModelIndex(int row, int column, void *ptr, const QAbstractItemModel *model);
+ int r, c;
+ void *p;
+ const QAbstractItemModel *m;
+};
+Q_DECLARE_TYPEINFO(QModelIndex, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QModelIndex &);
+#endif
+
+class QPersistentModelIndexData;
+
+class Q_CORE_EXPORT QPersistentModelIndex
+{
+public:
+ QPersistentModelIndex();
+ QPersistentModelIndex(const QModelIndex &index);
+ QPersistentModelIndex(const QPersistentModelIndex &other);
+ ~QPersistentModelIndex();
+ bool operator<(const QPersistentModelIndex &other) const;
+ bool operator==(const QPersistentModelIndex &other) const;
+ inline bool operator!=(const QPersistentModelIndex &other) const
+ { return !operator==(other); }
+ QPersistentModelIndex &operator=(const QPersistentModelIndex &other);
+ bool operator==(const QModelIndex &other) const;
+ bool operator!=(const QModelIndex &other) const;
+ QPersistentModelIndex &operator=(const QModelIndex &other);
+ operator const QModelIndex&() const;
+ int row() const;
+ int column() const;
+ void *internalPointer() const;
+ qint64 internalId() const;
+ QModelIndex parent() const;
+ QModelIndex sibling(int row, int column) const;
+ QModelIndex child(int row, int column) const;
+ QVariant data(int role = Qt::DisplayRole) const;
+ Qt::ItemFlags flags() const;
+ const QAbstractItemModel *model() const;
+ bool isValid() const;
+private:
+ QPersistentModelIndexData *d;
+ friend uint qHash(const QPersistentModelIndex &);
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
+#endif
+};
+Q_DECLARE_TYPEINFO(QPersistentModelIndex, Q_MOVABLE_TYPE);
+
+inline uint qHash(const QPersistentModelIndex &index)
+{ return qHash(index.d); }
+
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QPersistentModelIndex &);
+#endif
+
+template<typename T> class QList;
+typedef QList<QModelIndex> QModelIndexList;
+
+class QMimeData;
+class QAbstractItemModelPrivate;
+template <class Key, class T> class QMap;
+
+
+class Q_CORE_EXPORT QAbstractItemModel : public QObject
+{
+ Q_OBJECT
+
+ friend class QPersistentModelIndexData;
+ friend class QAbstractItemViewPrivate;
+public:
+
+ explicit QAbstractItemModel(QObject *parent = 0);
+ virtual ~QAbstractItemModel();
+
+ bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ virtual QModelIndex index(int row, int column,
+ const QModelIndex &parent = QModelIndex()) const = 0;
+ virtual QModelIndex parent(const QModelIndex &child) const = 0;
+
+ inline QModelIndex sibling(int row, int column, const QModelIndex &idx) const
+ { return index(row, column, parent(idx)); }
+
+ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0;
+ virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0;
+ virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const;
+
+ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0;
+ virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+ virtual QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const;
+ virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,
+ int role = Qt::EditRole);
+
+ virtual QMap<int, QVariant> itemData(const QModelIndex &index) const;
+ virtual bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles);
+
+ virtual QStringList mimeTypes() const;
+ virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
+ virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent);
+ virtual Qt::DropActions supportedDropActions() const;
+
+ Qt::DropActions supportedDragActions() const;
+ void setSupportedDragActions(Qt::DropActions);
+
+ virtual bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ virtual bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex());
+ virtual bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex());
+ virtual bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex());
+
+ inline bool insertRow(int row, const QModelIndex &parent = QModelIndex());
+ inline bool insertColumn(int column, const QModelIndex &parent = QModelIndex());
+ inline bool removeRow(int row, const QModelIndex &parent = QModelIndex());
+ inline bool removeColumn(int column, const QModelIndex &parent = QModelIndex());
+
+ virtual void fetchMore(const QModelIndex &parent);
+ virtual bool canFetchMore(const QModelIndex &parent) const;
+ virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+ virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
+ virtual QModelIndex buddy(const QModelIndex &index) const;
+ virtual QModelIndexList match(const QModelIndex &start, int role,
+ const QVariant &value, int hits = 1,
+ Qt::MatchFlags flags =
+ Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const;
+ virtual QSize span(const QModelIndex &index) const;
+
+ const QHash<int,QByteArray> &roleNames() const;
+
+#ifdef Q_NO_USING_KEYWORD
+ inline QObject *parent() const { return QObject::parent(); }
+#else
+ using QObject::parent;
+#endif
+
+Q_SIGNALS:
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void headerDataChanged(Qt::Orientation orientation, int first, int last);
+ void layoutChanged();
+ void layoutAboutToBeChanged();
+
+#if !defined(Q_MOC_RUN) && !defined(qdoc)
+private: // can only be emitted by QAbstractItemModel
+#endif
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void rowsInserted(const QModelIndex &parent, int first, int last);
+
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void rowsRemoved(const QModelIndex &parent, int first, int last);
+
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void columnsInserted(const QModelIndex &parent, int first, int last);
+
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void columnsRemoved(const QModelIndex &parent, int first, int last);
+
+ void modelAboutToBeReset();
+ void modelReset();
+
+ void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow );
+ void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row );
+
+ void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn );
+ void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column );
+
+
+public Q_SLOTS:
+ virtual bool submit();
+ virtual void revert();
+
+protected:
+ QAbstractItemModel(QAbstractItemModelPrivate &dd, QObject *parent = 0);
+
+ inline QModelIndex createIndex(int row, int column, void *data = 0) const;
+ inline QModelIndex createIndex(int row, int column, int id) const;
+ inline QModelIndex createIndex(int row, int column, quint32 id) const;
+
+ void encodeData(const QModelIndexList &indexes, QDataStream &stream) const;
+ bool decodeData(int row, int column, const QModelIndex &parent, QDataStream &stream);
+
+ void beginInsertRows(const QModelIndex &parent, int first, int last);
+ void endInsertRows();
+
+ void beginRemoveRows(const QModelIndex &parent, int first, int last);
+ void endRemoveRows();
+
+ bool beginMoveRows(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationRow);
+ void endMoveRows();
+
+ void beginInsertColumns(const QModelIndex &parent, int first, int last);
+ void endInsertColumns();
+
+ void beginRemoveColumns(const QModelIndex &parent, int first, int last);
+ void endRemoveColumns();
+
+ bool beginMoveColumns(const QModelIndex &sourceParent, int sourceFirst, int sourceLast, const QModelIndex &destinationParent, int destinationColumn);
+ void endMoveColumns();
+
+ void reset();
+
+ void beginResetModel();
+ void endResetModel();
+
+ void changePersistentIndex(const QModelIndex &from, const QModelIndex &to);
+ void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);
+ QModelIndexList persistentIndexList() const;
+
+ void setRoleNames(const QHash<int,QByteArray> &roleNames);
+
+private:
+ Q_DECLARE_PRIVATE(QAbstractItemModel)
+ Q_DISABLE_COPY(QAbstractItemModel)
+};
+
+inline bool QAbstractItemModel::insertRow(int arow, const QModelIndex &aparent)
+{ return insertRows(arow, 1, aparent); }
+inline bool QAbstractItemModel::insertColumn(int acolumn, const QModelIndex &aparent)
+{ return insertColumns(acolumn, 1, aparent); }
+inline bool QAbstractItemModel::removeRow(int arow, const QModelIndex &aparent)
+{ return removeRows(arow, 1, aparent); }
+inline bool QAbstractItemModel::removeColumn(int acolumn, const QModelIndex &aparent)
+{ return removeColumns(acolumn, 1, aparent); }
+
+inline QModelIndex QAbstractItemModel::createIndex(int arow, int acolumn, void *adata) const
+{ return QModelIndex(arow, acolumn, adata, this); }
+inline QModelIndex QAbstractItemModel::createIndex(int arow, int acolumn, int aid) const
+#if defined(Q_CC_MSVC)
+#pragma warning( push )
+#pragma warning( disable : 4312 ) // avoid conversion warning on 64-bit
+#endif
+{ return QModelIndex(arow, acolumn, reinterpret_cast<void*>(aid), this); }
+#if defined(Q_CC_MSVC)
+#pragma warning( pop )
+#endif
+inline QModelIndex QAbstractItemModel::createIndex(int arow, int acolumn, quint32 aid) const
+#if defined(Q_CC_MSVC)
+#pragma warning( push )
+#pragma warning( disable : 4312 ) // avoid conversion warning on 64-bit
+#endif
+{ return QModelIndex(arow, acolumn, reinterpret_cast<void*>(aid), this); }
+#if defined(Q_CC_MSVC)
+#pragma warning( pop )
+#endif
+
+
+class Q_CORE_EXPORT QAbstractTableModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit QAbstractTableModel(QObject *parent = 0);
+ ~QAbstractTableModel();
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent);
+protected:
+ QAbstractTableModel(QAbstractItemModelPrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractTableModel)
+ QModelIndex parent(const QModelIndex &child) const;
+ bool hasChildren(const QModelIndex &parent) const;
+};
+
+class Q_CORE_EXPORT QAbstractListModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit QAbstractListModel(QObject *parent = 0);
+ ~QAbstractListModel();
+
+ QModelIndex index(int row, int column = 0, const QModelIndex &parent = QModelIndex()) const;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent);
+protected:
+ QAbstractListModel(QAbstractItemModelPrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractListModel)
+ QModelIndex parent(const QModelIndex &child) const;
+ int columnCount(const QModelIndex &parent) const;
+ bool hasChildren(const QModelIndex &parent) const;
+};
+
+// inline implementations
+
+inline QModelIndex::QModelIndex(int arow, int acolumn, void *adata,
+ const QAbstractItemModel *amodel)
+ : r(arow), c(acolumn), p(adata), m(amodel) {}
+
+inline QModelIndex QModelIndex::parent() const
+{ return m ? m->parent(*this) : QModelIndex(); }
+
+inline QModelIndex QModelIndex::sibling(int arow, int acolumn) const
+{ return m ? (r == arow && c == acolumn) ? *this : m->index(arow, acolumn, m->parent(*this)) : QModelIndex(); }
+
+inline QModelIndex QModelIndex::child(int arow, int acolumn) const
+{ return m ? m->index(arow, acolumn, *this) : QModelIndex(); }
+
+inline QVariant QModelIndex::data(int arole) const
+{ return m ? m->data(*this, arole) : QVariant(); }
+
+inline Qt::ItemFlags QModelIndex::flags() const
+{ return m ? m->flags(*this) : Qt::ItemFlags(0); }
+
+inline uint qHash(const QModelIndex &index)
+{ return uint((index.row() << 4) + index.column() + index.internalId()); }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTITEMMODEL_H
diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h
new file mode 100644
index 0000000000..dfe5cef86a
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel_p.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QABSTRACTITEMMODEL_P_H
+#define QABSTRACTITEMMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QAbstractItemModel*. This header file may change from version
+// to version without notice, or even be removed.
+//
+// We mean it.
+//
+//
+
+#include "private/qobject_p.h"
+#include "QtCore/qstack.h"
+#include "QtCore/qset.h"
+#include "QtCore/qhash.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPersistentModelIndexData
+{
+public:
+ QPersistentModelIndexData() : model(0) {}
+ QPersistentModelIndexData(const QModelIndex &idx) : index(idx), model(idx.model()) {}
+ QModelIndex index;
+ QAtomicInt ref;
+ const QAbstractItemModel *model;
+ static QPersistentModelIndexData *create(const QModelIndex &index);
+ static void destroy(QPersistentModelIndexData *data);
+};
+
+class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractItemModel)
+
+public:
+ QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {}
+ void removePersistentIndexData(QPersistentModelIndexData *data);
+ void movePersistentIndexes(QVector<QPersistentModelIndexData *> indexes, int change, const QModelIndex &parent, Qt::Orientation orientation);
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void rowsInserted(const QModelIndex &parent, int first, int last);
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void rowsRemoved(const QModelIndex &parent, int first, int last);
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last);
+ void columnsInserted(const QModelIndex &parent, int first, int last);
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
+ void columnsRemoved(const QModelIndex &parent, int first, int last);
+ static QAbstractItemModel *staticEmptyModel();
+ static bool variantLessThan(const QVariant &v1, const QVariant &v2);
+
+ void itemsAboutToBeMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation);
+ void itemsMoved(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation);
+ bool allowMove(const QModelIndex &srcParent, int srcFirst, int srcLast, const QModelIndex &destinationParent, int destinationChild, Qt::Orientation orientation);
+
+ inline QModelIndex createIndex(int row, int column, void *data = 0) const {
+ return q_func()->createIndex(row, column, data);
+ }
+
+ inline QModelIndex createIndex(int row, int column, int id) const {
+ return q_func()->createIndex(row, column, id);
+ }
+
+ inline bool indexValid(const QModelIndex &index) const {
+ return (index.row() >= 0) && (index.column() >= 0) && (index.model() == q_func());
+ }
+
+ inline void invalidatePersistentIndexes() {
+ foreach (QPersistentModelIndexData *data, persistent.indexes) {
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+ persistent.indexes.clear();
+ }
+
+ /*!
+ \internal
+ clean the QPersistentModelIndex relative to the index if there is one.
+ To be used before an index is invalided
+ */
+ inline void invalidatePersistentIndex(const QModelIndex &index) {
+ QHash<QModelIndex, QPersistentModelIndexData *>::iterator it = persistent.indexes.find(index);
+ if(it != persistent.indexes.end()) {
+ QPersistentModelIndexData *data = *it;
+ persistent.indexes.erase(it);
+ data->index = QModelIndex();
+ data->model = 0;
+ }
+ }
+
+ struct Change {
+ Change() : first(-1), last(-1) {}
+ Change(const Change &c) : parent(c.parent), first(c.first), last(c.last), needsAdjust(c.needsAdjust) {}
+ Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l), needsAdjust(false) {}
+ QModelIndex parent;
+ int first, last;
+
+
+ // In cases such as this:
+ // - A
+ // - B
+ // - C
+ // - - D
+ // - - E
+ // - - F
+ //
+ // If B is moved to above E, C is the source parent in the signal and its row is 2. When the move is
+ // completed however, C is at row 1 and there is no row 2 at the same level in the model at all.
+ // The QModelIndex is adjusted to correct that in those cases before reporting it though the
+ // rowsMoved signal.
+ bool needsAdjust;
+
+ bool isValid() { return first >= 0 && last >= 0; }
+ };
+ QStack<Change> changes;
+
+ struct Persistent {
+ Persistent() {}
+ QHash<QModelIndex, QPersistentModelIndexData *> indexes;
+ QStack<QVector<QPersistentModelIndexData *> > moved;
+ QStack<QVector<QPersistentModelIndexData *> > invalidated;
+ void insertMultiAtEnd(const QModelIndex& key, QPersistentModelIndexData *data);
+ } persistent;
+
+ Qt::DropActions supportedDragActions;
+
+ QHash<int,QByteArray> roleNames;
+ static const QHash<int,QByteArray> &defaultRoleNames();
+};
+
+QT_END_NAMESPACE
+
+#endif // QABSTRACTITEMMODEL_P_H
diff --git a/src/corelib/kernel/qbasictimer.cpp b/src/corelib/kernel/qbasictimer.cpp
new file mode 100644
index 0000000000..6924848773
--- /dev/null
+++ b/src/corelib/kernel/qbasictimer.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qbasictimer.h"
+#include "qcoreapplication.h"
+#include "qabstracteventdispatcher.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QBasicTimer
+ \brief The QBasicTimer class provides timer events for objects.
+
+ \ingroup events
+
+ This is a fast, lightweight, and low-level class used by Qt
+ internally. We recommend using the higher-level QTimer class
+ rather than this class if you want to use timers in your
+ applications. Note that this timer is a repeating timer that
+ will send subsequent timer events unless the stop() function is called.
+
+ To use this class, create a QBasicTimer, and call its start()
+ function with a timeout interval and with a pointer to a QObject
+ subclass. When the timer times out it will send a timer event to
+ the QObject subclass. The timer can be stopped at any time using
+ stop(). isActive() returns true for a timer that is running;
+ i.e. it has been started, has not reached the timeout time, and
+ has not been stopped. The timer's ID can be retrieved using
+ timerId().
+
+ The \l{widgets/wiggly}{Wiggly} example uses QBasicTimer to repaint
+ a widget at regular intervals.
+
+ \sa QTimer, QTimerEvent, QObject::timerEvent(), Timers, {Wiggly Example}
+*/
+
+
+/*!
+ \fn QBasicTimer::QBasicTimer()
+
+ Contructs a basic timer.
+
+ \sa start()
+*/
+/*!
+ \fn QBasicTimer::~QBasicTimer()
+
+ Destroys the basic timer.
+*/
+
+/*!
+ \fn bool QBasicTimer::isActive() const
+
+ Returns true if the timer is running and has not been stopped; otherwise
+ returns false.
+
+ \sa start() stop()
+*/
+
+/*!
+ \fn int QBasicTimer::timerId() const
+
+ Returns the timer's ID.
+
+ \sa QTimerEvent::timerId()
+*/
+
+/*!
+ \fn void QBasicTimer::start(int msec, QObject *object)
+
+ Starts (or restarts) the timer with a \a msec milliseconds
+ timeout.
+
+ The given \a object will receive timer events.
+
+ \sa stop() isActive() QObject::timerEvent()
+ */
+void QBasicTimer::start(int msec, QObject *obj)
+{
+ stop();
+ if (obj)
+ id = obj->startTimer(msec);
+}
+
+/*!
+ Stops the timer.
+
+ \sa start() isActive()
+*/
+void QBasicTimer::stop()
+{
+ if (id) {
+ QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
+ if (eventDispatcher)
+ eventDispatcher->unregisterTimer(id);
+ }
+ id = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qbasictimer.h b/src/corelib/kernel/qbasictimer.h
new file mode 100644
index 0000000000..2b56624086
--- /dev/null
+++ b/src/corelib/kernel/qbasictimer.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QBASICTIMER_H
+#define QBASICTIMER_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QObject;
+
+class Q_CORE_EXPORT QBasicTimer
+{
+ int id;
+public:
+ inline QBasicTimer() : id(0) {}
+ inline ~QBasicTimer() { if (id) stop(); }
+
+ inline bool isActive() const { return id != 0; }
+ inline int timerId() const { return id; }
+
+ void start(int msec, QObject *obj);
+ void stop();
+};
+Q_DECLARE_TYPEINFO(QBasicTimer, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QBASICTIMER_H
diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp
new file mode 100644
index 0000000000..7b3f35e308
--- /dev/null
+++ b/src/corelib/kernel/qcore_mac.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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/qcore_mac_p.h>
+#include <new>
+#include "qvarlengtharray.h"
+
+QT_BEGIN_NAMESPACE
+
+QString QCFString::toQString(CFStringRef str)
+{
+ if(!str)
+ return QString();
+ CFIndex length = CFStringGetLength(str);
+ const UniChar *chars = CFStringGetCharactersPtr(str);
+ if (chars)
+ return QString(reinterpret_cast<const QChar *>(chars), length);
+
+ QVarLengthArray<UniChar> buffer(length);
+ CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data());
+ return QString(reinterpret_cast<const QChar *>(buffer.constData()), length);
+}
+
+QCFString::operator QString() const
+{
+ if (string.isEmpty() && type)
+ const_cast<QCFString*>(this)->string = toQString(type);
+ return string;
+}
+
+CFStringRef QCFString::toCFStringRef(const QString &string)
+{
+ return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
+ string.length());
+}
+
+QCFString::operator CFStringRef() const
+{
+ if (!type)
+ const_cast<QCFString*>(this)->type = toCFStringRef(string);
+ return type;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
new file mode 100644
index 0000000000..f7f6bfe483
--- /dev/null
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCORE_MAC_P_H
+#define QCORE_MAC_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef __IMAGECAPTURE__
+# define __IMAGECAPTURE__
+#endif
+
+#undef OLD_DEBUG
+#ifdef DEBUG
+# define OLD_DEBUG DEBUG
+# undef DEBUG
+#endif
+#define DEBUG 0
+#ifdef qDebug
+# define old_qDebug qDebug
+# undef qDebug
+#endif
+
+#if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED)
+#include <ApplicationServices/ApplicationServices.h>
+#else
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#ifndef QT_NO_CORESERVICES
+#include <CoreServices/CoreServices.h>
+#endif
+
+#undef DEBUG
+#ifdef OLD_DEBUG
+# define DEBUG OLD_DEBUG
+# undef OLD_DEBUG
+#endif
+
+#ifdef old_qDebug
+# undef qDebug
+# define qDebug QT_NO_QDEBUG_MACRO
+# undef old_qDebug
+#endif
+
+#include "qstring.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Helper class that automates refernce counting for CFtypes.
+ After constructing the QCFType object, it can be copied like a
+ value-based type.
+
+ Note that you must own the object you are wrapping.
+ This is typically the case if you get the object from a Core
+ Foundation function with the word "Create" or "Copy" in it. If
+ you got the object from a "Get" function, either retain it or use
+ constructFromGet(). One exception to this rule is the
+ HIThemeGet*Shape functions, which in reality are "Copy" functions.
+*/
+template <typename T>
+class Q_CORE_EXPORT QCFType
+{
+public:
+ inline QCFType(const T &t = 0) : type(t) {}
+ inline QCFType(const QCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
+ inline ~QCFType() { if (type) CFRelease(type); }
+ inline operator T() { return type; }
+ inline QCFType operator =(const QCFType &helper)
+ {
+ if (helper.type)
+ CFRetain(helper.type);
+ CFTypeRef type2 = type;
+ type = helper.type;
+ if (type2)
+ CFRelease(type2);
+ return *this;
+ }
+ inline T *operator&() { return &type; }
+ static QCFType constructFromGet(const T &t)
+ {
+ CFRetain(t);
+ return QCFType<T>(t);
+ }
+protected:
+ T type;
+};
+
+class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
+{
+public:
+ inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
+ inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
+ inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
+ operator QString() const;
+ operator CFStringRef() const;
+ static QString toQString(CFStringRef cfstr);
+ static CFStringRef toCFStringRef(const QString &str);
+private:
+ QString string;
+};
+
+QT_END_NAMESPACE
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5)
+#ifndef __LP64__
+ typedef float CGFloat;
+ typedef int NSInteger;
+ typedef unsigned int NSUInteger;
+ #define SRefCon SInt32
+ #define URefCon UInt32
+#endif
+#endif
+
+#endif // QCORE_MAC_P_H
diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp
new file mode 100644
index 0000000000..c717cb9f69
--- /dev/null
+++ b/src/corelib/kernel/qcore_symbian_p.cpp
@@ -0,0 +1,317 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 <exception>
+#include <e32base.h>
+#include <e32uid.h>
+#include "qcore_symbian_p.h"
+#include <string>
+#include <in_sock.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Helper function for calling into Symbian classes that expect a TDes&.
+ This function converts a QString to a TDes by allocating memory that
+ must be deleted by the caller.
+*/
+
+Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString)
+{
+ HBufC *buffer;
+#ifdef QT_NO_UNICODE
+ TPtrC8 ptr(reinterpret_cast<const TUint8*>(aString.toLocal8Bit().constData()));
+#else
+ TPtrC16 ptr(qt_QString2TPtrC(aString));
+#endif
+ buffer = HBufC::New(ptr.Length());
+ Q_CHECK_PTR(buffer);
+ buffer->Des().Copy(ptr);
+ return buffer;
+}
+
+Q_CORE_EXPORT QString qt_TDesC2QString(const TDesC& aDescriptor)
+{
+#ifdef QT_NO_UNICODE
+ return QString::fromLocal8Bit(aDescriptor.Ptr(), aDescriptor.Length());
+#else
+ return QString(reinterpret_cast<const QChar *>(aDescriptor.Ptr()), aDescriptor.Length());
+#endif
+}
+
+QHBufC::QHBufC()
+ : m_hBufC(0)
+{
+}
+
+QHBufC::QHBufC(const QHBufC &src)
+ : m_hBufC(src.m_hBufC->Alloc())
+{
+ Q_CHECK_PTR(m_hBufC);
+}
+
+/*!
+ \internal
+ Constructs a QHBufC from an HBufC. Note that the QHBufC instance takes
+ ownership of the HBufC.
+*/
+QHBufC::QHBufC(HBufC *src)
+ : m_hBufC(src)
+{
+}
+
+QHBufC::QHBufC(const QString &src)
+{
+ m_hBufC = qt_QString2HBufC(src);
+}
+
+QHBufC::~QHBufC()
+{
+ if (m_hBufC)
+ delete m_hBufC;
+}
+
+class QS60PluginResolver
+{
+public:
+ QS60PluginResolver()
+ : initTried(false) {}
+
+ ~QS60PluginResolver() {
+ lib.Close();
+ }
+
+ TLibraryFunction resolve(int ordinal) {
+ if (!initTried) {
+ init();
+ initTried = true;
+ }
+
+ if (lib.Handle())
+ return lib.Lookup(ordinal);
+ else
+ return reinterpret_cast<TLibraryFunction>(NULL);
+ }
+
+private:
+ void init()
+ {
+ _LIT(KLibName_3_1, "qts60plugin_3_1" QT_LIBINFIX_UNICODE L".dll");
+ _LIT(KLibName_3_2, "qts60plugin_3_2" QT_LIBINFIX_UNICODE L".dll");
+ _LIT(KLibName_5_0, "qts60plugin_5_0" QT_LIBINFIX_UNICODE L".dll");
+
+ TPtrC libName;
+ TInt uidValue;
+ switch (QSysInfo::s60Version()) {
+ case QSysInfo::SV_S60_3_1:
+ libName.Set(KLibName_3_1);
+ uidValue = 0x2001E620;
+ break;
+ case QSysInfo::SV_S60_3_2:
+ libName.Set(KLibName_3_2);
+ uidValue = 0x2001E621;
+ break;
+ case QSysInfo::SV_S60_5_0: // Fall through to default
+ default:
+ // Default to 5.0 version, as any unknown platform is likely to be newer than that
+ libName.Set(KLibName_5_0);
+ uidValue = 0x2001E622;
+ break;
+ }
+
+ TUidType libUid(KDynamicLibraryUid, KSharedLibraryUid, TUid::Uid(uidValue));
+ lib.Load(libName, libUid);
+
+ // Duplicate lib handle to enable process wide access to it. Since Duplicate overwrites
+ // existing handle without closing it, store original for subsequent closing.
+ RLibrary origHandleCloser = lib;
+ lib.Duplicate(RThread(), EOwnerProcess);
+ origHandleCloser.Close();
+ }
+
+ RLibrary lib;
+ bool initTried;
+};
+
+Q_GLOBAL_STATIC(QS60PluginResolver, qt_s60_plugin_resolver);
+
+/*!
+ \internal
+ Resolves a platform version specific function from S60 plugin.
+ If plugin is missing or resolving fails for another reason, NULL is returned.
+*/
+Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal)
+{
+ return qt_s60_plugin_resolver()->resolve(ordinal);
+}
+
+class QS60RFsSession
+{
+public:
+ QS60RFsSession() {
+ qt_symbian_throwIfError(iFs.Connect());
+ qt_symbian_throwIfError(iFs.ShareProtected());
+ }
+
+ ~QS60RFsSession() {
+ iFs.Close();
+ }
+
+ RFs& GetRFs() {
+ return iFs;
+ }
+
+private:
+
+ RFs iFs;
+};
+
+uint qHash(const RSubSessionBase& key)
+{
+ return qHash(key.SubSessionHandle());
+}
+
+Q_GLOBAL_STATIC(QS60RFsSession, qt_s60_RFsSession);
+
+Q_CORE_EXPORT RFs& qt_s60GetRFs()
+{
+ return qt_s60_RFsSession()->GetRFs();
+}
+
+QSymbianSocketManager::QSymbianSocketManager() :
+ iNextSocket(0), iDefaultConnection(0)
+{
+ TSessionPref preferences;
+ // ### In future this could be changed to KAfInet6 when that is more common than IPv4
+ preferences.iAddrFamily = KAfInet;
+ preferences.iProtocol = KProtocolInetIp;
+ //use global message pool, as we do not know how many sockets app will use
+ //TODO: is this the right choice?
+ qt_symbian_throwIfError(iSocketServ.Connect(preferences, -1));
+ qt_symbian_throwIfError(iSocketServ.ShareAuto());
+}
+
+QSymbianSocketManager::~QSymbianSocketManager()
+{
+ iSocketServ.Close();
+ if(!socketMap.isEmpty()) {
+ qWarning("leaked %d sockets on exit", socketMap.count());
+ }
+}
+
+RSocketServ& QSymbianSocketManager::getSocketServer() {
+ return iSocketServ;
+}
+
+int QSymbianSocketManager::addSocket(const RSocket& socket) {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ Q_ASSERT(!socketMap.contains(sock));
+ if(socketMap.contains(sock))
+ return socketMap.value(sock);
+ // allocate socket number
+ int guard = 0;
+ while(reverseSocketMap.contains(iNextSocket)) {
+ iNextSocket++;
+ iNextSocket %= max_sockets;
+ guard++;
+ if(guard > max_sockets)
+ return -1;
+ }
+ int id = iNextSocket;
+
+ socketMap[sock] = id;
+ reverseSocketMap[id] = sock;
+ return id + socket_offset;
+}
+
+bool QSymbianSocketManager::removeSocket(const RSocket &socket) {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ if(!socketMap.contains(sock))
+ return false;
+ int id = socketMap.value(sock);
+ socketMap.remove(sock);
+ reverseSocketMap.remove(id);
+ return true;
+}
+
+int QSymbianSocketManager::lookupSocket(const RSocket& socket) const {
+ QHashableSocket sock(static_cast<const QHashableSocket &>(socket));
+ QMutexLocker l(&iMutex);
+ if(!socketMap.contains(sock))
+ return -1;
+ int id = socketMap.value(sock);
+ return id + socket_offset;
+}
+
+bool QSymbianSocketManager::lookupSocket(int fd, RSocket& socket) const {
+ QMutexLocker l(&iMutex);
+ int id = fd - socket_offset;
+ if(!reverseSocketMap.contains(id))
+ return false;
+ socket = reverseSocketMap.value(id);
+ return true;
+}
+
+void QSymbianSocketManager::setDefaultConnection(RConnection* con)
+{
+ iDefaultConnection = con;
+}
+
+RConnection* QSymbianSocketManager::defaultConnection() const
+{
+ return iDefaultConnection;
+}
+
+Q_GLOBAL_STATIC(QSymbianSocketManager, qt_symbianSocketManager);
+
+QSymbianSocketManager& QSymbianSocketManager::instance()
+{
+ return *(qt_symbianSocketManager());
+}
+
+Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer()
+{
+ return QSymbianSocketManager::instance().getSocketServer();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h
new file mode 100644
index 0000000000..cbe84a8aa1
--- /dev/null
+++ b/src/corelib/kernel/qcore_symbian_p.h
@@ -0,0 +1,282 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCORE_SYMBIAN_P_H
+#define QCORE_SYMBIAN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <e32std.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qmutex.h>
+#include <qstring.h>
+#include <qrect.h>
+#include <qhash.h>
+#include <f32file.h>
+#include <es_sock.h>
+
+#define QT_LSTRING2(x) L##x
+#define QT_LSTRING(x) QT_LSTRING2(x)
+
+#if defined(QT_LIBINFIX)
+# define QT_LIBINFIX_UNICODE QT_LSTRING(QT_LIBINFIX)
+#else
+# define QT_LIBINFIX_UNICODE L""
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT HBufC* qt_QString2HBufC(const QString& aString);
+
+Q_CORE_EXPORT QString qt_TDesC2QString(const TDesC& aDescriptor);
+inline QString qt_TDes2QString(const TDes& aDescriptor) { return qt_TDesC2QString(aDescriptor); }
+
+static inline QSize qt_TSize2QSize(const TSize& ts)
+{
+ return QSize(ts.iWidth, ts.iHeight);
+}
+
+static inline TSize qt_QSize2TSize(const QSize& qs)
+{
+ return TSize(qs.width(), qs.height());
+}
+
+static inline QRect qt_TRect2QRect(const TRect& tr)
+{
+ return QRect(tr.iTl.iX, tr.iTl.iY, tr.Width(), tr.Height());
+}
+
+static inline TRect qt_QRect2TRect(const QRect& qr)
+{
+ return TRect(TPoint(qr.left(), qr.top()), TSize(qr.width(), qr.height()));
+}
+
+// Returned TPtrC is valid as long as the given parameter is valid and unmodified
+static inline TPtrC qt_QString2TPtrC( const QString& string )
+{
+ return TPtrC16(static_cast<const TUint16*>(string.utf16()), string.length());
+}
+
+/*!
+ \internal
+ This class is a wrapper around the Symbian HBufC descriptor class.
+ It makes sure that the heap allocated HBufC class is freed when it is
+ destroyed.
+*/
+class Q_CORE_EXPORT QHBufC
+{
+public:
+ QHBufC();
+ QHBufC(const QHBufC &src);
+ QHBufC(HBufC *src);
+ QHBufC(const QString &src);
+ ~QHBufC();
+
+ inline operator HBufC *() { return m_hBufC; }
+ inline operator const HBufC *() const { return m_hBufC; }
+ inline HBufC *data() { return m_hBufC; }
+ inline const HBufC *data() const { return m_hBufC; }
+ inline HBufC & operator*() { return *m_hBufC; }
+ inline const HBufC & operator*() const { return *m_hBufC; }
+ inline HBufC * operator->() { return m_hBufC; }
+ inline const HBufC * operator->() const { return m_hBufC; }
+
+ inline bool operator==(const QHBufC &param) const { return data() == param.data(); }
+ inline bool operator!=(const QHBufC &param) const { return data() != param.data(); }
+
+private:
+ HBufC *m_hBufC;
+};
+
+inline uint qHash(TUid uid)
+{
+ return qHash(uid.iUid);
+}
+
+// S60 version specific function ordinals that can be resolved
+enum S60PluginFuncOrdinals
+{
+ S60Plugin_TimeFormatL = 1,
+ S60Plugin_GetTimeFormatSpec = 2,
+ S60Plugin_GetLongDateFormatSpec = 3,
+ S60Plugin_GetShortDateFormatSpec = 4,
+ S60Plugin_LocalizedDirectoryName = 5,
+ S60Plugin_GetSystemDrive = 6
+};
+
+Q_CORE_EXPORT TLibraryFunction qt_resolveS60PluginFunc(int ordinal);
+
+Q_CORE_EXPORT RFs& qt_s60GetRFs();
+Q_CORE_EXPORT RSocketServ& qt_symbianGetSocketServer();
+
+// Defined in qlocale_symbian.cpp.
+Q_CORE_EXPORT QByteArray qt_symbianLocaleName(int code);
+
+template <typename R>
+struct QScopedPointerRCloser
+{
+ static inline void cleanup(R *rPointer)
+ {
+ // Enforce a complete type.
+ // If you get a compile error here, read the section on forward declared
+ // classes in the QScopedPointer documentation.
+ typedef char IsIncompleteType[ sizeof(R) ? 1 : -1 ];
+ (void) sizeof(IsIncompleteType);
+
+ if (rPointer)
+ rPointer->Close();
+ }
+};
+
+//Wrapper for RSocket so it can be used as a key in QHash or QMap
+class QHashableSocket : public RSocket
+{
+public:
+ bool operator==(const QHashableSocket &other) const
+ {
+ return SubSessionHandle() == other.SubSessionHandle()
+ && Session().Handle() == other.Session().Handle();
+ }
+ bool operator<(const QHashableSocket &other) const
+ {
+ if (Session().Handle() == other.Session().Handle())
+ return SubSessionHandle() < other.SubSessionHandle();
+ return Session().Handle() < other.Session().Handle();
+ }
+};
+
+uint qHash(const RSubSessionBase& key);
+
+/*!
+ \internal
+ This class exists in QtCore for the benefit of QSocketNotifier, which uses integer
+ file descriptors in its public API.
+ So we need a way to map between int and RSocket.
+ Additionally, it is used to host the global RSocketServ session
+*/
+class Q_CORE_EXPORT QSymbianSocketManager
+{
+public:
+ QSymbianSocketManager();
+ ~QSymbianSocketManager();
+
+ /*!
+ \internal
+ \return handle to the socket server
+ */
+ RSocketServ& getSocketServer();
+ /*!
+ \internal
+ Adds a symbian socket to the global map
+ \param an open socket
+ \return pseudo file descriptor, -1 if out of resources
+ */
+ int addSocket(const RSocket &sock);
+ /*!
+ \internal
+ Removes a symbian socket from the global map
+ \param an open socket
+ \return true if the socket was in the map
+ */
+ bool removeSocket(const RSocket &sock);
+ /*!
+ \internal
+ Get pseudo file descriptor for a socket
+ \param an open socket
+ \return integer handle, or -1 if not in map
+ */
+ int lookupSocket(const RSocket &sock) const;
+ /*!
+ \internal
+ Get socket for a pseudo file descriptor
+ \param an open socket fd
+ \param sock (out) socket handle
+ \return true on success or false if not in map
+ */
+ bool lookupSocket(int fd, RSocket& sock) const;
+
+ /*!
+ \internal
+ Set the default connection to use for new sockets
+ \param an open connection
+ */
+ void setDefaultConnection(RConnection* con);
+ /*!
+ \internal
+ Get the default connection to use for new sockets
+ \return the connection, or null pointer if there is none set
+ */
+ RConnection *defaultConnection() const;
+
+ /*!
+ \internal
+ Gets a reference to the singleton socket manager
+ */
+ static QSymbianSocketManager& instance();
+private:
+ int allocateSocket();
+
+ const static int max_sockets = 0x20000; //covers all TCP and UDP ports, probably run out of memory first
+ const static int socket_offset = 0x40000000; //hacky way of separating sockets from file descriptors
+ int iNextSocket;
+ QHash<QHashableSocket, int> socketMap;
+ QHash<int, RSocket> reverseSocketMap;
+ mutable QMutex iMutex;
+ RSocketServ iSocketServ;
+ RConnection *iDefaultConnection;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QCORE_SYMBIAN_P_H
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
new file mode 100644
index 0000000000..834f05b208
--- /dev/null
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qcore_unix_p.h"
+#include "qelapsedtimer.h"
+
+#ifdef Q_OS_NACL
+#elif !defined (Q_OS_VXWORKS)
+# if !defined(Q_OS_HPUX) || defined(__ia64)
+# include <sys/select.h>
+# endif
+# include <sys/time.h>
+#else
+# include <selectLib.h>
+#endif
+
+#include <stdlib.h>
+
+#ifdef Q_OS_MAC
+#include <mach/mach_time.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static inline bool time_update(struct timeval *tv, const struct timeval &start,
+ const struct timeval &timeout)
+{
+ if (!QElapsedTimer::isMonotonic()) {
+ // we cannot recalculate the timeout without a monotonic clock as the time may have changed
+ return false;
+ }
+
+ // clock source is monotonic, so we can recalculate how much timeout is left
+ struct timeval now = qt_gettime();
+ *tv = timeout + start - now;
+ return tv->tv_sec >= 0;
+}
+
+int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
+ const struct timeval *orig_timeout)
+{
+ if (!orig_timeout) {
+ // no timeout -> block forever
+ register int ret;
+ EINTR_LOOP(ret, select(nfds, fdread, fdwrite, fdexcept, 0));
+ return ret;
+ }
+
+ timeval start = qt_gettime();
+ timeval timeout = *orig_timeout;
+
+ // loop and recalculate the timeout as needed
+ int ret;
+ forever {
+ ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout);
+ if (ret != -1 || errno != EINTR)
+ return ret;
+
+ // recalculate the timeout
+ if (!time_update(&timeout, start, *orig_timeout)) {
+ // timeout during update
+ // or clock reset, fake timeout error
+ return 0;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
new file mode 100644
index 0000000000..33df0daab4
--- /dev/null
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCORE_UNIX_P_H
+#define QCORE_UNIX_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of Qt code on Unix. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qplatformdefs.h"
+
+#ifndef Q_OS_UNIX
+# error "qcore_unix_p.h included on a non-Unix system"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#if defined(Q_OS_VXWORKS)
+# include <ioLib.h>
+#endif
+
+struct sockaddr;
+
+#if defined(Q_OS_LINUX) && defined(O_CLOEXEC)
+# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 1
+QT_BEGIN_NAMESPACE
+namespace QtLibcSupplement {
+ inline int accept4(int, sockaddr *, QT_SOCKLEN_T *, int)
+ { errno = ENOSYS; return -1; }
+ inline int dup3(int, int, int)
+ { errno = ENOSYS; return -1; }
+ inline int pipe2(int [], int )
+ { errno = ENOSYS; return -1; }
+}
+QT_END_NAMESPACE
+using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement);
+
+#else
+# define QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC 0
+#endif
+
+#define EINTR_LOOP(var, cmd) \
+ do { \
+ var = cmd; \
+ } while (var == -1 && errno == EINTR)
+
+QT_BEGIN_NAMESPACE
+
+// Internal operator functions for timevals
+inline timeval &normalizedTimeval(timeval &t)
+{
+ while (t.tv_usec > 1000000l) {
+ ++t.tv_sec;
+ t.tv_usec -= 1000000l;
+ }
+ while (t.tv_usec < 0l) {
+ --t.tv_sec;
+ t.tv_usec += 1000000l;
+ }
+ return t;
+}
+inline bool operator<(const timeval &t1, const timeval &t2)
+{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); }
+inline bool operator==(const timeval &t1, const timeval &t2)
+{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; }
+inline timeval &operator+=(timeval &t1, const timeval &t2)
+{
+ t1.tv_sec += t2.tv_sec;
+ t1.tv_usec += t2.tv_usec;
+ return normalizedTimeval(t1);
+}
+inline timeval operator+(const timeval &t1, const timeval &t2)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec + t2.tv_sec;
+ tmp.tv_usec = t1.tv_usec + t2.tv_usec;
+ return normalizedTimeval(tmp);
+}
+inline timeval operator-(const timeval &t1, const timeval &t2)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1);
+ tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000);
+ return normalizedTimeval(tmp);
+}
+inline timeval operator*(const timeval &t1, int mul)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec * mul;
+ tmp.tv_usec = t1.tv_usec * mul;
+ return normalizedTimeval(tmp);
+}
+
+// don't call QT_OPEN or ::open
+// call qt_safe_open
+static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
+{
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
+ register int fd;
+ EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
+
+ // unknown flags are ignored, so we have no way of verifying if
+ // O_CLOEXEC was accepted
+ if (fd != -1)
+ ::fcntl(fd, F_SETFD, FD_CLOEXEC);
+ return fd;
+}
+#undef QT_OPEN
+#define QT_OPEN qt_safe_open
+
+#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks
+// don't call ::pipe
+// call qt_safe_pipe
+static inline int qt_safe_pipe(int pipefd[2], int flags = 0)
+{
+#ifdef O_CLOEXEC
+ Q_ASSERT((flags & ~(O_CLOEXEC | O_NONBLOCK)) == 0);
+#else
+ Q_ASSERT((flags & ~O_NONBLOCK) == 0);
+#endif
+
+ register int ret;
+#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
+ // use pipe2
+ flags |= O_CLOEXEC;
+ ret = ::pipe2(pipefd, flags); // pipe2 is Linux-specific and is documented not to return EINTR
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+#endif
+
+ ret = ::pipe(pipefd);
+ if (ret == -1)
+ return -1;
+
+ ::fcntl(pipefd[0], F_SETFD, FD_CLOEXEC);
+ ::fcntl(pipefd[1], F_SETFD, FD_CLOEXEC);
+
+ // set non-block too?
+ if (flags & O_NONBLOCK) {
+ ::fcntl(pipefd[0], F_SETFL, ::fcntl(pipefd[0], F_GETFL) | O_NONBLOCK);
+ ::fcntl(pipefd[1], F_SETFL, ::fcntl(pipefd[1], F_GETFL) | O_NONBLOCK);
+ }
+
+ return 0;
+}
+
+#endif // Q_OS_VXWORKS
+
+// don't call dup or fcntl(F_DUPFD)
+static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC)
+{
+ Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
+
+ register int ret;
+#ifdef F_DUPFD_CLOEXEC
+ // use this fcntl
+ if (flags & FD_CLOEXEC) {
+ ret = ::fcntl(oldfd, F_DUPFD_CLOEXEC, atleast);
+ if (ret != -1 || errno != EINVAL)
+ return ret;
+ }
+#endif
+
+ // use F_DUPFD
+ ret = ::fcntl(oldfd, F_DUPFD, atleast);
+
+ if (flags && ret != -1)
+ ::fcntl(ret, F_SETFD, flags);
+ return ret;
+}
+
+// don't call dup2
+// call qt_safe_dup2
+static inline int qt_safe_dup2(int oldfd, int newfd, int flags = FD_CLOEXEC)
+{
+ Q_ASSERT(flags == FD_CLOEXEC || flags == 0);
+
+ register int ret;
+#if QT_UNIX_SUPPORTS_THREADSAFE_CLOEXEC && defined(O_CLOEXEC)
+ // use dup3
+ if (flags & FD_CLOEXEC) {
+ EINTR_LOOP(ret, ::dup3(oldfd, newfd, O_CLOEXEC));
+ if (ret == 0 || errno != ENOSYS)
+ return ret;
+ }
+#endif
+ EINTR_LOOP(ret, ::dup2(oldfd, newfd));
+ if (ret == -1)
+ return -1;
+
+ if (flags)
+ ::fcntl(newfd, F_SETFD, flags);
+ return 0;
+}
+
+static inline qint64 qt_safe_read(int fd, void *data, qint64 maxlen)
+{
+ qint64 ret = 0;
+ EINTR_LOOP(ret, QT_READ(fd, data, maxlen));
+ return ret;
+}
+#undef QT_READ
+#define QT_READ qt_safe_read
+
+static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
+{
+ qint64 ret = 0;
+ EINTR_LOOP(ret, QT_WRITE(fd, data, len));
+ return ret;
+}
+#undef QT_WRITE
+#define QT_WRITE qt_safe_write
+
+static inline int qt_safe_close(int fd)
+{
+ register int ret;
+ EINTR_LOOP(ret, QT_CLOSE(fd));
+ return ret;
+}
+#undef QT_CLOSE
+#define QT_CLOSE qt_safe_close
+
+// - Open C does not (yet?) implement these on Symbian OS
+// - VxWorks doesn't have processes
+#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_VXWORKS)
+static inline int qt_safe_execve(const char *filename, char *const argv[],
+ char *const envp[])
+{
+ register int ret;
+ EINTR_LOOP(ret, ::execve(filename, argv, envp));
+ return ret;
+}
+
+static inline int qt_safe_execv(const char *path, char *const argv[])
+{
+ register int ret;
+ EINTR_LOOP(ret, ::execv(path, argv));
+ return ret;
+}
+
+static inline int qt_safe_execvp(const char *file, char *const argv[])
+{
+ register int ret;
+ EINTR_LOOP(ret, ::execvp(file, argv));
+ return ret;
+}
+#endif
+
+#ifndef Q_OS_VXWORKS // no processes on VxWorks
+static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
+{
+ register int ret;
+ EINTR_LOOP(ret, ::waitpid(pid, status, options));
+ return ret;
+}
+
+#endif // Q_OS_VXWORKS
+
+#if !defined(_POSIX_MONOTONIC_CLOCK)
+# define _POSIX_MONOTONIC_CLOCK -1
+#endif
+
+timeval qt_gettime(); // in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
+
+Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
+ const struct timeval *tv);
+
+// according to X/OPEN we have to define semun ourselves
+// we use prefix as on some systems sem.h will have it
+struct semid_ds;
+union qt_semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* array for GETALL, SETALL */
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
new file mode 100644
index 0000000000..be86c58d47
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -0,0 +1,2730 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreevent.h"
+#include "qeventloop.h"
+#include "qcorecmdlineargs_p.h"
+#include <qdatastream.h>
+#include <qdebug.h>
+#include <qdir.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qhash.h>
+#include <private/qprocess_p.h>
+#include <qtextcodec.h>
+#include <qthread.h>
+#include <qthreadpool.h>
+#include <qthreadstorage.h>
+#include <private/qthread_p.h>
+#include <qelapsedtimer.h>
+#include <qlibraryinfo.h>
+#include <qvarlengtharray.h>
+#include <private/qfactoryloader_p.h>
+#include <private/qfunctions_p.h>
+#include <private/qlocale_p.h>
+
+#ifdef Q_OS_SYMBIAN
+# include <exception>
+# include <f32file.h>
+# include <e32ldr.h>
+# include "qeventdispatcher_symbian_p.h"
+# include "private/qcore_symbian_p.h"
+# include "private/qfilesystemengine_p.h"
+# include <apacmdln.h>
+#elif defined(Q_OS_UNIX)
+# if !defined(QT_NO_GLIB)
+# include "qeventdispatcher_glib_p.h"
+# endif
+# include "qeventdispatcher_unix_p.h"
+#endif
+
+#ifdef Q_OS_WIN
+# include "qeventdispatcher_win_p.h"
+#endif
+
+#ifdef Q_OS_MAC
+# include "qcore_mac_p.h"
+#endif
+
+#include <stdlib.h>
+
+#ifdef Q_OS_UNIX
+# include <locale.h>
+#endif
+
+#ifdef Q_OS_VXWORKS
+# include <taskLib.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QMutexUnlocker
+{
+public:
+ inline explicit QMutexUnlocker(QMutex *m)
+ : mtx(m)
+ { }
+ inline ~QMutexUnlocker() { unlock(); }
+ inline void unlock() { if (mtx) mtx->unlock(); mtx = 0; }
+
+private:
+ Q_DISABLE_COPY(QMutexUnlocker)
+
+ QMutex *mtx;
+};
+
+#ifdef Q_OS_SYMBIAN
+typedef TDriveNumber (*SystemDriveFunc)(RFs&);
+static SystemDriveFunc PtrGetSystemDrive = 0;
+static CApaCommandLine* apaCommandLine = 0;
+static char *apaTail = 0;
+static QVector<char *> *apaArgv = 0;
+
+static void qt_cleanup_apa_cmd_line()
+{
+ delete apaCommandLine;
+ apaCommandLine = 0;
+ delete apaArgv;
+ apaArgv = 0;
+ delete apaTail;
+ apaTail = 0;
+}
+
+static inline void qt_init_symbian_apa_arguments(int &argc, char **&argv)
+{
+ // If app is launched via CApaCommandLine::StartApp(), normal arguments only contain
+ // application name.
+ if (argc == 1) {
+ CApaCommandLine* commandLine = QCoreApplicationPrivate::symbianCommandLine();
+ if(commandLine) {
+ TPtrC8 apaCmdLine = commandLine->TailEnd();
+ int tailLen = apaCmdLine.Length();
+ if (tailLen) {
+ apaTail = reinterpret_cast<char *>(qMalloc(tailLen + 1));
+ qMemCopy(apaTail, reinterpret_cast<const char *>(apaCmdLine.Ptr()), tailLen);
+ apaTail[tailLen] = '\0';
+ apaArgv = new QVector<char *>(8);
+ // Reuse windows command line parsing
+ *apaArgv = qWinCmdLine<char>(apaTail, tailLen, argc);
+ apaArgv->insert(0, argv[0]);
+ argc++;
+ argv = apaArgv->data();
+ }
+ }
+ }
+}
+
+CApaCommandLine* QCoreApplicationPrivate::symbianCommandLine()
+{
+ // Getting of Apa command line needs to be static as it can only be called successfully
+ // once per process.
+ if (!apaCommandLine) {
+ TInt err = CApaCommandLine::GetCommandLineFromProcessEnvironment(apaCommandLine);
+ if (err == KErrNone) {
+ qAddPostRoutine(qt_cleanup_apa_cmd_line);
+ }
+ }
+ return apaCommandLine;
+}
+
+#endif
+
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+extern QString qAppFileName();
+#endif
+
+int QCoreApplicationPrivate::app_compile_version = 0x040000; //we don't know exactly, but it's at least 4.0.0
+#if defined(QT3_SUPPORT)
+bool QCoreApplicationPrivate::useQt3Support = true;
+#endif
+
+#if !defined(Q_OS_WIN)
+#ifdef Q_OS_MAC
+QString QCoreApplicationPrivate::macMenuBarName()
+{
+ QString bundleName;
+ CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("CFBundleName"));
+ if (string)
+ bundleName = QCFString::toQString(static_cast<CFStringRef>(string));
+ return bundleName;
+}
+#endif
+QString QCoreApplicationPrivate::appName() const
+{
+ static QString applName;
+#ifdef Q_OS_MAC
+ applName = macMenuBarName();
+#endif
+ if (applName.isEmpty() && argv[0]) {
+ char *p = strrchr(argv[0], '/');
+ applName = QString::fromLocal8Bit(p ? p + 1 : argv[0]);
+ }
+ return applName;
+}
+#endif
+
+bool QCoreApplicationPrivate::checkInstance(const char *function)
+{
+ bool b = (QCoreApplication::self != 0);
+ if (!b)
+ qWarning("QApplication::%s: Please instantiate the QApplication object first", function);
+ return b;
+}
+
+// Support for introspection
+
+QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set = { 0, 0, 0, 0 };
+
+void qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set)
+{
+ qt_signal_spy_callback_set = callback_set;
+}
+
+extern "C" void Q_CORE_EXPORT qt_startup_hook()
+{
+}
+
+typedef QList<QtCleanUpFunction> QVFuncList;
+Q_GLOBAL_STATIC(QVFuncList, postRList)
+
+void qAddPostRoutine(QtCleanUpFunction p)
+{
+ QVFuncList *list = postRList();
+ if (!list)
+ return;
+ list->prepend(p);
+}
+
+void qRemovePostRoutine(QtCleanUpFunction p)
+{
+ QVFuncList *list = postRList();
+ if (!list)
+ return;
+ list->removeAll(p);
+}
+
+void Q_CORE_EXPORT qt_call_post_routines()
+{
+ QVFuncList *list = 0;
+ QT_TRY {
+ list = postRList();
+ } QT_CATCH(const std::bad_alloc &) {
+ // ignore - if we can't allocate a post routine list,
+ // there's a high probability that there's no post
+ // routine to be executed :)
+ }
+ if (!list)
+ return;
+ while (!list->isEmpty())
+ (list->takeFirst())();
+}
+
+
+// app starting up if false
+bool QCoreApplicationPrivate::is_app_running = false;
+ // app closing down if true
+bool QCoreApplicationPrivate::is_app_closing = false;
+// initialized in qcoreapplication and in qtextstream autotest when setlocale is called.
+Q_CORE_EXPORT bool qt_locale_initialized = false;
+
+
+Q_CORE_EXPORT uint qGlobalPostedEventsCount()
+{
+ QThreadData *currentThreadData = QThreadData::current();
+ return currentThreadData->postEventList.size() - currentThreadData->postEventList.startOffset;
+}
+
+
+void qt_set_current_thread_to_main_thread()
+{
+ QCoreApplicationPrivate::theMainThread = QThread::currentThread();
+}
+
+
+
+QCoreApplication *QCoreApplication::self = 0;
+QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;
+uint QCoreApplicationPrivate::attribs;
+
+#ifdef Q_OS_UNIX
+Qt::HANDLE qt_application_thread_id = 0;
+#endif
+
+struct QCoreApplicationData {
+ QCoreApplicationData() {
+#ifndef QT_NO_LIBRARY
+ app_libpaths = 0;
+#endif
+ }
+ ~QCoreApplicationData() {
+#ifndef QT_NO_LIBRARY
+ delete app_libpaths;
+#endif
+
+ // cleanup the QAdoptedThread created for the main() thread
+ if (QCoreApplicationPrivate::theMainThread) {
+ QThreadData *data = QThreadData::get2(QCoreApplicationPrivate::theMainThread);
+ QCoreApplicationPrivate::theMainThread = 0;
+ data->deref(); // deletes the data and the adopted thread
+ }
+ }
+ QString orgName, orgDomain, application;
+ QString applicationVersion;
+
+#ifndef QT_NO_LIBRARY
+ QStringList *app_libpaths;
+#endif
+
+};
+
+Q_GLOBAL_STATIC(QCoreApplicationData, coreappdata)
+
+QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint flags)
+ : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0),
+ in_exec(false), aboutToQuitEmitted(false)
+{
+ app_compile_version = flags & 0xffffff;
+#if defined(QT3_SUPPORT)
+ useQt3Support = !(flags & 0x01000000);
+#endif
+ static const char *const empty = "";
+ if (argc == 0 || argv == 0) {
+ argc = 0;
+ argv = (char **)&empty; // ouch! careful with QCoreApplication::argv()!
+ }
+ QCoreApplicationPrivate::is_app_closing = false;
+
+#ifdef Q_OS_SYMBIAN
+ qt_init_symbian_apa_arguments(argc, argv);
+#endif
+
+#ifdef Q_OS_UNIX
+ qt_application_thread_id = QThread::currentThreadId();
+#endif
+
+ // note: this call to QThread::currentThread() may end up setting theMainThread!
+ if (QThread::currentThread() != theMainThread)
+ qWarning("WARNING: QApplication was not created in the main() thread.");
+}
+
+QCoreApplicationPrivate::~QCoreApplicationPrivate()
+{
+ if (threadData) {
+#ifndef QT_NO_THREAD
+ void *data = &threadData->tls;
+ QThreadStorageData::finish((void **)data);
+#endif
+
+ // need to clear the state of the mainData, just in case a new QCoreApplication comes along.
+ QMutexLocker locker(&threadData->postEventList.mutex);
+ for (int i = 0; i < threadData->postEventList.size(); ++i) {
+ const QPostEvent &pe = threadData->postEventList.at(i);
+ if (pe.event) {
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ }
+ }
+ threadData->postEventList.clear();
+ threadData->postEventList.recursion = 0;
+ threadData->quitNow = false;
+ }
+}
+
+void QCoreApplicationPrivate::createEventDispatcher()
+{
+ Q_Q(QCoreApplication);
+#if defined(Q_OS_SYMBIAN)
+ eventDispatcher = new QEventDispatcherSymbian(q);
+#elif defined(Q_OS_UNIX)
+# if !defined(QT_NO_GLIB)
+ if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported())
+ eventDispatcher = new QEventDispatcherGlib(q);
+ else
+# endif
+ eventDispatcher = new QEventDispatcherUNIX(q);
+#elif defined(Q_OS_WIN)
+ eventDispatcher = new QEventDispatcherWin32(q);
+#else
+# error "QEventDispatcher not yet ported to this platform"
+#endif
+}
+
+QThread *QCoreApplicationPrivate::theMainThread = 0;
+QThread *QCoreApplicationPrivate::mainThread()
+{
+ Q_ASSERT(theMainThread != 0);
+ return theMainThread;
+}
+
+#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD)
+void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
+{
+ QThread *currentThread = QThread::currentThread();
+ QThread *thr = receiver->thread();
+ Q_ASSERT_X(currentThread == thr || !thr,
+ "QCoreApplication::sendEvent",
+ QString::fromLatin1("Cannot send events to objects owned by a different thread. "
+ "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4")
+ .arg(QString::number((quintptr) currentThread, 16))
+ .arg(receiver->objectName())
+ .arg(QLatin1String(receiver->metaObject()->className()))
+ .arg(QString::number((quintptr) thr, 16))
+ .toLocal8Bit().data());
+ Q_UNUSED(currentThread);
+ Q_UNUSED(thr);
+}
+#elif defined(Q_OS_SYMBIAN) && defined (QT_NO_DEBUG)
+// no implementation in release builds, but keep the symbol present
+void QCoreApplicationPrivate::checkReceiverThread(QObject * /* receiver */)
+{
+}
+#endif
+
+void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
+{
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ QStringList *app_libpaths = coreappdata()->app_libpaths;
+ Q_ASSERT(app_libpaths);
+# if defined(Q_OS_SYMBIAN)
+ QString app_location( QCoreApplication::applicationDirPath() );
+ // File existence check for application's private dir requires additional '\' or
+ // platform security will not allow it.
+ if (app_location != QLibraryInfo::location(QLibraryInfo::PluginsPath) && QFile::exists(app_location + QLatin1Char('\\')) && !app_libpaths->contains(app_location))
+# else
+ QString app_location( QCoreApplication::applicationFilePath() );
+ app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
+ app_location = QDir(app_location).canonicalPath();
+ if (QFile::exists(app_location) && !app_libpaths->contains(app_location))
+# endif
+ app_libpaths->append(app_location);
+#endif
+}
+
+QString qAppName()
+{
+ if (!QCoreApplicationPrivate::checkInstance("qAppName"))
+ return QString();
+ return QCoreApplication::instance()->d_func()->appName();
+}
+
+/*!
+ \class QCoreApplication
+ \brief The QCoreApplication class provides an event loop for console Qt
+ applications.
+
+ This class is used by non-GUI applications to provide their event
+ loop. For non-GUI application that uses Qt, there should be exactly
+ one QCoreApplication object. For GUI applications, see
+ QApplication.
+
+ QCoreApplication contains the main event loop, where all events
+ from the operating system (e.g., timer and network events) and
+ other sources are processed and dispatched. It also handles the
+ application's initialization and finalization, as well as
+ system-wide and application-wide settings.
+
+ \section1 The Event Loop and Event Handling
+
+ The event loop is started with a call to exec(). Long running
+ operations can call processEvents() to keep the application
+ responsive.
+
+ In general, we recommend that you create a QCoreApplication or a
+ QApplication object in your \c main() function as early as
+ possible. exec() will not return until the event loop exits; e.g.,
+ when quit() is called.
+
+ Several static convenience functions are also provided. The
+ QCoreApplication object is available from instance(). Events can
+ be sent or posted using sendEvent(), postEvent(), and
+ sendPostedEvents(). Pending events can be removed with
+ removePostedEvents() or flushed with flush().
+
+ The class provides a quit() slot and an aboutToQuit() signal.
+
+ \section1 Application and Library Paths
+
+ An application has an applicationDirPath() and an
+ applicationFilePath(). Library paths (see QLibrary) can be retrieved
+ with libraryPaths() and manipulated by setLibraryPaths(), addLibraryPath(),
+ and removeLibraryPath().
+
+ \section1 Internationalization and Translations
+
+ Translation files can be added or removed
+ using installTranslator() and removeTranslator(). Application
+ strings can be translated using translate(). The QObject::tr()
+ and QObject::trUtf8() functions are implemented in terms of
+ translate().
+
+ \section1 Accessing Command Line Arguments
+
+ The command line arguments which are passed to QCoreApplication's
+ constructor should be accessed using the arguments() function.
+ Note that some arguments supplied by the user may have been
+ processed and removed by QCoreApplication.
+
+ In cases where command line arguments need to be obtained using the
+ argv() function, you must convert them from the local string encoding
+ using QString::fromLocal8Bit().
+
+ \section1 Locale Settings
+
+ On Unix/Linux Qt is configured to use the system locale settings by
+ default. This can cause a conflict when using POSIX functions, for
+ instance, when converting between data types such as floats and
+ strings, since the notation may differ between locales. To get
+ around this problem, call the POSIX function \c{setlocale(LC_NUMERIC,"C")}
+ right after initializing QApplication or QCoreApplication to reset
+ the locale that is used for number formatting to "C"-locale.
+
+ \sa QApplication, QAbstractEventDispatcher, QEventLoop,
+ {Semaphores Example}, {Wait Conditions Example}
+*/
+
+/*!
+ \fn static QCoreApplication *QCoreApplication::instance()
+
+ Returns a pointer to the application's QCoreApplication (or
+ QApplication) instance.
+
+ If no instance has been allocated, \c null is returned.
+*/
+
+/*!\internal
+ */
+QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
+ : QObject(p, 0)
+{
+ init();
+ // note: it is the subclasses' job to call
+ // QCoreApplicationPrivate::eventDispatcher->startingUp();
+}
+
+/*!
+ Flushes the platform specific event queues.
+
+ If you are doing graphical changes inside a loop that does not
+ return to the event loop on asynchronous window systems like X11
+ or double buffered window systems like Mac OS X, and you want to
+ visualize these changes immediately (e.g. Splash Screens), call
+ this function.
+
+ \sa sendPostedEvents()
+*/
+void QCoreApplication::flush()
+{
+ if (self && self->d_func()->eventDispatcher)
+ self->d_func()->eventDispatcher->flush();
+}
+
+/*!
+ Constructs a Qt kernel application. Kernel applications are
+ applications without a graphical user interface. These type of
+ applications are used at the console or as server processes.
+
+ The \a argc and \a argv arguments are processed by the application,
+ and made available in a more convenient form by the arguments()
+ function.
+
+ \warning The data referred to by \a argc and \a argv must stay valid
+ for the entire lifetime of the QCoreApplication object. In addition,
+ \a argc must be greater than zero and \a argv must contain at least
+ one valid character string.
+*/
+QCoreApplication::QCoreApplication(int &argc, char **argv)
+ : QObject(*new QCoreApplicationPrivate(argc, argv, 0x040000))
+{
+ init();
+ QCoreApplicationPrivate::eventDispatcher->startingUp();
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_LIBRARY)
+ // Refresh factoryloader, as text codecs are requested during lib path
+ // resolving process and won't be therefore properly loaded.
+ // Unknown if this is symbian specific issue.
+ QFactoryLoader::refreshAll();
+#endif
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
+ d_func()->symbianInit();
+#endif
+}
+
+QCoreApplication::QCoreApplication(int &argc, char **argv, int _internal)
+: QObject(*new QCoreApplicationPrivate(argc, argv, _internal))
+{
+ init();
+ QCoreApplicationPrivate::eventDispatcher->startingUp();
+#if defined(Q_OS_SYMBIAN)
+#ifndef QT_NO_LIBRARY
+ // Refresh factoryloader, as text codecs are requested during lib path
+ // resolving process and won't be therefore properly loaded.
+ // Unknown if this is symbian specific issue.
+ QFactoryLoader::refreshAll();
+#endif
+#ifndef QT_NO_SYSTEMLOCALE
+ d_func()->symbianInit();
+#endif
+#endif //Q_OS_SYMBIAN
+}
+
+
+// ### move to QCoreApplicationPrivate constructor?
+void QCoreApplication::init()
+{
+ Q_D(QCoreApplication);
+
+#ifdef Q_OS_UNIX
+ setlocale(LC_ALL, ""); // use correct char set mapping
+ qt_locale_initialized = true;
+#endif
+
+ Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
+ QCoreApplication::self = this;
+
+#ifdef Q_OS_SYMBIAN
+ //ensure temp and working directories exist
+ QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::tempPath()), true);
+ QFileSystemEngine::createDirectory(QFileSystemEntry(QFileSystemEngine::currentPath()), true);
+#endif
+
+#ifndef QT_NO_THREAD
+ QThread::initialize();
+#endif
+
+ // use the event dispatcher created by the app programmer (if any)
+ if (!QCoreApplicationPrivate::eventDispatcher)
+ QCoreApplicationPrivate::eventDispatcher = d->threadData->eventDispatcher;
+ // otherwise we create one
+ if (!QCoreApplicationPrivate::eventDispatcher)
+ d->createEventDispatcher();
+ Q_ASSERT(QCoreApplicationPrivate::eventDispatcher != 0);
+
+ if (!QCoreApplicationPrivate::eventDispatcher->parent())
+ QCoreApplicationPrivate::eventDispatcher->moveToThread(d->threadData->thread);
+
+ d->threadData->eventDispatcher = QCoreApplicationPrivate::eventDispatcher;
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ if (!coreappdata()->app_libpaths) {
+ // make sure that library paths is initialized
+ libraryPaths();
+ } else {
+ d->appendApplicationPathToLibraryPaths();
+ }
+#endif
+
+#if defined(Q_OS_UNIX) && !(defined(QT_NO_PROCESS))
+ // Make sure the process manager thread object is created in the main
+ // thread.
+ QProcessPrivate::initializeProcessManager();
+#endif
+
+#ifdef QT_EVAL
+ extern void qt_core_eval_init(uint);
+ qt_core_eval_init(d->application_type);
+#endif
+
+#if defined(Q_OS_SYMBIAN) \
+ && defined(Q_CC_NOKIAX86) \
+ && defined(QT_DEBUG)
+ /**
+ * Prevent the executable from being locked in the Symbian emulator. The
+ * code dramatically simplifies debugging on Symbian, but beyond that has
+ * no impact.
+ *
+ * Force the ZLazyUnloadTimer to fire and therefore unload code segments
+ * immediately. The code affects Symbian's file server and on the other
+ * hand needs only to be run once in each emulator run.
+ */
+ {
+ RLoader loader;
+ CleanupClosePushL(loader);
+ User::LeaveIfError(loader.Connect());
+ User::LeaveIfError(loader.CancelLazyDllUnload());
+ CleanupStack::PopAndDestroy(&loader);
+ }
+#endif
+
+ qt_startup_hook();
+}
+
+#if defined(Q_OS_SYMBIAN) && !defined(QT_NO_SYSTEMLOCALE)
+void QCoreApplicationPrivate::symbianInit()
+{
+ if (!environmentChangeNotifier)
+ environmentChangeNotifier.reset(new QEnvironmentChangeNotifier);
+}
+#endif
+
+
+/*!
+ Destroys the QCoreApplication object.
+*/
+QCoreApplication::~QCoreApplication()
+{
+ qt_call_post_routines();
+
+ self = 0;
+ QCoreApplicationPrivate::is_app_closing = true;
+ QCoreApplicationPrivate::is_app_running = false;
+
+#if !defined(QT_NO_THREAD)
+#if !defined(QT_NO_CONCURRENT)
+ // Synchronize and stop the global thread pool threads.
+ QThreadPool *globalThreadPool = 0;
+ QT_TRY {
+ globalThreadPool = QThreadPool::globalInstance();
+ } QT_CATCH (...) {
+ // swallow the exception, since destructors shouldn't throw
+ }
+ if (globalThreadPool)
+ globalThreadPool->waitForDone();
+#endif
+ QThread::cleanup();
+#endif
+
+ d_func()->threadData->eventDispatcher = 0;
+ if (QCoreApplicationPrivate::eventDispatcher)
+ QCoreApplicationPrivate::eventDispatcher->closingDown();
+ QCoreApplicationPrivate::eventDispatcher = 0;
+
+#ifndef QT_NO_LIBRARY
+ delete coreappdata()->app_libpaths;
+ coreappdata()->app_libpaths = 0;
+#endif
+}
+
+
+/*!
+ Sets the attribute \a attribute if \a on is true;
+ otherwise clears the attribute.
+
+ One of the attributes that can be set with this method is
+ Qt::AA_ImmediateWidgetCreation. It tells Qt to create toplevel
+ windows immediately. Normally, resources for widgets are allocated
+ on demand to improve efficiency and minimize resource usage.
+ Therefore, if it is important to minimize resource consumption, do
+ not set this attribute.
+
+ \sa testAttribute()
+*/
+void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
+{
+ if (on)
+ QCoreApplicationPrivate::attribs |= 1 << attribute;
+ else
+ QCoreApplicationPrivate::attribs &= ~(1 << attribute);
+#ifdef Q_OS_MAC
+ // Turn on the no native menubar here, since we used to
+ // do this implicitly. We DO NOT flip it off if someone sets
+ // it to false.
+ // Ideally, we'd have magic that would be something along the lines of
+ // "follow MacPluginApplication" unless explicitly set.
+ // Considering this attribute isn't only at the beginning
+ // it's unlikely it will ever be a problem, but I want
+ // to have the behavior documented here.
+ if (attribute == Qt::AA_MacPluginApplication && on
+ && !testAttribute(Qt::AA_DontUseNativeMenuBar)) {
+ setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+ }
+#endif
+}
+
+/*!
+ Returns true if attribute \a attribute is set;
+ otherwise returns false.
+
+ \sa setAttribute()
+ */
+bool QCoreApplication::testAttribute(Qt::ApplicationAttribute attribute)
+{
+ return QCoreApplicationPrivate::testAttribute(attribute);
+}
+
+
+/*!
+ \internal
+
+ This function is here to make it possible for Qt extensions to
+ hook into event notification without subclassing QApplication
+*/
+bool QCoreApplication::notifyInternal(QObject *receiver, QEvent *event)
+{
+ // Make it possible for Qt Jambi and QSA to hook into events even
+ // though QApplication is subclassed...
+ bool result = false;
+ void *cbdata[] = { receiver, event, &result };
+ if (QInternal::activateCallbacks(QInternal::EventNotifyCallback, cbdata)) {
+ return result;
+ }
+
+ // Qt enforces the rule that events can only be sent to objects in
+ // the current thread, so receiver->d_func()->threadData is
+ // equivalent to QThreadData::current(), just without the function
+ // call overhead.
+ QObjectPrivate *d = receiver->d_func();
+ QThreadData *threadData = d->threadData;
+ ++threadData->loopLevel;
+
+#ifdef QT_JAMBI_BUILD
+ int deleteWatch = 0;
+ int *oldDeleteWatch = QObjectPrivate::setDeleteWatch(d, &deleteWatch);
+
+ bool inEvent = d->inEventHandler;
+ d->inEventHandler = true;
+#endif
+
+ bool returnValue;
+ QT_TRY {
+ returnValue = notify(receiver, event);
+ } QT_CATCH (...) {
+ --threadData->loopLevel;
+ QT_RETHROW;
+ }
+
+#ifdef QT_JAMBI_BUILD
+ // Restore the previous state if the object was not deleted..
+ if (!deleteWatch) {
+ d->inEventHandler = inEvent;
+ }
+ QObjectPrivate::resetDeleteWatch(d, oldDeleteWatch, deleteWatch);
+#endif
+ --threadData->loopLevel;
+ return returnValue;
+}
+
+
+/*!
+ Sends \a event to \a receiver: \a {receiver}->event(\a event).
+ Returns the value that is returned from the receiver's event
+ handler. Note that this function is called for all events sent to
+ any object in any thread.
+
+ For certain types of events (e.g. mouse and key events),
+ the event will be propagated to the receiver's parent and so on up to
+ the top-level object if the receiver is not interested in the event
+ (i.e., it returns false).
+
+ There are five different ways that events can be processed;
+ reimplementing this virtual function is just one of them. All five
+ approaches are listed below:
+ \list 1
+ \i Reimplementing paintEvent(), mousePressEvent() and so
+ on. This is the commonest, easiest and least powerful way.
+
+ \i Reimplementing this function. This is very powerful, providing
+ complete control; but only one subclass can be active at a time.
+
+ \i Installing an event filter on QCoreApplication::instance(). Such
+ an event filter is able to process all events for all widgets, so
+ it's just as powerful as reimplementing notify(); furthermore, it's
+ possible to have more than one application-global event filter.
+ Global event filters even see mouse events for
+ \l{QWidget::isEnabled()}{disabled widgets}. Note that application
+ event filters are only called for objects that live in the main
+ thread.
+
+ \i Reimplementing QObject::event() (as QWidget does). If you do
+ this you get Tab key presses, and you get to see the events before
+ any widget-specific event filters.
+
+ \i Installing an event filter on the object. Such an event filter gets all
+ the events, including Tab and Shift+Tab key press events, as long as they
+ do not change the focus widget.
+ \endlist
+
+ \sa QObject::event(), installEventFilter()
+*/
+
+bool QCoreApplication::notify(QObject *receiver, QEvent *event)
+{
+ Q_D(QCoreApplication);
+ // no events are delivered after ~QCoreApplication() has started
+ if (QCoreApplicationPrivate::is_app_closing)
+ return true;
+
+ if (receiver == 0) { // serious error
+ qWarning("QCoreApplication::notify: Unexpected null receiver");
+ return true;
+ }
+
+#ifndef QT_NO_DEBUG
+ d->checkReceiverThread(receiver);
+#endif
+
+ return receiver->isWidgetType() ? false : d->notify_helper(receiver, event);
+}
+
+bool QCoreApplicationPrivate::sendThroughApplicationEventFilters(QObject *receiver, QEvent *event)
+{
+ if (receiver->d_func()->threadData == this->threadData) {
+ // application event filters are only called for objects in the GUI thread
+ for (int i = 0; i < eventFilters.size(); ++i) {
+ register QObject *obj = eventFilters.at(i);
+ if (!obj)
+ continue;
+ if (obj->d_func()->threadData != threadData) {
+ qWarning("QCoreApplication: Application event filter cannot be in a different thread.");
+ continue;
+ }
+ if (obj->eventFilter(receiver, event))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject *receiver, QEvent *event)
+{
+ Q_Q(QCoreApplication);
+ if (receiver != q) {
+ for (int i = 0; i < receiver->d_func()->eventFilters.size(); ++i) {
+ register QObject *obj = receiver->d_func()->eventFilters.at(i);
+ if (!obj)
+ continue;
+ if (obj->d_func()->threadData != receiver->d_func()->threadData) {
+ qWarning("QCoreApplication: Object event filter cannot be in a different thread.");
+ continue;
+ }
+ if (obj->eventFilter(receiver, event))
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!\internal
+
+ Helper function called by notify()
+ */
+bool QCoreApplicationPrivate::notify_helper(QObject *receiver, QEvent * event)
+{
+ // send to all application event filters
+ if (sendThroughApplicationEventFilters(receiver, event))
+ return true;
+ // send to all receiver event filters
+ if (sendThroughObjectEventFilters(receiver, event))
+ return true;
+ // deliver the event
+ return receiver->event(event);
+}
+
+/*!
+ Returns true if an application object has not been created yet;
+ otherwise returns false.
+
+ \sa closingDown()
+*/
+
+bool QCoreApplication::startingUp()
+{
+ return !QCoreApplicationPrivate::is_app_running;
+}
+
+/*!
+ Returns true if the application objects are being destroyed;
+ otherwise returns false.
+
+ \sa startingUp()
+*/
+
+bool QCoreApplication::closingDown()
+{
+ return QCoreApplicationPrivate::is_app_closing;
+}
+
+
+/*!
+ Processes all pending events for the calling thread according to
+ the specified \a flags until there are no more events to process.
+
+ You can call this function occasionally when your program is busy
+ performing a long operation (e.g. copying a file).
+
+ In event you are running a local loop which calls this function
+ continuously, without an event loop, the
+ \l{QEvent::DeferredDelete}{DeferredDelete} events will
+ not be processed. This can affect the behaviour of widgets,
+ e.g. QToolTip, that rely on \l{QEvent::DeferredDelete}{DeferredDelete}
+ events to function properly. An alternative would be to call
+ \l{QCoreApplication::sendPostedEvents()}{sendPostedEvents()} from
+ within that local loop.
+
+ Calling this function processes events only for the calling thread.
+
+ \threadsafe
+
+ \sa exec(), QTimer, QEventLoop::processEvents(), flush(), sendPostedEvents()
+*/
+void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ QThreadData *data = QThreadData::current();
+ if (!data->eventDispatcher)
+ return;
+ if (flags & QEventLoop::DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ data->eventDispatcher->processEvents(flags);
+}
+
+/*!
+ \overload processEvents()
+
+ Processes pending events for the calling thread for \a maxtime
+ milliseconds or until there are no more events to process,
+ whichever is shorter.
+
+ You can call this function occasionally when you program is busy
+ doing a long operation (e.g. copying a file).
+
+ Calling this function processes events only for the calling thread.
+
+ \threadsafe
+
+ \sa exec(), QTimer, QEventLoop::processEvents()
+*/
+void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime)
+{
+ QThreadData *data = QThreadData::current();
+ if (!data->eventDispatcher)
+ return;
+ QElapsedTimer start;
+ start.start();
+ if (flags & QEventLoop::DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ while (data->eventDispatcher->processEvents(flags & ~QEventLoop::WaitForMoreEvents)) {
+ if (start.elapsed() > maxtime)
+ break;
+ if (flags & QEventLoop::DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+}
+
+/*****************************************************************************
+ Main event loop wrappers
+ *****************************************************************************/
+
+/*!
+ Enters the main event loop and waits until exit() is called.
+ Returns the value that was set to exit() (which is 0 if exit() is
+ called via quit()).
+
+ It is necessary to call this function to start event handling. The
+ main event loop receives events from the window system and
+ dispatches these to the application widgets.
+
+ To make your application perform idle processing (i.e. executing a
+ special function whenever there are no pending events), use a
+ QTimer with 0 timeout. More advanced idle processing schemes can
+ be achieved using processEvents().
+
+ We recommend that you connect clean-up code to the
+ \l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in
+ your application's \c{main()} function because on some platforms the
+ QCoreApplication::exec() call may not return. For example, on Windows
+ when the user logs off, the system terminates the process after Qt
+ closes all top-level windows. Hence, there is no guarantee that the
+ application will have time to exit its event loop and execute code at
+ the end of the \c{main()} function after the QCoreApplication::exec()
+ call.
+
+ \sa quit(), exit(), processEvents(), QApplication::exec()
+*/
+int QCoreApplication::exec()
+{
+ if (!QCoreApplicationPrivate::checkInstance("exec"))
+ return -1;
+
+ QThreadData *threadData = self->d_func()->threadData;
+ if (threadData != QThreadData::current()) {
+ qWarning("%s::exec: Must be called from the main thread", self->metaObject()->className());
+ return -1;
+ }
+ if (!threadData->eventLoops.isEmpty()) {
+ qWarning("QCoreApplication::exec: The event loop is already running");
+ return -1;
+ }
+
+ threadData->quitNow = false;
+ QEventLoop eventLoop;
+ self->d_func()->in_exec = true;
+ self->d_func()->aboutToQuitEmitted = false;
+ int returnCode = eventLoop.exec();
+ threadData->quitNow = false;
+ if (self) {
+ self->d_func()->in_exec = false;
+ if (!self->d_func()->aboutToQuitEmitted)
+ emit self->aboutToQuit();
+ self->d_func()->aboutToQuitEmitted = true;
+ sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+
+ return returnCode;
+}
+
+
+/*!
+ Tells the application to exit with a return code.
+
+ After this function has been called, the application leaves the
+ main event loop and returns from the call to exec(). The exec()
+ function returns \a returnCode. If the event loop is not running,
+ this function does nothing.
+
+ By convention, a \a returnCode of 0 means success, and any non-zero
+ value indicates an error.
+
+ Note that unlike the C library function of the same name, this
+ function \e does return to the caller -- it is event processing that
+ stops.
+
+ \sa quit(), exec()
+*/
+void QCoreApplication::exit(int returnCode)
+{
+ if (!self)
+ return;
+ QThreadData *data = self->d_func()->threadData;
+ data->quitNow = true;
+ for (int i = 0; i < data->eventLoops.size(); ++i) {
+ QEventLoop *eventLoop = data->eventLoops.at(i);
+ eventLoop->exit(returnCode);
+ }
+}
+
+/*****************************************************************************
+ QCoreApplication management of posted events
+ *****************************************************************************/
+
+/*!
+ \fn bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
+
+ Sends event \a event directly to receiver \a receiver, using the
+ notify() function. Returns the value that was returned from the
+ event handler.
+
+ The event is \e not deleted when the event has been sent. The normal
+ approach is to create the event on the stack, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 0
+
+ \sa postEvent(), notify()
+*/
+
+/*!
+ Adds the event \a event, with the object \a receiver as the
+ receiver of the event, to an event queue and returns immediately.
+
+ The event must be allocated on the heap since the post event queue
+ will take ownership of the event and delete it once it has been
+ posted. It is \e {not safe} to access the event after
+ it has been posted.
+
+ When control returns to the main event loop, all events that are
+ stored in the queue will be sent using the notify() function.
+
+ Events are processed in the order posted. For more control over
+ the processing order, use the postEvent() overload below, which
+ takes a priority argument. This function posts all event with a
+ Qt::NormalEventPriority.
+
+ \threadsafe
+
+ \sa sendEvent(), notify(), sendPostedEvents()
+*/
+
+void QCoreApplication::postEvent(QObject *receiver, QEvent *event)
+{
+ postEvent(receiver, event, Qt::NormalEventPriority);
+}
+
+
+/*!
+ \overload postEvent()
+ \since 4.3
+
+ Adds the event \a event, with the object \a receiver as the
+ receiver of the event, to an event queue and returns immediately.
+
+ The event must be allocated on the heap since the post event queue
+ will take ownership of the event and delete it once it has been
+ posted. It is \e {not safe} to access the event after
+ it has been posted.
+
+ When control returns to the main event loop, all events that are
+ stored in the queue will be sent using the notify() function.
+
+ Events are sorted in descending \a priority order, i.e. events
+ with a high \a priority are queued before events with a lower \a
+ priority. The \a priority can be any integer value, i.e. between
+ INT_MAX and INT_MIN, inclusive; see Qt::EventPriority for more
+ details. Events with equal \a priority will be processed in the
+ order posted.
+
+ \threadsafe
+
+ \sa sendEvent(), notify(), sendPostedEvents(), Qt::EventPriority
+*/
+void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)
+{
+ if (receiver == 0) {
+ qWarning("QCoreApplication::postEvent: Unexpected null receiver");
+ delete event;
+ return;
+ }
+
+ QThreadData * volatile * pdata = &receiver->d_func()->threadData;
+ QThreadData *data = *pdata;
+ if (!data) {
+ // posting during destruction? just delete the event to prevent a leak
+ delete event;
+ return;
+ }
+
+ // lock the post event mutex
+ data->postEventList.mutex.lock();
+
+ // if object has moved to another thread, follow it
+ while (data != *pdata) {
+ data->postEventList.mutex.unlock();
+
+ data = *pdata;
+ if (!data) {
+ // posting during destruction? just delete the event to prevent a leak
+ delete event;
+ return;
+ }
+
+ data->postEventList.mutex.lock();
+ }
+
+ QMutexUnlocker locker(&data->postEventList.mutex);
+
+ // if this is one of the compressible events, do compression
+ if (receiver->d_func()->postedEvents
+ && self && self->compressEvent(event, receiver, &data->postEventList)) {
+ return;
+ }
+
+ if (event->type() == QEvent::DeferredDelete && data == QThreadData::current()) {
+ // remember the current running eventloop for DeferredDelete
+ // events posted in the receiver's thread
+ event->d = reinterpret_cast<QEventPrivate *>(quintptr(data->loopLevel));
+ }
+
+ // delete the event on exceptions to protect against memory leaks till the event is
+ // properly owned in the postEventList
+ QScopedPointer<QEvent> eventDeleter(event);
+ if (data->postEventList.isEmpty() || data->postEventList.last().priority >= priority) {
+ // optimization: we can simply append if the last event in
+ // the queue has higher or equal priority
+ data->postEventList.append(QPostEvent(receiver, event, priority));
+ } else {
+ // insert event in descending priority order, using upper
+ // bound for a given priority (to ensure proper ordering
+ // of events with the same priority)
+ QPostEventList::iterator begin = data->postEventList.begin()
+ + data->postEventList.insertionOffset,
+ end = data->postEventList.end();
+ QPostEventList::iterator at = qUpperBound(begin, end, priority);
+ data->postEventList.insert(at, QPostEvent(receiver, event, priority));
+ }
+ eventDeleter.take();
+ event->posted = true;
+ ++receiver->d_func()->postedEvents;
+ data->canWait = false;
+ locker.unlock();
+
+ if (data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+}
+
+/*!
+ \internal
+ Returns true if \a event was compressed away (possibly deleted) and should not be added to the list.
+*/
+bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventList *postedEvents)
+{
+#ifdef Q_WS_WIN
+ Q_ASSERT(event);
+ Q_ASSERT(receiver);
+ Q_ASSERT(postedEvents);
+
+ // compress posted timers to this object.
+ if (event->type() == QEvent::Timer && receiver->d_func()->postedEvents > 0) {
+ int timerId = ((QTimerEvent *) event)->timerId();
+ for (int i=0; i<postedEvents->size(); ++i) {
+ const QPostEvent &e = postedEvents->at(i);
+ if (e.receiver == receiver && e.event && e.event->type() == QEvent::Timer
+ && ((QTimerEvent *) e.event)->timerId() == timerId) {
+ delete event;
+ return true;
+ }
+ }
+ } else
+#endif
+ if ((event->type() == QEvent::DeferredDelete
+ || event->type() == QEvent::Quit)
+ && receiver->d_func()->postedEvents > 0) {
+ for (int i = 0; i < postedEvents->size(); ++i) {
+ const QPostEvent &cur = postedEvents->at(i);
+ if (cur.receiver != receiver
+ || cur.event == 0
+ || cur.event->type() != event->type())
+ continue;
+ // found an event for this receiver
+ delete event;
+ return true;
+ }
+ }
+ return false;
+}
+
+/*!
+ \fn void QCoreApplication::sendPostedEvents()
+ \overload sendPostedEvents()
+
+ Dispatches all posted events, i.e. empties the event queue.
+*/
+
+/*!
+ Immediately dispatches all events which have been previously queued
+ with QCoreApplication::postEvent() and which are for the object \a receiver
+ and have the event type \a event_type.
+
+ Events from the window system are \e not dispatched by this
+ function, but by processEvents().
+
+ If \a receiver is null, the events of \a event_type are sent for all
+ objects. If \a event_type is 0, all the events are sent for \a receiver.
+
+ \note This method must be called from the same thread as its QObject parameter, \a receiver.
+
+ \sa flush(), postEvent()
+*/
+
+void QCoreApplication::sendPostedEvents(QObject *receiver, int event_type)
+{
+ QThreadData *data = QThreadData::current();
+
+ QCoreApplicationPrivate::sendPostedEvents(receiver, event_type, data);
+}
+
+void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type,
+ QThreadData *data)
+{
+ if (event_type == -1) {
+ // we were called by an obsolete event dispatcher.
+ event_type = 0;
+ }
+
+ if (receiver && receiver->d_func()->threadData != data) {
+ qWarning("QCoreApplication::sendPostedEvents: Cannot send "
+ "posted events for objects in another thread");
+ return;
+ }
+
+ ++data->postEventList.recursion;
+
+#ifdef QT3_SUPPORT
+ if (event_type == QEvent::ChildInserted) {
+ if (receiver) {
+ // optimize sendPostedEvents(w, QEvent::ChildInserted) calls away
+ receiver->d_func()->sendPendingChildInsertedEvents();
+ --data->postEventList.recursion;
+ return;
+ }
+
+ // ChildInserted events are sent in response to *Request
+ event_type = QEvent::ChildInsertedRequest;
+ }
+#endif
+
+ QMutexLocker locker(&data->postEventList.mutex);
+
+ // by default, we assume that the event dispatcher can go to sleep after
+ // processing all events. if any new events are posted while we send
+ // events, canWait will be set to false.
+ data->canWait = (data->postEventList.size() == 0);
+
+ if (data->postEventList.size() == 0 || (receiver && !receiver->d_func()->postedEvents)) {
+ --data->postEventList.recursion;
+ return;
+ }
+
+ data->canWait = true;
+
+ // okay. here is the tricky loop. be careful about optimizing
+ // this, it looks the way it does for good reasons.
+ int startOffset = data->postEventList.startOffset;
+ int &i = (!event_type && !receiver) ? data->postEventList.startOffset : startOffset;
+ data->postEventList.insertionOffset = data->postEventList.size();
+
+ while (i < data->postEventList.size()) {
+ // avoid live-lock
+ if (i >= data->postEventList.insertionOffset)
+ break;
+
+ const QPostEvent &pe = data->postEventList.at(i);
+ ++i;
+
+ if (!pe.event)
+ continue;
+ if ((receiver && receiver != pe.receiver) || (event_type && event_type != pe.event->type())) {
+ data->canWait = false;
+ continue;
+ }
+
+ if (pe.event->type() == QEvent::DeferredDelete) {
+ // DeferredDelete events are only sent when we are explicitly asked to
+ // (s.a. QEvent::DeferredDelete), and then only if the event loop that
+ // posted the event has returned.
+ const bool allowDeferredDelete =
+ (quintptr(pe.event->d) > unsigned(data->loopLevel)
+ || (!quintptr(pe.event->d) && data->loopLevel > 0)
+ || (event_type == QEvent::DeferredDelete
+ && quintptr(pe.event->d) == unsigned(data->loopLevel)));
+ if (!allowDeferredDelete) {
+ // cannot send deferred delete
+ if (!event_type && !receiver) {
+ // don't lose the event
+ data->postEventList.append(pe);
+ const_cast<QPostEvent &>(pe).event = 0;
+ }
+ continue;
+ }
+ }
+
+ // first, we diddle the event so that we can deliver
+ // it, and that no one will try to touch it later.
+ pe.event->posted = false;
+ QEvent * e = pe.event;
+ QObject * r = pe.receiver;
+
+ --r->d_func()->postedEvents;
+ Q_ASSERT(r->d_func()->postedEvents >= 0);
+
+ // next, update the data structure so that we're ready
+ // for the next event.
+ const_cast<QPostEvent &>(pe).event = 0;
+
+ locker.unlock();
+ // after all that work, it's time to deliver the event.
+#ifdef QT_NO_EXCEPTIONS
+ QCoreApplication::sendEvent(r, e);
+#else
+ try {
+ QCoreApplication::sendEvent(r, e);
+ } catch (...) {
+ delete e;
+ locker.relock();
+
+ // since we were interrupted, we need another pass to make sure we clean everything up
+ data->canWait = false;
+
+ // uglehack: copied from below
+ --data->postEventList.recursion;
+ if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+ throw; // rethrow
+ }
+#endif
+
+ delete e;
+ locker.relock();
+
+ // careful when adding anything below this point - the
+ // sendEvent() call might invalidate any invariants this
+ // function depends on.
+ }
+
+ --data->postEventList.recursion;
+ if (!data->postEventList.recursion && !data->canWait && data->eventDispatcher)
+ data->eventDispatcher->wakeUp();
+
+ // clear the global list, i.e. remove everything that was
+ // delivered.
+ if (!event_type && !receiver && data->postEventList.startOffset >= 0) {
+ const QPostEventList::iterator it = data->postEventList.begin();
+ data->postEventList.erase(it, it + data->postEventList.startOffset);
+ data->postEventList.insertionOffset -= data->postEventList.startOffset;
+ Q_ASSERT(data->postEventList.insertionOffset >= 0);
+ data->postEventList.startOffset = 0;
+ }
+}
+
+/*!
+ Removes all events posted using postEvent() for \a receiver.
+
+ The events are \e not dispatched, instead they are removed from the
+ queue. You should never need to call this function. If you do call it,
+ be aware that killing events may cause \a receiver to break one or
+ more invariants.
+
+ \threadsafe
+*/
+
+void QCoreApplication::removePostedEvents(QObject *receiver)
+{
+ removePostedEvents(receiver, 0);
+}
+
+/*!
+ \overload removePostedEvents()
+ \since 4.3
+
+ Removes all events of the given \a eventType that were posted
+ using postEvent() for \a receiver.
+
+ The events are \e not dispatched, instead they are removed from
+ the queue. You should never need to call this function. If you do
+ call it, be aware that killing events may cause \a receiver to
+ break one or more invariants.
+
+ If \a receiver is null, the events of \a eventType are removed for
+ all objects. If \a eventType is 0, all the events are removed for
+ \a receiver.
+
+ \threadsafe
+*/
+
+void QCoreApplication::removePostedEvents(QObject *receiver, int eventType)
+{
+#ifdef QT3_SUPPORT
+ if (eventType == QEvent::ChildInserted)
+ eventType = QEvent::ChildInsertedRequest;
+#endif
+
+ QThreadData *data = receiver ? receiver->d_func()->threadData : QThreadData::current();
+ QMutexLocker locker(&data->postEventList.mutex);
+
+ // the QObject destructor calls this function directly. this can
+ // happen while the event loop is in the middle of posting events,
+ // and when we get here, we may not have any more posted events
+ // for this object.
+ if (receiver && !receiver->d_func()->postedEvents)
+ return;
+
+ //we will collect all the posted events for the QObject
+ //and we'll delete after the mutex was unlocked
+ QVarLengthArray<QEvent*> events;
+ int n = data->postEventList.size();
+ int j = 0;
+
+ for (int i = 0; i < n; ++i) {
+ const QPostEvent &pe = data->postEventList.at(i);
+
+ if ((!receiver || pe.receiver == receiver)
+ && (pe.event && (eventType == 0 || pe.event->type() == eventType))) {
+ --pe.receiver->d_func()->postedEvents;
+#ifdef QT3_SUPPORT
+ if (pe.event->type() == QEvent::ChildInsertedRequest)
+ pe.receiver->d_func()->pendingChildInsertedEvents.clear();
+#endif
+ pe.event->posted = false;
+ events.append(pe.event);
+ const_cast<QPostEvent &>(pe).event = 0;
+ } else if (!data->postEventList.recursion) {
+ if (i != j)
+ data->postEventList.swap(i, j);
+ ++j;
+ }
+ }
+
+#ifdef QT_DEBUG
+ if (receiver && eventType == 0) {
+ Q_ASSERT(!receiver->d_func()->postedEvents);
+ }
+#endif
+
+ if (!data->postEventList.recursion) {
+ // truncate list
+ data->postEventList.erase(data->postEventList.begin() + j, data->postEventList.end());
+ }
+
+ locker.unlock();
+ for (int i = 0; i < events.count(); ++i) {
+ delete events[i];
+ }
+}
+
+/*!
+ Removes \a event from the queue of posted events, and emits a
+ warning message if appropriate.
+
+ \warning This function can be \e really slow. Avoid using it, if
+ possible.
+
+ \threadsafe
+*/
+
+void QCoreApplicationPrivate::removePostedEvent(QEvent * event)
+{
+ if (!event || !event->posted)
+ return;
+
+ QThreadData *data = QThreadData::current();
+
+ QMutexLocker locker(&data->postEventList.mutex);
+
+ if (data->postEventList.size() == 0) {
+#if defined(QT_DEBUG)
+ qDebug("QCoreApplication::removePostedEvent: Internal error: %p %d is posted",
+ (void*)event, event->type());
+ return;
+#endif
+ }
+
+ for (int i = 0; i < data->postEventList.size(); ++i) {
+ const QPostEvent & pe = data->postEventList.at(i);
+ if (pe.event == event) {
+#ifndef QT_NO_DEBUG
+ qWarning("QCoreApplication::removePostedEvent: Event of type %d deleted while posted to %s %s",
+ event->type(),
+ pe.receiver->metaObject()->className(),
+ pe.receiver->objectName().toLocal8Bit().data());
+#endif
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ const_cast<QPostEvent &>(pe).event = 0;
+ return;
+ }
+ }
+}
+
+/*!\reimp
+
+*/
+bool QCoreApplication::event(QEvent *e)
+{
+ if (e->type() == QEvent::Quit) {
+ quit();
+ return true;
+ }
+ return QObject::event(e);
+}
+
+/*! \enum QCoreApplication::Encoding
+
+ This enum type defines the 8-bit encoding of character string
+ arguments to translate():
+
+ \value CodecForTr The encoding specified by
+ QTextCodec::codecForTr() (Latin-1 if none has
+ been set).
+ \value UnicodeUTF8 UTF-8.
+ \value DefaultCodec (Obsolete) Use CodecForTr instead.
+
+ \sa QObject::tr(), QObject::trUtf8(), QString::fromUtf8()
+*/
+
+/*!
+ Tells the application to exit with return code 0 (success).
+ Equivalent to calling QCoreApplication::exit(0).
+
+ It's common to connect the QApplication::lastWindowClosed() signal
+ to quit(), and you also often connect e.g. QAbstractButton::clicked() or
+ signals in QAction, QMenu, or QMenuBar to it.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 1
+
+ \sa exit(), aboutToQuit(), QApplication::lastWindowClosed()
+*/
+
+void QCoreApplication::quit()
+{
+ exit(0);
+}
+
+/*!
+ \fn void QCoreApplication::aboutToQuit()
+
+ This signal is emitted when the application is about to quit the
+ main event loop, e.g. when the event loop level drops to zero.
+ This may happen either after a call to quit() from inside the
+ application or when the users shuts down the entire desktop session.
+
+ The signal is particularly useful if your application has to do some
+ last-second cleanup. Note that no user interaction is possible in
+ this state.
+
+ \sa quit()
+*/
+
+#ifndef QT_NO_TRANSLATION
+/*!
+ Adds the translation file \a translationFile to the list of
+ translation files to be used for translations.
+
+ Multiple translation files can be installed. Translations are
+ searched for in the reverse order in which they were installed,
+ so the most recently installed translation file is searched first
+ and the first translation file installed is searched last.
+ The search stops as soon as a translation containing a matching
+ string is found.
+
+ Installing or removing a QTranslator, or changing an installed QTranslator
+ generates a \l{QEvent::LanguageChange}{LanguageChange} event for the
+ QCoreApplication instance. A QApplication instance will propagate the event
+ to all toplevel windows, where a reimplementation of changeEvent can
+ re-translate the user interface by passing user-visible strings via the
+ tr() function to the respective property setters. User-interface classes
+ generated by \l{Qt Designer} provide a \c retranslateUi() function that can be
+ called.
+
+ \sa removeTranslator() translate() QTranslator::load() {Dynamic Translation}
+*/
+
+void QCoreApplication::installTranslator(QTranslator *translationFile)
+{
+ if (!translationFile)
+ return;
+
+ if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
+ return;
+ QCoreApplicationPrivate *d = self->d_func();
+ d->translators.prepend(translationFile);
+
+#ifndef QT_NO_TRANSLATION_BUILDER
+ if (translationFile->isEmpty())
+ return;
+#endif
+
+ QEvent ev(QEvent::LanguageChange);
+ QCoreApplication::sendEvent(self, &ev);
+}
+
+/*!
+ Removes the translation file \a translationFile from the list of
+ translation files used by this application. (It does not delete the
+ translation file from the file system.)
+
+ \sa installTranslator() translate(), QObject::tr()
+*/
+
+void QCoreApplication::removeTranslator(QTranslator *translationFile)
+{
+ if (!translationFile)
+ return;
+ if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
+ return;
+ QCoreApplicationPrivate *d = self->d_func();
+ if (d->translators.removeAll(translationFile) && !self->closingDown()) {
+ QEvent ev(QEvent::LanguageChange);
+ QCoreApplication::sendEvent(self, &ev);
+ }
+}
+
+/*!
+ \overload translate()
+*/
+QString QCoreApplication::translate(const char *context, const char *sourceText,
+ const char *disambiguation, Encoding encoding)
+{
+ return translate(context, sourceText, disambiguation, encoding, -1);
+}
+
+static void replacePercentN(QString *result, int n)
+{
+ if (n >= 0) {
+ int percentPos = 0;
+ int len = 0;
+ while ((percentPos = result->indexOf(QLatin1Char('%'), percentPos + len)) != -1) {
+ len = 1;
+ QString fmt;
+ if (result->at(percentPos + len) == QLatin1Char('L')) {
+ ++len;
+ fmt = QLatin1String("%L1");
+ } else {
+ fmt = QLatin1String("%1");
+ }
+ if (result->at(percentPos + len) == QLatin1Char('n')) {
+ fmt = fmt.arg(n);
+ ++len;
+ result->replace(percentPos, len, fmt);
+ len = fmt.length();
+ }
+ }
+ }
+}
+
+/*!
+ \reentrant
+ \since 4.5
+
+ Returns the translation text for \a sourceText, by querying the
+ installed translation files. The translation files are searched
+ from the most recently installed file back to the first
+ installed file.
+
+ QObject::tr() and QObject::trUtf8() provide this functionality
+ more conveniently.
+
+ \a context is typically a class name (e.g., "MyDialog") and \a
+ sourceText is either English text or a short identifying text.
+
+ \a disambiguation is an identifying string, for when the same \a
+ sourceText is used in different roles within the same context. By
+ default, it is null.
+
+ See the \l QTranslator and \l QObject::tr() documentation for
+ more information about contexts, disambiguations and comments.
+
+ \a encoding indicates the 8-bit encoding of character strings.
+
+ \a n is used in conjunction with \c %n to support plural forms.
+ See QObject::tr() for details.
+
+ If none of the translation files contain a translation for \a
+ sourceText in \a context, this function returns a QString
+ equivalent of \a sourceText. The encoding of \a sourceText is
+ specified by \e encoding; it defaults to CodecForTr.
+
+ This function is not virtual. You can use alternative translation
+ techniques by subclassing \l QTranslator.
+
+ \warning This method is reentrant only if all translators are
+ installed \e before calling this method. Installing or removing
+ translators while performing translations is not supported. Doing
+ so will most likely result in crashes or other undesirable
+ behavior.
+
+ \sa QObject::tr() installTranslator() QTextCodec::codecForTr()
+*/
+
+
+QString QCoreApplication::translate(const char *context, const char *sourceText,
+ const char *disambiguation, Encoding encoding, int n)
+{
+ QString result;
+
+ if (!sourceText)
+ return result;
+
+ if (self && !self->d_func()->translators.isEmpty()) {
+ QList<QTranslator*>::ConstIterator it;
+ QTranslator *translationFile;
+ for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {
+ translationFile = *it;
+ result = translationFile->translate(context, sourceText, disambiguation, n);
+ if (!result.isEmpty())
+ break;
+ }
+ }
+
+ if (result.isEmpty()) {
+#ifdef QT_NO_TEXTCODEC
+ Q_UNUSED(encoding)
+#else
+ if (encoding == UnicodeUTF8)
+ result = QString::fromUtf8(sourceText);
+ else if (QTextCodec::codecForTr() != 0)
+ result = QTextCodec::codecForTr()->toUnicode(sourceText);
+ else
+#endif
+ result = QString::fromLatin1(sourceText);
+ }
+
+ replacePercentN(&result, n);
+ return result;
+}
+
+// Declared in qglobal.h
+QString qtTrId(const char *id, int n)
+{
+ return QCoreApplication::translate(0, id, 0, QCoreApplication::UnicodeUTF8, n);
+}
+
+bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
+{
+ return QCoreApplication::self
+ && QCoreApplication::self->d_func()->translators.contains(translator);
+}
+
+#endif //QT_NO_TRANSLATE
+
+/*!
+ Returns the directory that contains the application executable.
+
+ For example, if you have installed Qt in the \c{C:\Trolltech\Qt}
+ directory, and you run the \c{regexp} example, this function will
+ return "C:/Trolltech/Qt/examples/tools/regexp".
+
+ On Mac OS X this will point to the directory actually containing the
+ executable, which may be inside of an application bundle (if the
+ application is bundled).
+
+ \warning On Linux, this function will try to get the path from the
+ \c {/proc} file system. If that fails, it assumes that \c
+ {argv[0]} contains the absolute file name of the executable. The
+ function also assumes that the current directory has not been
+ changed by the application.
+
+ In Symbian this function will return the application private directory,
+ not the path to executable itself, as those are always in \c {/sys/bin}.
+ If the application is in a read only drive, i.e. ROM, then the private path
+ on the system drive will be returned.
+
+ \sa applicationFilePath()
+*/
+QString QCoreApplication::applicationDirPath()
+{
+ if (!self) {
+ qWarning("QCoreApplication::applicationDirPath: Please instantiate the QApplication object first");
+ return QString();
+ }
+
+ QCoreApplicationPrivate *d = self->d_func();
+ if (d->cachedApplicationDirPath.isNull())
+#if defined(Q_OS_SYMBIAN)
+ {
+ QString appPath;
+ RFs& fs = qt_s60GetRFs();
+ TChar driveChar;
+ QChar qDriveChar;
+ driveChar = (RProcess().FileName())[0];
+
+ //Check if the process is installed in a read only drive (typically ROM),
+ //and use the system drive (typically C:) if so.
+ TInt drive;
+ TDriveInfo driveInfo;
+ TInt err = fs.CharToDrive(driveChar, drive);
+ if (err == KErrNone) {
+ err = fs.Drive(driveInfo, drive);
+ }
+ if (err != KErrNone || (driveInfo.iDriveAtt & KDriveAttRom) || (driveInfo.iMediaAtt
+ & KMediaAttWriteProtected)) {
+ if(!PtrGetSystemDrive)
+ PtrGetSystemDrive = reinterpret_cast<SystemDriveFunc>(qt_resolveS60PluginFunc(S60Plugin_GetSystemDrive));
+ Q_ASSERT(PtrGetSystemDrive);
+ drive = PtrGetSystemDrive(fs);
+ fs.DriveToChar(drive, driveChar);
+ }
+
+ qDriveChar = QChar(QLatin1Char(driveChar)).toUpper();
+
+ TFileName privatePath;
+ fs.PrivatePath(privatePath);
+ appPath = qt_TDesC2QString(privatePath);
+ appPath.prepend(QLatin1Char(':')).prepend(qDriveChar);
+
+ // Create the appPath if it doesn't exist. Non-existing appPath will cause
+ // Platform Security violations later on if the app doesn't have AllFiles capability.
+ err = fs.CreatePrivatePath(drive);
+ if (err != KErrNone)
+ qWarning("QCoreApplication::applicationDirPath: Failed to create private path.");
+
+ d->cachedApplicationDirPath = QFileInfo(appPath).path();
+ }
+#else
+ d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
+#endif
+ return d->cachedApplicationDirPath;
+}
+
+/*!
+ Returns the file path of the application executable.
+
+ For example, if you have installed Qt in the \c{/usr/local/qt}
+ directory, and you run the \c{regexp} example, this function will
+ return "/usr/local/qt/examples/tools/regexp/regexp".
+
+ \warning On Linux, this function will try to get the path from the
+ \c {/proc} file system. If that fails, it assumes that \c
+ {argv[0]} contains the absolute file name of the executable. The
+ function also assumes that the current directory has not been
+ changed by the application.
+
+ \sa applicationDirPath()
+*/
+QString QCoreApplication::applicationFilePath()
+{
+ if (!self) {
+ qWarning("QCoreApplication::applicationFilePath: Please instantiate the QApplication object first");
+ return QString();
+ }
+
+ QCoreApplicationPrivate *d = self->d_func();
+ if (!d->cachedApplicationFilePath.isNull())
+ return d->cachedApplicationFilePath;
+
+#if defined(Q_WS_WIN)
+ d->cachedApplicationFilePath = QFileInfo(qAppFileName()).filePath();
+ return d->cachedApplicationFilePath;
+#elif defined(Q_WS_MAC)
+ QString qAppFileName_str = qAppFileName();
+ if(!qAppFileName_str.isEmpty()) {
+ QFileInfo fi(qAppFileName_str);
+ d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
+ return d->cachedApplicationFilePath;
+ }
+#endif
+#if defined(Q_OS_SYMBIAN)
+ QString appPath;
+ RProcess proc;
+ TInt err = proc.Open(proc.Id());
+ if (err == KErrNone) {
+ TFileName procName = proc.FileName();
+ appPath.append(QString(reinterpret_cast<const QChar*>(procName.Ptr()), procName.Length()));
+ proc.Close();
+ }
+
+ d->cachedApplicationFilePath = appPath;
+ return d->cachedApplicationFilePath;
+
+#elif defined( Q_OS_UNIX )
+# ifdef Q_OS_LINUX
+ // Try looking for a /proc/<pid>/exe symlink first which points to
+ // the absolute path of the executable
+ QFileInfo pfi(QString::fromLatin1("/proc/%1/exe").arg(getpid()));
+ if (pfi.exists() && pfi.isSymLink()) {
+ d->cachedApplicationFilePath = pfi.canonicalFilePath();
+ return d->cachedApplicationFilePath;
+ }
+# endif
+
+ QString argv0 = QFile::decodeName(QByteArray(argv()[0]));
+ QString absPath;
+
+ if (!argv0.isEmpty() && argv0.at(0) == QLatin1Char('/')) {
+ /*
+ If argv0 starts with a slash, it is already an absolute
+ file path.
+ */
+ absPath = argv0;
+ } else if (argv0.contains(QLatin1Char('/'))) {
+ /*
+ If argv0 contains one or more slashes, it is a file path
+ relative to the current directory.
+ */
+ absPath = QDir::current().absoluteFilePath(argv0);
+ } else {
+ /*
+ Otherwise, the file path has to be determined using the
+ PATH environment variable.
+ */
+ QByteArray pEnv = qgetenv("PATH");
+ QDir currentDir = QDir::current();
+ QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1Char(':'));
+ for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
+ if ((*p).isEmpty())
+ continue;
+ QString candidate = currentDir.absoluteFilePath(*p + QLatin1Char('/') + argv0);
+ QFileInfo candidate_fi(candidate);
+ if (candidate_fi.exists() && !candidate_fi.isDir()) {
+ absPath = candidate;
+ break;
+ }
+ }
+ }
+
+ absPath = QDir::cleanPath(absPath);
+
+ QFileInfo fi(absPath);
+ d->cachedApplicationFilePath = fi.exists() ? fi.canonicalFilePath() : QString();
+ return d->cachedApplicationFilePath;
+#endif
+}
+
+/*!
+ \since 4.4
+
+ Returns the current process ID for the application.
+*/
+qint64 QCoreApplication::applicationPid()
+{
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+ return GetCurrentProcessId();
+#elif defined(Q_OS_VXWORKS)
+ return (pid_t) taskIdCurrent;
+#else
+ return getpid();
+#endif
+}
+
+/*!
+ \obsolete
+
+ Use arguments().size() instead.
+*/
+int QCoreApplication::argc()
+{
+ if (!self) {
+ qWarning("QCoreApplication::argc: Please instantiate the QApplication object first");
+ return 0;
+ }
+ return self->d_func()->argc;
+}
+
+
+/*!
+ \obsolete
+
+ Use arguments() instead.
+*/
+char **QCoreApplication::argv()
+{
+ if (!self) {
+ qWarning("QCoreApplication::argv: Please instantiate the QApplication object first");
+ return 0;
+ }
+ return self->d_func()->argv;
+}
+
+/*!
+ \since 4.1
+
+ Returns the list of command-line arguments.
+
+ Usually arguments().at(0) is the program name, arguments().at(1)
+ is the first argument, and arguments().last() is the last
+ argument. See the note below about Windows.
+
+ Calling this function is slow - you should store the result in a variable
+ when parsing the command line.
+
+ \warning On Unix, this list is built from the argc and argv parameters passed
+ to the constructor in the main() function. The string-data in argv is
+ interpreted using QString::fromLocal8Bit(); hence it is not possible to
+ pass, for example, Japanese command line arguments on a system that runs in a
+ Latin1 locale. Most modern Unix systems do not have this limitation, as they are
+ Unicode-based.
+
+ On NT-based Windows, this limitation does not apply either.
+ On Windows, the arguments() are not built from the contents of argv/argc, as
+ the content does not support Unicode. Instead, the arguments() are constructed
+ from the return value of
+ \l{http://msdn2.microsoft.com/en-us/library/ms683156(VS.85).aspx}{GetCommandLine()}.
+ As a result of this, the string given by arguments().at(0) might not be
+ the program name on Windows, depending on how the application was started.
+
+ For Symbian applications started with \c RApaLsSession::StartApp one can specify
+ arguments using \c CApaCommandLine::SetTailEndL function. Such arguments are only
+ available via this method; they will not be passed to \c main function. Also note
+ that only 8-bit string data set with \c CApaCommandLine::SetTailEndL is supported
+ by this function.
+
+ \sa applicationFilePath()
+*/
+
+QStringList QCoreApplication::arguments()
+{
+ QStringList list;
+
+ if (!self) {
+ qWarning("QCoreApplication::arguments: Please instantiate the QApplication object first");
+ return list;
+ }
+#ifdef Q_OS_WIN
+ QString cmdline = QString::fromWCharArray(GetCommandLine());
+
+#if defined(Q_OS_WINCE)
+ wchar_t tempFilename[MAX_PATH+1];
+ if (GetModuleFileName(0, tempFilename, MAX_PATH)) {
+ tempFilename[MAX_PATH] = 0;
+ cmdline.prepend(QLatin1Char('\"') + QString::fromWCharArray(tempFilename) + QLatin1String("\" "));
+ }
+#endif // Q_OS_WINCE
+
+ list = qWinCmdArgs(cmdline);
+ if (self->d_func()->application_type) { // GUI app? Skip known - see qapplication.cpp
+ QStringList stripped;
+ for (int a = 0; a < list.count(); ++a) {
+ QString arg = list.at(a);
+ QByteArray l1arg = arg.toLatin1();
+ if (l1arg == "-qdevel" ||
+ l1arg == "-qdebug" ||
+ l1arg == "-reverse" ||
+ l1arg == "-stylesheet" ||
+ l1arg == "-widgetcount")
+ ;
+ else if (l1arg.startsWith("-style=") ||
+ l1arg.startsWith("-qmljsdebugger="))
+ ;
+ else if (l1arg == "-style" ||
+ l1arg == "-session" ||
+ l1arg == "-graphicssystem" ||
+ l1arg == "-testability")
+ ++a;
+ else
+ stripped += arg;
+ }
+ list = stripped;
+ }
+#else
+ const int ac = self->d_func()->argc;
+ char ** const av = self->d_func()->argv;
+ for (int a = 0; a < ac; ++a) {
+ list << QString::fromLocal8Bit(av[a]);
+ }
+#endif
+
+ return list;
+}
+
+/*!
+ \property QCoreApplication::organizationName
+ \brief the name of the organization that wrote this application
+
+ The value is used by the QSettings class when it is constructed
+ using the empty constructor. This saves having to repeat this
+ information each time a QSettings object is created.
+
+ On Mac, QSettings uses organizationDomain() as the organization
+ if it's not an empty string; otherwise it uses
+ organizationName(). On all other platforms, QSettings uses
+ organizationName() as the organization.
+
+ \sa organizationDomain applicationName
+*/
+
+void QCoreApplication::setOrganizationName(const QString &orgName)
+{
+ coreappdata()->orgName = orgName;
+}
+
+QString QCoreApplication::organizationName()
+{
+ return coreappdata()->orgName;
+}
+
+/*!
+ \property QCoreApplication::organizationDomain
+ \brief the Internet domain of the organization that wrote this application
+
+ The value is used by the QSettings class when it is constructed
+ using the empty constructor. This saves having to repeat this
+ information each time a QSettings object is created.
+
+ On Mac, QSettings uses organizationDomain() as the organization
+ if it's not an empty string; otherwise it uses organizationName().
+ On all other platforms, QSettings uses organizationName() as the
+ organization.
+
+ \sa organizationName applicationName applicationVersion
+*/
+void QCoreApplication::setOrganizationDomain(const QString &orgDomain)
+{
+ coreappdata()->orgDomain = orgDomain;
+}
+
+QString QCoreApplication::organizationDomain()
+{
+ return coreappdata()->orgDomain;
+}
+
+/*!
+ \property QCoreApplication::applicationName
+ \brief the name of this application
+
+ The value is used by the QSettings class when it is constructed
+ using the empty constructor. This saves having to repeat this
+ information each time a QSettings object is created.
+
+ \sa organizationName organizationDomain applicationVersion
+*/
+void QCoreApplication::setApplicationName(const QString &application)
+{
+ coreappdata()->application = application;
+}
+
+QString QCoreApplication::applicationName()
+{
+ return coreappdata()->application;
+}
+
+/*!
+ \property QCoreApplication::applicationVersion
+ \since 4.4
+ \brief the version of this application
+
+ \sa applicationName organizationName organizationDomain
+*/
+void QCoreApplication::setApplicationVersion(const QString &version)
+{
+ coreappdata()->applicationVersion = version;
+}
+
+QString QCoreApplication::applicationVersion()
+{
+ return coreappdata()->applicationVersion;
+}
+
+#ifndef QT_NO_LIBRARY
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive))
+
+/*!
+ Returns a list of paths that the application will search when
+ dynamically loading libraries.
+
+ Qt provides default library paths, but they can also be set using
+ a \l{Using qt.conf}{qt.conf} file. Paths specified in this file
+ will override default values.
+
+ This list will include the installation directory for plugins if
+ it exists (the default installation directory for plugins is \c
+ INSTALL/plugins, where \c INSTALL is the directory where Qt was
+ installed). The directory of the application executable (NOT the
+ working directory) is always added, as well as the colon separated
+ entries of the QT_PLUGIN_PATH environment variable.
+
+ If you want to iterate over the list, you can use the \l foreach
+ pseudo-keyword:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 2
+
+ \sa setLibraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary,
+ {How to Create Qt Plugins}
+*/
+QStringList QCoreApplication::libraryPaths()
+{
+ QMutexLocker locker(libraryPathMutex());
+ if (!coreappdata()->app_libpaths) {
+ QStringList *app_libpaths = coreappdata()->app_libpaths = new QStringList;
+ QString installPathPlugins = QLibraryInfo::location(QLibraryInfo::PluginsPath);
+#if defined(Q_OS_SYMBIAN)
+ // Add existing path on all drives for relative PluginsPath in Symbian
+ if (installPathPlugins.at(1) != QChar(QLatin1Char(':'))) {
+ QString tempPath = installPathPlugins;
+ if (tempPath.at(tempPath.length() - 1) != QDir::separator()) {
+ tempPath += QDir::separator();
+ }
+ RFs& fs = qt_s60GetRFs();
+ TPtrC tempPathPtr(reinterpret_cast<const TText*> (tempPath.constData()));
+ TFindFile finder(fs);
+ TInt err = finder.FindByDir(tempPathPtr, tempPathPtr);
+ while (err == KErrNone) {
+ QString foundDir(reinterpret_cast<const QChar *>(finder.File().Ptr()),
+ finder.File().Length());
+ foundDir = QDir(foundDir).canonicalPath();
+ if (!app_libpaths->contains(foundDir))
+ app_libpaths->append(foundDir);
+ err = finder.Find();
+ }
+ }
+#else
+ if (QFile::exists(installPathPlugins)) {
+ // Make sure we convert from backslashes to slashes.
+ installPathPlugins = QDir(installPathPlugins).canonicalPath();
+ if (!app_libpaths->contains(installPathPlugins))
+ app_libpaths->append(installPathPlugins);
+ }
+#endif
+
+ // If QCoreApplication is not yet instantiated,
+ // make sure we add the application path when we construct the QCoreApplication
+ if (self) self->d_func()->appendApplicationPathToLibraryPaths();
+
+ const QByteArray libPathEnv = qgetenv("QT_PLUGIN_PATH");
+ if (!libPathEnv.isEmpty()) {
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+ QLatin1Char pathSep(';');
+#else
+ QLatin1Char pathSep(':');
+#endif
+ QStringList paths = QString::fromLatin1(libPathEnv).split(pathSep, QString::SkipEmptyParts);
+ for (QStringList::const_iterator it = paths.constBegin(); it != paths.constEnd(); ++it) {
+ QString canonicalPath = QDir(*it).canonicalPath();
+ if (!canonicalPath.isEmpty()
+ && !app_libpaths->contains(canonicalPath)) {
+ app_libpaths->append(canonicalPath);
+ }
+ }
+ }
+ }
+ return *(coreappdata()->app_libpaths);
+}
+
+
+
+/*!
+
+ Sets the list of directories to search when loading libraries to
+ \a paths. All existing paths will be deleted and the path list
+ will consist of the paths given in \a paths.
+
+ In Symbian this function is only useful for setting paths for
+ finding Qt extension plugin stubs, since the OS can only
+ load libraries from the \c{/sys/bin} directory.
+
+ \sa libraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary
+ */
+void QCoreApplication::setLibraryPaths(const QStringList &paths)
+{
+ QMutexLocker locker(libraryPathMutex());
+ if (!coreappdata()->app_libpaths)
+ coreappdata()->app_libpaths = new QStringList;
+ *(coreappdata()->app_libpaths) = paths;
+ locker.unlock();
+ QFactoryLoader::refreshAll();
+}
+
+/*!
+ Prepends \a path to the beginning of the library path list, ensuring that
+ it is searched for libraries first. If \a path is empty or already in the
+ path list, the path list is not changed.
+
+ The default path list consists of a single entry, the installation
+ directory for plugins. The default installation directory for plugins
+ is \c INSTALL/plugins, where \c INSTALL is the directory where Qt was
+ installed.
+
+ In Symbian this function is only useful for adding paths for
+ finding Qt extension plugin stubs, since the OS can only
+ load libraries from the \c{/sys/bin} directory.
+
+ \sa removeLibraryPath(), libraryPaths(), setLibraryPaths()
+ */
+void QCoreApplication::addLibraryPath(const QString &path)
+{
+ if (path.isEmpty())
+ return;
+
+ QMutexLocker locker(libraryPathMutex());
+
+ // make sure that library paths is initialized
+ libraryPaths();
+
+ QString canonicalPath = QDir(path).canonicalPath();
+ if (!canonicalPath.isEmpty()
+ && !coreappdata()->app_libpaths->contains(canonicalPath)) {
+ coreappdata()->app_libpaths->prepend(canonicalPath);
+ locker.unlock();
+ QFactoryLoader::refreshAll();
+ }
+}
+
+/*!
+ Removes \a path from the library path list. If \a path is empty or not
+ in the path list, the list is not changed.
+
+ \sa addLibraryPath(), libraryPaths(), setLibraryPaths()
+*/
+void QCoreApplication::removeLibraryPath(const QString &path)
+{
+ if (path.isEmpty())
+ return;
+
+ QMutexLocker locker(libraryPathMutex());
+
+ // make sure that library paths is initialized
+ libraryPaths();
+
+ QString canonicalPath = QDir(path).canonicalPath();
+ coreappdata()->app_libpaths->removeAll(canonicalPath);
+ QFactoryLoader::refreshAll();
+}
+
+#endif //QT_NO_LIBRARY
+
+/*!
+ \typedef QCoreApplication::EventFilter
+
+ A function with the following signature that can be used as an
+ event filter:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 3
+
+ \sa setEventFilter()
+*/
+
+/*!
+ \fn EventFilter QCoreApplication::setEventFilter(EventFilter filter)
+
+ Replaces the event filter function for the QCoreApplication with
+ \a filter and returns the pointer to the replaced event filter
+ function. Only the current event filter function is called. If you
+ want to use both filter functions, save the replaced EventFilter
+ in a place where yours can call it.
+
+ The event filter function set here is called for all messages
+ received by all threads meant for all Qt objects. It is \e not
+ called for messages that are not meant for Qt objects.
+
+ The event filter function should return true if the message should
+ be filtered, (i.e. stopped). It should return false to allow
+ processing the message to continue.
+
+ By default, no event filter function is set (i.e., this function
+ returns a null EventFilter the first time it is called).
+
+ \note The filter function set here receives native messages,
+ i.e. MSG or XEvent structs, that are going to Qt objects. It is
+ called by QCoreApplication::filterEvent(). If the filter function
+ returns false to indicate the message should be processed further,
+ the native message can then be translated into a QEvent and
+ handled by the standard Qt \l{QEvent} {event} filering, e.g.
+ QObject::installEventFilter().
+
+ \note The filter function set here is different form the filter
+ function set via QAbstractEventDispatcher::setEventFilter(), which
+ gets all messages received by its thread, even messages meant for
+ objects that are not handled by Qt.
+
+ \sa QObject::installEventFilter(), QAbstractEventDispatcher::setEventFilter()
+*/
+QCoreApplication::EventFilter
+QCoreApplication::setEventFilter(QCoreApplication::EventFilter filter)
+{
+ Q_D(QCoreApplication);
+ EventFilter old = d->eventFilter;
+ d->eventFilter = filter;
+ return old;
+}
+
+/*!
+ Sends \a message through the event filter that was set by
+ setEventFilter(). If no event filter has been set, this function
+ returns false; otherwise, this function returns the result of the
+ event filter function in the \a result parameter.
+
+ \sa setEventFilter()
+*/
+bool QCoreApplication::filterEvent(void *message, long *result)
+{
+ Q_D(QCoreApplication);
+ if (result)
+ *result = 0;
+ if (d->eventFilter)
+ return d->eventFilter(message, result);
+#ifdef Q_OS_WIN
+ return winEventFilter(reinterpret_cast<MSG *>(message), result);
+#else
+ return false;
+#endif
+}
+
+/*!
+ This function returns true if there are pending events; otherwise
+ returns false. Pending events can be either from the window
+ system or posted events using postEvent().
+
+ \sa QAbstractEventDispatcher::hasPendingEvents()
+*/
+bool QCoreApplication::hasPendingEvents()
+{
+ QAbstractEventDispatcher *eventDispatcher = QAbstractEventDispatcher::instance();
+ if (eventDispatcher)
+ return eventDispatcher->hasPendingEvents();
+ return false;
+}
+
+#ifdef QT3_SUPPORT
+/*! \fn void QCoreApplication::lock()
+
+ In Qt 3, this function locked the Qt library mutex, allowing
+ non-GUI threads to perform basic printing operations using
+ QPainter.
+
+ In Qt 4, this is no longer supported, since painting is only
+ supported from within a paint event handler. This function does
+ nothing.
+
+ \sa QWidget::paintEvent()
+*/
+
+/*! \fn void QCoreApplication::unlock(bool wakeUpGui)
+
+ In Qt 3, this function unlocked the Qt library mutex. The mutex
+ allowed non-GUI threads to perform basic printing operations
+ using QPainter.
+
+ In Qt 4, this is no longer supported, since painting is only
+ supported from within a paint event handler. This function does
+ nothing.
+*/
+
+/*! \fn bool QCoreApplication::locked()
+
+ This function does nothing. It is there to keep old code working.
+ It always returns false.
+
+ See lock() for details.
+*/
+
+/*! \fn bool QCoreApplication::tryLock()
+
+ This function does nothing. It is there to keep old code working.
+ It always returns false.
+
+ See lock() for details.
+*/
+
+/*! \fn void QCoreApplication::processOneEvent()
+ \obsolete
+
+ Waits for an event to occur, processes it, then returns.
+
+ This function is useful for adapting Qt to situations where the
+ event processing must be grafted onto existing program loops.
+
+ Using this function in new applications may be an indication of design
+ problems.
+
+ \sa processEvents(), exec(), QTimer
+*/
+
+/*! \obsolete
+
+ This function enters the main event loop (recursively). Do not call
+ it unless you really know what you are doing.
+*/
+int QCoreApplication::enter_loop()
+{
+ if (!QCoreApplicationPrivate::checkInstance("enter_loop"))
+ return -1;
+ if (QThreadData::current() != self->d_func()->threadData) {
+ qWarning("QCoreApplication::enter_loop: Must be called from the main thread");
+ return -1;
+ }
+ QEventLoop eventLoop;
+ int returnCode = eventLoop.exec();
+ return returnCode;
+}
+
+/*! \obsolete
+
+ This function exits from a recursive call to the main event loop.
+ Do not call it unless you are an expert.
+*/
+void QCoreApplication::exit_loop()
+{
+ if (!QCoreApplicationPrivate::checkInstance("exit_loop"))
+ return;
+ QThreadData *data = QThreadData::current();
+ if (data != self->d_func()->threadData) {
+ qWarning("QCoreApplication::exit_loop: Must be called from the main thread");
+ return;
+ }
+ if (!data->eventLoops.isEmpty())
+ data->eventLoops.top()->exit();
+}
+
+/*! \obsolete
+
+ Returns the current loop level.
+*/
+int QCoreApplication::loopLevel()
+{
+ if (!QCoreApplicationPrivate::checkInstance("loopLevel"))
+ return -1;
+ return self->d_func()->threadData->eventLoops.size();
+}
+#endif
+
+/*
+ \fn void QCoreApplication::watchUnixSignal(int signal, bool watch)
+ \internal
+*/
+
+/*!
+ \fn void QCoreApplication::unixSignal(int number)
+ \internal
+
+ This signal is emitted whenever a Unix signal is received by the
+ application. The Unix signal received is specified by its \a number.
+*/
+
+/*!
+ \fn void qAddPostRoutine(QtCleanUpFunction ptr)
+ \relates QCoreApplication
+
+ Adds a global routine that will be called from the QApplication
+ destructor. This function is normally used to add cleanup routines
+ for program-wide functionality.
+
+ The function specified by \a ptr should take no arguments and should
+ return nothing. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 4
+
+ Note that for an application- or module-wide cleanup,
+ qAddPostRoutine() is often not suitable. For example, if the
+ program is split into dynamically loaded modules, the relevant
+ module may be unloaded long before the QApplication destructor is
+ called.
+
+ For modules and libraries, using a reference-counted
+ initialization manager or Qt's parent-child deletion mechanism may
+ be better. Here is an example of a private class that uses the
+ parent-child mechanism to call a cleanup function at the right
+ time:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 5
+
+ By selecting the right parent object, this can often be made to
+ clean up the module's data at the right moment.
+*/
+
+/*!
+ \macro Q_DECLARE_TR_FUNCTIONS(context)
+ \relates QCoreApplication
+
+ The Q_DECLARE_TR_FUNCTIONS() macro declares and implements two
+ translation functions, \c tr() and \c trUtf8(), with these
+ signatures:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 6
+
+ This macro is useful if you want to use QObject::tr() or
+ QObject::trUtf8() in classes that don't inherit from QObject.
+
+ Q_DECLARE_TR_FUNCTIONS() must appear at the very top of the
+ class definition (before the first \c{public:} or \c{protected:}).
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qcoreapplication.cpp 7
+
+ The \a context parameter is normally the class name, but it can
+ be any string.
+
+ \sa Q_OBJECT, QObject::tr(), QObject::trUtf8()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
new file mode 100644
index 0000000000..3957158d83
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -0,0 +1,297 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCOREAPPLICATION_H
+#define QCOREAPPLICATION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qeventloop.h>
+
+#ifdef QT_INCLUDE_COMPAT
+#include <QtCore/qstringlist.h>
+#endif
+
+#if defined(Q_WS_WIN) && !defined(tagMSG)
+typedef struct tagMSG MSG;
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QCoreApplicationPrivate;
+class QTextCodec;
+class QTranslator;
+class QPostEventList;
+class QStringList;
+
+#define qApp QCoreApplication::instance()
+
+class Q_CORE_EXPORT QCoreApplication : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName)
+ Q_PROPERTY(QString applicationVersion READ applicationVersion WRITE setApplicationVersion)
+ Q_PROPERTY(QString organizationName READ organizationName WRITE setOrganizationName)
+ Q_PROPERTY(QString organizationDomain READ organizationDomain WRITE setOrganizationDomain)
+
+ Q_DECLARE_PRIVATE(QCoreApplication)
+public:
+ enum { ApplicationFlags = QT_VERSION
+#if !defined(QT3_SUPPORT)
+ | 0x01000000
+#endif
+ };
+
+#if defined(QT_BUILD_CORE_LIB) || defined(qdoc)
+ QCoreApplication(int &argc, char **argv); // ### Qt5 remove
+#endif
+#if !defined(qdoc)
+ QCoreApplication(int &argc, char **argv, int
+#if !defined(QT_BUILD_CORE_LIB)
+ = ApplicationFlags
+#endif
+ );
+#endif
+
+ ~QCoreApplication();
+
+#ifdef QT_DEPRECATED
+ QT_DEPRECATED static int argc();
+ QT_DEPRECATED static char **argv();
+#endif
+ static QStringList arguments();
+
+ static void setAttribute(Qt::ApplicationAttribute attribute, bool on = true);
+ static bool testAttribute(Qt::ApplicationAttribute attribute);
+
+ static void setOrganizationDomain(const QString &orgDomain);
+ static QString organizationDomain();
+ static void setOrganizationName(const QString &orgName);
+ static QString organizationName();
+ static void setApplicationName(const QString &application);
+ static QString applicationName();
+ static void setApplicationVersion(const QString &version);
+ static QString applicationVersion();
+
+ static QCoreApplication *instance() { return self; }
+
+ static int exec();
+ static void processEvents(QEventLoop::ProcessEventsFlags flags = QEventLoop::AllEvents);
+ static void processEvents(QEventLoop::ProcessEventsFlags flags, int maxtime);
+ static void exit(int retcode=0);
+
+ static bool sendEvent(QObject *receiver, QEvent *event);
+ static void postEvent(QObject *receiver, QEvent *event);
+ static void postEvent(QObject *receiver, QEvent *event, int priority);
+ static void sendPostedEvents(QObject *receiver, int event_type);
+ static void sendPostedEvents();
+ static void removePostedEvents(QObject *receiver);
+ static void removePostedEvents(QObject *receiver, int eventType);
+ static bool hasPendingEvents();
+
+ virtual bool notify(QObject *, QEvent *);
+
+ static bool startingUp();
+ static bool closingDown();
+
+ static QString applicationDirPath();
+ static QString applicationFilePath();
+ static qint64 applicationPid();
+
+#ifndef QT_NO_LIBRARY
+ static void setLibraryPaths(const QStringList &);
+ static QStringList libraryPaths();
+ static void addLibraryPath(const QString &);
+ static void removeLibraryPath(const QString &);
+#endif // QT_NO_LIBRARY
+
+#ifndef QT_NO_TRANSLATION
+ static void installTranslator(QTranslator * messageFile);
+ static void removeTranslator(QTranslator * messageFile);
+#endif
+ enum Encoding { CodecForTr, UnicodeUTF8, DefaultCodec = CodecForTr };
+ // ### Qt 5: merge
+ static QString translate(const char * context,
+ const char * key,
+ const char * disambiguation = 0,
+ Encoding encoding = CodecForTr);
+ static QString translate(const char * context,
+ const char * key,
+ const char * disambiguation,
+ Encoding encoding, int n);
+
+ static void flush();
+
+#if defined(QT3_SUPPORT)
+ inline QT3_SUPPORT void lock() {}
+ inline QT3_SUPPORT void unlock(bool = true) {}
+ inline QT3_SUPPORT bool locked() { return false; }
+ inline QT3_SUPPORT bool tryLock() { return false; }
+
+ static inline QT3_SUPPORT void processOneEvent()
+ { processEvents(QEventLoop::WaitForMoreEvents); }
+ static QT3_SUPPORT int enter_loop();
+ static QT3_SUPPORT void exit_loop();
+ static QT3_SUPPORT int loopLevel();
+#endif
+
+#if defined(Q_WS_WIN)
+ virtual bool winEventFilter(MSG *message, long *result);
+#endif
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ static void watchUnixSignal(int signal, bool watch);
+#endif
+
+ typedef bool (*EventFilter)(void *message, long *result);
+ EventFilter setEventFilter(EventFilter filter);
+ bool filterEvent(void *message, long *result);
+
+public Q_SLOTS:
+ static void quit();
+
+Q_SIGNALS:
+ void aboutToQuit();
+ void unixSignal(int);
+
+protected:
+ bool event(QEvent *);
+
+ virtual bool compressEvent(QEvent *, QObject *receiver, QPostEventList *);
+
+protected:
+ QCoreApplication(QCoreApplicationPrivate &p);
+
+private:
+ static bool sendSpontaneousEvent(QObject *receiver, QEvent *event);
+ bool notifyInternal(QObject *receiver, QEvent *event);
+
+ void init();
+
+ static QCoreApplication *self;
+
+ Q_DISABLE_COPY(QCoreApplication)
+
+ friend class QEventDispatcherUNIXPrivate;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QETWidget;
+ friend class Q3AccelManager;
+ friend class QShortcutMap;
+ friend class QWidget;
+ friend class QWidgetPrivate;
+ friend bool qt_sendSpontaneousEvent(QObject*, QEvent*);
+ friend Q_CORE_EXPORT QString qAppName();
+ friend class QClassFactory;
+};
+
+inline bool QCoreApplication::sendEvent(QObject *receiver, QEvent *event)
+{ if (event) event->spont = false; return self ? self->notifyInternal(receiver, event) : false; }
+
+inline bool QCoreApplication::sendSpontaneousEvent(QObject *receiver, QEvent *event)
+{ if (event) event->spont = true; return self ? self->notifyInternal(receiver, event) : false; }
+
+inline void QCoreApplication::sendPostedEvents() { sendPostedEvents(0, 0); }
+
+#ifdef QT_NO_TRANSLATION
+// Simple versions
+inline QString QCoreApplication::translate(const char *, const char *sourceText,
+ const char *, Encoding encoding)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (encoding == UnicodeUTF8)
+ return QString::fromUtf8(sourceText);
+#else
+ Q_UNUSED(encoding)
+#endif
+ return QString::fromLatin1(sourceText);
+}
+
+// Simple versions
+inline QString QCoreApplication::translate(const char *, const char *sourceText,
+ const char *, Encoding encoding, int)
+{
+#ifndef QT_NO_TEXTCODEC
+ if (encoding == UnicodeUTF8)
+ return QString::fromUtf8(sourceText);
+#else
+ Q_UNUSED(encoding)
+#endif
+ return QString::fromLatin1(sourceText);
+}
+#endif
+
+// ### merge the four functions into two (using "int n = -1")
+#define Q_DECLARE_TR_FUNCTIONS(context) \
+public: \
+ static inline QString tr(const char *sourceText, const char *disambiguation = 0) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation); } \
+ static inline QString trUtf8(const char *sourceText, const char *disambiguation = 0) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation, \
+ QCoreApplication::UnicodeUTF8); } \
+ static inline QString tr(const char *sourceText, const char *disambiguation, int n) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation, \
+ QCoreApplication::CodecForTr, n); } \
+ static inline QString trUtf8(const char *sourceText, const char *disambiguation, int n) \
+ { return QCoreApplication::translate(#context, sourceText, disambiguation, \
+ QCoreApplication::UnicodeUTF8, n); } \
+private:
+
+typedef void (*QtCleanUpFunction)();
+
+Q_CORE_EXPORT void qAddPostRoutine(QtCleanUpFunction);
+Q_CORE_EXPORT void qRemovePostRoutine(QtCleanUpFunction);
+Q_CORE_EXPORT QString qAppName(); // get application name
+
+#if defined(Q_WS_WIN) && !defined(QT_NO_DEBUG_STREAM)
+Q_CORE_EXPORT QString decodeMSG(const MSG &);
+Q_CORE_EXPORT QDebug operator<<(QDebug, const MSG &);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCOREAPPLICATION_H
diff --git a/src/corelib/kernel/qcoreapplication_mac.cpp b/src/corelib/kernel/qcoreapplication_mac.cpp
new file mode 100644
index 0000000000..0734c6ccd4
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_mac.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qcoreapplication.h"
+#include "private/qcoreapplication_p.h"
+#include <private/qcore_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*****************************************************************************
+ QCoreApplication utility functions
+ *****************************************************************************/
+QString qAppFileName()
+{
+ static QString appFileName;
+ if (appFileName.isEmpty()) {
+ QCFType<CFURLRef> bundleURL(CFBundleCopyExecutableURL(CFBundleGetMainBundle()));
+ if(bundleURL) {
+ QCFString cfPath(CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle));
+ if(cfPath)
+ appFileName = cfPath;
+ }
+ }
+ return appFileName;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
new file mode 100644
index 0000000000..add2a3553e
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCOREAPPLICATION_P_H
+#define QCOREAPPLICATION_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 "QtCore/qcoreapplication.h"
+#include "QtCore/qtranslator.h"
+#include "private/qobject_p.h"
+
+#ifdef Q_OS_SYMBIAN
+#include <f32file.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QTranslator*> QTranslatorList;
+
+#if defined(Q_OS_SYMBIAN)
+# if !defined(QT_NO_SYSTEMLOCALE)
+class QEnvironmentChangeNotifier;
+# endif
+class CApaCommandLine;
+#endif
+class QAbstractEventDispatcher;
+
+class Q_CORE_EXPORT QCoreApplicationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QCoreApplication)
+
+public:
+ QCoreApplicationPrivate(int &aargc, char **aargv, uint flags);
+ ~QCoreApplicationPrivate();
+
+ bool sendThroughApplicationEventFilters(QObject *, QEvent *);
+ bool sendThroughObjectEventFilters(QObject *, QEvent *);
+ bool notify_helper(QObject *, QEvent *);
+
+ virtual QString appName() const;
+ virtual void createEventDispatcher();
+ static void removePostedEvent(QEvent *);
+#ifdef Q_OS_WIN
+ static void removePostedTimerEvent(QObject *object, int timerId);
+#endif
+
+#ifdef Q_OS_MAC
+ static QString macMenuBarName();
+#endif
+
+ static QThread *theMainThread;
+ static QThread *mainThread();
+ static bool checkInstance(const char *method);
+ static void sendPostedEvents(QObject *receiver, int event_type, QThreadData *data);
+
+#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD) || defined (Q_OS_SYMBIAN)
+ void checkReceiverThread(QObject *receiver);
+#endif
+ int &argc;
+ char **argv;
+ void appendApplicationPathToLibraryPaths(void);
+
+#ifndef QT_NO_TRANSLATION
+ QTranslatorList translators;
+#endif
+ uint application_type;
+
+ QCoreApplication::EventFilter eventFilter;
+
+ bool in_exec;
+ bool aboutToQuitEmitted;
+ QString cachedApplicationDirPath;
+ QString cachedApplicationFilePath;
+#if defined(Q_OS_SYMBIAN)
+# if !defined(QT_NO_SYSTEMLOCALE)
+ QScopedPointer<QEnvironmentChangeNotifier> environmentChangeNotifier;
+ void symbianInit();
+# endif
+ static CApaCommandLine* symbianCommandLine();
+#endif
+
+ static bool isTranslatorInstalled(QTranslator *translator);
+
+ static QAbstractEventDispatcher *eventDispatcher;
+ static bool is_app_running;
+ static bool is_app_closing;
+
+ static uint attribs;
+ static inline bool testAttribute(uint flag) { return attribs & (1 << flag); }
+ static int app_compile_version;
+#if defined(QT3_SUPPORT)
+ static bool useQt3Support;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOREAPPLICATION_P_H
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
new file mode 100644
index 0000000000..a6f43a8900
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -0,0 +1,1060 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qstringlist.h"
+#include "qt_windows.h"
+#include "qvector.h"
+#include "qmutex.h"
+#include "qfileinfo.h"
+#include "qcorecmdlineargs_p.h"
+#include <private/qthread_p.h>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+bool usingWinMain = false; // whether the qWinMain() is used or not
+int appCmdShow = 0;
+
+Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle
+{
+ return GetModuleHandle(0);
+}
+
+Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app handle
+{
+ return 0;
+}
+
+Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command
+{
+#if defined(Q_OS_WINCE)
+ return appCmdShow;
+#else
+ STARTUPINFO startupInfo;
+ GetStartupInfo(&startupInfo);
+
+ return (startupInfo.dwFlags & STARTF_USESHOWWINDOW)
+ ? startupInfo.wShowWindow
+ : SW_SHOWDEFAULT;
+#endif
+}
+
+Q_CORE_EXPORT QString qAppFileName() // get application file name
+{
+ // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths
+ // up to, and including MAX_PATH size perfectly fine with string termination, as well
+ // as easily detect if the file path is indeed larger than MAX_PATH, in which case we
+ // need to use the heap instead. This is a work-around, since contrary to what the
+ // MSDN documentation states, GetModuleFileName sometimes doesn't set the
+ // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if
+ // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH.
+ // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal
+ // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use
+ // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok).
+ wchar_t buffer[MAX_PATH + 2];
+ DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1);
+ buffer[MAX_PATH + 1] = 0;
+
+ if (v == 0)
+ return QString();
+ else if (v <= MAX_PATH)
+ return QString::fromWCharArray(buffer);
+
+ // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap
+ wchar_t *b = 0;
+ int i = 1;
+ size_t size;
+ do {
+ ++i;
+ size = MAX_PATH * i;
+ b = reinterpret_cast<wchar_t *>(realloc(b, (size + 1) * sizeof(wchar_t)));
+ if (b)
+ v = GetModuleFileName(NULL, b, size);
+ } while (b && v == size);
+
+ if (b)
+ *(b + size) = 0;
+ QString res = QString::fromWCharArray(b);
+ free(b);
+
+ return res;
+}
+
+QString QCoreApplicationPrivate::appName() const
+{
+ return QFileInfo(qAppFileName()).baseName();
+}
+
+class QWinMsgHandlerCriticalSection
+{
+ CRITICAL_SECTION cs;
+public:
+ QWinMsgHandlerCriticalSection()
+ { InitializeCriticalSection(&cs); }
+ ~QWinMsgHandlerCriticalSection()
+ { DeleteCriticalSection(&cs); }
+
+ void lock()
+ { EnterCriticalSection(&cs); }
+ void unlock()
+ { LeaveCriticalSection(&cs); }
+};
+
+Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str)
+{
+ Q_UNUSED(t);
+ // OutputDebugString is not threadsafe.
+
+ // cannot use QMutex here, because qWarning()s in the QMutex
+ // implementation may cause this function to recurse
+ static QWinMsgHandlerCriticalSection staticCriticalSection;
+
+ if (!str)
+ str = "(null)";
+
+ staticCriticalSection.lock();
+
+ QString s(QString::fromLocal8Bit(str));
+ s += QLatin1Char('\n');
+ OutputDebugString((wchar_t*)s.utf16());
+
+ staticCriticalSection.unlock();
+}
+
+
+/*****************************************************************************
+ qWinMain() - Initializes Windows. Called from WinMain() in qtmain_win.cpp
+ *****************************************************************************/
+
+#if defined(Q_OS_WINCE)
+Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+#else
+Q_CORE_EXPORT
+void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
+ int cmdShow, int &argc, QVector<char *> &argv)
+#endif
+{
+ static bool already_called = false;
+
+ if (already_called) {
+ qWarning("Qt: Internal error: qWinMain should be called only once");
+ return;
+ }
+ already_called = true;
+ usingWinMain = true;
+
+ // Install default debug handler
+ qInstallMsgHandler(qWinMsgHandler);
+
+ // Create command line
+ argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
+
+ appCmdShow = cmdShow;
+
+ // Ignore Windows parameters
+ Q_UNUSED(instance);
+ Q_UNUSED(prevInstance);
+}
+
+/*!
+ The message procedure calls this function for every message
+ received. Reimplement this function if you want to process window
+ messages \a msg that are not processed by Qt. If you don't want
+ the event to be processed by Qt, then return true and set \a result
+ to the value that the window procedure should return. Otherwise
+ return false.
+
+ It is only directly addressed messages that are filtered. To
+ handle system wide messages, such as messages from a registered
+ hot key, you need to install an event filter on the event
+ dispatcher, which is returned from
+ QAbstractEventDispatcher::instance().
+*/
+bool QCoreApplication::winEventFilter(MSG *msg, long *result) // Windows event filter
+{
+ Q_UNUSED(msg);
+ Q_UNUSED(result);
+ return false;
+}
+
+void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
+{
+ QThreadData *data = object->d_func()->threadData;
+
+ QMutexLocker locker(&data->postEventList.mutex);
+ if (data->postEventList.size() == 0)
+ return;
+ for (int i = 0; i < data->postEventList.size(); ++i) {
+ const QPostEvent & pe = data->postEventList.at(i);
+ if (pe.receiver == object
+ && pe.event
+ && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
+ && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ const_cast<QPostEvent &>(pe).event = 0;
+ return;
+ }
+ }
+}
+
+#if defined(Q_WS_WIN) && !defined(QT_NO_DEBUG_STREAM)
+/*****************************************************************************
+ Convenience functions for convert WM_* messages into human readable strings,
+ including a nifty QDebug operator<< for simpel QDebug() << msg output.
+ *****************************************************************************/
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <windowsx.h>
+#include "qdebug.h"
+QT_END_INCLUDE_NAMESPACE
+
+#if !defined(GET_X_LPARAM)
+# define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
+# define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
+#endif
+#ifdef _WIN32_WCE
+# ifndef WM_NCACTIVATE
+# define WM_NCACTIVATE 0x86
+# endif
+#endif
+
+// The values below should never change. Note that none of the usual
+// WM_...FIRST & WM_...LAST values are in the list, as they normally have other
+// WM_... representations
+struct KnownWM {
+ uint WM;
+ const char* str;
+} knownWM[] =
+{{ 0x0000, "WM_NULL" },
+ { 0x0001, "WM_CREATE" },
+ { 0x0002, "WM_DESTROY" },
+ { 0x0003, "WM_MOVE" },
+ { 0x0005, "WM_SIZE" },
+ { 0x0006, "WM_ACTIVATE" },
+ { 0x0007, "WM_SETFOCUS" },
+ { 0x0008, "WM_KILLFOCUS" },
+ { 0x000A, "WM_ENABLE" },
+ { 0x000B, "WM_SETREDRAW" },
+ { 0x000C, "WM_SETTEXT" },
+ { 0x000D, "WM_GETTEXT" },
+ { 0x000E, "WM_GETTEXTLENGTH" },
+ { 0x000F, "WM_PAINT" },
+ { 0x0010, "WM_CLOSE" },
+ { 0x0011, "WM_QUERYENDSESSION" },
+ { 0x0013, "WM_QUERYOPEN" },
+ { 0x0016, "WM_ENDSESSION" },
+ { 0x0012, "WM_QUIT" },
+ { 0x0014, "WM_ERASEBKGND" },
+ { 0x0015, "WM_SYSCOLORCHANGE" },
+ { 0x0018, "WM_SHOWWINDOW" },
+ { 0x001A, "WM_WININICHANGE" },
+ { 0x001B, "WM_DEVMODECHANGE" },
+ { 0x001C, "WM_ACTIVATEAPP" },
+ { 0x001D, "WM_FONTCHANGE" },
+ { 0x001E, "WM_TIMECHANGE" },
+ { 0x001F, "WM_CANCELMODE" },
+ { 0x0020, "WM_SETCURSOR" },
+ { 0x0021, "WM_MOUSEACTIVATE" },
+ { 0x0022, "WM_CHILDACTIVATE" },
+ { 0x0023, "WM_QUEUESYNC" },
+ { 0x0024, "WM_GETMINMAXINFO" },
+ { 0x0026, "WM_PAINTICON" },
+ { 0x0027, "WM_ICONERASEBKGND" },
+ { 0x0028, "WM_NEXTDLGCTL" },
+ { 0x002A, "WM_SPOOLERSTATUS" },
+ { 0x002B, "WM_DRAWITEM" },
+ { 0x002C, "WM_MEASUREITEM" },
+ { 0x002D, "WM_DELETEITEM" },
+ { 0x002E, "WM_VKEYTOITEM" },
+ { 0x002F, "WM_CHARTOITEM" },
+ { 0x0030, "WM_SETFONT" },
+ { 0x0031, "WM_GETFONT" },
+ { 0x0032, "WM_SETHOTKEY" },
+ { 0x0033, "WM_GETHOTKEY" },
+ { 0x0037, "WM_QUERYDRAGICON" },
+ { 0x0039, "WM_COMPAREITEM" },
+ { 0x003D, "WM_GETOBJECT" },
+ { 0x0041, "WM_COMPACTING" },
+ { 0x0044, "WM_COMMNOTIFY" },
+ { 0x0046, "WM_WINDOWPOSCHANGING" },
+ { 0x0047, "WM_WINDOWPOSCHANGED" },
+ { 0x0048, "WM_POWER" },
+ { 0x004A, "WM_COPYDATA" },
+ { 0x004B, "WM_CANCELJOURNAL" },
+ { 0x004E, "WM_NOTIFY" },
+ { 0x0050, "WM_INPUTLANGCHANGEREQUEST" },
+ { 0x0051, "WM_INPUTLANGCHANGE" },
+ { 0x0052, "WM_TCARD" },
+ { 0x0053, "WM_HELP" },
+ { 0x0054, "WM_USERCHANGED" },
+ { 0x0055, "WM_NOTIFYFORMAT" },
+ { 0x007B, "WM_CONTEXTMENU" },
+ { 0x007C, "WM_STYLECHANGING" },
+ { 0x007D, "WM_STYLECHANGED" },
+ { 0x007E, "WM_DISPLAYCHANGE" },
+ { 0x007F, "WM_GETICON" },
+ { 0x0080, "WM_SETICON" },
+ { 0x0081, "WM_NCCREATE" },
+ { 0x0082, "WM_NCDESTROY" },
+ { 0x0083, "WM_NCCALCSIZE" },
+ { 0x0084, "WM_NCHITTEST" },
+ { 0x0085, "WM_NCPAINT" },
+ { 0x0086, "WM_NCACTIVATE" },
+ { 0x0087, "WM_GETDLGCODE" },
+ { 0x0088, "WM_SYNCPAINT" },
+ { 0x00A0, "WM_NCMOUSEMOVE" },
+ { 0x00A1, "WM_NCLBUTTONDOWN" },
+ { 0x00A2, "WM_NCLBUTTONUP" },
+ { 0x00A3, "WM_NCLBUTTONDBLCLK" },
+ { 0x00A4, "WM_NCRBUTTONDOWN" },
+ { 0x00A5, "WM_NCRBUTTONUP" },
+ { 0x00A6, "WM_NCRBUTTONDBLCLK" },
+ { 0x00A7, "WM_NCMBUTTONDOWN" },
+ { 0x00A8, "WM_NCMBUTTONUP" },
+ { 0x00A9, "WM_NCMBUTTONDBLCLK" },
+ { 0x00AB, "WM_NCXBUTTONDOWN" },
+ { 0x00AC, "WM_NCXBUTTONUP" },
+ { 0x00AD, "WM_NCXBUTTONDBLCLK" },
+ { 0x00FF, "WM_INPUT" },
+ { 0x0100, "WM_KEYDOWN" },
+ { 0x0101, "WM_KEYUP" },
+ { 0x0102, "WM_CHAR" },
+ { 0x0103, "WM_DEADCHAR" },
+ { 0x0104, "WM_SYSKEYDOWN" },
+ { 0x0105, "WM_SYSKEYUP" },
+ { 0x0106, "WM_SYSCHAR" },
+ { 0x0107, "WM_SYSDEADCHAR" },
+ { 0x0109, "WM_UNICHAR" },
+ { 0x010D, "WM_IME_STARTCOMPOSITION" },
+ { 0x010E, "WM_IME_ENDCOMPOSITION" },
+ { 0x010F, "WM_IME_COMPOSITION" },
+ { 0x0110, "WM_INITDIALOG" },
+ { 0x0111, "WM_COMMAND" },
+ { 0x0112, "WM_SYSCOMMAND" },
+ { 0x0113, "WM_TIMER" },
+ { 0x0114, "WM_HSCROLL" },
+ { 0x0115, "WM_VSCROLL" },
+ { 0x0116, "WM_INITMENU" },
+ { 0x0117, "WM_INITMENUPOPUP" },
+ { 0x011F, "WM_MENUSELECT" },
+ { 0x0120, "WM_MENUCHAR" },
+ { 0x0121, "WM_ENTERIDLE" },
+ { 0x0122, "WM_MENURBUTTONUP" },
+ { 0x0123, "WM_MENUDRAG" },
+ { 0x0124, "WM_MENUGETOBJECT" },
+ { 0x0125, "WM_UNINITMENUPOPUP" },
+ { 0x0126, "WM_MENUCOMMAND" },
+ { 0x0127, "WM_CHANGEUISTATE" },
+ { 0x0128, "WM_UPDATEUISTATE" },
+ { 0x0129, "WM_QUERYUISTATE" },
+ { 0x0132, "WM_CTLCOLORMSGBOX" },
+ { 0x0133, "WM_CTLCOLOREDIT" },
+ { 0x0134, "WM_CTLCOLORLISTBOX" },
+ { 0x0135, "WM_CTLCOLORBTN" },
+ { 0x0136, "WM_CTLCOLORDLG" },
+ { 0x0137, "WM_CTLCOLORSCROLLBAR" },
+ { 0x0138, "WM_CTLCOLORSTATIC" },
+ { 0x0200, "WM_MOUSEMOVE" },
+ { 0x0201, "WM_LBUTTONDOWN" },
+ { 0x0202, "WM_LBUTTONUP" },
+ { 0x0203, "WM_LBUTTONDBLCLK" },
+ { 0x0204, "WM_RBUTTONDOWN" },
+ { 0x0205, "WM_RBUTTONUP" },
+ { 0x0206, "WM_RBUTTONDBLCLK" },
+ { 0x0207, "WM_MBUTTONDOWN" },
+ { 0x0208, "WM_MBUTTONUP" },
+ { 0x0209, "WM_MBUTTONDBLCLK" },
+ { 0x020A, "WM_MOUSEWHEEL" },
+ { 0x020B, "WM_XBUTTONDOWN" },
+ { 0x020C, "WM_XBUTTONUP" },
+ { 0x020D, "WM_XBUTTONDBLCLK" },
+ { 0x020E, "WM_MOUSEHWHEEL" },
+ { 0x0210, "WM_PARENTNOTIFY" },
+ { 0x0211, "WM_ENTERMENULOOP" },
+ { 0x0212, "WM_EXITMENULOOP" },
+ { 0x0213, "WM_NEXTMENU" },
+ { 0x0214, "WM_SIZING" },
+ { 0x0215, "WM_CAPTURECHANGED" },
+ { 0x0216, "WM_MOVING" },
+ { 0x0218, "WM_POWERBROADCAST" },
+ { 0x0219, "WM_DEVICECHANGE" },
+ { 0x0220, "WM_MDICREATE" },
+ { 0x0221, "WM_MDIDESTROY" },
+ { 0x0222, "WM_MDIACTIVATE" },
+ { 0x0223, "WM_MDIRESTORE" },
+ { 0x0224, "WM_MDINEXT" },
+ { 0x0225, "WM_MDIMAXIMIZE" },
+ { 0x0226, "WM_MDITILE" },
+ { 0x0227, "WM_MDICASCADE" },
+ { 0x0228, "WM_MDIICONARRANGE" },
+ { 0x0229, "WM_MDIGETACTIVE" },
+ { 0x0230, "WM_MDISETMENU" },
+ { 0x0231, "WM_ENTERSIZEMOVE" },
+ { 0x0232, "WM_EXITSIZEMOVE" },
+ { 0x0233, "WM_DROPFILES" },
+ { 0x0234, "WM_MDIREFRESHMENU" },
+ { 0x0281, "WM_IME_SETCONTEXT" },
+ { 0x0282, "WM_IME_NOTIFY" },
+ { 0x0283, "WM_IME_CONTROL" },
+ { 0x0284, "WM_IME_COMPOSITIONFULL" },
+ { 0x0285, "WM_IME_SELECT" },
+ { 0x0286, "WM_IME_CHAR" },
+ { 0x0288, "WM_IME_REQUEST" },
+ { 0x0290, "WM_IME_KEYDOWN" },
+ { 0x0291, "WM_IME_KEYUP" },
+ { 0x02A0, "WM_NCMOUSEHOVER" },
+ { 0x02A1, "WM_MOUSEHOVER" },
+ { 0x02A2, "WM_NCMOUSELEAVE" },
+ { 0x02A3, "WM_MOUSELEAVE" },
+ { 0x02B1, "WM_WTSSESSION_CHANGE" },
+ { 0x02C0, "WM_TABLET_FIRST" },
+ { 0x02C1, "WM_TABLET_FIRST + 1" },
+ { 0x02C2, "WM_TABLET_FIRST + 2" },
+ { 0x02C3, "WM_TABLET_FIRST + 3" },
+ { 0x02C4, "WM_TABLET_FIRST + 4" },
+ { 0x02C5, "WM_TABLET_FIRST + 5" },
+ { 0x02C6, "WM_TABLET_FIRST + 6" },
+ { 0x02C7, "WM_TABLET_FIRST + 7" },
+ { 0x02C8, "WM_TABLET_FIRST + 8" },
+ { 0x02C9, "WM_TABLET_FIRST + 9" },
+ { 0x02CA, "WM_TABLET_FIRST + 10" },
+ { 0x02CB, "WM_TABLET_FIRST + 11" },
+ { 0x02CC, "WM_TABLET_FIRST + 12" },
+ { 0x02CD, "WM_TABLET_FIRST + 13" },
+ { 0x02CE, "WM_TABLET_FIRST + 14" },
+ { 0x02CF, "WM_TABLET_FIRST + 15" },
+ { 0x02D0, "WM_TABLET_FIRST + 16" },
+ { 0x02D1, "WM_TABLET_FIRST + 17" },
+ { 0x02D2, "WM_TABLET_FIRST + 18" },
+ { 0x02D3, "WM_TABLET_FIRST + 19" },
+ { 0x02D4, "WM_TABLET_FIRST + 20" },
+ { 0x02D5, "WM_TABLET_FIRST + 21" },
+ { 0x02D6, "WM_TABLET_FIRST + 22" },
+ { 0x02D7, "WM_TABLET_FIRST + 23" },
+ { 0x02D8, "WM_TABLET_FIRST + 24" },
+ { 0x02D9, "WM_TABLET_FIRST + 25" },
+ { 0x02DA, "WM_TABLET_FIRST + 26" },
+ { 0x02DB, "WM_TABLET_FIRST + 27" },
+ { 0x02DC, "WM_TABLET_FIRST + 28" },
+ { 0x02DD, "WM_TABLET_FIRST + 29" },
+ { 0x02DE, "WM_TABLET_FIRST + 30" },
+ { 0x02DF, "WM_TABLET_LAST" },
+ { 0x0300, "WM_CUT" },
+ { 0x0301, "WM_COPY" },
+ { 0x0302, "WM_PASTE" },
+ { 0x0303, "WM_CLEAR" },
+ { 0x0304, "WM_UNDO" },
+ { 0x0305, "WM_RENDERFORMAT" },
+ { 0x0306, "WM_RENDERALLFORMATS" },
+ { 0x0307, "WM_DESTROYCLIPBOARD" },
+ { 0x0308, "WM_DRAWCLIPBOARD" },
+ { 0x0309, "WM_PAINTCLIPBOARD" },
+ { 0x030A, "WM_VSCROLLCLIPBOARD" },
+ { 0x030B, "WM_SIZECLIPBOARD" },
+ { 0x030C, "WM_ASKCBFORMATNAME" },
+ { 0x030D, "WM_CHANGECBCHAIN" },
+ { 0x030E, "WM_HSCROLLCLIPBOARD" },
+ { 0x030F, "WM_QUERYNEWPALETTE" },
+ { 0x0310, "WM_PALETTEISCHANGING" },
+ { 0x0311, "WM_PALETTECHANGED" },
+ { 0x0312, "WM_HOTKEY" },
+ { 0x0317, "WM_PRINT" },
+ { 0x0318, "WM_PRINTCLIENT" },
+ { 0x0319, "WM_APPCOMMAND" },
+ { 0x031A, "WM_THEMECHANGED" },
+ { 0x0358, "WM_HANDHELDFIRST" },
+ { 0x0359, "WM_HANDHELDFIRST + 1" },
+ { 0x035A, "WM_HANDHELDFIRST + 2" },
+ { 0x035B, "WM_HANDHELDFIRST + 3" },
+ { 0x035C, "WM_HANDHELDFIRST + 4" },
+ { 0x035D, "WM_HANDHELDFIRST + 5" },
+ { 0x035E, "WM_HANDHELDFIRST + 6" },
+ { 0x035F, "WM_HANDHELDLAST" },
+ { 0x0360, "WM_AFXFIRST" },
+ { 0x0361, "WM_AFXFIRST + 1" },
+ { 0x0362, "WM_AFXFIRST + 2" },
+ { 0x0363, "WM_AFXFIRST + 3" },
+ { 0x0364, "WM_AFXFIRST + 4" },
+ { 0x0365, "WM_AFXFIRST + 5" },
+ { 0x0366, "WM_AFXFIRST + 6" },
+ { 0x0367, "WM_AFXFIRST + 7" },
+ { 0x0368, "WM_AFXFIRST + 8" },
+ { 0x0369, "WM_AFXFIRST + 9" },
+ { 0x036A, "WM_AFXFIRST + 10" },
+ { 0x036B, "WM_AFXFIRST + 11" },
+ { 0x036C, "WM_AFXFIRST + 12" },
+ { 0x036D, "WM_AFXFIRST + 13" },
+ { 0x036E, "WM_AFXFIRST + 14" },
+ { 0x036F, "WM_AFXFIRST + 15" },
+ { 0x0370, "WM_AFXFIRST + 16" },
+ { 0x0371, "WM_AFXFIRST + 17" },
+ { 0x0372, "WM_AFXFIRST + 18" },
+ { 0x0373, "WM_AFXFIRST + 19" },
+ { 0x0374, "WM_AFXFIRST + 20" },
+ { 0x0375, "WM_AFXFIRST + 21" },
+ { 0x0376, "WM_AFXFIRST + 22" },
+ { 0x0377, "WM_AFXFIRST + 23" },
+ { 0x0378, "WM_AFXFIRST + 24" },
+ { 0x0379, "WM_AFXFIRST + 25" },
+ { 0x037A, "WM_AFXFIRST + 26" },
+ { 0x037B, "WM_AFXFIRST + 27" },
+ { 0x037C, "WM_AFXFIRST + 28" },
+ { 0x037D, "WM_AFXFIRST + 29" },
+ { 0x037E, "WM_AFXFIRST + 30" },
+ { 0x037F, "WM_AFXLAST" },
+ { 0x0380, "WM_PENWINFIRST" },
+ { 0x0381, "WM_PENWINFIRST + 1" },
+ { 0x0382, "WM_PENWINFIRST + 2" },
+ { 0x0383, "WM_PENWINFIRST + 3" },
+ { 0x0384, "WM_PENWINFIRST + 4" },
+ { 0x0385, "WM_PENWINFIRST + 5" },
+ { 0x0386, "WM_PENWINFIRST + 6" },
+ { 0x0387, "WM_PENWINFIRST + 7" },
+ { 0x0388, "WM_PENWINFIRST + 8" },
+ { 0x0389, "WM_PENWINFIRST + 9" },
+ { 0x038A, "WM_PENWINFIRST + 10" },
+ { 0x038B, "WM_PENWINFIRST + 11" },
+ { 0x038C, "WM_PENWINFIRST + 12" },
+ { 0x038D, "WM_PENWINFIRST + 13" },
+ { 0x038E, "WM_PENWINFIRST + 14" },
+ { 0x038F, "WM_PENWINLAST" },
+ { 0x0400, "WM_USER" },
+ { 0x8000, "WM_APP" },
+ { 0,0 }}; // End of known messages
+
+// Looks up the WM_ message in the table above
+static const char* findWMstr(uint msg)
+{
+ uint i = 0;
+ const char* result = 0;
+ // Known WM_'s
+ while (knownWM[i].str && (knownWM[i].WM != msg))
+ ++i;
+ result = knownWM[i].str;
+ return result;
+};
+
+// Convenience function for converting flags and values into readable strings
+struct FLAG_STRING_STRUCT
+{
+ uint value;
+ const char* str;
+};
+
+FLAG_STRING_STRUCT FLAG_STRING(int value = 0, const char *c = 0)
+{
+ FLAG_STRING_STRUCT s = {value, c};
+ return s;
+}
+
+#define FLGSTR(x) FLAG_STRING(x, #x)
+
+// Returns an ORed (" | ") together string for the flags active in the actual
+// value. (...) must consist of FLAG_STRING, with a FLAG_STRING() as the last
+// value in the list passed to the function
+QString flagCheck(uint actual, ...)
+{
+ va_list ap;
+ va_start(ap, actual);
+
+ QString result;
+ int count = 0;
+ FLAG_STRING_STRUCT v;
+ while((v=va_arg(ap,FLAG_STRING_STRUCT)).str) {
+ if ((actual & v.value) == v.value) {
+ if (count++)
+ result += QLatin1String(" | ");
+ result += QString::fromLatin1(v.str);
+ }
+ }
+ va_end(ap);
+ return result;
+};
+
+// Returns the string representation of the value in 'actual'. (...) must
+// consist of FLAG_STRING, with a FLAG_STRING() as the last value in the list
+// passed to the function
+QString valueCheck(uint actual, ...)
+{
+ va_list ap;
+ va_start(ap, actual);
+
+ QString result;
+ FLAG_STRING_STRUCT v;
+ while((v=va_arg(ap,FLAG_STRING_STRUCT)).str && (actual != v.value))
+ ;
+ result = QString::fromLatin1(v.str);
+
+ va_end(ap);
+ return result;
+};
+
+#ifdef Q_CC_BOR
+
+QString decodeMSG(const MSG& msg)
+{
+ return QString::fromLatin1("THis is not supported on Borland");
+}
+
+#else
+
+// Returns a "human readable" string representation of the MSG and the
+// information it points to
+QString decodeMSG(const MSG& msg)
+{
+ const WPARAM wParam = msg.wParam;
+ const LPARAM lParam = msg.lParam;
+ QString wmmsg = QString::fromLatin1(findWMstr(msg.message));
+ // Unknown WM_, so use number
+ if (wmmsg.isEmpty())
+ wmmsg = QString::fromLatin1("WM_(%1)").arg(msg.message);
+
+ QString rawParameters;
+ rawParameters.sprintf("hwnd(0x%p) ", (void *)msg.hwnd);
+
+ // Custom WM_'s
+ if (msg.message > WM_APP)
+ wmmsg = QString::fromLatin1("WM_APP + %1").arg(msg.message - WM_APP);
+ else if (msg.message > WM_USER)
+ wmmsg = QString::fromLatin1("WM_USER + %1").arg(msg.message - WM_USER);
+
+ QString parameters;
+ switch (msg.message) {
+#ifdef WM_ACTIVATE
+ case WM_ACTIVATE:
+ {
+ QString activation = valueCheck(wParam,
+ FLAG_STRING(WA_ACTIVE, "Activate"),
+ FLAG_STRING(WA_INACTIVE, "Deactivate"),
+ FLAG_STRING(WA_CLICKACTIVE, "Activate by mouseclick"),
+ FLAG_STRING());
+ parameters.sprintf("%s Hwnd (0x%p)", activation.toLatin1().data(), (void *)msg.hwnd);
+ }
+ break;
+#endif
+#ifdef WM_CAPTURECHANGED
+ case WM_CAPTURECHANGED:
+ parameters.sprintf("Hwnd gaining capture (0x%p)", (void *)lParam);
+ break;
+#endif
+#ifdef WM_CREATE
+ case WM_CREATE:
+ {
+ LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
+ QString styles = flagCheck(lpcs->style,
+ FLGSTR(WS_BORDER),
+ FLGSTR(WS_CAPTION),
+ FLGSTR(WS_CHILD),
+ FLGSTR(WS_CLIPCHILDREN),
+ FLGSTR(WS_CLIPSIBLINGS),
+ FLGSTR(WS_DISABLED),
+ FLGSTR(WS_DLGFRAME),
+ FLGSTR(WS_GROUP),
+ FLGSTR(WS_HSCROLL),
+ FLGSTR(WS_OVERLAPPED),
+#if defined(WS_OVERLAPPEDWINDOW) && (WS_OVERLAPPEDWINDOW != 0)
+ FLGSTR(WS_OVERLAPPEDWINDOW),
+#endif
+#ifdef WS_ICONIC
+ FLGSTR(WS_ICONIC),
+#endif
+ FLGSTR(WS_MAXIMIZE),
+ FLGSTR(WS_MAXIMIZEBOX),
+ FLGSTR(WS_MINIMIZE),
+ FLGSTR(WS_MINIMIZEBOX),
+ FLGSTR(WS_OVERLAPPEDWINDOW),
+ FLGSTR(WS_POPUP),
+#ifdef WS_POPUPWINDOW
+ FLGSTR(WS_POPUPWINDOW),
+#endif
+ FLGSTR(WS_SIZEBOX),
+ FLGSTR(WS_SYSMENU),
+ FLGSTR(WS_TABSTOP),
+ FLGSTR(WS_THICKFRAME),
+#ifdef WS_TILED
+ FLGSTR(WS_TILED),
+#endif
+#ifdef WS_TILEDWINDOW
+ FLGSTR(WS_TILEDWINDOW),
+#endif
+ FLGSTR(WS_VISIBLE),
+ FLGSTR(WS_VSCROLL),
+ FLAG_STRING());
+
+ QString exStyles = flagCheck(lpcs->dwExStyle,
+#ifdef WS_EX_ACCEPTFILES
+ FLGSTR(WS_EX_ACCEPTFILES),
+#endif
+#ifdef WS_EX_APPWINDOW
+ FLGSTR(WS_EX_APPWINDOW),
+#endif
+ FLGSTR(WS_EX_CLIENTEDGE),
+ FLGSTR(WS_EX_DLGMODALFRAME),
+#ifdef WS_EX_LEFT
+ FLGSTR(WS_EX_LEFT),
+#endif
+ FLGSTR(WS_EX_LEFTSCROLLBAR),
+#ifdef WS_EX_LTRREADING
+ FLGSTR(WS_EX_LTRREADING),
+#endif
+#ifdef WS_EX_MDICHILD
+ FLGSTR(WS_EX_MDICHILD),
+#endif
+#ifdef WS_EX_NOACTIVATE
+ FLGSTR(WS_EX_NOACTIVATE),
+#endif
+#ifdef WS_EX_NOANIMATION
+ FLGSTR(WS_EX_NOANIMATION),
+#endif
+ FLGSTR(WS_EX_NOPARENTNOTIFY),
+ FLGSTR(WS_EX_OVERLAPPEDWINDOW),
+#ifdef WS_EX_PALETTEWINDOW
+ FLGSTR(WS_EX_PALETTEWINDOW),
+#endif
+#ifdef WS_EX_RIGHT
+ FLGSTR(WS_EX_RIGHT),
+#endif
+#ifdef WS_EX_RIGHTSCROLLBAR
+ FLGSTR(WS_EX_RIGHTSCROLLBAR),
+#endif
+#ifdef WS_EX_RTLREADING
+ FLGSTR(WS_EX_RTLREADING),
+#endif
+ FLGSTR(WS_EX_STATICEDGE),
+ FLGSTR(WS_EX_TOOLWINDOW),
+ FLGSTR(WS_EX_TOPMOST),
+#ifdef WS_EX_TRANSPARENT
+ FLGSTR(WS_EX_TRANSPARENT),
+#endif
+ FLGSTR(WS_EX_WINDOWEDGE),
+#ifdef WS_EX_CAPTIONOKBTN
+ FLGSTR(WS_EX_CAPTIONOKBTN),
+#endif
+ FLAG_STRING());
+
+ QString className;
+ if (lpcs->lpszClass != 0) {
+ if (HIWORD(lpcs->lpszClass) == 0) // Atom
+ className = QString::number(LOWORD(lpcs->lpszClass), 16);
+ else // String
+ className = QString((QChar*)lpcs->lpszClass,
+ (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszClass)));
+ }
+
+ QString windowName;
+ if (lpcs->lpszName != 0)
+ windowName = QString((QChar*)lpcs->lpszName,
+ (int)wcslen(reinterpret_cast<const wchar_t *>(lpcs->lpszName)));
+
+ parameters.sprintf("x,y(%4d,%4d) w,h(%4d,%4d) className(%s) windowName(%s) parent(0x%p) style(%s) exStyle(%s)",
+ lpcs->x, lpcs->y, lpcs->cx, lpcs->cy, className.toLatin1().data(),
+ windowName.toLatin1().data(), (void *)lpcs->hwndParent,
+ styles.toLatin1().data(), exStyles.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_DESTROY
+ case WM_DESTROY:
+ parameters.sprintf("Destroy hwnd (0x%p)", (void *)msg.hwnd);
+ break;
+#endif
+#ifdef WM_IME_NOTIFY
+ case WM_IME_NOTIFY:
+ {
+ QString imnCommand = valueCheck(wParam,
+ FLGSTR(IMN_CHANGECANDIDATE),
+ FLGSTR(IMN_CLOSECANDIDATE),
+ FLGSTR(IMN_CLOSESTATUSWINDOW),
+ FLGSTR(IMN_GUIDELINE),
+ FLGSTR(IMN_OPENCANDIDATE),
+ FLGSTR(IMN_OPENSTATUSWINDOW),
+ FLGSTR(IMN_SETCANDIDATEPOS),
+ FLGSTR(IMN_SETCOMPOSITIONFONT),
+ FLGSTR(IMN_SETCOMPOSITIONWINDOW),
+ FLGSTR(IMN_SETCONVERSIONMODE),
+ FLGSTR(IMN_SETOPENSTATUS),
+ FLGSTR(IMN_SETSENTENCEMODE),
+ FLGSTR(IMN_SETSTATUSWINDOWPOS),
+ FLAG_STRING());
+ parameters.sprintf("Command(%s : 0x%p)", imnCommand.toLatin1().data(), (void *)lParam);
+ }
+ break;
+#endif
+#ifdef WM_IME_SETCONTEXT
+ case WM_IME_SETCONTEXT:
+ {
+ bool fSet = (BOOL)wParam;
+ DWORD fShow = (DWORD)lParam;
+ QString showFlgs = flagCheck(fShow,
+#ifdef ISC_SHOWUICOMPOSITIONWINDOW
+ FLGSTR(ISC_SHOWUICOMPOSITIONWINDOW),
+#endif
+#ifdef ISC_SHOWUIGUIDWINDOW
+ FLGSTR(ISC_SHOWUIGUIDWINDOW),
+#endif
+#ifdef ISC_SHOWUISOFTKBD
+ FLGSTR(ISC_SHOWUISOFTKBD),
+#endif
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 1),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 2),
+ FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 3),
+ FLAG_STRING());
+ parameters.sprintf("Input context(%s) Show flags(%s)", (fSet? "Active" : "Inactive"), showFlgs.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_KILLFOCUS
+ case WM_KILLFOCUS:
+ parameters.sprintf("Hwnd gaining keyboard focus (0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_CHAR
+ case WM_CHAR:
+#endif
+#ifdef WM_IME_CHAR
+ case WM_IME_CHAR:
+#endif
+#ifdef WM_KEYDOWN
+ case WM_KEYDOWN:
+#endif
+#ifdef WM_KEYUP
+ case WM_KEYUP:
+ {
+ int nVirtKey = (int)wParam;
+ long lKeyData = (long)lParam;
+ int repCount = (lKeyData & 0xffff); // Bit 0-15
+ int scanCode = (lKeyData & 0xf0000) >> 16; // Bit 16-23
+ bool contextCode = (lKeyData && 0x20000000); // Bit 29
+ bool prevState = (lKeyData && 0x40000000); // Bit 30
+ bool transState = (lKeyData && 0x80000000); // Bit 31
+ parameters.sprintf("Virual-key(0x%x) Scancode(%d) Rep(%d) Contextcode(%d), Prev state(%d), Trans state(%d)",
+ nVirtKey, scanCode, repCount, contextCode, prevState, transState);
+ }
+ break;
+#endif
+#ifdef WM_NCACTIVATE
+ case WM_NCACTIVATE:
+ {
+ parameters = (msg.wParam? QLatin1String("Active Titlebar") : QLatin1String("Inactive Titlebar"));
+ }
+ break;
+#endif
+#ifdef WM_MOUSEACTIVATE
+ case WM_MOUSEACTIVATE:
+ {
+ QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
+ parameters.sprintf("TLW(0x%p) HittestCode(0x%x) MouseMsg(%s)", (void *)wParam, LOWORD(lParam), mouseMsg.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_MOUSELEAVE
+ case WM_MOUSELEAVE:
+ break; // wParam & lParam not used
+#endif
+#ifdef WM_MOUSEHOVER
+ case WM_MOUSEHOVER:
+#endif
+#ifdef WM_MOUSEWHEEL
+ case WM_MOUSEWHEEL:
+#endif
+#ifdef WM_MOUSEHWHEEL
+ case WM_MOUSEHWHEEL:
+#endif
+#ifdef WM_LBUTTONDBLCLK
+ case WM_LBUTTONDBLCLK:
+#endif
+#ifdef WM_LBUTTONDOWN
+ case WM_LBUTTONDOWN:
+#endif
+#ifdef WM_LBUTTONUP
+ case WM_LBUTTONUP:
+#endif
+#ifdef WM_MBUTTONDBLCLK
+ case WM_MBUTTONDBLCLK:
+#endif
+#ifdef WM_MBUTTONDOWN
+ case WM_MBUTTONDOWN:
+#endif
+#ifdef WM_MBUTTONUP
+ case WM_MBUTTONUP:
+#endif
+#ifdef WM_RBUTTONDBLCLK
+ case WM_RBUTTONDBLCLK:
+#endif
+#ifdef WM_RBUTTONDOWN
+ case WM_RBUTTONDOWN:
+#endif
+#ifdef WM_RBUTTONUP
+ case WM_RBUTTONUP:
+#endif
+#ifdef WM_MOUSEMOVE
+ case WM_MOUSEMOVE:
+ {
+ QString vrtKeys = flagCheck(wParam,
+ FLGSTR(MK_CONTROL),
+ FLGSTR(MK_LBUTTON),
+ FLGSTR(MK_MBUTTON),
+ FLGSTR(MK_RBUTTON),
+ FLGSTR(MK_SHIFT),
+#ifdef MK_XBUTTON1
+ FLGSTR(MK_XBUTTON1),
+#endif
+#ifdef MK_XBUTTON2
+ FLGSTR(MK_XBUTTON2),
+#endif
+ FLAG_STRING());
+ parameters.sprintf("x,y(%4d,%4d) Virtual Keys(%s)", GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), vrtKeys.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_MOVE
+ case WM_MOVE:
+ parameters.sprintf("x,y(%4d,%4d)", LOWORD(lParam), HIWORD(lParam));
+ break;
+#endif
+#if defined(WM_PAINT) && defined(WM_ERASEBKGND)
+ case WM_ERASEBKGND:
+ case WM_PAINT:
+ parameters.sprintf("hdc(0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_QUERYNEWPALETTE
+ case WM_QUERYNEWPALETTE:
+ break; // lParam & wParam are unused
+#endif
+#ifdef WM_SETCURSOR
+ case WM_SETCURSOR:
+ {
+ QString mouseMsg = QString::fromLatin1(findWMstr(HIWORD(lParam)));
+ parameters.sprintf("HitTestCode(0x%x) MouseMsg(%s)", LOWORD(lParam), mouseMsg.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_SETFOCUS
+ case WM_SETFOCUS:
+ parameters.sprintf("Lost Focus (0x%p)", (void *)wParam);
+ break;
+#endif
+#ifdef WM_SETTEXT
+ case WM_SETTEXT:
+ parameters.sprintf("Set Text (%s)", QString((QChar*)lParam, (int)wcslen(reinterpret_cast<const wchar_t *>(lParam))).toLatin1().data()); //Unicode string
+ break;
+#endif
+#ifdef WM_SIZE
+ case WM_SIZE:
+ {
+ QString showMode = valueCheck(wParam,
+ FLGSTR(SIZE_MAXHIDE),
+ FLGSTR(SIZE_MAXIMIZED),
+ FLGSTR(SIZE_MAXSHOW),
+ FLGSTR(SIZE_MINIMIZED),
+ FLGSTR(SIZE_RESTORED),
+ FLAG_STRING());
+
+ parameters.sprintf("w,h(%4d,%4d) showmode(%s)", LOWORD(lParam), HIWORD(lParam), showMode.toLatin1().data());
+ }
+ break;
+#endif
+#ifdef WM_WINDOWPOSCHANGED
+ case WM_WINDOWPOSCHANGED:
+ {
+ LPWINDOWPOS winPos = (LPWINDOWPOS)lParam;
+ if (!winPos)
+ break;
+ QString hwndAfter = valueCheck(quint64(winPos->hwndInsertAfter),
+ FLAG_STRING((qptrdiff)HWND_BOTTOM, "HWND_BOTTOM"),
+ FLAG_STRING((qptrdiff)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
+ FLAG_STRING((qptrdiff)HWND_TOP, "HWND_TOP"),
+ FLAG_STRING((qptrdiff)HWND_TOPMOST, "HWND_TOPMOST"),
+ FLAG_STRING());
+ if (hwndAfter.isEmpty())
+ hwndAfter = QString::number((quintptr)winPos->hwndInsertAfter, 16);
+ QString flags = flagCheck(winPos->flags,
+ FLGSTR(SWP_DRAWFRAME),
+ FLGSTR(SWP_FRAMECHANGED),
+ FLGSTR(SWP_HIDEWINDOW),
+ FLGSTR(SWP_NOACTIVATE),
+#ifdef SWP_NOCOPYBITS
+ FLGSTR(SWP_NOCOPYBITS),
+#endif
+ FLGSTR(SWP_NOMOVE),
+ FLGSTR(SWP_NOOWNERZORDER),
+ FLGSTR(SWP_NOREDRAW),
+ FLGSTR(SWP_NOREPOSITION),
+#ifdef SWP_NOSENDCHANGING
+ FLGSTR(SWP_NOSENDCHANGING),
+#endif
+ FLGSTR(SWP_NOSIZE),
+ FLGSTR(SWP_NOZORDER),
+ FLGSTR(SWP_SHOWWINDOW),
+ FLAG_STRING());
+ parameters.sprintf("x,y(%4d,%4d) w,h(%4d,%4d) flags(%s) hwndAfter(%s)", winPos->x, winPos->y, winPos->cx, winPos->cy, flags.toLatin1().data(), hwndAfter.toLatin1().data());
+ }
+ break;
+#endif
+ default:
+ parameters.sprintf("wParam(0x%p) lParam(0x%p)", (void *)wParam, (void *)lParam);
+ break;
+ }
+ // Yes, we want to give the WM_ names 20 chars of space before showing the
+ // decoded message, since some of the common messages are quite long, and
+ // we don't want the decoded information to vary in output position
+ QString message = QString::fromLatin1("%1: ").arg(wmmsg, 20);
+ message += rawParameters;
+ message += parameters;
+ return message;
+}
+
+#endif
+
+QDebug operator<<(QDebug dbg, const MSG &msg)
+{
+ dbg << decodeMSG(msg);
+ return dbg.nospace();
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcorecmdlineargs_p.h b/src/corelib/kernel/qcorecmdlineargs_p.h
new file mode 100644
index 0000000000..cdde7828f7
--- /dev/null
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCORECMDLINEARGS_P_H
+#define QCORECMDLINEARGS_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 "QtCore/qstring.h"
+#include "QtCore/qstringlist.h"
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "QtCore/qvector.h"
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+# include "qt_windows.h"
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+// template implementation of the parsing algorithm
+// this is used from qcoreapplication_win.cpp and the tools (rcc, uic...)
+
+template<typename Char>
+static QVector<Char*> qWinCmdLine(Char *cmdParam, int length, int &argc)
+{
+ QVector<Char*> argv(8);
+ Char *p = cmdParam;
+ Char *p_end = p + length;
+
+ argc = 0;
+
+ while (*p && p < p_end) { // parse cmd line arguments
+ while (QChar((short)(*p)).isSpace()) // skip white space
+ p++;
+ if (*p && p < p_end) { // arg starts
+ int quote;
+ Char *start, *r;
+ if (*p == Char('\"') || *p == Char('\'')) { // " or ' quote
+ quote = *p;
+ start = ++p;
+ } else {
+ quote = 0;
+ start = p;
+ }
+ r = start;
+ while (*p && p < p_end) {
+ if (quote) {
+ if (*p == quote) {
+ p++;
+ if (QChar((short)(*p)).isSpace())
+ break;
+ quote = 0;
+ }
+ }
+ if (*p == '\\') { // escape char?
+ p++;
+ if (*p == Char('\"') || *p == Char('\''))
+ ; // yes
+ else
+ p--; // treat \ literally
+ } else {
+ if (!quote && (*p == Char('\"') || *p == Char('\''))) { // " or ' quote
+ quote = *p++;
+ continue;
+ } else if (QChar((short)(*p)).isSpace() && !quote)
+ break;
+ }
+ if (*p)
+ *r++ = *p++;
+ }
+ if (*p && p < p_end)
+ p++;
+ *r = Char('\0');
+
+ if (argc >= (int)argv.size()-1) // expand array
+ argv.resize(argv.size()*2);
+ argv[argc++] = start;
+ }
+ }
+ argv[argc] = 0;
+
+ return argv;
+}
+
+#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
+static inline QStringList qWinCmdArgs(QString cmdLine) // not const-ref: this might be modified
+{
+ QStringList args;
+
+ int argc = 0;
+ QVector<wchar_t*> argv = qWinCmdLine<wchar_t>((wchar_t *)cmdLine.utf16(), cmdLine.length(), argc);
+ for (int a = 0; a < argc; ++a) {
+ args << QString::fromWCharArray(argv[a]);
+ }
+
+ return args;
+}
+
+static inline QStringList qCmdLineArgs(int argc, char *argv[])
+{
+ Q_UNUSED(argc)
+ Q_UNUSED(argv)
+ QString cmdLine = QString::fromWCharArray(GetCommandLine());
+ return qWinCmdArgs(cmdLine);
+}
+#endif
+#else // !Q_OS_WIN || !Q_OS_SYMBIAN
+
+static inline QStringList qCmdLineArgs(int argc, char *argv[])
+{
+ QStringList args;
+ for (int i = 0; i != argc; ++i)
+ args += QString::fromLocal8Bit(argv[i]);
+ return args;
+}
+
+#endif // Q_OS_WIN || Q_OS_SYMBIAN
+
+QT_END_NAMESPACE
+
+#endif // QCORECMDLINEARGS_WIN_P_H
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
new file mode 100644
index 0000000000..fbb08faaf9
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -0,0 +1,612 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qcoreevent.h"
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+
+#include "qmutex.h"
+#include "qset.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEvent
+ \brief The QEvent class is the base class of all
+ event classes. Event objects contain event parameters.
+
+ \ingroup events
+
+ Qt's main event loop (QCoreApplication::exec()) fetches native
+ window system events from the event queue, translates them into
+ QEvents, and sends the translated events to \l{QObject}s.
+
+ In general, events come from the underlying window system
+ (spontaneous() returns true), but it is also possible to manually
+ send events using QCoreApplication::sendEvent() and
+ QCoreApplication::postEvent() (spontaneous() returns false).
+
+ QObjects receive events by having their QObject::event() function
+ called. The function can be reimplemented in subclasses to
+ customize event handling and add additional event types;
+ QWidget::event() is a notable example. By default, events are
+ dispatched to event handlers like QObject::timerEvent() and
+ QWidget::mouseMoveEvent(). QObject::installEventFilter() allows an
+ object to intercept events destined for another object.
+
+ The basic QEvent contains only an event type parameter and an
+ "accept" flag. The accept flag set with accept(), and cleared
+ with ignore(). It is set by default, but don't rely on this as
+ subclasses may choose to clear it in their constructor.
+
+ Subclasses of QEvent contain additional parameters that describe
+ the particular event.
+
+ \sa QObject::event(), QObject::installEventFilter(),
+ QWidget::event(), QCoreApplication::sendEvent(),
+ QCoreApplication::postEvent(), QCoreApplication::processEvents()
+*/
+
+
+/*!
+ \enum QEvent::Type
+
+ This enum type defines the valid event types in Qt. The event
+ types and the specialized classes for each type are as follows:
+
+ \value None Not an event.
+ \value AccessibilityDescription Used to query accessibility description texts (QAccessibleEvent).
+ \value AccessibilityHelp Used to query accessibility help texts (QAccessibleEvent).
+ \value AccessibilityPrepare Accessibility information is requested.
+ \value ActionAdded A new action has been added (QActionEvent).
+ \value ActionChanged An action has been changed (QActionEvent).
+ \value ActionRemoved An action has been removed (QActionEvent).
+ \value ActivationChange A widget's top-level window activation state has changed.
+ \value ApplicationActivate The application has been made available to the user.
+ \value ApplicationActivated This enum has been deprecated. Use ApplicationActivate instead.
+ \value ApplicationDeactivate The application has been suspended, and is unavailable to the user.
+ \value ApplicationFontChange The default application font has changed.
+ \value ApplicationLayoutDirectionChange The default application layout direction has changed.
+ \value ApplicationPaletteChange The default application palette has changed.
+ \value ApplicationWindowIconChange The application's icon has changed.
+ \value ChildAdded An object gets a child (QChildEvent).
+ \value ChildInserted An object gets a child (QChildEvent). Qt3Support only, use ChildAdded instead.
+ \value ChildPolished A widget child gets polished (QChildEvent).
+ \value ChildRemoved An object loses a child (QChildEvent).
+ \value Clipboard The clipboard contents have changed (QClipboardEvent).
+ \value Close Widget was closed (QCloseEvent).
+ \value CloseSoftwareInputPanel A widget wants to close the software input panel (SIP).
+ \value ContentsRectChange The margins of the widget's content rect changed.
+ \value ContextMenu Context popup menu (QContextMenuEvent).
+ \value CursorChange The widget's cursor has changed.
+ \value DeferredDelete The object will be deleted after it has cleaned up.
+ \value DragEnter The cursor enters a widget during a drag and drop operation (QDragEnterEvent).
+ \value DragLeave The cursor leaves a widget during a drag and drop operation (QDragLeaveEvent).
+ \value DragMove A drag and drop operation is in progress (QDragMoveEvent).
+ \value Drop A drag and drop operation is completed (QDropEvent).
+ \value EnabledChange Widget's enabled state has changed.
+ \value Enter Mouse enters widget's boundaries.
+ \value EnterEditFocus An editor widget gains focus for editing.
+ \value EnterWhatsThisMode Send to toplevel widgets when the application enters "What's This?" mode.
+ \value FileOpen File open request (QFileOpenEvent).
+ \value FocusIn Widget gains keyboard focus (QFocusEvent).
+ \value FocusOut Widget loses keyboard focus (QFocusEvent).
+ \value FontChange Widget's font has changed.
+ \value GrabKeyboard Item gains keyboard grab (QGraphicsItem only).
+ \value GrabMouse Item gains mouse grab (QGraphicsItem only).
+ \value GraphicsSceneContextMenu Context popup menu over a graphics scene (QGraphicsSceneContextMenuEvent).
+ \value GraphicsSceneDragEnter The cursor enters a graphics scene during a drag and drop operation (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneDragLeave The cursor leaves a graphics scene during a drag and drop operation (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneDragMove A drag and drop operation is in progress over a scene (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneDrop A drag and drop operation is completed over a scene (QGraphicsSceneDragDropEvent).
+ \value GraphicsSceneHelp The user requests help for a graphics scene (QHelpEvent).
+ \value GraphicsSceneHoverEnter The mouse cursor enters a hover item in a graphics scene (QGraphicsSceneHoverEvent).
+ \value GraphicsSceneHoverLeave The mouse cursor leaves a hover item in a graphics scene (QGraphicsSceneHoverEvent).
+ \value GraphicsSceneHoverMove The mouse cursor moves inside a hover item in a graphics scene (QGraphicsSceneHoverEvent).
+ \value GraphicsSceneMouseDoubleClick Mouse press again (double click) in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMouseMove Move mouse in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMousePress Mouse press in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMouseRelease Mouse release in a graphics scene (QGraphicsSceneMouseEvent).
+ \value GraphicsSceneMove Widget was moved (QGraphicsSceneMoveEvent).
+ \value GraphicsSceneResize Widget was resized (QGraphicsSceneResizeEvent).
+ \value GraphicsSceneWheel Mouse wheel rolled in a graphics scene (QGraphicsSceneWheelEvent).
+ \value Hide Widget was hidden (QHideEvent).
+ \value HideToParent A child widget has been hidden.
+ \value HoverEnter The mouse cursor enters a hover widget (QHoverEvent).
+ \value HoverLeave The mouse cursor leaves a hover widget (QHoverEvent).
+ \value HoverMove The mouse cursor moves inside a hover widget (QHoverEvent).
+ \value IconDrag The main icon of a window has been dragged away (QIconDragEvent).
+ \value IconTextChange Widget's icon text has been changed.
+ \value InputMethod An input method is being used (QInputMethodEvent).
+ \value KeyPress Key press (QKeyEvent).
+ \value KeyRelease Key release (QKeyEvent).
+ \value LanguageChange The application translation changed.
+ \value LayoutDirectionChange The direction of layouts changed.
+ \value LayoutRequest Widget layout needs to be redone.
+ \value Leave Mouse leaves widget's boundaries.
+ \value LeaveEditFocus An editor widget loses focus for editing.
+ \value LeaveWhatsThisMode Send to toplevel widgets when the application leaves "What's This?" mode.
+ \value LocaleChange The system locale has changed.
+ \value NonClientAreaMouseButtonDblClick A mouse double click occurred outside the client area.
+ \value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area.
+ \value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area.
+ \value NonClientAreaMouseMove A mouse move occurred outside the client area.
+ \value MacSizeChange The user changed his widget sizes (Mac OS X only).
+ \value MenubarUpdated The window's menu bar has been updated.
+ \value MetaCall An asynchronous method invocation via QMetaObject::invokeMethod().
+ \value ModifiedChange Widgets modification state has been changed.
+ \value MouseButtonDblClick Mouse press again (QMouseEvent).
+ \value MouseButtonPress Mouse press (QMouseEvent).
+ \value MouseButtonRelease Mouse release (QMouseEvent).
+ \value MouseMove Mouse move (QMouseEvent).
+ \value MouseTrackingChange The mouse tracking state has changed.
+ \value Move Widget's position changed (QMoveEvent).
+ \value Paint Screen update necessary (QPaintEvent).
+ \value PaletteChange Palette of the widget changed.
+ \value ParentAboutToChange The widget parent is about to change.
+ \value ParentChange The widget parent has changed.
+ \value Polish The widget is polished.
+ \value PolishRequest The widget should be polished.
+ \value QueryWhatsThis The widget should accept the event if it has "What's This?" help.
+ \value RequestSoftwareInputPanel A widget wants to open a software input panel (SIP).
+ \value Resize Widget's size changed (QResizeEvent).
+ \value Shortcut Key press in child for shortcut key handling (QShortcutEvent).
+ \value ShortcutOverride Key press in child, for overriding shortcut key handling (QKeyEvent).
+ \value Show Widget was shown on screen (QShowEvent).
+ \value ShowToParent A child widget has been shown.
+ \value SockAct Socket activated, used to implement QSocketNotifier.
+ \value StateMachineSignal A signal delivered to a state machine (QStateMachine::SignalEvent).
+ \value StateMachineWrapped The event is a wrapper for, i.e., contains, another event (QStateMachine::WrappedEvent).
+ \value StatusTip A status tip is requested (QStatusTipEvent).
+ \value StyleChange Widget's style has been changed.
+ \value TabletMove Wacom tablet move (QTabletEvent).
+ \value TabletPress Wacom tablet press (QTabletEvent).
+ \value TabletRelease Wacom tablet release (QTabletEvent).
+ \value OkRequest Ok button in decoration pressed. Supported only for Windows CE.
+ \value TabletEnterProximity Wacom tablet enter proximity event (QTabletEvent), sent to QApplication.
+ \value TabletLeaveProximity Wacom tablet leave proximity event (QTabletEvent), sent to QApplication.
+ \value Timer Regular timer events (QTimerEvent).
+ \value ToolBarChange The toolbar button is toggled on Mac OS X.
+ \value ToolTip A tooltip was requested (QHelpEvent).
+ \value ToolTipChange The widget's tooltip has changed.
+ \value UngrabKeyboard Item loses keyboard grab (QGraphicsItem only).
+ \value UngrabMouse Item loses mouse grab (QGraphicsItem only).
+ \value UpdateLater The widget should be queued to be repainted at a later time.
+ \value UpdateRequest The widget should be repainted.
+ \value WhatsThis The widget should reveal "What's This?" help (QHelpEvent).
+ \value WhatsThisClicked A link in a widget's "What's This?" help was clicked.
+ \value Wheel Mouse wheel rolled (QWheelEvent).
+ \value WinEventAct A Windows-specific activation event has occurred.
+ \value WindowActivate Window was activated.
+ \value WindowBlocked The window is blocked by a modal dialog.
+ \value WindowDeactivate Window was deactivated.
+ \value WindowIconChange The window's icon has changed.
+ \value WindowStateChange The \l{QWidget::windowState()}{window's state} (minimized, maximized or full-screen) has changed (QWindowStateChangeEvent).
+ \value WindowTitleChange The window title has changed.
+ \value WindowUnblocked The window is unblocked after a modal dialog exited.
+ \value ZOrderChange The widget's z-order has changed. This event is never sent to top level windows.
+ \value KeyboardLayoutChange The keyboard layout has changed.
+ \value DynamicPropertyChange A dynamic property was added, changed or removed from the object.
+ \value TouchBegin Beginning of a sequence of touch-screen and/or track-pad events (QTouchEvent)
+ \value TouchUpdate Touch-screen event (QTouchEvent)
+ \value TouchEnd End of touch-event sequence (QTouchEvent)
+ \value WinIdChange The window system identifer for this native widget has changed
+ \value Gesture A gesture was triggered (QGestureEvent)
+ \value GestureOverride A gesture override was triggered (QGestureEvent)
+ \value ScrollPrepare The object needs to fill in its geometry information (QScrollPrepareEvent)
+ \value Scroll The object needs to scroll to the supplied position (QScrollEvent)
+
+ User events should have values between \c User and \c{MaxUser}:
+
+ \value User User-defined event.
+ \value MaxUser Last user event ID.
+
+ For convenience, you can use the registerEventType() function to
+ register and reserve a custom event type for your
+ application. Doing so will allow you to avoid accidentally
+ re-using a custom event type already in use elsewhere in your
+ application.
+
+ \omitvalue Accel
+ \omitvalue AccelAvailable
+ \omitvalue AccelOverride
+ \omitvalue AcceptDropsChange
+ \omitvalue ActivateControl
+ \omitvalue CaptionChange
+ \omitvalue ChildInsertedRequest
+ \omitvalue ChildInserted
+ \omitvalue Create
+ \omitvalue DeactivateControl
+ \omitvalue Destroy
+ \omitvalue DragResponse
+ \omitvalue EmbeddingControl
+ \omitvalue HelpRequest
+ \omitvalue IconChange
+ \omitvalue LayoutHint
+ \omitvalue Quit
+ \omitvalue Reparent
+ \omitvalue ShowWindowRequest
+ \omitvalue Speech
+ \omitvalue Style
+ \omitvalue ThreadChange
+ \omitvalue ZeroTimerEvent
+ \omitvalue ApplicationActivated
+ \omitvalue ApplicationDeactivated
+ \omitvalue MacGLWindowChange
+ \omitvalue MacGLClearDrawable
+ \omitvalue NetworkReplyUpdated
+ \omitvalue FutureCallOut
+ \omitvalue UpdateSoftKeys
+ \omitvalue NativeGesture
+*/
+
+/*!
+ Contructs an event object of type \a type.
+*/
+QEvent::QEvent(Type type)
+ : d(0), t(type), posted(false), spont(false), m_accept(true)
+{}
+
+/*!
+ Destroys the event. If it was \link
+ QCoreApplication::postEvent() posted \endlink,
+ it will be removed from the list of events to be posted.
+*/
+
+QEvent::~QEvent()
+{
+ if (posted && QCoreApplication::instance())
+ QCoreApplicationPrivate::removePostedEvent(this);
+}
+
+
+/*!
+ \property QEvent::accepted
+ the accept flag of the event object
+
+ Setting the accept parameter indicates that the event receiver
+ wants the event. Unwanted events might be propagated to the parent
+ widget. By default, isAccepted() is set to true, but don't rely on
+ this as subclasses may choose to clear it in their constructor.
+
+ For convenience, the accept flag can also be set with accept(),
+ and cleared with ignore().
+*/
+
+/*!
+ \fn void QEvent::accept()
+
+ Sets the accept flag of the event object, the equivalent of
+ calling setAccepted(true).
+
+ Setting the accept parameter indicates that the event receiver
+ wants the event. Unwanted events might be propagated to the parent
+ widget.
+
+ \sa ignore()
+*/
+
+
+/*!
+ \fn void QEvent::ignore()
+
+ Clears the accept flag parameter of the event object, the
+ equivalent of calling setAccepted(false).
+
+ Clearing the accept parameter indicates that the event receiver
+ does not want the event. Unwanted events might be propagated to the
+ parent widget.
+
+ \sa accept()
+*/
+
+
+/*!
+ \fn QEvent::Type QEvent::type() const
+
+ Returns the event type.
+*/
+
+/*!
+ \fn bool QEvent::spontaneous() const
+
+ Returns true if the event originated outside the application (a
+ system event); otherwise returns false.
+
+ The return value of this function is not defined for paint events.
+*/
+
+class QEventUserEventRegistration
+{
+public:
+ QMutex mutex;
+ QSet<int> set;
+};
+Q_GLOBAL_STATIC(QEventUserEventRegistration, userEventRegistrationHelper)
+
+/*!
+ \since 4.4
+ \threadsafe
+
+ Registers and returns a custom event type. The \a hint provided
+ will be used if it is available, otherwise it will return a value
+ between QEvent::User and QEvent::MaxUser that has not yet been
+ registered. The \a hint is ignored if its value is not between
+ QEvent::User and QEvent::MaxUser.
+*/
+int QEvent::registerEventType(int hint)
+{
+ QEventUserEventRegistration *userEventRegistration
+ = userEventRegistrationHelper();
+ if (!userEventRegistration)
+ return -1;
+
+ QMutexLocker locker(&userEventRegistration->mutex);
+
+ // if the type hint hasn't been registered yet, take it
+ if (hint >= QEvent::User && hint <= QEvent::MaxUser && !userEventRegistration->set.contains(hint)) {
+ userEventRegistration->set.insert(hint);
+ return hint;
+ }
+
+ // find a free event type, starting at MaxUser and decreasing
+ int id = QEvent::MaxUser;
+ while (userEventRegistration->set.contains(id) && id >= QEvent::User)
+ --id;
+ if (id >= QEvent::User) {
+ userEventRegistration->set.insert(id);
+ return id;
+ }
+ return -1;
+}
+
+/*!
+ \class QTimerEvent
+ \brief The QTimerEvent class contains parameters that describe a
+ timer event.
+
+ \ingroup events
+
+ Timer events are sent at regular intervals to objects that have
+ started one or more timers. Each timer has a unique identifier. A
+ timer is started with QObject::startTimer().
+
+ The QTimer class provides a high-level programming interface that
+ uses signals instead of events. It also provides single-shot timers.
+
+ The event handler QObject::timerEvent() receives timer events.
+
+ \sa QTimer, QObject::timerEvent(), QObject::startTimer(),
+ QObject::killTimer()
+*/
+
+/*!
+ Constructs a timer event object with the timer identifier set to
+ \a timerId.
+*/
+QTimerEvent::QTimerEvent(int timerId)
+ : QEvent(Timer), id(timerId)
+{}
+
+/*! \internal
+*/
+QTimerEvent::~QTimerEvent()
+{
+}
+
+/*!
+ \fn int QTimerEvent::timerId() const
+
+ Returns the unique timer identifier, which is the same identifier
+ as returned from QObject::startTimer().
+*/
+
+/*!
+ \class QChildEvent
+ \brief The QChildEvent class contains event parameters for child object
+ events.
+
+ \ingroup events
+
+ Child events are sent immediately to objects when children are
+ added or removed.
+
+ In both cases you can only rely on the child being a QObject (or,
+ if QObject::isWidgetType() returns true, a QWidget). This is
+ because in the QEvent::ChildAdded case the child is not yet fully
+ constructed; in the QEvent::ChildRemoved case it might have
+ already been destructed.
+
+ The handler for these events is QObject::childEvent().
+*/
+
+/*!
+ Constructs a child event object of a particular \a type for the
+ \a child.
+
+ \a type can be QEvent::ChildAdded, QEvent::ChildRemoved,
+ QEvent::ChildPolished, or QEvent::ChildRemoved.
+
+ \sa child()
+*/
+QChildEvent::QChildEvent(Type type, QObject *child)
+ : QEvent(type), c(child)
+{}
+
+/*! \internal
+*/
+QChildEvent::~QChildEvent()
+{
+}
+
+/*!
+ \fn QObject *QChildEvent::child() const
+
+ Returns the child object that was added or removed.
+*/
+
+/*!
+ \fn bool QChildEvent::added() const
+
+ Returns true if type() is QEvent::ChildAdded; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QChildEvent::removed() const
+
+ Returns true if type() is QEvent::ChildRemoved; otherwise returns
+ false.
+*/
+
+/*!
+ \fn bool QChildEvent::polished() const
+
+ Returns true if type() is QEvent::ChildPolished; otherwise returns
+ false.
+*/
+
+/*!
+ \class QCustomEvent
+ \brief The QCustomEvent class provides support for custom events.
+
+ \compat
+
+ QCustomEvent has a \c{void *} that can be used to store custom
+ data.
+
+ In Qt 3, QObject::customEvent() took a QCustomEvent pointer. We
+ found out that this approach was unsatisfactory, because
+ there was often no safe way of deleting the data held in the
+ \c{void *}.
+
+ In Qt 4, QObject::customEvent() takes a plain QEvent pointer.
+ You can add custom data by subclassing.
+
+ \sa QObject::customEvent(), QCoreApplication::notify()
+*/
+
+/*!
+ \fn QCustomEvent::QCustomEvent(int type, void *data)
+
+ Constructs a custom event object with the event \a type and a
+ pointer to \a data. The value of \a type must be at least as
+ large as QEvent::User. By default, the data pointer is set to 0.
+*/
+#ifdef QT3_SUPPORT
+QCustomEvent::QCustomEvent(int type, void *data)
+ : QEvent(static_cast<Type>(type))
+{
+ d = reinterpret_cast<QEventPrivate *>(data);
+}
+
+/*! \internal
+*/
+QCustomEvent::~QCustomEvent()
+{
+}
+#endif
+/*!
+ \fn void QCustomEvent::setData(void *data)
+
+ \compat
+
+ Sets the generic data pointer to \a data.
+
+ \sa data()
+*/
+
+/*!
+ \fn void *QCustomEvent::data() const
+
+ \compat
+
+ Returns a pointer to the generic event data.
+
+ \sa setData()
+*/
+
+/*!
+ \fn bool QChildEvent::inserted() const
+
+ \compat
+
+ A child has been inserted if the event's type() is ChildInserted.
+*/
+
+/*!
+ \class QDynamicPropertyChangeEvent
+ \since 4.2
+ \brief The QDynamicPropertyChangeEvent class contains event parameters for dynamic
+ property change events.
+
+ \ingroup events
+
+ Dynamic property change events are sent to objects when properties are
+ dynamically added, changed or removed using QObject::setProperty().
+*/
+
+/*!
+ Constructs a dynamic property change event object with the property name set to
+ \a name.
+*/
+QDynamicPropertyChangeEvent::QDynamicPropertyChangeEvent(const QByteArray &name)
+ : QEvent(QEvent::DynamicPropertyChange), n(name)
+{
+}
+
+/*!
+ \internal
+*/
+QDynamicPropertyChangeEvent::~QDynamicPropertyChangeEvent()
+{
+}
+
+/*!
+ \fn QByteArray QDynamicPropertyChangeEvent::propertyName() const
+
+ Returns the name of the dynamic property that was added, changed or
+ removed.
+
+ \sa QObject::setProperty(), QObject::dynamicPropertyNames()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
new file mode 100644
index 0000000000..c9d311ae35
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent.h
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCOREEVENT_H
+#define QCOREEVENT_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEventPrivate;
+class Q_CORE_EXPORT QEvent // event base class
+{
+ Q_GADGET
+ QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ Q_ENUMS(Type)
+public:
+ enum Type {
+ /*
+ If you get a strange compiler error on the line with None,
+ it's probably because you're also including X11 headers,
+ which #define the symbol None. Put the X11 includes after
+ the Qt includes to solve this problem.
+ */
+ None = 0, // invalid event
+ Timer = 1, // timer event
+ MouseButtonPress = 2, // mouse button pressed
+ MouseButtonRelease = 3, // mouse button released
+ MouseButtonDblClick = 4, // mouse button double click
+ MouseMove = 5, // mouse move
+ KeyPress = 6, // key pressed
+ KeyRelease = 7, // key released
+ FocusIn = 8, // keyboard focus received
+ FocusOut = 9, // keyboard focus lost
+ Enter = 10, // mouse enters widget
+ Leave = 11, // mouse leaves widget
+ Paint = 12, // paint widget
+ Move = 13, // move widget
+ Resize = 14, // resize widget
+ Create = 15, // after widget creation
+ Destroy = 16, // during widget destruction
+ Show = 17, // widget is shown
+ Hide = 18, // widget is hidden
+ Close = 19, // request to close widget
+ Quit = 20, // request to quit application
+ ParentChange = 21, // widget has been reparented
+ ParentAboutToChange = 131, // sent just before the parent change is done
+#ifdef QT3_SUPPORT
+ Reparent = ParentChange,
+#endif
+ ThreadChange = 22, // object has changed threads
+ WindowActivate = 24, // window was activated
+ WindowDeactivate = 25, // window was deactivated
+ ShowToParent = 26, // widget is shown to parent
+ HideToParent = 27, // widget is hidden to parent
+ Wheel = 31, // wheel event
+ WindowTitleChange = 33, // window title changed
+ WindowIconChange = 34, // icon changed
+ ApplicationWindowIconChange = 35, // application icon changed
+ ApplicationFontChange = 36, // application font changed
+ ApplicationLayoutDirectionChange = 37, // application layout direction changed
+ ApplicationPaletteChange = 38, // application palette changed
+ PaletteChange = 39, // widget palette changed
+ Clipboard = 40, // internal clipboard event
+ Speech = 42, // reserved for speech input
+ MetaCall = 43, // meta call event
+ SockAct = 50, // socket activation
+ WinEventAct = 132, // win event activation
+ DeferredDelete = 52, // deferred delete event
+ DragEnter = 60, // drag moves into widget
+ DragMove = 61, // drag moves in widget
+ DragLeave = 62, // drag leaves or is cancelled
+ Drop = 63, // actual drop
+ DragResponse = 64, // drag accepted/rejected
+ ChildAdded = 68, // new child widget
+ ChildPolished = 69, // polished child widget
+#ifdef QT3_SUPPORT
+ ChildInsertedRequest = 67, // send ChildInserted compatibility events to receiver
+ ChildInserted = 70, // compatibility child inserted
+ LayoutHint = 72, // compatibility relayout request
+#endif
+ ChildRemoved = 71, // deleted child widget
+ ShowWindowRequest = 73, // widget's window should be mapped
+ PolishRequest = 74, // widget should be polished
+ Polish = 75, // widget is polished
+ LayoutRequest = 76, // widget should be relayouted
+ UpdateRequest = 77, // widget should be repainted
+ UpdateLater = 78, // request update() later
+
+ EmbeddingControl = 79, // ActiveX embedding
+ ActivateControl = 80, // ActiveX activation
+ DeactivateControl = 81, // ActiveX deactivation
+ ContextMenu = 82, // context popup menu
+ InputMethod = 83, // input method
+ AccessibilityPrepare = 86, // accessibility information is requested
+ TabletMove = 87, // Wacom tablet event
+ LocaleChange = 88, // the system locale changed
+ LanguageChange = 89, // the application language changed
+ LayoutDirectionChange = 90, // the layout direction changed
+ Style = 91, // internal style event
+ TabletPress = 92, // tablet press
+ TabletRelease = 93, // tablet release
+ OkRequest = 94, // CE (Ok) button pressed
+ HelpRequest = 95, // CE (?) button pressed
+
+ IconDrag = 96, // proxy icon dragged
+
+ FontChange = 97, // font has changed
+ EnabledChange = 98, // enabled state has changed
+ ActivationChange = 99, // window activation has changed
+ StyleChange = 100, // style has changed
+ IconTextChange = 101, // icon text has changed
+ ModifiedChange = 102, // modified state has changed
+ MouseTrackingChange = 109, // mouse tracking state has changed
+
+ WindowBlocked = 103, // window is about to be blocked modally
+ WindowUnblocked = 104, // windows modal blocking has ended
+ WindowStateChange = 105,
+
+ ToolTip = 110,
+ WhatsThis = 111,
+ StatusTip = 112,
+
+ ActionChanged = 113,
+ ActionAdded = 114,
+ ActionRemoved = 115,
+
+ FileOpen = 116, // file open request
+
+ Shortcut = 117, // shortcut triggered
+ ShortcutOverride = 51, // shortcut override request
+
+#ifdef QT3_SUPPORT
+ Accel = 30, // accelerator event
+ AccelAvailable = 32, // accelerator available event
+ AccelOverride = ShortcutOverride, // accelerator override event
+#endif
+
+ WhatsThisClicked = 118,
+
+#ifdef QT3_SUPPORT
+ CaptionChange = WindowTitleChange,
+ IconChange = WindowIconChange,
+#endif
+ ToolBarChange = 120, // toolbar visibility toggled
+
+ ApplicationActivate = 121, // application has been changed to active
+ ApplicationActivated = ApplicationActivate, // deprecated
+ ApplicationDeactivate = 122, // application has been changed to inactive
+ ApplicationDeactivated = ApplicationDeactivate, // deprecated
+
+ QueryWhatsThis = 123, // query what's this widget help
+ EnterWhatsThisMode = 124,
+ LeaveWhatsThisMode = 125,
+
+ ZOrderChange = 126, // child widget has had its z-order changed
+
+ HoverEnter = 127, // mouse cursor enters a hover widget
+ HoverLeave = 128, // mouse cursor leaves a hover widget
+ HoverMove = 129, // mouse cursor move inside a hover widget
+
+ AccessibilityHelp = 119, // accessibility help text request
+ AccessibilityDescription = 130, // accessibility description text request
+
+ // last event id used = 132
+
+#ifdef QT_KEYPAD_NAVIGATION
+ EnterEditFocus = 150, // enter edit mode in keypad navigation
+ LeaveEditFocus = 151, // enter edit mode in keypad navigation
+#endif
+ AcceptDropsChange = 152,
+
+ MenubarUpdated = 153, // Support event for Q3MainWindow, which needs to
+ // knwow when QMenubar is updated.
+
+ ZeroTimerEvent = 154, // Used for Windows Zero timer events
+
+ GraphicsSceneMouseMove = 155, // GraphicsView
+ GraphicsSceneMousePress = 156,
+ GraphicsSceneMouseRelease = 157,
+ GraphicsSceneMouseDoubleClick = 158,
+ GraphicsSceneContextMenu = 159,
+ GraphicsSceneHoverEnter = 160,
+ GraphicsSceneHoverMove = 161,
+ GraphicsSceneHoverLeave = 162,
+ GraphicsSceneHelp = 163,
+ GraphicsSceneDragEnter = 164,
+ GraphicsSceneDragMove = 165,
+ GraphicsSceneDragLeave = 166,
+ GraphicsSceneDrop = 167,
+ GraphicsSceneWheel = 168,
+
+ KeyboardLayoutChange = 169, // keyboard layout changed
+
+ DynamicPropertyChange = 170, // A dynamic property was changed through setProperty/property
+
+ TabletEnterProximity = 171,
+ TabletLeaveProximity = 172,
+
+ NonClientAreaMouseMove = 173,
+ NonClientAreaMouseButtonPress = 174,
+ NonClientAreaMouseButtonRelease = 175,
+ NonClientAreaMouseButtonDblClick = 176,
+
+ MacSizeChange = 177, // when the Qt::WA_Mac{Normal,Small,Mini}Size changes
+
+ ContentsRectChange = 178, // sent by QWidget::setContentsMargins (internal)
+
+ MacGLWindowChange = 179, // Internal! the window of the GLWidget has changed
+
+ FutureCallOut = 180,
+
+ GraphicsSceneResize = 181,
+ GraphicsSceneMove = 182,
+
+ CursorChange = 183,
+ ToolTipChange = 184,
+
+ NetworkReplyUpdated = 185, // Internal for QNetworkReply
+
+ GrabMouse = 186,
+ UngrabMouse = 187,
+ GrabKeyboard = 188,
+ UngrabKeyboard = 189,
+ MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear
+
+ StateMachineSignal = 192,
+ StateMachineWrapped = 193,
+
+ TouchBegin = 194,
+ TouchUpdate = 195,
+ TouchEnd = 196,
+
+#ifndef QT_NO_GESTURES
+ NativeGesture = 197, // Internal for platform gesture support
+#endif
+ RequestSoftwareInputPanel = 199,
+ CloseSoftwareInputPanel = 200,
+
+ UpdateSoftKeys = 201, // Internal for compressing soft key updates
+
+ WinIdChange = 203,
+#ifndef QT_NO_GESTURES
+ Gesture = 198,
+ GestureOverride = 202,
+#endif
+ ScrollPrepare = 204,
+ Scroll = 205,
+
+ // 512 reserved for Qt Jambi's MetaCall event
+ // 513 reserved for Qt Jambi's DeleteOnMainThread event
+
+ User = 1000, // first user event id
+ MaxUser = 65535 // last user event id
+ };
+
+ QEvent(Type type);
+ virtual ~QEvent();
+ inline Type type() const { return static_cast<Type>(t); }
+ inline bool spontaneous() const { return spont; }
+
+ inline void setAccepted(bool accepted) { m_accept = accepted; }
+ inline bool isAccepted() const { return m_accept; }
+
+ inline void accept() { m_accept = true; }
+ inline void ignore() { m_accept = false; }
+
+ static int registerEventType(int hint = -1);
+
+protected:
+ QEventPrivate *d;
+ ushort t;
+
+private:
+ ushort posted : 1;
+ ushort spont : 1;
+ ushort m_accept : 1;
+ ushort reserved : 13;
+
+ friend class QCoreApplication;
+ friend class QCoreApplicationPrivate;
+ friend class QThreadData;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class Q3AccelManager;
+ friend class QShortcutMap;
+ friend class QETWidget;
+ friend class QGraphicsView;
+ friend class QGraphicsViewPrivate;
+ friend class QGraphicsScene;
+ friend class QGraphicsScenePrivate;
+#ifndef QT_NO_GESTURES
+ friend class QGestureManager;
+#endif
+};
+
+class Q_CORE_EXPORT QTimerEvent : public QEvent
+{
+public:
+ QTimerEvent( int timerId );
+ ~QTimerEvent();
+ int timerId() const { return id; }
+protected:
+ int id;
+};
+
+class QObject;
+
+class Q_CORE_EXPORT QChildEvent : public QEvent
+{
+public:
+ QChildEvent( Type type, QObject *child );
+ ~QChildEvent();
+ QObject *child() const { return c; }
+ bool added() const { return type() == ChildAdded; }
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT bool inserted() const { return type() == ChildInserted; }
+#endif
+ bool polished() const { return type() == ChildPolished; }
+ bool removed() const { return type() == ChildRemoved; }
+protected:
+ QObject *c;
+};
+
+#ifdef QT3_SUPPORT
+class Q_CORE_EXPORT QCustomEvent : public QEvent
+{
+public:
+ QT3_SUPPORT_CONSTRUCTOR QCustomEvent(int type, void *data = 0);
+ ~QCustomEvent();
+ QT3_SUPPORT void *data() const { return d; }
+ QT3_SUPPORT void setData(void* aData) { d = reinterpret_cast<QEventPrivate *>(aData); }
+};
+#endif
+
+class Q_CORE_EXPORT QDynamicPropertyChangeEvent : public QEvent
+{
+public:
+ QDynamicPropertyChangeEvent(const QByteArray &name);
+ ~QDynamicPropertyChangeEvent();
+
+ inline QByteArray propertyName() const { return n; }
+
+private:
+ QByteArray n;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCOREEVENT_H
diff --git a/src/corelib/kernel/qcoreglobaldata.cpp b/src/corelib/kernel/qcoreglobaldata.cpp
new file mode 100644
index 0000000000..d90b46cb26
--- /dev/null
+++ b/src/corelib/kernel/qcoreglobaldata.cpp
@@ -0,0 +1,53 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qcoreglobaldata_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QCoreGlobalData, globalInstance)
+
+QCoreGlobalData *QCoreGlobalData::instance()
+{
+ return globalInstance();
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreglobaldata_p.h b/src/corelib/kernel/qcoreglobaldata_p.h
new file mode 100644
index 0000000000..aeb7bd8840
--- /dev/null
+++ b/src/corelib/kernel/qcoreglobaldata_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCOREGLOBALDATA_P_H
+#define QCOREGLOBALDATA_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 "QtCore/qmap.h"
+#include "QtCore/qstringlist.h"
+#include "QtCore/qreadwritelock.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QCoreGlobalData {
+ QMap<QString, QStringList> dirSearchPaths;
+ QReadWriteLock dirSearchPathsLock;
+
+ static QCoreGlobalData *instance();
+};
+
+
+QT_END_NAMESPACE
+#endif // QCOREGLOBALDATA_P_H
+
diff --git a/src/corelib/kernel/qcrashhandler.cpp b/src/corelib/kernel/qcrashhandler.cpp
new file mode 100644
index 0000000000..fbdbac0b5c
--- /dev/null
+++ b/src/corelib/kernel/qcrashhandler.cpp
@@ -0,0 +1,423 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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$
+**
+****************************************************************************/
+
+/*************************************************************************
+ *
+ * stacktrace.c 1.2 1998/12/21
+ *
+ * Copyright (c) 1998 by Bjorn Reese <breese@imada.ou.dk>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS AND
+ * CONTRIBUTORS ACCEPT NO RESPONSIBILITY IN ANY CONCEIVABLE MANNER.
+ *
+ ************************************************************************/
+
+#include "qplatformdefs.h"
+#include "private/qcrashhandler_p.h"
+#include "qbytearray.h" // for qvsnprintf()
+
+#ifndef QT_NO_CRASHHANDLER
+
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+QtCrashHandler QSegfaultHandler::callback = 0;
+
+#if defined(__GLIBC__) && (__GLIBC__ >= 2) && !defined(__UCLIBC__) && !defined(QT_LINUXBASE)
+QT_BEGIN_INCLUDE_NAMESPACE
+# include "qstring.h"
+# include <execinfo.h>
+QT_END_INCLUDE_NAMESPACE
+
+static void print_backtrace(FILE *outb)
+{
+ void *stack[128];
+ int stack_size = backtrace(stack, sizeof(stack) / sizeof(void *));
+ char **stack_symbols = backtrace_symbols(stack, stack_size);
+ fprintf(outb, "Stack [%d]:\n", stack_size);
+ if(FILE *cppfilt = popen("c++filt", "rw")) {
+ dup2(fileno(outb), fileno(cppfilt));
+ for(int i = stack_size-1; i>=0; --i)
+ fwrite(stack_symbols[i], 1, strlen(stack_symbols[i]), cppfilt);
+ pclose(cppfilt);
+ } else {
+ for(int i = stack_size-1; i>=0; --i)
+ fprintf(outb, "#%d %p [%s]\n", i, stack[i], stack_symbols[i]);
+ }
+}
+static void init_backtrace(char **, int)
+{
+}
+
+#else /* Don't use the GLIBC callback */
+/* Code sourced from: */
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#if defined(Q_OS_IRIX) && defined(USE_LIBEXC)
+# include <libexc.h>
+#endif
+QT_END_INCLUDE_NAMESPACE
+
+
+static char *globalProgName = NULL;
+static bool backtrace_command(FILE *outb, const char *format, ...)
+{
+
+ bool ret = false;
+ char buffer[50];
+
+ /*
+ * Please note that vsnprintf() is not ASync safe (ie. cannot safely
+ * be used from a signal handler.) If this proves to be a problem
+ * then the cmd string can be built by more basic functions such as
+ * strcpy, strcat, and a home-made integer-to-ascii function.
+ */
+ va_list args;
+ char cmd[512];
+ va_start(args, format);
+ qvsnprintf(cmd, 512, format, args);
+ va_end(args);
+
+ char *foo = cmd;
+#if 0
+ foo = "echo hi";
+#endif
+ if(FILE *inb = popen(foo, "r")) {
+ while(!feof(inb)) {
+ int len = fread(buffer, 1, sizeof(buffer), inb);
+ if(!len)
+ break;
+ if(!ret) {
+ fwrite("Output from ", 1, strlen("Output from "), outb);
+ strtok(cmd, " ");
+ fwrite(cmd, 1, strlen(cmd), outb);
+ fwrite("\n", 1, 1, outb);
+ ret = true;
+ }
+ fwrite(buffer, 1, len, outb);
+ }
+ fclose(inb);
+ }
+ return ret;
+}
+
+static void init_backtrace(char **argv, int argc)
+{
+ if(argc >= 1)
+ globalProgName = argv[0];
+}
+
+static void print_backtrace(FILE *outb)
+{
+ /*
+ * In general dbx seems to do a better job than gdb.
+ *
+ * Different dbx implementations require different flags/commands.
+ */
+#if defined(Q_OS_AIX)
+ if(backtrace_command(outb, "dbx -a %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "EOF\n",
+ (int)getpid()))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_FREEBSD)
+ /*
+ * FreeBSD insists on sending a SIGSTOP to the process we
+ * attach to, so we let the debugger send a SIGCONT to that
+ * process after we have detached.
+ */
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "shell kill -CONT %d\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid(), (int)getpid()))
+ return;
+#elif defined(Q_OS_HPUX)
+ /*
+ * HP decided to call their debugger xdb.
+ *
+ * This does not seem to work properly yet. The debugger says
+ * "Note: Stack traces may not be possible until you are
+ * stopped in user code." on HP-UX 09.01
+ *
+ * -L = line-oriented interface.
+ * "T [depth]" gives a stacktrace with local variables.
+ * The final "y" is confirmation to the quit command.
+ */
+ if(backtrace_command(outb, "xdb -P %d -L %s 2>&1 <<EOF\n"
+ "T 50\n"
+ "q\ny\n"
+ "EOF\n",
+ (int)getpid(), globalProgName))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_IRIX)
+ /*
+ * "set $page=0" drops hold mode
+ * "dump ." displays the contents of the variables
+ */
+ if(backtrace_command(outb, "dbx -p %d 2>/dev/null <<EOF\n"
+ "set \\$page=0\n"
+ "where\n"
+# if !defined(__GNUC__)
+ /* gcc does not generate this information */
+ "dump .\n"
+# endif
+ "detach\n"
+ "EOF\n",
+ (int)getpid()))
+ return;
+
+# if defined(USE_LIBEXC)
+ if(trace_back_stack_and_print())
+ return;
+# endif
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "echo ---\\n\n"
+ "frame 5\n" /* Skip signal handler frames */
+ "set \\$x = 50\n"
+ "while (\\$x)\n" /* Print local variables for each frame */
+ "info locals\n"
+ "up\n"
+ "set \\$x--\n"
+ "end\n"
+ "echo ---\\n\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_OSF)
+ if(backtrace_command(outb, "dbx -pid %d %s 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ (int)getpid(), globalProgName))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_SCO)
+ /*
+ * SCO OpenServer dbx is like a catch-22. The 'detach' command
+ * depends on whether ptrace(S) support detaching or not. If it
+ * is supported then 'detach' must be used, otherwise the process
+ * will be killed upon dbx exit. If it isn't supported then 'detach'
+ * will cause the process to be killed. We do not want it to be
+ * killed.
+ *
+ * Out of two evils, the omission of 'detach' was chosen because
+ * it worked on our system.
+ */
+ if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "quit\nEOF\n",
+ globalProgName, (int)getpid()))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_SOLARIS)
+ if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+ "echo ---\\n\n"
+ "frame 5\n" /* Skip signal handler frames */
+ "set \\$x = 50\n"
+ "while (\\$x)\n" /* Print local variables for each frame */
+ "info locals\n"
+ "up\n"
+ "set \\$x--\n"
+ "end\n"
+ "echo ---\\n\n"
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+ if(backtrace_command(outb, "/usr/proc/bin/pstack %d",
+ (int)getpid()))
+ return;
+ /*
+ * Other Unices (AIX, HPUX, SCO) also have adb, but
+ * they seem unable to attach to a running process.)
+ */
+ if(backtrace_command(outb, "adb %s 2>&1 <<EOF\n"
+ "0t%d:A\n" /* Attach to pid */
+ "\\$c\n" /* print stacktrace */
+ ":R\n" /* Detach */
+ "\\$q\n" /* Quit */
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#elif defined(Q_OS_INTEGRITY)
+ /* abort */
+ CheckSuccess(Failure);
+#else /* All other platforms */
+ /*
+ * TODO: SCO/UnixWare 7 must be something like (not tested)
+ * debug -i c <pid> <<EOF\nstack -f 4\nquit\nEOF\n
+ */
+# if !defined(__GNUC__)
+ if(backtrace_command(outb, "dbx %s %d 2>/dev/null <<EOF\n"
+ "where\n"
+ "detach\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+# endif
+ if(backtrace_command(outb, "gdb -q %s %d 2>/dev/null <<EOF\n"
+ "set prompt\n"
+ "where\n"
+#if 0
+ "echo ---\\n\n"
+ "frame 4\n"
+ "set \\$x = 50\n"
+ "while (\\$x)\n"
+ "info locals\n"
+ "up\n"
+ "set \\$x--\n"
+ "end\n"
+ "echo ---\\n\n"
+#endif
+ "detach\n"
+ "quit\n"
+ "EOF\n",
+ globalProgName, (int)getpid()))
+ return;
+#endif
+ const char debug_err[] = "No debugger found\n";
+ fwrite(debug_err, strlen(debug_err), 1, outb);
+}
+/* end of copied code */
+#endif
+
+
+void qt_signal_handler(int sig)
+{
+ signal(sig, SIG_DFL);
+ if(QSegfaultHandler::callback) {
+ (*QSegfaultHandler::callback)();
+ _exit(1);
+ }
+ FILE *outb = stderr;
+ if(char *crash_loc = ::getenv("QT_CRASH_OUTPUT")) {
+ if(FILE *new_outb = fopen(crash_loc, "w")) {
+ fprintf(stderr, "Crash (backtrace written to %s)!!!\n", crash_loc);
+ outb = new_outb;
+ }
+ } else {
+ fprintf(outb, "Crash!!!\n");
+ }
+ print_backtrace(outb);
+ if(outb != stderr)
+ fclose(outb);
+ _exit(1);
+}
+
+
+void
+QSegfaultHandler::initialize(char **argv, int argc)
+{
+ init_backtrace(argv, argc);
+
+ struct sigaction SignalAction;
+ SignalAction.sa_flags = 0;
+ SignalAction.sa_handler = qt_signal_handler;
+ sigemptyset(&SignalAction.sa_mask);
+ sigaction(SIGSEGV, &SignalAction, NULL);
+ sigaction(SIGBUS, &SignalAction, NULL);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CRASHHANDLER
diff --git a/src/corelib/kernel/qcrashhandler_p.h b/src/corelib/kernel/qcrashhandler_p.h
new file mode 100644
index 0000000000..1d41a3c693
--- /dev/null
+++ b/src/corelib/kernel/qcrashhandler_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QCRASHHANDLER_P_H
+#define QCRASHHANDLER_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 <QtCore/qglobal.h>
+
+#ifndef QT_NO_CRASHHANDLER
+
+QT_BEGIN_NAMESPACE
+
+typedef void (*QtCrashHandler)();
+
+class Q_CORE_EXPORT QSegfaultHandler
+{
+ friend void qt_signal_handler(int);
+ static QtCrashHandler callback;
+public:
+ static void initialize(char **, int);
+
+ inline static void installCrashHandler(QtCrashHandler h) { callback = h; }
+ inline static QtCrashHandler crashHandler() { return callback; }
+
+private:
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_CRASHHANDLER
+
+#endif // QCRASHHANDLER_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_glib.cpp b/src/corelib/kernel/qeventdispatcher_glib.cpp
new file mode 100644
index 0000000000..4e19414231
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -0,0 +1,601 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qeventdispatcher_glib_p.h"
+#include "qeventdispatcher_unix_p.h"
+
+#include <private/qmutexpool_p.h>
+#include <private/qthread_p.h>
+
+#include "qcoreapplication.h"
+#include "qsocketnotifier.h"
+
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+
+#include <glib.h>
+
+QT_BEGIN_NAMESPACE
+
+struct GPollFDWithQSocketNotifier
+{
+ GPollFD pollfd;
+ QSocketNotifier *socketNotifier;
+};
+
+struct GSocketNotifierSource
+{
+ GSource source;
+ QList<GPollFDWithQSocketNotifier *> pollfds;
+};
+
+static gboolean socketNotifierSourcePrepare(GSource *, gint *timeout)
+{
+ if (timeout)
+ *timeout = -1;
+ return false;
+}
+
+static gboolean socketNotifierSourceCheck(GSource *source)
+{
+ GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source);
+
+ bool pending = false;
+ for (int i = 0; !pending && i < src->pollfds.count(); ++i) {
+ GPollFDWithQSocketNotifier *p = src->pollfds.at(i);
+
+ if (p->pollfd.revents & G_IO_NVAL) {
+ // disable the invalid socket notifier
+ static const char *t[] = { "Read", "Write", "Exception" };
+ qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...",
+ p->pollfd.fd, t[int(p->socketNotifier->type())]);
+ // ### note, modifies src->pollfds!
+ p->socketNotifier->setEnabled(false);
+ }
+
+ pending = ((p->pollfd.revents & p->pollfd.events) != 0);
+ }
+
+ return pending;
+}
+
+static gboolean socketNotifierSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ QEvent event(QEvent::SockAct);
+
+ GSocketNotifierSource *src = reinterpret_cast<GSocketNotifierSource *>(source);
+ for (int i = 0; i < src->pollfds.count(); ++i) {
+ GPollFDWithQSocketNotifier *p = src->pollfds.at(i);
+
+ if ((p->pollfd.revents & p->pollfd.events) != 0)
+ QCoreApplication::sendEvent(p->socketNotifier, &event);
+ }
+
+ return true; // ??? don't remove, right?
+}
+
+static GSourceFuncs socketNotifierSourceFuncs = {
+ socketNotifierSourcePrepare,
+ socketNotifierSourceCheck,
+ socketNotifierSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct GTimerSource
+{
+ GSource source;
+ QTimerInfoList timerList;
+ QEventLoop::ProcessEventsFlags processEventsFlags;
+ bool runWithIdlePriority;
+};
+
+static gboolean timerSourcePrepareHelper(GTimerSource *src, gint *timeout)
+{
+ timeval tv = { 0l, 0l };
+ if (!(src->processEventsFlags & QEventLoop::X11ExcludeTimers) && src->timerList.timerWait(tv))
+ *timeout = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+ else
+ *timeout = -1;
+
+ return (*timeout == 0);
+}
+
+static gboolean timerSourceCheckHelper(GTimerSource *src)
+{
+ if (src->timerList.isEmpty()
+ || (src->processEventsFlags & QEventLoop::X11ExcludeTimers))
+ return false;
+
+ if (src->timerList.updateCurrentTime() < src->timerList.first()->timeout)
+ return false;
+
+ return true;
+}
+
+static gboolean timerSourcePrepare(GSource *source, gint *timeout)
+{
+ gint dummy;
+ if (!timeout)
+ timeout = &dummy;
+
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+ if (src->runWithIdlePriority) {
+ if (timeout)
+ *timeout = -1;
+ return false;
+ }
+
+ return timerSourcePrepareHelper(src, timeout);
+}
+
+static gboolean timerSourceCheck(GSource *source)
+{
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+ if (src->runWithIdlePriority)
+ return false;
+ return timerSourceCheckHelper(src);
+}
+
+static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ GTimerSource *timerSource = reinterpret_cast<GTimerSource *>(source);
+ if (timerSource->processEventsFlags & QEventLoop::X11ExcludeTimers)
+ return true;
+ timerSource->runWithIdlePriority = true;
+ (void) timerSource->timerList.activateTimers();
+ return true; // ??? don't remove, right again?
+}
+
+static GSourceFuncs timerSourceFuncs = {
+ timerSourcePrepare,
+ timerSourceCheck,
+ timerSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct GIdleTimerSource
+{
+ GSource source;
+ GTimerSource *timerSource;
+};
+
+static gboolean idleTimerSourcePrepare(GSource *source, gint *timeout)
+{
+ GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source);
+ GTimerSource *timerSource = idleTimerSource->timerSource;
+ if (!timerSource->runWithIdlePriority) {
+ // Yield to the normal priority timer source
+ if (timeout)
+ *timeout = -1;
+ return false;
+ }
+
+ return timerSourcePrepareHelper(timerSource, timeout);
+}
+
+static gboolean idleTimerSourceCheck(GSource *source)
+{
+ GIdleTimerSource *idleTimerSource = reinterpret_cast<GIdleTimerSource *>(source);
+ GTimerSource *timerSource = idleTimerSource->timerSource;
+ if (!timerSource->runWithIdlePriority) {
+ // Yield to the normal priority timer source
+ return false;
+ }
+ return timerSourceCheckHelper(timerSource);
+}
+
+static gboolean idleTimerSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ GTimerSource *timerSource = reinterpret_cast<GIdleTimerSource *>(source)->timerSource;
+ (void) timerSourceDispatch(&timerSource->source, 0, 0);
+ return true;
+}
+
+static GSourceFuncs idleTimerSourceFuncs = {
+ idleTimerSourcePrepare,
+ idleTimerSourceCheck,
+ idleTimerSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct GPostEventSource
+{
+ GSource source;
+ QAtomicInt serialNumber;
+ int lastSerialNumber;
+ QEventDispatcherGlibPrivate *d;
+};
+
+static gboolean postEventSourcePrepare(GSource *s, gint *timeout)
+{
+ QThreadData *data = QThreadData::current();
+ if (!data)
+ return false;
+
+ gint dummy;
+ if (!timeout)
+ timeout = &dummy;
+ *timeout = data->canWait ? -1 : 0;
+
+ GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
+ return (!data->canWait
+ || (source->serialNumber != source->lastSerialNumber));
+}
+
+static gboolean postEventSourceCheck(GSource *source)
+{
+ return postEventSourcePrepare(source, 0);
+}
+
+static gboolean postEventSourceDispatch(GSource *s, GSourceFunc, gpointer)
+{
+ GPostEventSource *source = reinterpret_cast<GPostEventSource *>(s);
+ source->lastSerialNumber = source->serialNumber;
+ QCoreApplication::sendPostedEvents();
+ source->d->runTimersOnceWithNormalPriority();
+ return true; // i dunno, george...
+}
+
+static GSourceFuncs postEventSourceFuncs = {
+ postEventSourcePrepare,
+ postEventSourceCheck,
+ postEventSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+
+QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(GMainContext *context)
+ : mainContext(context)
+{
+ if (qgetenv("QT_NO_THREADED_GLIB").isEmpty()) {
+ static int dummyValue = 0; // only used for its address
+ QMutexLocker locker(QMutexPool::instance()->get(&dummyValue));
+ if (!g_thread_supported())
+ g_thread_init(NULL);
+ }
+
+ if (mainContext) {
+ g_main_context_ref(mainContext);
+ } else {
+ QCoreApplication *app = QCoreApplication::instance();
+ if (app && QThread::currentThread() == app->thread()) {
+ mainContext = g_main_context_default();
+ g_main_context_ref(mainContext);
+ } else {
+ mainContext = g_main_context_new();
+ }
+ }
+
+#if GLIB_CHECK_VERSION (2, 22, 0)
+ g_main_context_push_thread_default (mainContext);
+#endif
+
+ // setup post event source
+ postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs,
+ sizeof(GPostEventSource)));
+ postEventSource->serialNumber = 1;
+ postEventSource->d = this;
+ g_source_set_can_recurse(&postEventSource->source, true);
+ g_source_attach(&postEventSource->source, mainContext);
+
+ // setup socketNotifierSource
+ socketNotifierSource =
+ reinterpret_cast<GSocketNotifierSource *>(g_source_new(&socketNotifierSourceFuncs,
+ sizeof(GSocketNotifierSource)));
+ (void) new (&socketNotifierSource->pollfds) QList<GPollFDWithQSocketNotifier *>();
+ g_source_set_can_recurse(&socketNotifierSource->source, true);
+ g_source_attach(&socketNotifierSource->source, mainContext);
+
+ // setup normal and idle timer sources
+ timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs,
+ sizeof(GTimerSource)));
+ (void) new (&timerSource->timerList) QTimerInfoList();
+ timerSource->processEventsFlags = QEventLoop::AllEvents;
+ timerSource->runWithIdlePriority = false;
+ g_source_set_can_recurse(&timerSource->source, true);
+ g_source_attach(&timerSource->source, mainContext);
+
+ idleTimerSource = reinterpret_cast<GIdleTimerSource *>(g_source_new(&idleTimerSourceFuncs,
+ sizeof(GIdleTimerSource)));
+ idleTimerSource->timerSource = timerSource;
+ g_source_set_can_recurse(&idleTimerSource->source, true);
+ g_source_set_priority(&idleTimerSource->source, G_PRIORITY_DEFAULT_IDLE);
+ g_source_attach(&idleTimerSource->source, mainContext);
+}
+
+void QEventDispatcherGlibPrivate::runTimersOnceWithNormalPriority()
+{
+ timerSource->runWithIdlePriority = false;
+}
+
+QEventDispatcherGlib::QEventDispatcherGlib(QObject *parent)
+ : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate), parent)
+{
+}
+
+QEventDispatcherGlib::QEventDispatcherGlib(GMainContext *mainContext, QObject *parent)
+ : QAbstractEventDispatcher(*(new QEventDispatcherGlibPrivate(mainContext)), parent)
+{ }
+
+QEventDispatcherGlib::~QEventDispatcherGlib()
+{
+ Q_D(QEventDispatcherGlib);
+
+ // destroy all timer sources
+ qDeleteAll(d->timerSource->timerList);
+ d->timerSource->timerList.~QTimerInfoList();
+ g_source_destroy(&d->timerSource->source);
+ g_source_unref(&d->timerSource->source);
+ d->timerSource = 0;
+ g_source_destroy(&d->idleTimerSource->source);
+ g_source_unref(&d->idleTimerSource->source);
+ d->idleTimerSource = 0;
+
+ // destroy socket notifier source
+ for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) {
+ GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds[i];
+ g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
+ delete p;
+ }
+ d->socketNotifierSource->pollfds.~QList<GPollFDWithQSocketNotifier *>();
+ g_source_destroy(&d->socketNotifierSource->source);
+ g_source_unref(&d->socketNotifierSource->source);
+ d->socketNotifierSource = 0;
+
+ // destroy post event source
+ g_source_destroy(&d->postEventSource->source);
+ g_source_unref(&d->postEventSource->source);
+ d->postEventSource = 0;
+
+ Q_ASSERT(d->mainContext != 0);
+#if GLIB_CHECK_VERSION (2, 22, 0)
+ g_main_context_pop_thread_default (d->mainContext);
+#endif
+ g_main_context_unref(d->mainContext);
+ d->mainContext = 0;
+}
+
+bool QEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherGlib);
+
+ const bool canWait = (flags & QEventLoop::WaitForMoreEvents);
+ if (canWait)
+ emit aboutToBlock();
+ else
+ emit awake();
+
+ // tell postEventSourcePrepare() and timerSource about any new flags
+ QEventLoop::ProcessEventsFlags savedFlags = d->timerSource->processEventsFlags;
+ d->timerSource->processEventsFlags = flags;
+
+ if (!(flags & QEventLoop::EventLoopExec)) {
+ // force timers to be sent at normal priority
+ d->timerSource->runWithIdlePriority = false;
+ }
+
+ bool result = g_main_context_iteration(d->mainContext, canWait);
+ while (!result && canWait)
+ result = g_main_context_iteration(d->mainContext, canWait);
+
+ d->timerSource->processEventsFlags = savedFlags;
+
+ if (canWait)
+ emit awake();
+
+ return result;
+}
+
+bool QEventDispatcherGlib::hasPendingEvents()
+{
+ Q_D(QEventDispatcherGlib);
+ return g_main_context_pending(d->mainContext);
+}
+
+void QEventDispatcherGlib::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+
+
+ GPollFDWithQSocketNotifier *p = new GPollFDWithQSocketNotifier;
+ p->pollfd.fd = sockfd;
+ switch (type) {
+ case QSocketNotifier::Read:
+ p->pollfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ break;
+ case QSocketNotifier::Write:
+ p->pollfd.events = G_IO_OUT | G_IO_ERR;
+ break;
+ case QSocketNotifier::Exception:
+ p->pollfd.events = G_IO_PRI | G_IO_ERR;
+ break;
+ }
+ p->socketNotifier = notifier;
+
+ d->socketNotifierSource->pollfds.append(p);
+
+ g_source_add_poll(&d->socketNotifierSource->source, &p->pollfd);
+}
+
+void QEventDispatcherGlib::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+#ifndef QT_NO_DEBUG
+ int sockfd = notifier->socket();
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+
+ for (int i = 0; i < d->socketNotifierSource->pollfds.count(); ++i) {
+ GPollFDWithQSocketNotifier *p = d->socketNotifierSource->pollfds.at(i);
+ if (p->socketNotifier == notifier) {
+ // found it
+ g_source_remove_poll(&d->socketNotifierSource->source, &p->pollfd);
+
+ d->socketNotifierSource->pollfds.removeAt(i);
+ delete p;
+
+ return;
+ }
+ }
+}
+
+void QEventDispatcherGlib::registerTimer(int timerId, int interval, QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1 || interval < 0 || !object) {
+ qWarning("QEventDispatcherGlib::registerTimer: invalid arguments");
+ return;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+ d->timerSource->timerList.registerTimer(timerId, interval, object);
+}
+
+bool QEventDispatcherGlib::unregisterTimer(int timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1) {
+ qWarning("QEventDispatcherGlib::unregisterTimer: invalid argument");
+ return false;
+ } else if (thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+ return d->timerSource->timerList.unregisterTimer(timerId);
+}
+
+bool QEventDispatcherGlib::unregisterTimers(QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QEventDispatcherGlib::unregisterTimers: invalid argument");
+ return false;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherGlib);
+ return d->timerSource->timerList.unregisterTimers(object);
+}
+
+QList<QEventDispatcherGlib::TimerInfo> QEventDispatcherGlib::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ Q_D(const QEventDispatcherGlib);
+ return d->timerSource->timerList.registeredTimers(object);
+}
+
+void QEventDispatcherGlib::interrupt()
+{
+ wakeUp();
+}
+
+void QEventDispatcherGlib::wakeUp()
+{
+ Q_D(QEventDispatcherGlib);
+ d->postEventSource->serialNumber.ref();
+ g_main_context_wakeup(d->mainContext);
+}
+
+void QEventDispatcherGlib::flush()
+{
+}
+
+bool QEventDispatcherGlib::versionSupported()
+{
+#if !defined(GLIB_MAJOR_VERSION) || !defined(GLIB_MINOR_VERSION) || !defined(GLIB_MICRO_VERSION)
+ return false;
+#else
+ return ((GLIB_MAJOR_VERSION << 16) + (GLIB_MINOR_VERSION << 8) + GLIB_MICRO_VERSION) >= 0x020301;
+#endif
+}
+
+QEventDispatcherGlib::QEventDispatcherGlib(QEventDispatcherGlibPrivate &dd, QObject *parent)
+ : QAbstractEventDispatcher(dd, parent)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_glib_p.h b/src/corelib/kernel/qeventdispatcher_glib_p.h
new file mode 100644
index 0000000000..65eff72fca
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QEVENTDISPATCHER_GLIB_P_H
+#define QEVENTDISPATCHER_GLIB_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qabstracteventdispatcher.h"
+#include "qabstracteventdispatcher_p.h"
+
+#include <QtCore/qhash.h>
+
+typedef struct _GMainContext GMainContext;
+
+QT_BEGIN_NAMESPACE
+
+class QEventDispatcherGlibPrivate;
+
+class Q_CORE_EXPORT QEventDispatcherGlib : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherGlib)
+
+public:
+ explicit QEventDispatcherGlib(QObject *parent = 0);
+ explicit QEventDispatcherGlib(GMainContext *context, QObject *parent = 0);
+ ~QEventDispatcherGlib();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *socketNotifier);
+ void unregisterSocketNotifier(QSocketNotifier *socketNotifier);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+ static bool versionSupported();
+
+protected:
+ QEventDispatcherGlib(QEventDispatcherGlibPrivate &dd, QObject *parent);
+};
+
+struct GPostEventSource;
+struct GSocketNotifierSource;
+struct GTimerSource;
+struct GIdleTimerSource;
+
+class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatcherPrivate
+{
+
+public:
+ QEventDispatcherGlibPrivate(GMainContext *context = 0);
+ GMainContext *mainContext;
+ GPostEventSource *postEventSource;
+ GSocketNotifierSource *socketNotifierSource;
+ GTimerSource *timerSource;
+ GIdleTimerSource *idleTimerSource;
+
+ void runTimersOnceWithNormalPriority();
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_GLIB_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
new file mode 100644
index 0000000000..e0eeb0819a
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -0,0 +1,1310 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qeventdispatcher_symbian_p.h"
+#include <private/qthread_p.h>
+#include <qcoreapplication.h>
+#include <private/qcoreapplication_p.h>
+#include <qsemaphore.h>
+
+#include <unistd.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+// when the system UI is Qt based, priority drop is not needed as CPU starved processes will not be killed.
+#undef QT_SYMBIAN_PRIORITY_DROP
+#else
+#define QT_SYMBIAN_PRIORITY_DROP
+#endif
+
+#define WAKE_UP_PRIORITY CActive::EPriorityStandard
+#define TIMER_PRIORITY CActive::EPriorityHigh
+#define NULLTIMER_PRIORITY CActive::EPriorityLow
+#define COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY CActive::EPriorityIdle
+
+static inline int qt_pipe_write(int socket, const char *data, qint64 len)
+{
+ return ::write(socket, data, len);
+}
+#if defined(write)
+# undef write
+#endif
+
+static inline int qt_pipe_close(int socket)
+{
+ return ::close(socket);
+}
+#if defined(close)
+# undef close
+#endif
+
+static inline int qt_pipe_fcntl(int socket, int command)
+{
+ return ::fcntl(socket, command);
+}
+static inline int qt_pipe2_fcntl(int socket, int command, int option)
+{
+ return ::fcntl(socket, command, option);
+}
+#if defined(fcntl)
+# undef fcntl
+#endif
+
+static inline int qt_socket_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
+{
+ return ::select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+// This simply interrupts the select and locks the mutex until destroyed.
+class QSelectMutexGrabber
+{
+public:
+ QSelectMutexGrabber(int writeFd, int readFd, QMutex *mutex)
+ : m_mutex(mutex)
+ {
+ if (m_mutex->tryLock())
+ return;
+
+ char dummy = 0;
+ qt_pipe_write(writeFd, &dummy, 1);
+
+ m_mutex->lock();
+
+ char buffer;
+ while (::read(readFd, &buffer, 1) > 0) {}
+ }
+
+ ~QSelectMutexGrabber()
+ {
+ m_mutex->unlock();
+ }
+
+private:
+ QMutex *m_mutex;
+};
+
+/*
+ * This class is designed to aid in implementing event handling in a more round robin fashion. We
+ * cannot change active objects that we do not own, but the active objects that Qt owns will use
+ * this as a base class with convenience functions.
+ *
+ * Here is how it works: On every RunL, the deriving class should call maybeQueueForLater().
+ * This will return whether the active object has been queued, or whether it should run immediately.
+ * Queued objects will run again after other events have been processed.
+ *
+ * The QCompleteDeferredAOs class is a special object that runs after all others, which will
+ * reactivate the objects that were previously not run.
+ */
+QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
+ : CActive(priority),
+ m_dispatcher(dispatcher),
+ m_hasAlreadyRun(false),
+ m_hasRunAgain(false),
+ m_iterationCount(1)
+{
+}
+
+QActiveObject::~QActiveObject()
+{
+ if (m_hasRunAgain)
+ m_dispatcher->removeDeferredActiveObject(this);
+}
+
+bool QActiveObject::maybeQueueForLater()
+{
+ Q_ASSERT(!m_hasRunAgain);
+
+ if (!m_hasAlreadyRun || m_dispatcher->iterationCount() != m_iterationCount) {
+ // First occurrence of this event in this iteration.
+ m_hasAlreadyRun = true;
+ m_iterationCount = m_dispatcher->iterationCount();
+ return false;
+ } else {
+ // The event has already occurred.
+ m_dispatcher->addDeferredActiveObject(this);
+ m_hasRunAgain = true;
+ return true;
+ }
+}
+
+bool QActiveObject::maybeDeferSocketEvent()
+{
+ Q_ASSERT(!m_hasRunAgain);
+ Q_ASSERT(m_dispatcher);
+ if (!m_dispatcher->areSocketEventsBlocked()) {
+ return false;
+ }
+ m_hasRunAgain = true;
+ m_dispatcher->addDeferredSocketActiveObject(this);
+ return true;
+}
+
+void QActiveObject::reactivateAndComplete()
+{
+ TInt error = iStatus.Int();
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, error);
+
+ m_hasRunAgain = false;
+ m_hasAlreadyRun = false;
+}
+
+QWakeUpActiveObject::QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher)
+ : QActiveObject(WAKE_UP_PRIORITY, dispatcher)
+{
+ m_hostThreadId = RThread().Id();
+ CActiveScheduler::Add(this);
+ iStatus = KRequestPending;
+ SetActive();
+}
+
+QWakeUpActiveObject::~QWakeUpActiveObject()
+{
+ Cancel();
+}
+
+void QWakeUpActiveObject::DoCancel()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ } else if (IsActive() && m_hostThreadId != RThread().Id()) {
+ // This is being cancelled in the adopted monitor thread, which can happen if an adopted thread with
+ // an event loop has exited. The event loop creates an event dispatcher with this active object, which may be complete but not run on exit.
+ // We force a cancellation in this thread, because a) the object cannot be deleted while active and b) without a cancellation
+ // the thread semaphore will be one count down.
+ // It is possible for this problem to affect other active objects. They symptom would be that finished signals
+ // from adopted threads are not sent, or they arrive much later than they should.
+ TRequestStatus *status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ }
+}
+
+void QWakeUpActiveObject::RunL()
+{
+ if (maybeQueueForLater())
+ return;
+
+ iStatus = KRequestPending;
+ SetActive();
+ QT_TRYCATCH_LEAVING(m_dispatcher->wakeUpWasCalled());
+}
+
+QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
+ : QActiveObject((timerInfo->interval) ? TIMER_PRIORITY : NULLTIMER_PRIORITY , dispatcher),
+ m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0)
+{
+ // start the timeout timer to ensure initialisation
+ m_timeoutTimer.start();
+}
+
+QTimerActiveObject::~QTimerActiveObject()
+{
+ Cancel();
+ m_rTimer.Close(); //close of null handle is safe
+}
+
+void QTimerActiveObject::DoCancel()
+{
+ if (m_timerInfo->interval > 0) {
+ m_rTimer.Cancel();
+ } else {
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+ }
+}
+
+void QTimerActiveObject::RunL()
+{
+ int error = KErrNone;
+ if (iStatus == KErrNone) {
+ QT_TRYCATCH_ERROR(error, Run());
+ } else {
+ error = iStatus.Int();
+ }
+ // All Symbian error codes are negative.
+ if (error < 0) {
+ CActiveScheduler::Current()->Error(error); // stop and report here, as this timer will be deleted on scope exit
+ }
+}
+
+#define MAX_SYMBIAN_TIMEOUT_MS 2000000
+void QTimerActiveObject::StartTimer()
+{
+ if (m_timerInfo->msLeft > MAX_SYMBIAN_TIMEOUT_MS) {
+ //There is loss of accuracy anyway due to needing to restart the timer every 33 minutes,
+ //so the 1/64s res of After() is acceptable for these very long timers.
+ m_rTimer.After(iStatus, MAX_SYMBIAN_TIMEOUT_MS * 1000);
+ m_timerInfo->msLeft -= MAX_SYMBIAN_TIMEOUT_MS;
+ } else {
+ // this algorithm implements drift correction for repeating timers
+ // calculate how late we are for this event
+ int timeSinceLastEvent = m_timeoutTimer.restart();
+ int overshoot = timeSinceLastEvent - m_expectedTimeSinceLastEvent;
+ if (overshoot > m_timerInfo->msLeft) {
+ // we skipped a whole timeout, restart from here
+ overshoot = 0;
+ }
+ // calculate when the next event should happen
+ int waitTime = m_timerInfo->msLeft - overshoot;
+ m_expectedTimeSinceLastEvent = waitTime;
+ // limit the actual ms wait time to avoid wild corrections
+ // this will cause the real event time to slowly drift back to the expected event time
+ // measurements show that Symbian timers always fire 1 or 2 ms late
+ const int limit = 4;
+ waitTime = qMax(m_timerInfo->msLeft - limit, waitTime);
+ m_rTimer.HighRes(iStatus, waitTime * 1000);
+ m_timerInfo->msLeft = 0;
+ }
+ SetActive();
+}
+
+void QTimerActiveObject::Run()
+{
+ //restart timer immediately, if the timeout has been split because it overflows max for platform.
+ if (m_timerInfo->msLeft > 0) {
+ StartTimer();
+ return;
+ }
+
+ if (maybeQueueForLater())
+ return;
+
+ if (m_timerInfo->interval > 0) {
+ // Start a new timer immediately so that we don't lose time.
+ m_timerInfo->msLeft = m_timerInfo->interval;
+ StartTimer();
+
+ m_timerInfo->dispatcher->timerFired(m_timerInfo->timerId);
+ } else {
+ // However, we only complete zero timers after the event has finished,
+ // in order to prevent busy looping when doing nested loops.
+
+ // Keep the refpointer around in order to avoid deletion until the end of this function.
+ SymbianTimerInfoPtr timerInfoPtr(m_timerInfo);
+
+ m_timerInfo->dispatcher->timerFired(m_timerInfo->timerId);
+
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QTimerActiveObject::Start()
+{
+ CActiveScheduler::Add(this);
+ m_timerInfo->msLeft = m_timerInfo->interval;
+ if (m_timerInfo->interval > 0) {
+ if (!m_rTimer.Handle()) {
+ qt_symbian_throwIfError(m_rTimer.CreateLocal());
+ }
+ m_timeoutTimer.start();
+ m_expectedTimeSinceLastEvent = 0;
+ StartTimer();
+ } else {
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+SymbianTimerInfo::SymbianTimerInfo()
+ : timerAO(0)
+{
+}
+
+SymbianTimerInfo::~SymbianTimerInfo()
+{
+ delete timerAO;
+}
+
+QCompleteDeferredAOs::QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher)
+ : CActive(COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY),
+ m_dispatcher(dispatcher)
+{
+ CActiveScheduler::Add(this);
+ iStatus = KRequestPending;
+ SetActive();
+}
+
+QCompleteDeferredAOs::~QCompleteDeferredAOs()
+{
+ Cancel();
+}
+
+void QCompleteDeferredAOs::complete()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QCompleteDeferredAOs::DoCancel()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QCompleteDeferredAOs::RunL()
+{
+ iStatus = KRequestPending;
+ SetActive();
+
+ QT_TRYCATCH_LEAVING(m_dispatcher->reactivateDeferredActiveObjects());
+}
+
+QSelectThread::QSelectThread()
+ : m_quit(false)
+{
+ if (::pipe(m_pipeEnds) != 0) {
+ qWarning("Select thread was unable to open a pipe, errno: %i", errno);
+ } else {
+ int flags0 = qt_pipe_fcntl(m_pipeEnds[0], F_GETFL);
+ int flags1 = qt_pipe_fcntl(m_pipeEnds[1], F_GETFL);
+ // We should check the error code here, but Open C has a bug that returns
+ // failure even though the operation was successful.
+ qt_pipe2_fcntl(m_pipeEnds[0], F_SETFL, flags0 | O_NONBLOCK);
+ qt_pipe2_fcntl(m_pipeEnds[1], F_SETFL, flags1 | O_NONBLOCK);
+ }
+}
+
+QSelectThread::~QSelectThread()
+{
+ qt_pipe_close(m_pipeEnds[1]);
+ qt_pipe_close(m_pipeEnds[0]);
+}
+
+void QSelectThread::run()
+{
+ Q_D(QThread);
+
+ m_mutex.lock();
+
+ while (!m_quit) {
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptionfds;
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptionfds);
+
+ int maxfd = 0;
+ maxfd = qMax(maxfd, updateSocketSet(QSocketNotifier::Read, &readfds));
+ maxfd = qMax(maxfd, updateSocketSet(QSocketNotifier::Write, &writefds));
+ maxfd = qMax(maxfd, updateSocketSet(QSocketNotifier::Exception, &exceptionfds));
+ maxfd = qMax(maxfd, m_pipeEnds[0]);
+ maxfd++;
+
+ FD_SET(m_pipeEnds[0], &readfds);
+
+ int ret;
+ int savedSelectErrno;
+ ret = qt_socket_select(maxfd, &readfds, &writefds, &exceptionfds, 0);
+ savedSelectErrno = errno;
+
+ if(ret == 0) {
+ // do nothing
+ } else if (ret < 0) {
+ switch (savedSelectErrno) {
+ case EBADF:
+ case EINVAL:
+ case ENOMEM:
+ case EFAULT:
+ qWarning("::select() returned an error: %i", savedSelectErrno);
+ break;
+ case ECONNREFUSED:
+ case EPIPE:
+ qWarning("::select() returned an error: %i (go through sockets)", savedSelectErrno);
+ // prepare to go through all sockets
+ // mark in fd sets both:
+ // good ones
+ // ones that return -1 in select
+ // after loop update notifiers for all of them
+
+ // as we don't have "exception" notifier type
+ // we should force monitoring fd_set of this
+ // type as well
+
+ // clean @ start
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptionfds);
+ for (QHash<QSocketNotifier *, TRequestStatus *>::const_iterator i = m_AOStatuses.begin();
+ i != m_AOStatuses.end(); ++i) {
+
+ fd_set onefds;
+ FD_ZERO(&onefds);
+ FD_SET(i.key()->socket(), &onefds);
+
+ fd_set excfds;
+ FD_ZERO(&excfds);
+ FD_SET(i.key()->socket(), &excfds);
+
+ maxfd = i.key()->socket() + 1;
+
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+
+ ret = 0;
+
+ if(i.key()->type() == QSocketNotifier::Read) {
+ ret = ::select(maxfd, &onefds, 0, &excfds, &timeout);
+ if(ret != 0) FD_SET(i.key()->socket(), &readfds);
+ } else if(i.key()->type() == QSocketNotifier::Write) {
+ ret = ::select(maxfd, 0, &onefds, &excfds, &timeout);
+ if(ret != 0) FD_SET(i.key()->socket(), &writefds);
+ }
+
+ } // end for
+
+ // traversed all, so update
+ updateActivatedNotifiers(QSocketNotifier::Exception, &exceptionfds);
+ updateActivatedNotifiers(QSocketNotifier::Read, &readfds);
+ updateActivatedNotifiers(QSocketNotifier::Write, &writefds);
+
+ break;
+ case EINTR: // Should never occur on Symbian, but this is future proof!
+ default:
+ qWarning("::select() returned an unknown error: %i", savedSelectErrno);
+
+ break;
+ }
+ } else {
+ updateActivatedNotifiers(QSocketNotifier::Exception, &exceptionfds);
+ updateActivatedNotifiers(QSocketNotifier::Read, &readfds);
+ updateActivatedNotifiers(QSocketNotifier::Write, &writefds);
+ }
+
+ if (FD_ISSET(m_pipeEnds[0], &readfds))
+ m_waitCond.wait(&m_mutex);
+ }
+
+ m_mutex.unlock();
+}
+
+void QSelectThread::requestSocketEvents ( QSocketNotifier *notifier, TRequestStatus *status )
+{
+ Q_D(QThread);
+
+ if (!isRunning()) {
+ start();
+ }
+
+ Q_ASSERT(QThread::currentThread() == this->thread());
+
+ QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex);
+
+ Q_ASSERT(!m_AOStatuses.contains(notifier));
+
+ m_AOStatuses.insert(notifier, status);
+
+ m_waitCond.wakeAll();
+}
+
+void QSelectThread::cancelSocketEvents ( QSocketNotifier *notifier )
+{
+ Q_ASSERT(QThread::currentThread() == this->thread());
+
+ QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex);
+
+ m_AOStatuses.remove(notifier);
+
+ m_waitCond.wakeAll();
+}
+
+void QSelectThread::restart()
+{
+ Q_ASSERT(QThread::currentThread() == this->thread());
+
+ QSelectMutexGrabber lock(m_pipeEnds[1], m_pipeEnds[0], &m_mutex);
+
+ m_waitCond.wakeAll();
+}
+
+int QSelectThread::updateSocketSet(QSocketNotifier::Type type, fd_set *fds)
+{
+ int maxfd = 0;
+ if(m_AOStatuses.isEmpty()) {
+ /*
+ * Wonder if should return -1
+ * to signal that no descriptors
+ * added to fds
+ */
+ return maxfd;
+ }
+ for ( QHash<QSocketNotifier *, TRequestStatus *>::const_iterator i = m_AOStatuses.begin();
+ i != m_AOStatuses.end(); ++i) {
+ if (i.key()->type() == type) {
+ FD_SET(i.key()->socket(), fds);
+ maxfd = qMax(maxfd, i.key()->socket());
+ } else if(type == QSocketNotifier::Exception) {
+ /*
+ * We are registering existing sockets
+ * always to exception set
+ *
+ * Doing double FD_SET shouldn't
+ * matter
+ */
+ FD_SET(i.key()->socket(), fds);
+ maxfd = qMax(maxfd, i.key()->socket());
+ }
+ }
+
+ return maxfd;
+}
+
+void QSelectThread::updateActivatedNotifiers(QSocketNotifier::Type type, fd_set *fds)
+{
+ Q_D(QThread);
+ if(m_AOStatuses.isEmpty()) {
+ return;
+ }
+ QList<QSocketNotifier *> toRemove;
+ for (QHash<QSocketNotifier *, TRequestStatus *>::const_iterator i = m_AOStatuses.begin();
+ i != m_AOStatuses.end(); ++i) {
+ if (i.key()->type() == type && FD_ISSET(i.key()->socket(), fds)) {
+ toRemove.append(i.key());
+ TRequestStatus *status = i.value();
+ // Thread data is still owned by the main thread.
+ QEventDispatcherSymbian::RequestComplete(d->threadData->symbian_thread_handle, status, KErrNone);
+ } else if(type == QSocketNotifier::Exception && FD_ISSET(i.key()->socket(), fds)) {
+ /*
+ * check if socket is in exception set
+ * then signal RequestComplete for it
+ */
+ qWarning("exception on %d [will close the socket handle - hack]", i.key()->socket());
+ // quick fix; there is a bug
+ // when doing read on socket
+ // errors not preoperly mapped
+ // after offline-ing the device
+ // on some devices we do get exception
+ ::close(i.key()->socket());
+ toRemove.append(i.key());
+ TRequestStatus *status = i.value();
+ QEventDispatcherSymbian::RequestComplete(d->threadData->symbian_thread_handle, status, KErrNone);
+ }
+ }
+
+ for (int c = 0; c < toRemove.size(); ++c) {
+ m_AOStatuses.remove(toRemove[c]);
+ }
+}
+
+void QSelectThread::stop()
+{
+ m_quit = true;
+ restart();
+ wait();
+}
+
+QSocketActiveObject::QSocketActiveObject(QEventDispatcherSymbian *dispatcher, QSocketNotifier *notifier)
+ : QActiveObject(CActive::EPriorityStandard, dispatcher),
+ m_notifier(notifier),
+ m_inSocketEvent(false),
+ m_deleteLater(false)
+{
+ CActiveScheduler::Add(this);
+ iStatus = KRequestPending;
+ SetActive();
+}
+
+QSocketActiveObject::~QSocketActiveObject()
+{
+ Cancel();
+}
+
+void QSocketActiveObject::DoCancel()
+{
+ if (iStatus.Int() == KRequestPending) {
+ TRequestStatus *status = &iStatus;
+ QEventDispatcherSymbian::RequestComplete(status, KErrNone);
+ }
+}
+
+void QSocketActiveObject::RunL()
+{
+ if (maybeDeferSocketEvent())
+ return;
+ if (maybeQueueForLater())
+ return;
+
+ QT_TRYCATCH_LEAVING(run());
+}
+
+void QSocketActiveObject::run()
+{
+ QEvent e(QEvent::SockAct);
+ m_inSocketEvent = true;
+ QCoreApplication::sendEvent(m_notifier, &e);
+ m_inSocketEvent = false;
+
+ if (m_deleteLater) {
+ delete this;
+ } else {
+ iStatus = KRequestPending;
+ SetActive();
+ m_dispatcher->reactivateSocketNotifier(m_notifier);
+ }
+}
+
+void QSocketActiveObject::deleteLater()
+{
+ if (m_inSocketEvent) {
+ m_deleteLater = true;
+ } else {
+ delete this;
+ }
+}
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+class QIdleDetectorThread
+{
+public:
+ QIdleDetectorThread()
+ : m_state(STATE_RUN), m_stop(false), m_running(false)
+ {
+ start();
+ }
+
+ ~QIdleDetectorThread()
+ {
+ stop();
+ }
+
+ void start()
+ {
+ QMutexLocker lock(&m_mutex);
+ if (m_running)
+ return;
+ m_stop = false;
+ m_state = STATE_RUN;
+ TInt err = m_idleDetectorThread.Create(KNullDesC(), &idleDetectorThreadFunc, 1024, &User::Allocator(), this);
+ if (err != KErrNone)
+ return; // Fail silently on error. Next kick will try again. Exception might stop the event being processed
+ m_idleDetectorThread.SetPriority(EPriorityAbsoluteBackgroundNormal);
+ m_idleDetectorThread.Resume();
+ m_running = true;
+ // get a callback from QCoreApplication destruction to stop this thread
+ qAddPostRoutine(StopIdleDetectorThread);
+ }
+
+ void stop()
+ {
+ QMutexLocker lock(&m_mutex);
+ if (!m_running)
+ return;
+ // close down the idle thread because if corelib is loaded temporarily, this would leak threads into the host process
+ m_stop = true;
+ m_kick.release();
+ m_idleDetectorThread.SetPriority(EPriorityNormal);
+ TRequestStatus s;
+ m_idleDetectorThread.Logon(s);
+ User::WaitForRequest(s);
+ m_idleDetectorThread.Close();
+ m_running = false;
+ }
+
+ void kick()
+ {
+ start();
+ m_state = STATE_KICKED;
+ m_kick.release();
+ }
+
+ bool hasRun()
+ {
+ return m_state == STATE_RUN;
+ }
+
+private:
+ static TInt idleDetectorThreadFunc(TAny* self)
+ {
+ User::RenameThread(_L("IdleDetectorThread"));
+ static_cast<QIdleDetectorThread*>(self)->IdleLoop();
+ return KErrNone;
+ }
+
+ void IdleLoop()
+ {
+ while (!m_stop) {
+ m_kick.acquire();
+ m_state = STATE_RUN;
+ }
+ }
+
+ static void StopIdleDetectorThread();
+
+private:
+ enum IdleStates {STATE_KICKED, STATE_RUN} m_state;
+ bool m_stop;
+ bool m_running;
+ RThread m_idleDetectorThread;
+ QSemaphore m_kick;
+ QMutex m_mutex;
+};
+
+Q_GLOBAL_STATIC(QIdleDetectorThread, idleDetectorThread);
+
+void QIdleDetectorThread::StopIdleDetectorThread()
+{
+ idleDetectorThread()->stop();
+}
+
+const int maxBusyTime = 2000; // maximum time we allow idle detector to be blocked before worrying, in milliseconds
+const int baseDelay = 1000; // minimum delay time used when backing off to allow idling, in microseconds
+#endif
+
+QEventDispatcherSymbian::QEventDispatcherSymbian(QObject *parent)
+ : QAbstractEventDispatcher(parent),
+ m_selectThread(0),
+ m_activeScheduler(0),
+ m_wakeUpAO(0),
+ m_completeDeferredAOs(0),
+ m_interrupt(false),
+ m_wakeUpDone(0),
+ m_iterationCount(0),
+ m_insideTimerEvent(false),
+ m_noSocketEvents(false)
+{
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ m_delay = baseDelay;
+ m_avgEventTime = 0;
+ idleDetectorThread();
+#endif
+}
+
+QEventDispatcherSymbian::~QEventDispatcherSymbian()
+{
+}
+
+void QEventDispatcherSymbian::startingUp()
+{
+ if( !CActiveScheduler::Current() ) {
+ m_activeScheduler = q_check_ptr(new CQtActiveScheduler()); // CBase derived class needs to be checked on new
+ CActiveScheduler::Install(m_activeScheduler);
+ }
+ m_wakeUpAO = q_check_ptr(new QWakeUpActiveObject(this));
+ m_completeDeferredAOs = q_check_ptr(new QCompleteDeferredAOs(this));
+ // We already might have posted events, wakeup once to process them
+ wakeUp();
+}
+
+QSelectThread& QEventDispatcherSymbian::selectThread() {
+ if (!m_selectThread)
+ m_selectThread = new QSelectThread;
+ return *m_selectThread;
+}
+
+void QEventDispatcherSymbian::closingDown()
+{
+ if (m_selectThread && m_selectThread->isRunning()) {
+ m_selectThread->stop();
+ }
+ delete m_selectThread;
+ m_selectThread = 0;
+
+ delete m_completeDeferredAOs;
+ delete m_wakeUpAO;
+ if (m_activeScheduler) {
+ delete m_activeScheduler;
+ }
+}
+
+bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags flags )
+{
+ bool handledAnyEvent = false;
+ bool oldNoSocketEventsValue = m_noSocketEvents;
+ bool oldInsideTimerEventValue = m_insideTimerEvent;
+
+ m_insideTimerEvent = false;
+
+ QT_TRY {
+ Q_D(QAbstractEventDispatcher);
+
+ // It is safe if this counter overflows. The main importance is that each
+ // iteration count is different from the last.
+ m_iterationCount++;
+
+ RThread &thread = d->threadData->symbian_thread_handle;
+
+ bool block;
+ if (flags & QEventLoop::WaitForMoreEvents) {
+ block = true;
+ emit aboutToBlock();
+ } else {
+ block = false;
+ }
+
+ if (flags & QEventLoop::ExcludeSocketNotifiers) {
+ m_noSocketEvents = true;
+ } else {
+ m_noSocketEvents = false;
+ handledAnyEvent = sendDeferredSocketEvents();
+ }
+
+ bool handledSymbianEvent = false;
+ m_interrupt = false;
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ QElapsedTimer eventTimer;
+#endif
+
+ while (1) {
+ if (block) {
+ // This is where Qt will spend most of its time.
+ CActiveScheduler::Current()->WaitForAnyRequest();
+ } else {
+ if (thread.RequestCount() == 0) {
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ if (idleDetectorThread()->hasRun()) {
+ m_lastIdleRequestTimer.start();
+ idleDetectorThread()->kick();
+ } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) {
+ User::AfterHighRes(m_delay);
+ }
+#endif
+ break;
+ }
+ // This one should return without delay.
+ CActiveScheduler::Current()->WaitForAnyRequest();
+ }
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ if (idleDetectorThread()->hasRun()) {
+ if (m_delay > baseDelay)
+ m_delay -= baseDelay;
+ m_lastIdleRequestTimer.start();
+ idleDetectorThread()->kick();
+ } else if (m_lastIdleRequestTimer.elapsed() > maxBusyTime) {
+ User::AfterHighRes(m_delay);
+ // allow delay to be up to 1/4 of execution time
+ if (!idleDetectorThread()->hasRun() && m_delay*3 < m_avgEventTime)
+ m_delay += baseDelay;
+ }
+ eventTimer.start();
+#endif
+
+ TInt error;
+ handledSymbianEvent = CActiveScheduler::RunIfReady(error, KMinTInt);
+ if (error) {
+ qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error);
+ CActiveScheduler::Current()->Error(error);
+ }
+
+#ifdef QT_SYMBIAN_PRIORITY_DROP
+ int eventDur = eventTimer.elapsed()*1000;
+ // average is calcualted as a 5% decaying exponential average
+ m_avgEventTime = (m_avgEventTime * 95 + eventDur * 5) / 100;
+#endif
+
+ if (!handledSymbianEvent) {
+ qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal");
+ }
+ handledAnyEvent = true;
+ if (m_interrupt) {
+ break;
+ }
+ block = false;
+ };
+
+ emit awake();
+ } QT_CATCH (const std::exception& ex) {
+#ifndef QT_NO_EXCEPTIONS
+ CActiveScheduler::Current()->Error(qt_symbian_exception2Error(ex));
+#endif
+ }
+
+ m_noSocketEvents = oldNoSocketEventsValue;
+ m_insideTimerEvent = oldInsideTimerEventValue;
+
+ return handledAnyEvent;
+}
+
+void QEventDispatcherSymbian::timerFired(int timerId)
+{
+ QHash<int, SymbianTimerInfoPtr>::iterator i = m_timerList.find(timerId);
+ if (i == m_timerList.end()) {
+ // The timer has been deleted. Ignore this event.
+ return;
+ }
+
+ SymbianTimerInfoPtr timerInfo = *i;
+
+ // Prevent infinite timer recursion.
+ if (timerInfo->inTimerEvent) {
+ return;
+ }
+
+ timerInfo->inTimerEvent = true;
+ bool oldInsideTimerEventValue = m_insideTimerEvent;
+ m_insideTimerEvent = true;
+
+ QTimerEvent event(timerInfo->timerId);
+ QCoreApplication::sendEvent(timerInfo->receiver, &event);
+
+ m_insideTimerEvent = oldInsideTimerEventValue;
+ timerInfo->inTimerEvent = false;
+
+ return;
+}
+
+void QEventDispatcherSymbian::wakeUpWasCalled()
+{
+ // The reactivation should happen in RunL, right before the call to this function.
+ // This is because m_wakeUpDone is the "signal" that the object can be completed
+ // once more.
+ // Also, by dispatching the posted events after resetting m_wakeUpDone, we guarantee
+ // that no posted event notification will be lost. If we did it the other way
+ // around, it would be possible for another thread to post an event right after
+ // the sendPostedEvents was done, but before the object was ready to be completed
+ // again. This could deadlock the application if there are no other posted events.
+ m_wakeUpDone.fetchAndStoreOrdered(0);
+ sendPostedEvents();
+}
+
+void QEventDispatcherSymbian::interrupt()
+{
+ m_interrupt = true;
+ wakeUp();
+}
+
+void QEventDispatcherSymbian::wakeUp()
+{
+ Q_D(QAbstractEventDispatcher);
+
+ if (m_wakeUpAO && m_wakeUpDone.testAndSetAcquire(0, 1)) {
+ TRequestStatus *status = &m_wakeUpAO->iStatus;
+ QEventDispatcherSymbian::RequestComplete(d->threadData->symbian_thread_handle, status, KErrNone);
+ }
+}
+
+bool QEventDispatcherSymbian::sendPostedEvents()
+{
+ Q_D(QAbstractEventDispatcher);
+
+ // moveToThread calls this and canWait == true -> Events will never get processed
+ // if we check for d->threadData->canWait
+ //
+ // QCoreApplication::postEvent sets canWait = false, but after the object and events
+ // are moved to a new thread, the canWait in new thread is true i.e. not changed to reflect
+ // the flag on old thread. That's why events in a new thread will not get processed.
+ // This migth be actually bug in moveToThread functionality, but because other platforms
+ // do not check canWait in wakeUp (where we essentially are now) - decided to remove it from
+ // here as well.
+
+ //if (!d->threadData->canWait) {
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ return true;
+ //}
+ //return false;
+}
+
+inline void QEventDispatcherSymbian::addDeferredActiveObject(QActiveObject *object)
+{
+ queueDeferredActiveObjectsCompletion();
+ m_deferredActiveObjects.append(object);
+}
+
+inline void QEventDispatcherSymbian::removeDeferredActiveObject(QActiveObject *object)
+{
+ m_deferredActiveObjects.removeAll(object);
+ m_deferredSocketEvents.removeAll(object);
+}
+
+inline void QEventDispatcherSymbian::addDeferredSocketActiveObject(QActiveObject *object)
+{
+ m_deferredSocketEvents.append(object);
+}
+
+void QEventDispatcherSymbian::queueDeferredActiveObjectsCompletion()
+{
+ m_completeDeferredAOs->complete();
+}
+
+void QEventDispatcherSymbian::reactivateDeferredActiveObjects()
+{
+ while (!m_deferredActiveObjects.isEmpty()) {
+ QActiveObject *object = m_deferredActiveObjects.takeFirst();
+ object->reactivateAndComplete();
+ }
+
+ // We do this because we want to return from processEvents. This is because
+ // each invocation of processEvents should only run each active object once.
+ // The active scheduler should run them continously, however.
+ m_interrupt = true;
+}
+
+bool QEventDispatcherSymbian::sendDeferredSocketEvents()
+{
+ bool sentAnyEvents = false;
+ while (!m_deferredSocketEvents.isEmpty()) {
+ sentAnyEvents = true;
+ QActiveObject *object = m_deferredSocketEvents.takeFirst();
+ object->reactivateAndComplete();
+ }
+
+ return sentAnyEvents;
+}
+
+void QEventDispatcherSymbian::flush()
+{
+}
+
+bool QEventDispatcherSymbian::hasPendingEvents()
+{
+ Q_D(QAbstractEventDispatcher);
+ return (d->threadData->symbian_thread_handle.RequestCount() != 0
+ || !d->threadData->canWait || !m_deferredSocketEvents.isEmpty());
+}
+
+void QEventDispatcherSymbian::registerSocketNotifier ( QSocketNotifier * notifier )
+{
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
+ QSocketActiveObject *socketAO = new QSocketActiveObject(this, notifier);
+ Q_CHECK_PTR(socketAO);
+ m_notifiers.insert(notifier, socketAO);
+ selectThread().requestSocketEvents(notifier, &socketAO->iStatus);
+}
+
+void QEventDispatcherSymbian::unregisterSocketNotifier ( QSocketNotifier * notifier )
+{
+ //note - this is only for "open C" file descriptors
+ //for native sockets, an active object in the symbian socket engine handles this
+ if (m_selectThread)
+ m_selectThread->cancelSocketEvents(notifier);
+ if (m_notifiers.contains(notifier)) {
+ QSocketActiveObject *sockObj = *m_notifiers.find(notifier);
+ m_deferredSocketEvents.removeAll(sockObj);
+ sockObj->deleteLater();
+ m_notifiers.remove(notifier);
+ }
+}
+
+void QEventDispatcherSymbian::reactivateSocketNotifier(QSocketNotifier *notifier)
+{
+ selectThread().requestSocketEvents(notifier, &m_notifiers[notifier]->iStatus);
+}
+
+void QEventDispatcherSymbian::registerTimer ( int timerId, int interval, QObject * object )
+{
+ if (interval < 0) {
+ qWarning("Timer interval < 0");
+ interval = 0;
+ }
+
+ SymbianTimerInfoPtr timer(new SymbianTimerInfo);
+ timer->timerId = timerId;
+ timer->interval = interval;
+ timer->inTimerEvent = false;
+ timer->receiver = object;
+ timer->dispatcher = this;
+ timer->timerAO = q_check_ptr(new QTimerActiveObject(this, timer.data()));
+ m_timerList.insert(timerId, timer);
+
+ timer->timerAO->Start();
+
+ if (m_insideTimerEvent)
+ // If we are inside a timer event, we need to prevent event starvation
+ // by preventing newly created timers from running in the same event processing
+ // iteration. Do this by calling the maybeQueueForLater() function to "fake" that we have
+ // already run once. This will cause the next run to be added to the deferred
+ // queue instead.
+ timer->timerAO->maybeQueueForLater();
+}
+
+bool QEventDispatcherSymbian::unregisterTimer ( int timerId )
+{
+ if (!m_timerList.contains(timerId)) {
+ return false;
+ }
+
+ SymbianTimerInfoPtr timerInfo = m_timerList.take(timerId);
+
+ if (!QObjectPrivate::get(timerInfo->receiver)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(timerId);
+
+ return true;
+}
+
+bool QEventDispatcherSymbian::unregisterTimers ( QObject * object )
+{
+ if (m_timerList.isEmpty())
+ return false;
+
+ bool unregistered = false;
+ for (QHash<int, SymbianTimerInfoPtr>::iterator i = m_timerList.begin(); i != m_timerList.end(); ) {
+ if ((*i)->receiver == object) {
+ i = m_timerList.erase(i);
+ unregistered = true;
+ } else {
+ ++i;
+ }
+ }
+
+ return unregistered;
+}
+
+QList<QEventDispatcherSymbian::TimerInfo> QEventDispatcherSymbian::registeredTimers ( QObject * object ) const
+{
+ QList<TimerInfo> list;
+ for (QHash<int, SymbianTimerInfoPtr>::const_iterator i = m_timerList.begin(); i != m_timerList.end(); ++i) {
+ if ((*i)->receiver == object) {
+ list.push_back(TimerInfo((*i)->timerId, (*i)->interval));
+ }
+ }
+
+ return list;
+}
+
+/*
+ * This active scheduler class implements a simple report and continue policy, for Symbian OS leaves
+ * or exceptions from Qt that fall back to the scheduler.
+ * It will be used in cases where there is no existing active scheduler installed.
+ * Apps which link to qts60main.lib will have the UI active scheduler installed in the main thread
+ * instead of this one. But this would be used in other threads in the UI.
+ * An app could replace this behaviour by installing an alternative active scheduler.
+ */
+void CQtActiveScheduler::Error(TInt aError) const
+{
+ QT_TRY {
+ qWarning("Error from active scheduler %d", aError);
+ }
+ QT_CATCH (const std::bad_alloc&) {} // ignore alloc fails, nothing more can be done
+}
+
+bool QActiveObject::wait(CActive* ao, int ms)
+{
+ if (!ao->IsActive())
+ return true; //request already complete
+ bool timedout = false;
+ if (ms > 0) {
+ TRequestStatus tstat;
+ RTimer t;
+ if (KErrNone != t.CreateLocal())
+ return false;
+ t.HighRes(tstat, ms*1000);
+ User::WaitForRequest(tstat, ao->iStatus);
+ if (tstat != KRequestPending) {
+ timedout = true;
+ } else {
+ t.Cancel();
+ //balance thread semaphore
+ User::WaitForRequest(tstat);
+ }
+ t.Close();
+ } else {
+ User::WaitForRequest(ao->iStatus);
+ }
+ if (timedout)
+ return false;
+
+ //evil cast to allow calling of protected virtual
+ ((QActiveObject*)ao)->RunL();
+
+ //clear active & pending flags
+ ao->iStatus = TRequestStatus();
+
+ return true;
+}
+
+bool QActiveObject::wait(QList<CActive*> aos, int ms)
+{
+ QVector<TRequestStatus*> stati;
+ stati.reserve(aos.count() + 1);
+ foreach (CActive* ao, aos) {
+ if (!ao->IsActive())
+ return true; //request already complete
+ stati.append(&(ao->iStatus));
+ }
+ bool timedout = false;
+ TRequestStatus tstat;
+ RTimer t;
+ if (ms > 0) {
+ if (KErrNone != t.CreateLocal())
+ return false;
+ t.HighRes(tstat, ms*1000);
+ stati.append(&tstat);
+ }
+ User::WaitForNRequest(stati.data(), stati.count());
+ if (ms > 0) {
+ if (tstat != KRequestPending) {
+ timedout = true;
+ } else {
+ t.Cancel();
+ //balance thread semaphore
+ User::WaitForRequest(tstat);
+ }
+ t.Close();
+ }
+ if (timedout)
+ return false;
+
+ foreach (CActive* ao, aos) {
+ if (ao->iStatus != KRequestPending) {
+ //evil cast to allow calling of protected virtual
+ ((QActiveObject*)ao)->RunL();
+
+ //clear active & pending flags
+ ao->iStatus = TRequestStatus();
+ break; //only call one
+ }
+ }
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qeventdispatcher_symbian_p.cpp"
diff --git a/src/corelib/kernel/qeventdispatcher_symbian_p.h b/src/corelib/kernel/qeventdispatcher_symbian_p.h
new file mode 100644
index 0000000000..6fdd4b248d
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_symbian_p.h
@@ -0,0 +1,327 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QEVENTDISPATCHER_SYMBIAN_P_H
+#define QEVENTDISPATCHER_SYMBIAN_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 <qhash.h>
+#include <qset.h>
+#include <qshareddata.h>
+#include <qabstracteventdispatcher.h>
+#include <private/qabstracteventdispatcher_p.h>
+#include <qthread.h>
+#include <qmutex.h>
+#include <qwaitcondition.h>
+#include <qsocketnotifier.h>
+#include <qdatetime.h>
+#include <qelapsedtimer.h>
+
+#include <e32base.h>
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QEventDispatcherSymbian;
+class QTimerActiveObject;
+
+class Q_CORE_EXPORT QActiveObject : public CActive
+{
+public:
+ QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher);
+ ~QActiveObject();
+
+ bool maybeQueueForLater();
+ bool maybeDeferSocketEvent();
+
+ void reactivateAndComplete();
+
+ static bool wait(CActive* ao, int ms);
+ static bool wait(QList<CActive*> aos, int ms);
+protected:
+ QEventDispatcherSymbian *m_dispatcher;
+
+private:
+ bool m_hasAlreadyRun : 1;
+ bool m_hasRunAgain : 1;
+ int m_iterationCount;
+};
+
+class QWakeUpActiveObject : public QActiveObject
+{
+public:
+ QWakeUpActiveObject(QEventDispatcherSymbian *dispatcher);
+ ~QWakeUpActiveObject();
+
+ void Complete();
+
+protected:
+ void DoCancel();
+ void RunL();
+
+private:
+ TThreadId m_hostThreadId;
+};
+
+struct SymbianTimerInfo : public QSharedData
+{
+ SymbianTimerInfo();
+ ~SymbianTimerInfo();
+
+ int timerId;
+ int interval;
+ int msLeft;
+ bool inTimerEvent;
+ QObject *receiver;
+ QTimerActiveObject *timerAO;
+ QEventDispatcherSymbian *dispatcher;
+};
+
+typedef QExplicitlySharedDataPointer<SymbianTimerInfo> SymbianTimerInfoPtr;
+
+// This is a bit of a proxy class. See comments in SetActive and Start for details.
+class QTimerActiveObject : public QActiveObject
+{
+public:
+ QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo);
+ ~QTimerActiveObject();
+
+ void Start();
+
+protected:
+ void DoCancel();
+ void RunL();
+
+private:
+ void Run();
+ void StartTimer();
+
+private:
+ SymbianTimerInfo *m_timerInfo;
+ QElapsedTimer m_timeoutTimer;
+ int m_expectedTimeSinceLastEvent;
+ RTimer m_rTimer;
+};
+
+class QCompleteDeferredAOs : public CActive
+{
+public:
+ QCompleteDeferredAOs(QEventDispatcherSymbian *dispatcher);
+ ~QCompleteDeferredAOs();
+
+ void complete();
+
+protected:
+ void DoCancel();
+ void RunL();
+
+private:
+ QEventDispatcherSymbian *m_dispatcher;
+};
+
+class QSocketActiveObject : public QActiveObject
+{
+public:
+ QSocketActiveObject(QEventDispatcherSymbian *dispatcher, QSocketNotifier *notifier);
+ ~QSocketActiveObject();
+
+ void deleteLater();
+
+protected:
+ void DoCancel();
+ void RunL();
+ void run();
+
+private:
+ QSocketNotifier *m_notifier;
+ bool m_inSocketEvent;
+ bool m_deleteLater;
+
+ friend class QEventDispatcherSymbian;
+};
+
+class QSelectThread : public QThread
+{
+ Q_DECLARE_PRIVATE(QThread)
+
+public:
+ QSelectThread();
+ ~QSelectThread();
+
+ void requestSocketEvents ( QSocketNotifier *notifier, TRequestStatus *status );
+ void cancelSocketEvents ( QSocketNotifier *notifier );
+ void restart();
+ void stop();
+
+protected:
+ void run();
+
+private:
+ int updateSocketSet(QSocketNotifier::Type type, fd_set *fds);
+ void updateActivatedNotifiers(QSocketNotifier::Type type, fd_set *fds);
+
+private:
+ int m_pipeEnds[2];
+ QHash<QSocketNotifier *, TRequestStatus *> m_AOStatuses;
+ QMutex m_mutex;
+ QWaitCondition m_waitCond;
+ bool m_quit;
+};
+
+class Q_CORE_EXPORT CQtActiveScheduler : public CActiveScheduler
+{
+public: // from CActiveScheduler
+ virtual void Error(TInt aError) const;
+};
+
+class Q_CORE_EXPORT QEventDispatcherSymbian : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QAbstractEventDispatcher)
+
+public:
+ QEventDispatcherSymbian(QObject *parent = 0);
+ ~QEventDispatcherSymbian();
+
+ void flush();
+ bool hasPendingEvents();
+ void interrupt();
+ bool processEvents ( QEventLoop::ProcessEventsFlags flags );
+ void registerSocketNotifier ( QSocketNotifier * notifier );
+ void registerTimer ( int timerId, int interval, QObject * object );
+ QList<TimerInfo> registeredTimers ( QObject * object ) const;
+ void unregisterSocketNotifier ( QSocketNotifier * notifier );
+ bool unregisterTimer ( int timerId );
+ bool unregisterTimers ( QObject * object );
+ void wakeUp();
+
+ void startingUp();
+ void closingDown();
+
+ void timerFired(int timerId);
+ void wakeUpWasCalled();
+ void reactivateSocketNotifier(QSocketNotifier *notifier);
+
+ void addDeferredActiveObject(QActiveObject *object);
+ void removeDeferredActiveObject(QActiveObject *object);
+ void queueDeferredActiveObjectsCompletion();
+ // Can be overridden to activate local active objects too, but do call baseclass!
+ virtual void reactivateDeferredActiveObjects();
+
+ inline int iterationCount() const { return m_iterationCount; }
+
+ void addDeferredSocketActiveObject(QActiveObject *object);
+ inline bool areSocketEventsBlocked() const { return m_noSocketEvents; }
+
+ static void RequestComplete(TRequestStatus *&status, TInt reason);
+ static void RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason);
+
+private:
+ bool sendPostedEvents();
+ bool sendDeferredSocketEvents();
+
+ QSelectThread& selectThread();
+private:
+ QSelectThread *m_selectThread;
+
+ CQtActiveScheduler *m_activeScheduler;
+
+ QHash<int, SymbianTimerInfoPtr> m_timerList;
+ QHash<QSocketNotifier *, QSocketActiveObject *> m_notifiers;
+
+ QWakeUpActiveObject *m_wakeUpAO;
+ QCompleteDeferredAOs *m_completeDeferredAOs;
+
+ volatile bool m_interrupt;
+ QAtomicInt m_wakeUpDone;
+
+ unsigned char m_iterationCount;
+ bool m_insideTimerEvent;
+ bool m_noSocketEvents;
+ //deferred until socket events are enabled
+ QList<QActiveObject *> m_deferredSocketEvents;
+ //deferred until idle
+ QList<QActiveObject *> m_deferredActiveObjects;
+
+ int m_delay;
+ int m_avgEventTime;
+ QElapsedTimer m_lastIdleRequestTimer;
+};
+
+#ifdef QT_DEBUG
+# define VERIFY_PENDING_REQUEST_STATUS \
+ Q_ASSERT(status->Int() == KRequestPending);
+#else
+# define VERIFY_PENDING_REQUEST_STATUS
+#endif
+
+// Convenience functions for doing some sanity checking on our own complete code.
+// Unless QT_DEBUG is defined, it is exactly equivalent to the Symbian version.
+inline void QEventDispatcherSymbian::RequestComplete(TRequestStatus *&status, TInt reason)
+{
+ VERIFY_PENDING_REQUEST_STATUS
+ User::RequestComplete(status, reason);
+}
+inline void QEventDispatcherSymbian::RequestComplete(RThread &threadHandle, TRequestStatus *&status, TInt reason)
+{
+ VERIFY_PENDING_REQUEST_STATUS
+ threadHandle.RequestComplete(status, reason);
+}
+
+#undef VERIFY_PENDING_REQUEST_STATUS
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_SYMBIAN_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
new file mode 100644
index 0000000000..dceb51d181
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -0,0 +1,979 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qplatformdefs.h"
+
+#include "qcoreapplication.h"
+#include "qpair.h"
+#include "qsocketnotifier.h"
+#include "qthread.h"
+#include "qelapsedtimer.h"
+
+#include "qeventdispatcher_unix_p.h"
+#include <private/qthread_p.h>
+#include <private/qcoreapplication_p.h>
+#include <private/qcore_unix_p.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+// VxWorks doesn't correctly set the _POSIX_... options
+#if defined(Q_OS_VXWORKS)
+# if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0)
+# undef _POSIX_MONOTONIC_CLOCK
+# define _POSIX_MONOTONIC_CLOCK 1
+# endif
+# include <pipeDrv.h>
+# include <selectLib.h>
+#endif
+
+#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED)
+# include <sys/times.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT bool qt_disable_lowpriority_timers=false;
+
+/*****************************************************************************
+ UNIX signal handling
+ *****************************************************************************/
+
+static sig_atomic_t signal_received;
+static sig_atomic_t signals_fired[NSIG];
+
+static void signalHandler(int sig)
+{
+ signals_fired[sig] = 1;
+ signal_received = 1;
+}
+
+
+#if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS)
+static void initThreadPipeFD(int fd)
+{
+ int ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
+ if (ret == -1)
+ perror("QEventDispatcherUNIXPrivate: Unable to init thread pipe");
+
+ int flags = fcntl(fd, F_GETFL);
+ if (flags == -1)
+ perror("QEventDispatcherUNIXPrivate: Unable to get flags on thread pipe");
+
+ ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (ret == -1)
+ perror("QEventDispatcherUNIXPrivate: Unable to set flags on thread pipe");
+}
+#endif
+
+QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
+{
+ extern Qt::HANDLE qt_application_thread_id;
+ mainThread = (QThread::currentThreadId() == qt_application_thread_id);
+ bool pipefail = false;
+
+ // initialize the common parts of the event loop
+#if defined(Q_OS_NACL)
+ // do nothing.
+#elif defined(Q_OS_INTEGRITY)
+ // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead
+ if (socketpair(AF_INET, SOCK_STREAM, 0, thread_pipe) == -1) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair");
+ pipefail = true;
+ } else {
+ initThreadPipeFD(thread_pipe[0]);
+ initThreadPipeFD(thread_pipe[1]);
+ }
+#elif defined(Q_OS_VXWORKS)
+ char name[20];
+ qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent));
+
+ // make sure there is no pipe with this name
+ pipeDevDelete(name, true);
+ // create the pipe
+ if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe device");
+ pipefail = true;
+ } else {
+ if ((thread_pipe[0] = open(name, O_RDWR, 0)) < 0) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
+ pipefail = true;
+ } else {
+ initThreadPipeFD(thread_pipe[0]);
+ thread_pipe[1] = thread_pipe[0];
+ }
+ }
+#else
+ if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) {
+ perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
+ pipefail = true;
+ }
+#endif
+
+ if (pipefail)
+ qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe");
+
+ sn_highest = -1;
+
+ interrupt = false;
+}
+
+QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
+{
+#if defined(Q_OS_NACL)
+ // do nothing.
+#elif defined(Q_OS_VXWORKS)
+ close(thread_pipe[0]);
+
+ char name[20];
+ qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent));
+
+ pipeDevDelete(name, true);
+#else
+ // cleanup the common parts of the event loop
+ close(thread_pipe[0]);
+ close(thread_pipe[1]);
+#endif
+
+ // cleanup timers
+ qDeleteAll(timerList);
+}
+
+int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout)
+{
+ Q_Q(QEventDispatcherUNIX);
+
+ // needed in QEventDispatcherUNIX::select()
+ timerList.updateCurrentTime();
+
+ int nsel;
+ do {
+ if (mainThread) {
+ while (signal_received) {
+ signal_received = 0;
+ for (int i = 0; i < NSIG; ++i) {
+ if (signals_fired[i]) {
+ signals_fired[i] = 0;
+ emit QCoreApplication::instance()->unixSignal(i);
+ }
+ }
+ }
+ }
+
+ // Process timers and socket notifiers - the common UNIX stuff
+ int highest = 0;
+ if (! (flags & QEventLoop::ExcludeSocketNotifiers) && (sn_highest >= 0)) {
+ // return the highest fd we can wait for input on
+ sn_vec[0].select_fds = sn_vec[0].enabled_fds;
+ sn_vec[1].select_fds = sn_vec[1].enabled_fds;
+ sn_vec[2].select_fds = sn_vec[2].enabled_fds;
+ highest = sn_highest;
+ } else {
+ FD_ZERO(&sn_vec[0].select_fds);
+ FD_ZERO(&sn_vec[1].select_fds);
+ FD_ZERO(&sn_vec[2].select_fds);
+ }
+
+ FD_SET(thread_pipe[0], &sn_vec[0].select_fds);
+ highest = qMax(highest, thread_pipe[0]);
+
+ nsel = q->select(highest + 1,
+ &sn_vec[0].select_fds,
+ &sn_vec[1].select_fds,
+ &sn_vec[2].select_fds,
+ timeout);
+ } while (nsel == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (nsel == -1) {
+ if (errno == EBADF) {
+ // it seems a socket notifier has a bad fd... find out
+ // which one it is and disable it
+ fd_set fdset;
+ timeval tm;
+ tm.tv_sec = tm.tv_usec = 0l;
+
+ for (int type = 0; type < 3; ++type) {
+ QSockNotType::List &list = sn_vec[type].list;
+ if (list.size() == 0)
+ continue;
+
+ for (int i = 0; i < list.size(); ++i) {
+ QSockNot *sn = list[i];
+
+ FD_ZERO(&fdset);
+ FD_SET(sn->fd, &fdset);
+
+ int ret = -1;
+ do {
+ switch (type) {
+ case 0: // read
+ ret = select(sn->fd + 1, &fdset, 0, 0, &tm);
+ break;
+ case 1: // write
+ ret = select(sn->fd + 1, 0, &fdset, 0, &tm);
+ break;
+ case 2: // except
+ ret = select(sn->fd + 1, 0, 0, &fdset, &tm);
+ break;
+ }
+ } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (ret == -1 && errno == EBADF) {
+ // disable the invalid socket notifier
+ static const char *t[] = { "Read", "Write", "Exception" };
+ qWarning("QSocketNotifier: Invalid socket %d and type '%s', disabling...",
+ sn->fd, t[type]);
+ sn->obj->setEnabled(false);
+ }
+ }
+ }
+ } else {
+ // EINVAL... shouldn't happen, so let's complain to stderr
+ // and hope someone sends us a bug report
+ perror("select");
+ }
+ }
+
+ // some other thread woke us up... consume the data on the thread pipe so that
+ // select doesn't immediately return next time
+ int nevents = 0;
+ if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) {
+#if defined(Q_OS_VXWORKS)
+ char c[16];
+ ::read(thread_pipe[0], c, sizeof(c));
+ ::ioctl(thread_pipe[0], FIOFLUSH, 0);
+#else
+ char c[16];
+ while (::read(thread_pipe[0], c, sizeof(c)) > 0)
+ ;
+#endif
+ if (!wakeUps.testAndSetRelease(1, 0)) {
+ // hopefully, this is dead code
+ qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!");
+ }
+ ++nevents;
+ }
+
+ // activate socket notifiers
+ if (! (flags & QEventLoop::ExcludeSocketNotifiers) && nsel > 0 && sn_highest >= 0) {
+ // if select says data is ready on any socket, then set the socket notifier
+ // to pending
+ for (int i=0; i<3; i++) {
+ QSockNotType::List &list = sn_vec[i].list;
+ for (int j = 0; j < list.size(); ++j) {
+ QSockNot *sn = list[j];
+ if (FD_ISSET(sn->fd, &sn_vec[i].select_fds))
+ q->setSocketNotifierPending(sn->obj);
+ }
+ }
+ }
+ return (nevents + q->activateSocketNotifiers());
+}
+
+/*
+ * Internal functions for manipulating timer data structures. The
+ * timerBitVec array is used for keeping track of timer identifiers.
+ */
+
+QTimerInfoList::QTimerInfoList()
+{
+#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL)
+ if (!QElapsedTimer::isMonotonic()) {
+ // not using monotonic timers, initialize the timeChanged() machinery
+ previousTime = qt_gettime();
+
+ tms unused;
+ previousTicks = times(&unused);
+
+ ticksPerSecond = sysconf(_SC_CLK_TCK);
+ msPerTick = 1000/ticksPerSecond;
+ } else {
+ // detected monotonic timers
+ previousTime.tv_sec = previousTime.tv_usec = 0;
+ previousTicks = 0;
+ ticksPerSecond = 0;
+ msPerTick = 0;
+ }
+#endif
+
+ firstTimerInfo = 0;
+}
+
+timeval QTimerInfoList::updateCurrentTime()
+{
+ return (currentTime = qt_gettime());
+}
+
+#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_INTEGRITY)) || defined(QT_BOOTSTRAPPED)
+
+template <>
+timeval qAbs(const timeval &t)
+{
+ timeval tmp = t;
+ if (tmp.tv_sec < 0) {
+ tmp.tv_sec = -tmp.tv_sec - 1;
+ tmp.tv_usec -= 1000000;
+ }
+ if (tmp.tv_sec == 0 && tmp.tv_usec < 0) {
+ tmp.tv_usec = -tmp.tv_usec;
+ }
+ return normalizedTimeval(tmp);
+}
+
+/*
+ Returns true if the real time clock has changed by more than 10%
+ relative to the processor time since the last time this function was
+ called. This presumably means that the system time has been changed.
+
+ If /a delta is nonzero, delta is set to our best guess at how much the system clock was changed.
+*/
+bool QTimerInfoList::timeChanged(timeval *delta)
+{
+#ifdef Q_OS_NACL
+ Q_UNUSED(delta)
+ return false; // Calling "times" crashes.
+#endif
+ struct tms unused;
+ clock_t currentTicks = times(&unused);
+
+ clock_t elapsedTicks = currentTicks - previousTicks;
+ timeval elapsedTime = currentTime - previousTime;
+
+ timeval elapsedTimeTicks;
+ elapsedTimeTicks.tv_sec = elapsedTicks / ticksPerSecond;
+ elapsedTimeTicks.tv_usec = (((elapsedTicks * 1000) / ticksPerSecond) % 1000) * 1000;
+
+ timeval dummy;
+ if (!delta)
+ delta = &dummy;
+ *delta = elapsedTime - elapsedTimeTicks;
+
+ previousTicks = currentTicks;
+ previousTime = currentTime;
+
+ // If tick drift is more than 10% off compared to realtime, we assume that the clock has
+ // been set. Of course, we have to allow for the tick granularity as well.
+ timeval tickGranularity;
+ tickGranularity.tv_sec = 0;
+ tickGranularity.tv_usec = msPerTick * 1000;
+ return elapsedTimeTicks < ((qAbs(*delta) - tickGranularity) * 10);
+}
+
+void QTimerInfoList::repairTimersIfNeeded()
+{
+ if (QElapsedTimer::isMonotonic())
+ return;
+ timeval delta;
+ if (timeChanged(&delta))
+ timerRepair(delta);
+}
+
+#else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED)
+
+void QTimerInfoList::repairTimersIfNeeded()
+{
+}
+
+#endif
+
+/*
+ insert timer info into list
+*/
+void QTimerInfoList::timerInsert(QTimerInfo *ti)
+{
+ int index = size();
+ while (index--) {
+ register const QTimerInfo * const t = at(index);
+ if (!(ti->timeout < t->timeout))
+ break;
+ }
+ insert(index+1, ti);
+}
+
+/*
+ repair broken timer
+*/
+void QTimerInfoList::timerRepair(const timeval &diff)
+{
+ // repair all timers
+ for (int i = 0; i < size(); ++i) {
+ register QTimerInfo *t = at(i);
+ t->timeout = t->timeout + diff;
+ }
+}
+
+/*
+ Returns the time to wait for the next timer, or null if no timers
+ are waiting.
+*/
+bool QTimerInfoList::timerWait(timeval &tm)
+{
+ timeval currentTime = updateCurrentTime();
+ repairTimersIfNeeded();
+
+ // Find first waiting timer not already active
+ QTimerInfo *t = 0;
+ for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
+ if (!(*it)->activateRef) {
+ t = *it;
+ break;
+ }
+ }
+
+ if (!t)
+ return false;
+
+ if (currentTime < t->timeout) {
+ // time to wait
+ tm = t->timeout - currentTime;
+ } else {
+ // no time to wait
+ tm.tv_sec = 0;
+ tm.tv_usec = 0;
+ }
+
+ return true;
+}
+
+void QTimerInfoList::registerTimer(int timerId, int interval, QObject *object)
+{
+ QTimerInfo *t = new QTimerInfo;
+ t->id = timerId;
+ t->interval.tv_sec = interval / 1000;
+ t->interval.tv_usec = (interval % 1000) * 1000;
+ t->timeout = updateCurrentTime() + t->interval;
+ t->obj = object;
+ t->activateRef = 0;
+
+ timerInsert(t);
+}
+
+bool QTimerInfoList::unregisterTimer(int timerId)
+{
+ // set timer inactive
+ for (int i = 0; i < count(); ++i) {
+ register QTimerInfo *t = at(i);
+ if (t->id == timerId) {
+ // found it
+ removeAt(i);
+ if (t == firstTimerInfo)
+ firstTimerInfo = 0;
+ if (t->activateRef)
+ *(t->activateRef) = 0;
+
+ // release the timer id
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(timerId);
+
+ delete t;
+ return true;
+ }
+ }
+ // id not found
+ return false;
+}
+
+bool QTimerInfoList::unregisterTimers(QObject *object)
+{
+ if (isEmpty())
+ return false;
+ for (int i = 0; i < count(); ++i) {
+ register QTimerInfo *t = at(i);
+ if (t->obj == object) {
+ // object found
+ removeAt(i);
+ if (t == firstTimerInfo)
+ firstTimerInfo = 0;
+ if (t->activateRef)
+ *(t->activateRef) = 0;
+
+ // release the timer id
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+ QAbstractEventDispatcherPrivate::releaseTimerId(t->id);
+
+ delete t;
+ // move back one so that we don't skip the new current item
+ --i;
+ }
+ }
+ return true;
+}
+
+QList<QPair<int, int> > QTimerInfoList::registeredTimers(QObject *object) const
+{
+ QList<QPair<int, int> > list;
+ for (int i = 0; i < count(); ++i) {
+ register const QTimerInfo * const t = at(i);
+ if (t->obj == object)
+ list << QPair<int, int>(t->id, t->interval.tv_sec * 1000 + t->interval.tv_usec / 1000);
+ }
+ return list;
+}
+
+/*
+ Activate pending timers, returning how many where activated.
+*/
+int QTimerInfoList::activateTimers()
+{
+ if (qt_disable_lowpriority_timers || isEmpty())
+ return 0; // nothing to do
+
+ int n_act = 0, maxCount = 0;
+ firstTimerInfo = 0;
+
+ timeval currentTime = updateCurrentTime();
+ repairTimersIfNeeded();
+
+
+ // Find out how many timer have expired
+ for (QTimerInfoList::const_iterator it = constBegin(); it != constEnd(); ++it) {
+ if (currentTime < (*it)->timeout)
+ break;
+ maxCount++;
+ }
+
+ //fire the timers.
+ while (maxCount--) {
+ if (isEmpty())
+ break;
+
+ QTimerInfo *currentTimerInfo = first();
+ if (currentTime < currentTimerInfo->timeout)
+ break; // no timer has expired
+
+ if (!firstTimerInfo) {
+ firstTimerInfo = currentTimerInfo;
+ } else if (firstTimerInfo == currentTimerInfo) {
+ // avoid sending the same timer multiple times
+ break;
+ } else if (currentTimerInfo->interval < firstTimerInfo->interval
+ || currentTimerInfo->interval == firstTimerInfo->interval) {
+ firstTimerInfo = currentTimerInfo;
+ }
+
+ // remove from list
+ removeFirst();
+
+ // determine next timeout time
+ currentTimerInfo->timeout += currentTimerInfo->interval;
+ if (currentTimerInfo->timeout < currentTime)
+ currentTimerInfo->timeout = currentTime + currentTimerInfo->interval;
+
+ // reinsert timer
+ timerInsert(currentTimerInfo);
+ if (currentTimerInfo->interval.tv_usec > 0 || currentTimerInfo->interval.tv_sec > 0)
+ n_act++;
+
+ if (!currentTimerInfo->activateRef) {
+ // send event, but don't allow it to recurse
+ currentTimerInfo->activateRef = &currentTimerInfo;
+
+ QTimerEvent e(currentTimerInfo->id);
+ QCoreApplication::sendEvent(currentTimerInfo->obj, &e);
+
+ if (currentTimerInfo)
+ currentTimerInfo->activateRef = 0;
+ }
+ }
+
+ firstTimerInfo = 0;
+ return n_act;
+}
+
+QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent)
+ : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent)
+{ }
+
+QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent)
+ : QAbstractEventDispatcher(dd, parent)
+{ }
+
+QEventDispatcherUNIX::~QEventDispatcherUNIX()
+{
+ Q_D(QEventDispatcherUNIX);
+ d->threadData->eventDispatcher = 0;
+}
+
+int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout)
+{
+ return qt_safe_select(nfds, readfds, writefds, exceptfds, timeout);
+}
+
+/*!
+ \internal
+*/
+void QEventDispatcherUNIX::registerTimer(int timerId, int interval, QObject *obj)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1 || interval < 0 || !obj) {
+ qWarning("QEventDispatcherUNIX::registerTimer: invalid arguments");
+ return;
+ } else if (obj->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ d->timerList.registerTimer(timerId, interval, obj);
+}
+
+/*!
+ \internal
+*/
+bool QEventDispatcherUNIX::unregisterTimer(int timerId)
+{
+#ifndef QT_NO_DEBUG
+ if (timerId < 1) {
+ qWarning("QEventDispatcherUNIX::unregisterTimer: invalid argument");
+ return false;
+ } else if (thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ return d->timerList.unregisterTimer(timerId);
+}
+
+/*!
+ \internal
+*/
+bool QEventDispatcherUNIX::unregisterTimers(QObject *object)
+{
+#ifndef QT_NO_DEBUG
+ if (!object) {
+ qWarning("QEventDispatcherUNIX::unregisterTimers: invalid argument");
+ return false;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ return d->timerList.unregisterTimers(object);
+}
+
+QList<QEventDispatcherUNIX::TimerInfo>
+QEventDispatcherUNIX::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherUNIX:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ Q_D(const QEventDispatcherUNIX);
+ return d->timerList.registeredTimers(object);
+}
+
+/*****************************************************************************
+ Socket notifier type
+ *****************************************************************************/
+QSockNotType::QSockNotType()
+{
+ FD_ZERO(&select_fds);
+ FD_ZERO(&enabled_fds);
+ FD_ZERO(&pending_fds);
+}
+
+QSockNotType::~QSockNotType()
+{
+ for (int i = 0; i < list.size(); ++i)
+ delete list[i];
+}
+
+/*****************************************************************************
+ QEventDispatcher implementations for UNIX
+ *****************************************************************************/
+
+void QEventDispatcherUNIX::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0
+ || unsigned(sockfd) >= FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ QSockNotType::List &list = d->sn_vec[type].list;
+ fd_set *fds = &d->sn_vec[type].enabled_fds;
+ QSockNot *sn;
+
+ sn = new QSockNot;
+ sn->obj = notifier;
+ sn->fd = sockfd;
+ sn->queue = &d->sn_vec[type].pending_fds;
+
+ int i;
+ for (i = 0; i < list.size(); ++i) {
+ QSockNot *p = list[i];
+ if (p->fd < sockfd)
+ break;
+ if (p->fd == sockfd) {
+ static const char *t[] = { "Read", "Write", "Exception" };
+ qWarning("QSocketNotifier: Multiple socket notifiers for "
+ "same socket %d and type %s", sockfd, t[type]);
+ }
+ }
+ list.insert(i, sn);
+
+ FD_SET(sockfd, fds);
+ d->sn_highest = qMax(d->sn_highest, sockfd);
+}
+
+void QEventDispatcherUNIX::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0
+ || unsigned(sockfd) >= FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread()
+ || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ QSockNotType::List &list = d->sn_vec[type].list;
+ fd_set *fds = &d->sn_vec[type].enabled_fds;
+ QSockNot *sn = 0;
+ int i;
+ for (i = 0; i < list.size(); ++i) {
+ sn = list[i];
+ if(sn->obj == notifier && sn->fd == sockfd)
+ break;
+ }
+ if (i == list.size()) // not found
+ return;
+
+ FD_CLR(sockfd, fds); // clear fd bit
+ FD_CLR(sockfd, sn->queue);
+ d->sn_pending_list.removeAll(sn); // remove from activation list
+ list.removeAt(i); // remove notifier found above
+ delete sn;
+
+ if (d->sn_highest == sockfd) { // find highest fd
+ d->sn_highest = -1;
+ for (int i=0; i<3; i++) {
+ if (!d->sn_vec[i].list.isEmpty())
+ d->sn_highest = qMax(d->sn_highest, // list is fd-sorted
+ d->sn_vec[i].list[0]->fd);
+ }
+ }
+}
+
+void QEventDispatcherUNIX::setSocketNotifierPending(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0
+ || unsigned(sockfd) >= FD_SETSIZE) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ }
+ Q_ASSERT(notifier->thread() == thread() && thread() == QThread::currentThread());
+#endif
+
+ Q_D(QEventDispatcherUNIX);
+ QSockNotType::List &list = d->sn_vec[type].list;
+ QSockNot *sn = 0;
+ int i;
+ for (i = 0; i < list.size(); ++i) {
+ sn = list[i];
+ if(sn->obj == notifier && sn->fd == sockfd)
+ break;
+ }
+ if (i == list.size()) // not found
+ return;
+
+ // We choose a random activation order to be more fair under high load.
+ // If a constant order is used and a peer early in the list can
+ // saturate the IO, it might grab our attention completely.
+ // Also, if we're using a straight list, the callback routines may
+ // delete other entries from the list before those other entries are
+ // processed.
+ if (! FD_ISSET(sn->fd, sn->queue)) {
+ if (d->sn_pending_list.isEmpty()) {
+ d->sn_pending_list.append(sn);
+ } else {
+ d->sn_pending_list.insert((qrand() & 0xff) %
+ (d->sn_pending_list.size()+1), sn);
+ }
+ FD_SET(sn->fd, sn->queue);
+ }
+}
+
+int QEventDispatcherUNIX::activateTimers()
+{
+ Q_ASSERT(thread() == QThread::currentThread());
+ Q_D(QEventDispatcherUNIX);
+ return d->timerList.activateTimers();
+}
+
+int QEventDispatcherUNIX::activateSocketNotifiers()
+{
+ Q_D(QEventDispatcherUNIX);
+ if (d->sn_pending_list.isEmpty())
+ return 0;
+
+ // activate entries
+ int n_act = 0;
+ QEvent event(QEvent::SockAct);
+ while (!d->sn_pending_list.isEmpty()) {
+ QSockNot *sn = d->sn_pending_list.takeFirst();
+ if (FD_ISSET(sn->fd, sn->queue)) {
+ FD_CLR(sn->fd, sn->queue);
+ QCoreApplication::sendEvent(sn->obj, &event);
+ ++n_act;
+ }
+ }
+ return n_act;
+}
+
+bool QEventDispatcherUNIX::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherUNIX);
+ d->interrupt = false;
+
+ // we are awake, broadcast it
+ emit awake();
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+
+ int nevents = 0;
+ const bool canWait = (d->threadData->canWait
+ && !d->interrupt
+ && (flags & QEventLoop::WaitForMoreEvents));
+
+ if (canWait)
+ emit aboutToBlock();
+
+ if (!d->interrupt) {
+ // return the maximum time we can wait for an event.
+ timeval *tm = 0;
+ timeval wait_tm = { 0l, 0l };
+ if (!(flags & QEventLoop::X11ExcludeTimers)) {
+ if (d->timerList.timerWait(wait_tm))
+ tm = &wait_tm;
+ }
+
+ if (!canWait) {
+ if (!tm)
+ tm = &wait_tm;
+
+ // no time to wait
+ tm->tv_sec = 0l;
+ tm->tv_usec = 0l;
+ }
+
+ nevents = d->doSelect(flags, tm);
+
+ // activate timers
+ if (! (flags & QEventLoop::X11ExcludeTimers)) {
+ nevents += activateTimers();
+ }
+ }
+ // return true if we handled events, false otherwise
+ return (nevents > 0);
+}
+
+bool QEventDispatcherUNIX::hasPendingEvents()
+{
+ extern uint qGlobalPostedEventsCount(); // from qapplication.cpp
+ return qGlobalPostedEventsCount();
+}
+
+void QEventDispatcherUNIX::wakeUp()
+{
+ Q_D(QEventDispatcherUNIX);
+ if (d->wakeUps.testAndSetAcquire(0, 1)) {
+ char c = 0;
+ qt_safe_write( d->thread_pipe[1], &c, 1 );
+ }
+}
+
+void QEventDispatcherUNIX::interrupt()
+{
+ Q_D(QEventDispatcherUNIX);
+ d->interrupt = true;
+ wakeUp();
+}
+
+void QEventDispatcherUNIX::flush()
+{ }
+
+
+
+
+void QCoreApplication::watchUnixSignal(int sig, bool watch)
+{
+ if (sig < NSIG) {
+ struct sigaction sa;
+ sigemptyset(&(sa.sa_mask));
+ sa.sa_flags = 0;
+ if (watch)
+ sa.sa_handler = signalHandler;
+ else
+ sa.sa_handler = SIG_DFL;
+ sigaction(sig, &sa, 0);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
new file mode 100644
index 0000000000..96a3e4a276
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QEVENTDISPATCHER_UNIX_P_H
+#define QEVENTDISPATCHER_UNIX_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 "QtCore/qabstracteventdispatcher.h"
+#include "QtCore/qlist.h"
+#include "private/qabstracteventdispatcher_p.h"
+#include "private/qcore_unix_p.h"
+#include "private/qpodlist_p.h"
+#include "QtCore/qvarlengtharray.h"
+
+#if defined(Q_OS_VXWORKS)
+# include <sys/times.h>
+#else
+# include <sys/time.h>
+# if (!defined(Q_OS_HPUX) || defined(__ia64)) && !defined(Q_OS_NACL)
+# include <sys/select.h>
+# endif
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// internal timer info
+struct QTimerInfo {
+ int id; // - timer identifier
+ timeval interval; // - timer interval
+ timeval timeout; // - when to sent event
+ QObject *obj; // - object to receive event
+ QTimerInfo **activateRef; // - ref from activateTimers
+};
+
+class QTimerInfoList : public QList<QTimerInfo*>
+{
+#if ((_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC)) || defined(QT_BOOTSTRAPPED)
+ timeval previousTime;
+ clock_t previousTicks;
+ int ticksPerSecond;
+ int msPerTick;
+
+ bool timeChanged(timeval *delta);
+#endif
+
+ // state variables used by activateTimers()
+ QTimerInfo *firstTimerInfo;
+
+public:
+ QTimerInfoList();
+
+ timeval currentTime;
+ timeval updateCurrentTime();
+
+ // must call updateCurrentTime() first!
+ void repairTimersIfNeeded();
+
+ bool timerWait(timeval &);
+ void timerInsert(QTimerInfo *);
+ void timerRepair(const timeval &);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<QPair<int, int> > registeredTimers(QObject *object) const;
+
+ int activateTimers();
+};
+
+struct QSockNot
+{
+ QSocketNotifier *obj;
+ int fd;
+ fd_set *queue;
+};
+
+class QSockNotType
+{
+public:
+ QSockNotType();
+ ~QSockNotType();
+
+ typedef QPodList<QSockNot*, 32> List;
+
+ List list;
+ fd_set select_fds;
+ fd_set enabled_fds;
+ fd_set pending_fds;
+
+};
+
+class QEventDispatcherUNIXPrivate;
+
+class Q_CORE_EXPORT QEventDispatcherUNIX : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherUNIX)
+
+public:
+ explicit QEventDispatcherUNIX(QObject *parent = 0);
+ ~QEventDispatcherUNIX();
+
+ bool processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+protected:
+ QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent = 0);
+
+ void setSocketNotifierPending(QSocketNotifier *notifier);
+
+ int activateTimers();
+ int activateSocketNotifiers();
+
+ virtual int select(int nfds,
+ fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout);
+};
+
+class Q_CORE_EXPORT QEventDispatcherUNIXPrivate : public QAbstractEventDispatcherPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherUNIX)
+
+public:
+ QEventDispatcherUNIXPrivate();
+ ~QEventDispatcherUNIXPrivate();
+
+ int doSelect(QEventLoop::ProcessEventsFlags flags, timeval *timeout);
+
+ bool mainThread;
+ int thread_pipe[2];
+
+ // highest fd for all socket notifiers
+ int sn_highest;
+ // 3 socket notifier types - read, write and exception
+ QSockNotType sn_vec[3];
+
+ QTimerInfoList timerList;
+
+ // pending socket notifiers list
+ QSockNotType::List sn_pending_list;
+
+ QAtomicInt wakeUps;
+ bool interrupt;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_UNIX_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
new file mode 100644
index 0000000000..6badb6a2f8
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -0,0 +1,1158 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qeventdispatcher_win_p.h"
+
+#include "qcoreapplication.h"
+#include "qhash.h"
+#include <private/qsystemlibrary_p.h>
+#include "qpair.h"
+#include "qset.h"
+#include "qsocketnotifier.h"
+#include "qvarlengtharray.h"
+#include "qwineventnotifier_p.h"
+
+#include "qabstracteventdispatcher_p.h"
+#include "qcoreapplication_p.h"
+#include <private/qthread_p.h>
+#include <private/qmutexpool_p.h>
+
+QT_BEGIN_NAMESPACE
+
+HINSTANCE qWinAppInst();
+extern uint qGlobalPostedEventsCount();
+
+#ifndef TIME_KILL_SYNCHRONOUS
+# define TIME_KILL_SYNCHRONOUS 0x0100
+#endif
+
+#ifndef QS_RAWINPUT
+# ifdef Q_OS_WINCE
+# define QS_RAWINPUT 0x0000
+# else
+# define QS_RAWINPUT 0x0400
+# endif
+#endif
+
+#ifndef WM_TOUCH
+# define WM_TOUCH 0x0240
+#endif
+#ifndef QT_NO_GESTURES
+#ifndef WM_GESTURE
+# define WM_GESTURE 0x0119
+#endif
+#ifndef WM_GESTURENOTIFY
+# define WM_GESTURENOTIFY 0x011A
+#endif
+#endif // QT_NO_GESTURES
+
+enum {
+ WM_QT_SOCKETNOTIFIER = WM_USER,
+ WM_QT_SENDPOSTEDEVENTS = WM_USER + 1,
+ SendPostedEventsWindowsTimerId = ~1u
+};
+
+#if defined(Q_OS_WINCE)
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <winsock.h>
+// Asynchronous Winsocks ------------------------------------------
+#ifndef QT_NO_THREAD
+#include <qthread.h>
+#include <qmap.h>
+#include <qmutex.h>
+QT_END_INCLUDE_NAMESPACE
+
+//#define QCE_ASYNC_DEBUG
+
+namespace {
+ class SocketAsyncHandler;
+
+ class SocketAsyncHandler : public QThread
+ {
+ public:
+ SocketAsyncHandler();
+ ~SocketAsyncHandler();
+ void run();
+ void select(SOCKET sock, HWND handle, unsigned int msg, long ev);
+ void removeSelect(SOCKET sock);
+ void safeRemove(SOCKET sock);
+ private:
+ struct SockInfo {
+ HWND handle;
+ unsigned int msg;
+ long ev;
+ };
+ QMap<SOCKET, SockInfo> sockets;
+ QMutex mutex;
+ QWaitCondition cond;
+ bool supposedToDie;
+ };
+
+ SocketAsyncHandler::SocketAsyncHandler()
+ : supposedToDie(false)
+ {
+ }
+
+ SocketAsyncHandler::~SocketAsyncHandler()
+ {
+ mutex.lock();
+ supposedToDie = true;
+ mutex.unlock();
+ cond.wakeOne();
+ wait();
+ while (sockets.size() > 0)
+ removeSelect(sockets.begin().key());
+ }
+
+ void SocketAsyncHandler::removeSelect(SOCKET sock)
+ {
+ if (!sockets.contains(sock))
+ return;
+ sockets.remove(sock);
+ return;
+ }
+
+ void SocketAsyncHandler::safeRemove(SOCKET sock)
+ {
+ QMutexLocker locker(&mutex);
+ removeSelect(sock);
+ }
+
+ void SocketAsyncHandler::select(SOCKET sock, HWND handle, unsigned int msg, long ev)
+ {
+ QMutexLocker locker(&mutex);
+
+ if (sockets.contains(sock))
+ sockets.remove(sock);
+
+ SockInfo info;
+ info.handle = handle;
+ info.msg = msg;
+ info.ev = ev;
+ sockets.insert(sock, info);
+ cond.wakeOne();
+ }
+
+ void SocketAsyncHandler::run()
+ {
+ do {
+ mutex.lock();
+
+ while (!supposedToDie && sockets.isEmpty()) {
+ cond.wait(&mutex);
+ }
+
+ if (supposedToDie) {
+ mutex.unlock();
+ break;
+ }
+
+ // Copy current items to reduce lock time
+ // and to be able to use SendMessage
+ QMap<SOCKET, SockInfo> currentSockets = sockets;
+ mutex.unlock();
+
+ fd_set readS, writeS, exS;
+ FD_ZERO(&readS);
+ FD_ZERO(&writeS);
+ FD_ZERO(&exS);
+
+ int maxFd = 0;
+
+ for (QMap<SOCKET, SockInfo>::iterator it = currentSockets.begin(); it != currentSockets.end(); ++it) {
+ const SockInfo &info = it.value();
+ int socket = it.key();
+ maxFd = qMax(maxFd, socket);
+
+ if ((info.ev & FD_READ) || (info.ev & FD_CLOSE) || (info.ev & FD_ACCEPT))
+ FD_SET(socket, &readS);
+ if ((info.ev & FD_WRITE)|| (info.ev & FD_CONNECT))
+ FD_SET(socket, &writeS);
+ if (info.ev & FD_OOB)
+ FD_SET(socket, &exS);
+ }
+
+ timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 50000;
+ int result = ::select(maxFd + 1, &readS, &writeS, &exS, &timeout);
+ if (result > 0) {
+ HWND handle;
+ unsigned int tmpMsg;
+ SOCKET sock;
+ HRESULT ret;
+ for (QMap<SOCKET, SockInfo>::const_iterator it = currentSockets.constBegin();
+ it != currentSockets.constEnd(); ++it) {
+ handle = (*it).handle;
+ tmpMsg = (*it).msg;
+ sock = it.key();
+ if (FD_ISSET(sock, &readS))
+ ret = SendMessage(handle, tmpMsg, sock, FD_READ);
+
+ if (FD_ISSET(sock, &writeS))
+ ret = SendMessage(handle, tmpMsg, sock, FD_WRITE);
+
+ if (FD_ISSET(sock, &exS))
+ ret = SendMessage(handle, tmpMsg, sock, FD_OOB);
+ }
+ }
+
+#ifdef QCE_ASYNC_DEBUG
+ else if (result == 0) { //timeout
+ qDebug(" WSAAsync select timeout");
+ } else if (result < 0) { // SocketError
+ // This might happen because of two reasons
+ // 1. We already closed a socket in between the copy and the select
+ // and thus select() returns an error
+ // 2. Something is really wrong, then
+ // ### Loop on all descriptors, try to select and remove the
+ // ### broken one.
+ qWarning("WSAAsync select error %d", WSAGetLastError());
+ }
+#endif
+ } while(true);
+ }
+} // namespace
+
+Q_GLOBAL_STATIC(SocketAsyncHandler, qt_async_handler)
+
+int WSAAsyncSelect(SOCKET sock, HWND handle, unsigned int msg, long ev)
+{
+ if (sock == 0 || handle == 0 || handle == INVALID_HANDLE_VALUE) {
+ WSASetLastError(WSAEINVAL);
+ return SOCKET_ERROR;
+ }
+
+ if (msg == 0 && ev == 0)
+ qt_async_handler()->safeRemove(sock);
+ else
+ qt_async_handler()->select(sock, handle, msg, ev);
+
+ qt_async_handler()->start(QThread::LowPriority);
+ WSASetLastError(0);
+ return 0;
+}
+#else // QT_NO_THREAD
+int WSAAsyncSelect(SOCKET, HWND, unsigned int, long)
+{
+ return SOCKET_ERROR;
+}
+#endif
+#endif // Q_OS_WINCE
+
+class QEventDispatcherWin32Private;
+
+struct QSockNot {
+ QSocketNotifier *obj;
+ int fd;
+};
+typedef QHash<int, QSockNot *> QSNDict;
+
+struct WinTimerInfo { // internal timer info
+ QObject *dispatcher;
+ int timerId;
+ int interval;
+ QObject *obj; // - object to receive events
+ bool inTimerEvent;
+ int fastTimerId;
+};
+
+class QZeroTimerEvent : public QTimerEvent
+{
+public:
+ inline QZeroTimerEvent(int timerId)
+ : QTimerEvent(timerId)
+ { t = QEvent::ZeroTimerEvent; }
+};
+
+typedef QList<WinTimerInfo*> WinTimerVec; // vector of TimerInfo structs
+typedef QHash<int, WinTimerInfo*> WinTimerDict; // fast dict of timers
+
+#if !defined(DWORD_PTR) && !defined(Q_WS_WIN64)
+#define DWORD_PTR DWORD
+#endif
+
+typedef MMRESULT(WINAPI *ptimeSetEvent)(UINT, UINT, LPTIMECALLBACK, DWORD_PTR, UINT);
+typedef MMRESULT(WINAPI *ptimeKillEvent)(UINT);
+
+static ptimeSetEvent qtimeSetEvent = 0;
+static ptimeKillEvent qtimeKillEvent = 0;
+
+LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+
+static void resolveTimerAPI()
+{
+ static bool triedResolve = false;
+ if (!triedResolve) {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
+ if (triedResolve)
+ return;
+#endif
+ triedResolve = true;
+#if !defined(Q_OS_WINCE)
+ qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeSetEvent");
+ qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("winmm"), "timeKillEvent");
+#else
+ qtimeSetEvent = (ptimeSetEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent");
+ qtimeKillEvent = (ptimeKillEvent)QSystemLibrary::resolve(QLatin1String("Mmtimer"), "timeKillEvent");
+#endif
+ }
+}
+
+
+class QEventDispatcherWin32Private : public QAbstractEventDispatcherPrivate
+{
+ Q_DECLARE_PUBLIC(QEventDispatcherWin32)
+public:
+ QEventDispatcherWin32Private();
+ ~QEventDispatcherWin32Private();
+
+ DWORD threadId;
+
+ bool interrupt;
+
+ // internal window handle used for socketnotifiers/timers/etc
+ HWND internalHwnd;
+ HHOOK getMessageHook;
+
+ // for controlling when to send posted events
+ QAtomicInt serialNumber;
+ int lastSerialNumber, sendPostedEventsWindowsTimerId;
+ QAtomicInt wakeUps;
+
+ // timers
+ WinTimerVec timerVec;
+ WinTimerDict timerDict;
+ void registerTimer(WinTimerInfo *t);
+ void unregisterTimer(WinTimerInfo *t, bool closingDown = false);
+ void sendTimerEvent(int timerId);
+
+ // socket notifiers
+ QSNDict sn_read;
+ QSNDict sn_write;
+ QSNDict sn_except;
+ void doWsaAsyncSelect(int socket);
+
+ QList<QWinEventNotifier *> winEventNotifierList;
+ void activateEventNotifier(QWinEventNotifier * wen);
+
+ QList<MSG> queuedUserInputEvents;
+ QList<MSG> queuedSocketEvents;
+};
+
+QEventDispatcherWin32Private::QEventDispatcherWin32Private()
+ : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0), getMessageHook(0),
+ serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), wakeUps(0)
+{
+ resolveTimerAPI();
+}
+
+QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
+{
+ if (internalHwnd)
+ DestroyWindow(internalHwnd);
+ QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
+ UnregisterClass((wchar_t*)className.utf16(), qWinAppInst());
+}
+
+void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
+{
+ QEvent event(QEvent::WinEventAct);
+ QCoreApplication::sendEvent(wen, &event);
+}
+
+// ### Qt 5: remove
+Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax, UINT wRemoveMsg)
+{
+ return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
+}
+
+// ### Qt 5: remove
+Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ return PostMessage(hWnd, msg, wParam, lParam);
+}
+
+// ### Qt 5: remove
+Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax)
+{
+ return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax);
+}
+
+// This function is called by a workerthread
+void WINAPI QT_WIN_CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_PTR user, DWORD_PTR /*reserved*/, DWORD_PTR /*reserved*/)
+{
+ if (!timerId) // sanity check
+ return;
+ WinTimerInfo *t = (WinTimerInfo*)user;
+ Q_ASSERT(t);
+ QCoreApplication::postEvent(t->dispatcher, new QTimerEvent(t->timerId));
+}
+
+LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
+{
+ if (message == WM_NCCREATE)
+ return true;
+
+ MSG msg;
+ msg.hwnd = hwnd;
+ msg.message = message;
+ msg.wParam = wp;
+ msg.lParam = lp;
+ QCoreApplication *app = QCoreApplication::instance();
+ long result;
+ if (!app) {
+ if (message == WM_TIMER)
+ KillTimer(hwnd, wp);
+ return 0;
+ } else if (app->filterEvent(&msg, &result)) {
+ return result;
+ }
+
+#ifdef GWLP_USERDATA
+ QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
+#else
+ QEventDispatcherWin32 *q = (QEventDispatcherWin32 *) GetWindowLong(hwnd, GWL_USERDATA);
+#endif
+ QEventDispatcherWin32Private *d = 0;
+ if (q != 0)
+ d = q->d_func();
+
+ if (message == WM_QT_SOCKETNOTIFIER) {
+ // socket notifier message
+ int type = -1;
+ switch (WSAGETSELECTEVENT(lp)) {
+ case FD_READ:
+ case FD_CLOSE:
+ case FD_ACCEPT:
+ type = 0;
+ break;
+ case FD_WRITE:
+ case FD_CONNECT:
+ type = 1;
+ break;
+ case FD_OOB:
+ type = 2;
+ break;
+ }
+ if (type >= 0) {
+ Q_ASSERT(d != 0);
+ QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+ QSNDict *dict = sn_vec[type];
+
+ QSockNot *sn = dict ? dict->value(wp) : 0;
+ if (sn) {
+ QEvent event(QEvent::SockAct);
+ QCoreApplication::sendEvent(sn->obj, &event);
+ }
+ }
+ return 0;
+ } else if (message == WM_QT_SENDPOSTEDEVENTS
+ // we also use a Windows timer to send posted events when the message queue is full
+ || (message == WM_TIMER
+ && d->sendPostedEventsWindowsTimerId != 0
+ && wp == (uint)d->sendPostedEventsWindowsTimerId)) {
+ int localSerialNumber = d->serialNumber;
+ if (localSerialNumber != d->lastSerialNumber) {
+ d->lastSerialNumber = localSerialNumber;
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ }
+ return 0;
+ } else if (message == WM_TIMER) {
+ Q_ASSERT(d != 0);
+ d->sendTimerEvent(wp);
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, message, wp, lp);
+}
+
+LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int code, WPARAM wp, LPARAM lp)
+{
+ if (wp == PM_REMOVE) {
+ QEventDispatcherWin32 *q = qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
+ Q_ASSERT(q != 0);
+ if (q) {
+ MSG *msg = (MSG *) lp;
+ QEventDispatcherWin32Private *d = q->d_func();
+ int localSerialNumber = d->serialNumber;
+ if (HIWORD(GetQueueStatus(QS_TIMER | QS_INPUT | QS_RAWINPUT)) == 0) {
+ // no more input or timer events in the message queue, we can allow posted events to be sent normally now
+ if (d->sendPostedEventsWindowsTimerId != 0) {
+ // stop the timer to send posted events, since we now allow the WM_QT_SENDPOSTEDEVENTS message
+ KillTimer(d->internalHwnd, d->sendPostedEventsWindowsTimerId);
+ d->sendPostedEventsWindowsTimerId = 0;
+ }
+ (void) d->wakeUps.fetchAndStoreRelease(0);
+ if (localSerialNumber != d->lastSerialNumber
+ // if this message IS the one that triggers sendPostedEvents(), no need to post it again
+ && (msg->hwnd != d->internalHwnd
+ || msg->message != WM_QT_SENDPOSTEDEVENTS)) {
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+ }
+ } else if (d->sendPostedEventsWindowsTimerId == 0
+ && localSerialNumber != d->lastSerialNumber) {
+ // start a special timer to continue delivering posted events while
+ // there are still input and timer messages in the message queue
+ d->sendPostedEventsWindowsTimerId = SetTimer(d->internalHwnd,
+ SendPostedEventsWindowsTimerId,
+ 0, // we specify zero, but Windows uses USER_TIMER_MINIMUM
+ NULL);
+ // we don't check the return value of SetTimer()... if creating the timer failed, there's little
+ // we can do. we just have to accept that posted events will be starved
+ }
+ }
+ }
+#ifdef Q_OS_WINCE
+ return 0;
+#else
+ return CallNextHookEx(0, code, wp, lp);
+#endif
+}
+
+static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
+{
+ // make sure that multiple Qt's can coexist in the same process
+ QString className = QLatin1String("QEventDispatcherWin32_Internal_Widget") + QString::number(quintptr(qt_internal_proc));
+
+ WNDCLASS wc;
+ wc.style = 0;
+ wc.lpfnWndProc = qt_internal_proc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = qWinAppInst();
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = reinterpret_cast<const wchar_t *> (className.utf16());
+
+ RegisterClass(&wc);
+ HWND wnd = CreateWindow(wc.lpszClassName, // classname
+ wc.lpszClassName, // window name
+ 0, // style
+ 0, 0, 0, 0, // geometry
+ 0, // parent
+ 0, // menu handle
+ qWinAppInst(), // application
+ 0); // windows creation data.
+
+ if (!wnd) {
+ qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
+ }
+
+#ifdef GWLP_USERDATA
+ SetWindowLongPtr(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
+#else
+ SetWindowLong(wnd, GWL_USERDATA, (LONG)eventDispatcher);
+#endif
+
+ return wnd;
+}
+
+void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
+{
+ Q_ASSERT(internalHwnd);
+
+ Q_Q(QEventDispatcherWin32);
+
+ int ok = 0;
+ if (t->interval > 20 || !t->interval || !qtimeSetEvent) {
+ ok = 1;
+ if (!t->interval) // optimization for single-shot-zero-timer
+ QCoreApplication::postEvent(q, new QZeroTimerEvent(t->timerId));
+ else
+ ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
+ } else {
+ ok = t->fastTimerId = qtimeSetEvent(t->interval, 1, qt_fast_timer_proc, (DWORD_PTR)t,
+ TIME_CALLBACK_FUNCTION | TIME_PERIODIC | TIME_KILL_SYNCHRONOUS);
+ if (ok == 0) { // fall back to normal timer if no more multimedia timers available
+ ok = SetTimer(internalHwnd, t->timerId, (uint) t->interval, 0);
+ }
+ }
+
+ if (ok == 0)
+ qErrnoWarning("QEventDispatcherWin32::registerTimer: Failed to create a timer");
+}
+
+void QEventDispatcherWin32Private::unregisterTimer(WinTimerInfo *t, bool closingDown)
+{
+ // mark timer as unused
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent && !closingDown)
+ QAbstractEventDispatcherPrivate::releaseTimerId(t->timerId);
+
+ if (t->interval == 0) {
+ QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+ } else if (t->fastTimerId != 0) {
+ qtimeKillEvent(t->fastTimerId);
+ QCoreApplicationPrivate::removePostedTimerEvent(t->dispatcher, t->timerId);
+ } else if (internalHwnd) {
+ KillTimer(internalHwnd, t->timerId);
+ }
+ delete t;
+}
+
+void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
+{
+ WinTimerInfo *t = timerDict.value(timerId);
+ if (t && !t->inTimerEvent) {
+ // send event, but don't allow it to recurse
+ t->inTimerEvent = true;
+
+ QTimerEvent e(t->timerId);
+ QCoreApplication::sendEvent(t->obj, &e);
+
+ // timer could have been removed
+ t = timerDict.value(timerId);
+ if (t) {
+ t->inTimerEvent = false;
+ }
+ }
+}
+
+void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket)
+{
+ Q_ASSERT(internalHwnd);
+ int sn_event = 0;
+ if (sn_read.contains(socket))
+ sn_event |= FD_READ | FD_CLOSE | FD_ACCEPT;
+ if (sn_write.contains(socket))
+ sn_event |= FD_WRITE | FD_CONNECT;
+ if (sn_except.contains(socket))
+ sn_event |= FD_OOB;
+ // BoundsChecker may emit a warning for WSAAsyncSelect when sn_event == 0
+ // This is a BoundsChecker bug and not a Qt bug
+ WSAAsyncSelect(socket, internalHwnd, sn_event ? WM_QT_SOCKETNOTIFIER : 0, sn_event);
+}
+
+void QEventDispatcherWin32::createInternalHwnd()
+{
+ Q_D(QEventDispatcherWin32);
+
+ Q_ASSERT(!d->internalHwnd);
+ if (d->internalHwnd)
+ return;
+ d->internalHwnd = qt_create_internal_window(this);
+
+#ifndef Q_OS_WINCE
+ // setup GetMessage hook needed to drive our posted events
+ d->getMessageHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC) qt_GetMessageHook, NULL, GetCurrentThreadId());
+ if (!d->getMessageHook) {
+ qFatal("Qt: INTERNALL ERROR: failed to install GetMessage hook");
+ }
+#endif
+
+ // register all socket notifiers
+ QList<int> sockets = (d->sn_read.keys().toSet()
+ + d->sn_write.keys().toSet()
+ + d->sn_except.keys().toSet()).toList();
+ for (int i = 0; i < sockets.count(); ++i)
+ d->doWsaAsyncSelect(sockets.at(i));
+
+ // start all normal timers
+ for (int i = 0; i < d->timerVec.count(); ++i)
+ d->registerTimer(d->timerVec.at(i));
+
+ // trigger a call to sendPostedEvents()
+ wakeUp();
+}
+
+QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
+ : QAbstractEventDispatcher(*new QEventDispatcherWin32Private, parent)
+{
+}
+
+QEventDispatcherWin32::~QEventDispatcherWin32()
+{
+}
+
+bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
+{
+ Q_D(QEventDispatcherWin32);
+
+ if (!d->internalHwnd)
+ createInternalHwnd();
+
+ d->interrupt = false;
+ emit awake();
+
+ bool canWait;
+ bool retVal = false;
+ bool seenWM_QT_SENDPOSTEDEVENTS = false;
+ bool needWM_QT_SENDPOSTEDEVENTS = false;
+ do {
+ DWORD waitRet = 0;
+ HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
+ QVarLengthArray<MSG> processedTimers;
+ while (!d->interrupt) {
+ DWORD nCount = d->winEventNotifierList.count();
+ Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
+
+ MSG msg;
+ bool haveMessage;
+
+ if (!(flags & QEventLoop::ExcludeUserInputEvents) && !d->queuedUserInputEvents.isEmpty()) {
+ // process queued user input events
+ haveMessage = true;
+ msg = d->queuedUserInputEvents.takeFirst();
+ } else if(!(flags & QEventLoop::ExcludeSocketNotifiers) && !d->queuedSocketEvents.isEmpty()) {
+ // process queued socket events
+ haveMessage = true;
+ msg = d->queuedSocketEvents.takeFirst();
+ } else {
+ haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);
+ if (haveMessage && (flags & QEventLoop::ExcludeUserInputEvents)
+ && ((msg.message >= WM_KEYFIRST
+ && msg.message <= WM_KEYLAST)
+ || (msg.message >= WM_MOUSEFIRST
+ && msg.message <= WM_MOUSELAST)
+ || msg.message == WM_MOUSEWHEEL
+ || msg.message == WM_MOUSEHWHEEL
+ || msg.message == WM_TOUCH
+#ifndef QT_NO_GESTURES
+ || msg.message == WM_GESTURE
+ || msg.message == WM_GESTURENOTIFY
+#endif
+ || msg.message == WM_CLOSE)) {
+ // queue user input events for later processing
+ haveMessage = false;
+ d->queuedUserInputEvents.append(msg);
+ }
+ if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
+ && (msg.message == WM_QT_SOCKETNOTIFIER && msg.hwnd == d->internalHwnd)) {
+ // queue socket events for later processing
+ haveMessage = false;
+ d->queuedSocketEvents.append(msg);
+ }
+ }
+ if (!haveMessage) {
+ // no message - check for signalled objects
+ for (int i=0; i<(int)nCount; i++)
+ pHandles[i] = d->winEventNotifierList.at(i)->handle();
+ waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
+ if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
+ // a new message has arrived, process it
+ continue;
+ }
+ }
+ if (haveMessage) {
+#ifdef Q_OS_WINCE
+ // WinCE doesn't support hooks at all, so we have to call this by hand :(
+ (void) qt_GetMessageHook(0, PM_REMOVE, (LPARAM) &msg);
+#endif
+
+ if (d->internalHwnd == msg.hwnd && msg.message == WM_QT_SENDPOSTEDEVENTS) {
+ if (seenWM_QT_SENDPOSTEDEVENTS) {
+ // when calling processEvents() "manually", we only want to send posted
+ // events once
+ needWM_QT_SENDPOSTEDEVENTS = true;
+ continue;
+ }
+ seenWM_QT_SENDPOSTEDEVENTS = true;
+ } else if (msg.message == WM_TIMER) {
+ // avoid live-lock by keeping track of the timers we've already sent
+ bool found = false;
+ for (int i = 0; !found && i < processedTimers.count(); ++i) {
+ const MSG processed = processedTimers.constData()[i];
+ found = (processed.wParam == msg.wParam && processed.hwnd == msg.hwnd && processed.lParam == msg.lParam);
+ }
+ if (found)
+ continue;
+ processedTimers.append(msg);
+ } else if (msg.message == WM_QUIT) {
+ if (QCoreApplication::instance())
+ QCoreApplication::instance()->quit();
+ return false;
+ }
+
+ if (!filterEvent(&msg)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ } else if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
+ d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
+ } else {
+ // nothing todo so break
+ break;
+ }
+ retVal = true;
+ }
+
+ // still nothing - wait for message or signalled objects
+ canWait = (!retVal
+ && !d->interrupt
+ && (flags & QEventLoop::WaitForMoreEvents));
+ if (canWait) {
+ DWORD nCount = d->winEventNotifierList.count();
+ Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
+ for (int i=0; i<(int)nCount; i++)
+ pHandles[i] = d->winEventNotifierList.at(i)->handle();
+
+ emit aboutToBlock();
+ waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
+ emit awake();
+ if (waitRet >= WAIT_OBJECT_0 && waitRet < WAIT_OBJECT_0 + nCount) {
+ d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
+ retVal = true;
+ }
+ }
+ } while (canWait);
+
+ if (!seenWM_QT_SENDPOSTEDEVENTS && (flags & QEventLoop::EventLoopExec) == 0) {
+ // when called "manually", always send posted events
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+ }
+
+ if (needWM_QT_SENDPOSTEDEVENTS)
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+
+ return retVal;
+}
+
+bool QEventDispatcherWin32::hasPendingEvents()
+{
+ MSG msg;
+ return qGlobalPostedEventsCount() || PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
+}
+
+void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be enabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherWin32);
+ QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+ QSNDict *dict = sn_vec[type];
+
+ if (QCoreApplication::closingDown()) // ### d->exitloop?
+ return; // after sn_cleanup, don't reinitialize.
+
+ if (dict->contains(sockfd)) {
+ const char *t[] = { "Read", "Write", "Exception" };
+ /* Variable "socket" below is a function pointer. */
+ qWarning("QSocketNotifier: Multiple socket notifiers for "
+ "same socket %d and type %s", sockfd, t[type]);
+ }
+
+ QSockNot *sn = new QSockNot;
+ sn->obj = notifier;
+ sn->fd = sockfd;
+ dict->insert(sn->fd, sn);
+
+ if (d->internalHwnd)
+ d->doWsaAsyncSelect(sockfd);
+}
+
+void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
+{
+ Q_ASSERT(notifier);
+ int sockfd = notifier->socket();
+ int type = notifier->type();
+#ifndef QT_NO_DEBUG
+ if (sockfd < 0) {
+ qWarning("QSocketNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QSocketNotifier: socket notifiers cannot be disabled from another thread");
+ return;
+ }
+#endif
+
+ Q_D(QEventDispatcherWin32);
+ QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except };
+ QSNDict *dict = sn_vec[type];
+ QSockNot *sn = dict->value(sockfd);
+ if (!sn)
+ return;
+
+ dict->remove(sockfd);
+ delete sn;
+
+ if (d->internalHwnd)
+ d->doWsaAsyncSelect(sockfd);
+}
+
+void QEventDispatcherWin32::registerTimer(int timerId, int interval, QObject *object)
+{
+ if (timerId < 1 || interval < 0 || !object) {
+ qWarning("QEventDispatcherWin32::registerTimer: invalid arguments");
+ return;
+ } else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QObject::startTimer: timers cannot be started from another thread");
+ return;
+ }
+
+ Q_D(QEventDispatcherWin32);
+
+ register WinTimerInfo *t = new WinTimerInfo;
+ t->dispatcher = this;
+ t->timerId = timerId;
+ t->interval = interval;
+ t->obj = object;
+ t->inTimerEvent = false;
+ t->fastTimerId = 0;
+
+ if (d->internalHwnd)
+ d->registerTimer(t);
+
+ d->timerVec.append(t); // store in timer vector
+ d->timerDict.insert(t->timerId, t); // store timers in dict
+}
+
+bool QEventDispatcherWin32::unregisterTimer(int timerId)
+{
+ if (timerId < 1) {
+ qWarning("QEventDispatcherWin32::unregisterTimer: invalid argument");
+ return false;
+ }
+ QThread *currentThread = QThread::currentThread();
+ if (thread() != currentThread) {
+ qWarning("QObject::killTimer: timers cannot be stopped from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWin32);
+ if (d->timerVec.isEmpty() || timerId <= 0)
+ return false;
+
+ WinTimerInfo *t = d->timerDict.value(timerId);
+ if (!t)
+ return false;
+
+ d->timerDict.remove(t->timerId);
+ d->timerVec.removeAll(t);
+ d->unregisterTimer(t);
+ return true;
+}
+
+bool QEventDispatcherWin32::unregisterTimers(QObject *object)
+{
+ if (!object) {
+ qWarning("QEventDispatcherWin32::unregisterTimers: invalid argument");
+ return false;
+ }
+ QThread *currentThread = QThread::currentThread();
+ if (object->thread() != thread() || thread() != currentThread) {
+ qWarning("QObject::killTimers: timers cannot be stopped from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWin32);
+ if (d->timerVec.isEmpty())
+ return false;
+ register WinTimerInfo *t;
+ for (int i=0; i<d->timerVec.size(); i++) {
+ t = d->timerVec.at(i);
+ if (t && t->obj == object) { // object found
+ d->timerDict.remove(t->timerId);
+ d->timerVec.removeAt(i);
+ d->unregisterTimer(t);
+ --i;
+ }
+ }
+ return true;
+}
+
+QList<QEventDispatcherWin32::TimerInfo>
+QEventDispatcherWin32::registeredTimers(QObject *object) const
+{
+ if (!object) {
+ qWarning("QEventDispatcherWin32:registeredTimers: invalid argument");
+ return QList<TimerInfo>();
+ }
+
+ Q_D(const QEventDispatcherWin32);
+ QList<TimerInfo> list;
+ for (int i = 0; i < d->timerVec.size(); ++i) {
+ const WinTimerInfo *t = d->timerVec.at(i);
+ if (t && t->obj == object)
+ list << TimerInfo(t->timerId, t->interval);
+ }
+ return list;
+}
+
+bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier)
+{
+ if (!notifier) {
+ qWarning("QWinEventNotifier: Internal error");
+ return false;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QWinEventNotifier: event notifiers cannot be enabled from another thread");
+ return false;
+ }
+
+ Q_D(QEventDispatcherWin32);
+
+ if (d->winEventNotifierList.contains(notifier))
+ return true;
+
+ if (d->winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 2) {
+ qWarning("QWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 2);
+ return false;
+ }
+ d->winEventNotifierList.append(notifier);
+ return true;
+}
+
+void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
+{
+ if (!notifier) {
+ qWarning("QWinEventNotifier: Internal error");
+ return;
+ } else if (notifier->thread() != thread() || thread() != QThread::currentThread()) {
+ qWarning("QWinEventNotifier: event notifiers cannot be disabled from another thread");
+ return;
+ }
+
+ Q_D(QEventDispatcherWin32);
+
+ int i = d->winEventNotifierList.indexOf(notifier);
+ if (i != -1)
+ d->winEventNotifierList.takeAt(i);
+}
+
+void QEventDispatcherWin32::activateEventNotifiers()
+{
+ Q_D(QEventDispatcherWin32);
+ //### this could break if events are removed/added in the activation
+ for (int i=0; i<d->winEventNotifierList.count(); i++) {
+#if !defined(Q_OS_WINCE)
+ if (WaitForSingleObjectEx(d->winEventNotifierList.at(i)->handle(), 0, TRUE) == WAIT_OBJECT_0)
+ d->activateEventNotifier(d->winEventNotifierList.at(i));
+#else
+ if (WaitForSingleObject(d->winEventNotifierList.at(i)->handle(), 0) == WAIT_OBJECT_0)
+ d->activateEventNotifier(d->winEventNotifierList.at(i));
+#endif
+ }
+}
+
+void QEventDispatcherWin32::wakeUp()
+{
+ Q_D(QEventDispatcherWin32);
+ d->serialNumber.ref();
+ if (d->internalHwnd && d->wakeUps.testAndSetAcquire(0, 1)) {
+ // post a WM_QT_SENDPOSTEDEVENTS to this thread if there isn't one already pending
+ PostMessage(d->internalHwnd, WM_QT_SENDPOSTEDEVENTS, 0, 0);
+ }
+}
+
+void QEventDispatcherWin32::interrupt()
+{
+ Q_D(QEventDispatcherWin32);
+ d->interrupt = true;
+ wakeUp();
+}
+
+void QEventDispatcherWin32::flush()
+{ }
+
+void QEventDispatcherWin32::startingUp()
+{ }
+
+void QEventDispatcherWin32::closingDown()
+{
+ Q_D(QEventDispatcherWin32);
+
+ // clean up any socketnotifiers
+ while (!d->sn_read.isEmpty())
+ unregisterSocketNotifier((*(d->sn_read.begin()))->obj);
+ while (!d->sn_write.isEmpty())
+ unregisterSocketNotifier((*(d->sn_write.begin()))->obj);
+ while (!d->sn_except.isEmpty())
+ unregisterSocketNotifier((*(d->sn_except.begin()))->obj);
+
+ // clean up any timers
+ for (int i = 0; i < d->timerVec.count(); ++i)
+ d->unregisterTimer(d->timerVec.at(i), true);
+ d->timerVec.clear();
+ d->timerDict.clear();
+
+#ifndef Q_OS_WINCE
+ if (d->getMessageHook)
+ UnhookWindowsHookEx(d->getMessageHook);
+ d->getMessageHook = 0;
+#endif
+}
+
+bool QEventDispatcherWin32::event(QEvent *e)
+{
+ Q_D(QEventDispatcherWin32);
+ if (e->type() == QEvent::ZeroTimerEvent) {
+ QZeroTimerEvent *zte = static_cast<QZeroTimerEvent*>(e);
+ WinTimerInfo *t = d->timerDict.value(zte->timerId());
+ if (t) {
+ t->inTimerEvent = true;
+
+ QTimerEvent te(zte->timerId());
+ QCoreApplication::sendEvent(t->obj, &te);
+
+ t = d->timerDict.value(zte->timerId());
+ if (t) {
+ if (t->interval == 0 && t->inTimerEvent) {
+ // post the next zero timer event as long as the timer was not restarted
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
+ }
+
+ t->inTimerEvent = false;
+ }
+ }
+ return true;
+ } else if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent*>(e);
+ d->sendTimerEvent(te->timerId());
+ }
+ return QAbstractEventDispatcher::event(e);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
new file mode 100644
index 0000000000..2e3a5bca19
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -0,0 +1,110 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QEVENTDISPATCHER_WIN_P_H
+#define QEVENTDISPATCHER_WIN_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 "QtCore/qabstracteventdispatcher.h"
+#include "QtCore/qt_windows.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWinEventNotifier;
+class QEventDispatcherWin32Private;
+
+// forward declaration
+LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+
+class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventDispatcherWin32)
+
+ void createInternalHwnd();
+ friend class QGuiEventDispatcherWin32;
+
+public:
+ explicit QEventDispatcherWin32(QObject *parent = 0);
+ ~QEventDispatcherWin32();
+
+ bool QT_ENSURE_STACK_ALIGNED_FOR_SSE processEvents(QEventLoop::ProcessEventsFlags flags);
+ bool hasPendingEvents();
+
+ void registerSocketNotifier(QSocketNotifier *notifier);
+ void unregisterSocketNotifier(QSocketNotifier *notifier);
+
+ void registerTimer(int timerId, int interval, QObject *object);
+ bool unregisterTimer(int timerId);
+ bool unregisterTimers(QObject *object);
+ QList<TimerInfo> registeredTimers(QObject *object) const;
+
+ bool registerEventNotifier(QWinEventNotifier *notifier);
+ void unregisterEventNotifier(QWinEventNotifier *notifier);
+ void activateEventNotifiers();
+
+ void wakeUp();
+ void interrupt();
+ void flush();
+
+ void startingUp();
+ void closingDown();
+
+ bool event(QEvent *e);
+
+private:
+ friend LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+ friend LRESULT QT_WIN_CALLBACK qt_GetMessageHook(int, WPARAM, LPARAM);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_WIN_P_H
diff --git a/src/corelib/kernel/qeventloop.cpp b/src/corelib/kernel/qeventloop.cpp
new file mode 100644
index 0000000000..d213b0e968
--- /dev/null
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -0,0 +1,329 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qeventloop.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qelapsedtimer.h"
+
+#include "qobject_p.h"
+#include <private/qthread_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QEventLoopPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QEventLoop)
+public:
+ inline QEventLoopPrivate()
+ : exit(true), inExec(false), returnCode(-1)
+ { }
+ bool exit, inExec;
+ int returnCode;
+};
+
+/*!
+ \class QEventLoop
+ \brief The QEventLoop class provides a means of entering and leaving an event loop.
+
+ At any time, you can create a QEventLoop object and call exec()
+ on it to start a local event loop. From within the event loop,
+ calling exit() will force exec() to return.
+
+ \sa QAbstractEventDispatcher
+*/
+
+/*!
+ \enum QEventLoop::ProcessEventsFlag
+
+ This enum controls the types of events processed by the
+ processEvents() functions.
+
+ \value AllEvents All events. Note that
+ \l{QEvent::DeferredDelete}{DeferredDelete} events are processed
+ specially. See QObject::deleteLater() for more details.
+
+ \value ExcludeUserInputEvents Do not process user input events,
+ such as ButtonPress and KeyPress. Note that the events are not
+ discarded; they will be delivered the next time processEvents() is
+ called without the ExcludeUserInputEvents flag.
+
+ \value ExcludeSocketNotifiers Do not process socket notifier
+ events. Note that the events are not discarded; they will be
+ delivered the next time processEvents() is called without the
+ ExcludeSocketNotifiers flag.
+
+ \value WaitForMoreEvents Wait for events if no pending events are
+ available.
+
+ \omitvalue X11ExcludeTimers
+ \omitvalue ExcludeUserInput
+ \omitvalue WaitForMore
+ \omitvalue EventLoopExec
+ \omitvalue DialogExec
+ \value DeferredDeletion deprecated - do not use.
+
+ \sa processEvents()
+*/
+
+/*!
+ Constructs an event loop object with the given \a parent.
+*/
+QEventLoop::QEventLoop(QObject *parent)
+ : QObject(*new QEventLoopPrivate, parent)
+{
+ Q_D(QEventLoop);
+ if (!QCoreApplication::instance()) {
+ qWarning("QEventLoop: Cannot be used without QApplication");
+ } else if (!d->threadData->eventDispatcher) {
+ QThreadPrivate::createEventDispatcher(d->threadData);
+ }
+}
+
+/*!
+ Destroys the event loop object.
+*/
+QEventLoop::~QEventLoop()
+{ }
+
+
+/*!
+ Processes pending events that match \a flags until there are no
+ more events to process. Returns true if pending events were handled;
+ otherwise returns false.
+
+ This function is especially useful if you have a long running
+ operation and want to show its progress without allowing user
+ input; i.e. by using the \l ExcludeUserInputEvents flag.
+
+ This function is simply a wrapper for
+ QAbstractEventDispatcher::processEvents(). See the documentation
+ for that function for details.
+*/
+bool QEventLoop::processEvents(ProcessEventsFlags flags)
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return false;
+ if (flags & DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ return d->threadData->eventDispatcher->processEvents(flags);
+}
+
+/*!
+ Enters the main event loop and waits until exit() is called.
+ Returns the value that was passed to exit().
+
+ If \a flags are specified, only events of the types allowed by
+ the \a flags will be processed.
+
+ It is necessary to call this function to start event handling. The
+ main event loop receives events from the window system and
+ dispatches these to the application widgets.
+
+ Generally speaking, no user interaction can take place before
+ calling exec(). As a special case, modal widgets like QMessageBox
+ can be used before calling exec(), because modal widgets
+ use their own local event loop.
+
+ To make your application perform idle processing (i.e. executing a
+ special function whenever there are no pending events), use a
+ QTimer with 0 timeout. More sophisticated idle processing schemes
+ can be achieved using processEvents().
+
+ \sa QApplication::quit(), exit(), processEvents()
+*/
+int QEventLoop::exec(ProcessEventsFlags flags)
+{
+ Q_D(QEventLoop);
+ //we need to protect from race condition with QThread::exit
+ QMutexLocker locker(&static_cast<QThreadPrivate *>(QObjectPrivate::get(d->threadData->thread))->mutex);
+ if (d->threadData->quitNow)
+ return -1;
+
+ if (d->inExec) {
+ qWarning("QEventLoop::exec: instance %p has already called exec()", this);
+ return -1;
+ }
+ d->inExec = true;
+ d->exit = false;
+ ++d->threadData->loopLevel;
+ d->threadData->eventLoops.push(this);
+ locker.unlock();
+
+ // remove posted quit events when entering a new event loop
+ QCoreApplication *app = QCoreApplication::instance();
+ if (app && app->thread() == thread())
+ QCoreApplication::removePostedEvents(app, QEvent::Quit);
+
+#if defined(QT_NO_EXCEPTIONS)
+ while (!d->exit)
+ processEvents(flags | WaitForMoreEvents | EventLoopExec);
+#else
+ try {
+ while (!d->exit)
+ processEvents(flags | WaitForMoreEvents | EventLoopExec);
+ } catch (...) {
+ qWarning("Qt has caught an exception thrown from an event handler. Throwing\n"
+ "exceptions from an event handler is not supported in Qt. You must\n"
+ "reimplement QApplication::notify() and catch all exceptions there.\n");
+
+ // copied from below
+ locker.relock();
+ QEventLoop *eventLoop = d->threadData->eventLoops.pop();
+ Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
+ Q_UNUSED(eventLoop); // --release warning
+ d->inExec = false;
+ --d->threadData->loopLevel;
+
+ throw;
+ }
+#endif
+
+ // copied above
+ locker.relock();
+ QEventLoop *eventLoop = d->threadData->eventLoops.pop();
+ Q_ASSERT_X(eventLoop == this, "QEventLoop::exec()", "internal error");
+ Q_UNUSED(eventLoop); // --release warning
+ d->inExec = false;
+ --d->threadData->loopLevel;
+
+ return d->returnCode;
+}
+
+/*!
+ Process pending events that match \a flags for a maximum of \a
+ maxTime milliseconds, or until there are no more events to
+ process, whichever is shorter.
+ This function is especially useful if you have a long running
+ operation and want to show its progress without allowing user
+ input, i.e. by using the \l ExcludeUserInputEvents flag.
+
+ \bold{Notes:}
+ \list
+ \o This function does not process events continuously; it
+ returns after all available events are processed.
+ \o Specifying the \l WaitForMoreEvents flag makes no sense
+ and will be ignored.
+ \endlist
+*/
+void QEventLoop::processEvents(ProcessEventsFlags flags, int maxTime)
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return;
+
+ QElapsedTimer start;
+ start.start();
+ if (flags & DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ while (processEvents(flags & ~WaitForMoreEvents)) {
+ if (start.elapsed() > maxTime)
+ break;
+ if (flags & DeferredDeletion)
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ }
+}
+
+/*!
+ Tells the event loop to exit with a return code.
+
+ After this function has been called, the event loop returns from
+ the call to exec(). The exec() function returns \a returnCode.
+
+ By convention, a \a returnCode of 0 means success, and any non-zero
+ value indicates an error.
+
+ Note that unlike the C library function of the same name, this
+ function \e does return to the caller -- it is event processing that
+ stops.
+
+ \sa QCoreApplication::quit(), quit(), exec()
+*/
+void QEventLoop::exit(int returnCode)
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return;
+
+ d->returnCode = returnCode;
+ d->exit = true;
+ d->threadData->eventDispatcher->interrupt();
+}
+
+/*!
+ Returns true if the event loop is running; otherwise returns
+ false. The event loop is considered running from the time when
+ exec() is called until exit() is called.
+
+ \sa exec() exit()
+ */
+bool QEventLoop::isRunning() const
+{
+ Q_D(const QEventLoop);
+ return !d->exit;
+}
+
+/*!
+ Wakes up the event loop.
+
+ \sa QAbstractEventDispatcher::wakeUp()
+*/
+void QEventLoop::wakeUp()
+{
+ Q_D(QEventLoop);
+ if (!d->threadData->eventDispatcher)
+ return;
+ d->threadData->eventDispatcher->wakeUp();
+}
+
+/*!
+ Tells the event loop to exit normally.
+
+ Same as exit(0).
+
+ \sa QCoreApplication::quit(), exit()
+*/
+void QEventLoop::quit()
+{ exit(0); }
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qeventloop.h b/src/corelib/kernel/qeventloop.h
new file mode 100644
index 0000000000..c0eae714a4
--- /dev/null
+++ b/src/corelib/kernel/qeventloop.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QEVENTLOOP_H
+#define QEVENTLOOP_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEventLoopPrivate;
+
+class Q_CORE_EXPORT QEventLoop : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QEventLoop)
+
+public:
+ explicit QEventLoop(QObject *parent = 0);
+ ~QEventLoop();
+
+ enum ProcessEventsFlag {
+ AllEvents = 0x00,
+ ExcludeUserInputEvents = 0x01,
+ ExcludeSocketNotifiers = 0x02,
+ WaitForMoreEvents = 0x04,
+#ifdef QT3_SUPPORT
+ ExcludeUserInput = ExcludeUserInputEvents,
+ WaitForMore = WaitForMoreEvents,
+#endif
+ X11ExcludeTimers = 0x08
+#ifdef QT_DEPRECATED
+ , DeferredDeletion = 0x10
+#endif
+ , EventLoopExec = 0x20
+ , DialogExec = 0x40
+ };
+ Q_DECLARE_FLAGS(ProcessEventsFlags, ProcessEventsFlag)
+
+ bool processEvents(ProcessEventsFlags flags = AllEvents);
+ void processEvents(ProcessEventsFlags flags, int maximumTime);
+
+ int exec(ProcessEventsFlags flags = AllEvents);
+ void exit(int returnCode = 0);
+ bool isRunning() const;
+
+ void wakeUp();
+
+public Q_SLOTS:
+ void quit();
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QEventLoop::ProcessEventsFlags)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QEVENTLOOP_H
diff --git a/src/corelib/kernel/qfunctions_nacl.cpp b/src/corelib/kernel/qfunctions_nacl.cpp
new file mode 100644
index 0000000000..f3d85ef300
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_nacl.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qfunctions_nacl.h"
+#include <pthread.h>
+#include <qglobal.h>
+
+/*
+ The purpose of this file is to stub out certain functions
+ that are not provided by the Native Client SDK. This is
+ done as an alterative to sprinkling the Qt sources with
+ NACL ifdefs.
+
+ There are two main classes of functions:
+
+ - Functions that are called but can have no effect:
+ For these we simply give an empty implementation
+
+ - Functions that are referenced in the source code, but
+ is not/must not be called at run-time:
+ These we either leave undefined or implement with a
+ qFatal.
+
+ This is a work in progress.
+*/
+
+extern "C" {
+
+void pthread_cleanup_push(void (*)(void *), void *)
+{
+
+}
+
+void pthread_cleanup_pop(int)
+{
+
+}
+
+int pthread_setcancelstate(int, int *)
+{
+ return 0;
+}
+
+int pthread_setcanceltype(int, int *)
+{
+ return 0;
+}
+
+void pthread_testcancel(void)
+{
+
+}
+
+
+int pthread_cancel(pthread_t)
+{
+ return 0;
+}
+
+int pthread_attr_setinheritsched(pthread_attr_t *,int)
+{
+ return 0;
+}
+
+
+int pthread_attr_getinheritsched(const pthread_attr_t *, int *)
+{
+ return 0;
+}
+
+// event dispatcher, select
+//struct fd_set;
+//struct timeval;
+
+int fcntl(int, int, ...)
+{
+ return 0;
+}
+
+int sigaction(int, const struct sigaction *, struct sigaction *)
+{
+ return 0;
+}
+
+int open(const char *, int, ...)
+{
+ return 0;
+}
+
+int open64(const char *, int, ...)
+{
+ return 0;
+}
+
+int access(const char *, int)
+{
+ return 0;
+}
+
+typedef long off64_t;
+off64_t ftello64(void *)
+{
+ qFatal("ftello64 called");
+ return 0;
+}
+
+off64_t lseek64(int, off_t, int)
+{
+ qFatal("lseek64 called");
+ return 0;
+}
+
+} // Extern C
+
+int select(int, fd_set *, fd_set *, fd_set *, struct timeval *)
+{
+ return 0;
+}
diff --git a/src/corelib/kernel/qfunctions_nacl.h b/src/corelib/kernel/qfunctions_nacl.h
new file mode 100644
index 0000000000..db36ad5bfd
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_nacl.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QNACLUNIMPLEMENTED_H
+#define QNACLUNIMPLEMENTED_H
+
+#ifdef Q_OS_NACL
+
+#include <sys/types.h>
+
+// pthread
+#include <pthread.h>
+#define PTHREAD_CANCEL_DISABLE 1
+#define PTHREAD_CANCEL_ENABLE 2
+#define PTHREAD_INHERIT_SCHED 3
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+extern "C" {
+
+void pthread_cleanup_push(void (*handler)(void *), void *arg);
+void pthread_cleanup_pop(int execute);
+
+int pthread_setcancelstate(int state, int *oldstate);
+int pthread_setcanceltype(int type, int *oldtype);
+void pthread_testcancel(void);
+int pthread_cancel(pthread_t thread);
+
+int pthread_attr_setinheritsched(pthread_attr_t *attr,
+ int inheritsched);
+int pthread_attr_getinheritsched(const pthread_attr_t *attr,
+ int *inheritsched);
+
+// event dispatcher, select
+//struct fd_set;
+//struct timeval;
+int fcntl(int fildes, int cmd, ...);
+int sigaction(int sig, const struct sigaction * act, struct sigaction * oact);
+
+typedef long off64_t;
+off64_t ftello64(void *stream);
+off64_t lseek64(int fildes, off_t offset, int whence);
+int open64(const char *path, int oflag, ...);
+
+}
+
+int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //Q_OS_NACL
+
+#endif //QNACLUNIMPLEMENTED_H
diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h
new file mode 100644
index 0000000000..d27fec3a0b
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qfunctions_*. This header file may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef QFUNCTIONS_P_H
+#define QFUNCTIONS_P_H
+
+#include <QtCore/qglobal.h>
+
+#if defined(Q_OS_WINCE)
+# include "QtCore/qfunctions_wince.h"
+#elif defined(Q_OS_VXWORKS)
+# include "QtCore/qfunctions_vxworks.h"
+#elif defined(Q_OS_NACL)
+# include "QtCore/qfunctions_nacl.h"
+#endif
+
+#ifdef Q_CC_RVCT
+// rvct doesn't see static operators when using our qalgorithms
+# define Q_STATIC_GLOBAL_OPERATOR inline
+# define Q_STATIC_GLOBAL_INLINE_OPERATOR inline
+#else
+# define Q_STATIC_GLOBAL_OPERATOR static
+# define Q_STATIC_GLOBAL_INLINE_OPERATOR static inline
+#endif
+
+QT_BEGIN_HEADER
+QT_END_HEADER
+
+#endif
+
diff --git a/src/corelib/kernel/qfunctions_vxworks.cpp b/src/corelib/kernel/qfunctions_vxworks.cpp
new file mode 100644
index 0000000000..1678ab67a9
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_vxworks.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qglobal.h"
+
+#ifdef Q_OS_VXWORKS
+
+#include "qplatformdefs.h"
+#include "qfunctions_vxworks.h"
+
+#include <vmLib.h>
+#include <selectLib.h>
+#include <ioLib.h>
+
+QT_USE_NAMESPACE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// no lfind() - used by the TIF image format
+void *lfind(const void* key, const void* base, size_t* elements, size_t size,
+ int (*compare)(const void*, const void*))
+{
+ const char* current = (char*) base;
+ const char* const end = (char*) (current + (*elements) * size);
+ while (current != end) {
+ if (compare(current, key) == 0)
+ return (void*)current;
+ current += size;
+ }
+ return 0;
+}
+
+
+// no rand_r(), but rand()
+// NOTE: this implementation is wrong for multi threaded applications,
+// but there is no way to get it right on VxWorks (in kernel mode)
+int rand_r(unsigned int * /*seedp*/)
+{
+ return rand();
+}
+
+// no usleep() support
+int usleep(unsigned int usec)
+{
+ div_t dt = div(usec, 1000000);
+ struct timespec ts = { dt.quot, dt.rem * 1000 };
+
+ return nanosleep(&ts, 0);
+}
+
+
+// gettimeofday() is declared, but is missing from the library
+// It IS however defined in the Curtis-Wright X11 libraries, so
+// we have to make the symbol 'weak'
+#if defined(Q_CC_DIAB)
+# pragma weak gettimeofday
+#endif
+int gettimeofday(struct timeval *tv, void /*struct timezone*/ *)
+{
+ // the compiler will optimize this and will only use one code path
+ if (sizeof(struct timeval) == sizeof(struct timespec)) {
+ int res = clock_gettime(CLOCK_REALTIME, (struct timespec *) tv);
+ if (!res)
+ tv->tv_usec /= 1000;
+ return res;
+ } else {
+ struct timespec ts;
+
+ int res = clock_gettime(CLOCK_REALTIME, &ts);
+ if (!res) {
+ tv->tv_sec = ts.tv_sec;
+ tv->tv_usec = ts.tv_nsec / 1000;
+ }
+ return res;
+ }
+}
+
+// neither getpagesize() or sysconf(_SC_PAGESIZE) are available
+int getpagesize()
+{
+ return vmPageSizeGet();
+}
+
+// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h)
+int symlink(const char *, const char *)
+{
+ errno = EIO;
+ return -1;
+}
+
+ssize_t readlink(const char *, char *, size_t)
+{
+ errno = EIO;
+ return -1;
+}
+
+// there's no truncate(), but ftruncate() support...
+int truncate(const char *path, off_t length)
+{
+ int fd = open(path, O_WRONLY, 00777);
+ if (fd >= 0) {
+ int res = ftruncate(fd, length);
+ int en = errno;
+ close(fd);
+ errno = en;
+ return res;
+ }
+ // errno is already set by open
+ return -1;
+}
+
+
+
+// VxWorks doesn't know about passwd & friends.
+// in order to avoid patching the unix fs path everywhere
+// we introduce some dummy functions that simulate a single
+// 'root' user on the system.
+
+uid_t getuid()
+{
+ return 0;
+}
+
+gid_t getgid()
+{
+ return 0;
+}
+
+uid_t geteuid()
+{
+ return 0;
+}
+
+struct passwd *getpwuid(uid_t uid)
+{
+ static struct passwd pwbuf = { "root", 0, 0, 0, 0, 0, 0 };
+
+ if (uid == 0) {
+ return &pwbuf;
+ } else {
+ errno = ENOENT;
+ return 0;
+ }
+}
+
+struct group *getgrgid(gid_t gid)
+{
+ static struct group grbuf = { "root", 0, 0, 0 };
+
+ if (gid == 0) {
+ return &grbuf;
+ } else {
+ errno = ENOENT;
+ return 0;
+ }
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // Q_OS_VXWORKS
diff --git a/src/corelib/kernel/qfunctions_vxworks.h b/src/corelib/kernel/qfunctions_vxworks.h
new file mode 100644
index 0000000000..78a37210a0
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_vxworks.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QFUNCTIONS_VXWORKS_H
+#define QFUNCTIONS_VXWORKS_H
+#ifdef Q_OS_VXWORKS
+
+#include <unistd.h>
+#include <pthread.h>
+#include <dirent.h>
+#include <signal.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/times.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <netinet/in.h>
+#ifndef QT_NO_IPV6IFNAME
+#include <net/if.h>
+#endif
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_BUILD_CORE_LIB
+QT_MODULE(Core)
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
+
+#ifndef NSIG
+#define NSIG _NSIGS
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// isascii is missing (sometimes!!)
+#ifndef isascii
+inline int isascii(int c) { return (c & 0x7f); }
+#endif
+
+// no lfind() - used by the TIF image format
+void *lfind(const void* key, const void* base, size_t* elements, size_t size,
+ int (*compare)(const void*, const void*));
+
+// no rand_r(), but rand()
+// NOTE: this implementation is wrong for multi threaded applications,
+// but there is no way to get it right on VxWorks (in kernel mode)
+int rand_r(unsigned int * /*seedp*/);
+
+// no usleep() support
+int usleep(unsigned int);
+
+// gettimeofday() is declared, but is missing from the library.
+// It IS however defined in the Curtis-Wright X11 libraries, so
+// we have to make the symbol 'weak'
+int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) __attribute__((weak));
+
+// neither getpagesize() or sysconf(_SC_PAGESIZE) are available
+int getpagesize();
+
+// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h)
+int symlink(const char *, const char *);
+ssize_t readlink(const char *, char *, size_t);
+
+// there's no truncate(), but ftruncate() support...
+int truncate(const char *path, off_t length);
+
+// VxWorks doesn't know about passwd & friends.
+// in order to avoid patching the unix fs path everywhere
+// we introduce some dummy functions that simulate a single
+// 'root' user on the system.
+
+uid_t getuid();
+gid_t getgid();
+uid_t geteuid();
+
+struct passwd {
+ char *pw_name; /* user name */
+ char *pw_passwd; /* user password */
+ uid_t pw_uid; /* user ID */
+ gid_t pw_gid; /* group ID */
+ char *pw_gecos; /* real name */
+ char *pw_dir; /* home directory */
+ char *pw_shell; /* shell program */
+};
+
+struct group {
+ char *gr_name; /* group name */
+ char *gr_passwd; /* group password */
+ gid_t gr_gid; /* group ID */
+ char **gr_mem; /* group members */
+};
+
+struct passwd *getpwuid(uid_t uid);
+struct group *getgrgid(gid_t gid);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif // Q_OS_VXWORKS
+#endif // QFUNCTIONS_VXWORKS_H
diff --git a/src/corelib/kernel/qfunctions_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp
new file mode 100644
index 0000000000..2de34c3bdc
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_wince.cpp
@@ -0,0 +1,451 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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$
+**
+****************************************************************************/
+#ifdef _WIN32_WCE //Q_OS_WINCE
+
+#include <windows.h>
+#include <winbase.h>
+#include <kfuncs.h>
+#include <stdio.h>
+#include <altcecrt.h>
+
+#include "qplatformdefs.h"
+#include "qfunctions_wince.h"
+#include "qstring.h"
+#include "qbytearray.h"
+#include "qhash.h"
+
+QT_USE_NAMESPACE
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+wchar_t* CEPrivConvCharToWide(const char* string)
+{
+ size_t length = strlen(string);
+ wchar_t* wString = new wchar_t[length +1];
+ for (unsigned int i = 0; i < (length +1); i++)
+ wString[i] = string[i];
+ return wString;
+}
+
+// Time -------------------------------------------------------------
+time_t qt_wince_ftToTime_t( const FILETIME ft )
+{
+ ULARGE_INTEGER li;
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+
+ // 100-nanosec to seconds
+ li.QuadPart /= 10000000;
+
+ // FILETIME is from 1601-01-01 T 00:00:00
+ // time_t is from 1970-01-01 T 00:00:00
+ // 1970 - 1601 = 369 year (89 leap years)
+ //
+ // ((369y*365d) + 89d) *24h *60min *60sec
+ // = 11644473600 seconds
+ li.QuadPart -= 11644473600;
+ return li.LowPart;
+}
+
+FILETIME qt_wince_time_tToFt( time_t tt )
+{
+ ULARGE_INTEGER li;
+ li.QuadPart = tt;
+ li.QuadPart += 11644473600;
+ li.QuadPart *= 10000000;
+
+ FILETIME ft;
+ ft.dwLowDateTime = li.LowPart;
+ ft.dwHighDateTime = li.HighPart;
+ return ft;
+}
+
+// File I/O ---------------------------------------------------------
+int errno = 0;
+
+int qt_wince__getdrive( void )
+{
+ return 1;
+}
+
+int qt_wince__waccess( const wchar_t *path, int pmode )
+{
+ DWORD res = GetFileAttributes( path );
+ if ( 0xFFFFFFFF == res )
+ return -1;
+
+ if ( (pmode & W_OK) && (res & FILE_ATTRIBUTE_READONLY) )
+ return -1;
+
+ if ( (pmode & X_OK) && !(res & FILE_ATTRIBUTE_DIRECTORY) ) {
+ QString file = QString::fromWCharArray(path);
+ if ( !(file.endsWith(QString::fromLatin1(".exe")) ||
+ file.endsWith(QString::fromLatin1(".com"))) )
+ return -1;
+ }
+
+ return 0;
+}
+
+int qt_wince_open( const char *filename, int oflag, int pmode )
+{
+ QString fn( QString::fromLatin1(filename) );
+ return _wopen( (wchar_t*)fn.utf16(), oflag, pmode );
+}
+
+int qt_wince__wopen( const wchar_t *filename, int oflag, int /*pmode*/ )
+{
+ wchar_t *flag;
+
+ if ( oflag & _O_APPEND ) {
+ if ( oflag & _O_WRONLY ) {
+ flag = L"a";
+ } else if ( oflag & _O_RDWR ) {
+ flag = L"a+";
+ }
+ } else if (oflag & _O_BINARY) {
+ if ( oflag & _O_WRONLY ) {
+ flag = L"wb";
+ } else if ( oflag & _O_RDWR ) {
+ flag = L"w+b"; // slightly different from "r+" where the file must exist
+ } else if ( oflag & _O_RDONLY ) {
+ flag = L"rb";
+ } else {
+ flag = L"b";
+ }
+ } else {
+ if ( oflag & _O_WRONLY ) {
+ flag = L"wt";
+ } else if ( oflag & _O_RDWR ) {
+ flag = L"w+t"; // slightly different from "r+" where the file must exist
+ } else if ( oflag & _O_RDONLY ) {
+ flag = L"rt";
+ } else {
+ flag = L"t";
+ }
+ }
+
+ int retval = (int)_wfopen( filename, flag );
+ return (retval == NULL) ? -1 : retval;
+}
+
+long qt_wince__lseek( int handle, long offset, int origin )
+{
+ return fseek( (FILE*)handle, offset, origin );
+}
+
+int qt_wince__read( int handle, void *buffer, unsigned int count )
+{
+ return fread( buffer, 1, count, (FILE*)handle );
+}
+
+int qt_wince__write( int handle, const void *buffer, unsigned int count )
+{
+ return fwrite( buffer, 1, count, (FILE*)handle );
+}
+
+int qt_wince__close( int handle )
+{
+ if (!handle)
+ return 0;
+ return fclose( (FILE*)handle );
+}
+
+FILE *qt_wince__fdopen(int handle, const char* /*mode*/)
+{
+ return (FILE*)handle;
+}
+
+FILE *qt_wince_fdopen( int handle, const char* /*mode*/ )
+{
+ return (FILE*)handle;
+}
+
+void qt_wince_rewind( FILE *stream )
+{
+ fseek( stream, 0L, SEEK_SET );
+}
+
+int qt_wince___fileno(FILE *f)
+{
+ return (int) _fileno(f);
+}
+
+FILE *qt_wince_tmpfile( void )
+{
+ static long i = 0;
+ char name[16];
+ sprintf( name, "tmp%i", i++ );
+ return fopen( name, "r+" );
+}
+
+int qt_wince__mkdir(const char *dirname)
+{
+ return CreateDirectory(reinterpret_cast<const wchar_t *> (QString(QString::fromLatin1(dirname)).utf16()), 0) ? 0 : -1;
+}
+
+int qt_wince__rmdir(const char *dirname)
+{
+ return RemoveDirectory(reinterpret_cast<const wchar_t *> (QString::fromLatin1(dirname).utf16())) ? 0 : -1;
+}
+
+int qt_wince__access( const char *path, int pmode )
+{
+ return _waccess(reinterpret_cast<const wchar_t *> (QString::fromLatin1(path).utf16()),pmode);
+}
+
+int qt_wince__rename( const char *oldname, const char *newname )
+{
+ return !MoveFile(reinterpret_cast<const wchar_t *> (QString::fromLatin1(oldname).utf16()), reinterpret_cast<const wchar_t *> (QString::fromLatin1(newname).utf16()));
+}
+
+int qt_wince__remove( const char *name )
+{
+ return !DeleteFile(reinterpret_cast<const wchar_t *> (QString::fromLatin1(name).utf16()));
+}
+
+int qt_wince_stat( const char *path, struct stat *buffer )
+{
+ WIN32_FIND_DATA finfo;
+ HANDLE ff = FindFirstFile( reinterpret_cast<const wchar_t *> (QString::fromLatin1(path).utf16()), &finfo );
+
+ if ( ff == INVALID_HANDLE_VALUE )
+ return -1;
+
+ buffer->st_ctime = qt_wince_ftToTime_t( finfo.ftCreationTime );
+ buffer->st_atime = qt_wince_ftToTime_t( finfo.ftLastAccessTime );
+ buffer->st_mtime = qt_wince_ftToTime_t( finfo.ftLastWriteTime );
+ buffer->st_nlink = 0;
+ buffer->st_size = finfo.nFileSizeLow; // ### missing high!
+ buffer->st_mode = (finfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR : _S_IFREG;
+ buffer->st_mode |= (finfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _O_RDONLY : _O_RDWR;
+ return (FindClose(ff) == 0);
+}
+
+int qt_wince__fstat( int handle, struct stat *buffer)
+{
+ BY_HANDLE_FILE_INFORMATION fInfo;
+ BOOL res = GetFileInformationByHandle((HANDLE)handle, &fInfo);
+
+ buffer->st_ctime = qt_wince_ftToTime_t( fInfo.ftCreationTime );
+ buffer->st_atime = qt_wince_ftToTime_t( fInfo.ftLastAccessTime );
+ buffer->st_mtime = qt_wince_ftToTime_t( fInfo.ftLastWriteTime );
+ buffer->st_nlink = 0;
+ buffer->st_size = fInfo.nFileSizeLow; // ### missing high!
+ buffer->st_mode = (fInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? _S_IFDIR : _S_IFREG;
+ buffer->st_mode |= (fInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? _O_RDONLY : _O_RDWR;
+ return (res == 0);
+}
+
+int qt_wince_SetErrorMode(int newValue)
+{
+ static int oldValue;
+ int result = oldValue;
+ oldValue = newValue;
+ return result;
+}
+
+bool qt_wince__chmod(const char *file, int mode)
+{
+ return _wchmod( reinterpret_cast<const wchar_t *> (QString::fromLatin1(file).utf16()), mode);
+}
+
+bool qt_wince__wchmod(const wchar_t *file, int mode)
+{
+ BOOL success = FALSE;
+ // ### Does not work properly, what about just adding one property?
+ if(mode&_S_IWRITE) {
+ success = SetFileAttributes(file, FILE_ATTRIBUTE_NORMAL);
+ } else if((mode&_S_IREAD) && !(mode&_S_IWRITE)) {
+ success = SetFileAttributes(file, FILE_ATTRIBUTE_READONLY);
+ }
+ return success ? 0 : -1;
+}
+
+HANDLE qt_wince_CreateFileA(LPCSTR filename, DWORD access, DWORD share, LPSECURITY_ATTRIBUTES attr, DWORD dispo, DWORD flags, HANDLE tempFile)
+{
+ return CreateFileW( reinterpret_cast<const wchar_t *>(QString::fromLatin1(filename).utf16()), access, share, attr, dispo, flags, tempFile);
+}
+
+// Graphics ---------------------------------------------------------
+BOOL qt_wince_SetWindowOrgEx( HDC /*hdc*/, int /*X*/, int /*Y*/, LPPOINT /*lpPoint*/) {
+ return TRUE;
+}
+
+// Threading --------------------------------------------------------
+HANDLE qt_wince__beginthread(void( *start_address )( void * ), unsigned stack_size, void *arglist)
+{
+ unsigned initflag = 0;
+ if (stack_size > 0)
+ initflag |= STACK_SIZE_PARAM_IS_A_RESERVATION;
+ return CreateThread(NULL, stack_size, (LPTHREAD_START_ROUTINE)start_address, arglist, initflag, NULL);
+}
+
+unsigned long qt_wince__beginthreadex( void *security,
+ unsigned stack_size,
+ unsigned (__stdcall *start_address)(void *),
+ void *arglist,
+ unsigned initflag,
+ unsigned *thrdaddr)
+{
+ if (stack_size > 0)
+ initflag |= STACK_SIZE_PARAM_IS_A_RESERVATION;
+ return (unsigned long)
+ CreateThread( (LPSECURITY_ATTRIBUTES)security,
+ (DWORD)stack_size,
+ (LPTHREAD_START_ROUTINE)start_address,
+ (LPVOID)arglist,
+ (DWORD)initflag | CREATE_SUSPENDED,
+ (LPDWORD)thrdaddr);
+}
+
+void qt_wince__endthreadex(unsigned nExitCode) {
+ ExitThread((DWORD)nExitCode);
+}
+
+void *qt_wince_bsearch(const void *key,
+ const void *base,
+ size_t num,
+ size_t size,
+ int (__cdecl *compare)(const void *, const void *))
+{
+ size_t low = 0;
+ size_t high = num - 1;
+ while (low <= high) {
+ size_t mid = (low + high) >> 1;
+ int c = compare(key, (char*)base + mid * size);
+ if (c < 0) {
+ if (!mid)
+ break;
+ high = mid - 1;
+ } else if (c > 0)
+ low = mid + 1;
+ else
+ return (char*) base + mid * size;
+ }
+ return 0;
+}
+
+void *lfind(const void* key, const void* base, size_t* elements, size_t size,
+ int (__cdecl *compare)(const void*, const void*))
+{
+ const char* current = (char*) base;
+ const char* const end = (char*) (current + (*elements) * size);
+ while (current != end) {
+ if (compare(current, key) == 0)
+ return (void*)current;
+ current += size;
+ }
+ return 0;
+}
+
+DWORD qt_wince_GetThreadLocale(void)
+{
+ return GetUserDefaultLCID();
+}
+
+void *qt_wince_calloc( size_t num, size_t size )
+{
+ void *ptr = malloc( num * size );
+ if( ptr )
+ memset( ptr, 0, num * size );
+ return ptr;
+}
+
+// _getpid is currently only used for creating a temporary filename
+int qt_wince__getpid()
+{
+ return qAbs((int)GetCurrentProcessId());
+}
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+// Environment ------------------------------------------------------
+inline QHash<QByteArray, QByteArray>& qt_app_environment()
+{
+ static QHash<QByteArray, QByteArray> internalEnvironment;
+ return internalEnvironment;
+}
+
+errno_t qt_wince_getenv_s(size_t* sizeNeeded, char* buffer, size_t bufferSize, const char* varName)
+{
+ if (!sizeNeeded)
+ return EINVAL;
+
+ if (!qt_app_environment().contains(varName)) {
+ if (buffer)
+ buffer[0] = '\0';
+ return ENOENT;
+ }
+
+ QByteArray value = qt_app_environment().value(varName);
+ if (!value.endsWith('\0')) // win32 guarantees terminated string
+ value.append('\0');
+
+ if (bufferSize < (size_t)value.size()) {
+ *sizeNeeded = value.size();
+ return 0;
+ }
+
+ strcpy(buffer, value.constData());
+ return 0;
+}
+
+errno_t qt_wince__putenv_s(const char* varName, const char* value)
+{
+ QByteArray input = value;
+ if (input.isEmpty()) {
+ if (qt_app_environment().contains(varName))
+ qt_app_environment().remove(varName);
+ } else {
+ // win32 guarantees terminated string
+ if (!input.endsWith('\0'))
+ input.append('\0');
+ qt_app_environment()[varName] = input;
+ }
+
+ return 0;
+}
+
+#endif // Q_OS_WINCE
diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h
new file mode 100644
index 0000000000..fffe407139
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_wince.h
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QFUNCTIONS_WCE_H
+#define QFUNCTIONS_WCE_H
+#ifdef Q_OS_WINCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <winuser.h>
+#include <winbase.h>
+#include <objbase.h>
+#include <kfuncs.h>
+#include <ctype.h>
+#include <time.h>
+#include <crtdefs.h>
+#include <altcecrt.h>
+#include <winsock.h>
+#include <ceconfig.h>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_BUILD_CORE_LIB
+QT_MODULE(Core)
+#endif
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+
+// The standard SDK misses this define...
+#define _control87 _controlfp
+
+#if !defined __cplusplus
+#define bool int
+#define true 1
+#define false 0
+#endif
+
+// Environment ------------------------------------------------------
+errno_t qt_wince_getenv_s(size_t*, char*, size_t, const char*);
+errno_t qt_wince__putenv_s(const char*, const char*);
+
+#ifdef __cplusplus // have this as tiff plugin is written in C
+extern "C" {
+#endif
+
+#if !defined(NO_ERRNO_H)
+#define NO_ERRNO_H
+#endif
+
+// Environment ------------------------------------------------------
+int qt_wince__getpid(void);
+
+
+// Time -------------------------------------------------------------
+#ifndef _TM_DEFINED
+#define _TM_DEFINED
+struct tm {
+ int tm_sec; /* seconds after the minute - [0,59] */
+ int tm_min; /* minutes after the hour - [0,59] */
+ int tm_hour; /* hours since midnight - [0,23] */
+ int tm_mday; /* day of the month - [1,31] */
+ int tm_mon; /* months since January - [0,11] */
+ int tm_year; /* years since 1900 */
+ int tm_wday; /* days since Sunday - [0,6] */
+ int tm_yday; /* days since January 1 - [0,365] */
+ int tm_isdst; /* daylight savings time flag */
+};
+#endif // _TM_DEFINED
+
+FILETIME qt_wince_time_tToFt( time_t tt );
+
+// File I/O ---------------------------------------------------------
+#define _O_RDONLY 0x0001
+#define _O_RDWR 0x0002
+#define _O_WRONLY 0x0004
+#define _O_CREAT 0x0008
+#define _O_TRUNC 0x0010
+#define _O_APPEND 0x0020
+#define _O_EXCL 0x0040
+
+#define O_RDONLY _O_RDONLY
+#define O_RDWR _O_RDWR
+#define O_WRONLY _O_WRONLY
+#define O_CREAT _O_CREAT
+#define O_TRUNC _O_TRUNC
+#define O_APPEND _O_APPEND
+#define O_EXCL _O_EXCL
+
+#define _S_IFMT 0x0600
+#define _S_IFDIR 0x0200
+#define _S_IFCHR 0x0100
+#define _S_IFREG 0x0400
+#define _S_IREAD 0x0010
+#define _S_IWRITE 0x0008
+
+#define S_IFMT _S_IFMT
+#define S_IFDIR _S_IFDIR
+#define S_IFCHR _S_IFCHR
+#define S_IFREG _S_IFREG
+#define S_IREAD _S_IREAD
+#define S_IWRITE _S_IWRITE
+
+#ifndef _IOFBF
+#define _IOFBF 0x0000
+#endif
+
+#ifndef _IOLBF
+#define _IOLBF 0x0040
+#endif
+
+#ifndef _IONBF
+#define _IONBF 0x0004
+#endif
+
+// Regular Berkeley error constants
+#ifndef _STAT_DEFINED
+#define _STAT_DEFINED
+struct stat
+{
+ int st_mode;
+ int st_size;
+ int st_nlink;
+ time_t st_mtime;
+ time_t st_atime;
+ time_t st_ctime;
+};
+#endif
+
+typedef int mode_t;
+extern int errno;
+
+int qt_wince__getdrive( void );
+int qt_wince__waccess( const wchar_t *path, int pmode );
+int qt_wince__wopen( const wchar_t *filename, int oflag, int pmode );
+long qt_wince__lseek( int handle, long offset, int origin );
+int qt_wince__read( int handle, void *buffer, unsigned int count );
+int qt_wince__write( int handle, const void *buffer, unsigned int count );
+int qt_wince__close( int handle );
+FILE *qt_wince__fdopen(int handle, const char *mode);
+FILE *qt_wince_fdopen(int handle, const char *mode);
+void qt_wince_rewind( FILE *stream );
+int qt_wince___fileno(FILE *);
+FILE *qt_wince_tmpfile( void );
+
+int qt_wince__mkdir(const char *dirname);
+int qt_wince__rmdir(const char *dirname);
+int qt_wince__access( const char *path, int pmode );
+int qt_wince__rename( const char *oldname, const char *newname );
+int qt_wince__remove( const char *name );
+#ifdef __cplusplus
+int qt_wince_open( const char *filename, int oflag, int pmode = 0 );
+#else
+int qt_wince_open( const char *filename, int oflag, int pmode );
+#endif
+int qt_wince_stat( const char *path, struct stat *buffer );
+int qt_wince__fstat( int handle, struct stat *buffer);
+
+#define SEM_FAILCRITICALERRORS 0x0001
+#define SEM_NOOPENFILEERRORBOX 0x0002
+int qt_wince_SetErrorMode(int);
+#ifndef CoInitialize
+#define CoInitialize(x) CoInitializeEx(x, COINIT_MULTITHREADED)
+#endif
+
+bool qt_wince__chmod(const char *file, int mode);
+bool qt_wince__wchmod(const wchar_t *file, int mode);
+
+#pragma warning(disable: 4273)
+HANDLE qt_wince_CreateFileA(LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
+
+// Printer ----------------------------------------------------------
+#define ETO_GLYPH_INDEX 0x0010
+
+// Graphics ---------------------------------------------------------
+#ifndef SM_CXCURSOR
+# define SM_CXCURSOR 13
+#endif
+#ifndef SM_CYCURSOR
+# define SM_CYCURSOR 14
+#endif
+BOOL qt_wince_SetWindowOrgEx( HDC hdc, int X, int Y, LPPOINT lpPoint );
+
+// Other stuff ------------------------------------------------------
+#define MWMO_ALERTABLE 0x0002
+// ### not the real values
+#define CREATE_NO_WINDOW 2
+#define CF_HDROP 15
+
+void *qt_wince_calloc(size_t num, size_t size);
+#if !defined(TLS_OUT_OF_INDEXES)
+# define TLS_OUT_OF_INDEXES 0xffffffff
+#endif
+DWORD qt_wince_GetThreadLocale(void);
+
+HANDLE qt_wince__beginthread(void( *start_address )( void * ), unsigned stack_size, void *arglist);
+
+unsigned long qt_wince__beginthreadex( void *security,
+ unsigned stack_size,
+ unsigned (__stdcall *start_address)(void *),
+ void *arglist,
+ unsigned initflag,
+ unsigned *thrdaddr );
+void qt_wince__endthreadex(unsigned nExitCode);
+
+
+// bsearch is needed for building the tiff plugin
+// otherwise it could go into qguifunctions_wce
+void *qt_wince_bsearch(const void *key,
+ const void *base,
+ size_t num,
+ size_t size,
+ int (__cdecl *compare)(const void *, const void *));
+
+// Missing typedefs
+#ifndef _TIME_T_DEFINED
+typedef unsigned long time_t;
+#define _TIME_T_DEFINED
+#endif
+typedef HANDLE HDROP;
+
+#ifndef WS_THICKFRAME
+#define WS_THICKFRAME WS_DLGFRAME
+#endif
+
+typedef UINT UWORD;
+
+// Missing definitions: not necessary equal to their Win32 values
+// (the goal is to just have a clean compilation of MFC)
+#define WS_MAXIMIZE 0
+#define WS_MINIMIZE 0
+#ifndef WS_EX_TOOLWINDOW
+#define WS_EX_TOOLWINDOW 0
+#endif
+#define WS_EX_NOPARENTNOTIFY 0
+#define WM_ENTERIDLE 0x0121
+#define WM_PRINT WM_PAINT
+#define WM_NCCREATE (0x0081)
+#define WM_PARENTNOTIFY 0
+#define WM_NCDESTROY (WM_APP-1)
+#ifndef SW_RESTORE
+#define SW_RESTORE (SW_SHOWNORMAL)
+#endif
+#define SW_NORMAL (SW_SHOWNORMAL)
+#define WAIT_OBJECT_0 0x00000000L
+#define DEFAULT_GUI_FONT SYSTEM_FONT
+#ifndef SWP_NOREDRAW
+#define SWP_NOREDRAW 0
+#endif
+#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
+#define HWND_TOPMOST ((HWND)-1)
+#define HWND_NOTOPMOST ((HWND)-2)
+#define PS_DOT 2
+#define PD_ALLPAGES 0
+#define PD_USEDEVMODECOPIES 0
+#define PD_NOSELECTION 0
+#define PD_HIDEPRINTTOFILE 0
+#define PD_NOPAGENUMS 0
+#define CF_METAFILEPICT 3
+#define MM_ANISOTROPIC 8
+#define KF_ALTDOWN 0x2000
+#define SPI_GETWORKAREA 48
+
+#ifndef WM_SETCURSOR
+ #define WM_SETCURSOR 0x0020
+ #define IDC_ARROW MAKEINTRESOURCE(32512)
+ #define IDC_IBEAM MAKEINTRESOURCE(32513)
+ #define IDC_WAIT MAKEINTRESOURCE(32514)
+ #define IDC_CROSS MAKEINTRESOURCE(32515)
+ #define IDC_UPARROW MAKEINTRESOURCE(32516)
+ #define IDC_SIZE MAKEINTRESOURCE(32646)
+ #define IDC_ICON MAKEINTRESOURCE(32512)
+ #define IDC_SIZENWSE MAKEINTRESOURCE(32642)
+ #define IDC_SIZENESW MAKEINTRESOURCE(32643)
+ #define IDC_SIZEWE MAKEINTRESOURCE(32644)
+ #define IDC_SIZENS MAKEINTRESOURCE(32645)
+ #define IDC_SIZEALL MAKEINTRESOURCE(32646)
+ #define IDC_NO MAKEINTRESOURCE(32648)
+ #define IDC_APPSTARTING MAKEINTRESOURCE(32650)
+ #define IDC_HELP MAKEINTRESOURCE(32651)
+ #define IDC_HAND MAKEINTRESOURCE(32649)
+#endif
+
+#define GMEM_MOVEABLE LMEM_MOVEABLE
+#define GPTR LPTR
+
+// WinCE: CESYSGEN prunes the following FRP defines,
+// and INTERNET_TRANSFER_TYPE_ASCII breaks in wininet.h
+#undef FTP_TRANSFER_TYPE_ASCII
+#define FTP_TRANSFER_TYPE_ASCII 0x00000001
+#undef FTP_TRANSFER_TYPE_BINARY
+#define FTP_TRANSFER_TYPE_BINARY 0x00000002
+
+typedef DWORD OLE_COLOR;
+
+// Define the Windows Styles which are not defined by MS
+#ifndef WS_POPUPWINDOW
+#define WS_POPUPWINDOW WS_POPUP|WS_BORDER|WS_SYSMENU|WS_CAPTION
+#endif
+
+#ifndef WS_OVERLAPPEDWINDOW
+#define WS_OVERLAPPEDWINDOW WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX
+#endif
+
+#ifndef WS_TILED
+#define WS_TILED WS_OVERLAPPED
+#endif
+
+#ifndef WS_TILEDWINDOW
+#define WS_TILEDWINDOW WS_OVERLAPPEDWINDOW
+#endif
+
+#ifndef WS_EX_CAPTIONOKBTN
+#define WS_EX_CAPTIONOKBTN 0x80000000L
+#endif
+
+#ifndef WS_EX_NODRAG
+#define WS_EX_NODRAG 0x40000000L
+#endif
+
+// As Windows CE lacks some standard functions used in Qt, these got
+// reimplented. Other projects do this as well and to not fill the
+// global namespace with this implementation, prepend qt_wince* and use
+// these versions inside of Qt.
+// The other declarations available in this file are being used per
+// define inside qplatformdefs.h of the corresponding WinCE mkspec.
+#define getenv_s(a,b,c,d) qt_wince_getenv_s(a,b,c,d)
+#define _putenv_s(a,b) qt_wince__putenv_s(a,b)
+#define _getpid() qt_wince__getpid()
+#define time_tToFt(a) qt_wince_time_tToFt(a)
+#define _getdrive() qt_wince__getdrive()
+#define _waccess(a,b) qt_wince__waccess(a,b)
+#define _wopen(a,b,c) qt_wince__wopen(a,b,c)
+#define _fdopen(a,b) qt_wince__fdopen(a,b)
+#define fdopen(a,b) qt_wince_fdopen(a,b)
+#define rewind(a) qt_wince_rewind(a)
+#define tmpfile() qt_wince_tmpfile()
+#define _rename(a,b) qt_wince__rename(a,b)
+#define _remove(a) qt_wince__remove(a)
+#define SetErrorMode(a) qt_wince_SetErrorMode(a)
+#define _chmod(a,b) qt_wince__chmod(a,b)
+#define _wchmod(a,b) qt_wince__wchmod(a,b)
+#define CreateFileA(a,b,c,d,e,f,g) qt_wince_CreateFileA(a,b,c,d,e,f,g)
+#define SetWindowOrgEx(a,b,c,d) qt_wince_SetWindowOrgEx(a,b,c,d)
+#define calloc(a,b) qt_wince_calloc(a,b)
+#define GetThreadLocale() qt_wince_GetThreadLocale()
+#define _beginthread(a,b,c) qt_wince__beginthread(a,b,c)
+#define _beginthreadex(a,b,c,d,e,f) qt_wince__beginthreadex(a,b,c,d,e,f)
+#define _endthreadex(a) qt_wince__endthreadex(a)
+#define bsearch(a,b,c,d,e) qt_wince_bsearch(a,b,c,d,e)
+
+#ifdef __cplusplus
+} // Extern C.
+#endif
+
+#endif // Q_OS_WINCE
+#endif // QFUNCTIONS_WCE_H
diff --git a/src/corelib/kernel/qmath.cpp b/src/corelib/kernel/qmath.cpp
new file mode 100644
index 0000000000..783dbbfa37
--- /dev/null
+++ b/src/corelib/kernel/qmath.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+const qreal qt_sine_table[QT_SINE_TABLE_SIZE] = {
+ qreal(0.0),
+ qreal(0.024541228522912288),
+ qreal(0.049067674327418015),
+ qreal(0.073564563599667426),
+ qreal(0.098017140329560604),
+ qreal(0.1224106751992162),
+ qreal(0.14673047445536175),
+ qreal(0.17096188876030122),
+ qreal(0.19509032201612825),
+ qreal(0.2191012401568698),
+ qreal(0.24298017990326387),
+ qreal(0.26671275747489837),
+ qreal(0.29028467725446233),
+ qreal(0.31368174039889152),
+ qreal(0.33688985339222005),
+ qreal(0.35989503653498811),
+ qreal(0.38268343236508978),
+ qreal(0.40524131400498986),
+ qreal(0.42755509343028208),
+ qreal(0.44961132965460654),
+ qreal(0.47139673682599764),
+ qreal(0.49289819222978404),
+ qreal(0.51410274419322166),
+ qreal(0.53499761988709715),
+ qreal(0.55557023301960218),
+ qreal(0.57580819141784534),
+ qreal(0.59569930449243336),
+ qreal(0.61523159058062682),
+ qreal(0.63439328416364549),
+ qreal(0.65317284295377676),
+ qreal(0.67155895484701833),
+ qreal(0.68954054473706683),
+ qreal(0.70710678118654746),
+ qreal(0.72424708295146689),
+ qreal(0.74095112535495911),
+ qreal(0.75720884650648446),
+ qreal(0.77301045336273699),
+ qreal(0.78834642762660623),
+ qreal(0.80320753148064483),
+ qreal(0.81758481315158371),
+ qreal(0.83146961230254524),
+ qreal(0.84485356524970701),
+ qreal(0.85772861000027212),
+ qreal(0.87008699110871135),
+ qreal(0.88192126434835494),
+ qreal(0.89322430119551532),
+ qreal(0.90398929312344334),
+ qreal(0.91420975570353069),
+ qreal(0.92387953251128674),
+ qreal(0.93299279883473885),
+ qreal(0.94154406518302081),
+ qreal(0.94952818059303667),
+ qreal(0.95694033573220894),
+ qreal(0.96377606579543984),
+ qreal(0.97003125319454397),
+ qreal(0.97570213003852857),
+ qreal(0.98078528040323043),
+ qreal(0.98527764238894122),
+ qreal(0.98917650996478101),
+ qreal(0.99247953459870997),
+ qreal(0.99518472667219682),
+ qreal(0.99729045667869021),
+ qreal(0.99879545620517241),
+ qreal(0.99969881869620425),
+ qreal(1.0),
+ qreal(0.99969881869620425),
+ qreal(0.99879545620517241),
+ qreal(0.99729045667869021),
+ qreal(0.99518472667219693),
+ qreal(0.99247953459870997),
+ qreal(0.98917650996478101),
+ qreal(0.98527764238894122),
+ qreal(0.98078528040323043),
+ qreal(0.97570213003852857),
+ qreal(0.97003125319454397),
+ qreal(0.96377606579543984),
+ qreal(0.95694033573220894),
+ qreal(0.94952818059303667),
+ qreal(0.94154406518302081),
+ qreal(0.93299279883473885),
+ qreal(0.92387953251128674),
+ qreal(0.91420975570353069),
+ qreal(0.90398929312344345),
+ qreal(0.89322430119551521),
+ qreal(0.88192126434835505),
+ qreal(0.87008699110871146),
+ qreal(0.85772861000027212),
+ qreal(0.84485356524970723),
+ qreal(0.83146961230254546),
+ qreal(0.81758481315158371),
+ qreal(0.80320753148064494),
+ qreal(0.78834642762660634),
+ qreal(0.7730104533627371),
+ qreal(0.75720884650648468),
+ qreal(0.74095112535495899),
+ qreal(0.72424708295146689),
+ qreal(0.70710678118654757),
+ qreal(0.68954054473706705),
+ qreal(0.67155895484701855),
+ qreal(0.65317284295377664),
+ qreal(0.63439328416364549),
+ qreal(0.61523159058062693),
+ qreal(0.59569930449243347),
+ qreal(0.57580819141784545),
+ qreal(0.55557023301960218),
+ qreal(0.53499761988709715),
+ qreal(0.51410274419322177),
+ qreal(0.49289819222978415),
+ qreal(0.47139673682599786),
+ qreal(0.44961132965460687),
+ qreal(0.42755509343028203),
+ qreal(0.40524131400498992),
+ qreal(0.38268343236508989),
+ qreal(0.35989503653498833),
+ qreal(0.33688985339222033),
+ qreal(0.31368174039889141),
+ qreal(0.29028467725446239),
+ qreal(0.26671275747489848),
+ qreal(0.24298017990326407),
+ qreal(0.21910124015687005),
+ qreal(0.19509032201612861),
+ qreal(0.17096188876030122),
+ qreal(0.1467304744553618),
+ qreal(0.12241067519921635),
+ qreal(0.098017140329560826),
+ qreal(0.073564563599667732),
+ qreal(0.049067674327417966),
+ qreal(0.024541228522912326),
+ qreal(0.0),
+ qreal(-0.02454122852291208),
+ qreal(-0.049067674327417724),
+ qreal(-0.073564563599667496),
+ qreal(-0.09801714032956059),
+ qreal(-0.1224106751992161),
+ qreal(-0.14673047445536158),
+ qreal(-0.17096188876030097),
+ qreal(-0.19509032201612836),
+ qreal(-0.2191012401568698),
+ qreal(-0.24298017990326382),
+ qreal(-0.26671275747489825),
+ qreal(-0.29028467725446211),
+ qreal(-0.31368174039889118),
+ qreal(-0.33688985339222011),
+ qreal(-0.35989503653498811),
+ qreal(-0.38268343236508967),
+ qreal(-0.40524131400498969),
+ qreal(-0.42755509343028181),
+ qreal(-0.44961132965460665),
+ qreal(-0.47139673682599764),
+ qreal(-0.49289819222978393),
+ qreal(-0.51410274419322155),
+ qreal(-0.53499761988709693),
+ qreal(-0.55557023301960196),
+ qreal(-0.57580819141784534),
+ qreal(-0.59569930449243325),
+ qreal(-0.61523159058062671),
+ qreal(-0.63439328416364527),
+ qreal(-0.65317284295377653),
+ qreal(-0.67155895484701844),
+ qreal(-0.68954054473706683),
+ qreal(-0.70710678118654746),
+ qreal(-0.72424708295146678),
+ qreal(-0.74095112535495888),
+ qreal(-0.75720884650648423),
+ qreal(-0.77301045336273666),
+ qreal(-0.78834642762660589),
+ qreal(-0.80320753148064505),
+ qreal(-0.81758481315158382),
+ qreal(-0.83146961230254524),
+ qreal(-0.84485356524970701),
+ qreal(-0.85772861000027201),
+ qreal(-0.87008699110871135),
+ qreal(-0.88192126434835494),
+ qreal(-0.89322430119551521),
+ qreal(-0.90398929312344312),
+ qreal(-0.91420975570353047),
+ qreal(-0.92387953251128652),
+ qreal(-0.93299279883473896),
+ qreal(-0.94154406518302081),
+ qreal(-0.94952818059303667),
+ qreal(-0.95694033573220882),
+ qreal(-0.96377606579543984),
+ qreal(-0.97003125319454397),
+ qreal(-0.97570213003852846),
+ qreal(-0.98078528040323032),
+ qreal(-0.98527764238894111),
+ qreal(-0.9891765099647809),
+ qreal(-0.99247953459871008),
+ qreal(-0.99518472667219693),
+ qreal(-0.99729045667869021),
+ qreal(-0.99879545620517241),
+ qreal(-0.99969881869620425),
+ qreal(-1.0),
+ qreal(-0.99969881869620425),
+ qreal(-0.99879545620517241),
+ qreal(-0.99729045667869021),
+ qreal(-0.99518472667219693),
+ qreal(-0.99247953459871008),
+ qreal(-0.9891765099647809),
+ qreal(-0.98527764238894122),
+ qreal(-0.98078528040323043),
+ qreal(-0.97570213003852857),
+ qreal(-0.97003125319454397),
+ qreal(-0.96377606579543995),
+ qreal(-0.95694033573220894),
+ qreal(-0.94952818059303679),
+ qreal(-0.94154406518302092),
+ qreal(-0.93299279883473907),
+ qreal(-0.92387953251128663),
+ qreal(-0.91420975570353058),
+ qreal(-0.90398929312344334),
+ qreal(-0.89322430119551532),
+ qreal(-0.88192126434835505),
+ qreal(-0.87008699110871146),
+ qreal(-0.85772861000027223),
+ qreal(-0.84485356524970723),
+ qreal(-0.83146961230254546),
+ qreal(-0.81758481315158404),
+ qreal(-0.80320753148064528),
+ qreal(-0.78834642762660612),
+ qreal(-0.77301045336273688),
+ qreal(-0.75720884650648457),
+ qreal(-0.74095112535495911),
+ qreal(-0.724247082951467),
+ qreal(-0.70710678118654768),
+ qreal(-0.68954054473706716),
+ qreal(-0.67155895484701866),
+ qreal(-0.65317284295377709),
+ qreal(-0.63439328416364593),
+ qreal(-0.61523159058062737),
+ qreal(-0.59569930449243325),
+ qreal(-0.57580819141784523),
+ qreal(-0.55557023301960218),
+ qreal(-0.53499761988709726),
+ qreal(-0.51410274419322188),
+ qreal(-0.49289819222978426),
+ qreal(-0.47139673682599792),
+ qreal(-0.44961132965460698),
+ qreal(-0.42755509343028253),
+ qreal(-0.40524131400499042),
+ qreal(-0.38268343236509039),
+ qreal(-0.359895036534988),
+ qreal(-0.33688985339222),
+ qreal(-0.31368174039889152),
+ qreal(-0.2902846772544625),
+ qreal(-0.26671275747489859),
+ qreal(-0.24298017990326418),
+ qreal(-0.21910124015687016),
+ qreal(-0.19509032201612872),
+ qreal(-0.17096188876030177),
+ qreal(-0.14673047445536239),
+ qreal(-0.12241067519921603),
+ qreal(-0.098017140329560506),
+ qreal(-0.073564563599667412),
+ qreal(-0.049067674327418091),
+ qreal(-0.024541228522912448)
+};
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h
new file mode 100644
index 0000000000..27c27dc4d1
--- /dev/null
+++ b/src/corelib/kernel/qmath.h
@@ -0,0 +1,288 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QMATH_H
+#define QMATH_H
+
+#include <math.h>
+
+#include <QtCore/qglobal.h>
+
+#ifdef Q_OS_SYMBIAN
+# include <e32math.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#define QT_SINE_TABLE_SIZE 256
+
+extern Q_CORE_EXPORT const qreal qt_sine_table[QT_SINE_TABLE_SIZE];
+
+inline int qCeil(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return int(ceilf(float(v)));
+ else
+#endif
+ return int(ceil(v));
+}
+
+inline int qFloor(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return int(floorf(float(v)));
+ else
+#endif
+ return int(floor(v));
+}
+
+inline qreal qFabs(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return fabsf(float(v));
+ else
+#endif
+ return fabs(v);
+}
+
+inline qreal qSin(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal sin_v;
+ Math::Sin(sin_v, static_cast<TReal>(v));
+ return static_cast<qreal>(sin_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return sinf(float(v));
+ else
+# endif
+ return sin(v);
+#endif
+}
+
+inline qreal qCos(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal cos_v;
+ Math::Cos(cos_v, static_cast<TReal>(v));
+ return static_cast<qreal>(cos_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return cosf(float(v));
+ else
+# endif
+ return cos(v);
+#endif
+}
+
+inline qreal qTan(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal tan_v;
+ Math::Tan(tan_v, static_cast<TReal>(v));
+ return static_cast<qreal>(tan_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return tanf(float(v));
+ else
+# endif
+ return tan(v);
+#endif
+}
+
+inline qreal qAcos(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal acos_v;
+ Math::ACos(acos_v, static_cast<TReal>(v));
+ return static_cast<qreal>(acos_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return acosf(float(v));
+ else
+# endif
+ return acos(v);
+#endif
+}
+
+inline qreal qAsin(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal asin_v;
+ Math::ASin(asin_v, static_cast<TReal>(v));
+ return static_cast<qreal>(asin_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return asinf(float(v));
+ else
+# endif
+ return asin(v);
+#endif
+}
+
+inline qreal qAtan(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal atan_v;
+ Math::ATan(atan_v, static_cast<TReal>(v));
+ return static_cast<qreal>(atan_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return atanf(float(v));
+ else
+# endif
+ return atan(v);
+#endif
+}
+
+inline qreal qAtan2(qreal x, qreal y)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal atan2_v;
+ Math::ATan(atan2_v, static_cast<TReal>(x), static_cast<TReal>(y));
+ return static_cast<qreal>(atan2_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if(sizeof(qreal) == sizeof(float))
+ return atan2f(float(x), float(y));
+ else
+# endif
+ return atan2(x, y);
+#endif
+}
+
+inline qreal qSqrt(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal sqrt_v;
+ Math::Sqrt(sqrt_v, static_cast<TReal>(v));
+ return static_cast<qreal>(sqrt_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return sqrtf(float(v));
+ else
+# endif
+ return sqrt(v);
+#endif
+}
+
+inline qreal qLn(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return logf(float(v));
+ else
+#endif
+ return log(v);
+}
+
+inline qreal qExp(qreal v)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal exp_v;
+ Math::Exp(exp_v, static_cast<TReal>(v));
+ return static_cast<qreal>(exp_v);
+#else
+ // only one signature
+ // exists, exp(double)
+ return exp(v);
+#endif
+}
+
+inline qreal qPow(qreal x, qreal y)
+{
+#ifdef Q_OS_SYMBIAN
+ TReal pow_v;
+ Math::Pow(pow_v, static_cast<TReal>(x), static_cast<TReal>(y));
+ return static_cast<qreal>(pow_v);
+#else
+# ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return powf(float(x), float(y));
+ else
+# endif
+ return pow(x, y);
+#endif
+}
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+inline qreal qFastSin(qreal x)
+{
+ int si = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
+ qreal d = x - si * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
+ int ci = si + QT_SINE_TABLE_SIZE / 4;
+ si &= QT_SINE_TABLE_SIZE - 1;
+ ci &= QT_SINE_TABLE_SIZE - 1;
+ return qt_sine_table[si] + (qt_sine_table[ci] - 0.5 * qt_sine_table[si] * d) * d;
+}
+
+inline qreal qFastCos(qreal x)
+{
+ int ci = int(x * (0.5 * QT_SINE_TABLE_SIZE / M_PI)); // Would be more accurate with qRound, but slower.
+ qreal d = x - ci * (2.0 * M_PI / QT_SINE_TABLE_SIZE);
+ int si = ci + QT_SINE_TABLE_SIZE / 4;
+ si &= QT_SINE_TABLE_SIZE - 1;
+ ci &= QT_SINE_TABLE_SIZE - 1;
+ return qt_sine_table[si] - (qt_sine_table[ci] + 0.5 * qt_sine_table[si] * d) * d;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMATH_H
diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc
new file mode 100644
index 0000000000..91c5f56888
--- /dev/null
+++ b/src/corelib/kernel/qmath.qdoc
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of this
+** file.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \headerfile <QtCore/qmath.h>
+ \title Math Functions
+ \ingroup funclists
+ \brief The <QtCore/qmath.h> header provides various math functions.
+ \pagekeywords math trigonometry qmath floor ceiling absolute sine cosine tangent inverse tan exponent power natural logarithm
+*/
+
+/*!
+ \fn int qCeil(qreal v)
+ Return the ceiling of the value \a v.
+
+ The ceiling is the smallest integer that is not less than \a v.
+ For example, if \a v is 41.2, then the ceiling is 42.
+
+ \relates <QtCore/qmath.h>
+ \sa qFloor()
+*/
+
+/*!
+ \fn int qFloor(qreal v)
+ Return the floor of the value \a v.
+
+ The floor is the largest integer that is not greater than \a v.
+ For example, if \a v is 41.2, then the floor is 41.
+
+ \relates <QtCore/qmath.h>
+ \sa qCeil()
+*/
+
+/*!
+ \fn qreal qFabs(qreal v)
+ Returns the absolute value of \a v as a qreal.
+*/
+
+/*!
+ \fn qreal qSin(qreal v)
+ Returns the sine of the angle \a v in radians.
+
+ \relates <QtCore/qmath.h>
+ \sa qCos(), qTan()
+*/
+
+/*!
+ \fn qreal qCos(qreal v)
+ Returns the cosine of an angle \a v in radians.
+
+ \relates <QtCore/qmath.h>
+ \sa qSin(), qTan()
+*/
+
+/*!
+ \fn qreal qTan(qreal v)
+ Returns the tangent of an angle \a v in radians.
+
+ \relates <QtCore/qmath.h>
+ \sa qSin(), qCos()
+*/
+
+/*!
+ \fn qreal qAcos(qreal v)
+ Returns the arccosine of \a v as an angle in radians.
+ Arccosine is the inverse operation of cosine.
+
+ \relates <QtCore/qmath.h>
+ \sa qAtan(), qAsin(), qCos()
+*/
+
+/*!
+ \fn qreal qAsin(qreal v)
+ Returns the arcsine of \a v as an angle in radians.
+ Arcsine is the inverse operation of sine.
+
+ \relates <QtCore/qmath.h>
+ \sa qSin(), qAtan(), qAcos()
+*/
+
+/*!
+ \fn qreal qAtan(qreal v)
+ Returns the arctangent of \a v as an angle in radians.
+ Arctangent is the inverse operation of tangent.
+
+ \relates <QtCore/qmath.h>
+ \sa qTan(), qAcos(), qAsin()
+*/
+
+/*!
+ \fn qreal qAtan2(qreal x, qreal y)
+ Returns the arctangent of a point specified by the coordinates \a x and \a y.
+ This function will return the angle and its direction.
+
+ \relates <QtCore/qmath.h>
+ \sa qAtan()
+*/
+
+/*!
+ \fn qreal qSqrt(qreal v)
+ Returns the square root of \a v.
+ This function returns a NaN if \a v is a negative number.
+
+ \relates <QtCore/qmath.h>
+ \sa qPow()
+*/
+
+/*!
+ \fn qreal qLn(qreal v)
+ Returns the natural logarithm of \a v. Natural logarithm uses base e.
+
+ \relates <QtCore/qmath.h>
+ \sa qExp()
+*/
+
+/*!
+ \fn qreal qExp(qreal v)
+ Returns the exponential function of \c e to the power of \a v.
+
+ \relates <QtCore/qmath.h>
+ \sa qLn()
+*/
+
+/*!
+ \fn qreal qPow(qreal x, qreal y)
+ Returns the value of \a x raised to the power of \a y.
+ That is, \a x is the base and \a y is the exponent.
+
+ \relates <QtCore/qmath.h>
+ \sa qSqrt()
+*/
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
new file mode 100644
index 0000000000..e671056466
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -0,0 +1,2778 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qmetaobject.h"
+#include "qmetatype.h"
+#include "qobject.h"
+
+#include <qcoreapplication.h>
+#include <qcoreevent.h>
+#include <qdatastream.h>
+#include <qstringlist.h>
+#include <qthread.h>
+#include <qvarlengtharray.h>
+#include <qvariant.h>
+#include <qhash.h>
+#include <qdebug.h>
+#include <qsemaphore.h>
+
+#include "private/qobject_p.h"
+#include "private/qmetaobject_p.h"
+
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMetaObject
+
+ \brief The QMetaObject class contains meta-information about Qt
+ objects.
+
+ \ingroup objectmodel
+
+ The Qt \l{Meta-Object System} in Qt is responsible for the
+ signals and slots inter-object communication mechanism, runtime
+ type information, and the Qt property system. A single
+ QMetaObject instance is created for each QObject subclass that is
+ used in an application, and this instance stores all the
+ meta-information for the QObject subclass. This object is
+ available as QObject::metaObject().
+
+ This class is not normally required for application programming,
+ but it is useful if you write meta-applications, such as scripting
+ engines or GUI builders.
+
+ The functions you are most likely to find useful are these:
+ \list
+ \o className() returns the name of a class.
+ \o superClass() returns the superclass's meta-object.
+ \o method() and methodCount() provide information
+ about a class's meta-methods (signals, slots and other
+ \l{Q_INVOKABLE}{invokable} member functions).
+ \o enumerator() and enumeratorCount() and provide information about
+ a class's enumerators.
+ \o propertyCount() and property() provide information about a
+ class's properties.
+ \o constructor() and constructorCount() provide information
+ about a class's meta-constructors.
+ \endlist
+
+ The index functions indexOfConstructor(), indexOfMethod(),
+ indexOfEnumerator(), and indexOfProperty() map names of constructors,
+ member functions, enumerators, or properties to indexes in the
+ meta-object. For example, Qt uses indexOfMethod() internally when you
+ connect a signal to a slot.
+
+ Classes can also have a list of \e{name}--\e{value} pairs of
+ additional class information, stored in QMetaClassInfo objects.
+ The number of pairs is returned by classInfoCount(), single pairs
+ are returned by classInfo(), and you can search for pairs with
+ indexOfClassInfo().
+
+ \sa QMetaClassInfo, QMetaEnum, QMetaMethod, QMetaProperty, QMetaType,
+ {Meta-Object System}
+*/
+
+/*!
+ \enum QMetaObject::Call
+
+ \internal
+
+ \value InvokeSlot
+ \value EmitSignal
+ \value ReadProperty
+ \value WriteProperty
+ \value ResetProperty
+ \value QueryPropertyDesignable
+ \value QueryPropertyScriptable
+ \value QueryPropertyStored
+ \value QueryPropertyEditable
+ \value QueryPropertyUser
+ \value CreateInstance
+*/
+
+/*!
+ \enum QMetaMethod::Access
+
+ This enum describes the access level of a method, following the conventions used in C++.
+
+ \value Private
+ \value Protected
+ \value Public
+*/
+
+static inline const QMetaObjectPrivate *priv(const uint* data)
+{ return reinterpret_cast<const QMetaObjectPrivate*>(data); }
+
+
+/*!
+ \since 4.5
+
+ Constructs a new instance of this class. You can pass up to ten arguments
+ (\a val0, \a val1, \a val2, \a val3, \a val4, \a val5, \a val6, \a val7,
+ \a val8, and \a val9) to the constructor. Returns the new object, or 0 if
+ no suitable constructor is available.
+
+ Note that only constructors that are declared with the Q_INVOKABLE
+ modifier are made available through the meta-object system.
+
+ \sa Q_ARG(), constructor()
+*/
+QObject *QMetaObject::newInstance(QGenericArgument val0,
+ QGenericArgument val1,
+ QGenericArgument val2,
+ QGenericArgument val3,
+ QGenericArgument val4,
+ QGenericArgument val5,
+ QGenericArgument val6,
+ QGenericArgument val7,
+ QGenericArgument val8,
+ QGenericArgument val9) const
+{
+ QByteArray constructorName = className();
+ {
+ int idx = constructorName.lastIndexOf(':');
+ if (idx != -1)
+ constructorName.remove(0, idx+1); // remove qualified part
+ }
+ QVarLengthArray<char, 512> sig;
+ sig.append(constructorName.constData(), constructorName.length());
+ sig.append('(');
+
+ enum { MaximumParamCount = 10 };
+ const char *typeNames[] = {val0.name(), val1.name(), val2.name(), val3.name(), val4.name(),
+ val5.name(), val6.name(), val7.name(), val8.name(), val9.name()};
+
+ int paramCount;
+ for (paramCount = 0; paramCount < MaximumParamCount; ++paramCount) {
+ int len = qstrlen(typeNames[paramCount]);
+ if (len <= 0)
+ break;
+ sig.append(typeNames[paramCount], len);
+ sig.append(',');
+ }
+ if (paramCount == 0)
+ sig.append(')'); // no parameters
+ else
+ sig[sig.size() - 1] = ')';
+ sig.append('\0');
+
+ int idx = indexOfConstructor(sig.constData());
+ if (idx < 0) {
+ QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
+ idx = indexOfConstructor(norm.constData());
+ }
+ if (idx < 0)
+ return 0;
+
+ QVariant ret(QMetaType::QObjectStar, (void*)0);
+ void *param[] = {ret.data(), val0.data(), val1.data(), val2.data(), val3.data(), val4.data(),
+ val5.data(), val6.data(), val7.data(), val8.data(), val9.data()};
+
+ if (static_metacall(CreateInstance, idx, param) >= 0)
+ return 0;
+ return *reinterpret_cast<QObject**>(param[0]);
+}
+
+/*!
+ \internal
+*/
+int QMetaObject::static_metacall(Call cl, int idx, void **argv) const
+{
+ const QMetaObjectExtraData *extra = reinterpret_cast<const QMetaObjectExtraData *>(d.extradata);
+ if (priv(d.data)->revision >= 6) {
+ if (!extra || !extra->static_metacall)
+ return 0;
+ extra->static_metacall(0, cl, idx, argv);
+ return -1;
+ } else if (priv(d.data)->revision >= 2) {
+ if (!extra || !extra->static_metacall)
+ return 0;
+ typedef int (*OldMetacall)(QMetaObject::Call, int, void **);
+ OldMetacall o = reinterpret_cast<OldMetacall>(extra->static_metacall);
+ return o(cl, idx, argv);
+ }
+ return 0;
+}
+
+/*!
+ \internal
+*/
+int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv)
+{
+ if (QMetaObject *mo = object->d_ptr->metaObject)
+ return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv);
+ else
+ return object->qt_metacall(cl, idx, argv);
+}
+
+/*!
+ \fn const char *QMetaObject::className() const
+
+ Returns the class name.
+
+ \sa superClass()
+*/
+
+/*!
+ \fn QMetaObject *QMetaObject::superClass() const
+
+ Returns the meta-object of the superclass, or 0 if there is no
+ such object.
+
+ \sa className()
+*/
+
+/*!
+ \internal
+
+ Returns \a obj if object \a obj inherits from this
+ meta-object; otherwise returns 0.
+*/
+QObject *QMetaObject::cast(QObject *obj) const
+{
+ if (obj) {
+ const QMetaObject *m = obj->metaObject();
+ do {
+ if (m == this)
+ return obj;
+ } while ((m = m->d.superdata));
+ }
+ return 0;
+}
+
+/*!
+ \internal
+
+ Returns \a obj if object \a obj inherits from this
+ meta-object; otherwise returns 0.
+*/
+const QObject *QMetaObject::cast(const QObject *obj) const
+{
+ if (obj) {
+ const QMetaObject *m = obj->metaObject();
+ do {
+ if (m == this)
+ return obj;
+ } while ((m = m->d.superdata));
+ }
+ return 0;
+}
+
+#ifndef QT_NO_TRANSLATION
+/*!
+ \internal
+*/
+QString QMetaObject::tr(const char *s, const char *c) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr);
+}
+
+/*!
+ \internal
+*/
+QString QMetaObject::tr(const char *s, const char *c, int n) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::CodecForTr, n);
+}
+
+/*!
+ \internal
+*/
+QString QMetaObject::trUtf8(const char *s, const char *c) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8);
+}
+
+/*!
+ \internal
+*/
+QString QMetaObject::trUtf8(const char *s, const char *c, int n) const
+{
+ return QCoreApplication::translate(d.stringdata, s, c, QCoreApplication::UnicodeUTF8, n);
+}
+#endif // QT_NO_TRANSLATION
+
+/*!
+ Returns the method offset for this class; i.e. the index position
+ of this class's first member function.
+
+ The offset is the sum of all the methods in the class's
+ superclasses (which is always positive since QObject has the
+ deleteLater() slot and a destroyed() signal).
+
+ \sa method(), methodCount(), indexOfMethod()
+*/
+int QMetaObject::methodOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->methodCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+
+/*!
+ Returns the enumerator offset for this class; i.e. the index
+ position of this class's first enumerator.
+
+ If the class has no superclasses with enumerators, the offset is
+ 0; otherwise the offset is the sum of all the enumerators in the
+ class's superclasses.
+
+ \sa enumerator(), enumeratorCount(), indexOfEnumerator()
+*/
+int QMetaObject::enumeratorOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->enumeratorCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+/*!
+ Returns the property offset for this class; i.e. the index
+ position of this class's first property.
+
+ The offset is the sum of all the properties in the class's
+ superclasses (which is always positive since QObject has the
+ name() property).
+
+ \sa property(), propertyCount(), indexOfProperty()
+*/
+int QMetaObject::propertyOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->propertyCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+/*!
+ Returns the class information offset for this class; i.e. the
+ index position of this class's first class information item.
+
+ If the class has no superclasses with class information, the
+ offset is 0; otherwise the offset is the sum of all the class
+ information items in the class's superclasses.
+
+ \sa classInfo(), classInfoCount(), indexOfClassInfo()
+*/
+int QMetaObject::classInfoOffset() const
+{
+ int offset = 0;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ offset += priv(m->d.data)->classInfoCount;
+ m = m->d.superdata;
+ }
+ return offset;
+}
+
+/*!
+ \since 4.5
+
+ Returns the number of constructors in this class.
+
+ \sa constructor(), indexOfConstructor()
+*/
+int QMetaObject::constructorCount() const
+{
+ if (priv(d.data)->revision < 2)
+ return 0;
+ return priv(d.data)->constructorCount;
+}
+
+/*!
+ Returns the number of methods in this class, including the number of
+ properties provided by each base class. These include signals and slots
+ as well as normal member functions.
+
+ Use code like the following to obtain a QStringList containing the methods
+ specific to a given class:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp methodCount
+
+ \sa method(), methodOffset(), indexOfMethod()
+*/
+int QMetaObject::methodCount() const
+{
+ int n = priv(d.data)->methodCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->methodCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/*!
+ Returns the number of enumerators in this class.
+
+ \sa enumerator(), enumeratorOffset(), indexOfEnumerator()
+*/
+int QMetaObject::enumeratorCount() const
+{
+ int n = priv(d.data)->enumeratorCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->enumeratorCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/*!
+ Returns the number of properties in this class, including the number of
+ properties provided by each base class.
+
+ Use code like the following to obtain a QStringList containing the properties
+ specific to a given class:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp propertyCount
+
+ \sa property(), propertyOffset(), indexOfProperty()
+*/
+int QMetaObject::propertyCount() const
+{
+ int n = priv(d.data)->propertyCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->propertyCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/*!
+ Returns the number of items of class information in this class.
+
+ \sa classInfo(), classInfoOffset(), indexOfClassInfo()
+*/
+int QMetaObject::classInfoCount() const
+{
+ int n = priv(d.data)->classInfoCount;
+ const QMetaObject *m = d.superdata;
+ while (m) {
+ n += priv(m->d.data)->classInfoCount;
+ m = m->d.superdata;
+ }
+ return n;
+}
+
+/** \internal
+* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within
+* the baseObject
+* \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything.
+* \a normalizeStringData set to true if we should do a second pass for old moc generated files normalizing all the symbols.
+*/
+template<int MethodType>
+static inline int indexOfMethodRelative(const QMetaObject **baseObject,
+ const char *method,
+ bool normalizeStringData)
+{
+ for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) {
+ int i = (MethodType == MethodSignal && priv(m->d.data)->revision >= 4)
+ ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1);
+ const int end = (MethodType == MethodSlot && priv(m->d.data)->revision >= 4)
+ ? (priv(m->d.data)->signalCount) : 0;
+ if (!normalizeStringData) {
+ for (; i >= end; --i) {
+ const char *stringdata = m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i];
+ if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) {
+ *baseObject = m;
+ return i;
+ }
+ }
+ } else if (priv(m->d.data)->revision < 5) {
+ for (; i >= end; --i) {
+ const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]);
+ const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata);
+ if (normalizedSignature == method) {
+ *baseObject = m;
+ return i;
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+
+/*!
+ \since 4.5
+
+ Finds \a constructor and returns its index; otherwise returns -1.
+
+ Note that the \a constructor has to be in normalized form, as returned
+ by normalizedSignature().
+
+ \sa constructor(), constructorCount(), normalizedSignature()
+*/
+int QMetaObject::indexOfConstructor(const char *constructor) const
+{
+ if (priv(d.data)->revision < 2)
+ return -1;
+ for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) {
+ const char *data = d.stringdata + d.data[priv(d.data)->constructorData + 5*i];
+ if (data[0] == constructor[0] && strcmp(constructor + 1, data + 1) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/*!
+ Finds \a method and returns its index; otherwise returns -1.
+
+ Note that the \a method has to be in normalized form, as returned
+ by normalizedSignature().
+
+ \sa method(), methodCount(), methodOffset(), normalizedSignature()
+*/
+int QMetaObject::indexOfMethod(const char *method) const
+{
+ const QMetaObject *m = this;
+ int i = indexOfMethodRelative<0>(&m, method, false);
+ if (i < 0) {
+ m = this;
+ i = indexOfMethodRelative<0>(&m, method, true);
+ }
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+/*!
+ Finds \a signal and returns its index; otherwise returns -1.
+
+ This is the same as indexOfMethod(), except that it will return
+ -1 if the method exists but isn't a signal.
+
+ Note that the \a signal has to be in normalized form, as returned
+ by normalizedSignature().
+
+ \sa indexOfMethod(), normalizedSignature(), method(), methodCount(), methodOffset()
+*/
+int QMetaObject::indexOfSignal(const char *signal) const
+{
+ const QMetaObject *m = this;
+ int i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, false);
+ if (i < 0) {
+ m = this;
+ i = QMetaObjectPrivate::indexOfSignalRelative(&m, signal, true);
+ }
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+/*! \internal
+ Same as QMetaObject::indexOfSignal, but the result is the local offset to the base object.
+
+ \a baseObject will be adjusted to the enclosing QMetaObject, or 0 if the signal is not found
+*/
+int QMetaObjectPrivate::indexOfSignalRelative(const QMetaObject **baseObject,
+ const char *signal,
+ bool normalizeStringData)
+{
+ int i = indexOfMethodRelative<MethodSignal>(baseObject, signal, normalizeStringData);
+#ifndef QT_NO_DEBUG
+ const QMetaObject *m = *baseObject;
+ if (i >= 0 && m && m->d.superdata) {
+ int conflict = m->d.superdata->indexOfMethod(signal);
+ if (conflict >= 0)
+ qWarning("QMetaObject::indexOfSignal: signal %s from %s redefined in %s",
+ signal, m->d.superdata->d.stringdata, m->d.stringdata);
+ }
+#endif
+ return i;
+}
+
+/*!
+ Finds \a slot and returns its index; otherwise returns -1.
+
+ This is the same as indexOfMethod(), except that it will return
+ -1 if the method exists but isn't a slot.
+
+ \sa indexOfMethod(), method(), methodCount(), methodOffset()
+*/
+int QMetaObject::indexOfSlot(const char *slot) const
+{
+ const QMetaObject *m = this;
+ int i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, false);
+ if (i < 0)
+ i = QMetaObjectPrivate::indexOfSlotRelative(&m, slot, true);
+ if (i >= 0)
+ i += m->methodOffset();
+ return i;
+}
+
+// same as indexOfSignalRelative but for slots.
+int QMetaObjectPrivate::indexOfSlotRelative(const QMetaObject **m,
+ const char *slot,
+ bool normalizeStringData)
+{
+ return indexOfMethodRelative<MethodSlot>(m, slot, normalizeStringData);
+}
+
+static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, const char *name)
+{
+ while (self) {
+ if (strcmp(self->d.stringdata, name) == 0)
+ return self;
+ if (self->d.extradata) {
+#ifdef Q_NO_DATA_RELOCATION
+ const QMetaObjectAccessor *e;
+ Q_ASSERT(priv(self->d.data)->revision >= 2);
+#else
+ const QMetaObject **e;
+ if (priv(self->d.data)->revision < 2) {
+ e = (const QMetaObject**)(self->d.extradata);
+ } else
+#endif
+ {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(self->d.extradata);
+ e = extra->objects;
+ }
+ if (e) {
+ while (*e) {
+#ifdef Q_NO_DATA_RELOCATION
+ if (const QMetaObject *m =QMetaObject_findMetaObject(&((*e)()), name))
+#else
+ if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
+#endif
+ return m;
+ ++e;
+ }
+ }
+ }
+ self = self->d.superdata;
+ }
+ return self;
+}
+
+/*!
+ Finds enumerator \a name and returns its index; otherwise returns
+ -1.
+
+ \sa enumerator(), enumeratorCount(), enumeratorOffset()
+*/
+int QMetaObject::indexOfEnumerator(const char *name) const
+{
+ const QMetaObject *m = this;
+ while (m) {
+ const QMetaObjectPrivate *d = priv(m->d.data);
+ for (int i = d->enumeratorCount - 1; i >= 0; --i) {
+ const char *prop = m->d.stringdata + m->d.data[d->enumeratorData + 4*i];
+ if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ i += m->enumeratorOffset();
+ return i;
+ }
+ }
+ m = m->d.superdata;
+ }
+ return -1;
+}
+
+/*!
+ Finds property \a name and returns its index; otherwise returns
+ -1.
+
+ \sa property(), propertyCount(), propertyOffset()
+*/
+int QMetaObject::indexOfProperty(const char *name) const
+{
+ const QMetaObject *m = this;
+ while (m) {
+ const QMetaObjectPrivate *d = priv(m->d.data);
+ for (int i = d->propertyCount-1; i >= 0; --i) {
+ const char *prop = m->d.stringdata + m->d.data[d->propertyData + 3*i];
+ if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) {
+ i += m->propertyOffset();
+ return i;
+ }
+ }
+ m = m->d.superdata;
+ }
+
+ if (priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)) {
+ QAbstractDynamicMetaObject *me =
+ const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this));
+
+ return me->createProperty(name, 0);
+ }
+
+ return -1;
+}
+
+/*!
+ Finds class information item \a name and returns its index;
+ otherwise returns -1.
+
+ \sa classInfo(), classInfoCount(), classInfoOffset()
+*/
+int QMetaObject::indexOfClassInfo(const char *name) const
+{
+ int i = -1;
+ const QMetaObject *m = this;
+ while (m && i < 0) {
+ for (i = priv(m->d.data)->classInfoCount-1; i >= 0; --i)
+ if (strcmp(name, m->d.stringdata
+ + m->d.data[priv(m->d.data)->classInfoData + 2*i]) == 0) {
+ i += m->classInfoOffset();
+ break;
+ }
+ m = m->d.superdata;
+ }
+ return i;
+}
+
+/*!
+ \since 4.5
+
+ Returns the meta-data for the constructor with the given \a index.
+
+ \sa constructorCount(), newInstance()
+*/
+QMetaMethod QMetaObject::constructor(int index) const
+{
+ int i = index;
+ QMetaMethod result;
+ if (priv(d.data)->revision >= 2 && i >= 0 && i < priv(d.data)->constructorCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->constructorData + 5*i;
+ }
+ return result;
+}
+
+/*!
+ Returns the meta-data for the method with the given \a index.
+
+ \sa methodCount(), methodOffset(), indexOfMethod()
+*/
+QMetaMethod QMetaObject::method(int index) const
+{
+ int i = index;
+ i -= methodOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->method(index);
+
+ QMetaMethod result;
+ if (i >= 0 && i < priv(d.data)->methodCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->methodData + 5*i;
+ }
+ return result;
+}
+
+/*!
+ Returns the meta-data for the enumerator with the given \a index.
+
+ \sa enumeratorCount(), enumeratorOffset(), indexOfEnumerator()
+*/
+QMetaEnum QMetaObject::enumerator(int index) const
+{
+ int i = index;
+ i -= enumeratorOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->enumerator(index);
+
+ QMetaEnum result;
+ if (i >= 0 && i < priv(d.data)->enumeratorCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->enumeratorData + 4*i;
+ }
+ return result;
+}
+
+/*!
+ Returns the meta-data for the property with the given \a index.
+ If no such property exists, a null QMetaProperty is returned.
+
+ \sa propertyCount(), propertyOffset(), indexOfProperty()
+*/
+QMetaProperty QMetaObject::property(int index) const
+{
+ int i = index;
+ i -= propertyOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->property(index);
+
+ QMetaProperty result;
+ if (i >= 0 && i < priv(d.data)->propertyCount) {
+ int handle = priv(d.data)->propertyData + 3*i;
+ int flags = d.data[handle + 2];
+ const char *type = d.stringdata + d.data[handle + 1];
+ result.mobj = this;
+ result.handle = handle;
+ result.idx = i;
+
+ if (flags & EnumOrFlag) {
+ result.menum = enumerator(indexOfEnumerator(type));
+ if (!result.menum.isValid()) {
+ QByteArray enum_name = type;
+ QByteArray scope_name = d.stringdata;
+ int s = enum_name.lastIndexOf("::");
+ if (s > 0) {
+ scope_name = enum_name.left(s);
+ enum_name = enum_name.mid(s + 2);
+ }
+ const QMetaObject *scope = 0;
+ if (scope_name == "Qt")
+ scope = &QObject::staticQtMetaObject;
+ else
+ scope = QMetaObject_findMetaObject(this, scope_name);
+ if (scope)
+ result.menum = scope->enumerator(scope->indexOfEnumerator(enum_name));
+ }
+ }
+ }
+ return result;
+}
+
+/*!
+ \since 4.2
+
+ Returns the property that has the \c USER flag set to true.
+
+ \sa QMetaProperty::isUser()
+*/
+QMetaProperty QMetaObject::userProperty() const
+{
+ const int propCount = propertyCount();
+ for (int i = propCount - 1; i >= 0; --i) {
+ const QMetaProperty prop = property(i);
+ if (prop.isUser())
+ return prop;
+ }
+ return QMetaProperty();
+}
+
+/*!
+ Returns the meta-data for the item of class information with the
+ given \a index.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 0
+
+ \sa classInfoCount(), classInfoOffset(), indexOfClassInfo()
+ */
+QMetaClassInfo QMetaObject::classInfo(int index) const
+{
+ int i = index;
+ i -= classInfoOffset();
+ if (i < 0 && d.superdata)
+ return d.superdata->classInfo(index);
+
+ QMetaClassInfo result;
+ if (i >= 0 && i < priv(d.data)->classInfoCount) {
+ result.mobj = this;
+ result.handle = priv(d.data)->classInfoData + 2*i;
+ }
+ return result;
+}
+
+/*!
+ Returns true if the \a signal and \a method arguments are
+ compatible; otherwise returns false.
+
+ Both \a signal and \a method are expected to be normalized.
+
+ \sa normalizedSignature()
+*/
+bool QMetaObject::checkConnectArgs(const char *signal, const char *method)
+{
+ const char *s1 = signal;
+ const char *s2 = method;
+ while (*s1++ != '(') { } // scan to first '('
+ while (*s2++ != '(') { }
+ if (*s2 == ')' || qstrcmp(s1,s2) == 0) // method has no args or
+ return true; // exact match
+ int s1len = qstrlen(s1);
+ int s2len = qstrlen(s2);
+ if (s2len < s1len && strncmp(s1,s2,s2len-1)==0 && s1[s2len-1]==',')
+ return true; // method has less args
+ return false;
+}
+
+static void qRemoveWhitespace(const char *s, char *d)
+{
+ char last = 0;
+ while (*s && is_space(*s))
+ s++;
+ while (*s) {
+ while (*s && !is_space(*s))
+ last = *d++ = *s++;
+ while (*s && is_space(*s))
+ s++;
+ if (*s && ((is_ident_char(*s) && is_ident_char(last))
+ || ((*s == ':') && (last == '<')))) {
+ last = *d++ = ' ';
+ }
+ }
+ *d = '\0';
+}
+
+static char *qNormalizeType(char *d, int &templdepth, QByteArray &result)
+{
+ const char *t = d;
+ while (*d && (templdepth
+ || (*d != ',' && *d != ')'))) {
+ if (*d == '<')
+ ++templdepth;
+ if (*d == '>')
+ --templdepth;
+ ++d;
+ }
+ if (strncmp("void", t, d - t) != 0)
+ result += normalizeTypeInternal(t, d);
+
+ return d;
+}
+
+
+/*!
+ \since 4.2
+
+ Normalizes a \a type.
+
+ See QMetaObject::normalizedSignature() for a description on how
+ Qt normalizes.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 1
+
+ \sa normalizedSignature()
+ */
+QByteArray QMetaObject::normalizedType(const char *type)
+{
+ QByteArray result;
+
+ if (!type || !*type)
+ return result;
+
+ QVarLengthArray<char> stackbuf(qstrlen(type) + 1);
+ qRemoveWhitespace(type, stackbuf.data());
+ int templdepth = 0;
+ qNormalizeType(stackbuf.data(), templdepth, result);
+
+ return result;
+}
+
+/*!
+ Normalizes the signature of the given \a method.
+
+ Qt uses normalized signatures to decide whether two given signals
+ and slots are compatible. Normalization reduces whitespace to a
+ minimum, moves 'const' to the front where appropriate, removes
+ 'const' from value types and replaces const references with
+ values.
+
+ \sa checkConnectArgs(), normalizedType()
+ */
+QByteArray QMetaObject::normalizedSignature(const char *method)
+{
+ QByteArray result;
+ if (!method || !*method)
+ return result;
+ int len = int(strlen(method));
+ QVarLengthArray<char> stackbuf(len + 1);
+ char *d = stackbuf.data();
+ qRemoveWhitespace(method, d);
+
+ result.reserve(len);
+
+ int argdepth = 0;
+ int templdepth = 0;
+ while (*d) {
+ if (argdepth == 1) {
+ d = qNormalizeType(d, templdepth, result);
+ if (!*d) //most likely an invalid signature.
+ break;
+ }
+ if (*d == '(')
+ ++argdepth;
+ if (*d == ')')
+ --argdepth;
+ result += *d++;
+ }
+
+ return result;
+}
+
+enum { MaximumParamCount = 11 }; // up to 10 arguments + 1 return value
+
+/*!
+ Invokes the \a member (a signal or a slot name) on the object \a
+ obj. Returns true if the member could be invoked. Returns false
+ if there is no such member or the parameters did not match.
+
+ The invocation can be either synchronous or asynchronous,
+ depending on \a type:
+
+ \list
+ \o If \a type is Qt::DirectConnection, the member will be invoked immediately.
+
+ \o If \a type is Qt::QueuedConnection,
+ a QEvent will be sent and the member is invoked as soon as the application
+ enters the main event loop.
+
+ \o If \a type is Qt::BlockingQueuedConnection, the method will be invoked in
+ the same way as for Qt::QueuedConnection, except that the current thread
+ will block until the event is delivered. Using this connection type to
+ communicate between objects in the same thread will lead to deadlocks.
+
+ \o If \a type is Qt::AutoConnection, the member is invoked
+ synchronously if \a obj lives in the same thread as the
+ caller; otherwise it will invoke the member asynchronously.
+ \endlist
+
+ The return value of the \a member function call is placed in \a
+ ret. If the invocation is asynchronous, the return value cannot
+ be evaluated. You can pass up to ten arguments (\a val0, \a val1,
+ \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
+ and \a val9) to the \a member function.
+
+ QGenericArgument and QGenericReturnArgument are internal
+ helper classes. Because signals and slots can be dynamically
+ invoked, you must enclose the arguments using the Q_ARG() and
+ Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
+ const reference of that type; Q_RETURN_ARG() takes a type name
+ and a non-const reference.
+
+ You only need to pass the name of the signal or slot to this function,
+ not the entire signature. For example, to asynchronously invoke
+ the \l{QPushButton::animateClick()}{animateClick()} slot on a
+ QPushButton, use the following code:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 2
+
+ With asynchronous method invocations, the parameters must be of
+ types that are known to Qt's meta-object system, because Qt needs
+ to copy the arguments to store them in an event behind the
+ scenes. If you try to use a queued connection and get the error
+ message
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 3
+
+ call qRegisterMetaType() to register the data type before you
+ call invokeMethod().
+
+ To synchronously invoke the \c compute(QString, int, double) slot on
+ some arbitrary object \c obj retrieve its return value:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 4
+
+ If the "compute" slot does not take exactly one QString, one int
+ and one double in the specified order, the call will fail.
+
+ \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaMethod::invoke()
+*/
+bool QMetaObject::invokeMethod(QObject *obj,
+ const char *member,
+ Qt::ConnectionType type,
+ QGenericReturnArgument ret,
+ QGenericArgument val0,
+ QGenericArgument val1,
+ QGenericArgument val2,
+ QGenericArgument val3,
+ QGenericArgument val4,
+ QGenericArgument val5,
+ QGenericArgument val6,
+ QGenericArgument val7,
+ QGenericArgument val8,
+ QGenericArgument val9)
+{
+ if (!obj)
+ return false;
+
+ QVarLengthArray<char, 512> sig;
+ int len = qstrlen(member);
+ if (len <= 0)
+ return false;
+ sig.append(member, len);
+ sig.append('(');
+
+ const char *typeNames[] = {ret.name(), val0.name(), val1.name(), val2.name(), val3.name(),
+ val4.name(), val5.name(), val6.name(), val7.name(), val8.name(),
+ val9.name()};
+
+ int paramCount;
+ for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
+ len = qstrlen(typeNames[paramCount]);
+ if (len <= 0)
+ break;
+ sig.append(typeNames[paramCount], len);
+ sig.append(',');
+ }
+ if (paramCount == 1)
+ sig.append(')'); // no parameters
+ else
+ sig[sig.size() - 1] = ')';
+ sig.append('\0');
+
+ int idx = obj->metaObject()->indexOfMethod(sig.constData());
+ if (idx < 0) {
+ QByteArray norm = QMetaObject::normalizedSignature(sig.constData());
+ idx = obj->metaObject()->indexOfMethod(norm.constData());
+ }
+
+ if (idx < 0 || idx >= obj->metaObject()->methodCount()) {
+ qWarning("QMetaObject::invokeMethod: No such method %s::%s",
+ obj->metaObject()->className(), sig.constData());
+ return false;
+ }
+ QMetaMethod method = obj->metaObject()->method(idx);
+ return method.invoke(obj, type, ret,
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+}
+
+/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
+ QGenericReturnArgument ret,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument());
+ \overload invokeMethod()
+
+ This overload always invokes the member using the connection type Qt::AutoConnection.
+*/
+
+/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
+ Qt::ConnectionType type,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+
+ \overload invokeMethod()
+
+ This overload can be used if the return value of the member is of no interest.
+*/
+
+/*!
+ \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+
+ \overload invokeMethod()
+
+ This overload invokes the member using the connection type Qt::AutoConnection and
+ ignores return values.
+*/
+
+/*!
+ \class QMetaMethod
+
+ \brief The QMetaMethod class provides meta-data about a member
+ function.
+
+ \ingroup objectmodel
+
+ A QMetaMethod has a methodType(), a signature(), a list of
+ parameterTypes() and parameterNames(), a return typeName(), a
+ tag(), and an access() specifier. You can use invoke() to invoke
+ the method on an arbitrary QObject.
+
+ \sa QMetaObject, QMetaEnum, QMetaProperty, {Qt's Property System}
+*/
+
+/*!
+ \enum QMetaMethod::Attributes
+
+ \internal
+
+ \value Compatibility
+ \value Cloned
+ \value Scriptable
+*/
+
+/*!
+ \fn const QMetaObject *QMetaMethod::enclosingMetaObject() const
+ \internal
+*/
+
+/*!
+ \enum QMetaMethod::MethodType
+
+ \value Method The function is a plain member function.
+ \value Signal The function is a signal.
+ \value Slot The function is a slot.
+ \value Constructor The function is a constructor.
+*/
+
+/*!
+ \fn QMetaMethod::QMetaMethod()
+ \internal
+*/
+
+/*!
+ Returns the signature of this method (e.g.,
+ \c{setValue(double)}).
+
+ \sa parameterTypes(), parameterNames()
+*/
+const char *QMetaMethod::signature() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns a list of parameter types.
+
+ \sa parameterNames(), signature()
+*/
+QList<QByteArray> QMetaMethod::parameterTypes() const
+{
+ QList<QByteArray> list;
+ if (!mobj)
+ return list;
+ const char *signature = mobj->d.stringdata + mobj->d.data[handle];
+ while (*signature && *signature != '(')
+ ++signature;
+ while (*signature && *signature != ')' && *++signature != ')') {
+ const char *begin = signature;
+ int level = 0;
+ while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
+ if (*signature == '<')
+ ++level;
+ else if (*signature == '>')
+ --level;
+ ++signature;
+ }
+ list += QByteArray(begin, signature - begin);
+ }
+ return list;
+}
+
+/*!
+ Returns a list of parameter names.
+
+ \sa parameterTypes(), signature()
+*/
+QList<QByteArray> QMetaMethod::parameterNames() const
+{
+ QList<QByteArray> list;
+ if (!mobj)
+ return list;
+ const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
+ if (*names == 0) {
+ // do we have one or zero arguments?
+ const char *signature = mobj->d.stringdata + mobj->d.data[handle];
+ while (*signature && *signature != '(')
+ ++signature;
+ if (*++signature != ')')
+ list += QByteArray();
+ } else {
+ --names;
+ do {
+ const char *begin = ++names;
+ while (*names && *names != ',')
+ ++names;
+ list += QByteArray(begin, names - begin);
+ } while (*names);
+ }
+ return list;
+}
+
+
+/*!
+ Returns the return type of this method, or an empty string if the
+ return type is \e void.
+*/
+const char *QMetaMethod::typeName() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle + 2];
+}
+
+/*!
+ Returns the tag associated with this method.
+
+ Tags are special macros recognized by \c moc that make it
+ possible to add extra information about a method. For the moment,
+ \c moc doesn't support any special tags.
+*/
+const char *QMetaMethod::tag() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle + 3];
+}
+
+
+/*! \internal */
+int QMetaMethod::attributes() const
+{
+ if (!mobj)
+ return false;
+ return ((mobj->d.data[handle + 4])>>4);
+}
+
+/*!
+ \since 4.6
+
+ Returns this method's index.
+*/
+int QMetaMethod::methodIndex() const
+{
+ if (!mobj)
+ return -1;
+ return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
+}
+
+/*!
+ \internal
+
+ Returns the method revision if one was
+ specified by Q_REVISION, otherwise returns 0.
+ */
+int QMetaMethod::revision() const
+{
+ if (!mobj)
+ return 0;
+ if ((QMetaMethod::Access)(mobj->d.data[handle + 4] & MethodRevisioned)) {
+ int offset = priv(mobj->d.data)->methodData
+ + priv(mobj->d.data)->methodCount * 5
+ + (handle - priv(mobj->d.data)->methodData) / 5;
+ return mobj->d.data[offset];
+ }
+ return 0;
+}
+
+/*!
+ Returns the access specification of this method (private,
+ protected, or public).
+
+ Signals are always protected, meaning that you can only emit them
+ from the class or from a subclass.
+
+ \sa methodType()
+*/
+QMetaMethod::Access QMetaMethod::access() const
+{
+ if (!mobj)
+ return Private;
+ return (QMetaMethod::Access)(mobj->d.data[handle + 4] & AccessMask);
+}
+
+/*!
+ Returns the type of this method (signal, slot, or method).
+
+ \sa access()
+*/
+QMetaMethod::MethodType QMetaMethod::methodType() const
+{
+ if (!mobj)
+ return QMetaMethod::Method;
+ return (QMetaMethod::MethodType)((mobj->d.data[handle + 4] & MethodTypeMask)>>2);
+}
+
+/*!
+ Invokes this method on the object \a object. Returns true if the member could be invoked.
+ Returns false if there is no such member or the parameters did not match.
+
+ The invocation can be either synchronous or asynchronous, depending on the
+ \a connectionType:
+
+ \list
+ \o If \a connectionType is Qt::DirectConnection, the member will be invoked immediately.
+
+ \o If \a connectionType is Qt::QueuedConnection,
+ a QEvent will be posted and the member is invoked as soon as the application
+ enters the main event loop.
+
+ \o If \a connectionType is Qt::AutoConnection, the member is invoked
+ synchronously if \a object lives in the same thread as the
+ caller; otherwise it will invoke the member asynchronously.
+ \endlist
+
+ The return value of this method call is placed in \a
+ returnValue. If the invocation is asynchronous, the return value cannot
+ be evaluated. You can pass up to ten arguments (\a val0, \a val1,
+ \a val2, \a val3, \a val4, \a val5, \a val6, \a val7, \a val8,
+ and \a val9) to this method call.
+
+ QGenericArgument and QGenericReturnArgument are internal
+ helper classes. Because signals and slots can be dynamically
+ invoked, you must enclose the arguments using the Q_ARG() and
+ Q_RETURN_ARG() macros. Q_ARG() takes a type name and a
+ const reference of that type; Q_RETURN_ARG() takes a type name
+ and a non-const reference.
+
+ To asynchronously invoke the
+ \l{QPushButton::animateClick()}{animateClick()} slot on a
+ QPushButton:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 6
+
+ With asynchronous method invocations, the parameters must be of
+ types that are known to Qt's meta-object system, because Qt needs
+ to copy the arguments to store them in an event behind the
+ scenes. If you try to use a queued connection and get the error
+ message
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 7
+
+ call qRegisterMetaType() to register the data type before you
+ call QMetaMethod::invoke().
+
+ To synchronously invoke the \c compute(QString, int, double) slot on
+ some arbitrary object \c obj retrieve its return value:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 8
+
+ QMetaObject::normalizedSignature() is used here to ensure that the format
+ of the signature is what invoke() expects. E.g. extra whitespace is
+ removed.
+
+ If the "compute" slot does not take exactly one QString, one int
+ and one double in the specified order, the call will fail.
+
+ \warning this method will not test the validity of the arguments: \a object
+ must be an instance of the class of the QMetaObject of which this QMetaMethod
+ has been constructed with. The arguments must have the same type as the ones
+ expected by the method, else, the behaviour is undefined.
+
+ \sa Q_ARG(), Q_RETURN_ARG(), qRegisterMetaType(), QMetaObject::invokeMethod()
+*/
+bool QMetaMethod::invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0,
+ QGenericArgument val1,
+ QGenericArgument val2,
+ QGenericArgument val3,
+ QGenericArgument val4,
+ QGenericArgument val5,
+ QGenericArgument val6,
+ QGenericArgument val7,
+ QGenericArgument val8,
+ QGenericArgument val9) const
+{
+ if (!object || !mobj)
+ return false;
+
+ Q_ASSERT(mobj->cast(object));
+
+ // check return type
+ if (returnValue.data()) {
+ const char *retType = typeName();
+ if (qstrcmp(returnValue.name(), retType) != 0) {
+ // normalize the return value as well
+ // the trick here is to make a function signature out of the return type
+ // so that we can call normalizedSignature() and avoid duplicating code
+ QByteArray unnormalized;
+ int len = qstrlen(returnValue.name());
+
+ unnormalized.reserve(len + 3);
+ unnormalized = "_("; // the function is called "_"
+ unnormalized.append(returnValue.name());
+ unnormalized.append(')');
+
+ QByteArray normalized = QMetaObject::normalizedSignature(unnormalized.constData());
+ normalized.truncate(normalized.length() - 1); // drop the ending ')'
+
+ if (qstrcmp(normalized.constData() + 2, retType) != 0)
+ return false;
+ }
+ }
+
+ // check argument count (we don't allow invoking a method if given too few arguments)
+ const char *typeNames[] = {
+ returnValue.name(),
+ val0.name(),
+ val1.name(),
+ val2.name(),
+ val3.name(),
+ val4.name(),
+ val5.name(),
+ val6.name(),
+ val7.name(),
+ val8.name(),
+ val9.name()
+ };
+ int paramCount;
+ for (paramCount = 1; paramCount < MaximumParamCount; ++paramCount) {
+ if (qstrlen(typeNames[paramCount]) <= 0)
+ break;
+ }
+ int metaMethodArgumentCount = 0;
+ {
+ // based on QMetaObject::parameterNames()
+ const char *names = mobj->d.stringdata + mobj->d.data[handle + 1];
+ if (*names == 0) {
+ // do we have one or zero arguments?
+ const char *signature = mobj->d.stringdata + mobj->d.data[handle];
+ while (*signature && *signature != '(')
+ ++signature;
+ if (*++signature != ')')
+ ++metaMethodArgumentCount;
+ } else {
+ --names;
+ do {
+ ++names;
+ while (*names && *names != ',')
+ ++names;
+ ++metaMethodArgumentCount;
+ } while (*names);
+ }
+ }
+ if (paramCount <= metaMethodArgumentCount)
+ return false;
+
+ // check connection type
+ QThread *currentThread = QThread::currentThread();
+ QThread *objectThread = object->thread();
+ if (connectionType == Qt::AutoConnection) {
+ connectionType = currentThread == objectThread
+ ? Qt::DirectConnection
+ : Qt::QueuedConnection;
+ }
+
+#ifdef QT_NO_THREAD
+ if (connectionType == Qt::BlockingQueuedConnection) {
+ connectionType = Qt::DirectConnection;
+ }
+#endif
+
+ // invoke!
+ void *param[] = {
+ returnValue.data(),
+ val0.data(),
+ val1.data(),
+ val2.data(),
+ val3.data(),
+ val4.data(),
+ val5.data(),
+ val6.data(),
+ val7.data(),
+ val8.data(),
+ val9.data()
+ };
+ // recompute the methodIndex by reversing the arithmetic in QMetaObject::property()
+ int idx_relative = ((handle - priv(mobj->d.data)->methodData) / 5);
+ int idx_offset = mobj->methodOffset();
+ QObjectPrivate::StaticMetaCallFunction callFunction =
+ (QMetaObjectPrivate::get(mobj)->revision >= 6 && mobj->d.extradata)
+ ? reinterpret_cast<const QMetaObjectExtraData *>(mobj->d.extradata)->static_metacall : 0;
+
+ if (connectionType == Qt::DirectConnection) {
+ if (callFunction) {
+ callFunction(object, QMetaObject::InvokeMetaMethod, idx_relative, param);
+ return true;
+ } else {
+ return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, idx_relative + idx_offset, param) < 0;
+ }
+ } else if (connectionType == Qt::QueuedConnection) {
+ if (returnValue.data()) {
+ qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in "
+ "queued connections");
+ return false;
+ }
+
+ int nargs = 1; // include return type
+ void **args = (void **) qMalloc(paramCount * sizeof(void *));
+ Q_CHECK_PTR(args);
+ int *types = (int *) qMalloc(paramCount * sizeof(int));
+ Q_CHECK_PTR(types);
+ types[0] = 0; // return type
+ args[0] = 0;
+
+ for (int i = 1; i < paramCount; ++i) {
+ types[i] = QMetaType::type(typeNames[i]);
+ if (types[i]) {
+ args[i] = QMetaType::construct(types[i], param[i]);
+ ++nargs;
+ } else if (param[i]) {
+ qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
+ typeNames[i]);
+ for (int x = 1; x < i; ++x) {
+ if (types[x] && args[x])
+ QMetaType::destroy(types[x], args[x]);
+ }
+ qFree(types);
+ qFree(args);
+ return false;
+ }
+ }
+
+ QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
+ 0, -1, nargs, types, args));
+ } else { // blocking queued connection
+#ifndef QT_NO_THREAD
+ if (currentThread == objectThread) {
+ qWarning("QMetaMethod::invoke: Dead lock detected in "
+ "BlockingQueuedConnection: Receiver is %s(%p)",
+ mobj->className(), object);
+ }
+
+ QSemaphore semaphore;
+ QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction,
+ 0, -1, 0, 0, param, &semaphore));
+ semaphore.acquire();
+#endif // QT_NO_THREAD
+ }
+ return true;
+}
+
+/*! \fn bool QMetaMethod::invoke(QObject *object,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ \overload invoke()
+
+ This overload always invokes this method using the connection type Qt::AutoConnection.
+*/
+
+/*! \fn bool QMetaMethod::invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+
+ \overload invoke()
+
+ This overload can be used if the return value of the member is of no interest.
+*/
+
+/*!
+ \fn bool QMetaMethod::invoke(QObject *object,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+
+ \overload invoke()
+
+ This overload invokes this method using the
+ connection type Qt::AutoConnection and ignores return values.
+*/
+
+/*!
+ \class QMetaEnum
+ \brief The QMetaEnum class provides meta-data about an enumerator.
+
+ \ingroup objectmodel
+
+ Use name() for the enumerator's name. The enumerator's keys (names
+ of each enumerated item) are returned by key(); use keyCount() to find
+ the number of keys. isFlag() returns whether the enumerator is
+ meant to be used as a flag, meaning that its values can be combined
+ using the OR operator.
+
+ The conversion functions keyToValue(), valueToKey(), keysToValue(),
+ and valueToKeys() allow conversion between the integer
+ representation of an enumeration or set value and its literal
+ representation. The scope() function returns the class scope this
+ enumerator was declared in.
+
+ \sa QMetaObject, QMetaMethod, QMetaProperty
+*/
+
+/*!
+ \fn bool QMetaEnum::isValid() const
+
+ Returns true if this enum is valid (has a name); otherwise returns
+ false.
+
+ \sa name()
+*/
+
+/*!
+ \fn const QMetaObject *QMetaEnum::enclosingMetaObject() const
+ \internal
+*/
+
+
+/*!
+ \fn QMetaEnum::QMetaEnum()
+ \internal
+*/
+
+/*!
+ Returns the name of the enumerator (without the scope).
+
+ For example, the Qt::AlignmentFlag enumeration has \c
+ AlignmentFlag as the name and \l Qt as the scope.
+
+ \sa isValid(), scope()
+*/
+const char *QMetaEnum::name() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns the number of keys.
+
+ \sa key()
+*/
+int QMetaEnum::keyCount() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.data[handle + 2];
+}
+
+
+/*!
+ Returns the key with the given \a index, or 0 if no such key exists.
+
+ \sa keyCount(), value(), valueToKey()
+*/
+const char *QMetaEnum::key(int index) const
+{
+ if (!mobj)
+ return 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ if (index >= 0 && index < count)
+ return mobj->d.stringdata + mobj->d.data[data + 2*index];
+ return 0;
+}
+
+/*!
+ Returns the value with the given \a index; or returns -1 if there
+ is no such value.
+
+ \sa keyCount(), key(), keyToValue()
+*/
+int QMetaEnum::value(int index) const
+{
+ if (!mobj)
+ return 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ if (index >= 0 && index < count)
+ return mobj->d.data[data + 2*index + 1];
+ return -1;
+}
+
+
+/*!
+ Returns true if this enumerator is used as a flag; otherwise returns
+ false.
+
+ When used as flags, enumerators can be combined using the OR
+ operator.
+
+ \sa keysToValue(), valueToKeys()
+*/
+bool QMetaEnum::isFlag() const
+{
+ return mobj && mobj->d.data[handle + 1];
+}
+
+
+/*!
+ Returns the scope this enumerator was declared in.
+
+ For example, the Qt::AlignmentFlag enumeration has \c Qt as
+ the scope and \c AlignmentFlag as the name.
+
+ \sa name()
+*/
+const char *QMetaEnum::scope() const
+{
+ return mobj?mobj->d.stringdata : 0;
+}
+
+/*!
+ Returns the integer value of the given enumeration \a key, or -1
+ if \a key is not defined.
+
+ For flag types, use keysToValue().
+
+ \sa valueToKey(), isFlag(), keysToValue()
+*/
+int QMetaEnum::keyToValue(const char *key) const
+{
+ if (!mobj || !key)
+ return -1;
+ uint scope = 0;
+ const char *qualified_key = key;
+ const char *s = key + qstrlen(key);
+ while (s > key && *s != ':')
+ --s;
+ if (s > key && *(s-1)==':') {
+ scope = s - key - 1;
+ key += scope + 2;
+ }
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ for (int i = 0; i < count; ++i)
+ if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key, mobj->d.stringdata, scope) == 0))
+ && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0)
+ return mobj->d.data[data + 2*i + 1];
+ return -1;
+}
+
+/*!
+ Returns the string that is used as the name of the given
+ enumeration \a value, or 0 if \a value is not defined.
+
+ For flag types, use valueToKeys().
+
+ \sa isFlag(), valueToKeys()
+*/
+const char* QMetaEnum::valueToKey(int value) const
+{
+ if (!mobj)
+ return 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ for (int i = 0; i < count; ++i)
+ if (value == (int)mobj->d.data[data + 2*i + 1])
+ return mobj->d.stringdata + mobj->d.data[data + 2*i];
+ return 0;
+}
+
+/*!
+ Returns the value derived from combining together the values of
+ the \a keys using the OR operator, or -1 if \a keys is not
+ defined. Note that the strings in \a keys must be '|'-separated.
+
+ \sa isFlag(), valueToKey(), valueToKeys()
+*/
+int QMetaEnum::keysToValue(const char *keys) const
+{
+ if (!mobj)
+ return -1;
+ QStringList l = QString::fromLatin1(keys).split(QLatin1Char('|'));
+ //#### TODO write proper code, do not use QStringList
+ int value = 0;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ for (int li = 0; li < l.size(); ++li) {
+ QString trimmed = l.at(li).trimmed();
+ QByteArray qualified_key = trimmed.toLatin1();
+ const char *key = qualified_key.constData();
+ uint scope = 0;
+ const char *s = key + qstrlen(key);
+ while (s > key && *s != ':')
+ --s;
+ if (s > key && *(s-1)==':') {
+ scope = s - key - 1;
+ key += scope + 2;
+ }
+ int i;
+ for (i = count-1; i >= 0; --i)
+ if ((!scope || (qstrlen(mobj->d.stringdata) == scope && strncmp(qualified_key.constData(), mobj->d.stringdata, scope) == 0))
+ && strcmp(key, mobj->d.stringdata + mobj->d.data[data + 2*i]) == 0) {
+ value |= mobj->d.data[data + 2*i + 1];
+ break;
+ }
+ if (i < 0)
+ value |= -1;
+ }
+ return value;
+}
+
+/*!
+ Returns a byte array of '|'-separated keys that represents the
+ given \a value.
+
+ \sa isFlag(), valueToKey(), keysToValue()
+*/
+QByteArray QMetaEnum::valueToKeys(int value) const
+{
+ QByteArray keys;
+ if (!mobj)
+ return keys;
+ int count = mobj->d.data[handle + 2];
+ int data = mobj->d.data[handle + 3];
+ int v = value;
+ for(int i = 0; i < count; i++) {
+ int k = mobj->d.data[data + 2*i + 1];
+ if ((k != 0 && (v & k) == k ) || (k == value)) {
+ v = v & ~k;
+ if (!keys.isEmpty())
+ keys += '|';
+ keys += mobj->d.stringdata + mobj->d.data[data + 2*i];
+ }
+ }
+ return keys;
+}
+
+static QByteArray qualifiedName(const QMetaEnum &e)
+{
+ return QByteArray(e.scope()) + "::" + e.name();
+}
+
+/*!
+ \class QMetaProperty
+ \brief The QMetaProperty class provides meta-data about a property.
+
+ \ingroup objectmodel
+
+ Property meta-data is obtained from an object's meta-object. See
+ QMetaObject::property() and QMetaObject::propertyCount() for
+ details.
+
+ \section1 Property Meta-Data
+
+ A property has a name() and a type(), as well as various
+ attributes that specify its behavior: isReadable(), isWritable(),
+ isDesignable(), isScriptable(), and isStored().
+
+ If the property is an enumeration, isEnumType() returns true; if the
+ property is an enumeration that is also a flag (i.e. its values
+ can be combined using the OR operator), isEnumType() and
+ isFlagType() both return true. The enumerator for these types is
+ available from enumerator().
+
+ The property's values are set and retrieved with read(), write(),
+ and reset(); they can also be changed through QObject's set and get
+ functions. See QObject::setProperty() and QObject::property() for
+ details.
+
+ \section1 Copying and Assignment
+
+ QMetaProperty objects can be copied by value. However, each copy will
+ refer to the same underlying property meta-data.
+
+ \sa QMetaObject, QMetaEnum, QMetaMethod, {Qt's Property System}
+*/
+
+/*!
+ \fn bool QMetaProperty::isValid() const
+
+ Returns true if this property is valid (readable); otherwise
+ returns false.
+
+ \sa isReadable()
+*/
+
+/*!
+ \fn const QMetaObject *QMetaProperty::enclosingMetaObject() const
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QMetaProperty::QMetaProperty()
+ : mobj(0), handle(0), idx(0)
+{
+}
+
+
+/*!
+ Returns this property's name.
+
+ \sa type(), typeName()
+*/
+const char *QMetaProperty::name() const
+{
+ if (!mobj)
+ return 0;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns the name of this property's type.
+
+ \sa type(), name()
+*/
+const char *QMetaProperty::typeName() const
+{
+ if (!mobj)
+ return 0;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ return mobj->d.stringdata + mobj->d.data[handle + 1];
+}
+
+/*!
+ Returns this property's type. The return value is one
+ of the values of the QVariant::Type enumeration.
+
+ \sa userType(), typeName(), name()
+*/
+QVariant::Type QMetaProperty::type() const
+{
+ if (!mobj)
+ return QVariant::Invalid;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ uint flags = mobj->d.data[handle + 2];
+
+ uint type = flags >> 24;
+ if (type == 0xff) // special value for QVariant
+ type = QVariant::LastType;
+ if (type)
+ return QVariant::Type(type);
+ if (isEnumType()) {
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ if (enumMetaTypeId == 0)
+ return QVariant::Int;
+ }
+#ifdef QT_COORD_TYPE
+ // qreal metatype must be resolved at runtime.
+ if (strcmp(typeName(), "qreal") == 0)
+ return QVariant::Type(qMetaTypeId<qreal>());
+#endif
+
+ return QVariant::UserType;
+}
+
+/*!
+ \since 4.2
+
+ Returns this property's user type. The return value is one
+ of the values that are registered with QMetaType, or 0 if
+ the type is not registered.
+
+ \sa type(), QMetaType, typeName()
+ */
+int QMetaProperty::userType() const
+{
+ QVariant::Type tp = type();
+ if (tp != QVariant::UserType)
+ return tp;
+ if (isEnumType()) {
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ return enumMetaTypeId;
+ }
+ return QMetaType::type(typeName());
+}
+
+/*!
+ \since 4.6
+
+ Returns this property's index.
+*/
+int QMetaProperty::propertyIndex() const
+{
+ if (!mobj)
+ return -1;
+ return idx + mobj->propertyOffset();
+}
+
+/*!
+ Returns true if the property's type is an enumeration value that
+ is used as a flag; otherwise returns false.
+
+ Flags can be combined using the OR operator. A flag type is
+ implicitly also an enum type.
+
+ \sa isEnumType(), enumerator(), QMetaEnum::isFlag()
+*/
+
+bool QMetaProperty::isFlagType() const
+{
+ return isEnumType() && menum.isFlag();
+}
+
+/*!
+ Returns true if the property's type is an enumeration value;
+ otherwise returns false.
+
+ \sa enumerator(), isFlagType()
+*/
+bool QMetaProperty::isEnumType() const
+{
+ if (!mobj)
+ return false;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ int flags = mobj->d.data[handle + 2];
+ return (flags & EnumOrFlag) && menum.name();
+}
+
+/*!
+ \internal
+
+ Returns true if the property has a C++ setter function that
+ follows Qt's standard "name" / "setName" pattern. Designer and uic
+ query hasStdCppSet() in order to avoid expensive
+ QObject::setProperty() calls. All properties in Qt [should] follow
+ this pattern.
+*/
+bool QMetaProperty::hasStdCppSet() const
+{
+ if (!mobj)
+ return false;
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ int flags = mobj->d.data[handle + 2];
+ return (flags & StdCppSet);
+}
+
+/*!
+ Returns the enumerator if this property's type is an enumerator
+ type; otherwise the returned value is undefined.
+
+ \sa isEnumType(), isFlagType()
+*/
+QMetaEnum QMetaProperty::enumerator() const
+{
+ return menum;
+}
+
+/*!
+ Reads the property's value from the given \a object. Returns the value
+ if it was able to read it; otherwise returns an invalid variant.
+
+ \sa write(), reset(), isReadable()
+*/
+QVariant QMetaProperty::read(const QObject *object) const
+{
+ if (!object || !mobj)
+ return QVariant();
+
+ uint t = QVariant::Int;
+ if (isEnumType()) {
+ /*
+ try to create a QVariant that can be converted to this enum
+ type (only works if the enum has already been registered
+ with QMetaType)
+ */
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ if (enumMetaTypeId != 0)
+ t = enumMetaTypeId;
+ } else {
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ uint flags = mobj->d.data[handle + 2];
+ const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
+ t = (flags >> 24);
+ if (t == 0xff) // special value for QVariant
+ t = QVariant::LastType;
+ if (t == QVariant::Invalid)
+ t = QMetaType::type(typeName);
+ if (t == QVariant::Invalid)
+ t = QVariant::nameToType(typeName);
+ if (t == QVariant::Invalid || t == QVariant::UserType) {
+ if (t == QVariant::Invalid)
+ qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property '%s::%s'", typeName, mobj->className(), name());
+ return QVariant();
+ }
+ }
+
+ // the status variable is changed by qt_metacall to indicate what it did
+ // this feature is currently only used by QtDBus and should not be depended
+ // upon. Don't change it without looking into QDBusAbstractInterface first
+ // -1 (unchanged): normal qt_metacall, result stored in argv[0]
+ // changed: result stored directly in value
+ int status = -1;
+ QVariant value;
+ void *argv[] = { 0, &value, &status };
+ if (t == QVariant::LastType) {
+ argv[0] = &value;
+ } else {
+ value = QVariant(t, (void*)0);
+ argv[0] = value.data();
+ }
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty,
+ idx + mobj->propertyOffset(), argv);
+
+ if (status != -1)
+ return value;
+ if (t != QVariant::LastType && argv[0] != value.data())
+ // pointer or reference
+ return QVariant((QVariant::Type)t, argv[0]);
+ return value;
+}
+
+/*!
+ Writes \a value as the property's value to the given \a object. Returns
+ true if the write succeeded; otherwise returns false.
+
+ \sa read(), reset(), isWritable()
+*/
+bool QMetaProperty::write(QObject *object, const QVariant &value) const
+{
+ if (!object || !isWritable())
+ return false;
+
+ QVariant v = value;
+ uint t = QVariant::Invalid;
+ if (isEnumType()) {
+ if (v.type() == QVariant::String
+#ifdef QT3_SUPPORT
+ || v.type() == QVariant::CString
+#endif
+ ) {
+ if (isFlagType())
+ v = QVariant(menum.keysToValue(value.toByteArray()));
+ else
+ v = QVariant(menum.keyToValue(value.toByteArray()));
+ } else if (v.type() != QVariant::Int && v.type() != QVariant::UInt) {
+ int enumMetaTypeId = QMetaType::type(qualifiedName(menum));
+ if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+ return false;
+ v = QVariant(*reinterpret_cast<const int *>(v.constData()));
+ }
+ v.convert(QVariant::Int);
+ } else {
+ int handle = priv(mobj->d.data)->propertyData + 3*idx;
+ uint flags = mobj->d.data[handle + 2];
+ t = flags >> 24;
+ if (t == 0xff) // special value for QVariant
+ t = QVariant::LastType;
+ if (t == QVariant::Invalid) {
+ const char *typeName = mobj->d.stringdata + mobj->d.data[handle + 1];
+ const char *vtypeName = value.typeName();
+ if (vtypeName && strcmp(typeName, vtypeName) == 0)
+ t = value.userType();
+ else
+ t = QVariant::nameToType(typeName);
+ }
+ if (t == QVariant::Invalid)
+ return false;
+ if (t != QVariant::LastType && t != (uint)value.userType() && (t < QMetaType::User && !v.convert((QVariant::Type)t)))
+ return false;
+ }
+
+ // the status variable is changed by qt_metacall to indicate what it did
+ // this feature is currently only used by QtDBus and should not be depended
+ // upon. Don't change it without looking into QDBusAbstractInterface first
+ // -1 (unchanged): normal qt_metacall, result stored in argv[0]
+ // changed: result stored directly in value, return the value of status
+ int status = -1;
+ // the flags variable is used by the declarative module to implement
+ // interception of property writes.
+ int flags = 0;
+ void *argv[] = { 0, &v, &status, &flags };
+ if (t == QVariant::LastType)
+ argv[0] = &v;
+ else
+ argv[0] = v.data();
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
+ return status;
+}
+
+/*!
+ Resets the property for the given \a object with a reset method.
+ Returns true if the reset worked; otherwise returns false.
+
+ Reset methods are optional; only a few properties support them.
+
+ \sa read(), write()
+*/
+bool QMetaProperty::reset(QObject *object) const
+{
+ if (!object || !mobj || !isResettable())
+ return false;
+ void *argv[] = { 0 };
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv);
+ return true;
+}
+
+/*!
+ Returns true if this property can be reset to a default value; otherwise
+ returns false.
+
+ \sa reset()
+*/
+bool QMetaProperty::isResettable() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Resettable;
+}
+
+/*!
+ Returns true if this property is readable; otherwise returns false.
+
+ \sa isWritable(), read(), isValid()
+ */
+bool QMetaProperty::isReadable() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Readable;
+}
+
+/*!
+ Returns true if this property has a corresponding change notify signal;
+ otherwise returns false.
+
+ \sa notifySignal()
+ */
+bool QMetaProperty::hasNotifySignal() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Notify;
+}
+
+/*!
+ \since 4.5
+
+ Returns the QMetaMethod instance of the property change notifying signal if
+ one was specified, otherwise returns an invalid QMetaMethod.
+
+ \sa hasNotifySignal()
+ */
+QMetaMethod QMetaProperty::notifySignal() const
+{
+ int id = notifySignalIndex();
+ if (id != -1)
+ return mobj->method(id);
+ else
+ return QMetaMethod();
+}
+
+/*!
+ \since 4.6
+
+ Returns the index of the property change notifying signal if one was
+ specified, otherwise returns -1.
+
+ \sa hasNotifySignal()
+ */
+int QMetaProperty::notifySignalIndex() const
+{
+ if (hasNotifySignal()) {
+ int offset = priv(mobj->d.data)->propertyData +
+ priv(mobj->d.data)->propertyCount * 3 + idx;
+ return mobj->d.data[offset] + mobj->methodOffset();
+ } else {
+ return -1;
+ }
+}
+
+/*!
+ \internal
+
+ Returns the property revision if one was
+ specified by REVISION, otherwise returns 0.
+ */
+int QMetaProperty::revision() const
+{
+ if (!mobj)
+ return 0;
+ int flags = mobj->d.data[handle + 2];
+ if (flags & Revisioned) {
+ int offset = priv(mobj->d.data)->propertyData +
+ priv(mobj->d.data)->propertyCount * 3 + idx;
+ // Revision data is placed after NOTIFY data, if present.
+ // Iterate through properties to discover whether we have NOTIFY signals.
+ for (int i = 0; i < priv(mobj->d.data)->propertyCount; ++i) {
+ int handle = priv(mobj->d.data)->propertyData + 3*i;
+ if (mobj->d.data[handle + 2] & Notify) {
+ offset += priv(mobj->d.data)->propertyCount;
+ break;
+ }
+ }
+ return mobj->d.data[offset];
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ Returns true if this property is writable; otherwise returns
+ false.
+
+ \sa isReadable(), write()
+ */
+bool QMetaProperty::isWritable() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Writable;
+}
+
+
+/*!
+ Returns true if this property is designable for the given \a object;
+ otherwise returns false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c DESIGNABLE attribute is false; otherwise
+ returns true (if the attribute is true or is a function or expression).
+
+ \sa isScriptable(), isStored()
+*/
+bool QMetaProperty::isDesignable(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Designable;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+
+
+}
+
+/*!
+ Returns true if the property is scriptable for the given \a object;
+ otherwise returns false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c SCRIPTABLE attribute is false; otherwise returns
+ true (if the attribute is true or is a function or expression).
+
+ \sa isDesignable(), isStored()
+*/
+bool QMetaProperty::isScriptable(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Scriptable;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ Returns true if the property is stored for \a object; otherwise returns
+ false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c STORED attribute is false; otherwise returns
+ true (if the attribute is true or is a function or expression).
+
+ \sa isDesignable(), isScriptable()
+*/
+bool QMetaProperty::isStored(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Stored;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ Returns true if this property is designated as the \c USER
+ property, i.e., the one that the user can edit for \a object or
+ that is significant in some other way. Otherwise it returns
+ false. e.g., the \c text property is the \c USER editable property
+ of a QLineEdit.
+
+ If \a object is null, the function returns false if the \c
+ {Q_PROPERTY()}'s \c USER attribute is false. Otherwise it returns
+ true.
+
+ \sa QMetaObject::userProperty(), isDesignable(), isScriptable()
+*/
+bool QMetaProperty::isUser(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & User;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ \since 4.6
+ Returns true if the property is constant; otherwise returns false.
+
+ A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute
+ is set.
+*/
+bool QMetaProperty::isConstant() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Constant;
+}
+
+/*!
+ \since 4.6
+ Returns true if the property is final; otherwise returns false.
+
+ A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute
+ is set.
+*/
+bool QMetaProperty::isFinal() const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ return flags & Final;
+}
+
+/*!
+ \obsolete
+
+ Returns true if the property is editable for the given \a object;
+ otherwise returns false.
+
+ If no \a object is given, the function returns false if the
+ \c{Q_PROPERTY()}'s \c EDITABLE attribute is false; otherwise returns
+ true (if the attribute is true or is a function or expression).
+
+ \sa isDesignable(), isScriptable(), isStored()
+*/
+bool QMetaProperty::isEditable(const QObject *object) const
+{
+ if (!mobj)
+ return false;
+ int flags = mobj->d.data[handle + 2];
+ bool b = flags & Editable;
+ if (object) {
+ void *argv[] = { &b };
+ QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ \class QMetaClassInfo
+
+ \brief The QMetaClassInfo class provides additional information
+ about a class.
+
+ \ingroup objectmodel
+
+ Class information items are simple \e{name}--\e{value} pairs that
+ are specified using Q_CLASSINFO() in the source code. The
+ information can be retrieved using name() and value(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetaobject.cpp 5
+
+ This mechanism is free for you to use in your Qt applications. Qt
+ doesn't use it for any of its classes.
+
+ \sa QMetaObject
+*/
+
+
+/*!
+ \fn QMetaClassInfo::QMetaClassInfo()
+ \internal
+*/
+
+/*!
+ \fn const QMetaObject *QMetaClassInfo::enclosingMetaObject() const
+ \internal
+*/
+
+/*!
+ Returns the name of this item.
+
+ \sa value()
+*/
+const char *QMetaClassInfo::name() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle];
+}
+
+/*!
+ Returns the value of this item.
+
+ \sa name()
+*/
+const char* QMetaClassInfo::value() const
+{
+ if (!mobj)
+ return 0;
+ return mobj->d.stringdata + mobj->d.data[handle + 1];
+}
+
+/*!
+ \macro QGenericArgument Q_ARG(Type, const Type &value)
+ \relates QMetaObject
+
+ This macro takes a \a Type and a \a value of that type and
+ returns a \l QGenericArgument object that can be passed to
+ QMetaObject::invokeMethod().
+
+ \sa Q_RETURN_ARG()
+*/
+
+/*!
+ \macro QGenericReturnArgument Q_RETURN_ARG(Type, Type &value)
+ \relates QMetaObject
+
+ This macro takes a \a Type and a non-const reference to a \a
+ value of that type and returns a QGenericReturnArgument object
+ that can be passed to QMetaObject::invokeMethod().
+
+ \sa Q_ARG()
+*/
+
+/*!
+ \class QGenericArgument
+
+ \brief The QGenericArgument class is an internal helper class for
+ marshalling arguments.
+
+ This class should never be used directly. Please use the \l Q_ARG()
+ macro instead.
+
+ \sa Q_ARG(), QMetaObject::invokeMethod(), QGenericReturnArgument
+*/
+
+/*!
+ \fn QGenericArgument::QGenericArgument(const char *name, const void *data)
+
+ Constructs a QGenericArgument object with the given \a name and \a data.
+*/
+
+/*!
+ \fn QGenericArgument::data () const
+
+ Returns the data set in the constructor.
+*/
+
+/*!
+ \fn QGenericArgument::name () const
+
+ Returns the name set in the constructor.
+*/
+
+/*!
+ \class QGenericReturnArgument
+
+ \brief The QGenericReturnArgument class is an internal helper class for
+ marshalling arguments.
+
+ This class should never be used directly. Please use the
+ Q_RETURN_ARG() macro instead.
+
+ \sa Q_RETURN_ARG(), QMetaObject::invokeMethod(), QGenericArgument
+*/
+
+/*!
+ \fn QGenericReturnArgument::QGenericReturnArgument(const char *name, void *data)
+
+ Constructs a QGenericReturnArgument object with the given \a name
+ and \a data.
+*/
+
+/*! \internal
+ If the local_method_index is a cloned method, return the index of the original.
+
+ Example: if the index of "destroyed()" is passed, the index of "destroyed(QObject*)" is returned
+ */
+int QMetaObjectPrivate::originalClone(const QMetaObject *mobj, int local_method_index)
+{
+ Q_ASSERT(local_method_index < get(mobj)->methodCount);
+ int handle = get(mobj)->methodData + 5 * local_method_index;
+ while (mobj->d.data[handle + 4] & MethodCloned) {
+ Q_ASSERT(local_method_index > 0);
+ handle -= 5;
+ local_method_index--;
+ }
+ return local_method_index;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
new file mode 100644
index 0000000000..e9bba45391
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject.h
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QMETAOBJECT_H
+#define QMETAOBJECT_H
+
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <typename T> class QList;
+
+class Q_CORE_EXPORT QMetaMethod
+{
+public:
+ inline QMetaMethod() : mobj(0),handle(0) {}
+
+ const char *signature() const;
+ const char *typeName() const;
+ QList<QByteArray> parameterTypes() const;
+ QList<QByteArray> parameterNames() const;
+ const char *tag() const;
+ enum Access { Private, Protected, Public };
+ Access access() const;
+ enum MethodType { Method, Signal, Slot, Constructor };
+ MethodType methodType() const;
+ enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 };
+ int attributes() const;
+ int methodIndex() const;
+ int revision() const;
+
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+
+ bool invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const;
+ inline bool invoke(QObject *object,
+ QGenericReturnArgument returnValue,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ {
+ return invoke(object, Qt::AutoConnection, returnValue,
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+ inline bool invoke(QObject *object,
+ Qt::ConnectionType connectionType,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ {
+ return invoke(object, connectionType, QGenericReturnArgument(),
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+ inline bool invoke(QObject *object,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const
+ {
+ return invoke(object, Qt::AutoConnection, QGenericReturnArgument(),
+ val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ friend struct QMetaObject;
+ friend struct QMetaObjectPrivate;
+ friend class QObject;
+};
+Q_DECLARE_TYPEINFO(QMetaMethod, Q_MOVABLE_TYPE);
+
+class Q_CORE_EXPORT QMetaEnum
+{
+public:
+ inline QMetaEnum() : mobj(0),handle(0) {}
+
+ const char *name() const;
+ bool isFlag() const;
+
+ int keyCount() const;
+ const char *key(int index) const;
+ int value(int index) const;
+
+ const char *scope() const;
+
+ int keyToValue(const char *key) const;
+ const char* valueToKey(int value) const;
+ int keysToValue(const char * keys) const;
+ QByteArray valueToKeys(int value) const;
+
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+
+ inline bool isValid() const { return name() != 0; }
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ friend struct QMetaObject;
+};
+Q_DECLARE_TYPEINFO(QMetaEnum, Q_MOVABLE_TYPE);
+
+class Q_CORE_EXPORT QMetaProperty
+{
+public:
+ QMetaProperty();
+
+ const char *name() const;
+ const char *typeName() const;
+ QVariant::Type type() const;
+ int userType() const;
+ int propertyIndex() const;
+
+ bool isReadable() const;
+ bool isWritable() const;
+ bool isResettable() const;
+ bool isDesignable(const QObject *obj = 0) const;
+ bool isScriptable(const QObject *obj = 0) const;
+ bool isStored(const QObject *obj = 0) const;
+ bool isEditable(const QObject *obj = 0) const;
+ bool isUser(const QObject *obj = 0) const;
+ bool isConstant() const;
+ bool isFinal() const;
+
+ bool isFlagType() const;
+ bool isEnumType() const;
+ QMetaEnum enumerator() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethod notifySignal() const;
+ int notifySignalIndex() const;
+
+ int revision() const;
+
+ QVariant read(const QObject *obj) const;
+ bool write(QObject *obj, const QVariant &value) const;
+ bool reset(QObject *obj) const;
+
+ bool hasStdCppSet() const;
+ inline bool isValid() const { return isReadable(); }
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ int idx;
+ QMetaEnum menum;
+ friend struct QMetaObject;
+};
+
+class Q_CORE_EXPORT QMetaClassInfo
+{
+public:
+ inline QMetaClassInfo() : mobj(0),handle(0) {}
+ const char *name() const;
+ const char *value() const;
+ inline const QMetaObject *enclosingMetaObject() const { return mobj; }
+private:
+ const QMetaObject *mobj;
+ uint handle;
+ friend struct QMetaObject;
+};
+Q_DECLARE_TYPEINFO(QMetaClassInfo, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMETAOBJECT_H
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
new file mode 100644
index 0000000000..fdadf4ac9f
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QMETAOBJECT_P_H
+#define QMETAOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of moc. This header file may change from version to version without notice,
+// or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_NAMESPACE
+
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Constant = 0x00000400,
+ Final = 0x00000800,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000,
+ Revisioned = 0x00800000
+};
+
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ AccessMask = 0x03, //mask
+
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodTypeMask = 0x0c,
+
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40,
+ MethodRevisioned = 0x80
+};
+
+enum MetaObjectFlags {
+ DynamicMetaObject = 0x01
+};
+
+class QMutex;
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData; //since revision 2
+ int flags; //since revision 3
+ int signalCount; //since revision 4
+ // revision 5 introduces changes in normalized signatures, no new members
+ // revision 6 added qt_static_metacall as a member of each Q_OBJECT and inside QMetaObject itself
+
+ static inline const QMetaObjectPrivate *get(const QMetaObject *metaobject)
+ { return reinterpret_cast<const QMetaObjectPrivate*>(metaobject->d.data); }
+
+ static int indexOfSignalRelative(const QMetaObject **baseObject,
+ const char* name,
+ bool normalizeStringData);
+ static int indexOfSlotRelative(const QMetaObject **m,
+ const char *slot,
+ bool normalizeStringData);
+ static int originalClone(const QMetaObject *obj, int local_method_index);
+
+#ifndef QT_NO_QOBJECT
+ //defined in qobject.cpp
+ enum DisconnectType { DisconnectAll, DisconnectOne };
+ static void memberIndexes(const QObject *obj, const QMetaMethod &member,
+ int *signalIndex, int *methodIndex);
+ static bool connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index_relative,
+ const QMetaObject *rmeta = 0,
+ int type = 0, int *types = 0);
+ static bool disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ DisconnectType = DisconnectAll);
+ static inline bool disconnectHelper(QObjectPrivate::Connection *c,
+ const QObject *receiver, int method_index,
+ QMutex *senderMutex, DisconnectType);
+#endif
+};
+
+#ifndef UTILS_H
+// mirrored in moc's utils.h
+static inline bool is_ident_char(char s)
+{
+ return ((s >= 'a' && s <= 'z')
+ || (s >= 'A' && s <= 'Z')
+ || (s >= '0' && s <= '9')
+ || s == '_'
+ );
+}
+
+static inline bool is_space(char s)
+{
+ return (s == ' ' || s == '\t');
+}
+#endif
+
+// This code is shared with moc.cpp
+static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixScope = false, bool adjustConst = true)
+{
+ int len = e - t;
+ /*
+ Convert 'char const *' into 'const char *'. Start at index 1,
+ not 0, because 'const char *' is already OK.
+ */
+ QByteArray constbuf;
+ for (int i = 1; i < len; i++) {
+ if ( t[i] == 'c'
+ && strncmp(t + i + 1, "onst", 4) == 0
+ && (i + 5 >= len || !is_ident_char(t[i + 5]))
+ && !is_ident_char(t[i-1])
+ ) {
+ constbuf = QByteArray(t, len);
+ if (is_space(t[i-1]))
+ constbuf.remove(i-1, 6);
+ else
+ constbuf.remove(i, 5);
+ constbuf.prepend("const ");
+ t = constbuf.data();
+ e = constbuf.data() + constbuf.length();
+ break;
+ }
+ /*
+ We musn't convert 'char * const *' into 'const char **'
+ and we must beware of 'Bar<const Bla>'.
+ */
+ if (t[i] == '&' || t[i] == '*' ||t[i] == '<')
+ break;
+ }
+ if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) {
+ if (*(e-1) == '&') { // treat const reference as value
+ t += 6;
+ --e;
+ } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value
+ t += 6;
+ }
+ }
+ QByteArray result;
+ result.reserve(len);
+
+#if 1
+ // consume initial 'const '
+ if (strncmp("const ", t, 6) == 0) {
+ t+= 6;
+ result += "const ";
+ }
+#endif
+
+ // some type substitutions for 'unsigned x'
+ if (strncmp("unsigned", t, 8) == 0) {
+ // make sure "unsigned" is an isolated word before making substitutions
+ if (!t[8] || !is_ident_char(t[8])) {
+ if (strncmp(" int", t+8, 4) == 0) {
+ t += 8+4;
+ result += "uint";
+ } else if (strncmp(" long", t+8, 5) == 0) {
+ if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int'
+ && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long'
+ ) {
+ t += 8+5;
+ result += "ulong";
+ }
+ } else if (strncmp(" short", t+8, 6) != 0 // preserve unsigned short
+ && strncmp(" char", t+8, 5) != 0) { // preserve unsigned char
+ // treat rest (unsigned) as uint
+ t += 8;
+ result += "uint";
+ }
+ }
+ } else {
+ // discard 'struct', 'class', and 'enum'; they are optional
+ // and we don't want them in the normalized signature
+ struct {
+ const char *keyword;
+ int len;
+ } optional[] = {
+ { "struct ", 7 },
+ { "class ", 6 },
+ { "enum ", 5 },
+ { 0, 0 }
+ };
+ int i = 0;
+ do {
+ if (strncmp(optional[i].keyword, t, optional[i].len) == 0) {
+ t += optional[i].len;
+ break;
+ }
+ } while (optional[++i].keyword != 0);
+ }
+
+ bool star = false;
+ while (t != e) {
+ char c = *t++;
+ if (fixScope && c == ':' && *t == ':' ) {
+ ++t;
+ c = *t++;
+ int i = result.size() - 1;
+ while (i >= 0 && is_ident_char(result.at(i)))
+ --i;
+ result.resize(i + 1);
+ }
+ star = star || c == '*';
+ result += c;
+ if (c == '<') {
+ //template recursion
+ const char* tt = t;
+ int templdepth = 1;
+ while (t != e) {
+ c = *t++;
+ if (c == '<')
+ ++templdepth;
+ if (c == '>')
+ --templdepth;
+ if (templdepth == 0 || (templdepth == 1 && c == ',')) {
+ result += normalizeTypeInternal(tt, t-1, fixScope, false);
+ result += c;
+ if (templdepth == 0) {
+ if (*t == '>')
+ result += ' '; // avoid >>
+ break;
+ }
+ tt = t;
+ }
+ }
+ }
+
+ // cv qualifers can appear after the type as well
+ if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0)
+ && (e - t == 5 || !is_ident_char(t[5]))) {
+ t += 5;
+ while (t != e && is_space(*t))
+ ++t;
+ if (adjustConst && t != e && *t == '&') {
+ // treat const ref as value
+ ++t;
+ } else if (adjustConst && !star) {
+ // treat const as value
+ } else if (!star) {
+ // move const to the front (but not if const comes after a *)
+ result.prepend("const ");
+ } else {
+ // keep const after a *
+ result += "const";
+ }
+ }
+ }
+
+ return result;
+}
+
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
new file mode 100644
index 0000000000..bdc96c638b
--- /dev/null
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -0,0 +1,1509 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qmetatype.h"
+#include "qobjectdefs.h"
+#include "qdatetime.h"
+#include "qbytearray.h"
+#include "qreadwritelock.h"
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qvector.h"
+#include "qlocale.h"
+#include "qeasingcurve.h"
+
+#ifdef QT_BOOTSTRAPPED
+# ifndef QT_NO_GEOM_VARIANT
+# define QT_NO_GEOM_VARIANT
+# endif
+#else
+# include "qbitarray.h"
+# include "qurl.h"
+# include "qvariant.h"
+#endif
+
+#ifndef QT_NO_GEOM_VARIANT
+# include "qsize.h"
+# include "qpoint.h"
+# include "qrect.h"
+# include "qline.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define NS(x) QT_PREPEND_NAMESPACE(x)
+
+/*!
+ \macro Q_DECLARE_METATYPE(Type)
+ \relates QMetaType
+
+ This macro makes the type \a Type known to QMetaType as long as it
+ provides a public default constructor, a public copy constructor and
+ a public destructor.
+ It is needed to use the type \a Type as a custom type in QVariant.
+
+ Ideally, this macro should be placed below the declaration of
+ the class or struct. If that is not possible, it can be put in
+ a private header file which has to be included every time that
+ type is used in a QVariant.
+
+ Adding a Q_DECLARE_METATYPE() makes the type known to all template
+ based functions, including QVariant. Note that if you intend to
+ use the type in \e queued signal and slot connections or in
+ QObject's property system, you also have to call
+ qRegisterMetaType() since the names are resolved at runtime.
+
+ This example shows a typical use case of Q_DECLARE_METATYPE():
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 0
+
+ If \c MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro
+ has to be outside the namespace:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 1
+
+ Since \c{MyStruct} is now known to QMetaType, it can be used in QVariant:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 2
+
+ \sa qRegisterMetaType()
+*/
+
+/*!
+ \enum QMetaType::Type
+
+ These are the built-in types supported by QMetaType:
+
+ \value Void \c void
+ \value Bool \c bool
+ \value Int \c int
+ \value UInt \c{unsigned int}
+ \value Double \c double
+ \value QChar QChar
+ \value QString QString
+ \value QByteArray QByteArray
+
+ \value VoidStar \c{void *}
+ \value Long \c{long}
+ \value LongLong LongLong
+ \value Short \c{short}
+ \value Char \c{char}
+ \value ULong \c{unsigned long}
+ \value ULongLong ULongLong
+ \value UShort \c{unsigned short}
+ \value UChar \c{unsigned char}
+ \value Float \c float
+ \value QObjectStar QObject *
+ \value QWidgetStar QWidget *
+ \value QVariant QVariant
+
+ \value QColorGroup QColorGroup
+ \value QCursor QCursor
+ \value QDate QDate
+ \value QSize QSize
+ \value QTime QTime
+ \value QVariantList QVariantList
+ \value QPolygon QPolygon
+ \value QColor QColor
+ \value QSizeF QSizeF
+ \value QRectF QRectF
+ \value QLine QLine
+ \value QTextLength QTextLength
+ \value QStringList QStringList
+ \value QVariantMap QVariantMap
+ \value QVariantHash QVariantHash
+ \value QIcon QIcon
+ \value QPen QPen
+ \value QLineF QLineF
+ \value QTextFormat QTextFormat
+ \value QRect QRect
+ \value QPoint QPoint
+ \value QUrl QUrl
+ \value QRegExp QRegExp
+ \value QDateTime QDateTime
+ \value QPointF QPointF
+ \value QPalette QPalette
+ \value QFont QFont
+ \value QBrush QBrush
+ \value QRegion QRegion
+ \value QBitArray QBitArray
+ \value QImage QImage
+ \value QKeySequence QKeySequence
+ \value QSizePolicy QSizePolicy
+ \value QPixmap QPixmap
+ \value QLocale QLocale
+ \value QBitmap QBitmap
+ \value QMatrix QMatrix
+ \value QTransform QTransform
+ \value QMatrix4x4 QMatrix4x4
+ \value QVector2D QVector2D
+ \value QVector3D QVector3D
+ \value QVector4D QVector4D
+ \value QQuaternion QQuaternion
+ \value QEasingCurve QEasingCurve
+
+ \value User Base value for user types
+
+ \omitvalue FirstCoreExtType
+ \omitvalue FirstGuiType
+ \omitvalue LastCoreExtType
+ \omitvalue LastCoreType
+ \omitvalue LastGuiType
+ \omitvalue QReal
+
+ Additional types can be registered using Q_DECLARE_METATYPE().
+
+ \sa type(), typeName()
+*/
+
+/*!
+ \class QMetaType
+ \brief The QMetaType class manages named types in the meta-object system.
+
+ \ingroup objectmodel
+ \threadsafe
+
+ The class is used as a helper to marshall types in QVariant and
+ in queued signals and slots connections. It associates a type
+ name to a type so that it can be created and destructed
+ dynamically at run-time. Declare new types with Q_DECLARE_METATYPE()
+ to make them available to QVariant and other template-based functions.
+ Call qRegisterMetaType() to make type available to non-template based
+ functions, such as the queued signal and slot connections.
+
+ Any class or struct that has a public default
+ constructor, a public copy constructor, and a public destructor
+ can be registered.
+
+ The following code allocates and destructs an instance of
+ \c{MyClass}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 3
+
+ If we want the stream operators \c operator<<() and \c
+ operator>>() to work on QVariant objects that store custom types,
+ the custom type must provide \c operator<<() and \c operator>>()
+ operators.
+
+ \sa Q_DECLARE_METATYPE(), QVariant::setValue(), QVariant::value(), QVariant::fromValue()
+*/
+
+#define QT_ADD_STATIC_METATYPE(STR, TP) \
+ { STR, sizeof(STR) - 1, TP }
+
+/* Note: these MUST be in the order of the enums */
+static const struct { const char * typeName; int typeNameLength; int type; } types[] = {
+
+ /* All Core types */
+ QT_ADD_STATIC_METATYPE("void", QMetaType::Void),
+ QT_ADD_STATIC_METATYPE("bool", QMetaType::Bool),
+ QT_ADD_STATIC_METATYPE("int", QMetaType::Int),
+ QT_ADD_STATIC_METATYPE("uint", QMetaType::UInt),
+ QT_ADD_STATIC_METATYPE("qlonglong", QMetaType::LongLong),
+ QT_ADD_STATIC_METATYPE("qulonglong", QMetaType::ULongLong),
+ QT_ADD_STATIC_METATYPE("double", QMetaType::Double),
+ QT_ADD_STATIC_METATYPE("QChar", QMetaType::QChar),
+ QT_ADD_STATIC_METATYPE("QVariantMap", QMetaType::QVariantMap),
+ QT_ADD_STATIC_METATYPE("QVariantList", QMetaType::QVariantList),
+ QT_ADD_STATIC_METATYPE("QString", QMetaType::QString),
+ QT_ADD_STATIC_METATYPE("QStringList", QMetaType::QStringList),
+ QT_ADD_STATIC_METATYPE("QByteArray", QMetaType::QByteArray),
+ QT_ADD_STATIC_METATYPE("QBitArray", QMetaType::QBitArray),
+ QT_ADD_STATIC_METATYPE("QDate", QMetaType::QDate),
+ QT_ADD_STATIC_METATYPE("QTime", QMetaType::QTime),
+ QT_ADD_STATIC_METATYPE("QDateTime", QMetaType::QDateTime),
+ QT_ADD_STATIC_METATYPE("QUrl", QMetaType::QUrl),
+ QT_ADD_STATIC_METATYPE("QLocale", QMetaType::QLocale),
+ QT_ADD_STATIC_METATYPE("QRect", QMetaType::QRect),
+ QT_ADD_STATIC_METATYPE("QRectF", QMetaType::QRectF),
+ QT_ADD_STATIC_METATYPE("QSize", QMetaType::QSize),
+ QT_ADD_STATIC_METATYPE("QSizeF", QMetaType::QSizeF),
+ QT_ADD_STATIC_METATYPE("QLine", QMetaType::QLine),
+ QT_ADD_STATIC_METATYPE("QLineF", QMetaType::QLineF),
+ QT_ADD_STATIC_METATYPE("QPoint", QMetaType::QPoint),
+ QT_ADD_STATIC_METATYPE("QPointF", QMetaType::QPointF),
+ QT_ADD_STATIC_METATYPE("QRegExp", QMetaType::QRegExp),
+ QT_ADD_STATIC_METATYPE("QVariantHash", QMetaType::QVariantHash),
+ QT_ADD_STATIC_METATYPE("QEasingCurve", QMetaType::QEasingCurve),
+
+ /* All GUI types */
+ QT_ADD_STATIC_METATYPE("QColorGroup", 63),
+ QT_ADD_STATIC_METATYPE("QFont", QMetaType::QFont),
+ QT_ADD_STATIC_METATYPE("QPixmap", QMetaType::QPixmap),
+ QT_ADD_STATIC_METATYPE("QBrush", QMetaType::QBrush),
+ QT_ADD_STATIC_METATYPE("QColor", QMetaType::QColor),
+ QT_ADD_STATIC_METATYPE("QPalette", QMetaType::QPalette),
+ QT_ADD_STATIC_METATYPE("QIcon", QMetaType::QIcon),
+ QT_ADD_STATIC_METATYPE("QImage", QMetaType::QImage),
+ QT_ADD_STATIC_METATYPE("QPolygon", QMetaType::QPolygon),
+ QT_ADD_STATIC_METATYPE("QRegion", QMetaType::QRegion),
+ QT_ADD_STATIC_METATYPE("QBitmap", QMetaType::QBitmap),
+ QT_ADD_STATIC_METATYPE("QCursor", QMetaType::QCursor),
+ QT_ADD_STATIC_METATYPE("QSizePolicy", QMetaType::QSizePolicy),
+ QT_ADD_STATIC_METATYPE("QKeySequence", QMetaType::QKeySequence),
+ QT_ADD_STATIC_METATYPE("QPen", QMetaType::QPen),
+ QT_ADD_STATIC_METATYPE("QTextLength", QMetaType::QTextLength),
+ QT_ADD_STATIC_METATYPE("QTextFormat", QMetaType::QTextFormat),
+ QT_ADD_STATIC_METATYPE("QMatrix", QMetaType::QMatrix),
+ QT_ADD_STATIC_METATYPE("QTransform", QMetaType::QTransform),
+ QT_ADD_STATIC_METATYPE("QMatrix4x4", QMetaType::QMatrix4x4),
+ QT_ADD_STATIC_METATYPE("QVector2D", QMetaType::QVector2D),
+ QT_ADD_STATIC_METATYPE("QVector3D", QMetaType::QVector3D),
+ QT_ADD_STATIC_METATYPE("QVector4D", QMetaType::QVector4D),
+ QT_ADD_STATIC_METATYPE("QQuaternion", QMetaType::QQuaternion),
+
+ /* All Metatype builtins */
+ QT_ADD_STATIC_METATYPE("void*", QMetaType::VoidStar),
+ QT_ADD_STATIC_METATYPE("long", QMetaType::Long),
+ QT_ADD_STATIC_METATYPE("short", QMetaType::Short),
+ QT_ADD_STATIC_METATYPE("char", QMetaType::Char),
+ QT_ADD_STATIC_METATYPE("ulong", QMetaType::ULong),
+ QT_ADD_STATIC_METATYPE("ushort", QMetaType::UShort),
+ QT_ADD_STATIC_METATYPE("uchar", QMetaType::UChar),
+ QT_ADD_STATIC_METATYPE("float", QMetaType::Float),
+ QT_ADD_STATIC_METATYPE("QObject*", QMetaType::QObjectStar),
+ QT_ADD_STATIC_METATYPE("QWidget*", QMetaType::QWidgetStar),
+ QT_ADD_STATIC_METATYPE("QVariant", QMetaType::QVariant),
+
+ /* Type aliases - order doesn't matter */
+ QT_ADD_STATIC_METATYPE("unsigned long", QMetaType::ULong),
+ QT_ADD_STATIC_METATYPE("unsigned int", QMetaType::UInt),
+ QT_ADD_STATIC_METATYPE("unsigned short", QMetaType::UShort),
+ QT_ADD_STATIC_METATYPE("unsigned char", QMetaType::UChar),
+ QT_ADD_STATIC_METATYPE("long long", QMetaType::LongLong),
+ QT_ADD_STATIC_METATYPE("unsigned long long", QMetaType::ULongLong),
+ QT_ADD_STATIC_METATYPE("qint8", QMetaType::Char),
+ QT_ADD_STATIC_METATYPE("signed char", QMetaType::Char),
+ QT_ADD_STATIC_METATYPE("quint8", QMetaType::UChar),
+ QT_ADD_STATIC_METATYPE("qint16", QMetaType::Short),
+ QT_ADD_STATIC_METATYPE("quint16", QMetaType::UShort),
+ QT_ADD_STATIC_METATYPE("qint32", QMetaType::Int),
+ QT_ADD_STATIC_METATYPE("quint32", QMetaType::UInt),
+ QT_ADD_STATIC_METATYPE("qint64", QMetaType::LongLong),
+ QT_ADD_STATIC_METATYPE("quint64", QMetaType::ULongLong),
+ QT_ADD_STATIC_METATYPE("QList<QVariant>", QMetaType::QVariantList),
+ QT_ADD_STATIC_METATYPE("QMap<QString,QVariant>", QMetaType::QVariantMap),
+ QT_ADD_STATIC_METATYPE("QHash<QString,QVariant>", QMetaType::QVariantHash),
+ // let QMetaTypeId2 figure out the type at compile time
+ QT_ADD_STATIC_METATYPE("qreal", QMetaTypeId2<qreal>::MetaType),
+
+ {0, 0, QMetaType::Void}
+};
+
+struct QMetaTypeGuiHelper
+{
+ QMetaType::Constructor constr;
+ QMetaType::Destructor destr;
+#ifndef QT_NO_DATASTREAM
+ QMetaType::SaveOperator saveOp;
+ QMetaType::LoadOperator loadOp;
+#endif
+};
+Q_CORE_EXPORT const QMetaTypeGuiHelper *qMetaTypeGuiHelper = 0;
+
+class QCustomTypeInfo
+{
+public:
+ QCustomTypeInfo() : typeName(), constr(0), destr(0)
+#ifndef QT_NO_DATASTREAM
+ , saveOp(0), loadOp(0)
+#endif
+ {}
+
+ QByteArray typeName;
+ QMetaType::Constructor constr;
+ QMetaType::Destructor destr;
+#ifndef QT_NO_DATASTREAM
+ QMetaType::SaveOperator saveOp;
+ QMetaType::LoadOperator loadOp;
+#endif
+ int alias;
+};
+
+Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
+Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
+Q_GLOBAL_STATIC(QReadWriteLock, customTypesLock)
+
+#ifndef QT_NO_DATASTREAM
+/*! \internal
+*/
+void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveOp,
+ LoadOperator loadOp)
+{
+ int idx = type(typeName);
+ if (!idx)
+ return;
+ registerStreamOperators(idx, saveOp, loadOp);
+}
+
+/*! \internal
+*/
+void QMetaType::registerStreamOperators(int idx, SaveOperator saveOp,
+ LoadOperator loadOp)
+{
+ if (idx < User)
+ return; //builtin types should not be registered;
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct)
+ return;
+ QWriteLocker locker(customTypesLock());
+ QCustomTypeInfo &inf = (*ct)[idx - User];
+ inf.saveOp = saveOp;
+ inf.loadOp = loadOp;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ Returns the type name associated with the given \a type, or 0 if no
+ matching type was found. The returned pointer must not be deleted.
+
+ \sa type(), isRegistered(), Type
+*/
+const char *QMetaType::typeName(int type)
+{
+ enum { GuiTypeCount = LastGuiType - FirstGuiType };
+
+ if (type >= 0 && type <= LastCoreType) {
+ return types[type].typeName;
+ } else if (type >= FirstGuiType && type <= LastGuiType) {
+ return types[type - FirstGuiType + LastCoreType + 1].typeName;
+ } else if (type >= FirstCoreExtType && type <= LastCoreExtType) {
+ return types[type - FirstCoreExtType + GuiTypeCount + LastCoreType + 2].typeName;
+ } else if (type >= User) {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ QReadLocker locker(customTypesLock());
+ return ct && ct->count() > type - User && !ct->at(type - User).typeName.isEmpty()
+ ? ct->at(type - User).typeName.constData()
+ : static_cast<const char *>(0);
+ }
+
+ return 0;
+}
+
+/*! \internal
+ Similar to QMetaType::type(), but only looks in the static set of types.
+*/
+static inline int qMetaTypeStaticType(const char *typeName, int length)
+{
+ int i = 0;
+ while (types[i].typeName && ((length != types[i].typeNameLength)
+ || strcmp(typeName, types[i].typeName))) {
+ ++i;
+ }
+ return types[i].type;
+}
+
+/*! \internal
+ Similar to QMetaType::type(), but only looks in the custom set of
+ types, and doesn't lock the mutex.
+*/
+static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
+{
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return 0;
+
+ for (int v = 0; v < ct->count(); ++v) {
+ const QCustomTypeInfo &customInfo = ct->at(v);
+ if ((length == customInfo.typeName.size())
+ && !strcmp(typeName, customInfo.typeName.constData())) {
+ if (customInfo.alias >= 0)
+ return customInfo.alias;
+ return v + QMetaType::User;
+ }
+ }
+ return 0;
+}
+
+/*! \internal
+
+ Registers a user type for marshalling, with \a typeName, a \a
+ destructor, and a \a constructor. Returns the type's handle,
+ or -1 if the type could not be registered.
+ */
+int QMetaType::registerType(const char *typeName, Destructor destructor,
+ Constructor constructor)
+{
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct || !typeName || !destructor || !constructor)
+ return -1;
+
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+
+ int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+
+ if (!idx) {
+ QWriteLocker locker(customTypesLock());
+ idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+ if (!idx) {
+ QCustomTypeInfo inf;
+ inf.typeName = normalizedTypeName;
+ inf.constr = constructor;
+ inf.destr = destructor;
+ inf.alias = -1;
+ idx = ct->size() + User;
+ ct->append(inf);
+ }
+ }
+ return idx;
+}
+
+/*! \internal
+ \since 4.7
+
+ Registers a user type for marshalling, as an alias of another type (typedef)
+*/
+int QMetaType::registerTypedef(const char* typeName, int aliasId)
+{
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct || !typeName)
+ return -1;
+
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+
+ int idx = qMetaTypeStaticType(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+
+ if (idx) {
+ Q_ASSERT(idx == aliasId);
+ return idx;
+ }
+
+ QWriteLocker locker(customTypesLock());
+ idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+
+ if (idx)
+ return idx;
+
+ QCustomTypeInfo inf;
+ inf.typeName = normalizedTypeName;
+ inf.alias = aliasId;
+ inf.constr = 0;
+ inf.destr = 0;
+ ct->append(inf);
+ return aliasId;
+}
+
+/*!
+ \since 4.4
+
+ Unregisters a user type, with \a typeName.
+
+ \sa type(), typeName()
+ */
+void QMetaType::unregisterType(const char *typeName)
+{
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct || !typeName)
+ return;
+
+#ifdef QT_NO_QOBJECT
+ NS(QByteArray) normalizedTypeName = typeName;
+#else
+ NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+ QWriteLocker locker(customTypesLock());
+ for (int v = 0; v < ct->count(); ++v) {
+ if (ct->at(v).typeName == typeName) {
+ QCustomTypeInfo &inf = (*ct)[v];
+ inf.typeName.clear();
+ inf.constr = 0;
+ inf.destr = 0;
+ inf.alias = -1;
+ }
+ }
+}
+
+/*!
+ Returns true if the datatype with ID \a type is registered;
+ otherwise returns false.
+
+ \sa type(), typeName(), Type
+*/
+bool QMetaType::isRegistered(int type)
+{
+ if (type >= 0 && type < User) {
+ // predefined type
+ return true;
+ }
+ QReadLocker locker(customTypesLock());
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ return ((type >= User) && (ct && ct->count() > type - User) && !ct->at(type - User).typeName.isEmpty());
+}
+
+/*!
+ Returns a handle to the type called \a typeName, or 0 if there is
+ no such type.
+
+ \sa isRegistered(), typeName(), Type
+*/
+int QMetaType::type(const char *typeName)
+{
+ int length = qstrlen(typeName);
+ if (!length)
+ return 0;
+ int type = qMetaTypeStaticType(typeName, length);
+ if (!type) {
+ QReadLocker locker(customTypesLock());
+ type = qMetaTypeCustomType_unlocked(typeName, length);
+#ifndef QT_NO_QOBJECT
+ if (!type) {
+ const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+ type = qMetaTypeStaticType(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+ if (!type) {
+ type = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
+ normalizedTypeName.size());
+ }
+ }
+#endif
+ }
+ return type;
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ Writes the object pointed to by \a data with the ID \a type to
+ the given \a stream. Returns true if the object is saved
+ successfully; otherwise returns false.
+
+ The type must have been registered with qRegisterMetaType() and
+ qRegisterMetaTypeStreamOperators() beforehand.
+
+ Normally, you should not need to call this function directly.
+ Instead, use QVariant's \c operator<<(), which relies on save()
+ to stream custom types.
+
+ \sa load(), qRegisterMetaTypeStreamOperators()
+*/
+bool QMetaType::save(QDataStream &stream, int type, const void *data)
+{
+ if (!data || !isRegistered(type))
+ return false;
+
+ switch(type) {
+ case QMetaType::Void:
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return false;
+ case QMetaType::Long:
+ stream << qlonglong(*static_cast<const long *>(data));
+ break;
+ case QMetaType::Int:
+ stream << *static_cast<const int *>(data);
+ break;
+ case QMetaType::Short:
+ stream << *static_cast<const short *>(data);
+ break;
+ case QMetaType::Char:
+ // force a char to be signed
+ stream << *static_cast<const signed char *>(data);
+ break;
+ case QMetaType::ULong:
+ stream << qulonglong(*static_cast<const ulong *>(data));
+ break;
+ case QMetaType::UInt:
+ stream << *static_cast<const uint *>(data);
+ break;
+ case QMetaType::LongLong:
+ stream << *static_cast<const qlonglong *>(data);
+ break;
+ case QMetaType::ULongLong:
+ stream << *static_cast<const qulonglong *>(data);
+ break;
+ case QMetaType::UShort:
+ stream << *static_cast<const ushort *>(data);
+ break;
+ case QMetaType::UChar:
+ stream << *static_cast<const uchar *>(data);
+ break;
+ case QMetaType::Bool:
+ stream << qint8(*static_cast<const bool *>(data));
+ break;
+ case QMetaType::Float:
+ stream << *static_cast<const float *>(data);
+ break;
+ case QMetaType::Double:
+ stream << *static_cast<const double *>(data);
+ break;
+ case QMetaType::QChar:
+ stream << *static_cast<const NS(QChar) *>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ stream << *static_cast<const NS(QVariantMap)*>(data);
+ break;
+ case QMetaType::QVariantHash:
+ stream << *static_cast<const NS(QVariantHash)*>(data);
+ break;
+ case QMetaType::QVariantList:
+ stream << *static_cast<const NS(QVariantList)*>(data);
+ break;
+ case QMetaType::QVariant:
+ stream << *static_cast<const NS(QVariant)*>(data);
+ break;
+#endif
+ case QMetaType::QByteArray:
+ stream << *static_cast<const NS(QByteArray)*>(data);
+ break;
+ case QMetaType::QString:
+ stream << *static_cast<const NS(QString)*>(data);
+ break;
+ case QMetaType::QStringList:
+ stream << *static_cast<const NS(QStringList)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ stream << *static_cast<const NS(QBitArray)*>(data);
+ break;
+#endif
+ case QMetaType::QDate:
+ stream << *static_cast<const NS(QDate)*>(data);
+ break;
+ case QMetaType::QTime:
+ stream << *static_cast<const NS(QTime)*>(data);
+ break;
+ case QMetaType::QDateTime:
+ stream << *static_cast<const NS(QDateTime)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ stream << *static_cast<const NS(QUrl)*>(data);
+ break;
+#endif
+ case QMetaType::QLocale:
+ stream << *static_cast<const NS(QLocale)*>(data);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ stream << *static_cast<const NS(QRect)*>(data);
+ break;
+ case QMetaType::QRectF:
+ stream << *static_cast<const NS(QRectF)*>(data);
+ break;
+ case QMetaType::QSize:
+ stream << *static_cast<const NS(QSize)*>(data);
+ break;
+ case QMetaType::QSizeF:
+ stream << *static_cast<const NS(QSizeF)*>(data);
+ break;
+ case QMetaType::QLine:
+ stream << *static_cast<const NS(QLine)*>(data);
+ break;
+ case QMetaType::QLineF:
+ stream << *static_cast<const NS(QLineF)*>(data);
+ break;
+ case QMetaType::QPoint:
+ stream << *static_cast<const NS(QPoint)*>(data);
+ break;
+ case QMetaType::QPointF:
+ stream << *static_cast<const NS(QPointF)*>(data);
+ break;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ stream << *static_cast<const NS(QRegExp)*>(data);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ stream << *static_cast<const NS(QEasingCurve)*>(data);
+ break;
+#endif
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+#endif
+ case QMetaType::QFont:
+ case QMetaType::QPixmap:
+ case QMetaType::QBrush:
+ case QMetaType::QColor:
+ case QMetaType::QPalette:
+ case QMetaType::QIcon:
+ case QMetaType::QImage:
+ case QMetaType::QPolygon:
+ case QMetaType::QRegion:
+ case QMetaType::QBitmap:
+ case QMetaType::QCursor:
+ case QMetaType::QSizePolicy:
+ case QMetaType::QKeySequence:
+ case QMetaType::QPen:
+ case QMetaType::QTextLength:
+ case QMetaType::QTextFormat:
+ case QMetaType::QMatrix:
+ case QMetaType::QTransform:
+ case QMetaType::QMatrix4x4:
+ case QMetaType::QVector2D:
+ case QMetaType::QVector3D:
+ case QMetaType::QVector4D:
+ case QMetaType::QQuaternion:
+ if (!qMetaTypeGuiHelper)
+ return false;
+ qMetaTypeGuiHelper[type - FirstGuiType].saveOp(stream, data);
+ break;
+ default: {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return false;
+
+ SaveOperator saveOp = 0;
+ {
+ QReadLocker locker(customTypesLock());
+ saveOp = ct->at(type - User).saveOp;
+ }
+
+ if (!saveOp)
+ return false;
+ saveOp(stream, data);
+ break; }
+ }
+
+ return true;
+}
+
+/*!
+ Reads the object of the specified \a type from the given \a
+ stream into \a data. Returns true if the object is loaded
+ successfully; otherwise returns false.
+
+ The type must have been registered with qRegisterMetaType() and
+ qRegisterMetaTypeStreamOperators() beforehand.
+
+ Normally, you should not need to call this function directly.
+ Instead, use QVariant's \c operator>>(), which relies on load()
+ to stream custom types.
+
+ \sa save(), qRegisterMetaTypeStreamOperators()
+*/
+bool QMetaType::load(QDataStream &stream, int type, void *data)
+{
+ if (!data || !isRegistered(type))
+ return false;
+
+ switch(type) {
+ case QMetaType::Void:
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return false;
+ case QMetaType::Long: {
+ qlonglong l;
+ stream >> l;
+ *static_cast<long *>(data) = long(l);
+ break; }
+ case QMetaType::Int:
+ stream >> *static_cast<int *>(data);
+ break;
+ case QMetaType::Short:
+ stream >> *static_cast<short *>(data);
+ break;
+ case QMetaType::Char:
+ // force a char to be signed
+ stream >> *static_cast<signed char *>(data);
+ break;
+ case QMetaType::ULong: {
+ qulonglong ul;
+ stream >> ul;
+ *static_cast<ulong *>(data) = ulong(ul);
+ break; }
+ case QMetaType::UInt:
+ stream >> *static_cast<uint *>(data);
+ break;
+ case QMetaType::LongLong:
+ stream >> *static_cast<qlonglong *>(data);
+ break;
+ case QMetaType::ULongLong:
+ stream >> *static_cast<qulonglong *>(data);
+ break;
+ case QMetaType::UShort:
+ stream >> *static_cast<ushort *>(data);
+ break;
+ case QMetaType::UChar:
+ stream >> *static_cast<uchar *>(data);
+ break;
+ case QMetaType::Bool: {
+ qint8 b;
+ stream >> b;
+ *static_cast<bool *>(data) = b;
+ break; }
+ case QMetaType::Float:
+ stream >> *static_cast<float *>(data);
+ break;
+ case QMetaType::Double:
+ stream >> *static_cast<double *>(data);
+ break;
+ case QMetaType::QChar:
+ stream >> *static_cast< NS(QChar)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ stream >> *static_cast< NS(QVariantMap)*>(data);
+ break;
+ case QMetaType::QVariantHash:
+ stream >> *static_cast< NS(QVariantHash)*>(data);
+ break;
+ case QMetaType::QVariantList:
+ stream >> *static_cast< NS(QVariantList)*>(data);
+ break;
+ case QMetaType::QVariant:
+ stream >> *static_cast< NS(QVariant)*>(data);
+ break;
+#endif
+ case QMetaType::QByteArray:
+ stream >> *static_cast< NS(QByteArray)*>(data);
+ break;
+ case QMetaType::QString:
+ stream >> *static_cast< NS(QString)*>(data);
+ break;
+ case QMetaType::QStringList:
+ stream >> *static_cast< NS(QStringList)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ stream >> *static_cast< NS(QBitArray)*>(data);
+ break;
+#endif
+ case QMetaType::QDate:
+ stream >> *static_cast< NS(QDate)*>(data);
+ break;
+ case QMetaType::QTime:
+ stream >> *static_cast< NS(QTime)*>(data);
+ break;
+ case QMetaType::QDateTime:
+ stream >> *static_cast< NS(QDateTime)*>(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ stream >> *static_cast< NS(QUrl)*>(data);
+ break;
+#endif
+ case QMetaType::QLocale:
+ stream >> *static_cast< NS(QLocale)*>(data);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ stream >> *static_cast< NS(QRect)*>(data);
+ break;
+ case QMetaType::QRectF:
+ stream >> *static_cast< NS(QRectF)*>(data);
+ break;
+ case QMetaType::QSize:
+ stream >> *static_cast< NS(QSize)*>(data);
+ break;
+ case QMetaType::QSizeF:
+ stream >> *static_cast< NS(QSizeF)*>(data);
+ break;
+ case QMetaType::QLine:
+ stream >> *static_cast< NS(QLine)*>(data);
+ break;
+ case QMetaType::QLineF:
+ stream >> *static_cast< NS(QLineF)*>(data);
+ break;
+ case QMetaType::QPoint:
+ stream >> *static_cast< NS(QPoint)*>(data);
+ break;
+ case QMetaType::QPointF:
+ stream >> *static_cast< NS(QPointF)*>(data);
+ break;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ stream >> *static_cast< NS(QRegExp)*>(data);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ stream >> *static_cast< NS(QEasingCurve)*>(data);
+ break;
+#endif
+#ifdef QT3_SUPPORT
+ case QMetaType::QColorGroup:
+#endif
+ case QMetaType::QFont:
+ case QMetaType::QPixmap:
+ case QMetaType::QBrush:
+ case QMetaType::QColor:
+ case QMetaType::QPalette:
+ case QMetaType::QIcon:
+ case QMetaType::QImage:
+ case QMetaType::QPolygon:
+ case QMetaType::QRegion:
+ case QMetaType::QBitmap:
+ case QMetaType::QCursor:
+ case QMetaType::QSizePolicy:
+ case QMetaType::QKeySequence:
+ case QMetaType::QPen:
+ case QMetaType::QTextLength:
+ case QMetaType::QTextFormat:
+ case QMetaType::QMatrix:
+ case QMetaType::QTransform:
+ case QMetaType::QMatrix4x4:
+ case QMetaType::QVector2D:
+ case QMetaType::QVector3D:
+ case QMetaType::QVector4D:
+ case QMetaType::QQuaternion:
+ if (!qMetaTypeGuiHelper)
+ return false;
+ qMetaTypeGuiHelper[type - FirstGuiType].loadOp(stream, data);
+ break;
+ default: {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return false;
+
+ LoadOperator loadOp = 0;
+ {
+ QReadLocker locker(customTypesLock());
+ loadOp = ct->at(type - User).loadOp;
+ }
+
+ if (!loadOp)
+ return false;
+ loadOp(stream, data);
+ break; }
+ }
+ return true;
+}
+#endif // QT_NO_DATASTREAM
+
+/*!
+ Returns a copy of \a copy, assuming it is of type \a type. If \a
+ copy is zero, creates a default type.
+
+ \sa destroy(), isRegistered(), Type
+*/
+void *QMetaType::construct(int type, const void *copy)
+{
+ if (copy) {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return new void *(*static_cast<void* const *>(copy));
+ case QMetaType::Long:
+ return new long(*static_cast<const long*>(copy));
+ case QMetaType::Int:
+ return new int(*static_cast<const int*>(copy));
+ case QMetaType::Short:
+ return new short(*static_cast<const short*>(copy));
+ case QMetaType::Char:
+ return new char(*static_cast<const char*>(copy));
+ case QMetaType::ULong:
+ return new ulong(*static_cast<const ulong*>(copy));
+ case QMetaType::UInt:
+ return new uint(*static_cast<const uint*>(copy));
+ case QMetaType::LongLong:
+ return new qlonglong(*static_cast<const qlonglong*>(copy));
+ case QMetaType::ULongLong:
+ return new qulonglong(*static_cast<const qulonglong*>(copy));
+ case QMetaType::UShort:
+ return new ushort(*static_cast<const ushort*>(copy));
+ case QMetaType::UChar:
+ return new uchar(*static_cast<const uchar*>(copy));
+ case QMetaType::Bool:
+ return new bool(*static_cast<const bool*>(copy));
+ case QMetaType::Float:
+ return new float(*static_cast<const float*>(copy));
+ case QMetaType::Double:
+ return new double(*static_cast<const double*>(copy));
+ case QMetaType::QChar:
+ return new NS(QChar)(*static_cast<const NS(QChar)*>(copy));
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ return new NS(QVariantMap)(*static_cast<const NS(QVariantMap)*>(copy));
+ case QMetaType::QVariantHash:
+ return new NS(QVariantHash)(*static_cast<const NS(QVariantHash)*>(copy));
+ case QMetaType::QVariantList:
+ return new NS(QVariantList)(*static_cast<const NS(QVariantList)*>(copy));
+ case QMetaType::QVariant:
+ return new NS(QVariant)(*static_cast<const NS(QVariant)*>(copy));
+#endif
+ case QMetaType::QByteArray:
+ return new NS(QByteArray)(*static_cast<const NS(QByteArray)*>(copy));
+ case QMetaType::QString:
+ return new NS(QString)(*static_cast<const NS(QString)*>(copy));
+ case QMetaType::QStringList:
+ return new NS(QStringList)(*static_cast<const NS(QStringList)*>(copy));
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ return new NS(QBitArray)(*static_cast<const NS(QBitArray)*>(copy));
+#endif
+ case QMetaType::QDate:
+ return new NS(QDate)(*static_cast<const NS(QDate)*>(copy));
+ case QMetaType::QTime:
+ return new NS(QTime)(*static_cast<const NS(QTime)*>(copy));
+ case QMetaType::QDateTime:
+ return new NS(QDateTime)(*static_cast<const NS(QDateTime)*>(copy));
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ return new NS(QUrl)(*static_cast<const NS(QUrl)*>(copy));
+#endif
+ case QMetaType::QLocale:
+ return new NS(QLocale)(*static_cast<const NS(QLocale)*>(copy));
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ return new NS(QRect)(*static_cast<const NS(QRect)*>(copy));
+ case QMetaType::QRectF:
+ return new NS(QRectF)(*static_cast<const NS(QRectF)*>(copy));
+ case QMetaType::QSize:
+ return new NS(QSize)(*static_cast<const NS(QSize)*>(copy));
+ case QMetaType::QSizeF:
+ return new NS(QSizeF)(*static_cast<const NS(QSizeF)*>(copy));
+ case QMetaType::QLine:
+ return new NS(QLine)(*static_cast<const NS(QLine)*>(copy));
+ case QMetaType::QLineF:
+ return new NS(QLineF)(*static_cast<const NS(QLineF)*>(copy));
+ case QMetaType::QPoint:
+ return new NS(QPoint)(*static_cast<const NS(QPoint)*>(copy));
+ case QMetaType::QPointF:
+ return new NS(QPointF)(*static_cast<const NS(QPointF)*>(copy));
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ return new NS(QRegExp)(*static_cast<const NS(QRegExp)*>(copy));
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ return new NS(QEasingCurve)(*static_cast<const NS(QEasingCurve)*>(copy));
+#endif
+ case QMetaType::Void:
+ return 0;
+ default:
+ ;
+ }
+ } else {
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return new void *;
+ case QMetaType::Long:
+ return new long;
+ case QMetaType::Int:
+ return new int;
+ case QMetaType::Short:
+ return new short;
+ case QMetaType::Char:
+ return new char;
+ case QMetaType::ULong:
+ return new ulong;
+ case QMetaType::UInt:
+ return new uint;
+ case QMetaType::LongLong:
+ return new qlonglong;
+ case QMetaType::ULongLong:
+ return new qulonglong;
+ case QMetaType::UShort:
+ return new ushort;
+ case QMetaType::UChar:
+ return new uchar;
+ case QMetaType::Bool:
+ return new bool;
+ case QMetaType::Float:
+ return new float;
+ case QMetaType::Double:
+ return new double;
+ case QMetaType::QChar:
+ return new NS(QChar);
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ return new NS(QVariantMap);
+ case QMetaType::QVariantHash:
+ return new NS(QVariantHash);
+ case QMetaType::QVariantList:
+ return new NS(QVariantList);
+ case QMetaType::QVariant:
+ return new NS(QVariant);
+#endif
+ case QMetaType::QByteArray:
+ return new NS(QByteArray);
+ case QMetaType::QString:
+ return new NS(QString);
+ case QMetaType::QStringList:
+ return new NS(QStringList);
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ return new NS(QBitArray);
+#endif
+ case QMetaType::QDate:
+ return new NS(QDate);
+ case QMetaType::QTime:
+ return new NS(QTime);
+ case QMetaType::QDateTime:
+ return new NS(QDateTime);
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ return new NS(QUrl);
+#endif
+ case QMetaType::QLocale:
+ return new NS(QLocale);
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ return new NS(QRect);
+ case QMetaType::QRectF:
+ return new NS(QRectF);
+ case QMetaType::QSize:
+ return new NS(QSize);
+ case QMetaType::QSizeF:
+ return new NS(QSizeF);
+ case QMetaType::QLine:
+ return new NS(QLine);
+ case QMetaType::QLineF:
+ return new NS(QLineF);
+ case QMetaType::QPoint:
+ return new NS(QPoint);
+ case QMetaType::QPointF:
+ return new NS(QPointF);
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ return new NS(QRegExp);
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ return new NS(QEasingCurve);
+#endif
+ case QMetaType::Void:
+ return 0;
+ default:
+ ;
+ }
+ }
+
+ Constructor constr = 0;
+ if (type >= FirstGuiType && type <= LastGuiType) {
+ if (!qMetaTypeGuiHelper)
+ return 0;
+ constr = qMetaTypeGuiHelper[type - FirstGuiType].constr;
+ } else {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ QReadLocker locker(customTypesLock());
+ if (type < User || !ct || ct->count() <= type - User)
+ return 0;
+ if (ct->at(type - User).typeName.isEmpty())
+ return 0;
+ constr = ct->at(type - User).constr;
+ }
+
+ return constr(copy);
+}
+
+/*!
+ Destroys the \a data, assuming it is of the \a type given.
+
+ \sa construct(), isRegistered(), Type
+*/
+void QMetaType::destroy(int type, void *data)
+{
+ if (!data)
+ return;
+ switch(type) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ delete static_cast<void**>(data);
+ break;
+ case QMetaType::Long:
+ delete static_cast<long*>(data);
+ break;
+ case QMetaType::Int:
+ delete static_cast<int*>(data);
+ break;
+ case QMetaType::Short:
+ delete static_cast<short*>(data);
+ break;
+ case QMetaType::Char:
+ delete static_cast<char*>(data);
+ break;
+ case QMetaType::ULong:
+ delete static_cast<ulong*>(data);
+ break;
+ case QMetaType::LongLong:
+ delete static_cast<qlonglong*>(data);
+ break;
+ case QMetaType::ULongLong:
+ delete static_cast<qulonglong*>(data);
+ break;
+ case QMetaType::UInt:
+ delete static_cast<uint*>(data);
+ break;
+ case QMetaType::UShort:
+ delete static_cast<ushort*>(data);
+ break;
+ case QMetaType::UChar:
+ delete static_cast<uchar*>(data);
+ break;
+ case QMetaType::Bool:
+ delete static_cast<bool*>(data);
+ break;
+ case QMetaType::Float:
+ delete static_cast<float*>(data);
+ break;
+ case QMetaType::Double:
+ delete static_cast<double*>(data);
+ break;
+ case QMetaType::QChar:
+ delete static_cast< NS(QChar)* >(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QVariantMap:
+ delete static_cast< NS(QVariantMap)* >(data);
+ break;
+ case QMetaType::QVariantHash:
+ delete static_cast< NS(QVariantHash)* >(data);
+ break;
+ case QMetaType::QVariantList:
+ delete static_cast< NS(QVariantList)* >(data);
+ break;
+ case QMetaType::QVariant:
+ delete static_cast< NS(QVariant)* >(data);
+ break;
+#endif
+ case QMetaType::QByteArray:
+ delete static_cast< NS(QByteArray)* >(data);
+ break;
+ case QMetaType::QString:
+ delete static_cast< NS(QString)* >(data);
+ break;
+ case QMetaType::QStringList:
+ delete static_cast< NS(QStringList)* >(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QBitArray:
+ delete static_cast< NS(QBitArray)* >(data);
+ break;
+#endif
+ case QMetaType::QDate:
+ delete static_cast< NS(QDate)* >(data);
+ break;
+ case QMetaType::QTime:
+ delete static_cast< NS(QTime)* >(data);
+ break;
+ case QMetaType::QDateTime:
+ delete static_cast< NS(QDateTime)* >(data);
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QUrl:
+ delete static_cast< NS(QUrl)* >(data);
+#endif
+ break;
+ case QMetaType::QLocale:
+ delete static_cast< NS(QLocale)* >(data);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QMetaType::QRect:
+ delete static_cast< NS(QRect)* >(data);
+ break;
+ case QMetaType::QRectF:
+ delete static_cast< NS(QRectF)* >(data);
+ break;
+ case QMetaType::QSize:
+ delete static_cast< NS(QSize)* >(data);
+ break;
+ case QMetaType::QSizeF:
+ delete static_cast< NS(QSizeF)* >(data);
+ break;
+ case QMetaType::QLine:
+ delete static_cast< NS(QLine)* >(data);
+ break;
+ case QMetaType::QLineF:
+ delete static_cast< NS(QLineF)* >(data);
+ break;
+ case QMetaType::QPoint:
+ delete static_cast< NS(QPoint)* >(data);
+ break;
+ case QMetaType::QPointF:
+ delete static_cast< NS(QPointF)* >(data);
+ break;
+#endif
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ delete static_cast< NS(QRegExp)* >(data);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QEasingCurve:
+ delete static_cast< NS(QEasingCurve)* >(data);
+ break;
+#endif
+ case QMetaType::Void:
+ break;
+ default: {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ Destructor destr = 0;
+ if (type >= FirstGuiType && type <= LastGuiType) {
+ Q_ASSERT(qMetaTypeGuiHelper);
+
+ if (!qMetaTypeGuiHelper)
+ return;
+ destr = qMetaTypeGuiHelper[type - FirstGuiType].destr;
+ } else {
+ QReadLocker locker(customTypesLock());
+ if (type < User || !ct || ct->count() <= type - User)
+ break;
+ if (ct->at(type - User).typeName.isEmpty())
+ break;
+ destr = ct->at(type - User).destr;
+ }
+ destr(data);
+ break; }
+ }
+}
+
+/*!
+ \fn int qRegisterMetaType(const char *typeName)
+ \relates QMetaType
+ \threadsafe
+
+ 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.
+
+ After a type has been registered, you can create and destroy
+ objects of that type dynamically at run-time.
+
+ This example registers the class \c{MyClass}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 4
+
+ This function is useful to register typedefs so they can be used
+ by QMetaProperty, or in QueuedConnections
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 9
+
+ \sa qRegisterMetaTypeStreamOperators(), QMetaType::isRegistered(),
+ Q_DECLARE_METATYPE()
+*/
+
+/*!
+ \fn int qRegisterMetaTypeStreamOperators(const char *typeName)
+ \relates QMetaType
+ \threadsafe
+
+ Registers the stream operators for the type \c{T} called \a
+ typeName.
+
+ Afterward, the type can be streamed using QMetaType::load() and
+ QMetaType::save(). These functions are used when streaming a
+ QVariant.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 5
+
+ The stream operators should have the following signatures:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 6
+
+ \sa qRegisterMetaType(), QMetaType::isRegistered(), Q_DECLARE_METATYPE()
+*/
+
+/*! \typedef QMetaType::Destructor
+ \internal
+*/
+/*! \typedef QMetaType::Constructor
+ \internal
+*/
+/*! \typedef QMetaType::SaveOperator
+ \internal
+*/
+/*! \typedef QMetaType::LoadOperator
+ \internal
+*/
+
+/*!
+ \fn int qRegisterMetaType()
+ \relates QMetaType
+ \threadsafe
+ \since 4.2
+
+ Call this function to register the type \c T. \c T must be declared with
+ Q_DECLARE_METATYPE(). Returns the meta type Id.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 7
+
+ To use the type \c T in QVariant, using Q_DECLARE_METATYPE() is
+ sufficient. To use the type \c T in queued signal and slot connections,
+ \c{qRegisterMetaType<T>()} must be called before the first connection
+ is established.
+
+ Also, to use type \c T with the QObject::property() API,
+ \c{qRegisterMetaType<T>()} must be called before it is used, typically
+ in the constructor of the class that uses \c T, or in the \c{main()}
+ function.
+
+ \sa Q_DECLARE_METATYPE()
+ */
+
+/*! \fn int qMetaTypeId()
+ \relates QMetaType
+ \threadsafe
+ \since 4.1
+
+ Returns the meta type id of type \c T at compile time. If the
+ type was not declared with Q_DECLARE_METATYPE(), compilation will
+ fail.
+
+ Typical usage:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmetatype.cpp 8
+
+ QMetaType::type() returns the same ID as qMetaTypeId(), but does
+ a lookup at runtime based on the name of the type.
+ QMetaType::type() is a bit slower, but compilation succeeds if a
+ type is not registered.
+
+ \sa Q_DECLARE_METATYPE(), QMetaType::type()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
new file mode 100644
index 0000000000..a2bb7d1597
--- /dev/null
+++ b/src/corelib/kernel/qmetatype.h
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QMETATYPE_H
+#define QMETATYPE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
+
+#ifndef QT_NO_DATASTREAM
+#include <QtCore/qdatastream.h>
+#endif
+
+#ifdef Bool
+#error qmetatype.h must be included before any header file that defines Bool
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QMetaType {
+public:
+ enum Type {
+ // these are merged with QVariant
+ Void = 0, Bool = 1, Int = 2, UInt = 3, LongLong = 4, ULongLong = 5,
+ Double = 6, QChar = 7, QVariantMap = 8, QVariantList = 9,
+ QString = 10, QStringList = 11, QByteArray = 12,
+ QBitArray = 13, QDate = 14, QTime = 15, QDateTime = 16, QUrl = 17,
+ QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22,
+ QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27,
+ QVariantHash = 28, QEasingCurve = 29, LastCoreType = QEasingCurve,
+
+ FirstGuiType = 63 /* QColorGroup */,
+#ifdef QT3_SUPPORT
+ QColorGroup = 63,
+#endif
+ QFont = 64, QPixmap = 65, QBrush = 66, QColor = 67, QPalette = 68,
+ QIcon = 69, QImage = 70, QPolygon = 71, QRegion = 72, QBitmap = 73,
+ QCursor = 74, QSizePolicy = 75, QKeySequence = 76, QPen = 77,
+ QTextLength = 78, QTextFormat = 79, QMatrix = 80, QTransform = 81,
+ QMatrix4x4 = 82, QVector2D = 83, QVector3D = 84, QVector4D = 85,
+ QQuaternion = 86,
+ LastGuiType = QQuaternion,
+
+ FirstCoreExtType = 128 /* VoidStar */,
+ VoidStar = 128, Long = 129, Short = 130, Char = 131, ULong = 132,
+ UShort = 133, UChar = 134, Float = 135, QObjectStar = 136, QWidgetStar = 137,
+ QVariant = 138,
+ LastCoreExtType = QVariant,
+
+// This logic must match the one in qglobal.h
+#if defined(QT_COORD_TYPE)
+ QReal = 0,
+#elif defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
+ QReal = Float,
+#else
+ QReal = Double,
+#endif
+
+ User = 256
+ };
+
+ typedef void (*Destructor)(void *);
+ typedef void *(*Constructor)(const void *);
+
+#ifndef QT_NO_DATASTREAM
+ typedef void (*SaveOperator)(QDataStream &, const void *);
+ typedef void (*LoadOperator)(QDataStream &, void *);
+ static void registerStreamOperators(const char *typeName, SaveOperator saveOp,
+ LoadOperator loadOp);
+ static void registerStreamOperators(int type, SaveOperator saveOp,
+ LoadOperator loadOp);
+#endif
+ static int registerType(const char *typeName, Destructor destructor,
+ Constructor constructor);
+ static int registerTypedef(const char *typeName, int aliasId);
+ static int type(const char *typeName);
+ static const char *typeName(int type);
+ static bool isRegistered(int type);
+ static void *construct(int type, const void *copy = 0);
+ static void destroy(int type, void *data);
+ static void unregisterType(const char *typeName);
+
+#ifndef QT_NO_DATASTREAM
+ static bool save(QDataStream &stream, int type, const void *data);
+ static bool load(QDataStream &stream, int type, void *data);
+#endif
+};
+
+template <typename T>
+void qMetaTypeDeleteHelper(T *t)
+{
+ delete t;
+}
+
+template <typename T>
+void *qMetaTypeConstructHelper(const T *t)
+{
+ if (!t)
+ return new T();
+ return new T(*static_cast<const T*>(t));
+}
+
+#ifndef QT_NO_DATASTREAM
+template <typename T>
+void qMetaTypeSaveHelper(QDataStream &stream, const T *t)
+{
+ stream << *t;
+}
+
+template <typename T>
+void qMetaTypeLoadHelper(QDataStream &stream, T *t)
+{
+ stream >> *t;
+}
+#endif // QT_NO_DATASTREAM
+
+template <typename T>
+struct QMetaTypeId
+{
+ enum { Defined = 0 };
+};
+
+template <typename T>
+struct QMetaTypeId2
+{
+ enum { Defined = QMetaTypeId<T>::Defined };
+ static inline int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
+};
+
+namespace QtPrivate {
+ template <typename T, bool Defined = QMetaTypeId2<T>::Defined>
+ struct QMetaTypeIdHelper {
+ static inline int qt_metatype_id()
+ { return QMetaTypeId2<T>::qt_metatype_id(); }
+ };
+ template <typename T> struct QMetaTypeIdHelper<T, false> {
+ static inline int qt_metatype_id()
+ { return -1; }
+ };
+}
+
+template <typename T>
+int qRegisterMetaType(const char *typeName
+#ifndef qdoc
+ , T * dummy = 0
+#endif
+)
+{
+ const int typedefOf = dummy ? -1 : QtPrivate::QMetaTypeIdHelper<T>::qt_metatype_id();
+ if (typedefOf != -1)
+ return QMetaType::registerTypedef(typeName, typedefOf);
+
+ typedef void*(*ConstructPtr)(const T*);
+ ConstructPtr cptr = qMetaTypeConstructHelper<T>;
+ typedef void(*DeletePtr)(T*);
+ DeletePtr dptr = qMetaTypeDeleteHelper<T>;
+
+ return QMetaType::registerType(typeName, reinterpret_cast<QMetaType::Destructor>(dptr),
+ reinterpret_cast<QMetaType::Constructor>(cptr));
+}
+
+#ifndef QT_NO_DATASTREAM
+template <typename T>
+void qRegisterMetaTypeStreamOperators(const char *typeName
+#ifndef qdoc
+ , T * /* dummy */ = 0
+#endif
+)
+{
+ typedef void(*SavePtr)(QDataStream &, const T *);
+ typedef void(*LoadPtr)(QDataStream &, T *);
+ SavePtr sptr = qMetaTypeSaveHelper<T>;
+ LoadPtr lptr = qMetaTypeLoadHelper<T>;
+
+ qRegisterMetaType<T>(typeName);
+ QMetaType::registerStreamOperators(typeName, reinterpret_cast<QMetaType::SaveOperator>(sptr),
+ reinterpret_cast<QMetaType::LoadOperator>(lptr));
+}
+#endif // QT_NO_DATASTREAM
+
+template <typename T>
+inline int qMetaTypeId(
+#ifndef qdoc
+ T * /* dummy */ = 0
+#endif
+)
+{
+ return QMetaTypeId2<T>::qt_metatype_id();
+}
+
+template <typename T>
+inline int qRegisterMetaType(
+#if !defined(qdoc) && !defined(Q_CC_SUN)
+ T * dummy = 0
+#endif
+)
+{
+#ifdef Q_CC_SUN
+ return qMetaTypeId(static_cast<T *>(0));
+#else
+ return qMetaTypeId(dummy);
+#endif
+}
+
+#ifndef QT_NO_DATASTREAM
+template <typename T>
+inline int qRegisterMetaTypeStreamOperators()
+{
+ typedef void(*SavePtr)(QDataStream &, const T *);
+ typedef void(*LoadPtr)(QDataStream &, T *);
+ SavePtr sptr = qMetaTypeSaveHelper<T>;
+ LoadPtr lptr = qMetaTypeLoadHelper<T>;
+
+ register int id = qMetaTypeId<T>();
+ QMetaType::registerStreamOperators(id,
+ reinterpret_cast<QMetaType::SaveOperator>(sptr),
+ reinterpret_cast<QMetaType::LoadOperator>(lptr));
+
+ return id;
+}
+#endif
+
+#define Q_DECLARE_METATYPE(TYPE) \
+ QT_BEGIN_NAMESPACE \
+ template <> \
+ struct QMetaTypeId< TYPE > \
+ { \
+ enum { Defined = 1 }; \
+ static int qt_metatype_id() \
+ { \
+ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \
+ if (!metatype_id) \
+ metatype_id = qRegisterMetaType< TYPE >(#TYPE, \
+ reinterpret_cast< TYPE *>(quintptr(-1))); \
+ return metatype_id; \
+ } \
+ }; \
+ QT_END_NAMESPACE
+
+#define Q_DECLARE_BUILTIN_METATYPE(TYPE, NAME) \
+ QT_BEGIN_NAMESPACE \
+ template<> struct QMetaTypeId2<TYPE> \
+ { \
+ enum { Defined = 1, MetaType = QMetaType::NAME }; \
+ static inline int qt_metatype_id() { return QMetaType::NAME; } \
+ }; \
+ QT_END_NAMESPACE
+
+class QString;
+class QByteArray;
+class QChar;
+class QStringList;
+class QBitArray;
+class QDate;
+class QTime;
+class QDateTime;
+class QUrl;
+class QLocale;
+class QRect;
+class QRectF;
+class QSize;
+class QSizeF;
+class QLine;
+class QLineF;
+class QPoint;
+class QPointF;
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+class QEasingCurve;
+class QWidget;
+class QObject;
+
+#ifdef QT3_SUPPORT
+class QColorGroup;
+#endif
+class QFont;
+class QPixmap;
+class QBrush;
+class QColor;
+class QPalette;
+class QIcon;
+class QImage;
+class QPolygon;
+class QRegion;
+class QBitmap;
+class QCursor;
+class QSizePolicy;
+class QKeySequence;
+class QPen;
+class QTextLength;
+class QTextFormat;
+class QMatrix;
+class QTransform;
+class QMatrix4x4;
+class QVector2D;
+class QVector3D;
+class QVector4D;
+class QQuaternion;
+class QVariant;
+
+QT_END_NAMESPACE
+
+Q_DECLARE_BUILTIN_METATYPE(QString, QString)
+Q_DECLARE_BUILTIN_METATYPE(int, Int)
+Q_DECLARE_BUILTIN_METATYPE(uint, UInt)
+Q_DECLARE_BUILTIN_METATYPE(bool, Bool)
+Q_DECLARE_BUILTIN_METATYPE(double, Double)
+Q_DECLARE_BUILTIN_METATYPE(QByteArray, QByteArray)
+Q_DECLARE_BUILTIN_METATYPE(QChar, QChar)
+Q_DECLARE_BUILTIN_METATYPE(long, Long)
+Q_DECLARE_BUILTIN_METATYPE(short, Short)
+Q_DECLARE_BUILTIN_METATYPE(char, Char)
+Q_DECLARE_BUILTIN_METATYPE(signed char, Char)
+Q_DECLARE_BUILTIN_METATYPE(ulong, ULong)
+Q_DECLARE_BUILTIN_METATYPE(ushort, UShort)
+Q_DECLARE_BUILTIN_METATYPE(uchar, UChar)
+Q_DECLARE_BUILTIN_METATYPE(float, Float)
+Q_DECLARE_BUILTIN_METATYPE(QObject *, QObjectStar)
+Q_DECLARE_BUILTIN_METATYPE(QWidget *, QWidgetStar)
+Q_DECLARE_BUILTIN_METATYPE(void *, VoidStar)
+Q_DECLARE_BUILTIN_METATYPE(qlonglong, LongLong)
+Q_DECLARE_BUILTIN_METATYPE(qulonglong, ULongLong)
+Q_DECLARE_BUILTIN_METATYPE(QStringList, QStringList)
+Q_DECLARE_BUILTIN_METATYPE(QBitArray, QBitArray)
+Q_DECLARE_BUILTIN_METATYPE(QDate, QDate)
+Q_DECLARE_BUILTIN_METATYPE(QTime, QTime)
+Q_DECLARE_BUILTIN_METATYPE(QDateTime, QDateTime)
+Q_DECLARE_BUILTIN_METATYPE(QUrl, QUrl)
+Q_DECLARE_BUILTIN_METATYPE(QLocale, QLocale)
+Q_DECLARE_BUILTIN_METATYPE(QRect, QRect)
+Q_DECLARE_BUILTIN_METATYPE(QRectF, QRectF)
+Q_DECLARE_BUILTIN_METATYPE(QSize, QSize)
+Q_DECLARE_BUILTIN_METATYPE(QSizeF, QSizeF)
+Q_DECLARE_BUILTIN_METATYPE(QLine, QLine)
+Q_DECLARE_BUILTIN_METATYPE(QLineF, QLineF)
+Q_DECLARE_BUILTIN_METATYPE(QPoint, QPoint)
+Q_DECLARE_BUILTIN_METATYPE(QPointF, QPointF)
+#ifndef QT_NO_REGEXP
+Q_DECLARE_BUILTIN_METATYPE(QRegExp, QRegExp)
+#endif
+Q_DECLARE_BUILTIN_METATYPE(QEasingCurve, QEasingCurve)
+
+#ifdef QT3_SUPPORT
+Q_DECLARE_BUILTIN_METATYPE(QColorGroup, QColorGroup)
+#endif
+Q_DECLARE_BUILTIN_METATYPE(QFont, QFont)
+Q_DECLARE_BUILTIN_METATYPE(QPixmap, QPixmap)
+Q_DECLARE_BUILTIN_METATYPE(QBrush, QBrush)
+Q_DECLARE_BUILTIN_METATYPE(QColor, QColor)
+Q_DECLARE_BUILTIN_METATYPE(QPalette, QPalette)
+Q_DECLARE_BUILTIN_METATYPE(QIcon, QIcon)
+Q_DECLARE_BUILTIN_METATYPE(QImage, QImage)
+Q_DECLARE_BUILTIN_METATYPE(QPolygon, QPolygon)
+Q_DECLARE_BUILTIN_METATYPE(QRegion, QRegion)
+Q_DECLARE_BUILTIN_METATYPE(QBitmap, QBitmap)
+Q_DECLARE_BUILTIN_METATYPE(QCursor, QCursor)
+Q_DECLARE_BUILTIN_METATYPE(QSizePolicy, QSizePolicy)
+Q_DECLARE_BUILTIN_METATYPE(QKeySequence, QKeySequence)
+Q_DECLARE_BUILTIN_METATYPE(QPen, QPen)
+Q_DECLARE_BUILTIN_METATYPE(QTextLength, QTextLength)
+Q_DECLARE_BUILTIN_METATYPE(QTextFormat, QTextFormat)
+Q_DECLARE_BUILTIN_METATYPE(QMatrix, QMatrix)
+Q_DECLARE_BUILTIN_METATYPE(QTransform, QTransform)
+Q_DECLARE_BUILTIN_METATYPE(QMatrix4x4, QMatrix4x4)
+Q_DECLARE_BUILTIN_METATYPE(QVector2D, QVector2D)
+Q_DECLARE_BUILTIN_METATYPE(QVector3D, QVector3D)
+Q_DECLARE_BUILTIN_METATYPE(QVector4D, QVector4D)
+Q_DECLARE_BUILTIN_METATYPE(QQuaternion, QQuaternion)
+Q_DECLARE_BUILTIN_METATYPE(QVariant, QVariant)
+
+QT_END_HEADER
+
+#endif // QMETATYPE_H
diff --git a/src/corelib/kernel/qmimedata.cpp b/src/corelib/kernel/qmimedata.cpp
new file mode 100644
index 0000000000..4e0f8aeb8e
--- /dev/null
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -0,0 +1,627 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qmimedata.h"
+
+#include "private/qobject_p.h"
+#include "qurl.h"
+#include "qstringlist.h"
+#include "qtextcodec.h"
+
+QT_BEGIN_NAMESPACE
+
+struct QMimeDataStruct
+{
+ QString format;
+ QVariant data;
+};
+
+class QMimeDataPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QMimeData)
+public:
+ void removeData(const QString &format);
+ void setData(const QString &format, const QVariant &data);
+ QVariant getData(const QString &format) const;
+
+ QVariant retrieveTypedData(const QString &format, QVariant::Type type) const;
+
+ QList<QMimeDataStruct> dataList;
+};
+
+void QMimeDataPrivate::removeData(const QString &format)
+{
+ for (int i=0; i<dataList.size(); i++) {
+ if (dataList.at(i).format == format) {
+ dataList.removeAt(i);
+ return;
+ }
+ }
+}
+
+void QMimeDataPrivate::setData(const QString &format, const QVariant &data)
+{
+ // remove it first if the format is already here.
+ removeData(format);
+ QMimeDataStruct mimeData;
+ mimeData.format = format;
+ mimeData.data = data;
+ dataList += mimeData;
+}
+
+
+QVariant QMimeDataPrivate::getData(const QString &format) const
+{
+ QVariant data;
+ for (int i=0; i<dataList.size(); i++) {
+ if (dataList.at(i).format == format) {
+ data = dataList.at(i).data;
+ break;
+ }
+ }
+ return data;
+}
+
+QVariant QMimeDataPrivate::retrieveTypedData(const QString &format, QVariant::Type type) const
+{
+ Q_Q(const QMimeData);
+
+ QVariant data = q->retrieveData(format, type);
+ if (data.type() == type || !data.isValid())
+ return data;
+
+ // provide more conversion possiblities than just what QVariant provides
+
+ // URLs can be lists as well...
+ if ((type == QVariant::Url && data.type() == QVariant::List)
+ || (type == QVariant::List && data.type() == QVariant::Url))
+ return data;
+
+ // images and pixmaps are interchangeable
+ if ((type == QVariant::Pixmap && data.type() == QVariant::Image)
+ || (type == QVariant::Image && data.type() == QVariant::Pixmap))
+ return data;
+
+ if (data.type() == QVariant::ByteArray) {
+ // see if we can convert to the requested type
+ switch(type) {
+#ifndef QT_NO_TEXTCODEC
+ case QVariant::String: {
+ const QByteArray ba = data.toByteArray();
+ QTextCodec *codec = QTextCodec::codecForName("utf-8");
+ if (format == QLatin1String("text/html"))
+ codec = QTextCodec::codecForHtml(ba, codec);
+ return codec->toUnicode(ba);
+ }
+#endif // QT_NO_TEXTCODEC
+ case QVariant::Color: {
+ QVariant newData = data;
+ newData.convert(QVariant::Color);
+ return newData;
+ }
+ case QVariant::List: {
+ if (format != QLatin1String("text/uri-list"))
+ break;
+ // fall through
+ }
+ case QVariant::Url: {
+ QByteArray ba = data.toByteArray();
+ // Qt 3.x will send text/uri-list with a trailing
+ // null-terminator (that is *not* sent for any other
+ // text/* mime-type), so chop it off
+ if (ba.endsWith('\0'))
+ ba.chop(1);
+
+ QList<QByteArray> urls = ba.split('\n');
+ QList<QVariant> list;
+ for (int i = 0; i < urls.size(); ++i) {
+ QByteArray ba = urls.at(i).trimmed();
+ if (!ba.isEmpty())
+ list.append(QUrl::fromEncoded(ba));
+ }
+ return list;
+ }
+ default:
+ break;
+ }
+
+ } else if (type == QVariant::ByteArray) {
+
+ // try to convert to bytearray
+ switch(data.type()) {
+ case QVariant::ByteArray:
+ case QVariant::Color:
+ return data.toByteArray();
+ break;
+ case QVariant::String:
+ return data.toString().toUtf8();
+ break;
+ case QVariant::Url:
+ return data.toUrl().toEncoded();
+ break;
+ case QVariant::List: {
+ // has to be list of URLs
+ QByteArray result;
+ QList<QVariant> list = data.toList();
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i).type() == QVariant::Url) {
+ result += list.at(i).toUrl().toEncoded();
+ result += "\r\n";
+ }
+ }
+ if (!result.isEmpty())
+ return result;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return data;
+}
+
+/*!
+ \class QMimeData
+ \brief The QMimeData class provides a container for data that records information
+ about its MIME type.
+
+ QMimeData is used to describe information that can be stored in
+ the \l{QClipboard}{clipboard}, and transferred via the \l{drag
+ and drop} mechanism. QMimeData objects associate the data that
+ they hold with the corresponding MIME types to ensure that
+ information can be safely transferred between applications, and
+ copied around within the same application.
+
+ QMimeData objects are usually created using \c new and supplied
+ to QDrag or QClipboard objects. This is to enable Qt to manage
+ the memory that they use.
+
+ A single QMimeData object can store the same data using several
+ different formats at the same time. The formats() function
+ returns a list of the available formats in order of preference.
+ The data() function returns the raw data associated with a MIME
+ type, and setData() allows you to set the data for a MIME type.
+
+ For the most common MIME types, QMimeData provides convenience
+ functions to access the data:
+
+ \table
+ \header \o Tester \o Getter \o Setter \o MIME Types
+ \row \o hasText() \o text() \o setText() \o \c text/plain
+ \row \o hasHtml() \o html() \o setHtml() \o \c text/html
+ \row \o hasUrls() \o urls() \o setUrls() \o \c text/uri-list
+ \row \o hasImage() \o imageData() \o setImageData() \o \c image/ *
+ \row \o hasColor() \o colorData() \o setColorData() \o \c application/x-color
+ \endtable
+
+ For example, if your write a widget that accepts URL drags, you
+ would end up writing code like this:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 0
+
+ There are three approaches for storing custom data in a QMimeData
+ object:
+
+ \list 1
+ \o Custom data can be stored directly in a QMimeData object as a
+ QByteArray using setData(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 1
+
+ \o We can subclass QMimeData and reimplement hasFormat(),
+ formats(), and retrieveData().
+
+ \o If the drag and drop operation occurs within a single
+ application, we can subclass QMimeData and add extra data in
+ it, and use a qobject_cast() in the receiver's drop event
+ handler. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 2
+ \endlist
+
+ \section1 Platform-Specific MIME Types
+
+ On Windows, formats() will also return custom formats available
+ in the MIME data, using the \c{x-qt-windows-mime} subtype to
+ indicate that they represent data in non-standard formats.
+ The formats will take the following form:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 3
+
+ The following are examples of custom MIME types:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 4
+
+ The \c value declaration of each format describes the way in which the
+ data is encoded.
+
+ On Windows, the MIME format does not always map directly to the
+ clipboard formats. Qt provides QWindowsMime to map clipboard
+ formats to open-standard MIME formats. Similarly, the
+ QMacPasteboardMime maps MIME to Mac flavors.
+
+ \sa QClipboard, QDragEnterEvent, QDragMoveEvent, QDropEvent, QDrag,
+ QWindowsMime, QMacPasteboardMime, {Drag and Drop}
+*/
+
+/*!
+ Constructs a new MIME data object with no data in it.
+*/
+QMimeData::QMimeData()
+ : QObject(*new QMimeDataPrivate, 0)
+{
+}
+
+/*!
+ Destroys the MIME data object.
+*/
+QMimeData::~QMimeData()
+{
+}
+
+/*!
+ Returns a list of URLs contained within the MIME data object.
+
+ URLs correspond to the MIME type \c text/uri-list.
+
+ \sa hasUrls(), data()
+*/
+QList<QUrl> QMimeData::urls() const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(QLatin1String("text/uri-list"), QVariant::List);
+ QList<QUrl> urls;
+ if (data.type() == QVariant::Url)
+ urls.append(data.toUrl());
+ else if (data.type() == QVariant::List) {
+ QList<QVariant> list = data.toList();
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i).type() == QVariant::Url)
+ urls.append(list.at(i).toUrl());
+ }
+ }
+ return urls;
+}
+
+/*!
+ Sets the URLs stored in the MIME data object to those specified by \a urls.
+
+ URLs correspond to the MIME type \c text/uri-list.
+
+ \sa hasUrls(), setData()
+*/
+void QMimeData::setUrls(const QList<QUrl> &urls)
+{
+ Q_D(QMimeData);
+ QList<QVariant> list;
+ for (int i = 0; i < urls.size(); ++i)
+ list.append(urls.at(i));
+
+ d->setData(QLatin1String("text/uri-list"), list);
+}
+
+/*!
+ Returns true if the object can return a list of urls; otherwise
+ returns false.
+
+ URLs correspond to the MIME type \c text/uri-list.
+
+ \sa setUrls(), urls(), hasFormat()
+*/
+bool QMimeData::hasUrls() const
+{
+ return hasFormat(QLatin1String("text/uri-list"));
+}
+
+
+/*!
+ Returns a plain text (MIME type \c text/plain) representation of
+ the data.
+
+ \sa hasText(), html(), data()
+*/
+QString QMimeData::text() const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(QLatin1String("text/plain"), QVariant::String);
+ return data.toString();
+}
+
+/*!
+ Sets \a text as the plain text (MIME type \c text/plain) used to
+ represent the data.
+
+ \sa hasText(), setHtml(), setData()
+*/
+void QMimeData::setText(const QString &text)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("text/plain"), text);
+}
+
+/*!
+ Returns true if the object can return plain text (MIME type \c
+ text/plain); otherwise returns false.
+
+ \sa setText(), text(), hasHtml(), hasFormat()
+*/
+bool QMimeData::hasText() const
+{
+ return hasFormat(QLatin1String("text/plain"));
+}
+
+/*!
+ Returns a string if the data stored in the object is HTML (MIME
+ type \c text/html); otherwise returns an empty string.
+
+ \sa hasHtml(), setData()
+*/
+QString QMimeData::html() const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(QLatin1String("text/html"), QVariant::String);
+ return data.toString();
+}
+
+/*!
+ Sets \a html as the HTML (MIME type \c text/html) used to
+ represent the data.
+
+ \sa hasHtml(), setText(), setData()
+*/
+void QMimeData::setHtml(const QString &html)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("text/html"), html);
+}
+
+/*!
+ Returns true if the object can return HTML (MIME type \c
+ text/html); otherwise returns false.
+
+ \sa setHtml(), html(), hasFormat()
+*/
+bool QMimeData::hasHtml() const
+{
+ return hasFormat(QLatin1String("text/html"));
+}
+
+/*!
+ Returns a QVariant storing a QImage if the object can return an
+ image; otherwise returns a null variant.
+
+ A QVariant is used because QMimeData belongs to the \l QtCore
+ library, whereas QImage belongs to \l QtGui. To convert the
+ QVariant to a QImage, simply use qvariant_cast(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 5
+
+ \sa hasImage()
+*/
+QVariant QMimeData::imageData() const
+{
+ Q_D(const QMimeData);
+ return d->retrieveTypedData(QLatin1String("application/x-qt-image"), QVariant::Image);
+}
+
+/*!
+ Sets the data in the object to the given \a image.
+
+ A QVariant is used because QMimeData belongs to the \l QtCore
+ library, whereas QImage belongs to \l QtGui. The conversion
+ from QImage to QVariant is implicit. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 6
+
+ \sa hasImage(), setData()
+*/
+void QMimeData::setImageData(const QVariant &image)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("application/x-qt-image"), image);
+}
+
+/*!
+ Returns true if the object can return an image; otherwise returns
+ false.
+
+ \sa setImageData(), imageData(), hasFormat()
+*/
+bool QMimeData::hasImage() const
+{
+ return hasFormat(QLatin1String("application/x-qt-image"));
+}
+
+/*!
+ Returns a color if the data stored in the object represents a
+ color (MIME type \c application/x-color); otherwise returns a
+ null variant.
+
+ A QVariant is used because QMimeData belongs to the \l QtCore
+ library, whereas QColor belongs to \l QtGui. To convert the
+ QVariant to a QColor, simply use qvariant_cast(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qmimedata.cpp 7
+
+ \sa hasColor(), setColorData(), data()
+*/
+QVariant QMimeData::colorData() const
+{
+ Q_D(const QMimeData);
+ return d->retrieveTypedData(QLatin1String("application/x-color"), QVariant::Color);
+}
+
+/*!
+ Sets the color data in the object to the given \a color.
+
+ Colors correspond to the MIME type \c application/x-color.
+
+ \sa hasColor(), setData()
+*/
+void QMimeData::setColorData(const QVariant &color)
+{
+ Q_D(QMimeData);
+ d->setData(QLatin1String("application/x-color"), color);
+}
+
+
+/*!
+ Returns true if the object can return a color (MIME type \c
+ application/x-color); otherwise returns false.
+
+ \sa setColorData(), colorData(), hasFormat()
+*/
+bool QMimeData::hasColor() const
+{
+ return hasFormat(QLatin1String("application/x-color"));
+}
+
+/*!
+ Returns the data stored in the object in the format described by
+ the MIME type specified by \a mimeType.
+*/
+QByteArray QMimeData::data(const QString &mimeType) const
+{
+ Q_D(const QMimeData);
+ QVariant data = d->retrieveTypedData(mimeType, QVariant::ByteArray);
+ return data.toByteArray();
+}
+
+/*!
+ Sets the data associated with the MIME type given by \a mimeType
+ to the specified \a data.
+
+ For the most common types of data, you can call the higher-level
+ functions setText(), setHtml(), setUrls(), setImageData(), and
+ setColorData() instead.
+
+ Note that if you want to use a custom data type in an item view drag and drop
+ operation, you must register it as a Qt \l{QMetaType}{meta type}, using the
+ Q_DECLARE_METATYPE() macro, and implement stream operators for it. The stream
+ operators must then be registered with the qRegisterMetaTypeStreamOperators()
+ function.
+
+ \sa hasFormat(), QMetaType, qRegisterMetaTypeStreamOperators()
+*/
+void QMimeData::setData(const QString &mimeType, const QByteArray &data)
+{
+ Q_D(QMimeData);
+ d->setData(mimeType, QVariant(data));
+}
+
+/*!
+ Returns true if the object can return data for the MIME type
+ specified by \a mimeType; otherwise returns false.
+
+ For the most common types of data, you can call the higher-level
+ functions hasText(), hasHtml(), hasUrls(), hasImage(), and
+ hasColor() instead.
+
+ \sa formats(), setData(), data()
+*/
+bool QMimeData::hasFormat(const QString &mimeType) const
+{
+ return formats().contains(mimeType);
+}
+
+/*!
+ Returns a list of formats supported by the object. This is a list
+ of MIME types for which the object can return suitable data. The
+ formats in the list are in a priority order.
+
+ For the most common types of data, you can call the higher-level
+ functions hasText(), hasHtml(), hasUrls(), hasImage(), and
+ hasColor() instead.
+
+ \sa hasFormat(), setData(), data()
+*/
+QStringList QMimeData::formats() const
+{
+ Q_D(const QMimeData);
+ QStringList list;
+ for (int i=0; i<d->dataList.size(); i++)
+ list += d->dataList.at(i).format;
+ return list;
+}
+
+/*!
+ Returns a variant with the given \a type containing data for the
+ MIME type specified by \a mimeType. If the object does not
+ support the MIME type or variant type given, a null variant is
+ returned instead.
+
+ This function is called by the general data() getter and by the
+ convenience getters (text(), html(), urls(), imageData(), and
+ colorData()). You can reimplement it if you want to store your
+ data using a custom data structure (instead of a QByteArray,
+ which is what setData() provides). You would then also need
+ to reimplement hasFormat() and formats().
+
+ \sa data()
+*/
+QVariant QMimeData::retrieveData(const QString &mimeType, QVariant::Type type) const
+{
+ Q_UNUSED(type);
+ Q_D(const QMimeData);
+ return d->getData(mimeType);
+}
+
+/*!
+ Removes all the MIME type and data entries in the object.
+*/
+void QMimeData::clear()
+{
+ Q_D(QMimeData);
+ d->dataList.clear();
+}
+
+/*!
+ \since 4.4
+
+ Removes the data entry for \a mimeType in the object.
+*/
+void QMimeData::removeFormat(const QString &mimeType)
+{
+ Q_D(QMimeData);
+ d->removeData(mimeType);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmimedata.h b/src/corelib/kernel/qmimedata.h
new file mode 100644
index 0000000000..28b999c235
--- /dev/null
+++ b/src/corelib/kernel/qmimedata.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QMIMEDATA_H
+#define QMIMEDATA_H
+
+#include <QtCore/qvariant.h>
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QUrl;
+class QMimeDataPrivate;
+
+class Q_CORE_EXPORT QMimeData : public QObject
+{
+ Q_OBJECT
+public:
+ QMimeData();
+ ~QMimeData();
+
+ QList<QUrl> urls() const;
+ void setUrls(const QList<QUrl> &urls);
+ bool hasUrls() const;
+
+ QString text() const;
+ void setText(const QString &text);
+ bool hasText() const;
+
+ QString html() const;
+ void setHtml(const QString &html);
+ bool hasHtml() const;
+
+ QVariant imageData() const;
+ void setImageData(const QVariant &image);
+ bool hasImage() const;
+
+ QVariant colorData() const;
+ void setColorData(const QVariant &color);
+ bool hasColor() const;
+
+ QByteArray data(const QString &mimetype) const;
+ void setData(const QString &mimetype, const QByteArray &data);
+ void removeFormat(const QString &mimetype);
+
+ virtual bool hasFormat(const QString &mimetype) const;
+ virtual QStringList formats() const;
+
+ void clear();
+protected:
+ virtual QVariant retrieveData(const QString &mimetype,
+ QVariant::Type preferredType) const;
+private:
+ Q_DISABLE_COPY(QMimeData)
+ Q_DECLARE_PRIVATE(QMimeData)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMIMEDATA_H
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
new file mode 100644
index 0000000000..357cfd3f33
--- /dev/null
+++ b/src/corelib/kernel/qobject.cpp
@@ -0,0 +1,4310 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qobject.h"
+#include "qobject_p.h"
+#include "qmetaobject_p.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qvariant.h"
+#include "qmetaobject.h"
+#include <qregexp.h>
+#include <qthread.h>
+#include <private/qthread_p.h>
+#include <qdebug.h>
+#include <qhash.h>
+#include <qpair.h>
+#include <qvarlengtharray.h>
+#include <qset.h>
+#include <qsemaphore.h>
+#include <qsharedpointer.h>
+
+#include <private/qorderedmutexlocker_p.h>
+#include <private/qmutexpool_p.h>
+
+#include <new>
+
+#include <ctype.h>
+#include <limits.h>
+
+QT_BEGIN_NAMESPACE
+
+static int DIRECT_CONNECTION_ONLY = 0;
+
+static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
+{
+ int *types = new int [typeNames.count() + 1];
+ Q_CHECK_PTR(types);
+ for (int i = 0; i < typeNames.count(); ++i) {
+ const QByteArray typeName = typeNames.at(i);
+ if (typeName.endsWith('*'))
+ types[i] = QMetaType::VoidStar;
+ else
+ types[i] = QMetaType::type(typeName);
+
+ if (!types[i]) {
+ qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
+ "(Make sure '%s' is registered using qRegisterMetaType().)",
+ typeName.constData(), typeName.constData());
+ delete [] types;
+ return 0;
+ }
+ }
+ types[typeNames.count()] = 0;
+
+ return types;
+}
+
+static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
+static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+/** \internal
+ * mutex to be locked when accessing the connectionlists or the senders list
+ */
+static inline QMutex *signalSlotLock(const QObject *o)
+{
+ if (!signalSlotMutexes) {
+ QMutexPool *mp = new QMutexPool;
+ if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
+ delete mp;
+ }
+ }
+ return signalSlotMutexes->get(o);
+}
+
+extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
+{
+ objectCount.ref();
+}
+
+extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
+{
+ if(!objectCount.deref()) {
+ QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
+ delete old;
+ }
+}
+
+void (*QAbstractDeclarativeData::destroyed)(QAbstractDeclarativeData *, QObject *) = 0;
+void (*QAbstractDeclarativeData::parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *) = 0;
+void (*QAbstractDeclarativeData::objectNameChanged)(QAbstractDeclarativeData *, QObject *) = 0;
+
+QObjectData::~QObjectData() {}
+
+QObjectPrivate::QObjectPrivate(int version)
+ : threadData(0), connectionLists(0), senders(0), currentSender(0), currentChildBeingDeleted(0)
+{
+ if (version != QObjectPrivateVersion)
+ qFatal("Cannot mix incompatible Qt library (version 0x%x) with this library (version 0x%x)",
+ version, QObjectPrivateVersion);
+
+ // QObjectData initialization
+ q_ptr = 0;
+ parent = 0; // no parent yet. It is set by setParent()
+ isWidget = false; // assume not a widget object
+ pendTimer = false; // no timers yet
+ blockSig = false; // not blocking signals
+ wasDeleted = false; // double-delete catcher
+ sendChildEvents = true; // if we should send ChildInsert and ChildRemove events to parent
+ receiveChildEvents = true;
+ postedEvents = 0;
+ extraData = 0;
+ connectedSignals[0] = connectedSignals[1] = 0;
+ inThreadChangeEvent = false;
+#ifdef QT_JAMBI_BUILD
+ inEventHandler = false;
+ deleteWatch = 0;
+#endif
+ metaObject = 0;
+ hasGuards = false;
+}
+
+QObjectPrivate::~QObjectPrivate()
+{
+ if (pendTimer) {
+ // unregister pending timers
+ if (threadData->eventDispatcher)
+ threadData->eventDispatcher->unregisterTimers(q_ptr);
+ }
+
+ if (postedEvents)
+ QCoreApplication::removePostedEvents(q_ptr, 0);
+
+ threadData->deref();
+
+ delete static_cast<QAbstractDynamicMetaObject*>(metaObject);
+#ifdef QT_JAMBI_BUILD
+ if (deleteWatch)
+ *deleteWatch = 1;
+#endif
+#ifndef QT_NO_USERDATA
+ if (extraData)
+ qDeleteAll(extraData->userData);
+ delete extraData;
+#endif
+}
+
+
+#ifdef QT_JAMBI_BUILD
+int *QObjectPrivate::setDeleteWatch(QObjectPrivate *d, int *w) {
+ int *old = d->deleteWatch;
+ d->deleteWatch = w;
+ return old;
+}
+
+
+void QObjectPrivate::resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch) {
+ if (!deleteWatch)
+ d->deleteWatch = oldWatch;
+
+ if (oldWatch)
+ *oldWatch = deleteWatch;
+}
+#endif
+
+#ifdef QT3_SUPPORT
+void QObjectPrivate::sendPendingChildInsertedEvents()
+{
+ Q_Q(QObject);
+ for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) {
+ QObject *c = pendingChildInsertedEvents.at(i).data();
+ if (!c || c->parent() != q)
+ continue;
+ QChildEvent childEvent(QEvent::ChildInserted, c);
+ QCoreApplication::sendEvent(q, &childEvent);
+ }
+ pendingChildInsertedEvents.clear();
+}
+
+#endif
+
+
+/*!\internal
+ For a given metaobject, compute the signal offset, and the method offset (including signals)
+*/
+static void computeOffsets(const QMetaObject *metaobject, int *signalOffset, int *methodOffset)
+{
+ *signalOffset = *methodOffset = 0;
+ const QMetaObject *m = metaobject->d.superdata;
+ while (m) {
+ const QMetaObjectPrivate *d = QMetaObjectPrivate::get(m);
+ *methodOffset += d->methodCount;
+ *signalOffset += (d->revision >= 4) ? d->signalCount : d->methodCount;
+ /*Before Qt 4.6 (revision 4), the signalCount information was not generated by moc.
+ so for compatibility we consider all the method as slot for old moc output*/
+ m = m->d.superdata;
+ }
+}
+
+/*
+ This vector contains the all connections from an object.
+
+ Each object may have one vector containing the lists of
+ connections for a given signal. The index in the vector correspond
+ to the signal index. The signal index is the one returned by
+ QObjectPrivate::signalIndex (not QMetaObject::indexOfSignal).
+ Negative index means connections to all signals.
+
+ This vector is protected by the object mutex (signalSlotMutexes())
+
+ Each Connection is also part of a 'senders' linked list. The mutex
+ of the receiver must be locked when touching the pointers of this
+ linked list.
+*/
+class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
+{
+public:
+ bool orphaned; //the QObject owner of this vector has been destroyed while the vector was inUse
+ bool dirty; //some Connection have been disconnected (their receiver is 0) but not removed from the list yet
+ int inUse; //number of functions that are currently accessing this object or its connections
+ QObjectPrivate::ConnectionList allsignals;
+
+ QObjectConnectionListVector()
+ : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
+ { }
+
+ QObjectPrivate::ConnectionList &operator[](int at)
+ {
+ if (at < 0)
+ return allsignals;
+ return QVector<QObjectPrivate::ConnectionList>::operator[](at);
+ }
+};
+
+// Used by QAccessibleWidget
+bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
+{
+ Q_Q(const QObject);
+ int signal_index = signalIndex(signal);
+ if (signal_index < 0)
+ return false;
+ QMutexLocker locker(signalSlotLock(q));
+ if (connectionLists) {
+ if (signal_index < connectionLists->count()) {
+ const QObjectPrivate::Connection *c =
+ connectionLists->at(signal_index).first;
+
+ while (c) {
+ if (c->receiver == receiver)
+ return true;
+ c = c->nextConnectionList;
+ }
+ }
+ }
+ return false;
+}
+
+// Used by QAccessibleWidget
+QObjectList QObjectPrivate::receiverList(const char *signal) const
+{
+ Q_Q(const QObject);
+ QObjectList returnValue;
+ int signal_index = signalIndex(signal);
+ if (signal_index < 0)
+ return returnValue;
+ QMutexLocker locker(signalSlotLock(q));
+ if (connectionLists) {
+ if (signal_index < connectionLists->count()) {
+ const QObjectPrivate::Connection *c = connectionLists->at(signal_index).first;
+
+ while (c) {
+ if (c->receiver)
+ returnValue << c->receiver;
+ c = c->nextConnectionList;
+ }
+ }
+ }
+ return returnValue;
+}
+
+// Used by QAccessibleWidget
+QObjectList QObjectPrivate::senderList() const
+{
+ QObjectList returnValue;
+ QMutexLocker locker(signalSlotLock(q_func()));
+ for (Connection *c = senders; c; c = c->next)
+ returnValue << c->sender;
+ return returnValue;
+}
+
+void QObjectPrivate::addConnection(int signal, Connection *c)
+{
+ if (!connectionLists)
+ connectionLists = new QObjectConnectionListVector();
+ if (signal >= connectionLists->count())
+ connectionLists->resize(signal + 1);
+
+ ConnectionList &connectionList = (*connectionLists)[signal];
+ if (connectionList.last) {
+ connectionList.last->nextConnectionList = c;
+ } else {
+ connectionList.first = c;
+ }
+ connectionList.last = c;
+
+ cleanConnectionLists();
+}
+
+void QObjectPrivate::cleanConnectionLists()
+{
+ if (connectionLists->dirty && !connectionLists->inUse) {
+ // remove broken connections
+ for (int signal = -1; signal < connectionLists->count(); ++signal) {
+ QObjectPrivate::ConnectionList &connectionList =
+ (*connectionLists)[signal];
+
+ // Set to the last entry in the connection list that was *not*
+ // deleted. This is needed to update the list's last pointer
+ // at the end of the cleanup.
+ QObjectPrivate::Connection *last = 0;
+
+ QObjectPrivate::Connection **prev = &connectionList.first;
+ QObjectPrivate::Connection *c = *prev;
+ while (c) {
+ if (c->receiver) {
+ last = c;
+ prev = &c->nextConnectionList;
+ c = *prev;
+ } else {
+ QObjectPrivate::Connection *next = c->nextConnectionList;
+ *prev = next;
+ delete c;
+ c = next;
+ }
+ }
+
+ // Correct the connection list's last pointer.
+ // As conectionList.last could equal last, this could be a noop
+ connectionList.last = last;
+ }
+ connectionLists->dirty = false;
+ }
+}
+
+typedef QMultiHash<QObject *, QObject **> GuardHash;
+Q_GLOBAL_STATIC(GuardHash, guardHash)
+Q_GLOBAL_STATIC(QMutex, guardHashLock)
+
+/*!\internal
+ */
+void QMetaObject::addGuard(QObject **ptr)
+{
+ if (!*ptr)
+ return;
+ GuardHash *hash = guardHash();
+ if (!hash) {
+ *ptr = 0;
+ return;
+ }
+ QMutexLocker locker(guardHashLock());
+ QObjectPrivate::get(*ptr)->hasGuards = true;
+ hash->insert(*ptr, ptr);
+}
+
+/*!\internal
+ */
+void QMetaObject::removeGuard(QObject **ptr)
+{
+ if (!*ptr)
+ return;
+ GuardHash *hash = guardHash();
+ /* check that the hash is empty - otherwise we might detach
+ the shared_null hash, which will alloc, which is not nice */
+ if (!hash || hash->isEmpty())
+ return;
+ QMutexLocker locker(guardHashLock());
+ if (!*ptr) //check again, under the lock
+ return;
+ GuardHash::iterator it = hash->find(*ptr);
+ const GuardHash::iterator end = hash->end();
+ bool more = false; //if the QObject has more pointer attached to it.
+ for (; it.key() == *ptr && it != end; ++it) {
+ if (it.value() == ptr) {
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
+ break;
+ }
+ more = true;
+ }
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
+}
+
+/*!\internal
+ */
+void QMetaObject::changeGuard(QObject **ptr, QObject *o)
+{
+ GuardHash *hash = guardHash();
+ if (!hash) {
+ *ptr = 0;
+ return;
+ }
+ QMutexLocker locker(guardHashLock());
+ if (o) {
+ hash->insert(o, ptr);
+ QObjectPrivate::get(o)->hasGuards = true;
+ }
+ if (*ptr) {
+ bool more = false; //if the QObject has more pointer attached to it.
+ GuardHash::iterator it = hash->find(*ptr);
+ const GuardHash::iterator end = hash->end();
+ for (; it.key() == *ptr && it != end; ++it) {
+ if (it.value() == ptr) {
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
+ break;
+ }
+ more = true;
+ }
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
+ }
+ *ptr = o;
+}
+
+/*! \internal
+ */
+void QObjectPrivate::clearGuards(QObject *object)
+{
+ GuardHash *hash = 0;
+ QMutex *mutex = 0;
+ QT_TRY {
+ hash = guardHash();
+ mutex = guardHashLock();
+ } QT_CATCH(const std::bad_alloc &) {
+ // do nothing in case of OOM - code below is safe
+ }
+
+ /* check that the hash is empty - otherwise we might detach
+ the shared_null hash, which will alloc, which is not nice */
+ if (hash && !hash->isEmpty()) {
+ QMutexLocker locker(mutex);
+ GuardHash::iterator it = hash->find(object);
+ const GuardHash::iterator end = hash->end();
+ while (it.key() == object && it != end) {
+ *it.value() = 0;
+ it = hash->erase(it);
+ }
+ }
+}
+
+/*! \internal
+ */
+QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId,
+ int nargs, int *types, void **args, QSemaphore *semaphore)
+ : QEvent(MetaCall), sender_(sender), signalId_(signalId),
+ nargs_(nargs), types_(types), args_(args), semaphore_(semaphore),
+ callFunction_(callFunction), method_offset_(method_offset), method_relative_(method_relative)
+{ }
+
+/*! \internal
+ */
+QMetaCallEvent::~QMetaCallEvent()
+{
+ if (types_) {
+ for (int i = 0; i < nargs_; ++i) {
+ if (types_[i] && args_[i])
+ QMetaType::destroy(types_[i], args_[i]);
+ }
+ qFree(types_);
+ qFree(args_);
+ }
+#ifndef QT_NO_THREAD
+ if (semaphore_)
+ semaphore_->release();
+#endif
+}
+
+/*! \internal
+ */
+void QMetaCallEvent::placeMetaCall(QObject *object)
+{
+ if (callFunction_) {
+ callFunction_(object, QMetaObject::InvokeMetaMethod, method_relative_, args_);
+ } else {
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method_offset_ + method_relative_, args_);
+ }
+}
+
+/*!
+ \class QObject
+ \brief The QObject class is the base class of all Qt objects.
+
+ \ingroup objectmodel
+
+ \reentrant
+
+ QObject is the heart of the Qt \l{Object Model}. The central
+ feature in this model is a very powerful mechanism for seamless
+ object communication called \l{signals and slots}. You can
+ connect a signal to a slot with connect() and destroy the
+ connection with disconnect(). To avoid never ending notification
+ loops you can temporarily block signals with blockSignals(). The
+ protected functions connectNotify() and disconnectNotify() make
+ it possible to track connections.
+
+ QObjects organize themselves in \l {Object Trees & Ownership}
+ {object trees}. When you create a QObject with another object as
+ parent, the object will automatically add itself to the parent's
+ children() list. The parent takes ownership of the object; i.e.,
+ it will automatically delete its children in its destructor. You
+ can look for an object by name and optionally type using
+ findChild() or findChildren().
+
+ Every object has an objectName() and its class name can be found
+ via the corresponding metaObject() (see QMetaObject::className()).
+ You can determine whether the object's class inherits another
+ class in the QObject inheritance hierarchy by using the
+ inherits() function.
+
+ When an object is deleted, it emits a destroyed() signal. You can
+ catch this signal to avoid dangling references to QObjects.
+
+ QObjects can receive events through event() and filter the events
+ of other objects. See installEventFilter() and eventFilter() for
+ details. A convenience handler, childEvent(), can be reimplemented
+ to catch child events.
+
+ Events are delivered in the thread in which the object was
+ created; see \l{Thread Support in Qt} and thread() for details.
+ Note that event processing is not done at all for QObjects with no
+ thread affinity (thread() returns zero). Use the moveToThread()
+ function to change the thread affinity for an object and its
+ children (the object cannot be moved if it has a parent).
+
+ Last but not least, QObject provides the basic timer support in
+ Qt; see QTimer for high-level support for timers.
+
+ Notice that the Q_OBJECT macro is mandatory for any object that
+ implements signals, slots or properties. You also need to run the
+ \l{moc}{Meta Object Compiler} on the source file. We strongly
+ recommend the use of this macro in all subclasses of QObject
+ regardless of whether or not they actually use signals, slots and
+ properties, since failure to do so may lead certain functions to
+ exhibit strange behavior.
+
+ All Qt widgets inherit QObject. The convenience function
+ isWidgetType() returns whether an object is actually a widget. It
+ is much faster than
+ \l{qobject_cast()}{qobject_cast}<QWidget *>(\e{obj}) or
+ \e{obj}->\l{inherits()}{inherits}("QWidget").
+
+ Some QObject functions, e.g. children(), return a QObjectList.
+ QObjectList is a typedef for QList<QObject *>.
+
+ \target No copy constructor
+ \section1 No copy constructor or assignment operator
+
+ QObject has neither a copy constructor nor an assignment operator.
+ This is by design. Actually, they are declared, but in a
+ \c{private} section with the macro Q_DISABLE_COPY(). In fact, all
+ Qt classes derived from QObject (direct or indirect) use this
+ macro to declare their copy constructor and assignment operator to
+ be private. The reasoning is found in the discussion on
+ \l{Identity vs Value} {Identity vs Value} on the Qt \l{Object
+ Model} page.
+
+ The main consequence is that you should use pointers to QObject
+ (or to your QObject subclass) where you might otherwise be tempted
+ to use your QObject subclass as a value. For example, without a
+ copy constructor, you can't use a subclass of QObject as the value
+ to be stored in one of the container classes. You must store
+ pointers.
+
+ \section1 Auto-Connection
+
+ Qt's meta-object system provides a mechanism to automatically connect
+ signals and slots between QObject subclasses and their children. As long
+ as objects are defined with suitable object names, and slots follow a
+ simple naming convention, this connection can be performed at run-time
+ by the QMetaObject::connectSlotsByName() function.
+
+ \l uic generates code that invokes this function to enable
+ auto-connection to be performed between widgets on forms created
+ with \QD. More information about using auto-connection with \QD is
+ given in the \l{Using a Designer UI File in Your Application} section of
+ the \QD manual.
+
+ \section1 Dynamic Properties
+
+ From Qt 4.2, dynamic properties can be added to and removed from QObject
+ instances at run-time. Dynamic properties do not need to be declared at
+ compile-time, yet they provide the same advantages as static properties
+ and are manipulated using the same API - using property() to read them
+ and setProperty() to write them.
+
+ From Qt 4.3, dynamic properties are supported by
+ \l{Qt Designer's Widget Editing Mode#The Property Editor}{Qt Designer},
+ and both standard Qt widgets and user-created forms can be given dynamic
+ properties.
+
+ \section1 Internationalization (i18n)
+
+ All QObject subclasses support Qt's translation features, making it possible
+ to translate an application's user interface into different languages.
+
+ To make user-visible text translatable, it must be wrapped in calls to
+ the tr() function. This is explained in detail in the
+ \l{Writing Source Code for Translation} document.
+
+ \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
+ \sa {Object Trees & Ownership}
+*/
+
+/*!
+ \relates QObject
+
+ Returns a pointer to the object named \a name that inherits \a
+ type and with a given \a parent.
+
+ Returns 0 if there is no such child.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 0
+*/
+
+void *qt_find_obj_child(QObject *parent, const char *type, const QString &name)
+{
+ QObjectList list = parent->children();
+ if (list.size() == 0) return 0;
+ for (int i = 0; i < list.size(); ++i) {
+ QObject *obj = list.at(i);
+ if (name == obj->objectName() && obj->inherits(type))
+ return obj;
+ }
+ return 0;
+}
+
+
+/*****************************************************************************
+ QObject member functions
+ *****************************************************************************/
+
+// check the constructor's parent thread argument
+static bool check_parent_thread(QObject *parent,
+ QThreadData *parentThreadData,
+ QThreadData *currentThreadData)
+{
+ if (parent && parentThreadData != currentThreadData) {
+ QThread *parentThread = parentThreadData->thread;
+ QThread *currentThread = currentThreadData->thread;
+ qWarning("QObject: Cannot create children for a parent that is in a different thread.\n"
+ "(Parent is %s(%p), parent's thread is %s(%p), current thread is %s(%p)",
+ parent->metaObject()->className(),
+ parent,
+ parentThread ? parentThread->metaObject()->className() : "QThread",
+ parentThread,
+ currentThread ? currentThread->metaObject()->className() : "QThread",
+ currentThread);
+ return false;
+ }
+ return true;
+}
+
+/*!
+ Constructs an object with parent object \a parent.
+
+ The parent of an object may be viewed as the object's owner. For
+ instance, a \l{QDialog}{dialog box} is the parent of the \gui OK
+ and \gui Cancel buttons it contains.
+
+ The destructor of a parent object destroys all child objects.
+
+ Setting \a parent to 0 constructs an object with no parent. If the
+ object is a widget, it will become a top-level window.
+
+ \sa parent(), findChild(), findChildren()
+*/
+
+QObject::QObject(QObject *parent)
+ : d_ptr(new QObjectPrivate)
+{
+ Q_D(QObject);
+ d_ptr->q_ptr = this;
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ if (parent) {
+ QT_TRY {
+ if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
+ parent = 0;
+ setParent(parent);
+ } QT_CATCH(...) {
+ d->threadData->deref();
+ QT_RETHROW;
+ }
+ }
+ qt_addObject(this);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload QObject()
+ \obsolete
+
+ Creates a new QObject with the given \a parent and object \a name.
+ */
+QObject::QObject(QObject *parent, const char *name)
+ : d_ptr(new QObjectPrivate)
+{
+ Q_D(QObject);
+ qt_addObject(d_ptr->q_ptr = this);
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ if (parent) {
+ if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
+ parent = 0;
+ setParent(parent);
+ }
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*! \internal
+ */
+QObject::QObject(QObjectPrivate &dd, QObject *parent)
+ : d_ptr(&dd)
+{
+ Q_D(QObject);
+ d_ptr->q_ptr = this;
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ if (parent) {
+ QT_TRY {
+ if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
+ parent = 0;
+ if (d->isWidget) {
+ if (parent) {
+ d->parent = parent;
+ d->parent->d_func()->children.append(this);
+ }
+ // no events sent here, this is done at the end of the QWidget constructor
+ } else {
+ setParent(parent);
+ }
+ } QT_CATCH(...) {
+ d->threadData->deref();
+ QT_RETHROW;
+ }
+ }
+ qt_addObject(this);
+}
+
+/*!
+ Destroys the object, deleting all its child objects.
+
+ All signals to and from the object are automatically disconnected, and
+ any pending posted events for the object are removed from the event
+ queue. However, it is often safer to use deleteLater() rather than
+ deleting a QObject subclass directly.
+
+ \warning All child objects are deleted. If any of these objects
+ are on the stack or global, sooner or later your program will
+ crash. We do not recommend holding pointers to child objects from
+ outside the parent. If you still do, the destroyed() signal gives
+ you an opportunity to detect when an object is destroyed.
+
+ \warning Deleting a QObject while pending events are waiting to
+ be delivered can cause a crash. You must not delete the QObject
+ directly if it exists in a different thread than the one currently
+ executing. Use deleteLater() instead, which will cause the event
+ loop to delete the object after all pending events have been
+ delivered to it.
+
+ \sa deleteLater()
+*/
+
+QObject::~QObject()
+{
+ Q_D(QObject);
+ d->wasDeleted = true;
+ d->blockSig = 0; // unblock signals so we always emit destroyed()
+
+ if (d->hasGuards && !d->isWidget) {
+ // set all QPointers for this object to zero - note that
+ // ~QWidget() does this for us, so we don't have to do it twice
+ QObjectPrivate::clearGuards(this);
+ }
+
+ if (d->sharedRefcount) {
+ if (d->sharedRefcount->strongref > 0) {
+ qWarning("QObject: shared QObject was deleted directly. The program is malformed and may crash.");
+ // but continue deleting, it's too late to stop anyway
+ }
+
+ // indicate to all QWeakPointers that this QObject has now been deleted
+ d->sharedRefcount->strongref = 0;
+ if (!d->sharedRefcount->weakref.deref())
+ delete d->sharedRefcount;
+ }
+
+
+ if (d->isSignalConnected(0)) {
+ QT_TRY {
+ emit destroyed(this);
+ } QT_CATCH(...) {
+ // all the signal/slots connections are still in place - if we don't
+ // quit now, we will crash pretty soon.
+ qWarning("Detected an unexpected exception in ~QObject while emitting destroyed().");
+ QT_RETHROW;
+ }
+ }
+
+ if (d->declarativeData)
+ QAbstractDeclarativeData::destroyed(d->declarativeData, this);
+
+ // set ref to zero to indicate that this object has been deleted
+ if (d->currentSender != 0)
+ d->currentSender->ref = 0;
+ d->currentSender = 0;
+
+ if (d->connectionLists || d->senders) {
+ QMutex *signalSlotMutex = signalSlotLock(this);
+ QMutexLocker locker(signalSlotMutex);
+
+ // disconnect all receivers
+ if (d->connectionLists) {
+ ++d->connectionLists->inUse;
+ int connectionListsCount = d->connectionLists->count();
+ for (int signal = -1; signal < connectionListsCount; ++signal) {
+ QObjectPrivate::ConnectionList &connectionList =
+ (*d->connectionLists)[signal];
+
+ while (QObjectPrivate::Connection *c = connectionList.first) {
+ if (!c->receiver) {
+ connectionList.first = c->nextConnectionList;
+ delete c;
+ continue;
+ }
+
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
+
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
+ }
+ if (needToUnlock)
+ m->unlockInline();
+
+ connectionList.first = c->nextConnectionList;
+ delete c;
+ }
+ }
+
+ if (!--d->connectionLists->inUse) {
+ delete d->connectionLists;
+ } else {
+ d->connectionLists->orphaned = true;
+ }
+ d->connectionLists = 0;
+ }
+
+ // disconnect all senders
+ QObjectPrivate::Connection *node = d->senders;
+ while (node) {
+ QObject *sender = node->sender;
+ QMutex *m = signalSlotLock(sender);
+ node->prev = &node;
+ bool needToUnlock = QOrderedMutexLocker::relock(signalSlotMutex, m);
+ //the node has maybe been removed while the mutex was unlocked in relock?
+ if (!node || node->sender != sender) {
+ m->unlockInline();
+ continue;
+ }
+ node->receiver = 0;
+ QObjectConnectionListVector *senderLists = sender->d_func()->connectionLists;
+ if (senderLists)
+ senderLists->dirty = true;
+
+ node = node->next;
+ if (needToUnlock)
+ m->unlockInline();
+ }
+ }
+
+ if (!d->children.isEmpty())
+ d->deleteChildren();
+
+ qt_removeObject(this);
+
+ if (d->parent) // remove it from parent object
+ d->setParent_helper(0);
+
+#ifdef QT_JAMBI_BUILD
+ if (d->inEventHandler) {
+ qWarning("QObject: Do not delete object, '%s', during its event handler!",
+ objectName().isNull() ? "unnamed" : qPrintable(objectName()));
+ }
+#endif
+}
+
+QObjectPrivate::Connection::~Connection()
+{
+ if (argumentTypes != &DIRECT_CONNECTION_ONLY)
+ delete [] static_cast<int *>(argumentTypes);
+}
+
+
+/*!
+ \fn QMetaObject *QObject::metaObject() const
+
+ Returns a pointer to the meta-object of this object.
+
+ A meta-object contains information about a class that inherits
+ QObject, e.g. class name, superclass name, properties, signals and
+ slots. Every QObject subclass that contains the Q_OBJECT macro will have a
+ meta-object.
+
+ The meta-object information is required by the signal/slot
+ connection mechanism and the property system. The inherits()
+ function also makes use of the meta-object.
+
+ If you have no pointer to an actual object instance but still
+ want to access the meta-object of a class, you can use \l
+ staticMetaObject.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 1
+
+ \sa staticMetaObject
+*/
+
+/*!
+ \variable QObject::staticMetaObject
+
+ This variable stores the meta-object for the class.
+
+ A meta-object contains information about a class that inherits
+ QObject, e.g. class name, superclass name, properties, signals and
+ slots. Every class that contains the Q_OBJECT macro will also have
+ a meta-object.
+
+ The meta-object information is required by the signal/slot
+ connection mechanism and the property system. The inherits()
+ function also makes use of the meta-object.
+
+ If you have a pointer to an object, you can use metaObject() to
+ retrieve the meta-object associated with that object.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 2
+
+ \sa metaObject()
+*/
+
+/*! \fn T *qobject_cast<T *>(QObject *object)
+ \relates QObject
+
+ Returns the given \a object cast to type T if the object is of type
+ T (or of a subclass); otherwise returns 0. If \a object is 0 then
+ it will also return 0.
+
+ The class T must inherit (directly or indirectly) QObject and be
+ declared with the \l Q_OBJECT macro.
+
+ A class is considered to inherit itself.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 3
+
+ The qobject_cast() function behaves similarly to the standard C++
+ \c dynamic_cast(), with the advantages that it doesn't require
+ RTTI support and it works across dynamic library boundaries.
+
+ qobject_cast() can also be used in conjunction with interfaces;
+ see the \l{tools/plugandpaint}{Plug & Paint} example for details.
+
+ \warning If T isn't declared with the Q_OBJECT macro, this
+ function's return value is undefined.
+
+ \sa QObject::inherits()
+*/
+
+/*!
+ \fn bool QObject::inherits(const char *className) const
+
+ Returns true if this object is an instance of a class that
+ inherits \a className or a QObject subclass that inherits \a
+ className; otherwise returns false.
+
+ A class is considered to inherit itself.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 4
+
+ If you need to determine whether an object is an instance of a particular
+ class for the purpose of casting it, consider using qobject_cast<Type *>(object)
+ instead.
+
+ \sa metaObject(), qobject_cast()
+*/
+
+/*!
+ \property QObject::objectName
+
+ \brief the name of this object
+
+ You can find an object by name (and type) using findChild(). You can
+ find a set of objects with findChildren().
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 5
+
+ By default, this property contains an empty string.
+
+ \sa metaObject(), QMetaObject::className()
+*/
+
+QString QObject::objectName() const
+{
+ Q_D(const QObject);
+ return d->objectName;
+}
+
+/*
+ Sets the object's name to \a name.
+*/
+void QObject::setObjectName(const QString &name)
+{
+ Q_D(QObject);
+ bool objectNameChanged = d->declarativeData && d->objectName != name;
+
+ d->objectName = name;
+
+ if (objectNameChanged)
+ d->declarativeData->objectNameChanged(d->declarativeData, this);
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \internal
+ QObject::child is compat but needs to call itself recursively,
+ that's why we need this helper.
+*/
+static QObject *qChildHelper(const char *objName, const char *inheritsClass,
+ bool recursiveSearch, const QObjectList &children)
+{
+ if (children.isEmpty())
+ return 0;
+
+ bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
+ const QLatin1String oName(objName);
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *obj = children.at(i);
+ if (onlyWidgets) {
+ if (obj->isWidgetType() && (!objName || obj->objectName() == oName))
+ return obj;
+ } else if ((!inheritsClass || obj->inherits(inheritsClass))
+ && (!objName || obj->objectName() == oName))
+ return obj;
+ if (recursiveSearch && (obj = qChildHelper(objName, inheritsClass,
+ recursiveSearch, obj->children())))
+ return obj;
+ }
+ return 0;
+}
+
+
+/*!
+ Searches the children and optionally grandchildren of this object,
+ and returns a child that is called \a objName that inherits \a
+ inheritsClass. If \a inheritsClass is 0 (the default), any class
+ matches.
+
+ If \a recursiveSearch is true (the default), child() performs a
+ depth-first search of the object's children.
+
+ If there is no such object, this function returns 0. If there are
+ more than one, the first one found is returned.
+*/
+QObject* QObject::child(const char *objName, const char *inheritsClass,
+ bool recursiveSearch) const
+{
+ Q_D(const QObject);
+ return qChildHelper(objName, inheritsClass, recursiveSearch, d->children);
+}
+#endif
+
+/*!
+ \fn bool QObject::isWidgetType() const
+
+ Returns true if the object is a widget; otherwise returns false.
+
+ Calling this function is equivalent to calling
+ inherits("QWidget"), except that it is much faster.
+*/
+
+
+/*!
+ This virtual function receives events to an object and should
+ return true if the event \a e was recognized and processed.
+
+ The event() function can be reimplemented to customize the
+ behavior of an object.
+
+ \sa installEventFilter(), timerEvent(), QApplication::sendEvent(),
+ QApplication::postEvent(), QWidget::event()
+*/
+
+bool QObject::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::Timer:
+ timerEvent((QTimerEvent*)e);
+ break;
+
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInsertedRequest:
+ d_func()->sendPendingChildInsertedEvents();
+ break;
+#endif
+
+ case QEvent::ChildAdded:
+ case QEvent::ChildPolished:
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInserted:
+#endif
+ case QEvent::ChildRemoved:
+ childEvent((QChildEvent*)e);
+ break;
+
+ case QEvent::DeferredDelete:
+ qDeleteInEventHandler(this);
+ break;
+
+ case QEvent::MetaCall:
+ {
+#ifdef QT_JAMBI_BUILD
+ d_func()->inEventHandler = false;
+#endif
+ QMetaCallEvent *mce = static_cast<QMetaCallEvent*>(e);
+ QObjectPrivate::Sender currentSender;
+ currentSender.sender = const_cast<QObject*>(mce->sender());
+ currentSender.signal = mce->signalId();
+ currentSender.ref = 1;
+ QObjectPrivate::Sender * const previousSender =
+ QObjectPrivate::setCurrentSender(this, &currentSender);
+#if defined(QT_NO_EXCEPTIONS)
+ mce->placeMetaCall(this);
+#else
+ QT_TRY {
+ mce->placeMetaCall(this);
+ } QT_CATCH(...) {
+ QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
+ QT_RETHROW;
+ }
+#endif
+ QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
+ break;
+ }
+
+ case QEvent::ThreadChange: {
+ Q_D(QObject);
+ QThreadData *threadData = d->threadData;
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
+ if (eventDispatcher) {
+ QList<QPair<int, int> > timers = eventDispatcher->registeredTimers(this);
+ if (!timers.isEmpty()) {
+ // set inThreadChangeEvent to true to tell the dispatcher not to release out timer ids
+ // back to the pool (since the timer ids are moving to a new thread).
+ d->inThreadChangeEvent = true;
+ eventDispatcher->unregisterTimers(this);
+ d->inThreadChangeEvent = false;
+ QMetaObject::invokeMethod(this, "_q_reregisterTimers", Qt::QueuedConnection,
+ Q_ARG(void*, (new QList<QPair<int, int> >(timers))));
+ }
+ }
+ break;
+ }
+
+ default:
+ if (e->type() >= QEvent::User) {
+ customEvent(e);
+ break;
+ }
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \fn void QObject::timerEvent(QTimerEvent *event)
+
+ This event handler can be reimplemented in a subclass to receive
+ timer events for the object.
+
+ QTimer provides a higher-level interface to the timer
+ functionality, and also more general information about timers. The
+ timer event is passed in the \a event parameter.
+
+ \sa startTimer(), killTimer(), event()
+*/
+
+void QObject::timerEvent(QTimerEvent *)
+{
+}
+
+
+/*!
+ This event handler can be reimplemented in a subclass to receive
+ child events. The event is passed in the \a event parameter.
+
+ QEvent::ChildAdded and QEvent::ChildRemoved events are sent to
+ objects when children are added or removed. In both cases you can
+ only rely on the child being a QObject, or if isWidgetType()
+ returns true, a QWidget. (This is because, in the
+ \l{QEvent::ChildAdded}{ChildAdded} case, the child is not yet
+ fully constructed, and in the \l{QEvent::ChildRemoved}{ChildRemoved}
+ case it might have been destructed already).
+
+ QEvent::ChildPolished events are sent to widgets when children
+ are polished, or when polished children are added. If you receive
+ a child polished event, the child's construction is usually
+ completed. However, this is not guaranteed, and multiple polish
+ events may be delivered during the execution of a widget's
+ constructor.
+
+ For every child widget, you receive one
+ \l{QEvent::ChildAdded}{ChildAdded} event, zero or more
+ \l{QEvent::ChildPolished}{ChildPolished} events, and one
+ \l{QEvent::ChildRemoved}{ChildRemoved} event.
+
+ The \l{QEvent::ChildPolished}{ChildPolished} event is omitted if
+ a child is removed immediately after it is added. If a child is
+ polished several times during construction and destruction, you
+ may receive several child polished events for the same child,
+ each time with a different virtual table.
+
+ \sa event()
+*/
+
+void QObject::childEvent(QChildEvent * /* event */)
+{
+}
+
+
+/*!
+ This event handler can be reimplemented in a subclass to receive
+ custom events. Custom events are user-defined events with a type
+ value at least as large as the QEvent::User item of the
+ QEvent::Type enum, and is typically a QEvent subclass. The event
+ is passed in the \a event parameter.
+
+ \sa event(), QEvent
+*/
+void QObject::customEvent(QEvent * /* event */)
+{
+}
+
+
+
+/*!
+ Filters events if this object has been installed as an event
+ filter for the \a watched object.
+
+ In your reimplementation of this function, if you want to filter
+ the \a event out, i.e. stop it being handled further, return
+ true; otherwise return false.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 6
+
+ Notice in the example above that unhandled events are passed to
+ the base class's eventFilter() function, since the base class
+ might have reimplemented eventFilter() for its own internal
+ purposes.
+
+ \warning If you delete the receiver object in this function, be
+ sure to return true. Otherwise, Qt will forward the event to the
+ deleted object and the program might crash.
+
+ \sa installEventFilter()
+*/
+
+bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
+{
+ return false;
+}
+
+/*!
+ \fn bool QObject::signalsBlocked() const
+
+ Returns true if signals are blocked; otherwise returns false.
+
+ Signals are not blocked by default.
+
+ \sa blockSignals()
+*/
+
+/*!
+ If \a block is true, signals emitted by this object are blocked
+ (i.e., emitting a signal will not invoke anything connected to it).
+ If \a block is false, no such blocking will occur.
+
+ The return value is the previous value of signalsBlocked().
+
+ Note that the destroyed() signal will be emitted even if the signals
+ for this object have been blocked.
+
+ \sa signalsBlocked()
+*/
+
+bool QObject::blockSignals(bool block)
+{
+ Q_D(QObject);
+ bool previous = d->blockSig;
+ d->blockSig = block;
+ return previous;
+}
+
+/*!
+ Returns the thread in which the object lives.
+
+ \sa moveToThread()
+*/
+QThread *QObject::thread() const
+{
+ return d_func()->threadData->thread;
+}
+
+/*!
+ Changes the thread affinity for this object and its children. The
+ object cannot be moved if it has a parent. Event processing will
+ continue in the \a targetThread.
+
+ To move an object to the main thread, use QApplication::instance()
+ to retrieve a pointer to the current application, and then use
+ QApplication::thread() to retrieve the thread in which the
+ application lives. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 7
+
+ If \a targetThread is zero, all event processing for this object
+ and its children stops.
+
+ Note that all active timers for the object will be reset. The
+ timers are first stopped in the current thread and restarted (with
+ the same interval) in the \a targetThread. As a result, constantly
+ moving an object between threads can postpone timer events
+ indefinitely.
+
+ A QEvent::ThreadChange event is sent to this object just before
+ the thread affinity is changed. You can handle this event to
+ perform any special processing. Note that any new events that are
+ posted to this object will be handled in the \a targetThread.
+
+ \warning This function is \e not thread-safe; the current thread
+ must be same as the current thread affinity. In other words, this
+ function can only "push" an object from the current thread to
+ another thread, it cannot "pull" an object from any arbitrary
+ thread to the current thread.
+
+ \sa thread()
+ */
+void QObject::moveToThread(QThread *targetThread)
+{
+ Q_D(QObject);
+
+ if (d->threadData->thread == targetThread) {
+ // object is already in this thread
+ return;
+ }
+
+ if (d->parent != 0) {
+ qWarning("QObject::moveToThread: Cannot move objects with a parent");
+ return;
+ }
+ if (d->isWidget) {
+ qWarning("QObject::moveToThread: Widgets cannot be moved to a new thread");
+ return;
+ }
+
+ QThreadData *currentData = QThreadData::current();
+ QThreadData *targetData = targetThread ? QThreadData::get2(targetThread) : new QThreadData(0);
+ if (d->threadData->thread == 0 && currentData == targetData) {
+ // one exception to the rule: we allow moving objects with no thread affinity to the current thread
+ currentData = d->threadData;
+ } else if (d->threadData != currentData) {
+ qWarning("QObject::moveToThread: Current thread (%p) is not the object's thread (%p).\n"
+ "Cannot move to target thread (%p)\n",
+ currentData->thread, d->threadData->thread, targetData->thread);
+
+#ifdef Q_WS_MAC
+ qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. "
+ "Check that all plugins are compiled against the right Qt binaries. Export "
+ "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
+#endif
+
+ return;
+ }
+
+ // prepare to move
+ d->moveToThread_helper();
+
+ QOrderedMutexLocker locker(&currentData->postEventList.mutex,
+ &targetData->postEventList.mutex);
+
+ // keep currentData alive (since we've got it locked)
+ currentData->ref();
+
+ // move the object
+ d_func()->setThreadData_helper(currentData, targetData);
+
+ locker.unlock();
+
+ // now currentData can commit suicide if it wants to
+ currentData->deref();
+}
+
+void QObjectPrivate::moveToThread_helper()
+{
+ Q_Q(QObject);
+ QEvent e(QEvent::ThreadChange);
+ QCoreApplication::sendEvent(q, &e);
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *child = children.at(i);
+ child->d_func()->moveToThread_helper();
+ }
+}
+
+void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData *targetData)
+{
+ Q_Q(QObject);
+
+ // move posted events
+ int eventsMoved = 0;
+ for (int i = 0; i < currentData->postEventList.size(); ++i) {
+ const QPostEvent &pe = currentData->postEventList.at(i);
+ if (!pe.event)
+ continue;
+ if (pe.receiver == q) {
+ // move this post event to the targetList
+ targetData->postEventList.append(pe);
+ const_cast<QPostEvent &>(pe).event = 0;
+ ++eventsMoved;
+ }
+ }
+ if (eventsMoved > 0 && targetData->eventDispatcher) {
+ targetData->canWait = false;
+ targetData->eventDispatcher->wakeUp();
+ }
+
+ // the current emitting thread shouldn't restore currentSender after calling moveToThread()
+ if (currentSender)
+ currentSender->ref = 0;
+ currentSender = 0;
+
+#ifdef QT_JAMBI_BUILD
+ // the current event thread also shouldn't restore the delete watch
+ inEventHandler = false;
+
+ if (deleteWatch)
+ *deleteWatch = 1;
+ deleteWatch = 0;
+#endif
+
+ // set new thread data
+ targetData->ref();
+ threadData->deref();
+ threadData = targetData;
+
+ for (int i = 0; i < children.size(); ++i) {
+ QObject *child = children.at(i);
+ child->d_func()->setThreadData_helper(currentData, targetData);
+ }
+}
+
+void QObjectPrivate::_q_reregisterTimers(void *pointer)
+{
+ Q_Q(QObject);
+ QList<QPair<int, int> > *timerList = reinterpret_cast<QList<QPair<int, int> > *>(pointer);
+ QAbstractEventDispatcher *eventDispatcher = threadData->eventDispatcher;
+ for (int i = 0; i < timerList->size(); ++i) {
+ const QPair<int, int> &pair = timerList->at(i);
+ eventDispatcher->registerTimer(pair.first, pair.second, q);
+ }
+ delete timerList;
+}
+
+
+//
+// The timer flag hasTimer is set when startTimer is called.
+// It is not reset when killing the timer because more than
+// one timer might be active.
+//
+
+/*!
+ Starts a timer and returns a timer identifier, or returns zero if
+ it could not start a timer.
+
+ A timer event will occur every \a interval milliseconds until
+ killTimer() is called. If \a interval is 0, then the timer event
+ occurs once every time there are no more window system events to
+ process.
+
+ The virtual timerEvent() function is called with the QTimerEvent
+ event parameter class when a timer event occurs. Reimplement this
+ function to get timer events.
+
+ If multiple timers are running, the QTimerEvent::timerId() can be
+ used to find out which timer was activated.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 8
+
+ Note that QTimer's accuracy depends on the underlying operating
+ system and hardware. Most platforms support an accuracy of 20
+ milliseconds; some provide more. If Qt is unable to deliver the
+ requested number of timer events, it will silently discard some.
+
+ The QTimer class provides a high-level programming interface with
+ single-shot timers and timer signals instead of events. There is
+ also a QBasicTimer class that is more lightweight than QTimer and
+ less clumsy than using timer IDs directly.
+
+ \sa timerEvent(), killTimer(), QTimer::singleShot()
+*/
+
+int QObject::startTimer(int interval)
+{
+ Q_D(QObject);
+
+ if (interval < 0) {
+ qWarning("QObject::startTimer: QTimer cannot have a negative interval");
+ return 0;
+ }
+
+ d->pendTimer = true; // set timer flag
+
+ if (!d->threadData->eventDispatcher) {
+ qWarning("QObject::startTimer: QTimer can only be used with threads started with QThread");
+ return 0;
+ }
+ return d->threadData->eventDispatcher->registerTimer(interval, this);
+}
+
+/*!
+ Kills the timer with timer identifier, \a id.
+
+ The timer identifier is returned by startTimer() when a timer
+ event is started.
+
+ \sa timerEvent(), startTimer()
+*/
+
+void QObject::killTimer(int id)
+{
+ Q_D(QObject);
+ if (d->threadData->eventDispatcher)
+ d->threadData->eventDispatcher->unregisterTimer(id);
+}
+
+
+/*!
+ \fn QObject *QObject::parent() const
+
+ Returns a pointer to the parent object.
+
+ \sa children()
+*/
+
+/*!
+ \fn const QObjectList &QObject::children() const
+
+ Returns a list of child objects.
+ The QObjectList class is defined in the \c{<QObject>} header
+ file as the following:
+
+ \quotefromfile src/corelib/kernel/qobject.h
+ \skipto /typedef .*QObjectList/
+ \printuntil QObjectList
+
+ The first child added is the \l{QList::first()}{first} object in
+ the list and the last child added is the \l{QList::last()}{last}
+ object in the list, i.e. new children are appended at the end.
+
+ Note that the list order changes when QWidget children are
+ \l{QWidget::raise()}{raised} or \l{QWidget::lower()}{lowered}. A
+ widget that is raised becomes the last object in the list, and a
+ widget that is lowered becomes the first object in the list.
+
+ \sa findChild(), findChildren(), parent(), setParent()
+*/
+
+#ifdef QT3_SUPPORT
+static void objSearch(QObjectList &result,
+ const QObjectList &list,
+ const char *inheritsClass,
+ bool onlyWidgets,
+ const char *objName,
+ QRegExp *rx,
+ bool recurse)
+{
+ for (int i = 0; i < list.size(); ++i) {
+ QObject *obj = list.at(i);
+ if (!obj)
+ continue;
+ bool ok = true;
+ if (onlyWidgets)
+ ok = obj->isWidgetType();
+ else if (inheritsClass && !obj->inherits(inheritsClass))
+ ok = false;
+ if (ok) {
+ if (objName)
+ ok = (obj->objectName() == QLatin1String(objName));
+#ifndef QT_NO_REGEXP
+ else if (rx)
+ ok = (rx->indexIn(obj->objectName()) != -1);
+#endif
+ }
+ if (ok) // match!
+ result.append(obj);
+ if (recurse) {
+ QObjectList clist = obj->children();
+ if (!clist.isEmpty())
+ objSearch(result, clist, inheritsClass,
+ onlyWidgets, objName, rx, recurse);
+ }
+ }
+}
+
+/*!
+ \internal
+
+ Searches the children and optionally grandchildren of this object,
+ and returns a list of those objects that are named or that match
+ \a objName and inherit \a inheritsClass. If \a inheritsClass is 0
+ (the default), all classes match. If \a objName is 0 (the
+ default), all object names match.
+
+ If \a regexpMatch is true (the default), \a objName is a regular
+ expression that the objects's names must match. The syntax is that
+ of a QRegExp. If \a regexpMatch is false, \a objName is a string
+ and object names must match it exactly.
+
+ Note that \a inheritsClass uses single inheritance from QObject,
+ the way inherits() does. According to inherits(), QWidget
+ inherits QObject but not QPaintDevice. This does not quite match
+ reality, but is the best that can be done on the wide variety of
+ compilers Qt supports.
+
+ Finally, if \a recursiveSearch is true (the default), queryList()
+ searches \e{n}th-generation as well as first-generation children.
+
+ If all this seems a bit complex for your needs, the simpler
+ child() function may be what you want.
+
+ This somewhat contrived example disables all the buttons in this
+ window:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 9
+
+ \warning Delete the list as soon you have finished using it. The
+ list contains pointers that may become invalid at almost any time
+ without notice (as soon as the user closes a window you may have
+ dangling pointers, for example).
+
+ \sa child() children(), parent(), inherits(), objectName(), QRegExp
+*/
+
+QObjectList QObject::queryList(const char *inheritsClass,
+ const char *objName,
+ bool regexpMatch,
+ bool recursiveSearch) const
+{
+ Q_D(const QObject);
+ QObjectList list;
+ bool onlyWidgets = (inheritsClass && qstrcmp(inheritsClass, "QWidget") == 0);
+#ifndef QT_NO_REGEXP
+ if (regexpMatch && objName) { // regexp matching
+ QRegExp rx(QString::fromLatin1(objName));
+ objSearch(list, d->children, inheritsClass, onlyWidgets, 0, &rx, recursiveSearch);
+ } else
+#endif
+ {
+ objSearch(list, d->children, inheritsClass, onlyWidgets, objName, 0, recursiveSearch);
+ }
+ return list;
+}
+#endif
+
+/*!
+ \fn T *QObject::findChild(const QString &name) const
+
+ Returns the child of this object that can be cast into type T and
+ that is called \a name, or 0 if there is no such object.
+ Omitting the \a name argument causes all object names to be matched.
+ The search is performed recursively.
+
+ If there is more than one child matching the search, the most
+ direct ancestor is returned. If there are several direct
+ ancestors, it is undefined which one will be returned. In that
+ case, findChildren() should be used.
+
+ This example returns a child \l{QPushButton} of \c{parentWidget}
+ named \c{"button1"}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 10
+
+ This example returns a \l{QListWidget} child of \c{parentWidget}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 11
+
+ \sa findChildren()
+*/
+
+/*!
+ \fn QList<T> QObject::findChildren(const QString &name) const
+
+ Returns all children of this object with the given \a name that can be
+ cast to type T, or an empty list if there are no such objects.
+ Omitting the \a name argument causes all object names to be matched.
+ The search is performed recursively.
+
+ The following example shows how to find a list of child \l{QWidget}s of
+ the specified \c{parentWidget} named \c{widgetname}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 12
+
+ This example returns all \c{QPushButton}s that are children of \c{parentWidget}:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 13
+
+ \sa findChild()
+*/
+
+/*!
+ \fn QList<T> QObject::findChildren(const QRegExp &regExp) const
+ \overload findChildren()
+
+ Returns the children of this object that can be cast to type T
+ and that have names matching the regular expression \a regExp,
+ or an empty list if there are no such objects.
+ The search is performed recursively.
+*/
+
+/*!
+ \fn T qFindChild(const QObject *obj, const QString &name)
+ \relates QObject
+ \obsolete
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QObject::findChild()
+*/
+
+/*!
+ \fn QList<T> qFindChildren(const QObject *obj, const QString &name)
+ \relates QObject
+ \obsolete
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QObject::findChildren()
+*/
+
+/*!
+ \fn QList<T> qFindChildren(const QObject *obj, const QRegExp &regExp)
+ \relates QObject
+ \overload qFindChildren()
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a regExp).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QObject::findChildren()
+*/
+
+/*!
+ \internal
+ \fn T qFindChild(const QObject *obj, const QString &name = QString(), T dummy = 0)
+ \relates QObject
+ \overload qFindChildren()
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QObject::findChild()
+*/
+
+/*!
+ \internal
+ \fn QList<T> qFindChildren(const QObject *obj, const QString &name = QString(), T dummy = 0)
+ \relates QObject
+ \overload qFindChildren()
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QObject::findChildren()
+*/
+
+/*!
+ \internal
+*/
+void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re,
+ const QMetaObject &mo, QList<void*> *list)
+{
+ if (!parent || !list)
+ return;
+ const QObjectList &children = parent->children();
+ QObject *obj;
+ for (int i = 0; i < children.size(); ++i) {
+ obj = children.at(i);
+ if (mo.cast(obj)) {
+ if (re) {
+ if (re->indexIn(obj->objectName()) != -1)
+ list->append(obj);
+ } else {
+ if (name.isNull() || obj->objectName() == name)
+ list->append(obj);
+ }
+ }
+ qt_qFindChildren_helper(obj, name, re, mo, list);
+ }
+}
+
+/*! \internal
+ */
+QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo)
+{
+ if (!parent)
+ return 0;
+ const QObjectList &children = parent->children();
+ QObject *obj;
+ int i;
+ for (i = 0; i < children.size(); ++i) {
+ obj = children.at(i);
+ if (mo.cast(obj) && (name.isNull() || obj->objectName() == name))
+ return obj;
+ }
+ for (i = 0; i < children.size(); ++i) {
+ obj = qt_qFindChild_helper(children.at(i), name, mo);
+ if (obj)
+ return obj;
+ }
+ return 0;
+}
+
+/*!
+ Makes the object a child of \a parent.
+
+ \sa QWidget::setParent()
+*/
+
+void QObject::setParent(QObject *parent)
+{
+ Q_D(QObject);
+ Q_ASSERT(!d->isWidget);
+ d->setParent_helper(parent);
+}
+
+void QObjectPrivate::deleteChildren()
+{
+ const bool reallyWasDeleted = wasDeleted;
+ wasDeleted = true;
+ // delete children objects
+ // don't use qDeleteAll as the destructor of the child might
+ // delete siblings
+ for (int i = 0; i < children.count(); ++i) {
+ currentChildBeingDeleted = children.at(i);
+ children[i] = 0;
+ delete currentChildBeingDeleted;
+ }
+ children.clear();
+ currentChildBeingDeleted = 0;
+ wasDeleted = reallyWasDeleted;
+}
+
+void QObjectPrivate::setParent_helper(QObject *o)
+{
+ Q_Q(QObject);
+ if (o == parent)
+ return;
+ if (parent) {
+ QObjectPrivate *parentD = parent->d_func();
+ if (parentD->wasDeleted && wasDeleted
+ && parentD->currentChildBeingDeleted == q) {
+ // don't do anything since QObjectPrivate::deleteChildren() already
+ // cleared our entry in parentD->children.
+ } else {
+ const int index = parentD->children.indexOf(q);
+ if (parentD->wasDeleted) {
+ parentD->children[index] = 0;
+ } else {
+ parentD->children.removeAt(index);
+ if (sendChildEvents && parentD->receiveChildEvents) {
+ QChildEvent e(QEvent::ChildRemoved, q);
+ QCoreApplication::sendEvent(parent, &e);
+ }
+ }
+ }
+ }
+ parent = o;
+ if (parent) {
+ // object hierarchies are constrained to a single thread
+ if (threadData != parent->d_func()->threadData) {
+ qWarning("QObject::setParent: Cannot set parent, new parent is in a different thread");
+ parent = 0;
+ return;
+ }
+ parent->d_func()->children.append(q);
+ if(sendChildEvents && parent->d_func()->receiveChildEvents) {
+ if (!isWidget) {
+ QChildEvent e(QEvent::ChildAdded, q);
+ QCoreApplication::sendEvent(parent, &e);
+#ifdef QT3_SUPPORT
+ if (QCoreApplicationPrivate::useQt3Support) {
+ if (parent->d_func()->pendingChildInsertedEvents.isEmpty()) {
+ QCoreApplication::postEvent(parent,
+ new QEvent(QEvent::ChildInsertedRequest),
+ Qt::HighEventPriority);
+ }
+ parent->d_func()->pendingChildInsertedEvents.append(q);
+ }
+#endif
+ }
+ }
+ }
+ if (!wasDeleted && declarativeData)
+ QAbstractDeclarativeData::parentChanged(declarativeData, q, o);
+}
+
+/*!
+ \fn void QObject::installEventFilter(QObject *filterObj)
+
+ Installs an event filter \a filterObj on this object. For example:
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 14
+
+ An event filter is an object that receives all events that are
+ sent to this object. The filter can either stop the event or
+ forward it to this object. The event filter \a filterObj receives
+ events via its eventFilter() function. The eventFilter() function
+ must return true if the event should be filtered, (i.e. stopped);
+ otherwise it must return false.
+
+ If multiple event filters are installed on a single object, the
+ filter that was installed last is activated first.
+
+ Here's a \c KeyPressEater class that eats the key presses of its
+ monitored objects:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 15
+
+ And here's how to install it on two widgets:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 16
+
+ The QShortcut class, for example, uses this technique to intercept
+ shortcut key presses.
+
+ \warning If you delete the receiver object in your eventFilter()
+ function, be sure to return true. If you return false, Qt sends
+ the event to the deleted object and the program will crash.
+
+ Note that the filtering object must be in the same thread as this
+ object. If \a filterObj is in a different thread, this function does
+ nothing. If either \a filterObj or this object are moved to a different
+ thread after calling this function, the event filter will not be
+ called until both objects have the same thread affinity again (it
+ is \e not removed).
+
+ \sa removeEventFilter(), eventFilter(), event()
+*/
+
+void QObject::installEventFilter(QObject *obj)
+{
+ Q_D(QObject);
+ if (!obj)
+ return;
+ if (d->threadData != obj->d_func()->threadData) {
+ qWarning("QObject::installEventFilter(): Cannot filter events for objects in a different thread.");
+ return;
+ }
+
+ // clean up unused items in the list
+ d->eventFilters.removeAll((QObject*)0);
+ d->eventFilters.removeAll(obj);
+ d->eventFilters.prepend(obj);
+}
+
+/*!
+ Removes an event filter object \a obj from this object. The
+ request is ignored if such an event filter has not been installed.
+
+ All event filters for this object are automatically removed when
+ this object is destroyed.
+
+ It is always safe to remove an event filter, even during event
+ filter activation (i.e. from the eventFilter() function).
+
+ \sa installEventFilter(), eventFilter(), event()
+*/
+
+void QObject::removeEventFilter(QObject *obj)
+{
+ Q_D(QObject);
+ for (int i = 0; i < d->eventFilters.count(); ++i) {
+ if (d->eventFilters.at(i) == obj)
+ d->eventFilters[i] = 0;
+ }
+}
+
+
+/*!
+ \fn QObject::destroyed(QObject *obj)
+
+ This signal is emitted immediately before the object \a obj is
+ destroyed, and can not be blocked.
+
+ All the objects's children are destroyed immediately after this
+ signal is emitted.
+
+ \sa deleteLater(), QPointer
+*/
+
+/*!
+ Schedules this object for deletion.
+
+ The object will be deleted when control returns to the event
+ loop. If the event loop is not running when this function is
+ called (e.g. deleteLater() is called on an object before
+ QCoreApplication::exec()), the object will be deleted once the
+ event loop is started.
+
+ Note that entering and leaving a new event loop (e.g., by opening a modal
+ dialog) will \e not perform the deferred deletion; for the object to be
+ deleted, the control must return to the event loop from which
+ deleteLater() was called.
+
+ \bold{Note:} It is safe to call this function more than once; when the
+ first deferred deletion event is delivered, any pending events for the
+ object are removed from the event queue.
+
+ \sa destroyed(), QPointer
+*/
+void QObject::deleteLater()
+{
+ QCoreApplication::postEvent(this, new QEvent(QEvent::DeferredDelete));
+}
+
+/*!
+ \fn QString QObject::tr(const char *sourceText, const char *disambiguation, int n)
+ \reentrant
+
+ Returns a translated version of \a sourceText, optionally based on a
+ \a disambiguation string and value of \a n for strings containing plurals;
+ otherwise returns \a sourceText itself if no appropriate translated string
+ is available.
+
+ Example:
+ \snippet mainwindows/sdi/mainwindow.cpp implicit tr context
+ \dots
+
+ If the same \a sourceText is used in different roles within the
+ same context, an additional identifying string may be passed in
+ \a disambiguation (0 by default). In Qt 4.4 and earlier, this was
+ the preferred way to pass comments to translators.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 17
+ \dots
+
+ See \l{Writing Source Code for Translation} for a detailed description of
+ Qt's translation mechanisms in general, and the
+ \l{Writing Source Code for Translation#Disambiguation}{Disambiguation}
+ section for information on disambiguation.
+
+ \warning This method is reentrant only if all translators are
+ installed \e before calling this method. Installing or removing
+ translators while performing translations is not supported. Doing
+ so will probably result in crashes or other undesirable behavior.
+
+ \sa trUtf8(), QApplication::translate(), QTextCodec::setCodecForTr(), {Internationalization with Qt}
+*/
+
+/*!
+ \fn QString QObject::trUtf8(const char *sourceText, const char *disambiguation, int n)
+ \reentrant
+
+ Returns a translated version of \a sourceText, or
+ QString::fromUtf8(\a sourceText) if there is no appropriate
+ version. It is otherwise identical to tr(\a sourceText, \a
+ disambiguation, \a n).
+
+ Note that using the Utf8 variants of the translation functions
+ is not required if \c CODECFORTR is already set to UTF-8 in the
+ qmake project file and QTextCodec::setCodecForTr("UTF-8") is
+ used.
+
+ \warning This method is reentrant only if all translators are
+ installed \e before calling this method. Installing or removing
+ translators while performing translations is not supported. Doing
+ so will probably result in crashes or other undesirable behavior.
+
+ \warning For portability reasons, we recommend that you use
+ escape sequences for specifying non-ASCII characters in string
+ literals to trUtf8(). For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 20
+
+ \sa tr(), QApplication::translate(), {Internationalization with Qt}
+*/
+
+
+
+
+/*****************************************************************************
+ Signals and slots
+ *****************************************************************************/
+
+
+const int flagged_locations_count = 2;
+static const char* flagged_locations[flagged_locations_count] = {0};
+
+const char *qFlagLocation(const char *method)
+{
+ static int idx = 0;
+ flagged_locations[idx] = method;
+ idx = (idx+1) % flagged_locations_count;
+ return method;
+}
+
+static int extract_code(const char *member)
+{
+ // extract code, ensure QMETHOD_CODE <= code <= QSIGNAL_CODE
+ return (((int)(*member) - '0') & 0x3);
+}
+
+static const char * extract_location(const char *member)
+{
+ for (int i = 0; i < flagged_locations_count; ++i) {
+ if (member == flagged_locations[i]) {
+ // signature includes location information after the first null-terminator
+ const char *location = member + qstrlen(member) + 1;
+ if (*location != '\0')
+ return location;
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static bool check_signal_macro(const QObject *sender, const char *signal,
+ const char *func, const char *op)
+{
+ int sigcode = extract_code(signal);
+ if (sigcode != QSIGNAL_CODE) {
+ if (sigcode == QSLOT_CODE)
+ qWarning("Object::%s: Attempt to %s non-signal %s::%s",
+ func, op, sender->metaObject()->className(), signal+1);
+ else
+ qWarning("Object::%s: Use the SIGNAL macro to %s %s::%s",
+ func, op, sender->metaObject()->className(), signal);
+ return false;
+ }
+ return true;
+}
+
+static bool check_method_code(int code, const QObject *object,
+ const char *method, const char *func)
+{
+ if (code != QSLOT_CODE && code != QSIGNAL_CODE) {
+ qWarning("Object::%s: Use the SLOT or SIGNAL macro to "
+ "%s %s::%s", func, func, object->metaObject()->className(), method);
+ return false;
+ }
+ return true;
+}
+
+static void err_method_notfound(const QObject *object,
+ const char *method, const char *func)
+{
+ const char *type = "method";
+ switch (extract_code(method)) {
+ case QSLOT_CODE: type = "slot"; break;
+ case QSIGNAL_CODE: type = "signal"; break;
+ }
+ const char *loc = extract_location(method);
+ if (strchr(method,')') == 0) // common typing mistake
+ qWarning("Object::%s: Parentheses expected, %s %s::%s%s%s",
+ func, type, object->metaObject()->className(), method+1,
+ loc ? " in ": "", loc ? loc : "");
+ else
+ qWarning("Object::%s: No such %s %s::%s%s%s",
+ func, type, object->metaObject()->className(), method+1,
+ loc ? " in ": "", loc ? loc : "");
+
+}
+
+
+static void err_info_about_objects(const char * func,
+ const QObject * sender,
+ const QObject * receiver)
+{
+ QString a = sender ? sender->objectName() : QString();
+ QString b = receiver ? receiver->objectName() : QString();
+ if (!a.isEmpty())
+ qWarning("Object::%s: (sender name: '%s')", func, a.toLocal8Bit().data());
+ if (!b.isEmpty())
+ qWarning("Object::%s: (receiver name: '%s')", func, b.toLocal8Bit().data());
+}
+
+/*!
+ Returns a pointer to the object that sent the signal, if called in
+ a slot activated by a signal; otherwise it returns 0. The pointer
+ is valid only during the execution of the slot that calls this
+ function from this object's thread context.
+
+ The pointer returned by this function becomes invalid if the
+ sender is destroyed, or if the slot is disconnected from the
+ sender's signal.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, getting access to the sender might be useful
+ when many signals are connected to a single slot.
+
+ \warning As mentioned above, the return value of this function is
+ not valid when the slot is called via a Qt::DirectConnection from
+ a thread different from this object's thread. Do not use this
+ function in this type of scenario.
+
+ \sa senderSignalIndex(), QSignalMapper
+*/
+
+QObject *QObject::sender() const
+{
+ Q_D(const QObject);
+
+ QMutexLocker locker(signalSlotLock(this));
+ if (!d->currentSender)
+ return 0;
+
+ for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
+ if (c->sender == d->currentSender->sender)
+ return d->currentSender->sender;
+ }
+
+ return 0;
+}
+
+/*!
+ \since 4.8
+
+ Returns the meta-method index of the signal that called the currently
+ executing slot, which is a member of the class returned by sender().
+ If called outside of a slot activated by a signal, -1 is returned.
+
+ For signals with default parameters, this function will always return
+ the index with all parameters, regardless of which was used with
+ connect(). For example, the signal \c {destroyed(QObject *obj = 0)}
+ will have two different indexes (with and without the parameter), but
+ this function will always return the index with a parameter. This does
+ not apply when overloading signals with different parameters.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, getting access to the signal index might be useful
+ when many signals are connected to a single slot.
+
+ \warning The return value of this function is not valid when the slot
+ is called via a Qt::DirectConnection from a thread different from this
+ object's thread. Do not use this function in this type of scenario.
+
+ \sa sender(), QMetaObject::indexOfSignal(), QMetaObject::method()
+*/
+
+int QObject::senderSignalIndex() const
+{
+ Q_D(const QObject);
+
+ QMutexLocker locker(signalSlotLock(this));
+ if (!d->currentSender)
+ return -1;
+
+ for (QObjectPrivate::Connection *c = d->senders; c; c = c->next) {
+ if (c->sender == d->currentSender->sender)
+ return d->currentSender->signal;
+ }
+
+ return -1;
+}
+
+/*!
+ Returns the number of receivers connected to the \a signal.
+
+ Since both slots and signals can be used as receivers for signals,
+ and the same connections can be made many times, the number of
+ receivers is the same as the number of connections made from this
+ signal.
+
+ When calling this function, you can use the \c SIGNAL() macro to
+ pass a specific signal:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 21
+
+ As the code snippet above illustrates, you can use this function
+ to avoid emitting a signal that nobody listens to.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, it might be useful when you need to perform
+ expensive initialization only if something is connected to a
+ signal.
+*/
+
+int QObject::receivers(const char *signal) const
+{
+ Q_D(const QObject);
+ int receivers = 0;
+ if (signal) {
+ QByteArray signal_name = QMetaObject::normalizedSignature(signal);
+ signal = signal_name;
+#ifndef QT_NO_DEBUG
+ if (!check_signal_macro(this, signal, "receivers", "bind"))
+ return 0;
+#endif
+ signal++; // skip code
+ int signal_index = d->signalIndex(signal);
+ if (signal_index < 0) {
+#ifndef QT_NO_DEBUG
+ err_method_notfound(this, signal-1, "receivers");
+#endif
+ return false;
+ }
+
+ Q_D(const QObject);
+ QMutexLocker locker(signalSlotLock(this));
+ if (d->connectionLists) {
+ if (signal_index < d->connectionLists->count()) {
+ const QObjectPrivate::Connection *c =
+ d->connectionLists->at(signal_index).first;
+ while (c) {
+ receivers += c->receiver ? 1 : 0;
+ c = c->nextConnectionList;
+ }
+ }
+ }
+ }
+ return receivers;
+}
+
+/*!
+ \internal
+
+ This helper function calculates signal and method index for the given
+ member in the specified class.
+
+ \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1.
+
+ \li If specified member is not a member of obj instance class (or one of
+ its parent classes) then both signalIndex and methodIndex are set to -1.
+
+ This function is used by QObject::connect and QObject::disconnect which
+ are working with QMetaMethod.
+
+ \param[out] signalIndex is set to the signal index of member. If the member
+ specified is not signal this variable is set to -1.
+
+ \param[out] methodIndex is set to the method index of the member. If the
+ member is not a method of the object specified by obj param this variable
+ is set to -1.
+*/
+void QMetaObjectPrivate::memberIndexes(const QObject *obj,
+ const QMetaMethod &member,
+ int *signalIndex, int *methodIndex)
+{
+ *signalIndex = -1;
+ *methodIndex = -1;
+ if (!obj || !member.mobj)
+ return;
+ const QMetaObject *m = obj->metaObject();
+ // Check that member is member of obj class
+ while (m != 0 && m != member.mobj)
+ m = m->d.superdata;
+ if (!m)
+ return;
+ *signalIndex = *methodIndex = (member.handle - get(member.mobj)->methodData)/5;
+
+ int signalOffset;
+ int methodOffset;
+ computeOffsets(m, &signalOffset, &methodOffset);
+
+ *methodIndex += methodOffset;
+ if (member.methodType() == QMetaMethod::Signal) {
+ *signalIndex = originalClone(m, *signalIndex);
+ *signalIndex += signalOffset;
+ } else {
+ *signalIndex = -1;
+ }
+}
+
+static inline void check_and_warn_compat(const QMetaObject *sender, const QMetaMethod &signal,
+ const QMetaObject *receiver, const QMetaMethod &method)
+{
+ if (signal.attributes() & QMetaMethod::Compatibility) {
+ if (!(method.attributes() & QMetaMethod::Compatibility))
+ qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)",
+ sender->className(), signal.signature());
+ } else if ((method.attributes() & QMetaMethod::Compatibility) &&
+ method.methodType() == QMetaMethod::Signal) {
+ qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
+ sender->className(), signal.signature(),
+ receiver->className(), method.signature());
+ }
+}
+
+/*!
+ \threadsafe
+
+ Creates a connection of the given \a type from the \a signal in
+ the \a sender object to the \a method in the \a receiver object.
+ Returns true if the connection succeeds; otherwise returns false.
+
+ You must use the \c SIGNAL() and \c SLOT() macros when specifying
+ the \a signal and the \a method, for example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 22
+
+ This example ensures that the label always displays the current
+ scroll bar value. Note that the signal and slots parameters must not
+ contain any variable names, only the type. E.g. the following would
+ not work and return false:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 23
+
+ A signal can also be connected to another signal:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 24
+
+ In this example, the \c MyWidget constructor relays a signal from
+ a private member variable, and makes it available under a name
+ that relates to \c MyWidget.
+
+ A signal can be connected to many slots and signals. Many signals
+ can be connected to one slot.
+
+ If a signal is connected to several slots, the slots are activated
+ in the same order as the order the connection was made, when the
+ signal is emitted.
+
+ The function returns true if it successfully connects the signal
+ to the slot. It will return false if it cannot create the
+ connection, for example, if QObject is unable to verify the
+ existence of either \a signal or \a method, or if their signatures
+ aren't compatible.
+
+ By default, a signal is emitted for every connection you make;
+ two signals are emitted for duplicate connections. You can break
+ all of these connections with a single disconnect() call.
+ If you pass the Qt::UniqueConnection \a type, the connection will only
+ be made if it is not a duplicate. If there is already a duplicate
+ (exact same signal to the exact same slot on the same objects),
+ the connection will fail and connect will return false.
+
+ The optional \a type parameter describes the type of connection
+ to establish. In particular, it determines whether a particular
+ signal is delivered to a slot immediately or queued for delivery
+ at a later time. If the signal is queued, the parameters must be
+ of types that are known to Qt's meta-object system, because Qt
+ needs to copy the arguments to store them in an event behind the
+ scenes. If you try to use a queued connection and get the error
+ message
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 25
+
+ call qRegisterMetaType() to register the data type before you
+ establish the connection.
+
+ \sa disconnect(), sender(), qRegisterMetaType()
+*/
+
+bool QObject::connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
+{
+ {
+ const void *cbdata[] = { sender, signal, receiver, method, &type };
+ if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
+ return true;
+ }
+
+#ifndef QT_NO_DEBUG
+ bool warnCompat = true;
+#endif
+ if (type == Qt::AutoCompatConnection) {
+ type = Qt::AutoConnection;
+#ifndef QT_NO_DEBUG
+ warnCompat = false;
+#endif
+ }
+
+ if (sender == 0 || receiver == 0 || signal == 0 || method == 0) {
+ qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
+ sender ? sender->metaObject()->className() : "(null)",
+ (signal && *signal) ? signal+1 : "(null)",
+ receiver ? receiver->metaObject()->className() : "(null)",
+ (method && *method) ? method+1 : "(null)");
+ return false;
+ }
+ QByteArray tmp_signal_name;
+
+ if (!check_signal_macro(sender, signal, "connect", "bind"))
+ return false;
+ const QMetaObject *smeta = sender->metaObject();
+ const char *signal_arg = signal;
+ ++signal; //skip code
+ int signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ if (signal_index < 0) {
+ // check for normalized signatures
+ tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
+ signal = tmp_signal_name.constData() + 1;
+
+ smeta = sender->metaObject();
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ }
+ if (signal_index < 0) {
+ // re-use tmp_signal_name and signal from above
+
+ smeta = sender->metaObject();
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ }
+ if (signal_index < 0) {
+ err_method_notfound(sender, signal_arg, "connect");
+ err_info_about_objects("connect", sender, receiver);
+ return false;
+ }
+ signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
+ int signalOffset, methodOffset;
+ computeOffsets(smeta, &signalOffset, &methodOffset);
+ int signal_absolute_index = signal_index + methodOffset;
+ signal_index += signalOffset;
+
+ QByteArray tmp_method_name;
+ int membcode = extract_code(method);
+
+ if (!check_method_code(membcode, receiver, method, "connect"))
+ return false;
+ const char *method_arg = method;
+ ++method; // skip code
+
+ const QMetaObject *rmeta = receiver->metaObject();
+ int method_index_relative = -1;
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
+ break;
+ case QSIGNAL_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
+ break;
+ }
+
+ if (method_index_relative < 0) {
+ // check for normalized methods
+ tmp_method_name = QMetaObject::normalizedSignature(method);
+ method = tmp_method_name.constData();
+
+ // rmeta may have been modified above
+ rmeta = receiver->metaObject();
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSlotRelative(&rmeta, method, true);
+ break;
+ case QSIGNAL_CODE:
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, false);
+ if (method_index_relative < 0)
+ method_index_relative = QMetaObjectPrivate::indexOfSignalRelative(&rmeta, method, true);
+ break;
+ }
+ }
+
+ if (method_index_relative < 0) {
+ err_method_notfound(receiver, method_arg, "connect");
+ err_info_about_objects("connect", sender, receiver);
+ return false;
+ }
+
+ if (!QMetaObject::checkConnectArgs(signal, method)) {
+ qWarning("QObject::connect: Incompatible sender/receiver arguments"
+ "\n %s::%s --> %s::%s",
+ sender->metaObject()->className(), signal,
+ receiver->metaObject()->className(), method);
+ return false;
+ }
+
+ int *types = 0;
+ if ((type == Qt::QueuedConnection)
+ && !(types = queuedConnectionTypes(smeta->method(signal_absolute_index).parameterTypes())))
+ return false;
+
+#ifndef QT_NO_DEBUG
+ if (warnCompat) {
+ QMetaMethod smethod = smeta->method(signal_absolute_index);
+ QMetaMethod rmethod = rmeta->method(method_index_relative + rmeta->methodOffset());
+ check_and_warn_compat(smeta, smethod, rmeta, rmethod);
+ }
+#endif
+ if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index_relative, rmeta ,type, types))
+ return false;
+ const_cast<QObject*>(sender)->connectNotify(signal - 1);
+ return true;
+}
+
+/*!
+ \since 4.8
+
+ Creates a connection of the given \a type from the \a signal in
+ the \a sender object to the \a method in the \a receiver object.
+ Returns true if the connection succeeds; otherwise returns false.
+
+ This function works in the same way as
+ connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
+ but it uses QMetaMethod to specify signal and method.
+
+ \see connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method,
+ Qt::ConnectionType type)
+ */
+bool QObject::connect(const QObject *sender, const QMetaMethod &signal,
+ const QObject *receiver, const QMetaMethod &method,
+ Qt::ConnectionType type)
+{
+#ifndef QT_NO_DEBUG
+ bool warnCompat = true;
+#endif
+ if (type == Qt::AutoCompatConnection) {
+ type = Qt::AutoConnection;
+#ifndef QT_NO_DEBUG
+ warnCompat = false;
+#endif
+ }
+
+ if (sender == 0
+ || receiver == 0
+ || signal.methodType() != QMetaMethod::Signal
+ || method.methodType() == QMetaMethod::Constructor) {
+ qWarning("QObject::connect: Cannot connect %s::%s to %s::%s",
+ sender ? sender->metaObject()->className() : "(null)",
+ signal.signature(),
+ receiver ? receiver->metaObject()->className() : "(null)",
+ method.signature() );
+ return false;
+ }
+
+ // Reconstructing SIGNAL() macro result for signal.signature() string
+ QByteArray signalSignature;
+ signalSignature.reserve(qstrlen(signal.signature())+1);
+ signalSignature.append((char)(QSIGNAL_CODE + '0'));
+ signalSignature.append(signal.signature());
+
+ {
+ QByteArray methodSignature;
+ methodSignature.reserve(qstrlen(method.signature())+1);
+ methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
+ : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
+ methodSignature.append(method.signature());
+ const void *cbdata[] = { sender, signalSignature.constData(), receiver, methodSignature.constData(), &type };
+ if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
+ return true;
+ }
+
+
+ int signal_index;
+ int method_index;
+ {
+ int dummy;
+ QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
+ QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
+ }
+
+ const QMetaObject *smeta = sender->metaObject();
+ const QMetaObject *rmeta = receiver->metaObject();
+ if (signal_index == -1) {
+ qWarning("QObject::connect: Can't find signal %s on instance of class %s",
+ signal.signature(), smeta->className());
+ return false;
+ }
+ if (method_index == -1) {
+ qWarning("QObject::connect: Can't find method %s on instance of class %s",
+ method.signature(), rmeta->className());
+ return false;
+ }
+
+ if (!QMetaObject::checkConnectArgs(signal.signature(), method.signature())) {
+ qWarning("QObject::connect: Incompatible sender/receiver arguments"
+ "\n %s::%s --> %s::%s",
+ smeta->className(), signal.signature(),
+ rmeta->className(), method.signature());
+ return false;
+ }
+
+ int *types = 0;
+ if ((type == Qt::QueuedConnection)
+ && !(types = queuedConnectionTypes(signal.parameterTypes())))
+ return false;
+
+#ifndef QT_NO_DEBUG
+ if (warnCompat)
+ check_and_warn_compat(smeta, signal, rmeta, method);
+#endif
+ if (!QMetaObjectPrivate::connect(sender, signal_index, receiver, method_index, 0, type, types))
+ return false;
+
+ const_cast<QObject*>(sender)->connectNotify(signalSignature.constData());
+ return true;
+}
+
+/*!
+ \fn bool QObject::connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type) const
+ \overload connect()
+ \threadsafe
+
+ Connects \a signal from the \a sender object to this object's \a
+ method.
+
+ Equivalent to connect(\a sender, \a signal, \c this, \a method, \a type).
+
+ Every connection you make emits a signal, so duplicate connections emit
+ two signals. You can break a connection using disconnect().
+
+ \sa disconnect()
+*/
+
+/*!
+ \threadsafe
+
+ Disconnects \a signal in object \a sender from \a method in object
+ \a receiver. Returns true if the connection is successfully broken;
+ otherwise returns false.
+
+ A signal-slot connection is removed when either of the objects
+ involved are destroyed.
+
+ disconnect() is typically used in three ways, as the following
+ examples demonstrate.
+ \list 1
+ \i Disconnect everything connected to an object's signals:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 26
+
+ equivalent to the non-static overloaded function
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 27
+
+ \i Disconnect everything connected to a specific signal:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 28
+
+ equivalent to the non-static overloaded function
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 29
+
+ \i Disconnect a specific receiver:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 30
+
+ equivalent to the non-static overloaded function
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 31
+
+ \endlist
+
+ 0 may be used as a wildcard, meaning "any signal", "any receiving
+ object", or "any slot in the receiving object", respectively.
+
+ The \a sender may never be 0. (You cannot disconnect signals from
+ more than one object in a single call.)
+
+ If \a signal is 0, it disconnects \a receiver and \a method from
+ any signal. If not, only the specified signal is disconnected.
+
+ If \a receiver is 0, it disconnects anything connected to \a
+ signal. If not, slots in objects other than \a receiver are not
+ disconnected.
+
+ If \a method is 0, it disconnects anything that is connected to \a
+ receiver. If not, only slots named \a method will be disconnected,
+ and all other slots are left alone. The \a method must be 0 if \a
+ receiver is left out, so you cannot disconnect a
+ specifically-named slot on all objects.
+
+ \sa connect()
+*/
+bool QObject::disconnect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *method)
+{
+ if (sender == 0 || (receiver == 0 && method != 0)) {
+ qWarning("Object::disconnect: Unexpected null parameter");
+ return false;
+ }
+
+ {
+ const void *cbdata[] = { sender, signal, receiver, method };
+ if (QInternal::activateCallbacks(QInternal::DisconnectCallback, (void **) cbdata))
+ return true;
+ }
+
+ const char *signal_arg = signal;
+ QByteArray signal_name;
+ bool signal_found = false;
+ if (signal) {
+ QT_TRY {
+ signal_name = QMetaObject::normalizedSignature(signal);
+ signal = signal_name.constData();
+ } QT_CATCH (const std::bad_alloc &) {
+ // if the signal is already normalized, we can continue.
+ if (sender->metaObject()->indexOfSignal(signal + 1) == -1)
+ QT_RETHROW;
+ }
+
+ if (!check_signal_macro(sender, signal, "disconnect", "unbind"))
+ return false;
+ signal++; // skip code
+ }
+
+ QByteArray method_name;
+ const char *method_arg = method;
+ int membcode = -1;
+ bool method_found = false;
+ if (method) {
+ QT_TRY {
+ method_name = QMetaObject::normalizedSignature(method);
+ method = method_name.constData();
+ } QT_CATCH(const std::bad_alloc &) {
+ // if the method is already normalized, we can continue.
+ if (receiver->metaObject()->indexOfMethod(method + 1) == -1)
+ QT_RETHROW;
+ }
+
+ membcode = extract_code(method);
+ if (!check_method_code(membcode, receiver, method, "disconnect"))
+ return false;
+ method++; // skip code
+ }
+
+ /* We now iterate through all the sender's and receiver's meta
+ * objects in order to also disconnect possibly shadowed signals
+ * and slots with the same signature.
+ */
+ bool res = false;
+ const QMetaObject *smeta = sender->metaObject();
+ do {
+ int signal_index = -1;
+ if (signal) {
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, false);
+ if (signal_index < 0)
+ signal_index = QMetaObjectPrivate::indexOfSignalRelative(&smeta, signal, true);
+ if (signal_index < 0)
+ break;
+ signal_index = QMetaObjectPrivate::originalClone(smeta, signal_index);
+ int signalOffset, methodOffset;
+ computeOffsets(smeta, &signalOffset, &methodOffset);
+ signal_index += signalOffset;
+ signal_found = true;
+ }
+
+ if (!method) {
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, -1);
+ } else {
+ const QMetaObject *rmeta = receiver->metaObject();
+ do {
+ int method_index = rmeta->indexOfMethod(method);
+ if (method_index >= 0)
+ while (method_index < rmeta->methodOffset())
+ rmeta = rmeta->superClass();
+ if (method_index < 0)
+ break;
+ res |= QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index);
+ method_found = true;
+ } while ((rmeta = rmeta->superClass()));
+ }
+ } while (signal && (smeta = smeta->superClass()));
+
+ if (signal && !signal_found) {
+ err_method_notfound(sender, signal_arg, "disconnect");
+ err_info_about_objects("disconnect", sender, receiver);
+ } else if (method && !method_found) {
+ err_method_notfound(receiver, method_arg, "disconnect");
+ err_info_about_objects("disconnect", sender, receiver);
+ }
+ if (res)
+ const_cast<QObject*>(sender)->disconnectNotify(signal ? (signal - 1) : 0);
+ return res;
+}
+
+/*!
+ \since 4.8
+
+ Disconnects \a signal in object \a sender from \a method in object
+ \a receiver. Returns true if the connection is successfully broken;
+ otherwise returns false.
+
+ This function provides the same posibilities like
+ disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
+ but uses QMetaMethod to represent the signal and the method to be disconnected.
+
+ Additionally this function returnsfalse and no signals and slots disconnected
+ if:
+ \list 1
+
+ \i \a signal is not a member of sender class or one of its parent classes.
+
+ \i \a method is not a member of receiver class or one of its parent classes.
+
+ \i \a signal instance represents not a signal.
+
+ \endlist
+
+ QMetaMethod() may be used as wildcard in the meaning "any signal" or "any slot in receiving object".
+ In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case
+ method shoud also be QMetaMethod(). \a sender parameter should be never 0.
+
+ \see disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
+ */
+bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal,
+ const QObject *receiver, const QMetaMethod &method)
+{
+ if (sender == 0 || (receiver == 0 && method.mobj != 0)) {
+ qWarning("Object::disconnect: Unexpected null parameter");
+ return false;
+ }
+ if (signal.mobj) {
+ if(signal.methodType() != QMetaMethod::Signal) {
+ qWarning("Object::%s: Attempt to %s non-signal %s::%s",
+ "disconnect","unbind",
+ sender->metaObject()->className(), signal.signature());
+ return false;
+ }
+ }
+ if (method.mobj) {
+ if(method.methodType() == QMetaMethod::Constructor) {
+ qWarning("QObject::disconect: cannot use constructor as argument %s::%s",
+ receiver->metaObject()->className(), method.signature());
+ return false;
+ }
+ }
+
+ // Reconstructing SIGNAL() macro result for signal.signature() string
+ QByteArray signalSignature;
+ if (signal.mobj) {
+ signalSignature.reserve(qstrlen(signal.signature())+1);
+ signalSignature.append((char)(QSIGNAL_CODE + '0'));
+ signalSignature.append(signal.signature());
+ }
+
+ {
+ QByteArray methodSignature;
+ if (method.mobj) {
+ methodSignature.reserve(qstrlen(method.signature())+1);
+ methodSignature.append((char)(method.methodType() == QMetaMethod::Slot ? QSLOT_CODE
+ : method.methodType() == QMetaMethod::Signal ? QSIGNAL_CODE : 0 + '0'));
+ methodSignature.append(method.signature());
+ }
+ const void *cbdata[] = { sender, signal.mobj ? signalSignature.constData() : 0,
+ receiver, method.mobj ? methodSignature.constData() : 0 };
+ if (QInternal::activateCallbacks(QInternal::ConnectCallback, (void **) cbdata))
+ return true;
+ }
+
+ int signal_index;
+ int method_index;
+ {
+ int dummy;
+ QMetaObjectPrivate::memberIndexes(sender, signal, &signal_index, &dummy);
+ QMetaObjectPrivate::memberIndexes(receiver, method, &dummy, &method_index);
+ }
+ // If we are here sender is not null. If signal is not null while signal_index
+ // is -1 then this signal is not a member of sender.
+ if (signal.mobj && signal_index == -1) {
+ qWarning("QObject::disconect: signal %s not found on class %s",
+ signal.signature(), sender->metaObject()->className());
+ return false;
+ }
+ // If this condition is true then method is not a member of receeiver.
+ if (receiver && method.mobj && method_index == -1) {
+ qWarning("QObject::disconect: method %s not found on class %s",
+ method.signature(), receiver->metaObject()->className());
+ return false;
+ }
+
+ if (!QMetaObjectPrivate::disconnect(sender, signal_index, receiver, method_index))
+ return false;
+
+ const_cast<QObject*>(sender)->disconnectNotify(method.mobj ? signalSignature.constData() : 0);
+ return true;
+}
+
+/*!
+ \threadsafe
+
+ \fn bool QObject::disconnect(const char *signal, const QObject *receiver, const char *method)
+ \overload disconnect()
+
+ Disconnects \a signal from \a method of \a receiver.
+
+ A signal-slot connection is removed when either of the objects
+ involved are destroyed.
+*/
+
+/*!
+ \fn bool QObject::disconnect(const QObject *receiver, const char *method)
+ \overload disconnect()
+
+ Disconnects all signals in this object from \a receiver's \a
+ method.
+
+ A signal-slot connection is removed when either of the objects
+ involved are destroyed.
+*/
+
+
+/*!
+ \fn void QObject::connectNotify(const char *signal)
+
+ This virtual function is called when something has been connected
+ to \a signal in this object.
+
+ If you want to compare \a signal with a specific signal, use
+ QLatin1String and the \c SIGNAL() macro as follows:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 32
+
+ If the signal contains multiple parameters or parameters that
+ contain spaces, call QMetaObject::normalizedSignature() on
+ the result of the \c SIGNAL() macro.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, it might be useful when you need to perform
+ expensive initialization only if something is connected to a
+ signal.
+
+ \sa connect(), disconnectNotify()
+*/
+
+void QObject::connectNotify(const char *)
+{
+}
+
+/*!
+ \fn void QObject::disconnectNotify(const char *signal)
+
+ This virtual function is called when something has been
+ disconnected from \a signal in this object.
+
+ See connectNotify() for an example of how to compare
+ \a signal with a specific signal.
+
+ \warning This function violates the object-oriented principle of
+ modularity. However, it might be useful for optimizing access to
+ expensive resources.
+
+ \sa disconnect(), connectNotify()
+*/
+
+void QObject::disconnectNotify(const char *)
+{
+}
+
+/* \internal
+ convert a signal index from the method range to the signal range
+ */
+static int methodIndexToSignalIndex(const QMetaObject *metaObject, int signal_index)
+{
+ if (signal_index < 0)
+ return signal_index;
+ while (metaObject && metaObject->methodOffset() > signal_index)
+ metaObject = metaObject->superClass();
+
+ if (metaObject) {
+ int signalOffset, methodOffset;
+ computeOffsets(metaObject, &signalOffset, &methodOffset);
+ if (signal_index < metaObject->methodCount())
+ signal_index = QMetaObjectPrivate::originalClone(metaObject, signal_index - methodOffset) + signalOffset;
+ else
+ signal_index = signal_index - methodOffset + signalOffset;
+ }
+ return signal_index;
+}
+
+/*!\internal
+ \a types is a 0-terminated vector of meta types for queued
+ connections.
+
+ if \a signal_index is -1, then we effectively connect *all* signals
+ from the sender to the receiver's slot
+ */
+bool QMetaObject::connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index, int type, int *types)
+{
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
+ return QMetaObjectPrivate::connect(sender, signal_index,
+ receiver, method_index,
+ 0, //FIXME, we could speed this connection up by computing the relative index
+ type, types);
+}
+
+/*! \internal
+ Same as the QMetaObject::connect, but \a signal_index must be the result of QObjectPrivate::signalIndex
+
+ method_index is relative to the rmeta metaobject, if rmeta is null, then it is absolute index
+ */
+bool QMetaObjectPrivate::connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ const QMetaObject *rmeta, int type, int *types)
+{
+ QObject *s = const_cast<QObject *>(sender);
+ QObject *r = const_cast<QObject *>(receiver);
+
+ int method_offset = rmeta ? rmeta->methodOffset() : 0;
+ QObjectPrivate::StaticMetaCallFunction callFunction =
+ (rmeta && QMetaObjectPrivate::get(rmeta)->revision >= 6 && rmeta->d.extradata)
+ ? reinterpret_cast<const QMetaObjectExtraData *>(rmeta->d.extradata)->static_metacall : 0;
+
+ QOrderedMutexLocker locker(signalSlotLock(sender),
+ signalSlotLock(receiver));
+
+ if (type & Qt::UniqueConnection) {
+ QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
+ if (connectionLists && connectionLists->count() > signal_index) {
+ const QObjectPrivate::Connection *c2 =
+ (*connectionLists)[signal_index].first;
+
+ int method_index_absolute = method_index + method_offset;
+
+ while (c2) {
+ if (c2->receiver == receiver && c2->method() == method_index_absolute)
+ return false;
+ c2 = c2->nextConnectionList;
+ }
+ }
+ type &= Qt::UniqueConnection - 1;
+ }
+
+ QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
+ c->sender = s;
+ c->receiver = r;
+ c->method_relative = method_index;
+ c->method_offset = method_offset;
+ c->connectionType = type;
+ c->argumentTypes = types;
+ c->nextConnectionList = 0;
+ c->callFunction = callFunction;
+
+ QT_TRY {
+ QObjectPrivate::get(s)->addConnection(signal_index, c);
+ } QT_CATCH(...) {
+ delete c;
+ QT_RETHROW;
+ }
+
+ c->prev = &(QObjectPrivate::get(r)->senders);
+ c->next = *c->prev;
+ *c->prev = c;
+ if (c->next)
+ c->next->prev = &c->next;
+
+ QObjectPrivate *const sender_d = QObjectPrivate::get(s);
+ if (signal_index < 0) {
+ sender_d->connectedSignals[0] = sender_d->connectedSignals[1] = ~0;
+ } else if (signal_index < (int)sizeof(sender_d->connectedSignals) * 8) {
+ sender_d->connectedSignals[signal_index >> 5] |= (1 << (signal_index & 0x1f));
+ }
+
+ return true;
+}
+
+/*!\internal
+ */
+bool QMetaObject::disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index)
+{
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
+ return QMetaObjectPrivate::disconnect(sender, signal_index,
+ receiver, method_index);
+}
+
+/*!\internal
+
+Disconnect a single signal connection. If QMetaObject::connect() has been called
+multiple times for the same sender, signal_index, receiver and method_index only
+one of these connections will be removed.
+ */
+bool QMetaObject::disconnectOne(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index)
+{
+ signal_index = methodIndexToSignalIndex(sender->metaObject(), signal_index);
+ return QMetaObjectPrivate::disconnect(sender, signal_index,
+ receiver, method_index,
+ QMetaObjectPrivate::DisconnectOne);
+}
+
+/*! \internal
+ Helper function to remove the connection from the senders list and setting the receivers to 0
+ */
+bool QMetaObjectPrivate::disconnectHelper(QObjectPrivate::Connection *c,
+ const QObject *receiver, int method_index,
+ QMutex *senderMutex, DisconnectType disconnectType)
+{
+ bool success = false;
+ while (c) {
+ if (c->receiver
+ && (receiver == 0 || (c->receiver == receiver
+ && (method_index < 0 || c->method() == method_index)))) {
+ bool needToUnlock = false;
+ QMutex *receiverMutex = 0;
+ if (!receiver) {
+ receiverMutex = signalSlotLock(c->receiver);
+ // need to relock this receiver and sender in the correct order
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, receiverMutex);
+ }
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next)
+ c->next->prev = c->prev;
+ }
+
+ if (needToUnlock)
+ receiverMutex->unlockInline();
+
+ c->receiver = 0;
+
+ success = true;
+
+ if (disconnectType == DisconnectOne)
+ return success;
+ }
+ c = c->nextConnectionList;
+ }
+ return success;
+}
+
+/*! \internal
+ Same as the QMetaObject::disconnect, but \a signal_index must be the result of QObjectPrivate::signalIndex
+ */
+bool QMetaObjectPrivate::disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ DisconnectType disconnectType)
+{
+ if (!sender)
+ return false;
+
+ QObject *s = const_cast<QObject *>(sender);
+
+ QMutex *senderMutex = signalSlotLock(sender);
+ QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
+ QOrderedMutexLocker locker(senderMutex, receiverMutex);
+
+ QObjectConnectionListVector *connectionLists = QObjectPrivate::get(s)->connectionLists;
+ if (!connectionLists)
+ return false;
+
+ // prevent incoming connections changing the connectionLists while unlocked
+ ++connectionLists->inUse;
+
+ bool success = false;
+ if (signal_index < 0) {
+ // remove from all connection lists
+ for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
+ QObjectPrivate::Connection *c =
+ (*connectionLists)[signal_index].first;
+ if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
+ success = true;
+ connectionLists->dirty = true;
+ }
+ }
+ } else if (signal_index < connectionLists->count()) {
+ QObjectPrivate::Connection *c =
+ (*connectionLists)[signal_index].first;
+ if (disconnectHelper(c, receiver, method_index, senderMutex, disconnectType)) {
+ success = true;
+ connectionLists->dirty = true;
+ }
+ }
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned && !connectionLists->inUse)
+ delete connectionLists;
+
+ return success;
+}
+
+/*!
+ \fn void QMetaObject::connectSlotsByName(QObject *object)
+
+ Searches recursively for all child objects of the given \a object, and connects
+ matching signals from them to slots of \a object that follow the following form:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 33
+
+ Let's assume our object has a child object of type QPushButton with
+ the \l{QObject::objectName}{object name} \c{button1}. The slot to catch the
+ button's \c{clicked()} signal would be:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 34
+
+ \sa QObject::setObjectName()
+ */
+void QMetaObject::connectSlotsByName(QObject *o)
+{
+ if (!o)
+ return;
+ const QMetaObject *mo = o->metaObject();
+ Q_ASSERT(mo);
+ const QObjectList list = o->findChildren<QObject *>(QString());
+ for (int i = 0; i < mo->methodCount(); ++i) {
+ const char *slot = mo->method(i).signature();
+ Q_ASSERT(slot);
+ if (slot[0] != 'o' || slot[1] != 'n' || slot[2] != '_')
+ continue;
+ bool foundIt = false;
+ for(int j = 0; j < list.count(); ++j) {
+ const QObject *co = list.at(j);
+ QByteArray objName = co->objectName().toAscii();
+ int len = objName.length();
+ if (!len || qstrncmp(slot + 3, objName.data(), len) || slot[len+3] != '_')
+ continue;
+ int sigIndex = co->d_func()->signalIndex(slot + len + 4);
+ if (sigIndex < 0) { // search for compatible signals
+ const QMetaObject *smo = co->metaObject();
+ int slotlen = qstrlen(slot + len + 4) - 1;
+ for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
+ QMetaMethod method = smo->method(k);
+ if (method.methodType() != QMetaMethod::Signal)
+ continue;
+
+ if (!qstrncmp(method.signature(), slot + len + 4, slotlen)) {
+ int signalOffset, methodOffset;
+ computeOffsets(method.enclosingMetaObject(), &signalOffset, &methodOffset);
+ sigIndex = k + - methodOffset + signalOffset;
+ break;
+ }
+ }
+ }
+ if (sigIndex < 0)
+ continue;
+ if (QMetaObjectPrivate::connect(co, sigIndex, o, i)) {
+ foundIt = true;
+ break;
+ }
+ }
+ if (foundIt) {
+ // we found our slot, now skip all overloads
+ while (mo->method(i + 1).attributes() & QMetaMethod::Cloned)
+ ++i;
+ } else if (!(mo->method(i).attributes() & QMetaMethod::Cloned)) {
+ qWarning("QMetaObject::connectSlotsByName: No matching signal for %s", slot);
+ }
+ }
+}
+
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
+{
+ if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ QMetaMethod m = sender->metaObject()->method(signal);
+ int *tmp = queuedConnectionTypes(m.parameterTypes());
+ if (!tmp) // cannot queue arguments
+ tmp = &DIRECT_CONNECTION_ONLY;
+ if (!c->argumentTypes.testAndSetOrdered(0, tmp)) {
+ if (tmp != &DIRECT_CONNECTION_ONLY)
+ delete [] tmp;
+ }
+ }
+ if (c->argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
+ return;
+ int nargs = 1; // include return type
+ while (c->argumentTypes[nargs-1])
+ ++nargs;
+ int *types = (int *) qMalloc(nargs*sizeof(int));
+ Q_CHECK_PTR(types);
+ void **args = (void **) qMalloc(nargs*sizeof(void *));
+ Q_CHECK_PTR(args);
+ types[0] = 0; // return type
+ args[0] = 0; // return value
+ for (int n = 1; n < nargs; ++n)
+ args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
+ QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method_offset,
+ c->method_relative,
+ c->callFunction,
+ sender, signal, nargs,
+ types, args));
+}
+
+
+/*!\internal
+ \obsolete.
+ Used to be called from QMetaObject::activate(QObject *, QMetaObject *, int, int, void **) before Qt 4.6
+ */
+void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
+{
+ Q_UNUSED(to_signal_index);
+ activate(sender, from_signal_index, argv);
+}
+
+/*!\internal
+ */
+void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
+ void **argv)
+{
+ int signalOffset;
+ int methodOffset;
+ computeOffsets(m, &signalOffset, &methodOffset);
+
+ int signal_index = signalOffset + local_signal_index;
+
+ if (!sender->d_func()->isSignalConnected(signal_index))
+ return; // nothing connected to these signals, and no spy
+
+ if (sender->d_func()->blockSig)
+ return;
+
+ int signal_absolute_index = methodOffset + local_signal_index;
+
+ void *empty_argv[] = { 0 };
+ if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
+ qt_signal_spy_callback_set.signal_begin_callback(sender, signal_absolute_index,
+ argv ? argv : empty_argv);
+ }
+
+ Qt::HANDLE currentThreadId = QThread::currentThreadId();
+
+ QMutexLocker locker(signalSlotLock(sender));
+ QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
+ if (!connectionLists) {
+ locker.unlock();
+ if (qt_signal_spy_callback_set.signal_end_callback != 0)
+ qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
+ return;
+ }
+ ++connectionLists->inUse;
+
+
+ const QObjectPrivate::ConnectionList *list;
+ if (signal_index < connectionLists->count())
+ list = &connectionLists->at(signal_index);
+ else
+ list = &connectionLists->allsignals;
+
+ do {
+ QObjectPrivate::Connection *c = list->first;
+ if (!c) continue;
+ // We need to check against last here to ensure that signals added
+ // during the signal emission are not emitted in this emission.
+ QObjectPrivate::Connection *last = list->last;
+
+ do {
+ if (!c->receiver)
+ continue;
+
+ QObject * const receiver = c->receiver;
+ const bool receiverInSameThread = currentThreadId == receiver->d_func()->threadData->threadId;
+
+ // determine if this connection should be sent immediately or
+ // put into the event queue
+ if ((c->connectionType == Qt::AutoConnection && !receiverInSameThread)
+ || (c->connectionType == Qt::QueuedConnection)) {
+ queued_activate(sender, signal_absolute_index, c, argv ? argv : empty_argv);
+ continue;
+#ifndef QT_NO_THREAD
+ } else if (c->connectionType == Qt::BlockingQueuedConnection) {
+ locker.unlock();
+ if (receiverInSameThread) {
+ qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
+ "Sender is %s(%p), receiver is %s(%p)",
+ sender->metaObject()->className(), sender,
+ receiver->metaObject()->className(), receiver);
+ }
+ QSemaphore semaphore;
+ QCoreApplication::postEvent(receiver, new QMetaCallEvent(c->method_offset, c->method_relative,
+ c->callFunction,
+ sender, signal_absolute_index,
+ 0, 0,
+ argv ? argv : empty_argv,
+ &semaphore));
+ semaphore.acquire();
+ locker.relock();
+ continue;
+#endif
+ }
+
+ QObjectPrivate::Sender currentSender;
+ QObjectPrivate::Sender *previousSender = 0;
+ if (receiverInSameThread) {
+ currentSender.sender = sender;
+ currentSender.signal = signal_absolute_index;
+ currentSender.ref = 1;
+ previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
+ }
+ const QObjectPrivate::StaticMetaCallFunction callFunction = c->callFunction;
+ const int method_relative = c->method_relative;
+ if (callFunction && c->method_offset <= receiver->metaObject()->methodOffset()) {
+ //we compare the vtable to make sure we are not in the destructor of the object.
+ locker.unlock();
+ if (qt_signal_spy_callback_set.slot_begin_callback != 0)
+ qt_signal_spy_callback_set.slot_begin_callback(receiver, c->method(), argv ? argv : empty_argv);
+
+ callFunction(receiver, QMetaObject::InvokeMetaMethod, method_relative, argv ? argv : empty_argv);
+
+ if (qt_signal_spy_callback_set.slot_end_callback != 0)
+ qt_signal_spy_callback_set.slot_end_callback(receiver, c->method());
+ locker.relock();
+ } else {
+ const int method = method_relative + c->method_offset;
+ locker.unlock();
+
+ if (qt_signal_spy_callback_set.slot_begin_callback != 0) {
+ qt_signal_spy_callback_set.slot_begin_callback(receiver,
+ method,
+ argv ? argv : empty_argv);
+ }
+
+#if defined(QT_NO_EXCEPTIONS)
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+#else
+ QT_TRY {
+ metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ } QT_CATCH(...) {
+ locker.relock();
+ if (receiverInSameThread)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned && !connectionLists->inUse)
+ delete connectionLists;
+ QT_RETHROW;
+ }
+#endif
+
+ if (qt_signal_spy_callback_set.slot_end_callback != 0)
+ qt_signal_spy_callback_set.slot_end_callback(receiver, method);
+
+ locker.relock();
+ }
+
+ if (receiverInSameThread)
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+
+ if (connectionLists->orphaned)
+ break;
+ } while (c != last && (c = c->nextConnectionList) != 0);
+
+ if (connectionLists->orphaned)
+ break;
+ } while (list != &connectionLists->allsignals &&
+ //start over for all signals;
+ ((list = &connectionLists->allsignals), true));
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned) {
+ if (!connectionLists->inUse)
+ delete connectionLists;
+ } else if (connectionLists->dirty) {
+ sender->d_func()->cleanConnectionLists();
+ }
+
+ locker.unlock();
+
+ if (qt_signal_spy_callback_set.signal_end_callback != 0)
+ qt_signal_spy_callback_set.signal_end_callback(sender, signal_absolute_index);
+
+}
+
+/*!\internal
+ Obsolete. (signal_index comes from indexOfMethod())
+*/
+void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
+{
+ const QMetaObject *mo = sender->metaObject();
+ while (mo->methodOffset() > signal_index)
+ mo = mo->superClass();
+ activate(sender, mo, signal_index - mo->methodOffset(), argv);
+}
+
+/*!\internal
+ Obsolete, called by moc generated code before Qt 4.6 for cloned signals
+ But since Qt 4.6, all clones are connected to their original
+ */
+void QMetaObject::activate(QObject *sender, const QMetaObject *m,
+ int from_local_signal_index, int to_local_signal_index, void **argv)
+{
+ Q_UNUSED(to_local_signal_index);
+ Q_ASSERT(from_local_signal_index == QMetaObjectPrivate::originalClone(m, to_local_signal_index));
+ activate(sender, m, from_local_signal_index, argv);
+}
+
+/*! \internal
+ Returns the signal index used in the internal connectionLists vector.
+
+ It is different from QMetaObject::indexOfSignal(): indexOfSignal is the same as indexOfMethod
+ while QObjectPrivate::signalIndex is smaller because it doesn't give index to slots.
+*/
+int QObjectPrivate::signalIndex(const char *signalName) const
+{
+ Q_Q(const QObject);
+ const QMetaObject *base = q->metaObject();
+ int relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, false);
+ if (relative_index < 0)
+ relative_index = QMetaObjectPrivate::indexOfSignalRelative(&base, signalName, true);
+ if (relative_index < 0)
+ return relative_index;
+ relative_index = QMetaObjectPrivate::originalClone(base, relative_index);
+ int signalOffset, methodOffset;
+ computeOffsets(base, &signalOffset, &methodOffset);
+ return relative_index + signalOffset;
+}
+
+/*****************************************************************************
+ Properties
+ *****************************************************************************/
+
+#ifndef QT_NO_PROPERTIES
+
+/*!
+ Sets the value of the object's \a name property to \a value.
+
+ If the property is defined in the class using Q_PROPERTY then
+ true is returned on success and false otherwise. If the property
+ is not defined using Q_PROPERTY, and therefore not listed in the
+ meta-object, it is added as a dynamic property and false is returned.
+
+ Information about all available properties is provided through the
+ metaObject() and dynamicPropertyNames().
+
+ Dynamic properties can be queried again using property() and can be
+ removed by setting the property value to an invalid QVariant.
+ Changing the value of a dynamic property causes a QDynamicPropertyChangeEvent
+ to be sent to the object.
+
+ \bold{Note:} Dynamic properties starting with "_q_" are reserved for internal
+ purposes.
+
+ \sa property(), metaObject(), dynamicPropertyNames()
+*/
+bool QObject::setProperty(const char *name, const QVariant &value)
+{
+ Q_D(QObject);
+ const QMetaObject* meta = metaObject();
+ if (!name || !meta)
+ return false;
+
+ int id = meta->indexOfProperty(name);
+ if (id < 0) {
+ if (!d->extraData)
+ d->extraData = new QObjectPrivate::ExtraData;
+
+ const int idx = d->extraData->propertyNames.indexOf(name);
+
+ if (!value.isValid()) {
+ if (idx == -1)
+ return false;
+ d->extraData->propertyNames.removeAt(idx);
+ d->extraData->propertyValues.removeAt(idx);
+ } else {
+ if (idx == -1) {
+ d->extraData->propertyNames.append(name);
+ d->extraData->propertyValues.append(value);
+ } else {
+ d->extraData->propertyValues[idx] = value;
+ }
+ }
+
+ QDynamicPropertyChangeEvent ev(name);
+ QCoreApplication::sendEvent(this, &ev);
+
+ return false;
+ }
+ QMetaProperty p = meta->property(id);
+#ifndef QT_NO_DEBUG
+ if (!p.isWritable())
+ qWarning("%s::setProperty: Property \"%s\" invalid,"
+ " read-only or does not exist", metaObject()->className(), name);
+#endif
+ return p.write(this, value);
+}
+
+/*!
+ Returns the value of the object's \a name property.
+
+ If no such property exists, the returned variant is invalid.
+
+ Information about all available properties is provided through the
+ metaObject() and dynamicPropertyNames().
+
+ \sa setProperty(), QVariant::isValid(), metaObject(), dynamicPropertyNames()
+*/
+QVariant QObject::property(const char *name) const
+{
+ Q_D(const QObject);
+ const QMetaObject* meta = metaObject();
+ if (!name || !meta)
+ return QVariant();
+
+ int id = meta->indexOfProperty(name);
+ if (id < 0) {
+ if (!d->extraData)
+ return QVariant();
+ const int i = d->extraData->propertyNames.indexOf(name);
+ return d->extraData->propertyValues.value(i);
+ }
+ QMetaProperty p = meta->property(id);
+#ifndef QT_NO_DEBUG
+ if (!p.isReadable())
+ qWarning("%s::property: Property \"%s\" invalid or does not exist",
+ metaObject()->className(), name);
+#endif
+ return p.read(this);
+}
+
+/*!
+ \since 4.2
+
+ Returns the names of all properties that were dynamically added to
+ the object using setProperty().
+*/
+QList<QByteArray> QObject::dynamicPropertyNames() const
+{
+ Q_D(const QObject);
+ if (d->extraData)
+ return d->extraData->propertyNames;
+ return QList<QByteArray>();
+}
+
+#endif // QT_NO_PROPERTIES
+
+
+/*****************************************************************************
+ QObject debugging output routines.
+ *****************************************************************************/
+
+static void dumpRecursive(int level, QObject *object)
+{
+#if defined(QT_DEBUG)
+ if (object) {
+ QByteArray buf;
+ buf.fill(' ', level / 2 * 8);
+ if (level % 2)
+ buf += " ";
+ QString name = object->objectName();
+ QString flags = QLatin1String("");
+#if 0
+ if (qApp->focusWidget() == object)
+ flags += 'F';
+ if (object->isWidgetType()) {
+ QWidget * w = (QWidget *)object;
+ if (w->isVisible()) {
+ QString t("<%1,%2,%3,%4>");
+ flags += t.arg(w->x()).arg(w->y()).arg(w->width()).arg(w->height());
+ } else {
+ flags += 'I';
+ }
+ }
+#endif
+ qDebug("%s%s::%s %s", (const char*)buf, object->metaObject()->className(), name.toLocal8Bit().data(),
+ flags.toLatin1().data());
+ QObjectList children = object->children();
+ if (!children.isEmpty()) {
+ for (int i = 0; i < children.size(); ++i)
+ dumpRecursive(level+1, children.at(i));
+ }
+ }
+#else
+ Q_UNUSED(level)
+ Q_UNUSED(object)
+#endif
+}
+
+/*!
+ Dumps a tree of children to the debug output.
+
+ This function is useful for debugging, but does nothing if the
+ library has been compiled in release mode (i.e. without debugging
+ information).
+
+ \sa dumpObjectInfo()
+*/
+
+void QObject::dumpObjectTree()
+{
+ dumpRecursive(0, this);
+}
+
+/*!
+ Dumps information about signal connections, etc. for this object
+ to the debug output.
+
+ This function is useful for debugging, but does nothing if the
+ library has been compiled in release mode (i.e. without debugging
+ information).
+
+ \sa dumpObjectTree()
+*/
+
+void QObject::dumpObjectInfo()
+{
+#if defined(QT_DEBUG)
+ qDebug("OBJECT %s::%s", metaObject()->className(),
+ objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
+
+ Q_D(QObject);
+ QMutexLocker locker(signalSlotLock(this));
+
+ // first, look for connections where this object is the sender
+ qDebug(" SIGNALS OUT");
+
+ if (d->connectionLists) {
+ int offset = 0;
+ int offsetToNextMetaObject = 0;
+ for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) {
+ if (signal_index >= offsetToNextMetaObject) {
+ const QMetaObject *mo = metaObject();
+ int signalOffset, methodOffset;
+ computeOffsets(mo, &signalOffset, &methodOffset);
+ while (signalOffset > signal_index) {
+ mo = mo->superClass();
+ offsetToNextMetaObject = signalOffset;
+ computeOffsets(mo, &signalOffset, &methodOffset);
+ }
+ offset = methodOffset - signalOffset;
+ }
+ const QMetaMethod signal = metaObject()->method(signal_index + offset);
+ qDebug(" signal: %s", signal.signature());
+
+ // receivers
+ const QObjectPrivate::Connection *c =
+ d->connectionLists->at(signal_index).first;
+ while (c) {
+ if (!c->receiver) {
+ qDebug(" <Disconnected receiver>");
+ c = c->nextConnectionList;
+ continue;
+ }
+ const QMetaObject *receiverMetaObject = c->receiver->metaObject();
+ const QMetaMethod method = receiverMetaObject->method(c->method());
+ qDebug(" --> %s::%s %s",
+ receiverMetaObject->className(),
+ c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
+ method.signature());
+ c = c->nextConnectionList;
+ }
+ }
+ } else {
+ qDebug( " <None>" );
+ }
+
+ // now look for connections where this object is the receiver
+ qDebug(" SIGNALS IN");
+
+ if (d->senders) {
+ for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
+ const QMetaMethod slot = metaObject()->method(s->method());
+ qDebug(" <-- %s::%s %s",
+ s->sender->metaObject()->className(),
+ s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
+ slot.signature());
+ }
+ } else {
+ qDebug(" <None>");
+ }
+#endif
+}
+
+#ifndef QT_NO_USERDATA
+/*!\internal
+ */
+uint QObject::registerUserData()
+{
+ static int user_data_registration = 0;
+ return user_data_registration++;
+}
+
+/*!\internal
+ */
+QObjectUserData::~QObjectUserData()
+{
+}
+
+/*!\internal
+ */
+void QObject::setUserData(uint id, QObjectUserData* data)
+{
+ Q_D(QObject);
+ if (!d->extraData)
+ d->extraData = new QObjectPrivate::ExtraData;
+
+ if (d->extraData->userData.size() <= (int) id)
+ d->extraData->userData.resize((int) id + 1);
+ d->extraData->userData[id] = data;
+}
+
+/*!\internal
+ */
+QObjectUserData* QObject::userData(uint id) const
+{
+ Q_D(const QObject);
+ if (!d->extraData)
+ return 0;
+ if ((int)id < d->extraData->userData.size())
+ return d->extraData->userData.at(id);
+ return 0;
+}
+
+#endif // QT_NO_USERDATA
+
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QObject *o) {
+#ifndef Q_BROKEN_DEBUG_STREAM
+ if (!o)
+ return dbg << "QObject(0x0) ";
+ dbg.nospace() << o->metaObject()->className() << '(' << (void *)o;
+ if (!o->objectName().isEmpty())
+ dbg << ", name = " << o->objectName();
+ dbg << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QObject to QDebug");
+ return dbg;
+ Q_UNUSED(o);
+#endif
+}
+#endif
+
+/*!
+ \fn void QObject::insertChild(QObject *object)
+
+ Use setParent() instead, i.e., call object->setParent(this).
+*/
+
+/*!
+ \fn void QObject::removeChild(QObject *object)
+
+ Use setParent() instead, i.e., call object->setParent(0).
+*/
+
+/*!
+ \fn bool QObject::isA(const char *className) const
+
+ Compare \a className with the object's metaObject()->className() instead.
+*/
+
+/*!
+ \fn const char *QObject::className() const
+
+ Use metaObject()->className() instead.
+*/
+
+/*!
+ \fn const char *QObject::name() const
+
+ Use objectName() instead.
+*/
+
+/*!
+ \fn const char *QObject::name(const char *defaultName) const
+
+ Use objectName() instead.
+*/
+
+/*!
+ \fn void QObject::setName(const char *name)
+
+ Use setObjectName() instead.
+*/
+
+/*!
+ \fn bool QObject::checkConnectArgs(const char *signal, const
+ QObject *object, const char *method)
+
+ Use QMetaObject::checkConnectArgs() instead.
+*/
+
+/*!
+ \fn QByteArray QObject::normalizeSignalSlot(const char *signalSlot)
+
+ Use QMetaObject::normalizedSignature() instead.
+*/
+
+/*!
+ \fn const char *QMetaObject::superClassName() const
+
+ \internal
+*/
+
+/*!
+ \macro Q_CLASSINFO(Name, Value)
+ \relates QObject
+
+ This macro associates extra information to the class, which is
+ available using QObject::metaObject(). Except for the ActiveQt
+ extension, Qt doesn't use this information.
+
+ The extra information takes the form of a \a Name string and a \a
+ Value literal string.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 35
+
+ \sa QMetaObject::classInfo()
+*/
+
+/*!
+ \macro Q_INTERFACES(...)
+ \relates QObject
+
+ This macro tells Qt which interfaces the class implements. This
+ is used when implementing plugins.
+
+ Example:
+
+ \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 1
+ \dots
+ \snippet examples/tools/plugandpaintplugins/basictools/basictoolsplugin.h 3
+
+ See the \l{tools/plugandpaintplugins/basictools}{Plug & Paint
+ Basic Tools} example for details.
+
+ \sa Q_DECLARE_INTERFACE(), Q_EXPORT_PLUGIN2(), {How to Create Qt Plugins}
+*/
+
+/*!
+ \macro Q_PROPERTY(...)
+ \relates QObject
+
+ This macro is used for declaring properties in classes that
+ inherit QObject. Properties behave like class data members, but
+ they have additional features accessible through the \l
+ {Meta-Object System}.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 36
+
+ The property name and type and the \c READ function are required.
+ The type can be any type supported by QVariant, or it can be a
+ user-defined type. The other items are optional, but a \c WRITE
+ function is common. The attributes default to true except \c USER,
+ which defaults to false.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 37
+
+ For more details about how to use this macro, and a more detailed
+ example of its use, see the discussion on \l {Qt's Property System}.
+
+ \sa {Qt's Property System}
+*/
+
+/*!
+ \macro Q_ENUMS(...)
+ \relates QObject
+
+ This macro registers one or several enum types to the meta-object
+ system.
+
+ For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 38
+
+ If you want to register an enum that is declared in another class,
+ the enum must be fully qualified with the name of the class
+ defining it. In addition, the class \e defining the enum has to
+ inherit QObject as well as declare the enum using Q_ENUMS().
+
+ \sa {Qt's Property System}
+*/
+
+/*!
+ \macro Q_FLAGS(...)
+ \relates QObject
+
+ This macro registers one or several \l{QFlags}{flags types} to the
+ meta-object system. It is typically used in a class definition to declare
+ that values of a given enum can be used as flags and combined using the
+ bitwise OR operator.
+
+ For example, in QLibrary, the \l{QLibrary::LoadHints}{LoadHints} flag is
+ declared in the following way:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39a
+
+ The declaration of the flags themselves is performed in the public section
+ of the QLibrary class itself, using the \l Q_DECLARE_FLAGS() macro:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39b
+
+ \note This macro takes care of registering individual flag values
+ with the meta-object system, so it is unnecessary to use Q_ENUMS()
+ in addition to this macro.
+
+ \sa {Qt's Property System}
+*/
+
+/*!
+ \macro Q_OBJECT
+ \relates QObject
+
+ The Q_OBJECT macro must appear in the private section of a class
+ definition that declares its own signals and slots or that uses
+ other services provided by Qt's meta-object system.
+
+ For example:
+
+ \snippet doc/src/snippets/signalsandslots/signalsandslots.h 1
+ \codeline
+ \snippet doc/src/snippets/signalsandslots/signalsandslots.h 2
+ \snippet doc/src/snippets/signalsandslots/signalsandslots.h 3
+
+ \note This macro requires the class to be a subclass of QObject. Use
+ Q_GADGET instead of Q_OBJECT to enable the meta object system's support
+ for enums in a class that is not a QObject subclass. Q_GADGET makes a
+ class member, \c{staticMetaObject}, available.
+ \c{staticMetaObject} is of type QMetaObject and provides access to the
+ enums declared with Q_ENUMS.
+ Q_GADGET is provided only for C++.
+
+ \sa {Meta-Object System}, {Signals and Slots}, {Qt's Property System}
+*/
+
+/*!
+ \macro Q_SIGNALS
+ \relates QObject
+
+ Use this macro to replace the \c signals keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_SIGNAL
+ \relates QObject
+
+ This is an additional macro that allows you to mark a single
+ function as a signal. It can be quite useful, especially when you
+ use a 3rd-party source code parser which doesn't understand a \c
+ signals or \c Q_SIGNALS groups.
+
+ Use this macro to replace the \c signals keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_SLOTS
+ \relates QObject
+
+ Use this macro to replace the \c slots keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_SLOT
+ \relates QObject
+
+ This is an additional macro that allows you to mark a single
+ function as a slot. It can be quite useful, especially when you
+ use a 3rd-party source code parser which doesn't understand a \c
+ slots or \c Q_SLOTS groups.
+
+ Use this macro to replace the \c slots keyword in class
+ declarations, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_EMIT
+ \relates QObject
+
+ Use this macro to replace the \c emit keyword for emitting
+ signals, when you want to use Qt Signals and Slots with a
+ \l{3rd Party Signals and Slots} {3rd party signal/slot mechanism}.
+
+ The macro is normally used when \c no_keywords is specified with
+ the \c CONFIG variable in the \c .pro file, but it can be used
+ even when \c no_keywords is \e not specified.
+*/
+
+/*!
+ \macro Q_INVOKABLE
+ \relates QObject
+
+ Apply this macro to definitions of member functions to allow them to
+ be invoked via the meta-object system. The macro is written before
+ the return type, as shown in the following example:
+
+ \snippet snippets/qmetaobject-invokable/window.h Window class with invokable method
+
+ The \c invokableMethod() function is marked up using Q_INVOKABLE, causing
+ it to be registered with the meta-object system and enabling it to be
+ invoked using QMetaObject::invokeMethod().
+ Since \c normalMethod() function is not registered in this way, it cannot
+ be invoked using QMetaObject::invokeMethod().
+*/
+
+/*!
+ \typedef QObjectList
+ \relates QObject
+
+ Synonym for QList<QObject *>.
+*/
+
+void qDeleteInEventHandler(QObject *o)
+{
+#ifdef QT_JAMBI_BUILD
+ if (!o)
+ return;
+ QObjectPrivate::get(o)->inEventHandler = false;
+#endif
+ delete o;
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qobject.cpp"
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
new file mode 100644
index 0000000000..0ad73f5fe9
--- /dev/null
+++ b/src/corelib/kernel/qobject.h
@@ -0,0 +1,411 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QOBJECT_H
+#define QOBJECT_H
+
+#ifndef QT_NO_QOBJECT
+
+#include <QtCore/qobjectdefs.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#ifdef QT_INCLUDE_COMPAT
+#include <QtCore/qcoreevent.h>
+#endif
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEvent;
+class QTimerEvent;
+class QChildEvent;
+struct QMetaObject;
+class QVariant;
+class QObjectPrivate;
+class QObject;
+class QThread;
+class QWidget;
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+#ifndef QT_NO_USERDATA
+class QObjectUserData;
+#endif
+
+typedef QList<QObject*> QObjectList;
+
+Q_CORE_EXPORT void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re,
+ const QMetaObject &mo, QList<void *> *list);
+Q_CORE_EXPORT QObject *qt_qFindChild_helper(const QObject *parent, const QString &name, const QMetaObject &mo);
+
+class
+#if defined(__INTEL_COMPILER) && defined(Q_OS_WIN)
+Q_CORE_EXPORT
+#endif
+QObjectData {
+public:
+ virtual ~QObjectData() = 0;
+ QObject *q_ptr;
+ QObject *parent;
+ QObjectList children;
+
+ uint isWidget : 1;
+ uint pendTimer : 1;
+ uint blockSig : 1;
+ uint wasDeleted : 1;
+ uint ownObjectName : 1;
+ uint sendChildEvents : 1;
+ uint receiveChildEvents : 1;
+ uint inEventHandler : 1; //only used if QT_JAMBI_BUILD
+ uint inThreadChangeEvent : 1;
+ uint hasGuards : 1; //true iff there is one or more QPointer attached to this object
+ uint unused : 22;
+ int postedEvents;
+ QMetaObject *metaObject; // assert dynamic
+};
+
+
+class Q_CORE_EXPORT QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString objectName READ objectName WRITE setObjectName)
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ Q_INVOKABLE explicit QObject(QObject *parent=0);
+ virtual ~QObject();
+
+ virtual bool event(QEvent *);
+ virtual bool eventFilter(QObject *, QEvent *);
+
+#ifdef qdoc
+ static QString tr(const char *sourceText, const char *comment = 0, int n = -1);
+ static QString trUtf8(const char *sourceText, const char *comment = 0, int n = -1);
+ virtual const QMetaObject *metaObject() const;
+ static const QMetaObject staticMetaObject;
+#endif
+#ifdef QT_NO_TRANSLATION
+ static QString tr(const char *sourceText, const char *, int)
+ { return QString::fromLatin1(sourceText); }
+ static QString tr(const char *sourceText, const char * = 0)
+ { return QString::fromLatin1(sourceText); }
+#ifndef QT_NO_TEXTCODEC
+ static QString trUtf8(const char *sourceText, const char *, int)
+ { return QString::fromUtf8(sourceText); }
+ static QString trUtf8(const char *sourceText, const char * = 0)
+ { return QString::fromUtf8(sourceText); }
+#endif
+#endif //QT_NO_TRANSLATION
+
+ QString objectName() const;
+ void setObjectName(const QString &name);
+
+ inline bool isWidgetType() const { return d_ptr->isWidget; }
+
+ inline bool signalsBlocked() const { return d_ptr->blockSig; }
+ bool blockSignals(bool b);
+
+ QThread *thread() const;
+ void moveToThread(QThread *thread);
+
+ int startTimer(int interval);
+ void killTimer(int id);
+
+ template<typename T>
+ inline T findChild(const QString &aName = QString()) const
+ { return static_cast<T>(qt_qFindChild_helper(this, aName, reinterpret_cast<T>(0)->staticMetaObject)); }
+
+ template<typename T>
+ inline QList<T> findChildren(const QString &aName = QString()) const
+ {
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(this, aName, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList);
+ return list;
+ }
+
+#ifndef QT_NO_REGEXP
+ template<typename T>
+ inline QList<T> findChildren(const QRegExp &re) const
+ {
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(this, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList);
+ return list;
+ }
+#endif
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT QObject *child(const char *objName, const char *inheritsClass = 0,
+ bool recursiveSearch = true) const;
+ QT3_SUPPORT QObjectList queryList(const char *inheritsClass = 0,
+ const char *objName = 0,
+ bool regexpMatch = true,
+ bool recursiveSearch = true) const;
+#endif
+ inline const QObjectList &children() const { return d_ptr->children; }
+
+ void setParent(QObject *);
+ void installEventFilter(QObject *);
+ void removeEventFilter(QObject *);
+
+
+ static bool connect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *member, Qt::ConnectionType =
+#ifdef qdoc
+ Qt::AutoConnection
+#else
+#ifdef QT3_SUPPORT
+ Qt::AutoCompatConnection
+#else
+ Qt::AutoConnection
+#endif
+#endif
+ );
+
+ static bool connect(const QObject *sender, const QMetaMethod &signal,
+ const QObject *receiver, const QMetaMethod &method,
+ Qt::ConnectionType type =
+#ifdef qdoc
+ Qt::AutoConnection
+#else
+#ifdef QT3_SUPPORT
+ Qt::AutoCompatConnection
+#else
+ Qt::AutoConnection
+#endif
+#endif
+ );
+
+ inline bool connect(const QObject *sender, const char *signal,
+ const char *member, Qt::ConnectionType type =
+#ifdef qdoc
+ Qt::AutoConnection
+#else
+#ifdef QT3_SUPPORT
+ Qt::AutoCompatConnection
+#else
+ Qt::AutoConnection
+#endif
+#endif
+ ) const;
+
+ static bool disconnect(const QObject *sender, const char *signal,
+ const QObject *receiver, const char *member);
+ static bool disconnect(const QObject *sender, const QMetaMethod &signal,
+ const QObject *receiver, const QMetaMethod &member);
+ inline bool disconnect(const char *signal = 0,
+ const QObject *receiver = 0, const char *member = 0)
+ { return disconnect(this, signal, receiver, member); }
+ inline bool disconnect(const QObject *receiver, const char *member = 0)
+ { return disconnect(this, 0, receiver, member); }
+
+ void dumpObjectTree();
+ void dumpObjectInfo();
+
+#ifndef QT_NO_PROPERTIES
+ bool setProperty(const char *name, const QVariant &value);
+ QVariant property(const char *name) const;
+ QList<QByteArray> dynamicPropertyNames() const;
+#endif // QT_NO_PROPERTIES
+
+#ifndef QT_NO_USERDATA
+ static uint registerUserData();
+ void setUserData(uint id, QObjectUserData* data);
+ QObjectUserData* userData(uint id) const;
+#endif // QT_NO_USERDATA
+
+Q_SIGNALS:
+ void destroyed(QObject * = 0);
+
+public:
+ inline QObject *parent() const { return d_ptr->parent; }
+
+ inline bool inherits(const char *classname) const
+ { return const_cast<QObject *>(this)->qt_metacast(classname) != 0; }
+
+public Q_SLOTS:
+ void deleteLater();
+
+protected:
+ QObject *sender() const;
+ int senderSignalIndex() const;
+ int receivers(const char* signal) const;
+
+ virtual void timerEvent(QTimerEvent *);
+ virtual void childEvent(QChildEvent *);
+ virtual void customEvent(QEvent *);
+
+ virtual void connectNotify(const char *signal);
+ virtual void disconnectNotify(const char *signal);
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT_CONSTRUCTOR QObject(QObject *parent, const char *name);
+ inline QT3_SUPPORT void insertChild(QObject *o)
+ { if (o) o->setParent(this); }
+ inline QT3_SUPPORT void removeChild(QObject *o)
+ { if (o) o->setParent(0); }
+ inline QT3_SUPPORT bool isA(const char *classname) const
+ { return qstrcmp(classname, metaObject()->className()) == 0; }
+ inline QT3_SUPPORT const char *className() const { return metaObject()->className(); }
+ inline QT3_SUPPORT const char *name() const { return objectName().latin1_helper(); }
+ inline QT3_SUPPORT const char *name(const char *defaultName) const
+ { QString s = objectName(); return s.isEmpty()?defaultName:s.latin1_helper(); }
+ inline QT3_SUPPORT void setName(const char *aName) { setObjectName(QLatin1String(aName)); }
+protected:
+ inline QT3_SUPPORT bool checkConnectArgs(const char *signal,
+ const QObject *,
+ const char *member)
+ { return QMetaObject::checkConnectArgs(signal, member); }
+ static inline QT3_SUPPORT QByteArray normalizeSignalSlot(const char *signalSlot)
+ { return QMetaObject::normalizedSignature(signalSlot); }
+#endif
+
+protected:
+ QObject(QObjectPrivate &dd, QObject *parent = 0);
+
+protected:
+ QScopedPointer<QObjectData> d_ptr;
+
+ static const QMetaObject staticQtMetaObject;
+
+ friend struct QMetaObject;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QCoreApplication;
+ friend class QCoreApplicationPrivate;
+ friend class QWidget;
+ friend class QThreadData;
+
+private:
+ Q_DISABLE_COPY(QObject)
+ Q_PRIVATE_SLOT(d_func(), void _q_reregisterTimers(void *))
+};
+
+inline bool QObject::connect(const QObject *asender, const char *asignal,
+ const char *amember, Qt::ConnectionType atype) const
+{ return connect(asender, asignal, this, amember, atype); }
+
+#ifndef QT_NO_USERDATA
+class Q_CORE_EXPORT QObjectUserData {
+public:
+ virtual ~QObjectUserData();
+};
+#endif
+
+#ifdef QT_DEPRECATED
+template<typename T>
+inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString())
+{ return o->findChild<T>(name); }
+
+template<typename T>
+inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QString &name = QString())
+{
+ return o->findChildren<T>(name);
+}
+
+#ifndef QT_NO_REGEXP
+template<typename T>
+inline QT_DEPRECATED QList<T> qFindChildren(const QObject *o, const QRegExp &re)
+{
+ return o->findChildren<T>(re);
+}
+#endif
+
+#endif //QT_DEPRECATED
+
+template <class T>
+inline T qobject_cast(QObject *object)
+{
+#if !defined(QT_NO_QOBJECT_CHECK)
+ reinterpret_cast<T>(object)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object));
+#endif
+ return static_cast<T>(reinterpret_cast<T>(object)->staticMetaObject.cast(object));
+}
+
+template <class T>
+inline T qobject_cast(const QObject *object)
+{
+#if !defined(QT_NO_QOBJECT_CHECK)
+ reinterpret_cast<T>(object)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
+#endif
+ return static_cast<T>(reinterpret_cast<T>(object)->staticMetaObject.cast(object));
+}
+
+
+template <class T> inline const char * qobject_interface_iid()
+{ return 0; }
+
+#ifndef Q_MOC_RUN
+# define Q_DECLARE_INTERFACE(IFace, IId) \
+ template <> inline const char *qobject_interface_iid<IFace *>() \
+ { return IId; } \
+ template <> inline IFace *qobject_cast<IFace *>(QObject *object) \
+ { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \
+ template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \
+ { return reinterpret_cast<IFace *>((object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0)); }
+#endif // Q_MOC_RUN
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
+
+#endif // QOBJECT_H
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
new file mode 100644
index 0000000000..2711a4b5f5
--- /dev/null
+++ b/src/corelib/kernel/qobject_p.h
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QOBJECT_P_H
+#define QOBJECT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qobject.h"
+#include "QtCore/qpointer.h"
+#include "QtCore/qsharedpointer.h"
+#include "QtCore/qcoreevent.h"
+#include "QtCore/qlist.h"
+#include "QtCore/qvector.h"
+#include "QtCore/qreadwritelock.h"
+#include "QtCore/qvariant.h"
+
+QT_BEGIN_NAMESPACE
+
+class QVariant;
+class QThreadData;
+class QObjectConnectionListVector;
+namespace QtSharedPointer { struct ExternalRefCountData; }
+
+/* mirrored in QtTestLib, DON'T CHANGE without prior warning */
+struct QSignalSpyCallbackSet
+{
+ typedef void (*BeginCallback)(QObject *caller, int method_index, void **argv);
+ typedef void (*EndCallback)(QObject *caller, int method_index);
+ BeginCallback signal_begin_callback,
+ slot_begin_callback;
+ EndCallback signal_end_callback,
+ slot_end_callback;
+};
+void Q_CORE_EXPORT qt_register_signal_spy_callbacks(const QSignalSpyCallbackSet &callback_set);
+
+extern QSignalSpyCallbackSet Q_CORE_EXPORT qt_signal_spy_callback_set;
+
+enum { QObjectPrivateVersion = QT_VERSION };
+
+class Q_CORE_EXPORT QAbstractDeclarativeData
+{
+public:
+ static void (*destroyed)(QAbstractDeclarativeData *, QObject *);
+ static void (*parentChanged)(QAbstractDeclarativeData *, QObject *, QObject *);
+ static void (*objectNameChanged)(QAbstractDeclarativeData *, QObject *);
+};
+
+class Q_CORE_EXPORT QObjectPrivate : public QObjectData
+{
+ Q_DECLARE_PUBLIC(QObject)
+
+public:
+ struct ExtraData
+ {
+ ExtraData() {}
+#ifndef QT_NO_USERDATA
+ QVector<QObjectUserData *> userData;
+#endif
+ QList<QByteArray> propertyNames;
+ QList<QVariant> propertyValues;
+ };
+
+ typedef void (*StaticMetaCallFunction)(QObject *, QMetaObject::Call, int, void **);
+ struct Connection
+ {
+ QObject *sender;
+ QObject *receiver;
+ StaticMetaCallFunction callFunction;
+ // The next pointer for the singly-linked ConnectionList
+ Connection *nextConnectionList;
+ //senders linked list
+ Connection *next;
+ Connection **prev;
+ QBasicAtomicPointer<int> argumentTypes;
+ ushort method_offset;
+ ushort method_relative;
+ ushort connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
+ ~Connection();
+ int method() const { return method_offset + method_relative; }
+ };
+ // ConnectionList is a singly-linked list
+ struct ConnectionList {
+ ConnectionList() : first(0), last(0) {}
+ Connection *first;
+ Connection *last;
+ };
+
+ struct Sender
+ {
+ QObject *sender;
+ int signal;
+ int ref;
+ };
+
+
+ QObjectPrivate(int version = QObjectPrivateVersion);
+ virtual ~QObjectPrivate();
+ void deleteChildren();
+
+ void setParent_helper(QObject *);
+ void moveToThread_helper();
+ void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
+ void _q_reregisterTimers(void *pointer);
+
+ bool isSender(const QObject *receiver, const char *signal) const;
+ QObjectList receiverList(const char *signal) const;
+ QObjectList senderList() const;
+
+ void addConnection(int signal, Connection *c);
+ void cleanConnectionLists();
+
+#ifdef QT3_SUPPORT
+ void sendPendingChildInsertedEvents();
+#endif
+
+ static inline Sender *setCurrentSender(QObject *receiver,
+ Sender *sender);
+ static inline void resetCurrentSender(QObject *receiver,
+ Sender *currentSender,
+ Sender *previousSender);
+#ifdef QT_JAMBI_BUILD
+ static int *setDeleteWatch(QObjectPrivate *d, int *newWatch);
+ static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch);
+#endif
+ static void clearGuards(QObject *);
+
+ static QObjectPrivate *get(QObject *o) {
+ return o->d_func();
+ }
+
+ int signalIndex(const char *signalName) const;
+ inline bool isSignalConnected(uint signalIdx) const;
+
+public:
+ QString objectName;
+ ExtraData *extraData; // extra data set by the user
+ QThreadData *threadData; // id of the thread that owns the object
+
+ QObjectConnectionListVector *connectionLists;
+
+ Connection *senders; // linked list of connections connected to this object
+ Sender *currentSender; // object currently activating the object
+ mutable quint32 connectedSignals[2];
+
+#ifdef QT3_SUPPORT
+ QVector< QWeakPointer<QObject> > pendingChildInsertedEvents;
+#else
+ // preserve binary compatibility with code compiled without Qt 3 support
+ // keeping the binary layout stable helps the Qt Creator debugger
+ void *unused;
+#endif
+
+ QList<QPointer<QObject> > eventFilters;
+ union {
+ QObject *currentChildBeingDeleted;
+ QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
+ };
+
+ // these objects are all used to indicate that a QObject was deleted
+ // plus QPointer, which keeps a separate list
+ QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
+#ifdef QT_JAMBI_BUILD
+ int *deleteWatch;
+#endif
+};
+
+
+/*! \internal
+
+ Returns true if the signal with index \a signal_index from object \a sender is connected.
+ Signals with indices above a certain range are always considered connected (see connectedSignals
+ in QObjectPrivate). If a signal spy is installed, all signals are considered connected.
+
+ \a signal_index must be the index returned by QObjectPrivate::signalIndex;
+*/
+inline bool QObjectPrivate::isSignalConnected(uint signal_index) const
+{
+ return signal_index >= sizeof(connectedSignals) * 8
+ || (connectedSignals[signal_index >> 5] & (1 << (signal_index & 0x1f))
+ || qt_signal_spy_callback_set.signal_begin_callback
+ || qt_signal_spy_callback_set.signal_end_callback);
+}
+
+inline QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
+ Sender *sender)
+{
+ Sender *previousSender = receiver->d_func()->currentSender;
+ receiver->d_func()->currentSender = sender;
+ return previousSender;
+}
+
+inline void QObjectPrivate::resetCurrentSender(QObject *receiver,
+ Sender *currentSender,
+ Sender *previousSender)
+{
+ // ref is set to zero when this object is deleted during the metacall
+ if (currentSender->ref == 1)
+ receiver->d_func()->currentSender = previousSender;
+ // if we've recursed, we need to tell the caller about the objects deletion
+ if (previousSender)
+ previousSender->ref = currentSender->ref;
+}
+
+
+Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE);
+
+class QSemaphore;
+class Q_CORE_EXPORT QMetaCallEvent : public QEvent
+{
+public:
+ QMetaCallEvent(ushort method_offset, ushort method_relative, QObjectPrivate::StaticMetaCallFunction callFunction , const QObject *sender, int signalId,
+ int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
+ ~QMetaCallEvent();
+
+ inline int id() const { return method_offset_ + method_relative_; }
+ inline const QObject *sender() const { return sender_; }
+ inline int signalId() const { return signalId_; }
+ inline void **args() const { return args_; }
+
+ virtual void placeMetaCall(QObject *object);
+
+private:
+ const QObject *sender_;
+ int signalId_;
+ int nargs_;
+ int *types_;
+ void **args_;
+ QSemaphore *semaphore_;
+ QObjectPrivate::StaticMetaCallFunction callFunction_;
+ ushort method_offset_;
+ ushort method_relative_;
+};
+
+class QBoolBlocker
+{
+public:
+ inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
+ inline ~QBoolBlocker(){block = reset; }
+private:
+ bool &block;
+ bool reset;
+};
+
+void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o);
+
+
+struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject
+{
+ virtual ~QAbstractDynamicMetaObject() {}
+ virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; }
+ virtual int createProperty(const char *, const char *) { return -1; }
+};
+
+QT_END_NAMESPACE
+
+#endif // QOBJECT_P_H
diff --git a/src/corelib/kernel/qobjectcleanuphandler.cpp b/src/corelib/kernel/qobjectcleanuphandler.cpp
new file mode 100644
index 0000000000..2355537a2a
--- /dev/null
+++ b/src/corelib/kernel/qobjectcleanuphandler.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qobjectcleanuphandler.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QObjectCleanupHandler
+ \brief The QObjectCleanupHandler class watches the lifetime of multiple QObjects.
+
+ \ingroup objectmodel
+
+ A QObjectCleanupHandler is useful whenever you need to know when a
+ number of \l{QObject}s that are owned by someone else have been
+ deleted. This is important, for example, when referencing memory
+ in an application that has been allocated in a shared library.
+
+ To keep track of some \l{QObject}s, create a
+ QObjectCleanupHandler, and add() the objects you are interested
+ in. If you are no longer interested in tracking a particular
+ object, use remove() to remove it from the cleanup handler. If an
+ object being tracked by the cleanup handler gets deleted by
+ someone else it will automatically be removed from the cleanup
+ handler. You can delete all the objects in the cleanup handler
+ with clear(), or by destroying the cleanup handler. isEmpty()
+ returns true if the QObjectCleanupHandler has no objects to keep
+ track of.
+
+ \sa QPointer
+*/
+
+/*!
+ Constructs an empty QObjectCleanupHandler.
+*/
+QObjectCleanupHandler::QObjectCleanupHandler()
+{
+}
+
+/*!
+ Destroys the cleanup handler. All objects in this cleanup handler
+ will be deleted.
+
+ \sa clear()
+*/
+QObjectCleanupHandler::~QObjectCleanupHandler()
+{
+ clear();
+}
+
+/*!
+ Adds \a object to this cleanup handler and returns the pointer to
+ the object.
+
+ \sa remove()
+*/
+QObject *QObjectCleanupHandler::add(QObject* object)
+{
+ if (!object)
+ return 0;
+
+ connect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ cleanupObjects.insert(0, object);
+ return object;
+}
+
+/*!
+ Removes the \a object from this cleanup handler. The object will
+ not be destroyed.
+
+ \sa add()
+*/
+void QObjectCleanupHandler::remove(QObject *object)
+{
+ int index;
+ if ((index = cleanupObjects.indexOf(object)) != -1) {
+ cleanupObjects.removeAt(index);
+ disconnect(object, SIGNAL(destroyed(QObject*)), this, SLOT(objectDestroyed(QObject*)));
+ }
+}
+
+/*!
+ Returns true if this cleanup handler is empty or if all objects in
+ this cleanup handler have been destroyed; otherwise return false.
+
+ \sa add() remove() clear()
+*/
+bool QObjectCleanupHandler::isEmpty() const
+{
+ return cleanupObjects.isEmpty();
+}
+
+/*!
+ Deletes all objects in this cleanup handler. The cleanup handler
+ becomes empty.
+
+ \sa isEmpty()
+*/
+void QObjectCleanupHandler::clear()
+{
+ while (!cleanupObjects.isEmpty())
+ delete cleanupObjects.takeFirst();
+}
+
+void QObjectCleanupHandler::objectDestroyed(QObject *object)
+{
+ remove(object);
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qobjectcleanuphandler.h b/src/corelib/kernel/qobjectcleanuphandler.h
new file mode 100644
index 0000000000..5004224e38
--- /dev/null
+++ b/src/corelib/kernel/qobjectcleanuphandler.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QOBJECTCLEANUPHANDLER_H
+#define QOBJECTCLEANUPHANDLER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QObjectCleanupHandler : public QObject
+{
+ Q_OBJECT
+
+public:
+ QObjectCleanupHandler();
+ ~QObjectCleanupHandler();
+
+ QObject* add(QObject* object);
+ void remove(QObject *object);
+ bool isEmpty() const;
+ void clear();
+
+private:
+ // ### move into d pointer
+ QObjectList cleanupObjects;
+
+private Q_SLOTS:
+ void objectDestroyed(QObject *);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QOBJECTCLEANUPHANDLER_H
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
new file mode 100644
index 0000000000..4384837f63
--- /dev/null
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -0,0 +1,506 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QOBJECTDEFS_H
+#define QOBJECTDEFS_H
+
+#include <QtCore/qnamespace.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QByteArray;
+
+class QString;
+
+#ifndef Q_MOC_OUTPUT_REVISION
+#define Q_MOC_OUTPUT_REVISION 63
+#endif
+
+// The following macros are our "extensions" to C++
+// They are used, strictly speaking, only by the moc.
+
+#ifndef Q_MOC_RUN
+# if defined(QT_NO_KEYWORDS)
+# define QT_NO_EMIT
+# else
+# define slots
+# define signals protected
+# endif
+# define Q_SLOTS
+# define Q_SIGNALS protected
+# define Q_PRIVATE_SLOT(d, signature)
+# define Q_EMIT
+#ifndef QT_NO_EMIT
+# define emit
+#endif
+#define Q_CLASSINFO(name, value)
+#define Q_INTERFACES(x)
+#define Q_PROPERTY(text)
+#define Q_PRIVATE_PROPERTY(d, text)
+#define Q_REVISION(v)
+#define Q_OVERRIDE(text)
+#define Q_ENUMS(x)
+#define Q_FLAGS(x)
+#ifdef QT3_SUPPORT
+# define Q_SETS(x)
+#endif
+#define Q_SCRIPTABLE
+#define Q_INVOKABLE
+#define Q_SIGNAL
+#define Q_SLOT
+
+#ifndef QT_NO_TRANSLATION
+# ifndef QT_NO_TEXTCODEC
+// full set of tr functions
+// ### Qt 5: merge overloads
+# define QT_TR_FUNCTIONS \
+ static inline QString tr(const char *s, const char *c = 0) \
+ { return staticMetaObject.tr(s, c); } \
+ static inline QString trUtf8(const char *s, const char *c = 0) \
+ { return staticMetaObject.trUtf8(s, c); } \
+ static inline QString tr(const char *s, const char *c, int n) \
+ { return staticMetaObject.tr(s, c, n); } \
+ static inline QString trUtf8(const char *s, const char *c, int n) \
+ { return staticMetaObject.trUtf8(s, c, n); }
+# else
+// no QTextCodec, no utf8
+// ### Qt 5: merge overloads
+# define QT_TR_FUNCTIONS \
+ static inline QString tr(const char *s, const char *c = 0) \
+ { return staticMetaObject.tr(s, c); } \
+ static inline QString tr(const char *s, const char *c, int n) \
+ { return staticMetaObject.tr(s, c, n); }
+# endif
+#else
+// inherit the ones from QObject
+# define QT_TR_FUNCTIONS
+#endif
+
+#if defined(QT_NO_QOBJECT_CHECK)
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT_CHECK
+#else
+
+/* This is a compile time check that ensures that any class cast with qobject_cast
+ actually contains a Q_OBJECT macro. Note: qobject_cast will fail if a QObject
+ subclass doesn't contain Q_OBJECT.
+
+ In qt_check_for_QOBJECT_macro, we call a dummy templated function with two
+ parameters, the first being "this" and the other the target of the qobject
+ cast. If the types are not identical, we know that a Q_OBJECT macro is missing.
+
+ If you get a compiler error here, make sure that the class you are casting
+ to contains a Q_OBJECT macro.
+*/
+
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT_CHECK \
+ template <typename T> inline void qt_check_for_QOBJECT_macro(const T &_q_argument) const \
+ { int i = qYouForgotTheQ_OBJECT_Macro(this, &_q_argument); i = i; }
+
+template <typename T>
+inline int qYouForgotTheQ_OBJECT_Macro(T, T) { return 0; }
+
+template <typename T1, typename T2>
+inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {}
+#endif // QT_NO_QOBJECT_CHECK
+
+#ifdef Q_NO_DATA_RELOCATION
+#define Q_OBJECT_GETSTATICMETAOBJECT static const QMetaObject &getStaticMetaObject();
+#else
+#define Q_OBJECT_GETSTATICMETAOBJECT
+#endif
+
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT \
+public: \
+ Q_OBJECT_CHECK \
+ static const QMetaObject staticMetaObject; \
+ Q_OBJECT_GETSTATICMETAOBJECT \
+ virtual const QMetaObject *metaObject() const; \
+ virtual void *qt_metacast(const char *); \
+ QT_TR_FUNCTIONS \
+ virtual int qt_metacall(QMetaObject::Call, int, void **); \
+private: \
+ Q_DECL_HIDDEN static const QMetaObjectExtraData staticMetaObjectExtraData; \
+ Q_DECL_HIDDEN static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
+
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT_FAKE Q_OBJECT
+/* tmake ignore Q_GADGET */
+#define Q_GADGET \
+public: \
+ static const QMetaObject staticMetaObject; \
+ Q_OBJECT_GETSTATICMETAOBJECT \
+private:
+#else // Q_MOC_RUN
+#define slots slots
+#define signals signals
+#define Q_SLOTS Q_SLOTS
+#define Q_SIGNALS Q_SIGNALS
+#define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value)
+#define Q_INTERFACES(x) Q_INTERFACES(x)
+#define Q_PROPERTY(text) Q_PROPERTY(text)
+#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text)
+#define Q_REVISION(v) Q_REVISION(v)
+#define Q_OVERRIDE(text) Q_OVERRIDE(text)
+#define Q_ENUMS(x) Q_ENUMS(x)
+#define Q_FLAGS(x) Q_FLAGS(x)
+#ifdef QT3_SUPPORT
+# define Q_SETS(x) Q_SETS(x)
+#endif
+ /* tmake ignore Q_OBJECT */
+#define Q_OBJECT Q_OBJECT
+ /* tmake ignore Q_OBJECT */
+#define Q_OBJECT_FAKE Q_OBJECT_FAKE
+ /* tmake ignore Q_GADGET */
+#define Q_GADGET Q_GADGET
+#define Q_SCRIPTABLE Q_SCRIPTABLE
+#define Q_INVOKABLE Q_INVOKABLE
+#define Q_SIGNAL Q_SIGNAL
+#define Q_SLOT Q_SLOT
+#endif //Q_MOC_RUN
+
+// macro for onaming members
+#ifdef METHOD
+#undef METHOD
+#endif
+#ifdef SLOT
+#undef SLOT
+#endif
+#ifdef SIGNAL
+#undef SIGNAL
+#endif
+
+Q_CORE_EXPORT const char *qFlagLocation(const char *method);
+
+#define QTOSTRING_HELPER(s) #s
+#define QTOSTRING(s) QTOSTRING_HELPER(s)
+#ifndef QT_NO_DEBUG
+# define QLOCATION "\0"__FILE__":"QTOSTRING(__LINE__)
+# ifndef QT_NO_KEYWORDS
+# define METHOD(a) qFlagLocation("0"#a QLOCATION)
+# endif
+# define SLOT(a) qFlagLocation("1"#a QLOCATION)
+# define SIGNAL(a) qFlagLocation("2"#a QLOCATION)
+#else
+# ifndef QT_NO_KEYWORDS
+# define METHOD(a) "0"#a
+# endif
+# define SLOT(a) "1"#a
+# define SIGNAL(a) "2"#a
+#endif
+
+#ifdef QT3_SUPPORT
+#define METHOD_CODE 0 // member type codes
+#define SLOT_CODE 1
+#define SIGNAL_CODE 2
+#endif
+
+#define QMETHOD_CODE 0 // member type codes
+#define QSLOT_CODE 1
+#define QSIGNAL_CODE 2
+
+#define Q_ARG(type, data) QArgument<type >(#type, data)
+#define Q_RETURN_ARG(type, data) QReturnArgument<type >(#type, data)
+
+class QObject;
+class QMetaMethod;
+class QMetaEnum;
+class QMetaProperty;
+class QMetaClassInfo;
+
+
+class Q_CORE_EXPORT QGenericArgument
+{
+public:
+ inline QGenericArgument(const char *aName = 0, const void *aData = 0)
+ : _data(aData), _name(aName) {}
+ inline void *data() const { return const_cast<void *>(_data); }
+ inline const char *name() const { return _name; }
+
+private:
+ const void *_data;
+ const char *_name;
+};
+
+class Q_CORE_EXPORT QGenericReturnArgument: public QGenericArgument
+{
+public:
+ inline QGenericReturnArgument(const char *aName = 0, void *aData = 0)
+ : QGenericArgument(aName, aData)
+ {}
+};
+
+template <class T>
+class QArgument: public QGenericArgument
+{
+public:
+ inline QArgument(const char *aName, const T &aData)
+ : QGenericArgument(aName, static_cast<const void *>(&aData))
+ {}
+};
+template <class T>
+class QArgument<T &>: public QGenericArgument
+{
+public:
+ inline QArgument(const char *aName, T &aData)
+ : QGenericArgument(aName, static_cast<const void *>(&aData))
+ {}
+};
+
+
+template <typename T>
+class QReturnArgument: public QGenericReturnArgument
+{
+public:
+ inline QReturnArgument(const char *aName, T &aData)
+ : QGenericReturnArgument(aName, static_cast<void *>(&aData))
+ {}
+};
+
+struct Q_CORE_EXPORT QMetaObject
+{
+ const char *className() const;
+ const QMetaObject *superClass() const;
+
+ QObject *cast(QObject *obj) const;
+ const QObject *cast(const QObject *obj) const;
+
+#ifndef QT_NO_TRANSLATION
+ // ### Qt 4: Merge overloads
+ QString tr(const char *s, const char *c) const;
+ QString trUtf8(const char *s, const char *c) const;
+ QString tr(const char *s, const char *c, int n) const;
+ QString trUtf8(const char *s, const char *c, int n) const;
+#endif // QT_NO_TRANSLATION
+
+ int methodOffset() const;
+ int enumeratorOffset() const;
+ int propertyOffset() const;
+ int classInfoOffset() const;
+
+ int constructorCount() const;
+ int methodCount() const;
+ int enumeratorCount() const;
+ int propertyCount() const;
+ int classInfoCount() const;
+
+ int indexOfConstructor(const char *constructor) const;
+ int indexOfMethod(const char *method) const;
+ int indexOfSignal(const char *signal) const;
+ int indexOfSlot(const char *slot) const;
+ int indexOfEnumerator(const char *name) const;
+ int indexOfProperty(const char *name) const;
+ int indexOfClassInfo(const char *name) const;
+
+ QMetaMethod constructor(int index) const;
+ QMetaMethod method(int index) const;
+ QMetaEnum enumerator(int index) const;
+ QMetaProperty property(int index) const;
+ QMetaClassInfo classInfo(int index) const;
+ QMetaProperty userProperty() const;
+
+ static bool checkConnectArgs(const char *signal, const char *method);
+ static QByteArray normalizedSignature(const char *method);
+ static QByteArray normalizedType(const char *type);
+
+ // internal index-based connect
+ static bool connect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index,
+ int type = 0, int *types = 0);
+ // internal index-based disconnect
+ static bool disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index);
+ static bool disconnectOne(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index);
+ // internal slot-name based connect
+ static void connectSlotsByName(QObject *o);
+
+ // internal index-based signal activation
+ static void activate(QObject *sender, int signal_index, void **argv); //obsolete
+ static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv); //obsolete
+ static void activate(QObject *sender, const QMetaObject *, int local_signal_index, void **argv);
+ static void activate(QObject *sender, const QMetaObject *, int from_local_signal_index, int to_local_signal_index, void **argv); //obsolete
+
+ // internal guarded pointers
+ static void addGuard(QObject **ptr);
+ static void removeGuard(QObject **ptr);
+ static void changeGuard(QObject **ptr, QObject *o);
+
+ static bool invokeMethod(QObject *obj, const char *member,
+ Qt::ConnectionType,
+ QGenericReturnArgument ret,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument());
+
+ static inline bool invokeMethod(QObject *obj, const char *member,
+ QGenericReturnArgument ret,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+ {
+ return invokeMethod(obj, member, Qt::AutoConnection, ret, val0, val1, val2, val3,
+ val4, val5, val6, val7, val8, val9);
+ }
+
+ static inline bool invokeMethod(QObject *obj, const char *member,
+ Qt::ConnectionType type,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+ {
+ return invokeMethod(obj, member, type, QGenericReturnArgument(), val0, val1, val2,
+ val3, val4, val5, val6, val7, val8, val9);
+ }
+
+ static inline bool invokeMethod(QObject *obj, const char *member,
+ QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument())
+ {
+ return invokeMethod(obj, member, Qt::AutoConnection, QGenericReturnArgument(), val0,
+ val1, val2, val3, val4, val5, val6, val7, val8, val9);
+ }
+
+ QObject *newInstance(QGenericArgument val0 = QGenericArgument(0),
+ QGenericArgument val1 = QGenericArgument(),
+ QGenericArgument val2 = QGenericArgument(),
+ QGenericArgument val3 = QGenericArgument(),
+ QGenericArgument val4 = QGenericArgument(),
+ QGenericArgument val5 = QGenericArgument(),
+ QGenericArgument val6 = QGenericArgument(),
+ QGenericArgument val7 = QGenericArgument(),
+ QGenericArgument val8 = QGenericArgument(),
+ QGenericArgument val9 = QGenericArgument()) const;
+
+ enum Call {
+ InvokeMetaMethod,
+ ReadProperty,
+ WriteProperty,
+ ResetProperty,
+ QueryPropertyDesignable,
+ QueryPropertyScriptable,
+ QueryPropertyStored,
+ QueryPropertyEditable,
+ QueryPropertyUser,
+ CreateInstance
+ };
+
+ int static_metacall(Call, int, void **) const;
+ static int metacall(QObject *, Call, int, void **);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT const char *superClassName() const;
+#endif
+
+ struct { // private data
+ const QMetaObject *superdata;
+ const char *stringdata;
+ const uint *data;
+ const void *extradata;
+ } d;
+};
+
+typedef const QMetaObject& (*QMetaObjectAccessor)();
+
+struct QMetaObjectExtraData
+{
+#ifdef Q_NO_DATA_RELOCATION
+ const QMetaObjectAccessor *objects;
+#else
+ const QMetaObject **objects;
+#endif
+
+ typedef void (*StaticMetacallFunction)(QObject *, QMetaObject::Call, int, void **); //from revision 6
+ //typedef int (*StaticMetaCall)(QMetaObject::Call, int, void **); //used from revison 2 until revison 5
+ StaticMetacallFunction static_metacall;
+};
+
+inline const char *QMetaObject::className() const
+{ return d.stringdata; }
+
+inline const QMetaObject *QMetaObject::superClass() const
+{ return d.superdata; }
+
+#ifdef QT3_SUPPORT
+inline const char *QMetaObject::superClassName() const
+{ return d.superdata ? d.superdata->className() : 0; }
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QOBJECTDEFS_H
diff --git a/src/corelib/kernel/qpointer.cpp b/src/corelib/kernel/qpointer.cpp
new file mode 100644
index 0000000000..73f695b65a
--- /dev/null
+++ b/src/corelib/kernel/qpointer.cpp
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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$
+**
+****************************************************************************/
+
+/*!
+ \class QPointer
+ \brief The QPointer class is a template class that provides guarded pointers to QObject.
+
+ \ingroup objectmodel
+
+
+ A guarded pointer, QPointer<T>, behaves like a normal C++
+ pointer \c{T *}, except that it is automatically set to 0 when the
+ referenced object is destroyed (unlike normal C++ pointers, which
+ become "dangling pointers" in such cases). \c T must be a
+ subclass of QObject.
+
+ Guarded pointers are useful whenever you need to store a pointer
+ to a QObject that is owned by someone else, and therefore might be
+ destroyed while you still hold a reference to it. You can safely
+ test the pointer for validity.
+
+ Qt also provides QSharedPointer, an implementation of a reference-counted
+ shared pointer object, which can be used to maintain a collection of
+ references to an individual pointer.
+
+ Example:
+
+ \snippet doc/src/snippets/pointer/pointer.cpp 0
+ \dots
+ \snippet doc/src/snippets/pointer/pointer.cpp 1
+ \snippet doc/src/snippets/pointer/pointer.cpp 2
+
+ If the QLabel is deleted in the meantime, the \c label variable
+ will hold 0 instead of an invalid address, and the last line will
+ never be executed.
+
+ The functions and operators available with a QPointer are the
+ same as those available with a normal unguarded pointer, except
+ the pointer arithmetic operators (\c{+}, \c{-}, \c{++}, and
+ \c{--}), which are normally used only with arrays of objects.
+
+ Use QPointers like normal pointers and you will not need to read
+ this class documentation.
+
+ For creating guarded pointers, you can construct or assign to them
+ from a T* or from another guarded pointer of the same type. You
+ can compare them with each other using operator==() and
+ operator!=(), or test for 0 with isNull(). You can dereference
+ them using either the \c *x or the \c x->member notation.
+
+ A guarded pointer will automatically cast to a \c T *, so you can
+ freely mix guarded and unguarded pointers. This means that if you
+ have a QPointer<QWidget>, you can pass it to a function that
+ requires a QWidget *. For this reason, it is of little value to
+ declare functions to take a QPointer as a parameter; just use
+ normal pointers. Use a QPointer when you are storing a pointer
+ over time.
+
+ Note that class \c T must inherit QObject, or a compilation or
+ link error will result.
+
+ \sa QSharedPointer, QObject, QObjectCleanupHandler
+*/
+
+/*!
+ \fn QPointer::QPointer()
+
+ Constructs a 0 guarded pointer.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QPointer::QPointer(T* p)
+
+ Constructs a guarded pointer that points to same object that \a p
+ points to.
+*/
+
+/*!
+ \fn QPointer::QPointer(const QPointer<T> &p)
+
+ Copies one guarded pointer from another. The constructed guarded
+ pointer points to the same object that \a p points to (which may
+ be 0).
+*/
+
+/*!
+ \fn QPointer::~QPointer()
+
+ Destroys the guarded pointer. Just like a normal pointer,
+ destroying a guarded pointer does \e not destroy the object being
+ pointed to.
+*/
+
+/*!
+ \fn QPointer<T>& QPointer::operator=(const QPointer<T> &p)
+
+ Assignment operator. This guarded pointer will now point to the
+ same object that \a p points to.
+*/
+
+/*!
+ \fn QPointer<T> & QPointer::operator=(T* p)
+
+ Assignment operator. This guarded pointer will now point to the
+ same object that \a p points to.
+*/
+
+/*!
+ \fn T* QPointer::data() const
+ \since 4.4
+
+ Returns the pointer to the object being guarded.
+*/
+
+/*!
+ \fn bool QPointer::isNull() const
+
+ Returns \c true if the referenced object has been destroyed or if
+ there is no referenced object; otherwise returns false.
+*/
+
+/*!
+ \fn T* QPointer::operator->() const
+
+ Overloaded arrow operator; implements pointer semantics. Just use
+ this operator as you would with a normal C++ pointer.
+*/
+
+/*!
+ \fn T& QPointer::operator*() const
+
+ Dereference operator; implements pointer semantics. Just use this
+ operator as you would with a normal C++ pointer.
+*/
+
+/*!
+ \fn QPointer::operator T*() const
+
+ Cast operator; implements pointer semantics. Because of this
+ function you can pass a QPointer\<T\> to a function where a T*
+ is required.
+*/
+
+/*!
+ \fn bool operator==(const T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(const QPointer<T> &p, const T *o)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(const QPointer<T> &p, T *o)
+ \relates QPointer
+
+ Equality operator. Returns true if \a o and the guarded
+ pointer \a p are pointing to the same object, otherwise
+ returns false.
+
+*/
+/*!
+ \fn bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
+
+ Equality operator. Returns true if the guarded pointers \a p1 and \a p2
+ are pointing to the same object, otherwise
+ returns false.
+
+*/
+
+
+/*!
+ \fn bool operator!=(const T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(const QPointer<T> &p, const T *o)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(T *o, const QPointer<T> &p)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(const QPointer<T> &p, T *o)
+ \relates QPointer
+
+ Inequality operator. Returns true if \a o and the guarded
+ pointer \a p are not pointing to the same object, otherwise
+ returns false.
+*/
+/*!
+ \fn bool operator!=(const QPointer<T> &p1, const QPointer<T> &p2)
+ \relates QPointer
+
+ Inequality operator. Returns true if the guarded pointers \a p1 and
+ \a p2 are not pointing to the same object, otherwise
+ returns false.
+*/
diff --git a/src/corelib/kernel/qpointer.h b/src/corelib/kernel/qpointer.h
new file mode 100644
index 0000000000..c2621cb8bd
--- /dev/null
+++ b/src/corelib/kernel/qpointer.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QPOINTER_H
+#define QPOINTER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+template <class T>
+class QPointer
+{
+ QObject *o;
+public:
+ inline QPointer() : o(0) {}
+ inline QPointer(T *p) : o(p)
+ { QMetaObject::addGuard(&o); }
+ inline QPointer(const QPointer<T> &p) : o(p.o)
+ { QMetaObject::addGuard(&o); }
+ inline ~QPointer()
+ { QMetaObject::removeGuard(&o); }
+ inline QPointer<T> &operator=(const QPointer<T> &p)
+ { if (this != &p) QMetaObject::changeGuard(&o, p.o); return *this; }
+ inline QPointer<T> &operator=(T* p)
+ { if (o != p) QMetaObject::changeGuard(&o, p); return *this; }
+
+ inline bool isNull() const
+ { return !o; }
+
+ inline T* operator->() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+ inline T& operator*() const
+ { return *static_cast<T*>(const_cast<QObject*>(o)); }
+ inline operator T*() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+ inline T* data() const
+ { return static_cast<T*>(const_cast<QObject*>(o)); }
+};
+
+
+#if (!defined(Q_CC_SUN) || (__SUNPRO_CC >= 0x580)) // ambiguity between const T * and T *
+
+template <class T>
+inline bool operator==(const T *o, const QPointer<T> &p)
+{ return o == p.operator->(); }
+
+template<class T>
+inline bool operator==(const QPointer<T> &p, const T *o)
+{ return p.operator->() == o; }
+
+#else
+
+template<class T>
+inline bool operator==(const void *o, const QPointer<T> &p)
+{ return o == p.operator->(); }
+
+template<class T>
+inline bool operator==(const QPointer<T> &p, const void *o)
+{ return p.operator->() == o; }
+
+#endif
+
+template <class T>
+inline bool operator==(T *o, const QPointer<T> &p)
+{ return o == p.operator->(); }
+
+template<class T>
+inline bool operator==(const QPointer<T> &p, T *o)
+{ return p.operator->() == o; }
+
+template<class T>
+inline bool operator==(const QPointer<T> &p1, const QPointer<T> &p2)
+{ return p1.operator->() == p2.operator->(); }
+
+
+#if (!defined(Q_CC_SUN) || (__SUNPRO_CC >= 0x580)) // ambiguity between const T * and T *
+
+template <class T>
+inline bool operator!=(const T *o, const QPointer<T> &p)
+{ return o != p.operator->(); }
+
+template<class T>
+inline bool operator!= (const QPointer<T> &p, const T *o)
+{ return p.operator->() != o; }
+
+#else
+
+template<class T>
+inline bool operator!= (const void *o, const QPointer<T> &p)
+{ return o != p.operator->(); }
+
+template<class T>
+inline bool operator!= (const QPointer<T> &p, const void *o)
+{ return p.operator->() != o; }
+
+#endif
+
+template <class T>
+inline bool operator!=(T *o, const QPointer<T> &p)
+{ return o != p.operator->(); }
+
+template<class T>
+inline bool operator!= (const QPointer<T> &p, T *o)
+{ return p.operator->() != o; }
+
+template<class T>
+inline bool operator!= (const QPointer<T> &p1, const QPointer<T> &p2)
+{ return p1.operator->() != p2.operator->() ; }
+
+// Make MSVC < 1400 (2005) handle "if (NULL == p)" syntax
+#if defined(Q_CC_MSVC) && (_MSC_VER < 1400)
+template<class T>
+inline bool operator== (int i, const QPointer<T> &p)
+{ Q_ASSERT(i == 0); return !i && p.isNull(); }
+
+template<class T>
+inline bool operator!= (int i, const QPointer<T> &p)
+{ Q_ASSERT(i == 0); return !i && !p.isNull(); }
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPOINTER_H
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
new file mode 100644
index 0000000000..78715a1966
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -0,0 +1,612 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdir.h>
+#include <qcryptographichash.h>
+#ifdef Q_OS_SYMBIAN
+#include <e32const.h>
+#endif
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
+/*!
+ \internal
+
+ Generate a string from the key which can be any unicode string into
+ the subset that the win/unix kernel allows.
+
+ On Unix this will be a file name
+ On Symbian key will be truncated to 80 characters
+ */
+QString
+QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
+ const QString &prefix)
+{
+ if (key.isEmpty())
+ return QString();
+
+ QString result = prefix;
+
+ QString part1 = key;
+ part1.replace(QRegExp(QLatin1String("[^A-Za-z]")), QString());
+ result.append(part1);
+
+ QByteArray hex = QCryptographicHash::hash(key.toUtf8(), QCryptographicHash::Sha1).toHex();
+ result.append(QLatin1String(hex));
+#ifdef Q_OS_WIN
+ return result;
+#elif defined(Q_OS_SYMBIAN)
+ return result.left(KMaxKernelName);
+#else
+ return QDir::tempPath() + QLatin1Char('/') + result;
+#endif
+}
+#endif // QT_NO_SHAREDMEMORY && QT_NO_SHAREDMEMORY
+
+#ifndef QT_NO_SHAREDMEMORY
+
+/*!
+ \class QSharedMemory
+ \since 4.4
+
+ \brief The QSharedMemory class provides access to a shared memory segment.
+
+ QSharedMemory provides access to a shared memory segment by multiple
+ threads and processes. It also provides a way for a single thread or
+ process to lock the memory for exclusive access.
+
+ When using this class, be aware of the following platform
+ differences:
+
+ \list
+
+ \o Windows: QSharedMemory does not "own" the shared memory segment.
+ When all threads or processes that have an instance of QSharedMemory
+ attached to a particular shared memory segment have either destroyed
+ their instance of QSharedMemory or exited, the Windows kernel
+ releases the shared memory segment automatically.
+
+ \o Unix: QSharedMemory "owns" the shared memory segment. When the
+ last thread or process that has an instance of QSharedMemory
+ attached to a particular shared memory segment detaches from the
+ segment by destroying its instance of QSharedMemory, the Unix kernel
+ release the shared memory segment. But if that last thread or
+ process crashes without running the QSharedMemory destructor, the
+ shared memory segment survives the crash.
+
+ \o HP-UX: Only one attach to a shared memory segment is allowed per
+ process. This means that QSharedMemory should not be used across
+ multiple threads in the same process in HP-UX.
+
+ \o Symbian: QSharedMemory does not "own" the shared memory segment.
+ When all threads or processes that have an instance of QSharedMemory
+ attached to a particular shared memory segment have either destroyed
+ their instance of QSharedMemory or exited, the Symbian kernel
+ releases the shared memory segment automatically.
+ Also, access to a shared memory segment cannot be limited to read-only
+ in Symbian.
+
+ \endlist
+
+ Remember to lock the shared memory with lock() before reading from
+ or writing to the shared memory, and remember to release the lock
+ with unlock() after you are done.
+
+ Unlike QtSharedMemory, QSharedMemory automatically destroys the
+ shared memory segment when the last instance of QSharedMemory is
+ detached from the segment, and no references to the segment
+ remain. Do not mix using QtSharedMemory and QSharedMemory. Port
+ everything to QSharedMemory.
+
+ \warning QSharedMemory changes the key in a Qt-specific way, unless otherwise
+ specified. Interoperation with non-Qt applications is achieved by first creating
+ a default shared memory with QSharedMemory() and then setting a native key with
+ setNativeKey(). When using native keys, shared memory is not protected against
+ multiple accesses on it (e.g. unable to lock()) and a user-defined mechanism
+ should be used to achieve a such protection.
+ */
+
+/*!
+ \overload QSharedMemory()
+
+ Constructs a shared memory object with the given \a parent. The
+ shared memory object's key is not set by the constructor, so the
+ shared memory object does not have an underlying shared memory
+ segment attached. The key must be set with setKey() or setNativeKey()
+ before create() or attach() can be used.
+
+ \sa setKey()
+ */
+QSharedMemory::QSharedMemory(QObject *parent)
+ : QObject(*new QSharedMemoryPrivate, parent)
+{
+}
+
+/*!
+ Constructs a shared memory object with the given \a parent and with
+ its key set to \a key. Because its key is set, its create() and
+ attach() functions can be called.
+
+ \sa setKey(), create(), attach()
+ */
+QSharedMemory::QSharedMemory(const QString &key, QObject *parent)
+ : QObject(*new QSharedMemoryPrivate, parent)
+{
+ setKey(key);
+}
+
+/*!
+ The destructor clears the key, which forces the shared memory object
+ to \l {detach()} {detach} from its underlying shared memory
+ segment. If this shared memory object is the last one connected to
+ the shared memory segment, the detach() operation destroys the
+ shared memory segment.
+
+ \sa detach() isAttached()
+ */
+QSharedMemory::~QSharedMemory()
+{
+ setKey(QString());
+}
+
+/*!
+ Sets the platform independent \a key for this shared memory object. If \a key
+ is the same as the current key, the function returns without doing anything.
+
+ You can call key() to retrieve the platform independent key. Internally,
+ QSharedMemory converts this key into a platform specific key. If you instead
+ call nativeKey(), you will get the platform specific, converted key.
+
+ If the shared memory object is attached to an underlying shared memory
+ segment, it will \l {detach()} {detach} from it before setting the new key.
+ This function does not do an attach().
+
+ \sa key() nativeKey() isAttached()
+*/
+void QSharedMemory::setKey(const QString &key)
+{
+ Q_D(QSharedMemory);
+ if (key == d->key && d->makePlatformSafeKey(key) == d->nativeKey)
+ return;
+
+ if (isAttached())
+ detach();
+ d->cleanHandle();
+ d->key = key;
+ d->nativeKey = d->makePlatformSafeKey(key);
+}
+
+/*!
+ \since 4.8
+
+ Sets the native, platform specific, \a key for this shared memory object. If
+ \a key is the same as the current native key, the function returns without
+ doing anything. If all you want is to assign a key to a segment, you should
+ call setKey() instead.
+
+ You can call nativeKey() to retrieve the native key. If a native key has been
+ assigned, calling key() will return a null string.
+
+ If the shared memory object is attached to an underlying shared memory
+ segment, it will \l {detach()} {detach} from it before setting the new key.
+ This function does not do an attach().
+
+ The application will not be portable if you set a native key.
+
+ \sa nativeKey() key() isAttached()
+*/
+void QSharedMemory::setNativeKey(const QString &key)
+{
+ Q_D(QSharedMemory);
+ if (key == d->nativeKey && d->key.isNull())
+ return;
+
+ if (isAttached())
+ detach();
+ d->cleanHandle();
+ d->key = QString();
+ d->nativeKey = key;
+}
+
+bool QSharedMemoryPrivate::initKey()
+{
+ if (!cleanHandle())
+ return false;
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ systemSemaphore.setKey(QString(), 1);
+ systemSemaphore.setKey(key, 1);
+ if (systemSemaphore.error() != QSystemSemaphore::NoError) {
+ QString function = QLatin1String("QSharedMemoryPrivate::initKey");
+ errorString = QSharedMemory::tr("%1: unable to set key on lock").arg(function);
+ switch(systemSemaphore.error()) {
+ case QSystemSemaphore::PermissionDenied:
+ error = QSharedMemory::PermissionDenied;
+ break;
+ case QSystemSemaphore::KeyError:
+ error = QSharedMemory::KeyError;
+ break;
+ case QSystemSemaphore::AlreadyExists:
+ error = QSharedMemory::AlreadyExists;
+ break;
+ case QSystemSemaphore::NotFound:
+ error = QSharedMemory::NotFound;
+ break;
+ case QSystemSemaphore::OutOfResources:
+ error = QSharedMemory::OutOfResources;
+ break;
+ case QSystemSemaphore::UnknownError:
+ default:
+ error = QSharedMemory::UnknownError;
+ break;
+ }
+ return false;
+ }
+#endif
+ errorString = QString();
+ error = QSharedMemory::NoError;
+ return true;
+}
+
+/*!
+ Returns the key assigned with setKey() to this shared memory, or a null key
+ if no key has been assigned, or if the segment is using a nativeKey(). The
+ key is the identifier used by Qt applications to identify the shared memory
+ segment.
+
+ You can find the native, platform specific, key used by the operating system
+ by calling nativeKey().
+
+ \sa setKey() setNativeKey()
+ */
+QString QSharedMemory::key() const
+{
+ Q_D(const QSharedMemory);
+ return d->key;
+}
+
+/*!
+ \since 4.8
+
+ Returns the native, platform specific, key for this shared memory object. The
+ native key is the identifier used by the operating system to identify the
+ shared memory segment.
+
+ You can use the native key to access shared memory segments that have not
+ been created by Qt, or to grant shared memory access to non-Qt applications.
+
+ \sa setKey() setNativeKey()
+*/
+QString QSharedMemory::nativeKey() const
+{
+ Q_D(const QSharedMemory);
+ return d->nativeKey;
+}
+
+/*!
+ Creates a shared memory segment of \a size bytes with the key passed to the
+ constructor, set with setKey() or set with setNativeKey(), then attaches to
+ the new shared memory segment with the given access \a mode and returns
+ \tt true. If a shared memory segment identified by the key already exists,
+ the attach operation is not performed and \tt false is returned. When the
+ return value is \tt false, call error() to determine which error occurred.
+
+ \sa error()
+ */
+bool QSharedMemory::create(int size, AccessMode mode)
+{
+ Q_D(QSharedMemory);
+
+ if (!d->initKey())
+ return false;
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+#ifndef Q_OS_WIN
+ // Take ownership and force set initialValue because the semaphore
+ // might have already existed from a previous crash.
+ d->systemSemaphore.setKey(d->key, 1, QSystemSemaphore::Create);
+#endif
+#endif
+
+ QString function = QLatin1String("QSharedMemory::create");
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ QSharedMemoryLocker lock(this);
+ if (!d->key.isNull() && !d->tryLocker(&lock, function))
+ return false;
+#endif
+
+ if (size <= 0) {
+ d->error = QSharedMemory::InvalidSize;
+ d->errorString =
+ QSharedMemory::tr("%1: create size is less then 0").arg(function);
+ return false;
+ }
+
+ if (!d->create(size))
+ return false;
+
+ return d->attach(mode);
+}
+
+/*!
+ Returns the size of the attached shared memory segment. If no shared
+ memory segment is attached, 0 is returned.
+
+ \sa create() attach()
+ */
+int QSharedMemory::size() const
+{
+ Q_D(const QSharedMemory);
+ return d->size;
+}
+
+/*!
+ \enum QSharedMemory::AccessMode
+
+ \value ReadOnly The shared memory segment is read-only. Writing to
+ the shared memory segment is not allowed. An attempt to write to a
+ shared memory segment created with ReadOnly causes the program to
+ abort.
+
+ \value ReadWrite Reading and writing the shared memory segment are
+ both allowed.
+*/
+
+/*!
+ Attempts to attach the process to the shared memory segment
+ identified by the key that was passed to the constructor or to a
+ call to setKey() or setNativeKey(). The access \a mode is \l {QSharedMemory::}
+ {ReadWrite} by default. It can also be \l {QSharedMemory::}
+ {ReadOnly}. Returns true if the attach operation is successful. If
+ false is returned, call error() to determine which error occurred.
+ After attaching the shared memory segment, a pointer to the shared
+ memory can be obtained by calling data().
+
+ \sa isAttached(), detach(), create()
+ */
+bool QSharedMemory::attach(AccessMode mode)
+{
+ Q_D(QSharedMemory);
+
+ if (isAttached() || !d->initKey())
+ return false;
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ QSharedMemoryLocker lock(this);
+ if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::attach")))
+ return false;
+#endif
+
+ if (isAttached() || !d->handle())
+ return false;
+
+ return d->attach(mode);
+}
+
+/*!
+ Returns true if this process is attached to the shared memory
+ segment.
+
+ \sa attach(), detach()
+ */
+bool QSharedMemory::isAttached() const
+{
+ Q_D(const QSharedMemory);
+ return (0 != d->memory);
+}
+
+/*!
+ Detaches the process from the shared memory segment. If this was the
+ last process attached to the shared memory segment, then the shared
+ memory segment is released by the system, i.e., the contents are
+ destroyed. The function returns true if it detaches the shared
+ memory segment. If it returns false, it usually means the segment
+ either isn't attached, or it is locked by another process.
+
+ \sa attach(), isAttached()
+ */
+bool QSharedMemory::detach()
+{
+ Q_D(QSharedMemory);
+ if (!isAttached())
+ return false;
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ QSharedMemoryLocker lock(this);
+ if (!d->key.isNull() && !d->tryLocker(&lock, QLatin1String("QSharedMemory::detach")))
+ return false;
+#endif
+
+ return d->detach();
+}
+
+/*!
+ Returns a pointer to the contents of the shared memory segment, if
+ one is attached. Otherwise it returns null. Remember to lock the
+ shared memory with lock() before reading from or writing to the
+ shared memory, and remember to release the lock with unlock() after
+ you are done.
+
+ \sa attach()
+ */
+void *QSharedMemory::data()
+{
+ Q_D(QSharedMemory);
+ return d->memory;
+}
+
+/*!
+ Returns a const pointer to the contents of the shared memory
+ segment, if one is attached. Otherwise it returns null. Remember to
+ lock the shared memory with lock() before reading from or writing to
+ the shared memory, and remember to release the lock with unlock()
+ after you are done.
+
+ \sa attach() create()
+ */
+const void* QSharedMemory::constData() const
+{
+ Q_D(const QSharedMemory);
+ return d->memory;
+}
+
+/*!
+ \overload data()
+ */
+const void *QSharedMemory::data() const
+{
+ Q_D(const QSharedMemory);
+ return d->memory;
+}
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+/*!
+ This is a semaphore that locks the shared memory segment for access
+ by this process and returns true. If another process has locked the
+ segment, this function blocks until the lock is released. Then it
+ acquires the lock and returns true. If this function returns false,
+ it means that you have ignored a false return from create() or attach(),
+ that you have set the key with setNativeKey() or that
+ QSystemSemaphore::acquire() failed due to an unknown system error.
+
+ \sa unlock(), data(), QSystemSemaphore::acquire()
+ */
+bool QSharedMemory::lock()
+{
+ Q_D(QSharedMemory);
+ if (d->lockedByMe) {
+ qWarning("QSharedMemory::lock: already locked");
+ return true;
+ }
+ if (d->systemSemaphore.acquire()) {
+ d->lockedByMe = true;
+ return true;
+ }
+ QString function = QLatin1String("QSharedMemory::lock");
+ d->errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
+ d->error = QSharedMemory::LockError;
+ return false;
+}
+
+/*!
+ Releases the lock on the shared memory segment and returns true, if
+ the lock is currently held by this process. If the segment is not
+ locked, or if the lock is held by another process, nothing happens
+ and false is returned.
+
+ \sa lock()
+ */
+bool QSharedMemory::unlock()
+{
+ Q_D(QSharedMemory);
+ if (!d->lockedByMe)
+ return false;
+ d->lockedByMe = false;
+ if (d->systemSemaphore.release())
+ return true;
+ QString function = QLatin1String("QSharedMemory::unlock");
+ d->errorString = QSharedMemory::tr("%1: unable to unlock").arg(function);
+ d->error = QSharedMemory::LockError;
+ return false;
+}
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+/*!
+ \enum QSharedMemory::SharedMemoryError
+
+ \value NoError No error occurred.
+
+ \value PermissionDenied The operation failed because the caller
+ didn't have the required permissions.
+
+ \value InvalidSize A create operation failed because the requested
+ size was invalid.
+
+ \value KeyError The operation failed because of an invalid key.
+
+ \value AlreadyExists A create() operation failed because a shared
+ memory segment with the specified key already existed.
+
+ \value NotFound An attach() failed because a shared memory segment
+ with the specified key could not be found.
+
+ \value LockError The attempt to lock() the shared memory segment
+ failed because create() or attach() failed and returned false, or
+ because a system error occurred in QSystemSemaphore::acquire().
+
+ \value OutOfResources A create() operation failed because there was
+ not enough memory available to fill the request.
+
+ \value UnknownError Something else happened and it was bad.
+*/
+
+/*!
+ Returns a value indicating whether an error occurred, and, if so,
+ which error it was.
+
+ \sa errorString()
+ */
+QSharedMemory::SharedMemoryError QSharedMemory::error() const
+{
+ Q_D(const QSharedMemory);
+ return d->error;
+}
+
+/*!
+ Returns a text description of the last error that occurred. If
+ error() returns an \l {QSharedMemory::SharedMemoryError} {error
+ value}, call this function to get a text string that describes the
+ error.
+
+ \sa error()
+ */
+QString QSharedMemory::errorString() const
+{
+ Q_D(const QSharedMemory);
+ return d->errorString;
+}
+
+#endif // QT_NO_SHAREDMEMORY
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsharedmemory.h b/src/corelib/kernel/qsharedmemory.h
new file mode 100644
index 0000000000..4a610033a1
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QSHAREDMEMORY_H
+#define QSHAREDMEMORY_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_SHAREDMEMORY
+
+class QSharedMemoryPrivate;
+
+class Q_CORE_EXPORT QSharedMemory : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSharedMemory)
+
+public:
+ enum AccessMode
+ {
+ ReadOnly,
+ ReadWrite
+ };
+
+ enum SharedMemoryError
+ {
+ NoError,
+ PermissionDenied,
+ InvalidSize,
+ KeyError,
+ AlreadyExists,
+ NotFound,
+ LockError,
+ OutOfResources,
+ UnknownError
+ };
+
+ QSharedMemory(QObject *parent = 0);
+ QSharedMemory(const QString &key, QObject *parent = 0);
+ ~QSharedMemory();
+
+ void setKey(const QString &key);
+ QString key() const;
+ void setNativeKey(const QString &key);
+ QString nativeKey() const;
+
+ bool create(int size, AccessMode mode = ReadWrite);
+ int size() const;
+
+ bool attach(AccessMode mode = ReadWrite);
+ bool isAttached() const;
+ bool detach();
+
+ void *data();
+ const void* constData() const;
+ const void *data() const;
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ bool lock();
+ bool unlock();
+#endif
+
+ SharedMemoryError error() const;
+ QString errorString() const;
+
+private:
+ Q_DISABLE_COPY(QSharedMemory)
+};
+
+#endif // QT_NO_SHAREDMEMORY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSHAREDMEMORY_H
+
diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h
new file mode 100644
index 0000000000..72eda372ae
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QSHAREDMEMORY_P_H
+#define QSHAREDMEMORY_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 "qsharedmemory.h"
+
+#ifdef QT_NO_SHAREDMEMORY
+# ifndef QT_NO_SYSTEMSEMAPHORE
+namespace QSharedMemoryPrivate
+{
+ int createUnixKeyFile(const QString &fileName);
+ QString makePlatformSafeKey(const QString &key,
+ const QString &prefix = QLatin1String("qipc_sharedmemory_"));
+}
+#endif
+#else
+
+#include "qsystemsemaphore.h"
+#include "private/qobject_p.h"
+
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#elif defined(Q_OS_SYMBIAN)
+#include <e32std.h>
+#include <sys/types.h>
+#else
+#include <sys/sem.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+/*!
+ Helper class
+ */
+class QSharedMemoryLocker
+{
+
+public:
+ inline QSharedMemoryLocker(QSharedMemory *sharedMemory) : q_sm(sharedMemory)
+ {
+ Q_ASSERT(q_sm);
+ }
+
+ inline ~QSharedMemoryLocker()
+ {
+ if (q_sm)
+ q_sm->unlock();
+ }
+
+ inline bool lock()
+ {
+ if (q_sm && q_sm->lock())
+ return true;
+ q_sm = 0;
+ return false;
+ }
+
+private:
+ QSharedMemory *q_sm;
+};
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+class Q_AUTOTEST_EXPORT QSharedMemoryPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSharedMemory)
+
+public:
+ QSharedMemoryPrivate();
+
+ void *memory;
+ int size;
+ QString key;
+ QString nativeKey;
+ QSharedMemory::SharedMemoryError error;
+ QString errorString;
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ QSystemSemaphore systemSemaphore;
+ bool lockedByMe;
+#endif
+
+ static int createUnixKeyFile(const QString &fileName);
+ static QString makePlatformSafeKey(const QString &key,
+ const QString &prefix = QLatin1String("qipc_sharedmemory_"));
+#ifdef Q_OS_WIN
+ HANDLE handle();
+#else
+ key_t handle();
+#endif
+ bool initKey();
+ bool cleanHandle();
+ bool create(int size);
+ bool attach(QSharedMemory::AccessMode mode);
+ bool detach();
+
+#ifdef Q_OS_SYMBIAN
+ void setErrorString(const QString &function, TInt errorCode);
+#else
+ void setErrorString(const QString &function);
+#endif
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ bool tryLocker(QSharedMemoryLocker *locker, const QString function) {
+ if (!locker->lock()) {
+ errorString = QSharedMemory::tr("%1: unable to lock").arg(function);
+ error = QSharedMemory::LockError;
+ return false;
+ }
+ return true;
+ }
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+private:
+#ifdef Q_OS_WIN
+ HANDLE hand;
+#elif defined(Q_OS_SYMBIAN)
+ RChunk chunk;
+#else
+ key_t unix_key;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SHAREDMEMORY
+
+#endif // QSHAREDMEMORY_P_H
+
diff --git a/src/corelib/kernel/qsharedmemory_symbian.cpp b/src/corelib/kernel/qsharedmemory_symbian.cpp
new file mode 100644
index 0000000000..3565e264db
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_symbian.cpp
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include "qcore_symbian_p.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SHAREDMEMORY
+
+#define QSHAREDMEMORY_DEBUG
+
+QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
+ memory(0), size(0), error(QSharedMemory::NoError),
+ systemSemaphore(QString()), lockedByMe(false)
+{
+}
+
+void QSharedMemoryPrivate::setErrorString(const QString &function, TInt errorCode)
+{
+ if (errorCode == KErrNone)
+ return;
+ switch (errorCode) {
+ case KErrAlreadyExists:
+ error = QSharedMemory::AlreadyExists;
+ errorString = QSharedMemory::tr("%1: already exists").arg(function);
+ break;
+ case KErrNotFound:
+ error = QSharedMemory::NotFound;
+ errorString = QSharedMemory::tr("%1: doesn't exists").arg(function);
+ break;
+ case KErrArgument:
+ error = QSharedMemory::InvalidSize;
+ errorString = QSharedMemory::tr("%1: invalid size").arg(function);
+ break;
+ case KErrNoMemory:
+ error = QSharedMemory::OutOfResources;
+ errorString = QSharedMemory::tr("%1: out of resources").arg(function);
+ break;
+ case KErrPermissionDenied:
+ error = QSharedMemory::PermissionDenied;
+ errorString = QSharedMemory::tr("%1: permission denied").arg(function);
+ break;
+ default:
+ errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errorCode);
+ error = QSharedMemory::UnknownError;
+#if defined QSHAREDMEMORY_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+ }
+}
+
+key_t QSharedMemoryPrivate::handle()
+{
+ // Not really cost effective to check here if shared memory is attachable, as it requires
+ // exactly the same call as attaching, so always assume handle is valid and return failure
+ // from attach.
+ return 1;
+}
+
+bool QSharedMemoryPrivate::cleanHandle()
+{
+ chunk.Close();
+ return true;
+}
+
+bool QSharedMemoryPrivate::create(int size)
+{
+ QString function = QLatin1String("QSharedMemory::create");
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: key error").arg(function);
+ return false;
+ }
+
+ TPtrC ptr(qt_QString2TPtrC(nativeKey));
+
+ TInt err = chunk.CreateGlobal(ptr, size, size);
+
+ setErrorString(function, err);
+
+ if (err != KErrNone)
+ return false;
+
+ // Zero out the created chunk
+ Mem::FillZ(chunk.Base(), chunk.Size());
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode /* mode */)
+{
+ // Grab a pointer to the memory block
+ if (!chunk.Handle()) {
+ QString function = QLatin1String("QSharedMemory::handle");
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
+ return false;
+ }
+
+ TPtrC ptr(qt_QString2TPtrC(nativeKey));
+
+ TInt err = KErrNoMemory;
+
+ err = chunk.OpenGlobal(ptr, false);
+
+ if (err != KErrNone) {
+ setErrorString(function, err);
+ return false;
+ }
+ }
+
+ size = chunk.Size();
+ memory = chunk.Base();
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::detach()
+{
+ chunk.Close();
+
+ memory = 0;
+ size = 0;
+
+ return true;
+}
+
+#endif //QT_NO_SHAREDMEMORY
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
new file mode 100644
index 0000000000..b30117f6c1
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -0,0 +1,302 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qplatformdefs.h"
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdir.h>
+#include <qdebug.h>
+
+#include <errno.h>
+
+#ifndef QT_NO_SHAREDMEMORY
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif //QT_NO_SHAREDMEMORY
+
+#include "private/qcore_unix_p.h"
+
+#ifndef QT_NO_SHAREDMEMORY
+QT_BEGIN_NAMESPACE
+
+QSharedMemoryPrivate::QSharedMemoryPrivate()
+ : QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
+#ifndef QT_NO_SYSTEMSEMAPHORE
+ systemSemaphore(QString()), lockedByMe(false),
+#endif
+ unix_key(0)
+{
+}
+
+void QSharedMemoryPrivate::setErrorString(const QString &function)
+{
+ // EINVAL is handled in functions so they can give better error strings
+ switch (errno) {
+ case EACCES:
+ errorString = QSharedMemory::tr("%1: permission denied").arg(function);
+ error = QSharedMemory::PermissionDenied;
+ break;
+ case EEXIST:
+ errorString = QSharedMemory::tr("%1: already exists").arg(function);
+ error = QSharedMemory::AlreadyExists;
+ break;
+ case ENOENT:
+ errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
+ error = QSharedMemory::NotFound;
+ break;
+ case EMFILE:
+ case ENOMEM:
+ case ENOSPC:
+ errorString = QSharedMemory::tr("%1: out of resources").arg(function);
+ error = QSharedMemory::OutOfResources;
+ break;
+ default:
+ errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errno);
+ error = QSharedMemory::UnknownError;
+#if defined QSHAREDMEMORY_DEBUG
+ qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
+#endif
+ }
+}
+
+/*!
+ \internal
+
+ If not already made create the handle used for accessing the shared memory.
+*/
+key_t QSharedMemoryPrivate::handle()
+{
+ // already made
+ if (unix_key)
+ return unix_key;
+
+ // don't allow making handles on empty keys
+ if (nativeKey.isEmpty()) {
+ errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::KeyError;
+ return 0;
+ }
+
+ // ftok requires that an actual file exists somewhere
+ if (!QFile::exists(nativeKey)) {
+ errorString = QSharedMemory::tr("%1: UNIX key file doesn't exist").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::NotFound;
+ return 0;
+ }
+
+ unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q');
+ if (-1 == unix_key) {
+ errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::KeyError;
+ unix_key = 0;
+ }
+ return unix_key;
+}
+
+#endif // QT_NO_SHAREDMEMORY
+
+#if !(defined(QT_NO_SHAREDMEMORY) && defined(QT_NO_SYSTEMSEMAPHORE))
+/*!
+ \internal
+ Creates the unix file if needed.
+ returns true if the unix file was created.
+
+ -1 error
+ 0 already existed
+ 1 created
+ */
+int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName)
+{
+ if (QFile::exists(fileName))
+ return 0;
+
+ int fd = qt_safe_open(QFile::encodeName(fileName).constData(),
+ O_EXCL | O_CREAT | O_RDWR, 0640);
+ if (-1 == fd) {
+ if (errno == EEXIST)
+ return 0;
+ return -1;
+ } else {
+ close(fd);
+ }
+ return 1;
+}
+#endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE
+
+#ifndef QT_NO_SHAREDMEMORY
+
+bool QSharedMemoryPrivate::cleanHandle()
+{
+ unix_key = 0;
+ return true;
+}
+
+bool QSharedMemoryPrivate::create(int size)
+{
+ // build file if needed
+ bool createdFile = false;
+ int built = createUnixKeyFile(nativeKey);
+ if (built == -1) {
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::KeyError;
+ return false;
+ }
+ if (built == 1) {
+ createdFile = true;
+ }
+
+ // get handle
+ if (!handle()) {
+ if (createdFile)
+ QFile::remove(nativeKey);
+ return false;
+ }
+
+ // create
+ if (-1 == shmget(unix_key, size, 0666 | IPC_CREAT | IPC_EXCL)) {
+ QString function = QLatin1String("QSharedMemory::create");
+ switch (errno) {
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: system-imposed size restrictions").arg(QLatin1String("QSharedMemory::handle"));
+ error = QSharedMemory::InvalidSize;
+ break;
+ default:
+ setErrorString(function);
+ }
+ if (createdFile && error != QSharedMemory::AlreadyExists)
+ QFile::remove(nativeKey);
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
+{
+ // grab the shared memory segment id
+ int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660));
+ if (-1 == id) {
+ setErrorString(QLatin1String("QSharedMemory::attach (shmget)"));
+ return false;
+ }
+
+ // grab the memory
+ memory = shmat(id, 0, (mode == QSharedMemory::ReadOnly ? SHM_RDONLY : 0));
+ if ((void*) - 1 == memory) {
+ memory = 0;
+ setErrorString(QLatin1String("QSharedMemory::attach (shmat)"));
+ return false;
+ }
+
+ // grab the size
+ shmid_ds shmid_ds;
+ if (!shmctl(id, IPC_STAT, &shmid_ds)) {
+ size = (int)shmid_ds.shm_segsz;
+ } else {
+ setErrorString(QLatin1String("QSharedMemory::attach (shmctl)"));
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::detach()
+{
+ // detach from the memory segment
+ if (-1 == shmdt(memory)) {
+ QString function = QLatin1String("QSharedMemory::detach");
+ switch (errno) {
+ case EINVAL:
+ errorString = QSharedMemory::tr("%1: not attached").arg(function);
+ error = QSharedMemory::NotFound;
+ break;
+ default:
+ setErrorString(function);
+ }
+ return false;
+ }
+ memory = 0;
+ size = 0;
+
+ // Get the number of current attachments
+ int id = shmget(unix_key, 0, 0444);
+ cleanHandle();
+
+ struct shmid_ds shmid_ds;
+ if (0 != shmctl(id, IPC_STAT, &shmid_ds)) {
+ switch (errno) {
+ case EINVAL:
+ return true;
+ default:
+ return false;
+ }
+ }
+ // If there are no attachments then remove it.
+ if (shmid_ds.shm_nattch == 0) {
+ // mark for removal
+ if (-1 == shmctl(id, IPC_RMID, &shmid_ds)) {
+ setErrorString(QLatin1String("QSharedMemory::remove"));
+ switch (errno) {
+ case EINVAL:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ // remove file
+ if (!QFile::remove(nativeKey))
+ return false;
+ }
+ return true;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SHAREDMEMORY
diff --git a/src/corelib/kernel/qsharedmemory_win.cpp b/src/corelib/kernel/qsharedmemory_win.cpp
new file mode 100644
index 0000000000..bc13e338bd
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SHAREDMEMORY
+
+QSharedMemoryPrivate::QSharedMemoryPrivate() : QObjectPrivate(),
+ memory(0), size(0), error(QSharedMemory::NoError),
+ systemSemaphore(QString()), lockedByMe(false), hand(0)
+{
+}
+
+void QSharedMemoryPrivate::setErrorString(const QString &function)
+{
+ BOOL windowsError = GetLastError();
+ if (windowsError == 0)
+ return;
+ switch (windowsError) {
+ case ERROR_ALREADY_EXISTS:
+ error = QSharedMemory::AlreadyExists;
+ errorString = QSharedMemory::tr("%1: already exists").arg(function);
+ break;
+ case ERROR_FILE_NOT_FOUND:
+#ifdef Q_OS_WINCE
+ // This happens on CE only if no file is present as CreateFileMappingW
+ // bails out with this error code
+ case ERROR_INVALID_PARAMETER:
+#endif
+ error = QSharedMemory::NotFound;
+ errorString = QSharedMemory::tr("%1: doesn't exist").arg(function);
+ break;
+ case ERROR_COMMITMENT_LIMIT:
+ error = QSharedMemory::InvalidSize;
+ errorString = QSharedMemory::tr("%1: invalid size").arg(function);
+ break;
+ case ERROR_NO_SYSTEM_RESOURCES:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ error = QSharedMemory::OutOfResources;
+ errorString = QSharedMemory::tr("%1: out of resources").arg(function);
+ break;
+ case ERROR_ACCESS_DENIED:
+ error = QSharedMemory::PermissionDenied;
+ errorString = QSharedMemory::tr("%1: permission denied").arg(function);
+ break;
+ default:
+ errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(windowsError);
+ error = QSharedMemory::UnknownError;
+#if defined QSHAREDMEMORY_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+ }
+}
+
+HANDLE QSharedMemoryPrivate::handle()
+{
+ if (!hand) {
+ QString function = QLatin1String("QSharedMemory::handle");
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
+ return false;
+ }
+#ifndef Q_OS_WINCE
+ hand = OpenFileMapping(FILE_MAP_ALL_ACCESS, false, (wchar_t*)nativeKey.utf16());
+#else
+ // This works for opening a mapping too, but always opens it with read/write access in
+ // attach as it seems.
+ hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, 0, (wchar_t*)nativeKey.utf16());
+#endif
+ if (!hand) {
+ setErrorString(function);
+ return false;
+ }
+ }
+ return hand;
+}
+
+bool QSharedMemoryPrivate::cleanHandle()
+{
+ if (hand != 0 && !CloseHandle(hand)) {
+ hand = 0;
+ setErrorString(QLatin1String("QSharedMemory::cleanHandle"));
+ return false;
+ }
+ hand = 0;
+ return true;
+}
+
+bool QSharedMemoryPrivate::create(int size)
+{
+ QString function = QLatin1String("QSharedMemory::create");
+ if (nativeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: key error").arg(function);
+ return false;
+ }
+
+ // Create the file mapping.
+ hand = CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0, size, (wchar_t*)nativeKey.utf16());
+ setErrorString(function);
+
+ // hand is valid when it already exists unlike unix so explicitly check
+ if (error == QSharedMemory::AlreadyExists || !hand)
+ return false;
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
+{
+ // Grab a pointer to the memory block
+ int permissions = (mode == QSharedMemory::ReadOnly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS);
+ memory = (void *)MapViewOfFile(handle(), permissions, 0, 0, 0);
+ if (0 == memory) {
+ setErrorString(QLatin1String("QSharedMemory::attach"));
+ cleanHandle();
+ return false;
+ }
+
+ // Grab the size of the memory we have been given (a multiple of 4K on windows)
+ MEMORY_BASIC_INFORMATION info;
+ if (!VirtualQuery(memory, &info, sizeof(info))) {
+ // Windows doesn't set an error code on this one,
+ // it should only be a kernel memory error.
+ error = QSharedMemory::UnknownError;
+ errorString = QSharedMemory::tr("%1: size query failed").arg(QLatin1String("QSharedMemory::attach: "));
+ return false;
+ }
+ size = info.RegionSize;
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::detach()
+{
+ // umap memory
+ if (!UnmapViewOfFile(memory)) {
+ setErrorString(QLatin1String("QSharedMemory::detach"));
+ return false;
+ }
+ memory = 0;
+ size = 0;
+
+ // close handle
+ return cleanHandle();
+}
+
+#endif //QT_NO_SHAREDMEMORY
+
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
new file mode 100644
index 0000000000..017aa72376
--- /dev/null
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsignalmapper.h"
+#ifndef QT_NO_SIGNALMAPPER
+#include "qhash.h"
+#include "qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSignalMapperPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSignalMapper)
+public:
+ void _q_senderDestroyed() {
+ Q_Q(QSignalMapper);
+ q->removeMappings(q->sender());
+ }
+ QHash<QObject *, int> intHash;
+ QHash<QObject *, QString> stringHash;
+ QHash<QObject *, QWidget*> widgetHash;
+ QHash<QObject *, QObject*> objectHash;
+
+};
+
+
+/*!
+ \class QSignalMapper
+ \brief The QSignalMapper class bundles signals from identifiable senders.
+
+ \ingroup objectmodel
+
+
+ This class collects a set of parameterless signals, and re-emits
+ them with integer, string or widget parameters corresponding to
+ the object that sent the signal.
+
+ The class supports the mapping of particular strings or integers
+ with particular objects using setMapping(). The objects' signals
+ can then be connected to the map() slot which will emit the
+ mapped() signal with the string or integer associated with the
+ original signalling object. Mappings can be removed later using
+ removeMappings().
+
+ Example: Suppose we want to create a custom widget that contains
+ a group of buttons (like a tool palette). One approach is to
+ connect each button's \c clicked() signal to its own custom slot;
+ but in this example we want to connect all the buttons to a
+ single slot and parameterize the slot by the button that was
+ clicked.
+
+ Here's the definition of a simple custom widget that has a single
+ signal, \c clicked(), which is emitted with the text of the button
+ that was clicked:
+
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.h 0
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.h 1
+
+ The only function that we need to implement is the constructor:
+
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 0
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 1
+ \snippet doc/src/snippets/qsignalmapper/buttonwidget.cpp 2
+
+ A list of texts is passed to the constructor. A signal mapper is
+ constructed and for each text in the list a QPushButton is
+ created. We connect each button's \c clicked() signal to the
+ signal mapper's map() slot, and create a mapping in the signal
+ mapper from each button to the button's text. Finally we connect
+ the signal mapper's mapped() signal to the custom widget's \c
+ clicked() signal. When the user clicks a button, the custom
+ widget will emit a single \c clicked() signal whose argument is
+ the text of the button the user clicked.
+
+ \sa QObject, QButtonGroup, QActionGroup
+*/
+
+/*!
+ Constructs a QSignalMapper with parent \a parent.
+*/
+QSignalMapper::QSignalMapper(QObject* parent)
+ : QObject(*new QSignalMapperPrivate, parent)
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload QSignalMapper()
+ \obsolete
+ */
+QSignalMapper::QSignalMapper(QObject *parent, const char *name)
+ : QObject(*new QSignalMapperPrivate, parent)
+{
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*!
+ Destroys the QSignalMapper.
+*/
+QSignalMapper::~QSignalMapper()
+{
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the given \a
+ sender, the signal mapped(\a id) is emitted.
+
+ There may be at most one integer ID for each sender.
+
+ \sa mapping()
+*/
+void QSignalMapper::setMapping(QObject *sender, int id)
+{
+ Q_D(QSignalMapper);
+ d->intHash.insert(sender, id);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the \a sender,
+ the signal mapped(\a text ) is emitted.
+
+ There may be at most one text for each sender.
+*/
+void QSignalMapper::setMapping(QObject *sender, const QString &text)
+{
+ Q_D(QSignalMapper);
+ d->stringHash.insert(sender, text);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the \a sender,
+ the signal mapped(\a widget ) is emitted.
+
+ There may be at most one widget for each sender.
+*/
+void QSignalMapper::setMapping(QObject *sender, QWidget *widget)
+{
+ Q_D(QSignalMapper);
+ d->widgetHash.insert(sender, widget);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Adds a mapping so that when map() is signalled from the \a sender,
+ the signal mapped(\a object ) is emitted.
+
+ There may be at most one object for each sender.
+*/
+void QSignalMapper::setMapping(QObject *sender, QObject *object)
+{
+ Q_D(QSignalMapper);
+ d->objectHash.insert(sender, object);
+ connect(sender, SIGNAL(destroyed()), this, SLOT(_q_senderDestroyed()));
+}
+
+/*!
+ Returns the sender QObject that is associated with the \a id.
+
+ \sa setMapping()
+*/
+QObject *QSignalMapper::mapping(int id) const
+{
+ Q_D(const QSignalMapper);
+ return d->intHash.key(id);
+}
+
+/*!
+ \overload mapping()
+*/
+QObject *QSignalMapper::mapping(const QString &id) const
+{
+ Q_D(const QSignalMapper);
+ return d->stringHash.key(id);
+}
+
+/*!
+ \overload mapping()
+
+ Returns the sender QObject that is associated with the \a widget.
+*/
+QObject *QSignalMapper::mapping(QWidget *widget) const
+{
+ Q_D(const QSignalMapper);
+ return d->widgetHash.key(widget);
+}
+
+/*!
+ \overload mapping()
+
+ Returns the sender QObject that is associated with the \a object.
+*/
+QObject *QSignalMapper::mapping(QObject *object) const
+{
+ Q_D(const QSignalMapper);
+ return d->objectHash.key(object);
+}
+
+/*!
+ Removes all mappings for \a sender.
+
+ This is done automatically when mapped objects are destroyed.
+*/
+void QSignalMapper::removeMappings(QObject *sender)
+{
+ Q_D(QSignalMapper);
+
+ d->intHash.remove(sender);
+ d->stringHash.remove(sender);
+ d->widgetHash.remove(sender);
+ d->objectHash.remove(sender);
+}
+
+/*!
+ This slot emits signals based on which object sends signals to it.
+*/
+void QSignalMapper::map() { map(sender()); }
+
+/*!
+ This slot emits signals based on the \a sender object.
+*/
+void QSignalMapper::map(QObject *sender)
+{
+ Q_D(QSignalMapper);
+ if (d->intHash.contains(sender))
+ emit mapped(d->intHash.value(sender));
+ if (d->stringHash.contains(sender))
+ emit mapped(d->stringHash.value(sender));
+ if (d->widgetHash.contains(sender))
+ emit mapped(d->widgetHash.value(sender));
+ if (d->objectHash.contains(sender))
+ emit mapped(d->objectHash.value(sender));
+}
+
+
+/*!
+ \fn void QSignalMapper::mapped(int i)
+
+ This signal is emitted when map() is signalled from an object that
+ has an integer mapping set. The object's mapped integer is passed
+ in \a i.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mapped(const QString &text)
+
+ This signal is emitted when map() is signalled from an object that
+ has a string mapping set. The object's mapped string is passed in
+ \a text.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mapped(QWidget *widget)
+
+ This signal is emitted when map() is signalled from an object that
+ has a widget mapping set. The object's mapped widget is passed in
+ \a widget.
+
+ \sa setMapping()
+*/
+
+/*!
+ \fn void QSignalMapper::mapped(QObject *object)
+
+ This signal is emitted when map() is signalled from an object that
+ has an object mapping set. The object provided by the map is passed in
+ \a object.
+
+ \sa setMapping()
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qsignalmapper.cpp"
+
+#endif // QT_NO_SIGNALMAPPER
+
diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h
new file mode 100644
index 0000000000..ddf5c34e47
--- /dev/null
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QSIGNALMAPPER_H
+#define QSIGNALMAPPER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_SIGNALMAPPER
+class QSignalMapperPrivate;
+
+class Q_CORE_EXPORT QSignalMapper : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSignalMapper)
+public:
+ explicit QSignalMapper(QObject *parent = 0);
+ ~QSignalMapper();
+
+ void setMapping(QObject *sender, int id);
+ void setMapping(QObject *sender, const QString &text);
+ void setMapping(QObject *sender, QWidget *widget);
+ void setMapping(QObject *sender, QObject *object);
+ void removeMappings(QObject *sender);
+
+ QObject *mapping(int id) const;
+ QObject *mapping(const QString &text) const;
+ QObject *mapping(QWidget *widget) const;
+ QObject *mapping(QObject *object) const;
+
+Q_SIGNALS:
+ void mapped(int);
+ void mapped(const QString &);
+ void mapped(QWidget *);
+ void mapped(QObject *);
+
+public Q_SLOTS:
+ void map();
+ void map(QObject *sender);
+
+private:
+ Q_DISABLE_COPY(QSignalMapper)
+ Q_PRIVATE_SLOT(d_func(), void _q_senderDestroyed())
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT_CONSTRUCTOR QSignalMapper(QObject *parent, const char *name);
+#endif
+};
+#endif // QT_NO_SIGNALMAPPER
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSIGNALMAPPER_H
diff --git a/src/corelib/kernel/qsocketnotifier.cpp b/src/corelib/kernel/qsocketnotifier.cpp
new file mode 100644
index 0000000000..360bc372f0
--- /dev/null
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsocketnotifier.h"
+
+#include "qplatformdefs.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+
+#include "qobject_p.h"
+#include <private/qthread_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSocketNotifier
+ \brief The QSocketNotifier class provides support for monitoring
+ activity on a file descriptor.
+
+ \ingroup network
+ \ingroup io
+
+ The QSocketNotifier makes it possible to integrate Qt's event
+ loop with other event loops based on file descriptors. For
+ example, the \l{CORBA Framework} uses it to process CORBA
+ events. File descriptor action is detected in Qt's main event
+ loop (QCoreApplication::exec()).
+
+ \target write notifiers
+
+ Once you have opened a device using a low-level (usually
+ platform-specific) API, you can create a socket notifier to
+ monitor the file descriptor. The socket notifier is enabled by
+ default, i.e. it emits the activated() signal whenever a socket
+ event corresponding to its type occurs. Connect the activated()
+ signal to the slot you want to be called when an event
+ corresponding to your socket notifier's type occurs.
+
+ There are three types of socket notifiers: read, write, and
+ exception. The type is described by the \l Type enum, and must be
+ specified when constructing the socket notifier. After
+ construction it can be determined using the type() function. Note
+ that if you need to monitor both reads and writes for the same
+ file descriptor, you must create two socket notifiers. Note also
+ that it is not possible to install two socket notifiers of the
+ same type (\l Read, \l Write, \l Exception) on the same socket.
+
+ The setEnabled() function allows you to disable as well as enable
+ the socket notifier. It is generally advisable to explicitly
+ enable or disable the socket notifier, especially for write
+ notifiers. A disabled notifier ignores socket events (the same
+ effect as not creating the socket notifier). Use the isEnabled()
+ function to determine the notifier's current status.
+
+ Finally, you can use the socket() function to retrieve the
+ socket identifier. Although the class is called QSocketNotifier,
+ it is normally used for other types of devices than sockets.
+ QTcpSocket and QUdpSocket provide notification through signals, so
+ there is normally no need to use a QSocketNotifier on them.
+
+ \section1 Notes for Windows Users
+
+ The socket passed to QSocketNotifier will become non-blocking, even if
+ it was created as a blocking socket.
+ The activated() signal is sometimes triggered by high general activity
+ on the host, even if there is nothing to read. A subsequent read from
+ the socket can then fail, the error indicating that there is no data
+ available (e.g., \c{WSAEWOULDBLOCK}). This is an operating system
+ limitation, and not a bug in QSocketNotifier.
+
+ To ensure that the socket notifier handles read notifications correctly,
+ follow these steps when you receive a notification:
+
+ \list 1
+ \o Disable the notifier.
+ \o Read data from the socket.
+ \o Re-enable the notifier if you are interested in more data (such as after
+ having written a new command to a remote server).
+ \endlist
+
+ To ensure that the socket notifier handles write notifications correctly,
+ follow these steps when you receive a notification:
+
+ \list 1
+ \o Disable the notifier.
+ \o Write as much data as you can (before \c EWOULDBLOCK is returned).
+ \o Re-enable notifier if you have more data to write.
+ \endlist
+
+ \bold{Further information:}
+ On Windows, Qt always disables the notifier after getting a notification,
+ and only re-enables it if more data is expected. For example, if data is
+ read from the socket and it can be used to read more, or if reading or
+ writing is not possible because the socket would block, in which case
+ it is necessary to wait before attempting to read or write again.
+
+ \sa QFile, QProcess, QTcpSocket, QUdpSocket
+*/
+
+/*!
+ \enum QSocketNotifier::Type
+
+ This enum describes the various types of events that a socket
+ notifier can recognize. The type must be specified when
+ constructing the socket notifier.
+
+ Note that if you need to monitor both reads and writes for the
+ same file descriptor, you must create two socket notifiers. Note
+ also that it is not possible to install two socket notifiers of
+ the same type (Read, Write, Exception) on the same socket.
+
+ \value Read There is data to be read.
+ \value Write Data can be written.
+ \value Exception An exception has occurred. We recommend against using this.
+
+ \sa QSocketNotifier(), type()
+*/
+
+/*!
+ Constructs a socket notifier with the given \a parent. It enables
+ the \a socket, and watches for events of the given \a type.
+
+ It is generally advisable to explicitly enable or disable the
+ socket notifier, especially for write notifiers.
+
+ \bold{Note for Windows users:} The socket passed to QSocketNotifier
+ will become non-blocking, even if it was created as a blocking socket.
+
+ \sa setEnabled(), isEnabled()
+*/
+
+QSocketNotifier::QSocketNotifier(int socket, Type type, QObject *parent)
+ : QObject(parent)
+{
+ if (socket < 0)
+ qWarning("QSocketNotifier: Invalid socket specified");
+ sockfd = socket;
+ sntype = type;
+ snenabled = true;
+
+ Q_D(QObject);
+ if (!d->threadData->eventDispatcher) {
+ qWarning("QSocketNotifier: Can only be used with threads started with QThread");
+ } else {
+ d->threadData->eventDispatcher->registerSocketNotifier(this);
+ }
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \obsolete
+
+ Use the QSocketNotifier() constructor combined with the
+ QObject::setObjectName() function instead.
+
+ \oldcode
+ QSocketNotifier *notifier = new QSocketNotifier(socket, type, parent, name);
+ \newcode
+ QSocketNotifier *notifier = new QSocketNotifier(socket, type, parent);
+ notifier->setObjectName(name);
+ \endcode
+*/
+
+QSocketNotifier::QSocketNotifier(int socket, Type type, QObject *parent,
+ const char *name)
+ : QObject(parent)
+{
+ setObjectName(QString::fromAscii(name));
+ if (socket < 0)
+ qWarning("QSocketNotifier: Invalid socket specified");
+ sockfd = socket;
+ sntype = type;
+ snenabled = true;
+
+ Q_D(QObject);
+ if (!d->threadData->eventDispatcher) {
+ qWarning("QSocketNotifier: Can only be used with threads started with QThread");
+ } else {
+ d->threadData->eventDispatcher->registerSocketNotifier(this);
+ }
+}
+#endif
+/*!
+ Destroys this socket notifier.
+*/
+
+QSocketNotifier::~QSocketNotifier()
+{
+ setEnabled(false);
+}
+
+
+/*!
+ \fn void QSocketNotifier::activated(int socket)
+
+ This signal is emitted whenever the socket notifier is enabled and
+ a socket event corresponding to its \l {Type}{type} occurs.
+
+ The socket identifier is passed in the \a socket parameter.
+
+ \sa type(), socket()
+*/
+
+
+/*!
+ \fn int QSocketNotifier::socket() const
+
+ Returns the socket identifier specified to the constructor.
+
+ \sa type()
+*/
+
+/*!
+ \fn Type QSocketNotifier::type() const
+
+ Returns the socket event type specified to the constructor.
+
+ \sa socket()
+*/
+
+
+/*!
+ \fn bool QSocketNotifier::isEnabled() const
+
+ Returns true if the notifier is enabled; otherwise returns false.
+
+ \sa setEnabled()
+*/
+
+/*!
+ If \a enable is true, the notifier is enabled; otherwise the notifier
+ is disabled.
+
+ The notifier is enabled by default, i.e. it emits the activated()
+ signal whenever a socket event corresponding to its
+ \l{type()}{type} occurs. If it is disabled, it ignores socket
+ events (the same effect as not creating the socket notifier).
+
+ Write notifiers should normally be disabled immediately after the
+ activated() signal has been emitted
+
+ \sa isEnabled(), activated()
+*/
+
+void QSocketNotifier::setEnabled(bool enable)
+{
+ if (sockfd < 0)
+ return;
+ if (snenabled == enable) // no change
+ return;
+ snenabled = enable;
+
+ Q_D(QObject);
+ if (!d->threadData->eventDispatcher) // perhaps application/thread is shutting down
+ return;
+ if (snenabled)
+ d->threadData->eventDispatcher->registerSocketNotifier(this);
+ else
+ d->threadData->eventDispatcher->unregisterSocketNotifier(this);
+}
+
+
+/*!\reimp
+*/
+bool QSocketNotifier::event(QEvent *e)
+{
+ // Emits the activated() signal when a QEvent::SockAct is
+ // received.
+ if (e->type() == QEvent::ThreadChange) {
+ if (snenabled) {
+ QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
+ Q_ARG(bool, snenabled));
+ setEnabled(false);
+ }
+ }
+ QObject::event(e); // will activate filters
+ if (e->type() == QEvent::SockAct) {
+ emit activated(sockfd);
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsocketnotifier.h b/src/corelib/kernel/qsocketnotifier.h
new file mode 100644
index 0000000000..13a5160e3c
--- /dev/null
+++ b/src/corelib/kernel/qsocketnotifier.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QSOCKETNOTIFIER_H
+#define QSOCKETNOTIFIER_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QSocketNotifier : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ enum Type { Read, Write, Exception };
+
+ QSocketNotifier(int socket, Type, QObject *parent = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QSocketNotifier(int socket, Type, QObject *parent, const char *name);
+#endif
+ ~QSocketNotifier();
+
+ inline int socket() const { return sockfd; }
+ inline Type type() const { return sntype; }
+
+ inline bool isEnabled() const { return snenabled; }
+
+public Q_SLOTS:
+ void setEnabled(bool);
+
+Q_SIGNALS:
+ void activated(int socket);
+
+protected:
+ bool event(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QSocketNotifier)
+
+ int sockfd;
+ Type sntype;
+ bool snenabled;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSOCKETNOTIFIER_H
diff --git a/src/corelib/kernel/qsystemerror.cpp b/src/corelib/kernel/qsystemerror.cpp
new file mode 100644
index 0000000000..18622c7a08
--- /dev/null
+++ b/src/corelib/kernel/qsystemerror.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 <qglobal.h>
+#include "qsystemerror_p.h"
+#if !defined(Q_OS_WINCE)
+# include <errno.h>
+# if defined(Q_CC_MSVC)
+# include <crtdbg.h>
+# endif
+#endif
+#ifdef Q_OS_WIN
+#include <windows.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_OS_WIN) && !defined(QT_NO_THREAD) && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX) && \
+ defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L
+namespace {
+ // There are two incompatible versions of strerror_r:
+ // a) the XSI/POSIX.1 version, which returns an int,
+ // indicating success or not
+ // b) the GNU version, which returns a char*, which may or may not
+ // be the beginning of the buffer we used
+ // The GNU libc manpage for strerror_r says you should use the the XSI
+ // version in portable code. However, it's impossible to do that if
+ // _GNU_SOURCE is defined so we use C++ overloading to decide what to do
+ // depending on the return type
+ static inline QString fromstrerror_helper(int, const QByteArray &buf)
+ {
+ return QString::fromLocal8Bit(buf);
+ }
+ static inline QString fromstrerror_helper(const char *str, const QByteArray &)
+ {
+ return QString::fromLocal8Bit(str);
+ }
+}
+#endif
+
+static QString standardLibraryErrorString(int errorCode)
+{
+ const char *s = 0;
+ QString ret;
+ switch (errorCode) {
+ case 0:
+ break;
+ case EACCES:
+ s = QT_TRANSLATE_NOOP("QIODevice", "Permission denied");
+ break;
+ case EMFILE:
+ s = QT_TRANSLATE_NOOP("QIODevice", "Too many open files");
+ break;
+ case ENOENT:
+ s = QT_TRANSLATE_NOOP("QIODevice", "No such file or directory");
+ break;
+ case ENOSPC:
+ s = QT_TRANSLATE_NOOP("QIODevice", "No space left on device");
+ break;
+ default: {
+ #if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && _POSIX_VERSION >= 200112L && !defined(Q_OS_INTEGRITY) && !defined(Q_OS_QNX)
+ QByteArray buf(1024, '\0');
+ ret = fromstrerror_helper(strerror_r(errorCode, buf.data(), buf.size()), buf);
+ #else
+ ret = QString::fromLocal8Bit(strerror(errorCode));
+ #endif
+ break; }
+ }
+ if (s) {
+ // ######## this breaks moc build currently
+ // ret = QCoreApplication::translate("QIODevice", s);
+ ret = QString::fromLatin1(s);
+ }
+ return ret.trimmed();
+}
+
+#ifdef Q_OS_WIN
+static QString windowsErrorString(int errorCode)
+{
+ QString ret;
+ wchar_t *string = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ errorCode,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&string,
+ 0,
+ NULL);
+ ret = QString::fromWCharArray(string);
+ LocalFree((HLOCAL)string);
+
+ if (ret.isEmpty() && errorCode == ERROR_MOD_NOT_FOUND)
+ ret = QString::fromLatin1("The specified module could not be found.");
+ return ret;
+}
+#endif
+
+#ifdef Q_OS_SYMBIAN
+static QString symbianErrorString(int errorCode)
+{
+ switch (errorCode) {
+ case KErrNotFound:
+ return QLatin1String("not found");
+ case KErrCancel:
+ return QLatin1String("cancelled");
+ case KErrNoMemory:
+ return QLatin1String("out of memory");
+ case KErrNotSupported:
+ return QLatin1String("not supported");
+ case KErrBadHandle:
+ return QLatin1String("bad handle"); //KERN-EXEC 0 panic is more likely
+ case KErrAlreadyExists:
+ return QLatin1String("already exists");
+ case KErrPathNotFound:
+ return QLatin1String("path not found");
+ case KErrInUse:
+ return QLatin1String("in use");
+ case KErrNotReady:
+ return QLatin1String("not ready (e.g. FS dismounted, network down)");
+ case KErrCorrupt:
+ return QLatin1String("corrupt");
+ case KErrAccessDenied:
+ return QLatin1String("access denied");
+ case KErrLocked:
+ return QLatin1String("locked");
+ case KErrWrite:
+ return QLatin1String("incomplete write error");
+ case KErrDisMounted:
+ return QLatin1String("file system dismounted during operation"); //i.e. a forcible dismount was done while we had files open
+ case KErrEof:
+ return QLatin1String("end of file");
+ case KErrDiskFull:
+ return QLatin1String("no space in file system");
+ case KErrBadName:
+ return QLatin1String("invalid filename");
+ case KErrTimedOut:
+ return QLatin1String("timed out");
+ case KErrBadDescriptor:
+ return QLatin1String("bad descriptor (passed address on stack to async call?)");
+ case KErrAbort:
+ return QLatin1String("aborted");
+ case KErrTooBig:
+ return QLatin1String("too big"); //e.g. trying to open a >2GB file with 32 bit API
+ case KErrBadPower:
+ return QLatin1String("insufficient power");
+ case KErrDirFull:
+ return QLatin1String("no space in directory table");
+ case KErrHardwareNotAvailable:
+ return QLatin1String("hardware not available");
+ case KErrSessionClosed:
+ return QLatin1String("session closed");
+ case KErrPermissionDenied:
+ return QLatin1String("permission denied");
+ default:
+ return QString(QLatin1String("symbian error %1")).arg(errorCode);
+ }
+}
+#endif
+
+QString QSystemError::toString()
+{
+ switch(errorScope) {
+ case NativeError:
+#if defined (Q_OS_WIN)
+ return windowsErrorString(errorCode);
+#elif defined (Q_OS_SYMBIAN)
+ return symbianErrorString(errorCode);
+#else
+ //unix: fall through as native and standard library are the same
+#endif
+ case StandardLibraryError:
+ return standardLibraryErrorString(errorCode);
+ default:
+ qWarning("invalid error scope");
+ //fall through
+ case NoError:
+ return QLatin1String("No error");
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/kernel/qsystemerror_p.h b/src/corelib/kernel/qsystemerror_p.h
new file mode 100644
index 0000000000..e96e85a7ad
--- /dev/null
+++ b/src/corelib/kernel/qsystemerror_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QSYSTEMERROR_P_H
+#define QSYSTEMERROR_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 <qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QSystemError
+{
+public:
+ enum ErrorScope
+ {
+ NoError,
+ StandardLibraryError,
+ NativeError
+ };
+
+ inline QSystemError(int error, ErrorScope scope);
+ inline QSystemError();
+
+ QString toString();
+ inline ErrorScope scope();
+ inline int error();
+
+ //data members
+ int errorCode;
+ ErrorScope errorScope;
+};
+
+QSystemError::QSystemError(int error, QSystemError::ErrorScope scope)
+: errorCode(error), errorScope(scope)
+{
+
+}
+
+QSystemError::QSystemError()
+: errorCode(0), errorScope(NoError)
+{
+
+}
+
+QSystemError::ErrorScope QSystemError::scope()
+{
+ return errorScope;
+}
+
+int QSystemError::error()
+{
+ return errorCode;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QSYSTEMERROR_P_H
diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp
new file mode 100644
index 0000000000..80dccc2184
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore.cpp
@@ -0,0 +1,363 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+/*!
+ \class QSystemSemaphore
+ \since 4.4
+
+ \brief The QSystemSemaphore class provides a general counting system semaphore.
+
+ A semaphore is a generalization of a mutex. While a mutex can be
+ locked only once, a semaphore can be acquired multiple times.
+ Typically, a semaphore is used to protect a certain number of
+ identical resources.
+
+ Like its lighter counterpart QSemaphore, a QSystemSemaphore can be
+ accessed from multiple \l {QThread} {threads}. Unlike QSemaphore, a
+ QSystemSemaphore can also be accessed from multiple \l {QProcess}
+ {processes}. This means QSystemSemaphore is a much heavier class, so
+ if your application doesn't need to access your semaphores across
+ multiple processes, you will probably want to use QSemaphore.
+
+ Semaphores support two fundamental operations, acquire() and release():
+
+ acquire() tries to acquire one resource. If there isn't a resource
+ available, the call blocks until a resource becomes available. Then
+ the resource is acquired and the call returns.
+
+ release() releases one resource so it can be acquired by another
+ process. The function can also be called with a parameter n > 1,
+ which releases n resources.
+
+ A system semaphore is created with a string key that other processes
+ can use to use the same semaphore.
+
+ Example: Create a system semaphore
+ \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 0
+
+ A typical application of system semaphores is for controlling access
+ to a circular buffer shared by a producer process and a consumer
+ processes.
+
+ \section1 Platform-Specific Behavior
+
+ When using this class, be aware of the following platform
+ differences:
+
+ \bold{Windows:} QSystemSemaphore does not own its underlying system
+ semaphore. Windows owns it. This means that when all instances of
+ QSystemSemaphore for a particular key have been destroyed, either by
+ having their destructors called, or because one or more processes
+ crash, Windows removes the underlying system semaphore.
+
+ \bold{Unix:}
+
+ \list
+ \o QSystemSemaphore owns the underlying system semaphore
+ in Unix systems. This means that the last process having an instance of
+ QSystemSemaphore for a particular key must remove the underlying
+ system semaphore in its destructor. If the last process crashes
+ without running the QSystemSemaphore destructor, Unix does not
+ automatically remove the underlying system semaphore, and the
+ semaphore survives the crash. A subsequent process that constructs a
+ QSystemSemaphore with the same key will then be given the existing
+ system semaphore. In that case, if the QSystemSemaphore constructor
+ has specified its \l {QSystemSemaphore::AccessMode} {access mode} as
+ \l {QSystemSemaphore::} {Open}, its initial resource count will not
+ be reset to the one provided but remain set to the value it received
+ in the crashed process. To protect against this, the first process
+ to create a semaphore for a particular key (usually a server), must
+ pass its \l {QSystemSemaphore::AccessMode} {access mode} as \l
+ {QSystemSemaphore::} {Create}, which will force Unix to reset the
+ resource count in the underlying system semaphore.
+
+ \o When a process using QSystemSemaphore terminates for
+ any reason, Unix automatically reverses the effect of all acquire
+ operations that were not released. Thus if the process acquires a
+ resource and then exits without releasing it, Unix will release that
+ resource.
+
+ \o Symbian: QSystemSemaphore behaves the same as Windows semaphores.
+ In other words, the operating system owns the semaphore and ignores
+ QSystemSemaphore::AccessMode.
+
+ \endlist
+
+ \sa QSharedMemory, QSemaphore
+ */
+
+/*!
+ Requests a system semaphore for the specified \a key. The parameters
+ \a initialValue and \a mode are used according to the following
+ rules, which are system dependent.
+
+ In Unix, if the \a mode is \l {QSystemSemaphore::} {Open} and the
+ system already has a semaphore identified by \a key, that semaphore
+ is used, and the semaphore's resource count is not changed, i.e., \a
+ initialValue is ignored. But if the system does not already have a
+ semaphore identified by \a key, it creates a new semaphore for that
+ key and sets its resource count to \a initialValue.
+
+ In Unix, if the \a mode is \l {QSystemSemaphore::} {Create} and the
+ system already has a semaphore identified by \a key, that semaphore
+ is used, and its resource count is set to \a initialValue. If the
+ system does not already have a semaphore identified by \a key, it
+ creates a new semaphore for that key and sets its resource count to
+ \a initialValue.
+
+ In Windows and in Symbian, \a mode is ignored, and the system always tries to
+ create a semaphore for the specified \a key. If the system does not
+ already have a semaphore identified as \a key, it creates the
+ semaphore and sets its resource count to \a initialValue. But if the
+ system already has a semaphore identified as \a key it uses that
+ semaphore and ignores \a initialValue.
+
+ The \l {QSystemSemaphore::AccessMode} {mode} parameter is only used
+ in Unix systems to handle the case where a semaphore survives a
+ process crash. In that case, the next process to allocate a
+ semaphore with the same \a key will get the semaphore that survived
+ the crash, and unless \a mode is \l {QSystemSemaphore::} {Create},
+ the resource count will not be reset to \a initialValue but will
+ retain the initial value it had been given by the crashed process.
+
+ \sa acquire(), key()
+ */
+QSystemSemaphore::QSystemSemaphore(const QString &key, int initialValue, AccessMode mode)
+ : d(new QSystemSemaphorePrivate)
+{
+ setKey(key, initialValue, mode);
+}
+
+/*!
+ The destructor destroys the QSystemSemaphore object, but the
+ underlying system semaphore is not removed from the system unless
+ this instance of QSystemSemaphore is the last one existing for that
+ system semaphore.
+
+ Two important side effects of the destructor depend on the system.
+ In Windows, if acquire() has been called for this semaphore but not
+ release(), release() will not be called by the destructor, nor will
+ the resource be released when the process exits normally. This would
+ be a program bug which could be the cause of a deadlock in another
+ process trying to acquire the same resource. In Unix, acquired
+ resources that are not released before the destructor is called are
+ automatically released when the process exits.
+*/
+QSystemSemaphore::~QSystemSemaphore()
+{
+ d->cleanHandle();
+}
+
+/*!
+ \enum QSystemSemaphore::AccessMode
+
+ This enum is used by the constructor and setKey(). Its purpose is to
+ enable handling the problem in Unix implementations of semaphores
+ that survive a crash. In Unix, when a semaphore survives a crash, we
+ need a way to force it to reset its resource count, when the system
+ reuses the semaphore. In Windows and in Symbian, where semaphores can't survive a
+ crash, this enum has no effect.
+
+ \value Open If the semaphore already exists, its initial resource
+ count is not reset. If the semaphore does not already exist, it is
+ created and its initial resource count set.
+
+ \value Create QSystemSemaphore takes ownership of the semaphore and
+ sets its resource count to the requested value, regardless of
+ whether the semaphore already exists by having survived a crash.
+ This value should be passed to the constructor, when the first
+ semaphore for a particular key is constructed and you know that if
+ the semaphore already exists it could only be because of a crash. In
+ Windows and in Symbian, where a semaphore can't survive a crash, Create and Open
+ have the same behavior.
+*/
+
+/*!
+ This function works the same as the constructor. It reconstructs
+ this QSystemSemaphore object. If the new \a key is different from
+ the old key, calling this function is like calling the destructor of
+ the semaphore with the old key, then calling the constructor to
+ create a new semaphore with the new \a key. The \a initialValue and
+ \a mode parameters are as defined for the constructor.
+
+ \sa QSystemSemaphore(), key()
+ */
+void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode mode)
+{
+ if (key == d->key && mode == Open)
+ return;
+ d->error = NoError;
+ d->errorString = QString();
+#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
+ // optimization to not destroy/create the file & semaphore
+ if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) {
+ d->initialValue = initialValue;
+ d->unix_key = -1;
+ d->handle(mode);
+ return;
+ }
+#endif
+ d->cleanHandle();
+ d->key = key;
+ d->initialValue = initialValue;
+ // cache the file name so it doesn't have to be generated all the time.
+ d->fileName = d->makeKeyFileName();
+ d->handle(mode);
+}
+
+/*!
+ Returns the key assigned to this system semaphore. The key is the
+ name by which the semaphore can be accessed from other processes.
+
+ \sa setKey()
+ */
+QString QSystemSemaphore::key() const
+{
+ return d->key;
+}
+
+/*!
+ Acquires one of the resources guarded by this semaphore, if there is
+ one available, and returns true. If all the resources guarded by this
+ semaphore have already been acquired, the call blocks until one of
+ them is released by another process or thread having a semaphore
+ with the same key.
+
+ If false is returned, a system error has occurred. Call error()
+ to get a value of QSystemSemaphore::SystemSemaphoreError that
+ indicates which error occurred.
+
+ \sa release()
+ */
+bool QSystemSemaphore::acquire()
+{
+ return d->modifySemaphore(-1);
+}
+
+/*!
+ Releases \a n resources guarded by the semaphore. Returns true
+ unless there is a system error.
+
+ Example: Create a system semaphore having five resources; acquire
+ them all and then release them all.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 1
+
+ This function can also "create" resources. For example, immediately
+ following the sequence of statements above, suppose we add the
+ statement:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qsystemsemaphore.cpp 2
+
+ Ten new resources are now guarded by the semaphore, in addition to
+ the five that already existed. You would not normally use this
+ function to create more resources.
+
+ \sa acquire()
+ */
+bool QSystemSemaphore::release(int n)
+{
+ if (n == 0)
+ return true;
+ if (n < 0) {
+ qWarning("QSystemSemaphore::release: n is negative.");
+ return false;
+ }
+ return d->modifySemaphore(n);
+}
+
+/*!
+ Returns a value indicating whether an error occurred, and, if so,
+ which error it was.
+
+ \sa errorString()
+ */
+QSystemSemaphore::SystemSemaphoreError QSystemSemaphore::error() const
+{
+ return d->error;
+}
+
+/*!
+ \enum QSystemSemaphore::SystemSemaphoreError
+
+ \value NoError No error occurred.
+
+ \value PermissionDenied The operation failed because the caller
+ didn't have the required permissions.
+
+ \value KeyError The operation failed because of an invalid key.
+
+ \value AlreadyExists The operation failed because a system
+ semaphore with the specified key already existed.
+
+ \value NotFound The operation failed because a system semaphore
+ with the specified key could not be found.
+
+ \value OutOfResources The operation failed because there was
+ not enough memory available to fill the request.
+
+ \value UnknownError Something else happened and it was bad.
+*/
+
+/*!
+ Returns a text description of the last error that occurred. If
+ error() returns an \l {QSystemSemaphore::SystemSemaphoreError} {error
+ value}, call this function to get a text string that describes the
+ error.
+
+ \sa error()
+ */
+QString QSystemSemaphore::errorString() const
+{
+ return d->errorString;
+}
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsystemsemaphore.h b/src/corelib/kernel/qsystemsemaphore.h
new file mode 100644
index 0000000000..305d311fda
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QSYSTEMSEMAPHORE_H
+#define QSYSTEMSEMAPHORE_H
+
+#include <QtCore/qstring.h>
+#include <QtCore/qscopedpointer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+class QSystemSemaphorePrivate;
+
+class Q_CORE_EXPORT QSystemSemaphore
+{
+
+public:
+ enum AccessMode
+ {
+ Open,
+ Create
+ };
+
+ enum SystemSemaphoreError
+ {
+ NoError,
+ PermissionDenied,
+ KeyError,
+ AlreadyExists,
+ NotFound,
+ OutOfResources,
+ UnknownError
+ };
+
+ QSystemSemaphore(const QString &key, int initialValue = 0, AccessMode mode = Open);
+ ~QSystemSemaphore();
+
+ void setKey(const QString &key, int initialValue = 0, AccessMode mode = Open);
+ QString key() const;
+
+ bool acquire();
+ bool release(int n = 1);
+
+ SystemSemaphoreError error() const;
+ QString errorString() const;
+
+private:
+ Q_DISABLE_COPY(QSystemSemaphore)
+ QScopedPointer<QSystemSemaphorePrivate> d;
+};
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSYSTEMSEMAPHORE_H
+
diff --git a/src/corelib/kernel/qsystemsemaphore_p.h b/src/corelib/kernel/qsystemsemaphore_p.h
new file mode 100644
index 0000000000..f8f5043e23
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QSYSTEMSEMAPHORE_P_H
+#define QSYSTEMSEMAPHORE_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 "qsystemsemaphore.h"
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+#include "qsharedmemory_p.h"
+#ifndef Q_OS_WINCE
+# include <sys/types.h>
+#endif
+
+#ifdef Q_OS_SYMBIAN
+class RSemaphore;
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QSystemSemaphorePrivate
+{
+
+public:
+ QSystemSemaphorePrivate();
+
+ QString makeKeyFileName()
+ {
+ return QSharedMemoryPrivate::makePlatformSafeKey(key, QLatin1String("qipc_systemsem_"));
+ }
+
+#ifdef Q_OS_WIN
+ HANDLE handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
+ void setErrorString(const QString &function);
+#elif defined(Q_OS_SYMBIAN)
+ int handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
+ void setErrorString(const QString &function,int err = 0);
+#else
+ key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
+ void setErrorString(const QString &function);
+#endif
+ void cleanHandle();
+ bool modifySemaphore(int count);
+
+ QString key;
+ QString fileName;
+ int initialValue;
+#ifdef Q_OS_WIN
+ HANDLE semaphore;
+ HANDLE semaphoreLock;
+#elif defined(Q_OS_SYMBIAN)
+ RSemaphore semaphore;
+#else
+ int semaphore;
+ bool createdFile;
+ bool createdSemaphore;
+ key_t unix_key;
+#endif
+ QString errorString;
+ QSystemSemaphore::SystemSemaphoreError error;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+#endif // QSYSTEMSEMAPHORE_P_H
+
diff --git a/src/corelib/kernel/qsystemsemaphore_symbian.cpp b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
new file mode 100644
index 0000000000..0d257b8f5e
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_symbian.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include "qcoreapplication.h"
+#include <qdebug.h>
+
+#include "qcore_symbian_p.h"
+#include <e32cmn.h>
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
+ error(QSystemSemaphore::NoError)
+{
+}
+
+void QSystemSemaphorePrivate::setErrorString(const QString &function, int err)
+{
+ if (err == KErrNone){
+ return;
+ }
+ switch(err){
+ case KErrAlreadyExists:
+ errorString = QCoreApplication::tr("%1: already exists", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::AlreadyExists;
+ break;
+ case KErrNotFound:
+ errorString = QCoreApplication::tr("%1: does not exist", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::NotFound;
+ break;
+ case KErrNoMemory:
+ case KErrInUse:
+ errorString = QCoreApplication::tr("%1: out of resources", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::OutOfResources;
+ break;
+ case KErrPermissionDenied:
+ errorString = QCoreApplication::tr("%1: permission denied", "QSystemSemaphore").arg(function);
+ error = QSystemSemaphore::PermissionDenied;
+ break;
+default:
+ errorString = QCoreApplication::tr("%1: unknown error %2", "QSystemSemaphore").arg(function).arg(err);
+ error = QSystemSemaphore::UnknownError;
+ }
+
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+}
+
+int QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
+{
+ if (semaphore.Handle()) {
+ return semaphore.Handle();
+ }
+
+ // don't allow making handles on empty keys
+ if (key.isEmpty())
+ return 0;
+
+ TPtrC name(qt_QString2TPtrC(fileName));
+ int err = KErrAlreadyExists;
+ int tryCount = 10;
+ // Sort out race conditions by retrying several times until existing handle is acquired.
+ // Sometimes opening can fail inexplicably with KErrPermissionDenied many times in a row.
+ while (err != KErrNoMemory && err != KErrNone && tryCount-- >= 0) {
+ err = semaphore.CreateGlobal(name, initialValue, EOwnerProcess);
+ if (err != KErrNoMemory && err != KErrNone)
+ err = semaphore.OpenGlobal(name,EOwnerProcess);
+ }
+ if (err){
+ setErrorString(QLatin1String("QSystemSemaphore::handle"),err);
+ return 0;
+ }
+ return semaphore.Handle();
+}
+
+void QSystemSemaphorePrivate::cleanHandle()
+{
+ semaphore.Close();
+}
+
+bool QSystemSemaphorePrivate::modifySemaphore(int count)
+{
+ if (0 == handle())
+ return false;
+
+ if (count > 0) {
+ semaphore.Signal(count);
+ } else {
+ semaphore.Wait();
+ }
+ return true;
+}
+
+#endif //QT_NO_SYSTEMSEMAPHORE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
new file mode 100644
index 0000000000..55b65b75de
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+
+#include <qdebug.h>
+#include <qfile.h>
+#include <qcoreapplication.h>
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "private/qcore_unix_p.h"
+
+// OpenBSD 4.2 doesn't define EIDRM, see BUGS section:
+// http://www.openbsd.org/cgi-bin/man.cgi?query=semop&manpath=OpenBSD+4.2
+#if defined(Q_OS_OPENBSD) && !defined(EIDRM)
+#define EIDRM EINVAL
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
+ semaphore(-1), createdFile(false),
+ createdSemaphore(false), unix_key(-1), error(QSystemSemaphore::NoError)
+{
+}
+
+void QSystemSemaphorePrivate::setErrorString(const QString &function)
+{
+ // EINVAL is handled in functions so they can give better error strings
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: permission denied").arg(function);
+ error = QSystemSemaphore::PermissionDenied;
+ break;
+ case EEXIST:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: already exists").arg(function);
+ error = QSystemSemaphore::AlreadyExists;
+ break;
+ case ENOENT:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: does not exist").arg(function);
+ error = QSystemSemaphore::NotFound;
+ break;
+ case ERANGE:
+ case ENOSPC:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function);
+ error = QSystemSemaphore::OutOfResources;
+ break;
+ default:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(errno);
+ error = QSystemSemaphore::UnknownError;
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << errorString << "key" << key << "errno" << errno << EINVAL;
+#endif
+ }
+}
+
+/*!
+ \internal
+
+ Setup unix_key
+ */
+key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
+{
+ if (key.isEmpty()){
+ errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+
+ // ftok requires that an actual file exists somewhere
+ if (-1 != unix_key)
+ return unix_key;
+
+ // Create the file needed for ftok
+ int built = QSharedMemoryPrivate::createUnixKeyFile(fileName);
+ if (-1 == built) {
+ errorString = QCoreApplication::tr("%1: unable to make key", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+ createdFile = (1 == built);
+
+ // Get the unix key for the created file
+ unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
+ if (-1 == unix_key) {
+ errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
+ error = QSystemSemaphore::KeyError;
+ return -1;
+ }
+
+ // Get semaphore
+ semaphore = semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL);
+ if (-1 == semaphore) {
+ if (errno == EEXIST)
+ semaphore = semget(unix_key, 1, 0666 | IPC_CREAT);
+ if (-1 == semaphore) {
+ setErrorString(QLatin1String("QSystemSemaphore::handle"));
+ cleanHandle();
+ return -1;
+ }
+ } else {
+ createdSemaphore = true;
+ // Force cleanup of file, it is possible that it can be left over from a crash
+ createdFile = true;
+ }
+
+ if (mode == QSystemSemaphore::Create) {
+ createdSemaphore = true;
+ createdFile = true;
+ }
+
+ // Created semaphore so initialize its value.
+ if (createdSemaphore && initialValue >= 0) {
+ qt_semun init_op;
+ init_op.val = initialValue;
+ if (-1 == semctl(semaphore, 0, SETVAL, init_op)) {
+ setErrorString(QLatin1String("QSystemSemaphore::handle"));
+ cleanHandle();
+ return -1;
+ }
+ }
+
+ return unix_key;
+}
+
+/*!
+ \internal
+
+ Cleanup the unix_key
+ */
+void QSystemSemaphorePrivate::cleanHandle()
+{
+ unix_key = -1;
+
+ // remove the file if we made it
+ if (createdFile) {
+ QFile::remove(fileName);
+ createdFile = false;
+ }
+
+ if (createdSemaphore) {
+ if (-1 != semaphore) {
+ if (-1 == semctl(semaphore, 0, IPC_RMID, 0)) {
+ setErrorString(QLatin1String("QSystemSemaphore::cleanHandle"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::cleanHandle semctl failed.");
+#endif
+ }
+ semaphore = -1;
+ }
+ createdSemaphore = false;
+ }
+}
+
+/*!
+ \internal
+ */
+bool QSystemSemaphorePrivate::modifySemaphore(int count)
+{
+ if (-1 == handle())
+ return false;
+
+ struct sembuf operation;
+ operation.sem_num = 0;
+ operation.sem_op = count;
+ operation.sem_flg = SEM_UNDO;
+
+ register int res;
+ EINTR_LOOP(res, semop(semaphore, &operation, 1));
+ if (-1 == res) {
+ // If the semaphore was removed be nice and create it and then modifySemaphore again
+ if (errno == EINVAL || errno == EIDRM) {
+ semaphore = -1;
+ cleanHandle();
+ handle();
+ return modifySemaphore(count);
+ }
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modify failed") << count << semctl(semaphore, 0, GETVAL) << errno << EIDRM << EINVAL;
+#endif
+ return false;
+ }
+
+ return true;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qsystemsemaphore_win.cpp b/src/corelib/kernel/qsystemsemaphore_win.cpp
new file mode 100644
index 0000000000..fad50f2ffb
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include "qcoreapplication.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+QSystemSemaphorePrivate::QSystemSemaphorePrivate() :
+ semaphore(0), error(QSystemSemaphore::NoError)
+{
+}
+
+void QSystemSemaphorePrivate::setErrorString(const QString &function)
+{
+ BOOL windowsError = GetLastError();
+ if (windowsError == 0)
+ return;
+
+ switch (windowsError) {
+ case ERROR_NO_SYSTEM_RESOURCES:
+ case ERROR_NOT_ENOUGH_MEMORY:
+ error = QSystemSemaphore::OutOfResources;
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function);
+ break;
+ case ERROR_ACCESS_DENIED:
+ error = QSystemSemaphore::PermissionDenied;
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: permission denied").arg(function);
+ break;
+ default:
+ errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(windowsError);
+ error = QSystemSemaphore::UnknownError;
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << errorString << "key" << key;
+#endif
+ }
+}
+
+HANDLE QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode)
+{
+ // don't allow making handles on empty keys
+ if (key.isEmpty())
+ return 0;
+
+ // Create it if it doesn't already exists.
+ if (semaphore == 0) {
+ semaphore = CreateSemaphore(0, initialValue, MAXLONG, (wchar_t*)fileName.utf16());
+ if (semaphore == NULL)
+ setErrorString(QLatin1String("QSystemSemaphore::handle"));
+ }
+
+ return semaphore;
+}
+
+void QSystemSemaphorePrivate::cleanHandle()
+{
+ if (semaphore && !CloseHandle(semaphore)) {
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphorePrivate::CloseHandle: sem failed");
+#endif
+ }
+ semaphore = 0;
+}
+
+bool QSystemSemaphorePrivate::modifySemaphore(int count)
+{
+ if (0 == handle())
+ return false;
+
+ if (count > 0) {
+ if (0 == ReleaseSemaphore(semaphore, count, 0)) {
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modifySemaphore ReleaseSemaphore failed");
+#endif
+ return false;
+ }
+ } else {
+ if (WAIT_OBJECT_0 != WaitForSingleObject(semaphore, INFINITE)) {
+ setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore"));
+#if defined QSYSTEMSEMAPHORE_DEBUG
+ qDebug() << QLatin1String("QSystemSemaphore::modifySemaphore WaitForSingleObject failed");
+#endif
+ return false;
+ }
+ }
+
+ return true;
+}
+
+#endif //QT_NO_SYSTEMSEMAPHORE
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
new file mode 100644
index 0000000000..79e4cca3e8
--- /dev/null
+++ b/src/corelib/kernel/qtcore_eval.cpp
@@ -0,0 +1,571 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 <qcoreevent.h>
+#include <qdatetime.h>
+#include <qlibraryinfo.h>
+#include <qobject.h>
+#include <qcoreapplication.h>
+
+#include "stdio.h"
+#include "stdlib.h"
+
+QT_BEGIN_NAMESPACE
+
+#include "qconfig_eval.cpp"
+
+static const char boilerplate_unsuported[] =
+ "\nQt %1 Evaluation License\n"
+ "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n"
+ "All rights reserved.\n\n"
+ "This trial version may only be used for evaluation purposes\n"
+ "and will shut down after 120 minutes.\n"
+ "Registered to:\n"
+ " Licensee: %2\n\n"
+ "The evaluation expires in %4 days\n\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static const char boilerplate_supported[] =
+ "\nQt %1 Evaluation License\n"
+ "Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).\n"
+ "All rights reserved.\n\n"
+ "This trial version may only be used for evaluation purposes\n"
+ "Registered to:\n"
+ " Licensee: %2\n\n"
+ "The evaluation expires in %4 days\n\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static const char boilerplate_expired[] =
+ "This software is using the trial version of the Qt GUI toolkit.\n"
+ "The trial period has expired. If you need more time to\n"
+ "evaluate Qt, or if you have any questions about Qt, contact us\n"
+ "at: http://qt.nokia.com/about/contact-us.\n\n";
+
+static const char will_shutdown_1min[] =
+ "\nThe evaluation of Qt will SHUT DOWN in 1 minute.\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static const char will_shutdown_now[] =
+ "\nThe evaluation of Qt has now reached its automatic\n"
+ "timeout and will shut down.\n"
+ "Contact http://qt.nokia.com/about/contact-us for pricing and purchasing information.\n";
+
+static int qt_eval_is_supported()
+{
+ const volatile char *const license_key = qt_eval_key_data + 12;
+
+ // fast fail
+ if (!qt_eval_key_data[0] || !*license_key)
+ return -1;
+
+ // is this an unsupported evaluation?
+ const volatile char *typecode = license_key;
+ int field = 2;
+ for ( ; field && *typecode; ++typecode)
+ if (*typecode == '-')
+ --field;
+
+ if (!field && typecode[1] == '4' && typecode[2] == 'M') {
+ if (typecode[0] == 'Q')
+ return 0;
+ else if (typecode[0] == 'R' || typecode[0] == 'Z')
+ return 1;
+ }
+ return -1;
+}
+
+static int qt_eval_days_left()
+{
+ if (qt_eval_is_supported() < 0)
+ return -2;
+
+ QDate today = QDate::currentDate();
+ QDate build = QLibraryInfo::buildDate();
+ return qMax(-1, today.daysTo(build) + 30);
+}
+
+static QString qt_eval_string()
+{
+ const char *msg;
+ switch (qt_eval_is_supported()) {
+ case 0:
+ msg = boilerplate_unsuported;
+ break;
+ case 1:
+ msg = boilerplate_supported;
+ break;
+ default:
+ return QString();
+ msg = 0;
+ }
+
+ return QString::fromLatin1(msg)
+ .arg(QLatin1String(QT_VERSION_STR))
+ .arg(QLibraryInfo::licensee())
+ .arg(qt_eval_days_left());
+}
+
+#define WARN_TIMEOUT 60 * 1000 * 119
+#define KILL_DELAY 60 * 1000 * 1
+
+class QCoreFuriCuri : public QObject
+{
+public:
+
+ int warn;
+ int kill;
+
+ QCoreFuriCuri() : QObject(), warn(-1), kill(-1)
+ {
+ if (!qt_eval_is_supported()) {
+ warn = startTimer(WARN_TIMEOUT);
+ kill = 0;
+ }
+ }
+
+ void timerEvent(QTimerEvent *e) {
+ if (e->timerId() == warn) {
+ killTimer(warn);
+ fprintf(stderr, "%s\n", will_shutdown_1min);
+ kill = startTimer(KILL_DELAY);
+ } else if (e->timerId() == kill) {
+ fprintf(stderr, "%s\n", will_shutdown_now);
+ QCoreApplication::instance()->quit();
+ }
+ }
+};
+
+#if defined(QT_BUILD_CORE_LIB) || defined (QT_BOOTSTRAPPED)
+
+void qt_core_eval_init(uint type)
+{
+ if (!type)
+ return; // GUI app
+
+ switch (qt_eval_days_left()) {
+ case -2:
+ return;
+
+ case -1:
+ fprintf(stderr, "%s\n", boilerplate_expired);
+ if (type == 0) {
+ // if we're a console app only.
+ exit(0);
+ }
+
+ default:
+ fprintf(stderr, "%s\n", qPrintable(qt_eval_string()));
+ if (type == 0) {
+ Q_UNUSED(new QCoreFuriCuri());
+ }
+ }
+}
+#endif
+
+#ifdef QT_BUILD_GUI_LIB
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <qdialog.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qmessagebox.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qapplication.h>
+QT_END_INCLUDE_NAMESPACE
+
+
+static const char * const qtlogo_eval_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"46 55 174 2",
+" c #002E02",
+". c #00370D",
+"X c #003A0E",
+"o c #003710",
+"O c #013C13",
+"+ c #043E1A",
+"@ c #084F0A",
+"# c #0B520C",
+"$ c #054413",
+"% c #0C4C17",
+"& c #07421D",
+"* c #09451D",
+"= c #0D491E",
+"- c #125515",
+"; c #13541A",
+": c #17591B",
+"> c #1B5C1D",
+", c #1F611F",
+"< c #20621E",
+"1 c #337B1E",
+"2 c #0B4521",
+"3 c #0F4923",
+"4 c #114B24",
+"5 c #154D2A",
+"6 c #175323",
+"7 c #1C5924",
+"8 c #1C532F",
+"9 c #1E5432",
+"0 c #245936",
+"q c #265938",
+"w c #295C3B",
+"e c #246324",
+"r c #266823",
+"t c #2A6C24",
+"y c #276628",
+"u c #2D7026",
+"i c #327427",
+"p c #367927",
+"a c #37782A",
+"s c #397C2A",
+"d c #2E613E",
+"f c #336C37",
+"g c #2F6040",
+"h c #356545",
+"j c #3C6B4E",
+"k c #3F6C51",
+"l c #406E4F",
+"z c #406D52",
+"x c #477457",
+"c c #497557",
+"v c #4B7857",
+"b c #517B5E",
+"n c #3C8423",
+"m c #3E812C",
+"M c #53A61D",
+"N c #41862C",
+"B c #458A2D",
+"V c #498F2D",
+"C c #479324",
+"Z c #489226",
+"A c #4D952C",
+"S c #478B30",
+"D c #488C30",
+"F c #4D9232",
+"G c #509632",
+"H c #549A33",
+"J c #589F35",
+"K c #56A526",
+"L c #57A821",
+"P c #5BAA27",
+"I c #57A32A",
+"U c #5CA72E",
+"Y c #5DAB2A",
+"T c #5CA336",
+"R c #60AD2E",
+"E c #63B12D",
+"W c #65AF35",
+"Q c #62A53F",
+"! c #65AE39",
+"~ c #66B036",
+"^ c #6AB437",
+"/ c #67B138",
+"( c #6AB339",
+") c #6DB838",
+"_ c #70BA3C",
+"` c #4D8545",
+"' c #4E8942",
+"] c #548851",
+"[ c #6FAF4A",
+"{ c #6DB243",
+"} c #71B546",
+"| c #70B840",
+" . c #73B648",
+".. c #79BA4E",
+"X. c #7CBB53",
+"o. c #598266",
+"O. c #62886D",
+"+. c #6A8F75",
+"@. c #6B9173",
+"#. c #70937A",
+"$. c #799F79",
+"%. c #7BAF66",
+"&. c #81BD5B",
+"*. c #85BF60",
+"=. c #85AC7F",
+"-. c #8DBA7B",
+";. c #87C061",
+":. c #8AC364",
+">. c #8DC46A",
+",. c #90C56E",
+"<. c #93C771",
+"1. c #96CA73",
+"2. c #9ACB7C",
+"3. c #9FD07D",
+"4. c #779981",
+"5. c #7F9F89",
+"6. c #809F88",
+"7. c #82A18B",
+"8. c #86A192",
+"9. c #8DA994",
+"0. c #8FA998",
+"q. c #94AF9B",
+"w. c #97B991",
+"e. c #97B19E",
+"r. c #9DB6A3",
+"t. c #A3BCA7",
+"y. c #A6BCAB",
+"u. c #A9BEB1",
+"i. c #9ECD81",
+"p. c #A2CF85",
+"a. c #A5D284",
+"s. c #A6D189",
+"d. c #A9D28E",
+"f. c #ABD491",
+"g. c #B1D797",
+"h. c #B1D699",
+"j. c #B5D89E",
+"k. c #ADC5AC",
+"l. c #B1CAAE",
+"z. c #B9DAA3",
+"x. c #BDDDA8",
+"c. c #ADC1B4",
+"v. c #B2C6B6",
+"b. c #B5C6BC",
+"n. c #B6C9BA",
+"m. c #BCD1BA",
+"M. c #C6E1B4",
+"N. c #CDE5BD",
+"B. c #C2D2C6",
+"V. c #CADEC2",
+"C. c #C6D3CC",
+"Z. c #C8D7CB",
+"A. c #CEDAD2",
+"S. c #D2DDD4",
+"D. c #D3E9C6",
+"F. c #D7EBC9",
+"G. c #D9EBCD",
+"H. c #DEEED4",
+"J. c #D6E0D9",
+"K. c #DAE4DC",
+"L. c #E0EFD7",
+"P. c #E5F2DD",
+"I. c #DFE8E0",
+"U. c #E4EBE5",
+"Y. c #E9EFEA",
+"T. c #EDF4EB",
+"R. c #F0FAE6",
+"E. c #F1F8EC",
+"W. c #EDF0F0",
+"Q. c #F4F7F3",
+"!. c #F6F9F4",
+"~. c #F8FAF7",
+"^. c #FEFEFE",
+"/. c None",
+/* pixels */
+"/././././.c h ' Q / W _ &.p././././././././././././././././././././././././././././././././.",
+"/././.4 O % Z ~ ~ W ~ W R U R R ( X.>.p././././././././././././././././././././././././././.",
+"/./.. * = J _ ~ ~ ~ ~ ~ / / / / W W U P P U W .;.2././././././././././././././././././././.",
+"/.= = & a ) W ~ ~ ~ ~ ~ / W / ~ ~ ~ ^ ( ( ^ ~ R R U P Y ~ .;.2././././././././././././././.",
+"O.O = = T ^ W ~ ~ ~ ~ ~ ~ W W / W ~ ~ ~ ~ ~ ~ ~ ( ( ( ( ~ W Y Y Y Y W { &.1././././././././.",
+"0 = * 7 ~ ~ ~ ~ ~ ~ ~ ~ ~ / / W ~ ~ ~ ~ ~ ~ ~ ~ W W W ~ ~ ~ ~ ( ( ( W W R U P U W { X.1.f./.",
+"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ / / ~ ~ ~ ~ ~ ~ ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ^ ( ( / ~ W R U U Y ",
+"= = & e ^ W ~ ~ ~ ~ ~ ~ ~ ~ W W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W ~ ~ ~ ^ ^ ( ",
+"= = * e ^ W ~ ~ ~ ~ ~ ~ / W / W ! ( / ~ W ^ ( ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ~ W W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ! ~ ~ ~ ~ ~ ~ W W ^ _ ~ K Y W W R P Y W ( ~ ~ ~ ~ ~ ~ ~ W / ~ ~ ~ ^ W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ~ ~ ~ ~ W ) W 1 ` w.V.L.H.D.z.,.~ Y ^ ~ ~ ~ ~ ~ W ~ ~ ~ ( ~ W W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ~ ~ ~ W ) V = 8.~.^.^.^.^.^.^.^.U.<.Y ~ ~ ~ ~ ~ W W ! ~ Y W ^ W ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ~ ~ W ^ B O u.^.~.^.^.^.^.~.~.^.^.^.h.Y ^ ~ ~ ^ F $ k.R.G.1.Y / ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ~ ~ ~ / W ( J X 7.^.~.^.^.^.^.^.^.^.^.^.^.^.s.Y / W ) a 2 U.^.^.d.U ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / ~ ~ ~ ^ > w ~.^.^.^.^.^.F.%.v c.^.^.^.^.~.X.W ~ ^ > h ^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ W ^ H o e.^.^.^.^.^.G.Y E n . y.^.^.^.^.M.Y ( ! $ @.^.~.^.f.U ( / ~ ~ W ~ ~ ",
+"= = & e ^ W ~ W ! ) t 4 U.^.^.^.^.^.>.U ( _ , 9 ~.^.^.^.~...^ A y.^.~.^.s.M W Y ~ ~ ~ ~ ~ ",
+"= 3 & e ^ W ~ ( ^ ( $ c ^.^.^.^.^.E.) ~ ~ ^ S o n.^.^.^.^.=.- l.v.Y.^.^.^.M.:.:.X.~ ~ ~ ~ ~ ",
+"= = & e ^ ! W W ( J X 7.^.^.^.^.^.F.Y ( W ^ T X 6.^.^.~.^.c.. J.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ",
+"= = & r ^ W / W ) B o v.^.~.^.^.^.M.U / ~ ~ ! $ o.^.^.^.^.K.* S.^.^.^.^.^.^.^.^.P.~ ~ ~ ~ ~ ",
+"= = & e ^ ! ~ W ) a + S.^.^.^.^.^.z.P ( W ~ ( % z ^.^.^.^.~.f t.U.^.^.^.^.~.^.^.P.~ ~ ~ ~ ~ ",
+"* = & e ^ W ~ W ) t 3 Y.^.^.^.^.^.f.P ( ~ ~ ^ ; h ^.^.^.^.^.:.@ j ^.^.^.^.h.{ X.&.~ ~ ~ ~ ~ ",
+"3 = & e ^ W ~ ~ ^ e 8 Q.^.^.^.^.^.s.P ~ ~ W ^ > 0 ~.^.^.^.^.1.# z ^.^.^.^.d.L W R ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ^ > q ~.^.^.^.^.^.p.U ^ ~ W ) e 9 ~.^.^.^.^.3.# k ^.^.^.^.f.Y ( / ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ^ > w ~.^.^.^.^.^.i.Y / ~ W ^ e 8 Q.^.^.^.^.a.# z ^.^.^.^.f.Y / ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ^ > w ^.^.^.^.^.^.2.Y / ~ ~ ) e 8 Q.^.^.^.^.s.# z ^.^.^.^.d.P ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W W W ^ > q ^.^.^.^.^.^.p.Y / ~ ~ ^ e 9 Q.^.^.^.^.a.@ z ^.^.^.^.f.U / ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ) 7 9 Q.^.^.^.^.^.a.P / ~ W ) , 9 Q.^.^.^.^.3.# z ^.^.~.^.f.P ^ ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W / W ) r 5 T.^.^.^.^.^.d.Y / ~ W ) > q ~.^.^.^.^.1.# k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ / / W ) i 2 I.^.^.^.^.^.h.P ( ~ W ( > g ^.^.^.^.^.:.# z ^.^.^.^.f.P / ~ ~ ~ ~ ~ ~ ",
+"= = & e ( W / W ) m O Z.^.^.^.^.^.x.P / ~ ~ ( ; j ^.^.^.^.~.&.- k ^.^.~.^.f.P / ~ ~ ~ ~ ~ ~ ",
+"= = & e ( W / W ) F o y.^.~.^.^.^.N.U ( ~ ~ W $ b ^.^.^.^.R._ - k ^.^.^.^.f.Y ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ ^ J X 4.^.^.^.^.^.L.~ ~ W ^ T X #.^.^.^.^.F.~ ; j ^.^.^.^.f.U ( ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ~ ~ ~ / ^ % l ^.^.^.^.^.!. .R ^ ^ G . r.^.~.^.^.j.E : j ^.^.^.^.f.P ) ( ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ W ) u = U.^.^.^.^.^.1.Y ! ) a & K.^.^.^.^.;.~ : j ^.^.~.^.z.M I I / ~ ~ W ~ ",
+"= = & e ( W ~ ~ W ( G . q.^.^.^.^.^.D.U ^ ! X o.^.^.^.^.P.~ ^ > g ^.^.^.^.E.-.$.m.X.W ~ ~ ~ ",
+"= = & e ^ / ~ ~ ^ ! ( > w ~.^.^.^.^.^.h.T > j T.^.^.~.^.a.Y _ i 3 U.^.^.^.^.^.^.^.X.R ~ ~ ~ ",
+"= = & e ^ / ~ ~ W W ^ H . 9.^.~.^.^.^.^.K.C.~.^.^.^.^.H.W W ^ T . q.^.~.^.^.^.^.^.X.R ~ ~ ~ ",
+"= = + e ^ W / ~ W W W ) m + B.^.~.^.^.^.^.^.^.^.^.^.E.X.Y ( W ^ B 6 y.^.^.^.E.D.2.( ~ ~ ~ ~ ",
+"= = * e ^ ! / ! W ^ W W ) a 4 b.^.^.^.^.^.^.^.^.^.P...Y ( ! W ! ^ W Z [ *.X.{ Y U ~ ~ ~ ~ ~ ",
+"= = & e ( W ~ ~ W / W / W ) A < +.A.~.^.^.^.^.!.p.W R ~ ~ ~ ~ ~ W / ) E U W W / ^ ~ ~ ~ ~ ~ ",
+"= = & e ^ W ~ ~ / W / / / W ( _ Z X 6.^.^.^.^.E.W ~ ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ / ~ ~ ~ ~ ~ ~ ~ ~ ",
+"= = & e ^ ~ ~ ~ W W / W ~ ~ ~ ~ ) ; h ^.^.^.^.^.d.M U ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ",
+"= = & e ^ W ~ ~ ^ W W / ~ ~ ~ W ) p + S.^.^.^.^.~.M.f. .W ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ .",
+"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( T O +.^.~.^.^.^.^.^.&.Y ( ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( Y 2.",
+"= = & e ( W ~ ~ ~ ~ ~ ~ ~ ~ ~ / W ) N + b.^.^.^.^.^.^.&.R ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W /.",
+"= = & e ^ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W ^ N 7 r.W.^.^.^.!.X.W ~ ~ W ~ W ~ ~ ~ ~ ~ ~ / ( ( K p./.",
+"= = & e ( W ~ ~ W ~ ~ ~ ~ ~ ~ ~ ~ ~ W ( W C Q &.:.X.| ~ ~ ~ ~ W ~ / ~ ( / ( ~ W E U P 1././.",
+"= = + e ^ / / / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W / ) ^ R Y W W ~ ~ ( / ( / W R Y Y U R ( X.,././././.",
+"= = * e ( / ~ / ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ W W W ! ( ( ( W W E U P Y W ( X.,.d./././././././././.",
+"= = * e ( W ~ ~ ~ ~ W ! ~ W ~ W ~ ( ( / ^ W W U Y P W ( X.,.d./././././././././././././././.",
+"8 $ * e ( W ~ ~ ~ ! ( ( ( / ( W R Y Y Y R ( X.>.d./././././././././././././././././././././.",
+"/.d . y ^ / / / ( W Y Y P P W ( X.>.d./././././././././././././././././././././././././././.",
+"/./.h : ^ R R R W ( X.<.f./././././././././././././././././././././././././././././././././.",
+"/././.] _ *.3./././././././././././././././././././././././././././././././././././././././."
+};
+
+class EvalMessageBox : public QDialog
+{
+public:
+ EvalMessageBox(bool expired)
+ {
+ setWindowTitle(QLatin1String(" "));
+
+ QString str = qt_eval_string();
+ if (expired) {
+ str = QLatin1String(boilerplate_expired);
+ } else {
+ str = qt_eval_string();
+ }
+ str = str.trimmed();
+
+ QFrame *border = new QFrame(this);
+
+ QLabel *pixmap_label = new QLabel(border);
+ pixmap_label->setPixmap(qtlogo_eval_xpm);
+ pixmap_label->setAlignment(Qt::AlignTop);
+
+ QLabel *text_label = new QLabel(str, border);
+
+ QHBoxLayout *pm_and_text_layout = new QHBoxLayout();
+ pm_and_text_layout->addWidget(pixmap_label);
+ pm_and_text_layout->addWidget(text_label);
+
+ QVBoxLayout *master_layout = new QVBoxLayout(border);
+ master_layout->addLayout(pm_and_text_layout);
+
+ QVBoxLayout *border_layout = new QVBoxLayout(this);
+ border_layout->setMargin(0);
+ border_layout->addWidget(border);
+
+ if (expired) {
+ QPushButton *cmd = new QPushButton(QLatin1String("OK"), border);
+ cmd->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ cmd->setDefault(true);
+
+ QHBoxLayout *button_layout = new QHBoxLayout();
+ master_layout->addLayout(button_layout);
+ button_layout->addWidget(cmd);
+
+ connect(cmd, SIGNAL(clicked()), this, SLOT(close()));
+ } else {
+ border->setFrameShape(QFrame::WinPanel);
+ border->setFrameShadow(QFrame::Raised);
+ setParent(parentWidget(), Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
+ QTimer::singleShot(7000, this, SLOT(close()));
+ setAttribute(Qt::WA_DeleteOnClose);
+ }
+
+ setFixedSize(sizeHint());
+ }
+};
+
+class QGuiFuriCuri : public QCoreFuriCuri
+{
+public:
+ void timerEvent(QTimerEvent *e) {
+ if (e->timerId() == warn) {
+ killTimer(warn);
+ QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_1min));
+ kill = startTimer(KILL_DELAY);
+ } else if (e->timerId() == kill) {
+ killTimer(kill);
+ QMessageBox::information(0, QLatin1String("Automatic Timeout"), QLatin1String(will_shutdown_now));
+ qApp->quit();
+ }
+ }
+};
+
+
+void qt_gui_eval_init(uint)
+{
+ switch (qt_eval_days_left()) {
+ case -2:
+ return;
+
+ case -1: {
+ EvalMessageBox box(true);
+ box.exec();
+ ::exit(0);
+ }
+
+ default: {
+ EvalMessageBox *box = new EvalMessageBox(false);
+ box->show();
+ Q_UNUSED(new QGuiFuriCuri());
+ }
+ }
+}
+
+static QString qt_eval_title_prefix()
+{
+ return QLatin1String("[Qt Evaluation] ");
+}
+
+QString qt_eval_adapt_window_title(const QString &title)
+{
+ if (qt_eval_days_left() == -2)
+ return title;
+ return qt_eval_title_prefix() + title;
+}
+
+void qt_eval_init_widget(QWidget *w)
+{
+ if (qt_eval_days_left() == -2)
+ return;
+ if (w->isTopLevel()) {
+ QString windowTitle = w->windowTitle();
+ if (windowTitle.isEmpty()) {
+ w->setWindowTitle(QLatin1String(" "));
+ } else if (!windowTitle.startsWith(qt_eval_title_prefix())) {
+ qt_eval_adapt_window_title(windowTitle);
+ }
+ }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
new file mode 100644
index 0000000000..3efeda229d
--- /dev/null
+++ b/src/corelib/kernel/qtimer.cpp
@@ -0,0 +1,394 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qtimer.h"
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QTimer
+ \brief The QTimer class provides repetitive and single-shot timers.
+
+ \ingroup events
+
+
+ The QTimer class provides a high-level programming interface for
+ timers. To use it, create a QTimer, connect its timeout() signal
+ to the appropriate slots, and call start(). From then on it will
+ emit the timeout() signal at constant intervals.
+
+ Example for a one second (1000 millisecond) timer (from the
+ \l{widgets/analogclock}{Analog Clock} example):
+
+ \snippet examples/widgets/analogclock/analogclock.cpp 4
+ \snippet examples/widgets/analogclock/analogclock.cpp 5
+ \snippet examples/widgets/analogclock/analogclock.cpp 6
+
+ From then on, the \c update() slot is called every second.
+
+ You can set a timer to time out only once by calling
+ setSingleShot(true). You can also use the static
+ QTimer::singleShot() function to call a slot after a specified
+ interval:
+
+ \snippet doc/src/snippets/timers/timers.cpp 3
+
+ 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 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
+ start a timer from another thread.
+
+ As a special case, a QTimer with a timeout of 0 will time out as
+ soon as all the events in the window system's event queue have
+ been processed. This can be used to do heavy work while providing
+ a snappy user interface:
+
+ \snippet doc/src/snippets/timers/timers.cpp 4
+ \snippet doc/src/snippets/timers/timers.cpp 5
+ \snippet doc/src/snippets/timers/timers.cpp 6
+
+ \c processOneThing() will from then on be called repeatedly. It
+ should be written in such a way that it always returns quickly
+ (typically after processing one data item) so that Qt can deliver
+ events to widgets and stop the timer as soon as it has done all
+ its work. This is the traditional way of implementing heavy work
+ in GUI applications; multithreading is now becoming available on
+ more and more platforms, and we expect that zero-millisecond
+ QTimers will gradually be replaced by \l{QThread}s.
+
+ \section1 Accuracy and Timer Resolution
+
+ Timers will never time out earlier than the specified timeout value
+ and they are not guaranteed to time out at the exact value specified.
+ In many situations, they may time out late by a period of time that
+ depends on the accuracy of the system timers.
+
+ The accuracy of timers depends on the underlying operating system
+ and hardware. Most platforms support a resolution of 1 millisecond,
+ though the accuracy of the timer will not equal this resolution
+ in many real-world situations.
+
+ If Qt is unable to deliver the requested number of timer clicks,
+ it will silently discard some.
+
+ \section1 Alternatives to QTimer
+
+ An alternative to using QTimer is to call QObject::startTimer()
+ for your object and reimplement the QObject::timerEvent() event
+ handler in your class (which must inherit QObject). The
+ disadvantage is that timerEvent() does not support such
+ high-level features as single-shot timers or signals.
+
+ Another alternative to using QTimer is to use QBasicTimer. It is
+ typically less cumbersome than using QObject::startTimer()
+ directly. See \l{Timers} for an overview of all three approaches.
+
+ Some operating systems limit the number of timers that may be
+ used; Qt tries to work around these limitations.
+
+ \sa QBasicTimer, QTimerEvent, QObject::timerEvent(), Timers,
+ {Analog Clock Example}, {Wiggly Example}
+*/
+
+
+static const int INV_TIMER = -1; // invalid timer id
+
+/*!
+ Constructs a timer with the given \a parent.
+*/
+
+QTimer::QTimer(QObject *parent)
+ : QObject(parent), id(INV_TIMER), inter(0), del(0), single(0), nulltimer(0)
+{
+}
+
+
+#ifdef QT3_SUPPORT
+/*!
+ Constructs a timer called \a name, with a \a parent.
+*/
+
+QTimer::QTimer(QObject *parent, const char *name)
+ : QObject(parent), id(INV_TIMER), single(0), nulltimer(0)
+{
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*!
+ Destroys the timer.
+*/
+
+QTimer::~QTimer()
+{
+ if (id != INV_TIMER) // stop running timer
+ stop();
+}
+
+
+/*!
+ \fn void QTimer::timeout()
+
+ This signal is emitted when the timer times out.
+
+ \sa interval, start(), stop()
+*/
+
+/*!
+ \property QTimer::active
+ \since 4.3
+
+ This boolean property is true if the timer is running; otherwise
+ false.
+*/
+
+/*!
+ \fn bool QTimer::isActive() const
+
+ Returns true if the timer is running (pending); otherwise returns
+ false.
+*/
+
+/*!
+ \fn int QTimer::timerId() const
+
+ Returns the ID of the timer if the timer is running; otherwise returns
+ -1.
+*/
+
+
+/*! \overload start()
+
+ Starts or restarts the timer with the timeout specified in \l interval.
+
+ If \l singleShot is true, the timer will be activated only once.
+*/
+void QTimer::start()
+{
+ if (id != INV_TIMER) // stop running timer
+ stop();
+ nulltimer = (!inter && single);
+ id = QObject::startTimer(inter);
+}
+
+/*!
+ Starts or restarts the timer with a timeout interval of \a msec
+ milliseconds.
+*/
+void QTimer::start(int msec)
+{
+ inter = msec;
+ start();
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \overload start()
+
+ Call setSingleShot(\a sshot) and start(\a msec) instead.
+*/
+
+int QTimer::start(int msec, bool sshot)
+{
+ if (id >=0 && nulltimer && !msec && sshot)
+ return id;
+ stop();
+ setInterval(msec);
+ setSingleShot(sshot);
+ start();
+ return timerId();
+}
+#endif
+
+
+/*!
+ Stops the timer.
+
+ \sa start()
+*/
+
+void QTimer::stop()
+{
+ if (id != INV_TIMER) {
+ QObject::killTimer(id);
+ id = INV_TIMER;
+ }
+}
+
+
+/*!
+ \reimp
+*/
+void QTimer::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == id) {
+ if (single)
+ stop();
+ emit timeout();
+ }
+}
+
+class QSingleShotTimer : public QObject
+{
+ Q_OBJECT
+ int timerId;
+public:
+ ~QSingleShotTimer();
+ QSingleShotTimer(int msec, QObject *r, const char * m);
+Q_SIGNALS:
+ void timeout();
+protected:
+ void timerEvent(QTimerEvent *);
+};
+
+QSingleShotTimer::QSingleShotTimer(int msec, QObject *receiver, const char *member)
+ : QObject(QAbstractEventDispatcher::instance())
+{
+ connect(this, SIGNAL(timeout()), receiver, member);
+ timerId = startTimer(msec);
+}
+
+QSingleShotTimer::~QSingleShotTimer()
+{
+ if (timerId > 0)
+ killTimer(timerId);
+}
+
+void QSingleShotTimer::timerEvent(QTimerEvent *)
+{
+ // need to kill the timer _before_ we emit timeout() in case the
+ // slot connected to timeout calls processEvents()
+ if (timerId > 0)
+ killTimer(timerId);
+ timerId = -1;
+ emit timeout();
+
+ // we would like to use delete later here, but it feels like a
+ // waste to post a new event to handle this event, so we just unset the flag
+ // and explicitly delete...
+ qDeleteInEventHandler(this);
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "qtimer.moc"
+QT_END_INCLUDE_NAMESPACE
+
+/*!
+ \reentrant
+ This static function calls a slot after a given time interval.
+
+ It is very convenient to use this function because you do not need
+ to bother with a \link QObject::timerEvent() timerEvent\endlink or
+ create a local QTimer object.
+
+ Example:
+ \snippet doc/src/snippets/code/src_corelib_kernel_qtimer.cpp 0
+
+ This sample program automatically terminates after 10 minutes
+ (600,000 milliseconds).
+
+ The \a receiver is the receiving object and the \a member is the
+ slot. The time interval is \a msec milliseconds.
+
+ \sa start()
+*/
+
+void QTimer::singleShot(int msec, QObject *receiver, const char *member)
+{
+ if (receiver && member) {
+ if (msec == 0) {
+ // special code shortpath for 0-timers
+ const char* bracketPosition = strchr(member, '(');
+ if (!bracketPosition || !(member[0] >= '0' && member[0] <= '3')) {
+ qWarning("QTimer::singleShot: Invalid slot specification");
+ return;
+ }
+ QByteArray methodName(member+1, bracketPosition - 1 - member); // extract method name
+ QMetaObject::invokeMethod(receiver, methodName.constData(), Qt::QueuedConnection);
+ return;
+ }
+ (void) new QSingleShotTimer(msec, receiver, member);
+ }
+}
+
+/*!
+ \property QTimer::singleShot
+ \brief whether the timer is a single-shot timer
+
+ A single-shot timer fires only once, non-single-shot timers fire
+ every \l interval milliseconds.
+
+ \sa interval, singleShot()
+*/
+
+/*!
+ \property QTimer::interval
+ \brief the timeout interval in milliseconds
+
+ The default value for this property is 0. A QTimer with a timeout
+ interval of 0 will time out as soon as all the events in the window
+ system's event queue have been processed.
+
+ Setting the interval of an active timer changes its timerId().
+
+ \sa singleShot
+*/
+void QTimer::setInterval(int msec)
+{
+ inter = msec;
+ if (id != INV_TIMER) { // create new timer
+ QObject::killTimer(id); // restart timer
+ id = QObject::startTimer(msec);
+ }
+}
+
+/*! \fn void QTimer::changeInterval(int msec)
+
+ Use setInterval(msec) or start(msec) instead.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
new file mode 100644
index 0000000000..a7470848ee
--- /dev/null
+++ b/src/corelib/kernel/qtimer.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QTIMER_H
+#define QTIMER_H
+
+#ifndef QT_NO_QOBJECT
+
+#include <QtCore/qbasictimer.h> // conceptual inheritance
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class Q_CORE_EXPORT QTimer : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(bool singleShot READ isSingleShot WRITE setSingleShot)
+ Q_PROPERTY(int interval READ interval WRITE setInterval)
+ Q_PROPERTY(bool active READ isActive)
+public:
+ explicit QTimer(QObject *parent = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QTimer(QObject *parent, const char *name);
+#endif
+ ~QTimer();
+
+ inline bool isActive() const { return id >= 0; }
+ int timerId() const { return id; }
+
+ void setInterval(int msec);
+ int interval() const { return inter; }
+
+ inline void setSingleShot(bool singleShot);
+ inline bool isSingleShot() const { return single; }
+
+ static void singleShot(int msec, QObject *receiver, const char *member);
+
+public Q_SLOTS:
+ void start(int msec);
+
+ void start();
+ void stop();
+
+#ifdef QT3_SUPPORT
+ inline QT_MOC_COMPAT void changeInterval(int msec) { start(msec); }
+ QT_MOC_COMPAT int start(int msec, bool sshot);
+#endif
+
+Q_SIGNALS:
+ void timeout();
+
+protected:
+ void timerEvent(QTimerEvent *);
+
+private:
+ Q_DISABLE_COPY(QTimer)
+
+ inline int startTimer(int){ return -1;}
+ inline void killTimer(int){}
+
+ int id, inter, del;
+ uint single : 1;
+ uint nulltimer : 1;
+};
+
+inline void QTimer::setSingleShot(bool asingleShot) { single = asingleShot; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_QOBJECT
+
+#endif // QTIMER_H
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
new file mode 100644
index 0000000000..22b06a56a6
--- /dev/null
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -0,0 +1,979 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qplatformdefs.h"
+
+#include "qtranslator.h"
+
+#ifndef QT_NO_TRANSLATION
+
+#include "qfileinfo.h"
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qdatastream.h"
+#include "qfile.h"
+#include "qmap.h"
+#include "qalgorithms.h"
+#include "qhash.h"
+#include "qtranslator_p.h"
+#include "qlocale.h"
+
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_INTEGRITY)
+#define QT_USE_MMAP
+#include "private/qcore_unix_p.h"
+#endif
+
+// most of the headers below are already included in qplatformdefs.h
+// also this lacks Large File support but that's probably irrelevant
+#if defined(QT_USE_MMAP)
+// for mmap
+#include <sys/mman.h>
+#include <errno.h>
+#endif
+
+#include <stdlib.h>
+
+#include "qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+enum Tag { Tag_End = 1, Tag_SourceText16, Tag_Translation, Tag_Context16, Tag_Obsolete1,
+ Tag_SourceText, Tag_Context, Tag_Comment, Tag_Obsolete2 };
+/*
+$ mcookie
+3cb86418caef9c95cd211cbf60a1bddd
+$
+*/
+
+// magic number for the file
+static const int MagicLength = 16;
+static const uchar magic[MagicLength] = {
+ 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95,
+ 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd
+};
+
+static bool match(const uchar* found, const char* target, uint len)
+{
+ // catch the case if \a found has a zero-terminating symbol and \a len includes it.
+ // (normalize it to be without the zero-terminating symbol)
+ if (len > 0 && found[len-1] == '\0')
+ --len;
+ return (memcmp(found, target, len) == 0 && target[len] == '\0');
+}
+
+static uint elfHash(const char *name)
+{
+ const uchar *k;
+ uint h = 0;
+ uint g;
+
+ if (name) {
+ k = (const uchar *) name;
+ while (*k) {
+ h = (h << 4) + *k++;
+ if ((g = (h & 0xf0000000)) != 0)
+ h ^= g >> 24;
+ h &= ~g;
+ }
+ }
+ if (!h)
+ h = 1;
+ return h;
+}
+
+static int numerusHelper(int n, const uchar *rules, int rulesSize)
+{
+#define CHECK_RANGE \
+ do { \
+ if (i >= rulesSize) \
+ return -1; \
+ } while (0)
+
+ int result = 0;
+ int i = 0;
+
+ if (rulesSize == 0)
+ return 0;
+
+ for (;;) {
+ bool orExprTruthValue = false;
+
+ for (;;) {
+ bool andExprTruthValue = true;
+
+ for (;;) {
+ bool truthValue = true;
+
+ CHECK_RANGE;
+ int opcode = rules[i++];
+
+ int leftOperand = n;
+ if (opcode & Q_MOD_10) {
+ leftOperand %= 10;
+ } else if (opcode & Q_MOD_100) {
+ leftOperand %= 100;
+ } else if (opcode & Q_LEAD_1000) {
+ while (leftOperand >= 1000)
+ leftOperand /= 1000;
+ }
+
+ int op = opcode & Q_OP_MASK;
+
+ CHECK_RANGE;
+ int rightOperand = rules[i++];
+
+ switch (op) {
+ default:
+ return -1;
+ case Q_EQ:
+ truthValue = (leftOperand == rightOperand);
+ break;
+ case Q_LT:
+ truthValue = (leftOperand < rightOperand);
+ break;
+ case Q_LEQ:
+ truthValue = (leftOperand <= rightOperand);
+ break;
+ case Q_BETWEEN:
+ int bottom = rightOperand;
+ CHECK_RANGE;
+ int top = rules[i++];
+ truthValue = (leftOperand >= bottom && leftOperand <= top);
+ }
+
+ if (opcode & Q_NOT)
+ truthValue = !truthValue;
+
+ andExprTruthValue = andExprTruthValue && truthValue;
+
+ if (i == rulesSize || rules[i] != Q_AND)
+ break;
+ ++i;
+ }
+
+ orExprTruthValue = orExprTruthValue || andExprTruthValue;
+
+ if (i == rulesSize || rules[i] != Q_OR)
+ break;
+ ++i;
+ }
+
+ if (orExprTruthValue)
+ return result;
+
+ ++result;
+
+ if (i == rulesSize)
+ return result;
+
+ if (rules[i++] != Q_NEWRULE)
+ break;
+ }
+ return -1;
+}
+
+class QTranslatorPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QTranslator)
+public:
+ enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69, NumerusRules = 0x88 };
+
+ QTranslatorPrivate()
+ : used_mmap(0), unmapPointer(0), unmapLength(0),
+ messageArray(0), offsetArray(0), contextArray(0), numerusRulesArray(0),
+ messageLength(0), offsetLength(0), contextLength(0), numerusRulesLength(0) {}
+
+ // for mmap'ed files, this is what needs to be unmapped.
+ bool used_mmap : 1;
+ char *unmapPointer;
+ unsigned int unmapLength;
+
+ // for squeezed but non-file data, this is what needs to be deleted
+ const uchar *messageArray;
+ const uchar *offsetArray;
+ const uchar *contextArray;
+ const uchar *numerusRulesArray;
+ uint messageLength;
+ uint offsetLength;
+ uint contextLength;
+ uint numerusRulesLength;
+
+ bool do_load(const QString &filename);
+ bool do_load(const uchar *data, int len);
+ QString do_translate(const char *context, const char *sourceText, const char *comment,
+ int n) const;
+ void clear();
+};
+
+/*!
+ \class QTranslator
+
+ \brief The QTranslator class provides internationalization support for text
+ output.
+
+ \ingroup i18n
+
+ An object of this class contains a set of translations from a
+ source language to a target language. QTranslator provides
+ functions to look up translations in a translation file.
+ Translation files are created using \l{Qt Linguist}.
+
+ The most common use of QTranslator is to: load a translation
+ file, install it using QApplication::installTranslator(), and use
+ it via QObject::tr(). Here's the \c main() function from the
+ \l{linguist/hellotr}{Hello tr()} example:
+
+ \snippet examples/linguist/hellotr/main.cpp 2
+
+ Note that the translator must be created \e before the
+ application's widgets.
+
+ Most applications will never need to do anything else with this
+ class. The other functions provided by this class are useful for
+ applications that work on translator files.
+
+ \section1 Looking up Translations
+
+ It is possible to look up a translation using translate() (as tr()
+ and QApplication::translate() do). The translate() function takes
+ up to three parameters:
+
+ \list
+ \o The \e context - usually the class name for the tr() caller.
+ \o The \e {source text} - usually the argument to tr().
+ \o The \e disambiguation - an optional string that helps disambiguate
+ different uses of the same text in the same context.
+ \endlist
+
+ For example, the "Cancel" in a dialog might have "Anuluj" when the
+ program runs in Polish (in this case the source text would be
+ "Cancel"). The context would (normally) be the dialog's class
+ name; there would normally be no comment, and the translated text
+ would be "Anuluj".
+
+ But it's not always so simple. The Spanish version of a printer
+ dialog with settings for two-sided printing and binding would
+ probably require both "Activado" and "Activada" as translations
+ for "Enabled". In this case the source text would be "Enabled" in
+ both cases, and the context would be the dialog's class name, but
+ the two items would have disambiguations such as "two-sided printing"
+ for one and "binding" for the other. The disambiguation enables the
+ translator to choose the appropriate gender for the Spanish version,
+ and enables Qt to distinguish between translations.
+
+ \section1 Using Multiple Translations
+
+ Multiple translation files can be installed in an application.
+ Translations are searched for in the reverse order in which they were
+ installed, so the most recently installed translation file is searched
+ for translations first and the earliest translation file is searched
+ last. The search stops as soon as a translation containing a matching
+ string is found.
+
+ This mechanism makes it possible for a specific translation to be
+ "selected" or given priority over the others; simply uninstall the
+ translator from the application by passing it to the
+ QApplication::removeTranslator() function and reinstall it with
+ QApplication::installTranslator(). It will then be the first
+ translation to be searched for matching strings.
+
+ \sa QApplication::installTranslator(), QApplication::removeTranslator(),
+ QObject::tr(), QApplication::translate(), {I18N Example},
+ {Hello tr() Example}, {Arrow Pad Example}, {Troll Print Example}
+*/
+
+/*!
+ Constructs an empty message file object with parent \a parent that
+ is not connected to any file.
+*/
+
+QTranslator::QTranslator(QObject * parent)
+ : QObject(*new QTranslatorPrivate, parent)
+{
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ \overload QTranslator()
+ \obsolete
+ */
+QTranslator::QTranslator(QObject * parent, const char * name)
+ : QObject(*new QTranslatorPrivate, parent)
+{
+ setObjectName(QString::fromAscii(name));
+}
+#endif
+
+/*!
+ Destroys the object and frees any allocated resources.
+*/
+
+QTranslator::~QTranslator()
+{
+ if (QCoreApplication::instance())
+ QCoreApplication::removeTranslator(this);
+ Q_D(QTranslator);
+ d->clear();
+}
+
+/*!
+
+ Loads \a filename + \a suffix (".qm" if the \a suffix is not
+ specified), which may be an absolute file name or relative to \a
+ directory. Returns true if the translation is successfully loaded;
+ otherwise returns false.
+
+ If \a directory is not specified, the directory of the
+ application's executable is used (i.e., as
+ \l{QCoreApplication::}{applicationDirPath()}).
+
+ The previous contents of this translator object are discarded.
+
+ If the file name does not exist, other file names are tried
+ in the following order:
+
+ \list 1
+ \o File name without \a suffix appended.
+ \o File name with text after a character in \a search_delimiters
+ stripped ("_." is the default for \a search_delimiters if it is
+ an empty string) and \a suffix.
+ \o File name stripped without \a suffix appended.
+ \o File name stripped further, etc.
+ \endlist
+
+ For example, an application running in the fr_CA locale
+ (French-speaking Canada) might call load("foo.fr_ca",
+ "/opt/foolib"). load() would then try to open the first existing
+ readable file from this list:
+
+ \list 1
+ \o \c /opt/foolib/foo.fr_ca.qm
+ \o \c /opt/foolib/foo.fr_ca
+ \o \c /opt/foolib/foo.fr.qm
+ \o \c /opt/foolib/foo.fr
+ \o \c /opt/foolib/foo.qm
+ \o \c /opt/foolib/foo
+ \endlist
+*/
+
+bool QTranslator::load(const QString & filename, const QString & directory,
+ const QString & search_delimiters,
+ const QString & suffix)
+{
+ Q_D(QTranslator);
+ d->clear();
+
+ QString prefix;
+ if (QFileInfo(filename).isRelative()) {
+ prefix = directory;
+ if (prefix.length() && !prefix.endsWith(QLatin1Char('/')))
+ prefix += QLatin1Char('/');
+ }
+
+ QString fname = filename;
+ QString realname;
+ QString delims;
+ delims = search_delimiters.isNull() ? QString::fromLatin1("_.") : search_delimiters;
+
+ for (;;) {
+ QFileInfo fi;
+
+ realname = prefix + fname + (suffix.isNull() ? QString::fromLatin1(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ break;
+
+ realname = prefix + fname;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ break;
+
+ int rightmost = 0;
+ for (int i = 0; i < (int)delims.length(); i++) {
+ int k = fname.lastIndexOf(delims[i]);
+ if (k > rightmost)
+ rightmost = k;
+ }
+
+ // no truncations? fail
+ if (rightmost == 0)
+ return false;
+
+ fname.truncate(rightmost);
+ }
+
+ // realname is now the fully qualified name of a readable file.
+ return d->do_load(realname);
+}
+
+bool QTranslatorPrivate::do_load(const QString &realname)
+{
+ QTranslatorPrivate *d = this;
+ bool ok = false;
+
+#ifdef QT_USE_MMAP
+
+#ifndef MAP_FILE
+#define MAP_FILE 0
+#endif
+#ifndef MAP_FAILED
+#define MAP_FAILED -1
+#endif
+
+ int fd = -1;
+ if (!realname.startsWith(QLatin1Char(':')))
+ fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY,
+#if defined(Q_OS_WIN)
+ _S_IREAD | _S_IWRITE
+#else
+ 0666
+#endif
+ );
+ if (fd >= 0) {
+ QT_STATBUF st;
+ if (!QT_FSTAT(fd, &st)) {
+ char *ptr;
+ ptr = reinterpret_cast<char *>(
+ mmap(0, st.st_size, // any address, whole file
+ PROT_READ, // read-only memory
+ MAP_FILE | MAP_PRIVATE, // swap-backed map from file
+ fd, 0)); // from offset 0 of fd
+ if (ptr && ptr != reinterpret_cast<char *>(MAP_FAILED)) {
+ d->used_mmap = true;
+ d->unmapPointer = ptr;
+ d->unmapLength = st.st_size;
+ ok = true;
+ }
+ }
+ ::close(fd);
+ }
+#endif // QT_USE_MMAP
+
+ if (!ok) {
+ QFile file(realname);
+ d->unmapLength = file.size();
+ if (!d->unmapLength)
+ return false;
+ d->unmapPointer = new char[d->unmapLength];
+
+ if (file.open(QIODevice::ReadOnly))
+ ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength));
+
+ if (!ok) {
+ delete [] d->unmapPointer;
+ d->unmapPointer = 0;
+ d->unmapLength = 0;
+ return false;
+ }
+ }
+
+ return d->do_load(reinterpret_cast<const uchar *>(d->unmapPointer), d->unmapLength);
+}
+
+static QString find_translation(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ QString path;
+ if (QFileInfo(filename).isRelative()) {
+ path = directory;
+ if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ }
+
+ QFileInfo fi;
+ QString realname;
+ QStringList fuzzyLocales;
+
+ // see http://www.unicode.org/reports/tr35/#LanguageMatching for inspiration
+
+ QStringList languages = locale.uiLanguages();
+#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN)
+ for (int i = languages.size()-1; i >= 0; --i) {
+ QString lang = languages.at(i);
+ QString lowerLang = lang.toLower();
+ if (lang != lowerLang)
+ languages.insert(i+1, lowerLang);
+ }
+#endif
+
+ // try explicit locales names first
+ foreach (QString localeName, languages) {
+ localeName.replace(QLatin1Char('-'), QLatin1Char('_'));
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ fuzzyLocales.append(localeName);
+ }
+
+ // start guessing
+ foreach (QString localeName, fuzzyLocales) {
+ for (;;) {
+ int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
+ // no truncations? fail
+ if (rightmost <= 0)
+ break;
+ localeName.truncate(rightmost);
+
+ realname = path + filename + prefix + localeName + (suffix.isNull() ? QLatin1String(".qm") : suffix);
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename + prefix + localeName;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+ }
+
+ if (!suffix.isNull()) {
+ realname = path + filename + suffix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+ }
+
+ realname = path + filename + prefix;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ realname = path + filename;
+ fi.setFile(realname);
+ if (fi.isReadable() && fi.isFile())
+ return realname;
+
+ return QString();
+}
+
+/*!
+ \since 4.8
+
+ Loads \a filename + \a prefix + \a \l{QLocale::uiLanguages()}{ui language
+ name} + \a suffix (".qm" if the \a suffix is not specified), which may be
+ an absolute file name or relative to \a directory. Returns true if the
+ translation is successfully loaded; otherwise returns false.
+
+ The previous contents of this translator object are discarded.
+
+ If the file name does not exist, other file names are tried
+ in the following order:
+
+ \list 1
+ \o File name without \a suffix appended.
+ \o File name with ui language part after a "_" character stripped and \a suffix.
+ \o File name with ui language part stripped without \a suffix appended.
+ \o File name with ui language part stripped further, etc.
+ \endlist
+
+ For example, an application running in the locale with the following
+ l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call
+ load(QLocale::system(), "foo", ".", "/opt/foolib", ".qm"). load() would
+ replace '-' (dash) with '_' (underscore) in the ui language and then try to
+ open the first existing readable file from this list:
+
+ \list 1
+ \o \c /opt/foolib/foo.es.qm
+ \o \c /opt/foolib/foo.es
+ \o \c /opt/foolib/foo.fr_CA.qm
+ \o \c /opt/foolib/foo.fr_CA
+ \o \c /opt/foolib/foo.de.qm
+ \o \c /opt/foolib/foo.de
+ \o \c /opt/foolib/foo.fr.qm
+ \o \c /opt/foolib/foo.fr
+ \o \c /opt/foolib/foo.qm
+ \o \c /opt/foolib/foo.
+ \o \c /opt/foolib/foo
+ \endlist
+
+ For OSs where file system is case sensitive, QTranslator also tries to load
+ a lower-cased version of the locale name.
+*/
+bool QTranslator::load(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix,
+ const QString & directory,
+ const QString & suffix)
+{
+ Q_D(QTranslator);
+ d->clear();
+ QString fname = find_translation(locale, filename, prefix, directory, suffix);
+ return !fname.isEmpty() && d->do_load(fname);
+}
+
+/*!
+ \overload load()
+ \fn bool QTranslator::load(const uchar *data, int len)
+
+ Loads the QM file data \a data of length \a len into the
+ translator.
+
+ The data is not copied. The caller must be able to guarantee that \a data
+ will not be deleted or modified.
+*/
+bool QTranslator::load(const uchar *data, int len)
+{
+ Q_D(QTranslator);
+ d->clear();
+ return d->do_load(data, len);
+}
+
+static quint8 read8(const uchar *data)
+{
+ return *data;
+}
+
+static quint16 read16(const uchar *data)
+{
+ return (data[0] << 8) | (data[1]);
+}
+
+static quint32 read32(const uchar *data)
+{
+ return (data[0] << 24)
+ | (data[1] << 16)
+ | (data[2] << 8)
+ | (data[3]);
+}
+
+bool QTranslatorPrivate::do_load(const uchar *data, int len)
+{
+ if (!data || len < MagicLength || memcmp(data, magic, MagicLength))
+ return false;
+
+ bool ok = true;
+ const uchar *end = data + len;
+
+ data += MagicLength;
+
+ while (data < end - 4) {
+ quint8 tag = read8(data++);
+ quint32 blockLen = read32(data);
+ data += 4;
+ if (!tag || !blockLen)
+ break;
+ if (data + blockLen > end) {
+ ok = false;
+ break;
+ }
+
+ if (tag == QTranslatorPrivate::Contexts) {
+ contextArray = data;
+ contextLength = blockLen;
+ } else if (tag == QTranslatorPrivate::Hashes) {
+ offsetArray = data;
+ offsetLength = blockLen;
+ } else if (tag == QTranslatorPrivate::Messages) {
+ messageArray = data;
+ messageLength = blockLen;
+ } else if (tag == QTranslatorPrivate::NumerusRules) {
+ numerusRulesArray = data;
+ numerusRulesLength = blockLen;
+ }
+
+ data += blockLen;
+ }
+
+ return ok;
+}
+
+static QString getMessage(const uchar *m, const uchar *end, const char *context,
+ const char *sourceText, const char *comment, int numerus)
+{
+ const uchar *tn = 0;
+ uint tn_length = 0;
+ int currentNumerus = -1;
+
+ for (;;) {
+ uchar tag = 0;
+ if (m < end)
+ tag = read8(m++);
+ switch((Tag)tag) {
+ case Tag_End:
+ goto end;
+ case Tag_Translation: {
+ int len = read32(m);
+ if (len % 1)
+ return QString();
+ m += 4;
+ if (++currentNumerus == numerus) {
+ tn_length = len;
+ tn = m;
+ }
+ m += len;
+ break;
+ }
+ case Tag_Obsolete1:
+ m += 4;
+ break;
+ case Tag_SourceText: {
+ quint32 len = read32(m);
+ m += 4;
+ if (!match(m, sourceText, len))
+ return QString();
+ m += len;
+ }
+ break;
+ case Tag_Context: {
+ quint32 len = read32(m);
+ m += 4;
+ if (!match(m, context, len))
+ return QString();
+ m += len;
+ }
+ break;
+ case Tag_Comment: {
+ quint32 len = read32(m);
+ m += 4;
+ if (*m && !match(m, comment, len))
+ return QString();
+ m += len;
+ }
+ break;
+ default:
+ return QString();
+ }
+ }
+end:
+ if (!tn)
+ return QString();
+ QString str = QString((const QChar *)tn, tn_length/2);
+ if (QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ for (int i = 0; i < str.length(); ++i)
+ str[i] = QChar((str.at(i).unicode() >> 8) + ((str.at(i).unicode() << 8) & 0xff00));
+ }
+ return str;
+}
+
+QString QTranslatorPrivate::do_translate(const char *context, const char *sourceText,
+ const char *comment, int n) const
+{
+ if (context == 0)
+ context = "";
+ if (sourceText == 0)
+ sourceText = "";
+ if (comment == 0)
+ comment = "";
+
+ if (!offsetLength)
+ return QString();
+
+ /*
+ Check if the context belongs to this QTranslator. If many
+ translators are installed, this step is necessary.
+ */
+ if (contextLength) {
+ quint16 hTableSize = read16(contextArray);
+ uint g = elfHash(context) % hTableSize;
+ const uchar *c = contextArray + 2 + (g << 1);
+ quint16 off = read16(c);
+ c += 2;
+ if (off == 0)
+ return QString();
+ c = contextArray + (2 + (hTableSize << 1) + (off << 1));
+
+ for (;;) {
+ quint8 len = read8(c++);
+ if (len == 0)
+ return QString();
+ if (match(c, context, len))
+ break;
+ c += len;
+ }
+ }
+
+ size_t numItems = offsetLength / (2 * sizeof(quint32));
+ if (!numItems)
+ return QString();
+
+ int numerus = 0;
+ if (n >= 0)
+ numerus = numerusHelper(n, numerusRulesArray, numerusRulesLength);
+
+ for (;;) {
+ quint32 h = elfHash(QByteArray(QByteArray(sourceText) + comment).constData());
+
+ const uchar *start = offsetArray;
+ const uchar *end = start + ((numItems-1) << 3);
+ while (start <= end) {
+ const uchar *middle = start + (((end - start) >> 4) << 3);
+ uint hash = read32(middle);
+ if (h == hash) {
+ start = middle;
+ break;
+ } else if (hash < h) {
+ start = middle + 8;
+ } else {
+ end = middle - 8;
+ }
+ }
+
+ if (start <= end) {
+ // go back on equal key
+ while (start != offsetArray && read32(start) == read32(start-8))
+ start -= 8;
+
+ while (start < offsetArray + offsetLength) {
+ quint32 rh = read32(start);
+ start += 4;
+ if (rh != h)
+ break;
+ quint32 ro = read32(start);
+ start += 4;
+ QString tn = getMessage(messageArray + ro, messageArray + messageLength, context,
+ sourceText, comment, numerus);
+ if (!tn.isNull())
+ return tn;
+ }
+ }
+ if (!comment[0])
+ break;
+ comment = "";
+ }
+ return QString();
+}
+
+/*!
+ Empties this translator of all contents.
+
+ This function works with stripped translator files.
+*/
+
+void QTranslatorPrivate::clear()
+{
+ Q_Q(QTranslator);
+ if (unmapPointer && unmapLength) {
+#if defined(QT_USE_MMAP)
+ if (used_mmap)
+ munmap(unmapPointer, unmapLength);
+ else
+#endif
+ delete [] unmapPointer;
+ }
+
+ unmapPointer = 0;
+ unmapLength = 0;
+ messageArray = 0;
+ contextArray = 0;
+ offsetArray = 0;
+ numerusRulesArray = 0;
+ messageLength = 0;
+ contextLength = 0;
+ offsetLength = 0;
+ numerusRulesLength = 0;
+
+ if (QCoreApplicationPrivate::isTranslatorInstalled(q))
+ QCoreApplication::postEvent(QCoreApplication::instance(),
+ new QEvent(QEvent::LanguageChange));
+}
+
+/*!
+ Returns the translation for the key (\a context, \a sourceText,
+ \a disambiguation). If none is found, also tries (\a context, \a
+ sourceText, ""). If that still fails, returns an empty string.
+
+ If you need to programatically insert translations in to a
+ QTranslator, this function can be reimplemented.
+
+ \sa load()
+*/
+QString QTranslator::translate(const char *context, const char *sourceText, const char *disambiguation) const
+{
+ Q_D(const QTranslator);
+ return d->do_translate(context, sourceText, disambiguation, -1);
+}
+
+
+/*!
+ \overload translate()
+
+ Returns the translation for the key (\a context, \a sourceText,
+ \a disambiguation). If none is found, also tries (\a context, \a
+ sourceText, ""). If that still fails, returns an empty string.
+
+ If \a n is not -1, it is used to choose an appropriate form for
+ the translation (e.g. "%n file found" vs. "%n files found").
+
+ \sa load()
+*/
+QString QTranslator::translate(const char *context, const char *sourceText, const char *disambiguation,
+ int n) const
+{
+ Q_D(const QTranslator);
+ // this step is necessary because the 3-parameter translate() overload is virtual
+ if (n == -1)
+ return translate(context, sourceText, disambiguation);
+ return d->do_translate(context, sourceText, disambiguation, n);
+}
+
+/*!
+ Returns true if this translator is empty, otherwise returns false.
+ This function works with stripped and unstripped translation files.
+*/
+bool QTranslator::isEmpty() const
+{
+ Q_D(const QTranslator);
+ return !d->unmapPointer && !d->unmapLength && !d->messageArray &&
+ !d->offsetArray && !d->contextArray;
+}
+
+/*!
+ \fn QString QTranslator::find(const char *context, const char *sourceText, const char * comment = 0) const
+
+ Use translate(\a context, \a sourceText, \a comment) instead.
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_TRANSLATION
diff --git a/src/corelib/kernel/qtranslator.h b/src/corelib/kernel/qtranslator.h
new file mode 100644
index 0000000000..7a4fa00369
--- /dev/null
+++ b/src/corelib/kernel/qtranslator.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QTRANSLATOR_H
+#define QTRANSLATOR_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_TRANSLATION
+
+class QLocale;
+class QTranslatorPrivate;
+
+class Q_CORE_EXPORT QTranslator : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QTranslator(QObject *parent = 0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QTranslator(QObject * parent, const char * name);
+#endif
+ ~QTranslator();
+
+ // ### Qt 5: Merge (with "int n = -1")
+ virtual QString translate(const char *context, const char *sourceText,
+ const char *disambiguation = 0) const;
+ QString translate(const char *context, const char *sourceText, const char *disambiguation,
+ int n) const;
+
+ virtual bool isEmpty() const;
+
+ bool load(const QString & filename,
+ const QString & directory = QString(),
+ const QString & search_delimiters = QString(),
+ const QString & suffix = QString());
+ bool load(const QLocale & locale,
+ const QString & filename,
+ const QString & prefix = QString(),
+ const QString & directory = QString(),
+ const QString & suffix = QString());
+ bool load(const uchar *data, int len);
+
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT QString find(const char *context, const char *sourceText, const char * comment = 0) const
+ { return translate(context, sourceText, comment); }
+#endif
+
+private:
+ Q_DISABLE_COPY(QTranslator)
+ Q_DECLARE_PRIVATE(QTranslator)
+};
+
+#endif // QT_NO_TRANSLATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTRANSLATOR_H
diff --git a/src/corelib/kernel/qtranslator_p.h b/src/corelib/kernel/qtranslator_p.h
new file mode 100644
index 0000000000..fd29592ded
--- /dev/null
+++ b/src/corelib/kernel/qtranslator_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QTRANSLATOR_P_H
+#define QTRANSLATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of qfontencodings_x11.cpp and qfont_x11.cpp. This header file may
+// change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+enum {
+ Q_EQ = 0x01,
+ Q_LT = 0x02,
+ Q_LEQ = 0x03,
+ Q_BETWEEN = 0x04,
+
+ Q_NOT = 0x08,
+ Q_MOD_10 = 0x10,
+ Q_MOD_100 = 0x20,
+ Q_LEAD_1000 = 0x40,
+
+ Q_AND = 0xFD,
+ Q_OR = 0xFE,
+ Q_NEWRULE = 0xFF,
+
+ Q_OP_MASK = 0x07,
+
+ Q_NEQ = Q_NOT | Q_EQ,
+ Q_GT = Q_NOT | Q_LEQ,
+ Q_GEQ = Q_NOT | Q_LT,
+ Q_NOT_BETWEEN = Q_NOT | Q_BETWEEN
+};
+
+#endif
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
new file mode 100644
index 0000000000..f0652386c2
--- /dev/null
+++ b/src/corelib/kernel/qvariant.cpp
@@ -0,0 +1,3237 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qvariant.h"
+#include "qbitarray.h"
+#include "qbytearray.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+#include "qmap.h"
+#include "qdatetime.h"
+#include "qeasingcurve.h"
+#include "qlist.h"
+#include "qstring.h"
+#include "qstringlist.h"
+#include "qurl.h"
+#include "qlocale.h"
+#include "private/qvariant_p.h"
+
+#ifndef QT_NO_GEOM_VARIANT
+#include "qsize.h"
+#include "qpoint.h"
+#include "qrect.h"
+#include "qline.h"
+#endif
+
+#include <float.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef DBL_DIG
+# define DBL_DIG 10
+#endif
+#ifndef FLT_DIG
+# define FLT_DIG 6
+#endif
+
+static void construct(QVariant::Private *x, const void *copy)
+{
+ x->is_shared = false;
+
+ switch (x->type) {
+ case QVariant::String:
+ v_construct<QString>(x, copy);
+ break;
+ case QVariant::Char:
+ v_construct<QChar>(x, copy);
+ break;
+ case QVariant::StringList:
+ v_construct<QStringList>(x, copy);
+ break;
+ case QVariant::Map:
+ v_construct<QVariantMap>(x, copy);
+ break;
+ case QVariant::Hash:
+ v_construct<QVariantHash>(x, copy);
+ break;
+ case QVariant::List:
+ v_construct<QVariantList>(x, copy);
+ break;
+ case QVariant::Date:
+ v_construct<QDate>(x, copy);
+ break;
+ case QVariant::Time:
+ v_construct<QTime>(x, copy);
+ break;
+ case QVariant::DateTime:
+ v_construct<QDateTime>(x, copy);
+ break;
+ case QVariant::ByteArray:
+ v_construct<QByteArray>(x, copy);
+ break;
+ case QVariant::BitArray:
+ v_construct<QBitArray>(x, copy);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size:
+ v_construct<QSize>(x, copy);
+ break;
+ case QVariant::SizeF:
+ v_construct<QSizeF>(x, copy);
+ break;
+ case QVariant::Rect:
+ v_construct<QRect>(x, copy);
+ break;
+ case QVariant::LineF:
+ v_construct<QLineF>(x, copy);
+ break;
+ case QVariant::Line:
+ v_construct<QLine>(x, copy);
+ break;
+ case QVariant::RectF:
+ v_construct<QRectF>(x, copy);
+ break;
+ case QVariant::Point:
+ v_construct<QPoint>(x, copy);
+ break;
+ case QVariant::PointF:
+ v_construct<QPointF>(x, copy);
+ break;
+#endif
+ case QVariant::Url:
+ v_construct<QUrl>(x, copy);
+ break;
+ case QVariant::Locale:
+ v_construct<QLocale>(x, copy);
+ break;
+#ifndef QT_NO_REGEXP
+ case QVariant::RegExp:
+ v_construct<QRegExp>(x, copy);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ v_construct<QEasingCurve>(x, copy);
+ break;
+#endif
+ case QVariant::Int:
+ x->data.i = copy ? *static_cast<const int *>(copy) : 0;
+ break;
+ case QVariant::UInt:
+ x->data.u = copy ? *static_cast<const uint *>(copy) : 0u;
+ break;
+ case QVariant::Bool:
+ x->data.b = copy ? *static_cast<const bool *>(copy) : false;
+ break;
+ case QVariant::Double:
+ x->data.d = copy ? *static_cast<const double*>(copy) : 0.0;
+ break;
+ case QMetaType::Float:
+ x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
+ break;
+ case QMetaType::QObjectStar:
+ x->data.o = copy ? *static_cast<QObject *const*>(copy) : 0;
+ break;
+ case QVariant::LongLong:
+ x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0);
+ break;
+ case QVariant::ULongLong:
+ x->data.ull = copy ? *static_cast<const qulonglong *>(copy) : Q_UINT64_C(0);
+ break;
+ case QVariant::Invalid:
+ case QVariant::UserType:
+ break;
+ default:
+ void *ptr = QMetaType::construct(x->type, copy);
+ if (!ptr) {
+ x->type = QVariant::Invalid;
+ } else {
+ x->is_shared = true;
+ x->data.shared = new QVariant::PrivateShared(ptr);
+ }
+ break;
+ }
+ x->is_null = !copy;
+}
+
+static void clear(QVariant::Private *d)
+{
+ switch (d->type) {
+ case QVariant::String:
+ v_clear<QString>(d);
+ break;
+ case QVariant::Char:
+ v_clear<QChar>(d);
+ break;
+ case QVariant::StringList:
+ v_clear<QStringList>(d);
+ break;
+ case QVariant::Map:
+ v_clear<QVariantMap>(d);
+ break;
+ case QVariant::Hash:
+ v_clear<QVariantHash>(d);
+ break;
+ case QVariant::List:
+ v_clear<QVariantList>(d);
+ break;
+ case QVariant::Date:
+ v_clear<QDate>(d);
+ break;
+ case QVariant::Time:
+ v_clear<QTime>(d);
+ break;
+ case QVariant::DateTime:
+ v_clear<QDateTime>(d);
+ break;
+ case QVariant::ByteArray:
+ v_clear<QByteArray>(d);
+ break;
+ case QVariant::BitArray:
+ v_clear<QBitArray>(d);
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Point:
+ v_clear<QPoint>(d);
+ break;
+ case QVariant::PointF:
+ v_clear<QPointF>(d);
+ break;
+ case QVariant::Size:
+ v_clear<QSize>(d);
+ break;
+ case QVariant::SizeF:
+ v_clear<QSizeF>(d);
+ break;
+ case QVariant::Rect:
+ v_clear<QRect>(d);
+ break;
+ case QVariant::LineF:
+ v_clear<QLineF>(d);
+ break;
+ case QVariant::Line:
+ v_clear<QLine>(d);
+ break;
+ case QVariant::RectF:
+ v_clear<QRectF>(d);
+ break;
+#endif
+ case QVariant::Url:
+ v_clear<QUrl>(d);
+ break;
+ case QVariant::Locale:
+ v_clear<QLocale>(d);
+ break;
+#ifndef QT_NO_REGEXP
+ case QVariant::RegExp:
+ v_clear<QRegExp>(d);
+ break;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ v_clear<QEasingCurve>(d);
+ break;
+#endif
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QMetaType::QObjectStar:
+ break;
+ case QVariant::Invalid:
+ case QVariant::UserType:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::Bool:
+ break;
+ default:
+ QMetaType::destroy(d->type, d->data.shared->ptr);
+ delete d->data.shared;
+ break;
+ }
+
+ d->type = QVariant::Invalid;
+ d->is_null = true;
+ d->is_shared = false;
+}
+
+static bool isNull(const QVariant::Private *d)
+{
+ switch(d->type) {
+ case QVariant::String:
+ return v_cast<QString>(d)->isNull();
+ case QVariant::Char:
+ return v_cast<QChar>(d)->isNull();
+ case QVariant::Date:
+ return v_cast<QDate>(d)->isNull();
+ case QVariant::Time:
+ return v_cast<QTime>(d)->isNull();
+ case QVariant::DateTime:
+ return v_cast<QDateTime>(d)->isNull();
+ case QVariant::ByteArray:
+ return v_cast<QByteArray>(d)->isNull();
+ case QVariant::BitArray:
+ return v_cast<QBitArray>(d)->isNull();
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size:
+ return v_cast<QSize>(d)->isNull();
+ case QVariant::SizeF:
+ return v_cast<QSizeF>(d)->isNull();
+ case QVariant::Rect:
+ return v_cast<QRect>(d)->isNull();
+ case QVariant::Line:
+ return v_cast<QLine>(d)->isNull();
+ case QVariant::LineF:
+ return v_cast<QLineF>(d)->isNull();
+ case QVariant::RectF:
+ return v_cast<QRectF>(d)->isNull();
+ case QVariant::Point:
+ return v_cast<QPoint>(d)->isNull();
+ case QVariant::PointF:
+ return v_cast<QPointF>(d)->isNull();
+#endif
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+#endif
+ case QVariant::Url:
+ case QVariant::Locale:
+ case QVariant::RegExp:
+ case QVariant::StringList:
+ case QVariant::Map:
+ case QVariant::Hash:
+ case QVariant::List:
+ case QVariant::Invalid:
+ case QVariant::UserType:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Bool:
+ case QVariant::Double:
+ case QMetaType::Float:
+ case QMetaType::QObjectStar:
+ break;
+ }
+ return d->is_null;
+}
+
+/*
+ \internal
+ \since 4.4
+
+ We cannot use v_cast() for QMetaType's numeric types because they're smaller than QVariant::Private::Data,
+ which in turns makes v_cast() believe the value is stored in d->data.c. But
+ it's not, since we're a QMetaType type.
+ */
+template<typename T>
+inline bool compareNumericMetaType(const QVariant::Private *const a, const QVariant::Private *const b)
+{
+ return *static_cast<const T *>(a->data.shared->ptr) == *static_cast<const T *>(b->data.shared->ptr);
+}
+
+/*!
+ \internal
+
+ Compares \a a to \a b. The caller guarantees that \a a and \a b
+ are of the same type.
+ */
+static bool compare(const QVariant::Private *a, const QVariant::Private *b)
+{
+ switch(a->type) {
+ case QVariant::List:
+ return *v_cast<QVariantList>(a) == *v_cast<QVariantList>(b);
+ case QVariant::Map: {
+ const QVariantMap *m1 = v_cast<QVariantMap>(a);
+ const QVariantMap *m2 = v_cast<QVariantMap>(b);
+ if (m1->count() != m2->count())
+ return false;
+ QVariantMap::ConstIterator it = m1->constBegin();
+ QVariantMap::ConstIterator it2 = m2->constBegin();
+ while (it != m1->constEnd()) {
+ if (*it != *it2 || it.key() != it2.key())
+ return false;
+ ++it;
+ ++it2;
+ }
+ return true;
+ }
+ case QVariant::Hash:
+ return *v_cast<QVariantHash>(a) == *v_cast<QVariantHash>(b);
+ case QVariant::String:
+ return *v_cast<QString>(a) == *v_cast<QString>(b);
+ case QVariant::Char:
+ return *v_cast<QChar>(a) == *v_cast<QChar>(b);
+ case QVariant::StringList:
+ return *v_cast<QStringList>(a) == *v_cast<QStringList>(b);
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size:
+ return *v_cast<QSize>(a) == *v_cast<QSize>(b);
+ case QVariant::SizeF:
+ return *v_cast<QSizeF>(a) == *v_cast<QSizeF>(b);
+ case QVariant::Rect:
+ return *v_cast<QRect>(a) == *v_cast<QRect>(b);
+ case QVariant::Line:
+ return *v_cast<QLine>(a) == *v_cast<QLine>(b);
+ case QVariant::LineF:
+ return *v_cast<QLineF>(a) == *v_cast<QLineF>(b);
+ case QVariant::RectF:
+ return *v_cast<QRectF>(a) == *v_cast<QRectF>(b);
+ case QVariant::Point:
+ return *v_cast<QPoint>(a) == *v_cast<QPoint>(b);
+ case QVariant::PointF:
+ return *v_cast<QPointF>(a) == *v_cast<QPointF>(b);
+#endif
+ case QVariant::Url:
+ return *v_cast<QUrl>(a) == *v_cast<QUrl>(b);
+ case QVariant::Locale:
+ return *v_cast<QLocale>(a) == *v_cast<QLocale>(b);
+#ifndef QT_NO_REGEXP
+ case QVariant::RegExp:
+ return *v_cast<QRegExp>(a) == *v_cast<QRegExp>(b);
+#endif
+ case QVariant::Int:
+ return a->data.i == b->data.i;
+ case QVariant::UInt:
+ return a->data.u == b->data.u;
+ case QVariant::LongLong:
+ return a->data.ll == b->data.ll;
+ case QVariant::ULongLong:
+ return a->data.ull == b->data.ull;
+ case QVariant::Bool:
+ return a->data.b == b->data.b;
+ case QVariant::Double:
+ return a->data.d == b->data.d;
+ case QMetaType::Float:
+ return a->data.f == b->data.f;
+ case QMetaType::QObjectStar:
+ return a->data.o == b->data.o;
+ case QVariant::Date:
+ return *v_cast<QDate>(a) == *v_cast<QDate>(b);
+ case QVariant::Time:
+ return *v_cast<QTime>(a) == *v_cast<QTime>(b);
+ case QVariant::DateTime:
+ return *v_cast<QDateTime>(a) == *v_cast<QDateTime>(b);
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ return *v_cast<QEasingCurve>(a) == *v_cast<QEasingCurve>(b);
+#endif
+ case QVariant::ByteArray:
+ return *v_cast<QByteArray>(a) == *v_cast<QByteArray>(b);
+ case QVariant::BitArray:
+ return *v_cast<QBitArray>(a) == *v_cast<QBitArray>(b);
+ case QVariant::Invalid:
+ return true;
+ case QMetaType::Long:
+ return compareNumericMetaType<long>(a, b);
+ case QMetaType::ULong:
+ return compareNumericMetaType<ulong>(a, b);
+ case QMetaType::Short:
+ return compareNumericMetaType<short>(a, b);
+ case QMetaType::UShort:
+ return compareNumericMetaType<ushort>(a, b);
+ case QMetaType::UChar:
+ return compareNumericMetaType<uchar>(a, b);
+ case QMetaType::Char:
+ return compareNumericMetaType<char>(a, b);
+ default:
+ break;
+ }
+ if (!QMetaType::isRegistered(a->type))
+ qFatal("QVariant::compare: type %d unknown to QVariant.", a->type);
+
+ const void *a_ptr = a->is_shared ? a->data.shared->ptr : &(a->data.ptr);
+ const void *b_ptr = b->is_shared ? b->data.shared->ptr : &(b->data.ptr);
+
+ /* The reason we cannot place this test in a case branch above for the types
+ * QMetaType::VoidStar, QMetaType::QObjectStar and so forth, is that it wouldn't include
+ * user defined pointer types. */
+ const char *const typeName = QMetaType::typeName(a->type);
+ uint typeNameLen = qstrlen(typeName);
+ if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*')
+ return *static_cast<void *const *>(a_ptr) == *static_cast<void *const *>(b_ptr);
+
+ if (a->is_null && b->is_null)
+ return true;
+
+ return a_ptr == b_ptr;
+}
+
+/*!
+ \internal
+ */
+static qlonglong qMetaTypeNumber(const QVariant::Private *d)
+{
+ switch (d->type) {
+ case QMetaType::Int:
+ return d->data.i;
+ case QMetaType::LongLong:
+ return d->data.ll;
+ case QMetaType::Char:
+ return qlonglong(*static_cast<signed char *>(d->data.shared->ptr));
+ case QMetaType::Short:
+ return qlonglong(*static_cast<short *>(d->data.shared->ptr));
+ case QMetaType::Long:
+ return qlonglong(*static_cast<long *>(d->data.shared->ptr));
+ case QMetaType::Float:
+ return qRound64(d->data.f);
+ case QVariant::Double:
+ return qRound64(d->data.d);
+ }
+ Q_ASSERT(false);
+ return 0;
+}
+
+static qulonglong qMetaTypeUNumber(const QVariant::Private *d)
+{
+ switch (d->type) {
+ case QVariant::UInt:
+ return d->data.u;
+ case QVariant::ULongLong:
+ return d->data.ull;
+ case QMetaType::UChar:
+ return qulonglong(*static_cast<unsigned char *>(d->data.shared->ptr));
+ case QMetaType::UShort:
+ return qulonglong(*static_cast<ushort *>(d->data.shared->ptr));
+ case QMetaType::ULong:
+ return qulonglong(*static_cast<ulong *>(d->data.shared->ptr));
+ }
+ Q_ASSERT(false);
+ return 0;
+}
+
+static qlonglong qConvertToNumber(const QVariant::Private *d, bool *ok)
+{
+ *ok = true;
+
+ switch (uint(d->type)) {
+ case QVariant::String:
+ return v_cast<QString>(d)->toLongLong(ok);
+ case QVariant::Char:
+ return v_cast<QChar>(d)->unicode();
+ case QVariant::ByteArray:
+ return v_cast<QByteArray>(d)->toLongLong(ok);
+ case QVariant::Bool:
+ return qlonglong(d->data.b);
+ case QVariant::Double:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ case QMetaType::LongLong:
+ return qMetaTypeNumber(d);
+ case QVariant::ULongLong:
+ case QVariant::UInt:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ return qlonglong(qMetaTypeUNumber(d));
+ }
+
+ *ok = false;
+ return Q_INT64_C(0);
+}
+
+static qulonglong qConvertToUnsignedNumber(const QVariant::Private *d, bool *ok)
+{
+ *ok = true;
+
+ switch (uint(d->type)) {
+ case QVariant::String:
+ return v_cast<QString>(d)->toULongLong(ok);
+ case QVariant::Char:
+ return v_cast<QChar>(d)->unicode();
+ case QVariant::ByteArray:
+ return v_cast<QByteArray>(d)->toULongLong(ok);
+ case QVariant::Bool:
+ return qulonglong(d->data.b);
+ case QVariant::Double:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ case QMetaType::LongLong:
+ return qulonglong(qMetaTypeNumber(d));
+ case QVariant::ULongLong:
+ case QVariant::UInt:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ return qMetaTypeUNumber(d);
+ }
+
+ *ok = false;
+ return Q_UINT64_C(0);
+}
+
+template<typename TInput, typename LiteralWrapper>
+inline bool qt_convertToBool(const QVariant::Private *const d)
+{
+ TInput str = v_cast<TInput>(d)->toLower();
+ return !(str == LiteralWrapper("0") || str == LiteralWrapper("false") || str.isEmpty());
+}
+
+/*!
+ \internal
+
+ Converts \a d to type \a t, which is placed in \a result.
+ */
+static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, bool *ok)
+{
+ Q_ASSERT(d->type != uint(t));
+ Q_ASSERT(result);
+
+ bool dummy;
+ if (!ok)
+ ok = &dummy;
+
+ switch (uint(t)) {
+ case QVariant::Url:
+ switch (d->type) {
+ case QVariant::String:
+ *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
+ break;
+ default:
+ return false;
+ }
+ break;
+ case QVariant::String: {
+ QString *str = static_cast<QString *>(result);
+ switch (d->type) {
+ case QVariant::Char:
+ *str = QString(*v_cast<QChar>(d));
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ *str = QChar::fromAscii(*static_cast<char *>(d->data.shared->ptr));
+ break;
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QVariant::Int:
+ case QVariant::LongLong:
+ *str = QString::number(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *str = QString::number(qMetaTypeUNumber(d));
+ break;
+ case QMetaType::Float:
+ *str = QString::number(d->data.f, 'g', FLT_DIG);
+ break;
+ case QVariant::Double:
+ *str = QString::number(d->data.d, 'g', DBL_DIG);
+ break;
+#if !defined(QT_NO_DATESTRING)
+ case QVariant::Date:
+ *str = v_cast<QDate>(d)->toString(Qt::ISODate);
+ break;
+ case QVariant::Time:
+ *str = v_cast<QTime>(d)->toString(Qt::ISODate);
+ break;
+ case QVariant::DateTime:
+ *str = v_cast<QDateTime>(d)->toString(Qt::ISODate);
+ break;
+#endif
+ case QVariant::Bool:
+ *str = QLatin1String(d->data.b ? "true" : "false");
+ break;
+ case QVariant::ByteArray:
+ *str = QString::fromAscii(v_cast<QByteArray>(d)->constData());
+ break;
+ case QVariant::StringList:
+ if (v_cast<QStringList>(d)->count() == 1)
+ *str = v_cast<QStringList>(d)->at(0);
+ break;
+ case QVariant::Url:
+ *str = v_cast<QUrl>(d)->toString();
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+ case QVariant::Char: {
+ QChar *c = static_cast<QChar *>(result);
+ switch (d->type) {
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ *c = QChar(ushort(qMetaTypeNumber(d)));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *c = QChar(ushort(qMetaTypeUNumber(d)));
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Size: {
+ QSize *s = static_cast<QSize *>(result);
+ switch (d->type) {
+ case QVariant::SizeF:
+ *s = v_cast<QSizeF>(d)->toSize();
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ case QVariant::SizeF: {
+ QSizeF *s = static_cast<QSizeF *>(result);
+ switch (d->type) {
+ case QVariant::Size:
+ *s = QSizeF(*(v_cast<QSize>(d)));
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ case QVariant::Line: {
+ QLine *s = static_cast<QLine *>(result);
+ switch (d->type) {
+ case QVariant::LineF:
+ *s = v_cast<QLineF>(d)->toLine();
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+
+ case QVariant::LineF: {
+ QLineF *s = static_cast<QLineF *>(result);
+ switch (d->type) {
+ case QVariant::Line:
+ *s = QLineF(*(v_cast<QLine>(d)));
+ break;
+ default:
+ return false;
+ }
+ break;
+ }
+#endif
+ case QVariant::StringList:
+ if (d->type == QVariant::List) {
+ QStringList *slst = static_cast<QStringList *>(result);
+ const QVariantList *list = v_cast<QVariantList >(d);
+ for (int i = 0; i < list->size(); ++i)
+ slst->append(list->at(i).toString());
+ } else if (d->type == QVariant::String) {
+ QStringList *slst = static_cast<QStringList *>(result);
+ *slst = QStringList(*v_cast<QString>(d));
+ } else {
+ return false;
+ }
+ break;
+ case QVariant::Date: {
+ QDate *dt = static_cast<QDate *>(result);
+ if (d->type == QVariant::DateTime)
+ *dt = v_cast<QDateTime>(d)->date();
+#ifndef QT_NO_DATESTRING
+ else if (d->type == QVariant::String)
+ *dt = QDate::fromString(*v_cast<QString>(d), Qt::ISODate);
+#endif
+ else
+ return false;
+
+ return dt->isValid();
+ }
+ case QVariant::Time: {
+ QTime *t = static_cast<QTime *>(result);
+ switch (d->type) {
+ case QVariant::DateTime:
+ *t = v_cast<QDateTime>(d)->time();
+ break;
+#ifndef QT_NO_DATESTRING
+ case QVariant::String:
+ *t = QTime::fromString(*v_cast<QString>(d), Qt::ISODate);
+ break;
+#endif
+ default:
+ return false;
+ }
+ return t->isValid();
+ }
+ case QVariant::DateTime: {
+ QDateTime *dt = static_cast<QDateTime *>(result);
+ switch (d->type) {
+#ifndef QT_NO_DATESTRING
+ case QVariant::String:
+ *dt = QDateTime::fromString(*v_cast<QString>(d), Qt::ISODate);
+ break;
+#endif
+ case QVariant::Date:
+ *dt = QDateTime(*v_cast<QDate>(d));
+ break;
+ default:
+ return false;
+ }
+ return dt->isValid();
+ }
+ case QVariant::ByteArray: {
+ QByteArray *ba = static_cast<QByteArray *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *ba = v_cast<QString>(d)->toAscii();
+ break;
+ case QVariant::Double:
+ *ba = QByteArray::number(d->data.d, 'g', DBL_DIG);
+ break;
+ case QMetaType::Float:
+ *ba = QByteArray::number(d->data.f, 'g', FLT_DIG);
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ *ba = QByteArray(1, *static_cast<char *>(d->data.shared->ptr));
+ break;
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ *ba = QByteArray::number(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *ba = QByteArray::number(qMetaTypeUNumber(d));
+ break;
+ case QVariant::Bool:
+ *ba = QByteArray(d->data.b ? "true" : "false");
+ break;
+ default:
+ return false;
+ }
+ }
+ break;
+ case QMetaType::Short:
+ *static_cast<short *>(result) = short(qConvertToNumber(d, ok));
+ return *ok;
+ case QMetaType::Long:
+ *static_cast<long *>(result) = long(qConvertToNumber(d, ok));
+ return *ok;
+ case QMetaType::UShort:
+ *static_cast<ushort *>(result) = ushort(qConvertToUnsignedNumber(d, ok));
+ return *ok;
+ case QMetaType::ULong:
+ *static_cast<ulong *>(result) = ulong(qConvertToUnsignedNumber(d, ok));
+ return *ok;
+ case QVariant::Int:
+ *static_cast<int *>(result) = int(qConvertToNumber(d, ok));
+ return *ok;
+ case QVariant::UInt:
+ *static_cast<uint *>(result) = uint(qConvertToUnsignedNumber(d, ok));
+ return *ok;
+ case QVariant::LongLong:
+ *static_cast<qlonglong *>(result) = qConvertToNumber(d, ok);
+ return *ok;
+ case QVariant::ULongLong: {
+ *static_cast<qulonglong *>(result) = qConvertToUnsignedNumber(d, ok);
+ return *ok;
+ }
+ case QMetaType::UChar: {
+ *static_cast<uchar *>(result) = qConvertToUnsignedNumber(d, ok);
+ return *ok;
+ }
+ case QVariant::Bool: {
+ bool *b = static_cast<bool *>(result);
+ switch(d->type) {
+ case QVariant::ByteArray:
+ *b = qt_convertToBool<QByteArray, QByteArray>(d);
+ break;
+ case QVariant::String:
+ *b = qt_convertToBool<QString, QLatin1String>(d);
+ break;
+ case QVariant::Char:
+ *b = !v_cast<QChar>(d)->isNull();
+ break;
+ case QVariant::Double:
+ case QVariant::Int:
+ case QVariant::LongLong:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ case QMetaType::Float:
+ *b = qMetaTypeNumber(d) != Q_INT64_C(0);
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *b = qMetaTypeUNumber(d) != Q_UINT64_C(0);
+ break;
+ default:
+ *b = false;
+ return false;
+ }
+ break;
+ }
+ case QVariant::Double: {
+ double *f = static_cast<double *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *f = v_cast<QString>(d)->toDouble(ok);
+ break;
+ case QVariant::ByteArray:
+ *f = v_cast<QByteArray>(d)->toDouble(ok);
+ break;
+ case QVariant::Bool:
+ *f = double(d->data.b);
+ break;
+ case QMetaType::Float:
+ *f = double(d->data.f);
+ break;
+ case QVariant::LongLong:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ *f = double(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *f = double(qMetaTypeUNumber(d));
+ break;
+ default:
+ *f = 0.0;
+ return false;
+ }
+ break;
+ }
+ case QMetaType::Float: {
+ float *f = static_cast<float *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *f = v_cast<QString>(d)->toFloat(ok);
+ break;
+ case QVariant::ByteArray:
+ *f = v_cast<QByteArray>(d)->toFloat(ok);
+ break;
+ case QVariant::Bool:
+ *f = float(d->data.b);
+ break;
+ case QVariant::Double:
+ *f = float(d->data.d);
+ break;
+ case QVariant::LongLong:
+ case QVariant::Int:
+ case QMetaType::Char:
+ case QMetaType::Short:
+ case QMetaType::Long:
+ *f = float(qMetaTypeNumber(d));
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ case QMetaType::UChar:
+ case QMetaType::UShort:
+ case QMetaType::ULong:
+ *f = float(qMetaTypeUNumber(d));
+ break;
+ default:
+ *f = 0.0f;
+ return false;
+ }
+ break;
+ }
+ case QVariant::List:
+ if (d->type == QVariant::StringList) {
+ QVariantList *lst = static_cast<QVariantList *>(result);
+ const QStringList *slist = v_cast<QStringList>(d);
+ for (int i = 0; i < slist->size(); ++i)
+ lst->append(QVariant(slist->at(i)));
+ } else if (qstrcmp(QMetaType::typeName(d->type), "QList<QVariant>") == 0) {
+ *static_cast<QVariantList *>(result) =
+ *static_cast<QList<QVariant> *>(d->data.shared->ptr);
+ } else {
+ return false;
+ }
+ break;
+ case QVariant::Map:
+ if (qstrcmp(QMetaType::typeName(d->type), "QMap<QString, QVariant>") == 0) {
+ *static_cast<QVariantMap *>(result) =
+ *static_cast<QMap<QString, QVariant> *>(d->data.shared->ptr);
+ } else {
+ return false;
+ }
+ break;
+ case QVariant::Hash:
+ if (qstrcmp(QMetaType::typeName(d->type), "QHash<QString, QVariant>") == 0) {
+ *static_cast<QVariantHash *>(result) =
+ *static_cast<QHash<QString, QVariant> *>(d->data.shared->ptr);
+ } else {
+ return false;
+ }
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Rect:
+ if (d->type == QVariant::RectF)
+ *static_cast<QRect *>(result) = (v_cast<QRectF>(d))->toRect();
+ else
+ return false;
+ break;
+ case QVariant::RectF:
+ if (d->type == QVariant::Rect)
+ *static_cast<QRectF *>(result) = *v_cast<QRect>(d);
+ else
+ return false;
+ break;
+ case QVariant::PointF:
+ if (d->type == QVariant::Point)
+ *static_cast<QPointF *>(result) = *v_cast<QPoint>(d);
+ else
+ return false;
+ break;
+ case QVariant::Point:
+ if (d->type == QVariant::PointF)
+ *static_cast<QPoint *>(result) = (v_cast<QPointF>(d))->toPoint();
+ else
+ return false;
+ break;
+ case QMetaType::Char:
+ {
+ *static_cast<qint8 *>(result) = qint8(qConvertToNumber(d, ok));
+ return *ok;
+ }
+#endif
+ default:
+ return false;
+ }
+ return true;
+}
+
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+static void streamDebug(QDebug dbg, const QVariant &v)
+{
+ switch (v.userType()) {
+ case QVariant::Int:
+ dbg.nospace() << v.toInt();
+ break;
+ case QVariant::UInt:
+ dbg.nospace() << v.toUInt();
+ break;
+ case QVariant::LongLong:
+ dbg.nospace() << v.toLongLong();
+ break;
+ case QVariant::ULongLong:
+ dbg.nospace() << v.toULongLong();
+ break;
+ case QMetaType::Float:
+ dbg.nospace() << v.toFloat();
+ break;
+ case QMetaType::QObjectStar:
+ dbg.nospace() << qvariant_cast<QObject *>(v);
+ break;
+ case QVariant::Double:
+ dbg.nospace() << v.toDouble();
+ break;
+ case QVariant::Bool:
+ dbg.nospace() << v.toBool();
+ break;
+ case QVariant::String:
+ dbg.nospace() << v.toString();
+ break;
+ case QVariant::Char:
+ dbg.nospace() << v.toChar();
+ break;
+ case QVariant::StringList:
+ dbg.nospace() << v.toStringList();
+ break;
+ case QVariant::Map:
+ dbg.nospace() << v.toMap();
+ break;
+ case QVariant::Hash:
+ dbg.nospace() << v.toHash();
+ break;
+ case QVariant::List:
+ dbg.nospace() << v.toList();
+ break;
+ case QVariant::Date:
+ dbg.nospace() << v.toDate();
+ break;
+ case QVariant::Time:
+ dbg.nospace() << v.toTime();
+ break;
+ case QVariant::DateTime:
+ dbg.nospace() << v.toDateTime();
+ break;
+#ifndef QT_BOOTSTRAPPED
+ case QVariant::EasingCurve:
+ dbg.nospace() << v.toEasingCurve();
+ break;
+#endif
+ case QVariant::ByteArray:
+ dbg.nospace() << v.toByteArray();
+ break;
+ case QVariant::Url:
+ dbg.nospace() << v.toUrl();
+ break;
+#ifndef QT_NO_GEOM_VARIANT
+ case QVariant::Point:
+ dbg.nospace() << v.toPoint();
+ break;
+ case QVariant::PointF:
+ dbg.nospace() << v.toPointF();
+ break;
+ case QVariant::Rect:
+ dbg.nospace() << v.toRect();
+ break;
+ case QVariant::Size:
+ dbg.nospace() << v.toSize();
+ break;
+ case QVariant::SizeF:
+ dbg.nospace() << v.toSizeF();
+ break;
+ case QVariant::Line:
+ dbg.nospace() << v.toLine();
+ break;
+ case QVariant::LineF:
+ dbg.nospace() << v.toLineF();
+ break;
+ case QVariant::RectF:
+ dbg.nospace() << v.toRectF();
+ break;
+#endif
+ case QVariant::BitArray:
+ //dbg.nospace() << v.toBitArray();
+ break;
+ default:
+ break;
+ }
+}
+#endif
+
+const QVariant::Handler qt_kernel_variant_handler = {
+ construct,
+ clear,
+ isNull,
+#ifndef QT_NO_DATASTREAM
+ 0,
+ 0,
+#endif
+ compare,
+ convert,
+ 0,
+#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
+ streamDebug
+#else
+ 0
+#endif
+};
+
+Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler()
+{
+ return &qt_kernel_variant_handler;
+}
+
+
+const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
+
+/*!
+ \class QVariant
+ \brief The QVariant class acts like a union for the most common Qt data types.
+
+ \ingroup objectmodel
+ \ingroup shared
+
+
+ Because C++ forbids unions from including types that have
+ non-default constructors or destructors, most interesting Qt
+ classes cannot be used in unions. Without QVariant, this would be
+ a problem for QObject::property() and for database work, etc.
+
+ A QVariant object holds a single value of a single type() at a
+ time. (Some type()s are multi-valued, for example a string list.)
+ You can find out what type, T, the variant holds, convert it to a
+ different type using convert(), get its value using one of the
+ toT() functions (e.g., toSize()) and check whether the type can
+ be converted to a particular type using canConvert().
+
+ The methods named toT() (e.g., toInt(), toString()) are const. If
+ you ask for the stored type, they return a copy of the stored
+ object. If you ask for a type that can be generated from the
+ stored type, toT() copies and converts and leaves the object
+ itself unchanged. If you ask for a type that cannot be generated
+ from the stored type, the result depends on the type; see the
+ function documentation for details.
+
+ Here is some example code to demonstrate the use of QVariant:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 0
+
+ You can even store QList<QVariant> and QMap<QString, QVariant>
+ values in a variant, so you can easily construct arbitrarily
+ complex data structures of arbitrary types. This is very powerful
+ 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 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
+
+ QVariant can be extended to support other types than those
+ mentioned in the \l Type enum. See the \l QMetaType documentation
+ for details.
+
+ \section1 A Note on GUI Types
+
+ Because QVariant is part of the QtCore library, it cannot provide
+ conversion functions to data types defined in QtGui, such as
+ QColor, QImage, and QPixmap. In other words, there is no \c
+ toColor() function. Instead, you can use the QVariant::value() or
+ the qvariant_cast() template function. For example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 2
+
+ The inverse conversion (e.g., from QColor to QVariant) is
+ automatic for all data types supported by QVariant, including
+ GUI-related types:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 3
+
+ \section1 Using canConvert() and convert() Consecutively
+
+ When using canConvert() and convert() consecutively, it is possible for
+ canConvert() to return true, but convert() to return false. This
+ is typically because canConvert() only reports the general ability of
+ QVariant to convert between types given suitable data; it is still
+ possible to supply data which cannot actually be converted.
+
+ For example, canConvert() would return true when called on a variant
+ containing a string because, in principle, QVariant is able to convert
+ strings of numbers to integers.
+ However, if the string contains non-numeric characters, it cannot be
+ converted to an integer, and any attempt to convert it will fail.
+ Hence, it is important to have both functions return true for a
+ successful conversion.
+
+ \sa QMetaType
+*/
+
+/*!
+ \enum QVariant::Type
+
+ This enum type defines the types of variable that a QVariant can
+ contain.
+
+ \value Invalid no type
+ \value BitArray a QBitArray
+ \value Bitmap a QBitmap
+ \value Bool a bool
+ \value Brush a QBrush
+ \value ByteArray a QByteArray
+ \value Char a QChar
+ \value Color a QColor
+ \value Cursor a QCursor
+ \value Date a QDate
+ \value DateTime a QDateTime
+ \value Double a double
+ \value EasingCurve a QEasingCurve
+ \value Font a QFont
+ \value Hash a QVariantHash
+ \value Icon a QIcon
+ \value Image a QImage
+ \value Int an int
+ \value KeySequence a QKeySequence
+ \value Line a QLine
+ \value LineF a QLineF
+ \value List a QVariantList
+ \value Locale a QLocale
+ \value LongLong a \l qlonglong
+ \value Map a QVariantMap
+ \value Matrix a QMatrix
+ \value Transform a QTransform
+ \value Matrix4x4 a QMatrix4x4
+ \value Palette a QPalette
+ \value Pen a QPen
+ \value Pixmap a QPixmap
+ \value Point a QPoint
+ \value PointArray a QPointArray
+ \value PointF a QPointF
+ \value Polygon a QPolygon
+ \value Quaternion a QQuaternion
+ \value Rect a QRect
+ \value RectF a QRectF
+ \value RegExp a QRegExp
+ \value Region a QRegion
+ \value Size a QSize
+ \value SizeF a QSizeF
+ \value SizePolicy a QSizePolicy
+ \value String a QString
+ \value StringList a QStringList
+ \value TextFormat a QTextFormat
+ \value TextLength a QTextLength
+ \value Time a QTime
+ \value UInt a \l uint
+ \value ULongLong a \l qulonglong
+ \value Url a QUrl
+ \value Vector2D a QVector2D
+ \value Vector3D a QVector3D
+ \value Vector4D a QVector4D
+
+ \value UserType Base value for user-defined types.
+
+ \omitvalue CString
+ \omitvalue ColorGroup
+ \omitvalue IconSet
+ \omitvalue LastGuiType
+ \omitvalue LastCoreType
+ \omitvalue LastType
+*/
+
+/*!
+ \fn QVariant::QVariant()
+
+ Constructs an invalid variant.
+*/
+
+
+/*!
+ \fn QVariant::QVariant(int typeOrUserType, const void *copy)
+
+ Constructs variant of type \a typeOrUserType, and initializes with
+ \a copy if \a copy is not 0.
+
+ Note that you have to pass the address of the variable you want stored.
+
+ Usually, you never have to use this constructor, use QVariant::fromValue()
+ instead to construct variants from the pointer types represented by
+ \c QMetaType::VoidStar, \c QMetaType::QObjectStar and
+ \c QMetaType::QWidgetStar.
+
+ \sa QVariant::fromValue(), Type
+*/
+
+/*!
+ \fn QVariant::QVariant(Type type)
+
+ Constructs a null variant of type \a type.
+*/
+
+
+
+/*!
+ \fn QVariant::create(int type, const void *copy)
+
+ \internal
+
+ Constructs a variant private of type \a type, and initializes with \a copy if
+ \a copy is not 0.
+*/
+
+void QVariant::create(int type, const void *copy)
+{
+ d.type = type;
+ handler->construct(&d, copy);
+}
+
+/*!
+ \fn QVariant::~QVariant()
+
+ Destroys the QVariant and the contained object.
+
+ Note that subclasses that reimplement clear() should reimplement
+ the destructor to call clear(). This destructor calls clear(), but
+ because it is the destructor, QVariant::clear() is called rather
+ than a subclass's clear().
+*/
+
+QVariant::~QVariant()
+{
+ if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type > Char && d.type < UserType))
+ handler->clear(&d);
+}
+
+/*!
+ \fn QVariant::QVariant(const QVariant &p)
+
+ Constructs a copy of the variant, \a p, passed as the argument to
+ this constructor.
+*/
+
+QVariant::QVariant(const QVariant &p)
+ : d(p.d)
+{
+ if (d.is_shared) {
+ d.data.shared->ref.ref();
+ } else if (p.d.type > Char && p.d.type < QVariant::UserType) {
+ handler->construct(&d, p.constData());
+ d.is_null = p.d.is_null;
+ }
+}
+
+#ifndef QT_NO_DATASTREAM
+/*!
+ Reads the variant from the data stream, \a s.
+*/
+QVariant::QVariant(QDataStream &s)
+{
+ d.is_null = true;
+ s >> *this;
+}
+#endif //QT_NO_DATASTREAM
+
+/*!
+ \fn QVariant::QVariant(const QString &val)
+
+ Constructs a new variant with a string value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QLatin1String &val)
+
+ Constructs a new variant with a string value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const char *val)
+
+ Constructs a new variant with a string value of \a val.
+ The variant creates a deep copy of \a val, using the encoding
+ set by QTextCodec::setCodecForCStrings().
+
+ Note that \a val is converted to a QString for storing in the
+ variant and QVariant::type() will return QMetaType::QString for
+ the variant.
+
+ You can disable this operator by defining \c
+ QT_NO_CAST_FROM_ASCII when you compile your applications.
+
+ \sa QTextCodec::setCodecForCStrings()
+*/
+
+#ifndef QT_NO_CAST_FROM_ASCII
+QVariant::QVariant(const char *val)
+{
+ QString s = QString::fromAscii(val);
+ create(String, &s);
+}
+#endif
+
+/*!
+ \fn QVariant::QVariant(const QStringList &val)
+
+ Constructs a new variant with a string list value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QMap<QString, QVariant> &val)
+
+ Constructs a new variant with a map of QVariants, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QHash<QString, QVariant> &val)
+
+ Constructs a new variant with a hash of QVariants, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QDate &val)
+
+ Constructs a new variant with a date value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QTime &val)
+
+ Constructs a new variant with a time value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QDateTime &val)
+
+ Constructs a new variant with a date/time value, \a val.
+*/
+
+/*!
+ \since 4.7
+ \fn QVariant::QVariant(const QEasingCurve &val)
+
+ Constructs a new variant with an easing curve value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QByteArray &val)
+
+ Constructs a new variant with a bytearray value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QBitArray &val)
+
+ Constructs a new variant with a bitarray value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QPoint &val)
+
+ Constructs a new variant with a point value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QPointF &val)
+
+ Constructs a new variant with a point value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QRectF &val)
+
+ Constructs a new variant with a rect value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QLineF &val)
+
+ Constructs a new variant with a line value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QLine &val)
+
+ Constructs a new variant with a line value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QRect &val)
+
+ Constructs a new variant with a rect value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QSize &val)
+
+ Constructs a new variant with a size value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QSizeF &val)
+
+ Constructs a new variant with a size value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(const QUrl &val)
+
+ Constructs a new variant with a url value of \a val.
+ */
+
+/*!
+ \fn QVariant::QVariant(int val)
+
+ Constructs a new variant with an integer value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(uint val)
+
+ Constructs a new variant with an unsigned integer value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(qlonglong val)
+
+ Constructs a new variant with a long long integer value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(qulonglong val)
+
+ Constructs a new variant with an unsigned long long integer value, \a val.
+*/
+
+
+/*!
+ \fn QVariant::QVariant(bool val)
+
+ Constructs a new variant with a boolean value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(double val)
+
+ Constructs a new variant with a floating point value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(float val)
+
+ Constructs a new variant with a floating point value, \a val.
+ \since 4.6
+*/
+
+/*!
+ \fn QVariant::QVariant(const QList<QVariant> &val)
+
+ Constructs a new variant with a list value, \a val.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QChar &c)
+
+ Constructs a new variant with a char value, \a c.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QLocale &l)
+
+ Constructs a new variant with a locale value, \a l.
+*/
+
+/*!
+ \fn QVariant::QVariant(const QRegExp &regExp)
+
+ Constructs a new variant with the regexp value \a regExp.
+*/
+
+/*! \since 4.2
+ \fn QVariant::QVariant(Qt::GlobalColor color)
+
+ Constructs a new variant of type QVariant::Color and initializes
+ it with \a color.
+
+ This is a convenience constructor that allows \c{QVariant(Qt::blue);}
+ to create a valid QVariant storing a QColor.
+
+ Note: This constructor will assert if the application does not link
+ to the Qt GUI library.
+ */
+
+QVariant::QVariant(Type type)
+{ create(type, 0); }
+QVariant::QVariant(int typeOrUserType, const void *copy)
+{ create(typeOrUserType, copy); d.is_null = false; }
+
+/*! \internal
+ flags is true if it is a pointer type
+ */
+QVariant::QVariant(int typeOrUserType, const void *copy, uint flags)
+{
+ if (flags) { //type is a pointer type
+ d.type = typeOrUserType;
+ d.data.ptr = *reinterpret_cast<void *const*>(copy);
+ d.is_null = false;
+ } else {
+ create(typeOrUserType, copy);
+ d.is_null = false;
+ }
+}
+
+QVariant::QVariant(int val)
+{ d.is_null = false; d.type = Int; d.data.i = val; }
+QVariant::QVariant(uint val)
+{ d.is_null = false; d.type = UInt; d.data.u = val; }
+QVariant::QVariant(qlonglong val)
+{ d.is_null = false; d.type = LongLong; d.data.ll = val; }
+QVariant::QVariant(qulonglong val)
+{ d.is_null = false; d.type = ULongLong; d.data.ull = val; }
+QVariant::QVariant(bool val)
+{ d.is_null = false; d.type = Bool; d.data.b = val; }
+QVariant::QVariant(double val)
+{ d.is_null = false; d.type = Double; d.data.d = val; }
+
+QVariant::QVariant(const QByteArray &val)
+{ d.is_null = false; d.type = ByteArray; v_construct<QByteArray>(&d, val); }
+QVariant::QVariant(const QBitArray &val)
+{ d.is_null = false; d.type = BitArray; v_construct<QBitArray>(&d, val); }
+QVariant::QVariant(const QString &val)
+{ d.is_null = false; d.type = String; v_construct<QString>(&d, val); }
+QVariant::QVariant(const QChar &val)
+{ d.is_null = false; d.type = Char; v_construct<QChar>(&d, val); }
+QVariant::QVariant(const QLatin1String &val)
+{ QString str(val); d.is_null = false; d.type = String; v_construct<QString>(&d, str); }
+QVariant::QVariant(const QStringList &val)
+{ d.is_null = false; d.type = StringList; v_construct<QStringList>(&d, val); }
+
+QVariant::QVariant(const QDate &val)
+{ d.is_null = false; d.type = Date; v_construct<QDate>(&d, val); }
+QVariant::QVariant(const QTime &val)
+{ d.is_null = false; d.type = Time; v_construct<QTime>(&d, val); }
+QVariant::QVariant(const QDateTime &val)
+{ d.is_null = false; d.type = DateTime; v_construct<QDateTime>(&d, val); }
+#ifndef QT_BOOTSTRAPPED
+QVariant::QVariant(const QEasingCurve &val)
+{ d.is_null = false; d.type = EasingCurve; v_construct<QEasingCurve>(&d, val); }
+#endif
+QVariant::QVariant(const QList<QVariant> &list)
+{ d.is_null = false; d.type = List; v_construct<QVariantList>(&d, list); }
+QVariant::QVariant(const QMap<QString, QVariant> &map)
+{ d.is_null = false; d.type = Map; v_construct<QVariantMap>(&d, map); }
+QVariant::QVariant(const QHash<QString, QVariant> &hash)
+{ d.is_null = false; d.type = Hash; v_construct<QVariantHash>(&d, hash); }
+#ifndef QT_NO_GEOM_VARIANT
+QVariant::QVariant(const QPoint &pt) { d.is_null = false; d.type = Point; v_construct<QPoint>(&d, pt); }
+QVariant::QVariant(const QPointF &pt) { d.is_null = false; d.type = PointF; v_construct<QPointF>(&d, pt); }
+QVariant::QVariant(const QRectF &r) { d.is_null = false; d.type = RectF; v_construct<QRectF>(&d, r); }
+QVariant::QVariant(const QLineF &l) { d.is_null = false; d.type = LineF; v_construct<QLineF>(&d, l); }
+QVariant::QVariant(const QLine &l) { d.is_null = false; d.type = Line; v_construct<QLine>(&d, l); }
+QVariant::QVariant(const QRect &r) { d.is_null = false; d.type = Rect; v_construct<QRect>(&d, r); }
+QVariant::QVariant(const QSize &s) { d.is_null = false; d.type = Size; v_construct<QSize>(&d, s); }
+QVariant::QVariant(const QSizeF &s) { d.is_null = false; d.type = SizeF; v_construct<QSizeF>(&d, s); }
+#endif
+QVariant::QVariant(const QUrl &u) { d.is_null = false; d.type = Url; v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QLocale &l) { d.is_null = false; d.type = Locale; v_construct<QLocale>(&d, l); }
+#ifndef QT_NO_REGEXP
+QVariant::QVariant(const QRegExp &regExp) { d.is_null = false; d.type = RegExp; v_construct<QRegExp>(&d, regExp); }
+#endif
+QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); }
+
+/*!
+ Returns the storage type of the value stored in the variant.
+ Although this function is declared as returning QVariant::Type,
+ the return value should be interpreted as QMetaType::Type. In
+ particular, QVariant::UserType is returned here only if the value
+ is equal or greater than QMetaType::User.
+
+ Note that return values in the ranges QVariant::Char through
+ QVariant::RegExp and QVariant::Font through QVariant::Transform
+ correspond to the values in the ranges QMetaType::QChar through
+ QMetaType::QRegExp and QMetaType::QFont through QMetaType::QQuaternion.
+
+ Pay particular attention when working with char and QChar
+ variants. Note that there is no QVariant constructor specifically
+ for type char, but there is one for QChar. For a variant of type
+ QChar, this function returns QVariant::Char, which is the same as
+ QMetaType::QChar, but for a variant of type \c char, this function
+ returns QMetaType::Char, which is \e not the same as
+ QVariant::Char.
+
+ Also note that the types \c void*, \c long, \c short, \c unsigned
+ \c long, \c unsigned \c short, \c unsigned \c char, \c float, \c
+ QObject*, and \c QWidget* are represented in QMetaType::Type but
+ not in QVariant::Type, and they can be returned by this function.
+ However, they are considered to be user defined types when tested
+ against QVariant::Type.
+
+ To test whether an instance of QVariant contains a data type that
+ is compatible with the data type you are interested in, use
+ canConvert().
+*/
+
+QVariant::Type QVariant::type() const
+{
+ return d.type >= QMetaType::User ? UserType : static_cast<Type>(d.type);
+}
+
+/*!
+ Returns the storage type of the value stored in the variant. For
+ non-user types, this is the same as type().
+
+ \sa type()
+*/
+
+int QVariant::userType() const
+{
+ return d.type;
+}
+
+/*!
+ Assigns the value of the variant \a variant to this variant.
+*/
+QVariant& QVariant::operator=(const QVariant &variant)
+{
+ if (this == &variant)
+ return *this;
+
+ clear();
+ if (variant.d.is_shared) {
+ variant.d.data.shared->ref.ref();
+ d = variant.d;
+ } else if (variant.d.type > Char && variant.d.type < UserType) {
+ d.type = variant.d.type;
+ handler->construct(&d, variant.constData());
+ d.is_null = variant.d.is_null;
+ } else {
+ d = variant.d;
+ }
+
+ return *this;
+}
+
+/*!
+ \fn void QVariant::swap(QVariant &other)
+ \since 4.8
+
+ Swaps variant \a other with this variant. This operation is very
+ fast and never fails.
+*/
+
+/*!
+ \fn void QVariant::detach()
+
+ \internal
+*/
+
+void QVariant::detach()
+{
+ if (!d.is_shared || d.data.shared->ref == 1)
+ return;
+
+ Private dd;
+ dd.type = d.type;
+ handler->construct(&dd, constData());
+ if (!d.data.shared->ref.deref())
+ handler->clear(&d);
+ d.data.shared = dd.data.shared;
+}
+
+/*!
+ \fn bool QVariant::isDetached() const
+
+ \internal
+*/
+
+// ### Qt 5: change typeName()(and froends= to return a QString. Suggestion from Harald.
+/*!
+ Returns the name of the type stored in the variant. The returned
+ strings describe the C++ datatype used to store the data: for
+ example, "QFont", "QString", or "QVariantList". An Invalid
+ variant returns 0.
+*/
+const char *QVariant::typeName() const
+{
+ return typeToName(Type(d.type));
+}
+
+/*!
+ Convert this variant to type Invalid and free up any resources
+ used.
+*/
+void QVariant::clear()
+{
+ if ((d.is_shared && !d.data.shared->ref.deref()) || (!d.is_shared && d.type < UserType && d.type > Char))
+ handler->clear(&d);
+ d.type = Invalid;
+ d.is_null = true;
+ d.is_shared = false;
+}
+
+/*!
+ Converts the enum representation of the storage type, \a typ, to
+ its string representation.
+
+ Returns a null pointer if the type is QVariant::Invalid or doesn't exist.
+*/
+const char *QVariant::typeToName(Type typ)
+{
+ if (typ == Invalid)
+ return 0;
+ if (typ == UserType)
+ return "UserType";
+
+ return QMetaType::typeName(typ);
+}
+
+
+/*!
+ Converts the string representation of the storage type given in \a
+ name, to its enum representation.
+
+ If the string representation cannot be converted to any enum
+ representation, the variant is set to \c Invalid.
+*/
+QVariant::Type QVariant::nameToType(const char *name)
+{
+ if (!name || !*name)
+ return Invalid;
+ if (strcmp(name, "Q3CString") == 0)
+ return ByteArray;
+ if (strcmp(name, "Q_LLONG") == 0)
+ return LongLong;
+ if (strcmp(name, "Q_ULLONG") == 0)
+ return ULongLong;
+ if (strcmp(name, "QIconSet") == 0)
+ return Icon;
+ if (strcmp(name, "UserType") == 0)
+ return UserType;
+
+ int metaType = QMetaType::type(name);
+ return metaType <= int(LastGuiType) ? QVariant::Type(metaType) : UserType;
+}
+
+#ifndef QT_NO_DATASTREAM
+enum { MapFromThreeCount = 36 };
+static const ushort map_from_three[MapFromThreeCount] =
+{
+ QVariant::Invalid,
+ QVariant::Map,
+ QVariant::List,
+ QVariant::String,
+ QVariant::StringList,
+ QVariant::Font,
+ QVariant::Pixmap,
+ QVariant::Brush,
+ QVariant::Rect,
+ QVariant::Size,
+ QVariant::Color,
+ QVariant::Palette,
+ 63, // ColorGroup
+ QVariant::Icon,
+ QVariant::Point,
+ QVariant::Image,
+ QVariant::Int,
+ QVariant::UInt,
+ QVariant::Bool,
+ QVariant::Double,
+ QVariant::ByteArray,
+ QVariant::Polygon,
+ QVariant::Region,
+ QVariant::Bitmap,
+ QVariant::Cursor,
+ QVariant::SizePolicy,
+ QVariant::Date,
+ QVariant::Time,
+ QVariant::DateTime,
+ QVariant::ByteArray,
+ QVariant::BitArray,
+ QVariant::KeySequence,
+ QVariant::Pen,
+ QVariant::LongLong,
+ QVariant::ULongLong,
+ QVariant::EasingCurve
+};
+
+/*!
+ Internal function for loading a variant from stream \a s. Use the
+ stream operators instead.
+
+ \internal
+*/
+void QVariant::load(QDataStream &s)
+{
+ clear();
+
+ quint32 u;
+ s >> u;
+ if (s.version() < QDataStream::Qt_4_0) {
+ if (u >= MapFromThreeCount)
+ return;
+ u = map_from_three[u];
+ }
+ qint8 is_null = false;
+ if (s.version() >= QDataStream::Qt_4_2)
+ s >> is_null;
+ if (u == QVariant::UserType) {
+ QByteArray name;
+ s >> name;
+ u = QMetaType::type(name);
+ if (!u) {
+ s.setStatus(QDataStream::ReadCorruptData);
+ return;
+ }
+ }
+ create(static_cast<int>(u), 0);
+ d.is_null = is_null;
+
+ if (!isValid()) {
+ // Since we wrote something, we should read something
+ QString x;
+ s >> x;
+ d.is_null = true;
+ return;
+ }
+
+ // const cast is safe since we operate on a newly constructed variant
+ if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) {
+ s.setStatus(QDataStream::ReadCorruptData);
+ qWarning("QVariant::load: unable to load type %d.", d.type);
+ }
+}
+
+/*!
+ Internal function for saving a variant to the stream \a s. Use the
+ stream operators instead.
+
+ \internal
+*/
+void QVariant::save(QDataStream &s) const
+{
+ quint32 tp = type();
+ if (s.version() < QDataStream::Qt_4_0) {
+ int i;
+ for (i = MapFromThreeCount - 1; i >= 0; i--) {
+ if (map_from_three[i] == tp) {
+ tp = i;
+ break;
+ }
+ }
+ if (i == -1) {
+ s << QVariant();
+ return;
+ }
+ }
+ s << tp;
+ if (s.version() >= QDataStream::Qt_4_2)
+ s << qint8(d.is_null);
+ if (tp == QVariant::UserType) {
+ s << QMetaType::typeName(userType());
+ }
+
+ if (!isValid()) {
+ s << QString();
+ return;
+ }
+
+ if (!QMetaType::save(s, d.type, constData())) {
+ Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
+ qWarning("QVariant::save: unable to save type %d.", d.type);
+ }
+}
+
+/*!
+ \since 4.4
+
+ Reads a variant \a p from the stream \a s.
+
+ \sa \link datastreamformat.html Format of the QDataStream
+ operators \endlink
+*/
+QDataStream& operator>>(QDataStream &s, QVariant &p)
+{
+ p.load(s);
+ return s;
+}
+
+/*!
+ Writes a variant \a p to the stream \a s.
+
+ \sa \link datastreamformat.html Format of the QDataStream
+ operators \endlink
+*/
+QDataStream& operator<<(QDataStream &s, const QVariant &p)
+{
+ p.save(s);
+ return s;
+}
+
+/*!
+ Reads a variant type \a p in enum representation from the stream \a s.
+*/
+QDataStream& operator>>(QDataStream &s, QVariant::Type &p)
+{
+ quint32 u;
+ s >> u;
+ p = (QVariant::Type)u;
+
+ return s;
+}
+
+/*!
+ Writes a variant type \a p to the stream \a s.
+*/
+QDataStream& operator<<(QDataStream &s, const QVariant::Type p)
+{
+ s << static_cast<quint32>(p);
+
+ return s;
+}
+
+#endif //QT_NO_DATASTREAM
+
+/*!
+ \fn bool QVariant::isValid() const
+
+ Returns true if the storage type of this variant is not
+ QVariant::Invalid; otherwise returns false.
+*/
+
+template <typename T>
+inline T qVariantToHelper(const QVariant::Private &d, QVariant::Type t,
+ const QVariant::Handler *handler, T * = 0)
+{
+ if (d.type == t)
+ return *v_cast<T>(&d);
+
+ T ret;
+ handler->convert(&d, t, &ret, 0);
+ return ret;
+}
+
+/*!
+ \fn QStringList QVariant::toStringList() const
+
+ Returns the variant as a QStringList if the variant has type()
+ StringList, \l String, or \l List of a type that can be converted
+ to QString; otherwise returns an empty list.
+
+ \sa canConvert(), convert()
+*/
+QStringList QVariant::toStringList() const
+{
+ return qVariantToHelper<QStringList>(d, StringList, handler);
+}
+
+/*!
+ Returns the variant as a QString if the variant has type() \l
+ String, \l Bool, \l ByteArray, \l Char, \l Date, \l DateTime, \l
+ Double, \l Int, \l LongLong, \l StringList, \l Time, \l UInt, or
+ \l ULongLong; otherwise returns an empty string.
+
+ \sa canConvert(), convert()
+*/
+QString QVariant::toString() const
+{
+ return qVariantToHelper<QString>(d, String, handler);
+}
+
+/*!
+ Returns the variant as a QMap<QString, QVariant> if the variant
+ has type() \l Map; otherwise returns an empty map.
+
+ \sa canConvert(), convert()
+*/
+QVariantMap QVariant::toMap() const
+{
+ return qVariantToHelper<QVariantMap>(d, Map, handler);
+}
+
+/*!
+ Returns the variant as a QHash<QString, QVariant> if the variant
+ has type() \l Hash; otherwise returns an empty map.
+
+ \sa canConvert(), convert()
+*/
+QVariantHash QVariant::toHash() const
+{
+ return qVariantToHelper<QVariantHash>(d, Hash, handler);
+}
+
+/*!
+ \fn QDate QVariant::toDate() const
+
+ Returns the variant as a QDate if the variant has type() \l Date,
+ \l DateTime, or \l String; otherwise returns an invalid date.
+
+ If the type() is \l String, an invalid date will be returned if the
+ string cannot be parsed as a Qt::ISODate format date.
+
+ \sa canConvert(), convert()
+*/
+QDate QVariant::toDate() const
+{
+ return qVariantToHelper<QDate>(d, Date, handler);
+}
+
+/*!
+ \fn QTime QVariant::toTime() const
+
+ Returns the variant as a QTime if the variant has type() \l Time,
+ \l DateTime, or \l String; otherwise returns an invalid time.
+
+ If the type() is \l String, an invalid time will be returned if
+ the string cannot be parsed as a Qt::ISODate format time.
+
+ \sa canConvert(), convert()
+*/
+QTime QVariant::toTime() const
+{
+ return qVariantToHelper<QTime>(d, Time, handler);
+}
+
+/*!
+ \fn QDateTime QVariant::toDateTime() const
+
+ Returns the variant as a QDateTime if the variant has type() \l
+ DateTime, \l Date, or \l String; otherwise returns an invalid
+ date/time.
+
+ If the type() is \l String, an invalid date/time will be returned
+ if the string cannot be parsed as a Qt::ISODate format date/time.
+
+ \sa canConvert(), convert()
+*/
+QDateTime QVariant::toDateTime() const
+{
+ return qVariantToHelper<QDateTime>(d, DateTime, handler);
+}
+
+/*!
+ \since 4.7
+ \fn QEasingCurve QVariant::toEasingCurve() const
+
+ Returns the variant as a QEasingCurve if the variant has type() \l
+ EasingCurve; otherwise returns a default easing curve.
+
+ \sa canConvert(), convert()
+*/
+#ifndef QT_BOOTSTRAPPED
+QEasingCurve QVariant::toEasingCurve() const
+{
+ return qVariantToHelper<QEasingCurve>(d, EasingCurve, handler);
+}
+#endif
+
+/*!
+ \fn QByteArray QVariant::toByteArray() const
+
+ Returns the variant as a QByteArray if the variant has type() \l
+ ByteArray or \l String (converted using QString::fromAscii());
+ otherwise returns an empty byte array.
+
+ \sa canConvert(), convert()
+*/
+QByteArray QVariant::toByteArray() const
+{
+ return qVariantToHelper<QByteArray>(d, ByteArray, handler);
+}
+
+#ifndef QT_NO_GEOM_VARIANT
+/*!
+ \fn QPoint QVariant::toPoint() const
+
+ Returns the variant as a QPoint if the variant has type()
+ \l Point or \l PointF; otherwise returns a null QPoint.
+
+ \sa canConvert(), convert()
+*/
+QPoint QVariant::toPoint() const
+{
+ return qVariantToHelper<QPoint>(d, Point, handler);
+}
+
+/*!
+ \fn QRect QVariant::toRect() const
+
+ Returns the variant as a QRect if the variant has type() \l Rect;
+ otherwise returns an invalid QRect.
+
+ \sa canConvert(), convert()
+*/
+QRect QVariant::toRect() const
+{
+ return qVariantToHelper<QRect>(d, Rect, handler);
+}
+
+/*!
+ \fn QSize QVariant::toSize() const
+
+ Returns the variant as a QSize if the variant has type() \l Size;
+ otherwise returns an invalid QSize.
+
+ \sa canConvert(), convert()
+*/
+QSize QVariant::toSize() const
+{
+ return qVariantToHelper<QSize>(d, Size, handler);
+}
+
+/*!
+ \fn QSizeF QVariant::toSizeF() const
+
+ Returns the variant as a QSizeF if the variant has type() \l
+ SizeF; otherwise returns an invalid QSizeF.
+
+ \sa canConvert(), convert()
+*/
+QSizeF QVariant::toSizeF() const
+{
+ return qVariantToHelper<QSizeF>(d, SizeF, handler);
+}
+
+/*!
+ \fn QRectF QVariant::toRectF() const
+
+ Returns the variant as a QRectF if the variant has type() \l Rect
+ or \l RectF; otherwise returns an invalid QRectF.
+
+ \sa canConvert(), convert()
+*/
+QRectF QVariant::toRectF() const
+{
+ return qVariantToHelper<QRectF>(d, RectF, handler);
+}
+
+/*!
+ \fn QLineF QVariant::toLineF() const
+
+ Returns the variant as a QLineF if the variant has type() \l
+ LineF; otherwise returns an invalid QLineF.
+
+ \sa canConvert(), convert()
+*/
+QLineF QVariant::toLineF() const
+{
+ return qVariantToHelper<QLineF>(d, LineF, handler);
+}
+
+/*!
+ \fn QLine QVariant::toLine() const
+
+ Returns the variant as a QLine if the variant has type() \l Line;
+ otherwise returns an invalid QLine.
+
+ \sa canConvert(), convert()
+*/
+QLine QVariant::toLine() const
+{
+ return qVariantToHelper<QLine>(d, Line, handler);
+}
+
+/*!
+ \fn QPointF QVariant::toPointF() const
+
+ Returns the variant as a QPointF if the variant has type() \l
+ Point or \l PointF; otherwise returns a null QPointF.
+
+ \sa canConvert(), convert()
+*/
+QPointF QVariant::toPointF() const
+{
+ return qVariantToHelper<QPointF>(d, PointF, handler);
+}
+
+#endif // QT_NO_GEOM_VARIANT
+
+/*!
+ \fn QUrl QVariant::toUrl() const
+
+ Returns the variant as a QUrl if the variant has type()
+ \l Url; otherwise returns an invalid QUrl.
+
+ \sa canConvert(), convert()
+*/
+QUrl QVariant::toUrl() const
+{
+ return qVariantToHelper<QUrl>(d, Url, handler);
+}
+
+/*!
+ \fn QLocale QVariant::toLocale() const
+
+ Returns the variant as a QLocale if the variant has type()
+ \l Locale; otherwise returns an invalid QLocale.
+
+ \sa canConvert(), convert()
+*/
+QLocale QVariant::toLocale() const
+{
+ return qVariantToHelper<QLocale>(d, Locale, handler);
+}
+
+/*!
+ \fn QRegExp QVariant::toRegExp() const
+ \since 4.1
+
+ Returns the variant as a QRegExp if the variant has type() \l
+ RegExp; otherwise returns an empty QRegExp.
+
+ \sa canConvert(), convert()
+*/
+#ifndef QT_NO_REGEXP
+QRegExp QVariant::toRegExp() const
+{
+ return qVariantToHelper<QRegExp>(d, RegExp, handler);
+}
+#endif
+
+/*!
+ \fn QChar QVariant::toChar() const
+
+ Returns the variant as a QChar if the variant has type() \l Char,
+ \l Int, or \l UInt; otherwise returns an invalid QChar.
+
+ \sa canConvert(), convert()
+*/
+QChar QVariant::toChar() const
+{
+ return qVariantToHelper<QChar>(d, Char, handler);
+}
+
+/*!
+ Returns the variant as a QBitArray if the variant has type()
+ \l BitArray; otherwise returns an empty bit array.
+
+ \sa canConvert(), convert()
+*/
+QBitArray QVariant::toBitArray() const
+{
+ return qVariantToHelper<QBitArray>(d, BitArray, handler);
+}
+
+template <typename T>
+inline T qNumVariantToHelper(const QVariant::Private &d,
+ const QVariant::Handler *handler, bool *ok, const T& val)
+{
+ uint t = qMetaTypeId<T>();
+ if (ok)
+ *ok = true;
+ if (d.type == t)
+ return val;
+
+ T ret;
+ if (!handler->convert(&d, QVariant::Type(t), &ret, ok) && ok)
+ *ok = false;
+ return ret;
+}
+
+/*!
+ Returns the variant as an int if the variant has type() \l Int,
+ \l Bool, \l ByteArray, \l Char, \l Double, \l LongLong, \l
+ String, \l UInt, or \l ULongLong; otherwise returns 0.
+
+ If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
+ converted to an int; otherwise \c{*}\a{ok} is set to false.
+
+ \bold{Warning:} If the value is convertible to a \l LongLong but is too
+ large to be represented in an int, the resulting arithmetic overflow will
+ not be reflected in \a ok. A simple workaround is to use QString::toInt().
+ Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code.
+
+ \sa canConvert(), convert()
+*/
+int QVariant::toInt(bool *ok) const
+{
+ return qNumVariantToHelper<int>(d, handler, ok, d.data.i);
+}
+
+/*!
+ Returns the variant as an unsigned int if the variant has type()
+ \l UInt, \l Bool, \l ByteArray, \l Char, \l Double, \l Int, \l
+ LongLong, \l String, or \l ULongLong; otherwise returns 0.
+
+ If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
+ converted to an unsigned int; otherwise \c{*}\a{ok} is set to false.
+
+ \bold{Warning:} If the value is convertible to a \l ULongLong but is too
+ large to be represented in an unsigned int, the resulting arithmetic overflow will
+ not be reflected in \a ok. A simple workaround is to use QString::toUInt().
+ Fixing this bug has been postponed to Qt 5 in order to avoid breaking existing code.
+
+ \sa canConvert(), convert()
+*/
+uint QVariant::toUInt(bool *ok) const
+{
+ return qNumVariantToHelper<uint>(d, handler, ok, d.data.u);
+}
+
+/*!
+ Returns the variant as a long long int if the variant has type()
+ \l LongLong, \l Bool, \l ByteArray, \l Char, \l Double, \l Int,
+ \l String, \l UInt, or \l ULongLong; otherwise returns 0.
+
+ If \a ok is non-null: \c{*}\c{ok} is set to true if the value could be
+ converted to an int; otherwise \c{*}\c{ok} is set to false.
+
+ \sa canConvert(), convert()
+*/
+qlonglong QVariant::toLongLong(bool *ok) const
+{
+ return qNumVariantToHelper<qlonglong>(d, handler, ok, d.data.ll);
+}
+
+/*!
+ Returns the variant as as an unsigned long long int if the
+ variant has type() \l ULongLong, \l Bool, \l ByteArray, \l Char,
+ \l Double, \l Int, \l LongLong, \l String, or \l UInt; otherwise
+ returns 0.
+
+ If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
+ converted to an int; otherwise \c{*}\a{ok} is set to false.
+
+ \sa canConvert(), convert()
+*/
+qulonglong QVariant::toULongLong(bool *ok) const
+{
+ return qNumVariantToHelper<qulonglong>(d, handler, ok, d.data.ull);
+}
+
+/*!
+ Returns the variant as a bool if the variant has type() Bool.
+
+ Returns true if the variant has type() \l Bool, \l Char, \l Double,
+ \l Int, \l LongLong, \l UInt, or \l ULongLong and the value is
+ non-zero, or if the variant has type \l String or \l ByteArray and
+ its lower-case content is not empty, "0" or "false"; otherwise
+ returns false.
+
+ \sa canConvert(), convert()
+*/
+bool QVariant::toBool() const
+{
+ if (d.type == Bool)
+ return d.data.b;
+
+ bool res = false;
+ handler->convert(&d, Bool, &res, 0);
+
+ return res;
+}
+
+/*!
+ Returns the variant as a double if the variant has type() \l
+ Double, \l QMetaType::Float, \l Bool, \l ByteArray, \l Int, \l LongLong, \l String, \l
+ UInt, or \l ULongLong; otherwise returns 0.0.
+
+ If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
+ converted to a double; otherwise \c{*}\a{ok} is set to false.
+
+ \sa canConvert(), convert()
+*/
+double QVariant::toDouble(bool *ok) const
+{
+ return qNumVariantToHelper<double>(d, handler, ok, d.data.d);
+}
+
+/*!
+ Returns the variant as a float if the variant has type() \l
+ Double, \l QMetaType::Float, \l Bool, \l ByteArray, \l Int, \l LongLong, \l String, \l
+ UInt, or \l ULongLong; otherwise returns 0.0.
+
+ \since 4.6
+
+ If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
+ converted to a double; otherwise \c{*}\a{ok} is set to false.
+
+ \sa canConvert(), convert()
+*/
+float QVariant::toFloat(bool *ok) const
+{
+ return qNumVariantToHelper<float>(d, handler, ok, d.data.f);
+}
+
+/*!
+ Returns the variant as a qreal if the variant has type() \l
+ Double, \l QMetaType::Float, \l Bool, \l ByteArray, \l Int, \l LongLong, \l String, \l
+ UInt, or \l ULongLong; otherwise returns 0.0.
+
+ \since 4.6
+
+ If \a ok is non-null: \c{*}\a{ok} is set to true if the value could be
+ converted to a double; otherwise \c{*}\a{ok} is set to false.
+
+ \sa canConvert(), convert()
+*/
+qreal QVariant::toReal(bool *ok) const
+{
+ return qNumVariantToHelper<qreal>(d, handler, ok, d.data.real);
+}
+
+/*!
+ Returns the variant as a QVariantList if the variant has type()
+ \l List or \l StringList; otherwise returns an empty list.
+
+ \sa canConvert(), convert()
+*/
+QVariantList QVariant::toList() const
+{
+ return qVariantToHelper<QVariantList>(d, List, handler);
+}
+
+/*! \fn QVariant::canCast(Type t) const
+ Use canConvert() instead.
+*/
+
+/*! \fn QVariant::cast(Type t)
+ Use convert() instead.
+*/
+
+
+static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
+{
+/*Invalid*/ 0,
+
+/*Bool*/ 1 << QVariant::Double | 1 << QVariant::Int | 1 << QVariant::UInt
+ | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::ByteArray
+ | 1 << QVariant::String | 1 << QVariant::Char,
+
+/*Int*/ 1 << QVariant::UInt | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::LongLong | 1 << QVariant::ULongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*UInt*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::LongLong | 1 << QVariant::ULongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*LLong*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::ULongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*ULlong*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::Double
+ | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::LongLong
+ | 1 << QVariant::Char | 1 << QVariant::ByteArray,
+
+/*double*/ 1 << QVariant::Int | 1 << QVariant::String | 1 << QVariant::ULongLong
+ | 1 << QVariant::Bool | 1 << QVariant::UInt | 1 << QVariant::LongLong
+ | 1 << QVariant::ByteArray,
+
+/*QChar*/ 1 << QVariant::Int | 1 << QVariant::UInt | 1 << QVariant::LongLong
+ | 1 << QVariant::ULongLong,
+
+/*QMap*/ 0,
+
+/*QList*/ 1 << QVariant::StringList,
+
+/*QString*/ 1 << QVariant::StringList | 1 << QVariant::ByteArray | 1 << QVariant::Int
+ | 1 << QVariant::UInt | 1 << QVariant::Bool | 1 << QVariant::Double
+ | 1 << QVariant::Date | 1 << QVariant::Time | 1 << QVariant::DateTime
+ | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char
+ | 1 << QVariant::Url,
+
+/*QStringList*/ 1 << QVariant::List | 1 << QVariant::String,
+
+/*QByteArray*/ 1 << QVariant::String | 1 << QVariant::Int | 1 << QVariant::UInt | 1 << QVariant::Bool
+ | 1 << QVariant::Double | 1 << QVariant::LongLong | 1 << QVariant::ULongLong,
+
+/*QBitArray*/ 0,
+
+/*QDate*/ 1 << QVariant::String | 1 << QVariant::DateTime,
+
+/*QTime*/ 1 << QVariant::String | 1 << QVariant::DateTime,
+
+/*QDateTime*/ 1 << QVariant::String | 1 << QVariant::Date,
+
+/*QUrl*/ 1 << QVariant::String,
+
+/*QLocale*/ 0,
+
+/*QRect*/ 1 << QVariant::RectF,
+
+/*QRectF*/ 1 << QVariant::Rect,
+
+/*QSize*/ 1 << QVariant::SizeF,
+
+/*QSizeF*/ 1 << QVariant::Size,
+
+/*QLine*/ 1 << QVariant::LineF,
+
+/*QLineF*/ 1 << QVariant::Line,
+
+/*QPoint*/ 1 << QVariant::PointF,
+
+/*QPointF*/ 1 << QVariant::Point,
+
+/*QRegExp*/ 0,
+
+/*QHash*/ 0,
+
+/*QEasingCurve*/ 0
+};
+
+/*!
+ Returns true if the variant's type can be cast to the requested
+ type, \a t. Such casting is done automatically when calling the
+ toInt(), toBool(), ... methods.
+
+ The following casts are done automatically:
+
+ \table
+ \header \o Type \o Automatically Cast To
+ \row \o \l Bool \o \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l ByteArray \o \l Double, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l Char \o \l Bool, \l Int, \l UInt, \l LongLong, \l ULongLong
+ \row \o \l Color \o \l String
+ \row \o \l Date \o \l DateTime, \l String
+ \row \o \l DateTime \o \l Date, \l String, \l Time
+ \row \o \l Double \o \l Bool, \l Int, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l Font \o \l String
+ \row \o \l Int \o \l Bool, \l Char, \l Double, \l LongLong, \l String, \l UInt, \l ULongLong
+ \row \o \l KeySequence \o \l Int, \l String
+ \row \o \l List \o \l StringList (if the list's items can be converted to strings)
+ \row \o \l LongLong \o \l Bool, \l ByteArray, \l Char, \l Double, \l Int, \l String, \l UInt, \l ULongLong
+ \row \o \l Point \o PointF
+ \row \o \l Rect \o RectF
+ \row \o \l String \o \l Bool, \l ByteArray, \l Char, \l Color, \l Date, \l DateTime, \l Double,
+ \l Font, \l Int, \l KeySequence, \l LongLong, \l StringList, \l Time, \l UInt,
+ \l ULongLong
+ \row \o \l StringList \o \l List, \l String (if the list contains exactly one item)
+ \row \o \l Time \o \l String
+ \row \o \l UInt \o \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l ULongLong
+ \row \o \l ULongLong \o \l Bool, \l Char, \l Double, \l Int, \l LongLong, \l String, \l UInt
+ \endtable
+
+ \sa convert()
+*/
+bool QVariant::canConvert(Type t) const
+{
+ //we can treat floats as double
+ //the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
+ //which can't be handled by qCanConvertMatrix
+ //In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
+ const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
+ if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
+
+ if (currentType == uint(t))
+ return true;
+
+ if (currentType > QVariant::LastCoreType || t > QVariant::LastCoreType) {
+ switch (uint(t)) {
+ case QVariant::Int:
+ return currentType == QVariant::KeySequence
+ || currentType == QMetaType::ULong
+ || currentType == QMetaType::Long
+ || currentType == QMetaType::UShort
+ || currentType == QMetaType::UChar
+ || currentType == QMetaType::Char
+ || currentType == QMetaType::Short;
+ case QVariant::Image:
+ return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
+ case QVariant::Pixmap:
+ return currentType == QVariant::Image || currentType == QVariant::Bitmap
+ || currentType == QVariant::Brush;
+ case QVariant::Bitmap:
+ return currentType == QVariant::Pixmap || currentType == QVariant::Image;
+ case QVariant::ByteArray:
+ return currentType == QVariant::Color;
+ case QVariant::String:
+ return currentType == QVariant::KeySequence || currentType == QVariant::Font
+ || currentType == QVariant::Color;
+ case QVariant::KeySequence:
+ return currentType == QVariant::String || currentType == QVariant::Int;
+ case QVariant::Font:
+ return currentType == QVariant::String;
+ case QVariant::Color:
+ return currentType == QVariant::String || currentType == QVariant::ByteArray
+ || currentType == QVariant::Brush;
+ case QVariant::Brush:
+ return currentType == QVariant::Color || currentType == QVariant::Pixmap;
+ case QMetaType::Long:
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ case QMetaType::ULong:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int;
+ default:
+ return false;
+ }
+ }
+
+ if(t == String && currentType == StringList)
+ return v_cast<QStringList>(&d)->count() == 1;
+ else
+ return qCanConvertMatrix[t] & (1 << currentType);
+}
+
+/*!
+ Casts the variant to the requested type, \a t. If the cast cannot be
+ done, the variant is cleared. Returns true if the current type of
+ the variant was successfully cast; otherwise returns false.
+
+ \warning For historical reasons, converting a null QVariant results
+ in a null value of the desired type (e.g., an empty string for
+ QString) and a result of false.
+
+ \sa canConvert(), clear()
+*/
+
+bool QVariant::convert(Type t)
+{
+ if (d.type == uint(t))
+ return true;
+
+ QVariant oldValue = *this;
+
+ clear();
+ if (!oldValue.canConvert(t))
+ return false;
+
+ create(t, 0);
+ if (oldValue.isNull())
+ return false;
+
+ bool isOk = true;
+ if (!handler->convert(&oldValue.d, t, data(), &isOk))
+ isOk = false;
+ d.is_null = !isOk;
+ return isOk;
+}
+
+/*!
+ \fn bool operator==(const QVariant &v1, const QVariant &v2)
+
+ \relates QVariant
+
+ Returns true if \a v1 and \a v2 are equal; otherwise returns false.
+
+ \warning This function doesn't support custom types registered
+ with qRegisterMetaType().
+*/
+/*!
+ \fn bool operator!=(const QVariant &v1, const QVariant &v2)
+
+ \relates QVariant
+
+ Returns false if \a v1 and \a v2 are equal; otherwise returns true.
+
+ \warning This function doesn't support custom types registered
+ with qRegisterMetaType().
+*/
+
+/*! \fn bool QVariant::operator==(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if they are
+ equal; otherwise returns false.
+
+ In the case of custom types, their equalness operators are not called.
+ Instead the values' addresses are compared.
+*/
+
+/*!
+ \fn bool QVariant::operator!=(const QVariant &v) const
+
+ Compares this QVariant with \a v and returns true if they are not
+ equal; otherwise returns false.
+
+ \warning This function doesn't support custom types registered
+ with qRegisterMetaType().
+*/
+
+static bool qIsNumericType(uint tp)
+{
+ return (tp >= QVariant::Bool && tp <= QVariant::Double)
+ || (tp >= QMetaType::Long && tp <= QMetaType::Float);
+}
+
+static bool qIsFloatingPoint(uint tp)
+{
+ return tp == QVariant::Double || tp == QMetaType::Float;
+}
+
+/*! \internal
+ */
+bool QVariant::cmp(const QVariant &v) const
+{
+ QVariant v2 = v;
+ if (d.type != v2.d.type) {
+ if (qIsNumericType(d.type) && qIsNumericType(v.d.type)) {
+ if (qIsFloatingPoint(d.type) || qIsFloatingPoint(v.d.type))
+ return qFuzzyCompare(toReal(), v.toReal());
+ else
+ return toLongLong() == v.toLongLong();
+ }
+ if (!v2.canConvert(Type(d.type)) || !v2.convert(Type(d.type)))
+ return false;
+ }
+ return handler->compare(&d, &v2.d);
+}
+
+/*! \internal
+ */
+
+const void *QVariant::constData() const
+{
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
+}
+
+/*!
+ \fn const void* QVariant::data() const
+
+ \internal
+*/
+
+/*! \internal */
+void* QVariant::data()
+{
+ detach();
+ return const_cast<void *>(constData());
+}
+
+
+#ifdef QT3_SUPPORT
+/*! \internal
+ */
+void *QVariant::castOrDetach(Type t)
+{
+ if (d.type != uint(t)) {
+ if (!convert(t))
+ create(t, 0);
+ } else {
+ detach();
+ }
+ return data();
+}
+#endif
+
+/*!
+ Returns true if this is a NULL variant, false otherwise.
+*/
+bool QVariant::isNull() const
+{
+ return handler->isNull(&d);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QVariant &v)
+{
+#ifndef Q_BROKEN_DEBUG_STREAM
+ dbg.nospace() << "QVariant(" << v.typeName() << ", ";
+ QVariant::handler->debugStream(dbg, v);
+ dbg.nospace() << ')';
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QVariant to QDebug");
+ return dbg;
+ Q_UNUSED(v);
+#endif
+}
+
+QDebug operator<<(QDebug dbg, const QVariant::Type p)
+{
+#ifndef Q_BROKEN_DEBUG_STREAM
+ dbg.nospace() << "QVariant::" << QVariant::typeToName(p);
+ return dbg.space();
+#else
+ qWarning("This compiler doesn't support streaming QVariant::Type to QDebug");
+ return dbg;
+ Q_UNUSED(p);
+#endif
+}
+#endif
+
+/*!
+ \fn int &QVariant::asInt()
+
+ Use toInt() instead.
+*/
+
+/*!
+ \fn uint &QVariant::asUInt()
+
+ Use toUInt() instead.
+*/
+
+/*!
+ \fn qlonglong &QVariant::asLongLong()
+
+ Use toLongLong() instead.
+*/
+
+/*!
+ \fn qulonglong &QVariant::asULongLong()
+
+ Use toULongLong() instead.
+*/
+
+/*!
+ \fn bool &QVariant::asBool()
+
+ Use toBool() instead.
+*/
+
+/*!
+ \fn double &QVariant::asDouble()
+
+ Use toDouble() instead.
+*/
+
+/*!
+ \fn QByteArray &QVariant::asByteArray()
+
+ Use toByteArray() instead.
+*/
+
+/*!
+ \fn QBitArray &QVariant::asBitArray()
+
+ Use toBitArray() instead.
+*/
+
+/*!
+ \fn QString &QVariant::asString()
+
+ Use toString() instead.
+*/
+
+/*!
+ \fn QStringList &QVariant::asStringList()
+
+ Use toStringList() instead.
+*/
+
+/*!
+ \fn QDate &QVariant::asDate()
+
+ Use toDate() instead.
+*/
+
+/*!
+ \fn QTime &QVariant::asTime()
+
+ Use toTime() instead.
+*/
+
+/*!
+ \fn QDateTime &QVariant::asDateTime()
+
+ Use toDateTime() instead.
+*/
+
+/*!
+ \fn QList<QVariant> &QVariant::asList()
+
+ Use toList() instead.
+*/
+
+/*!
+ \fn QMap<QString, QVariant> &QVariant::asMap()
+
+ Use toMap() instead.
+*/
+
+/*!
+ \fn QVariant::QVariant(bool b, int dummy)
+
+ Use the QVariant(bool) constructor instead.
+
+*/
+
+/*!
+ \fn const QByteArray QVariant::toCString() const
+
+ Use toByteArray() instead.
+*/
+
+/*!
+ \fn QByteArray &QVariant::asCString()
+
+ Use toByteArray() instead.
+*/
+
+/*!
+ \fn QPoint &QVariant::asPoint()
+
+ Use toPoint() instead.
+ */
+
+/*!
+ \fn QRect &QVariant::asRect()
+
+ Use toRect() instead.
+ */
+
+/*!
+ \fn QSize &QVariant::asSize()
+
+ Use toSize() instead.
+ */
+
+/*! \fn void QVariant::setValue(const T &value)
+
+ Stores a copy of \a value. If \c{T} is a type that QVariant
+ doesn't support, QMetaType is used to store the value. A compile
+ error will occur if QMetaType doesn't handle the type.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 4
+
+ \sa value(), fromValue(), canConvert()
+ */
+
+/*! \fn T QVariant::value() const
+
+ Returns the stored value converted to the template type \c{T}.
+ Call canConvert() to find out whether a type can be converted.
+ If the value cannot be converted, \l{default-constructed value}
+ will be returned.
+
+ If the type \c{T} is supported by QVariant, this function behaves
+ exactly as toString(), toInt() etc.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 5
+
+ \sa setValue(), fromValue(), canConvert()
+*/
+
+/*! \fn bool QVariant::canConvert() const
+
+ Returns true if the variant can be converted to the template type \c{T},
+ otherwise false.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 6
+
+ \sa convert()
+*/
+
+/*! \fn static QVariant QVariant::fromValue(const T &value)
+
+ Returns a QVariant containing a copy of \a value. Behaves
+ exactly like setValue() otherwise.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 7
+
+ \note If you are working with custom types, you should use
+ the Q_DECLARE_METATYPE() macro to register your custom type.
+
+ \sa setValue(), value()
+*/
+
+/*!
+ \fn QVariant qVariantFromValue(const T &value)
+ \relates QVariant
+ \obsolete
+
+ Returns a variant containing a copy of the given \a value
+ with template type \c{T}.
+
+ This function is equivalent to QVariant::fromValue(\a value).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ For example, a QObject pointer can be stored in a variant with the
+ following code:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 8
+
+ \sa QVariant::fromValue()
+*/
+
+/*! \fn void qVariantSetValue(QVariant &variant, const T &value)
+ \relates QVariant
+ \obsolete
+
+ Sets the contents of the given \a variant to a copy of the
+ \a value with the specified template type \c{T}.
+
+ This function is equivalent to QVariant::setValue(\a value).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QVariant::setValue()
+*/
+
+/*!
+ \fn T qvariant_cast(const QVariant &value)
+ \relates QVariant
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ This function is equivalent to QVariant::value().
+
+ \sa QVariant::value()
+*/
+
+/*! \fn T qVariantValue(const QVariant &value)
+ \relates QVariant
+ \obsolete
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ This function is equivalent to
+ \l{QVariant::value()}{QVariant::value}<T>(\a value).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QVariant::value(), qvariant_cast()
+*/
+
+/*! \fn bool qVariantCanConvert(const QVariant &value)
+ \relates QVariant
+ \obsolete
+
+ Returns true if the given \a value can be converted to the
+ template type specified; otherwise returns false.
+
+ This function is equivalent to QVariant::canConvert(\a value).
+
+ \note This function was provided as a workaround for MSVC 6
+ which did not support member template functions. It is advised
+ to use the other form in new code.
+
+ \sa QVariant::canConvert()
+*/
+
+/*!
+ \typedef QVariantList
+ \relates QVariant
+
+ Synonym for QList<QVariant>.
+*/
+
+/*!
+ \typedef QVariantMap
+ \relates QVariant
+
+ Synonym for QMap<QString, QVariant>.
+*/
+
+/*!
+ \typedef QVariantHash
+ \relates QVariant
+ \since 4.5
+
+ Synonym for QHash<QString, QVariant>.
+*/
+
+/*!
+ \typedef QVariant::DataPtr
+ \internal
+*/
+
+/*!
+ \fn DataPtr &QVariant::data_ptr()
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
new file mode 100644
index 0000000000..1b8cb7fd0b
--- /dev/null
+++ b/src/corelib/kernel/qvariant.h
@@ -0,0 +1,618 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QVARIANT_H
+#define QVARIANT_H
+
+#include <QtCore/qatomic.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QBitArray;
+class QDataStream;
+class QDate;
+class QDateTime;
+class QEasingCurve;
+class QLine;
+class QLineF;
+class QLocale;
+class QMatrix;
+class QTransform;
+class QStringList;
+class QTime;
+class QPoint;
+class QPointF;
+class QSize;
+class QSizeF;
+class QRect;
+class QRectF;
+#ifndef QT_NO_REGEXP
+class QRegExp;
+#endif
+class QTextFormat;
+class QTextLength;
+class QUrl;
+class QVariant;
+class QVariantComparisonHelper;
+
+template <typename T>
+inline QVariant qVariantFromValue(const T &);
+
+template<typename T>
+inline T qvariant_cast(const QVariant &);
+
+class Q_CORE_EXPORT QVariant
+{
+ public:
+ enum Type {
+ Invalid = 0,
+
+ Bool = 1,
+ Int = 2,
+ UInt = 3,
+ LongLong = 4,
+ ULongLong = 5,
+ Double = 6,
+ Char = 7,
+ Map = 8,
+ List = 9,
+ String = 10,
+ StringList = 11,
+ ByteArray = 12,
+ BitArray = 13,
+ Date = 14,
+ Time = 15,
+ DateTime = 16,
+ Url = 17,
+ Locale = 18,
+ Rect = 19,
+ RectF = 20,
+ Size = 21,
+ SizeF = 22,
+ Line = 23,
+ LineF = 24,
+ Point = 25,
+ PointF = 26,
+ RegExp = 27,
+ Hash = 28,
+ EasingCurve = 29,
+ LastCoreType = EasingCurve,
+
+ // value 62 is internally reserved
+#ifdef QT3_SUPPORT
+ ColorGroup = 63,
+#endif
+ Font = 64,
+ Pixmap = 65,
+ Brush = 66,
+ Color = 67,
+ Palette = 68,
+ Icon = 69,
+ Image = 70,
+ Polygon = 71,
+ Region = 72,
+ Bitmap = 73,
+ Cursor = 74,
+ SizePolicy = 75,
+ KeySequence = 76,
+ Pen = 77,
+ TextLength = 78,
+ TextFormat = 79,
+ Matrix = 80,
+ Transform = 81,
+ Matrix4x4 = 82,
+ Vector2D = 83,
+ Vector3D = 84,
+ Vector4D = 85,
+ Quaternion = 86,
+ LastGuiType = Quaternion,
+
+ UserType = 127,
+#ifdef QT3_SUPPORT
+ IconSet = Icon,
+ CString = ByteArray,
+ PointArray = Polygon,
+#endif
+ LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type
+ };
+
+ inline QVariant();
+ ~QVariant();
+ QVariant(Type type);
+ QVariant(int typeOrUserType, const void *copy);
+ QVariant(int typeOrUserType, const void *copy, uint flags);
+ QVariant(const QVariant &other);
+
+#ifndef QT_NO_DATASTREAM
+ QVariant(QDataStream &s);
+#endif
+
+ QVariant(int i);
+ QVariant(uint ui);
+ QVariant(qlonglong ll);
+ QVariant(qulonglong ull);
+ QVariant(bool b);
+ QVariant(double d);
+ QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; }
+#ifndef QT_NO_CAST_FROM_ASCII
+ QT_ASCII_CAST_WARN_CONSTRUCTOR QVariant(const char *str);
+#endif
+
+ QVariant(const QByteArray &bytearray);
+ QVariant(const QBitArray &bitarray);
+ QVariant(const QString &string);
+ QVariant(const QLatin1String &string);
+ QVariant(const QStringList &stringlist);
+ QVariant(const QChar &qchar);
+ QVariant(const QDate &date);
+ QVariant(const QTime &time);
+ QVariant(const QDateTime &datetime);
+ QVariant(const QList<QVariant> &list);
+ QVariant(const QMap<QString,QVariant> &map);
+ QVariant(const QHash<QString,QVariant> &hash);
+#ifndef QT_NO_GEOM_VARIANT
+ QVariant(const QSize &size);
+ QVariant(const QSizeF &size);
+ QVariant(const QPoint &pt);
+ QVariant(const QPointF &pt);
+ QVariant(const QLine &line);
+ QVariant(const QLineF &line);
+ QVariant(const QRect &rect);
+ QVariant(const QRectF &rect);
+#endif
+ QVariant(const QUrl &url);
+ QVariant(const QLocale &locale);
+#ifndef QT_NO_REGEXP
+ QVariant(const QRegExp &regExp);
+#endif
+#ifndef QT_BOOTSTRAPPED
+ QVariant(const QEasingCurve &easing);
+#endif
+ QVariant(Qt::GlobalColor color);
+
+ QVariant& operator=(const QVariant &other);
+#ifdef Q_COMPILER_RVALUE_REFS
+ inline QVariant &operator=(QVariant &&other)
+ { qSwap(d, other.d); return *this; }
+#endif
+
+ inline void swap(QVariant &other) { qSwap(d, other.d); }
+
+ Type type() const;
+ int userType() const;
+ const char *typeName() const;
+
+ bool canConvert(Type t) const;
+ bool convert(Type t);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT bool canCast(Type t) const
+ { return canConvert(t); }
+ inline QT3_SUPPORT bool cast(Type t)
+ { return convert(t); }
+#endif
+
+ inline bool isValid() const;
+ bool isNull() const;
+
+ void clear();
+
+ void detach();
+ inline bool isDetached() const;
+
+ int toInt(bool *ok = 0) const;
+ uint toUInt(bool *ok = 0) const;
+ qlonglong toLongLong(bool *ok = 0) const;
+ qulonglong toULongLong(bool *ok = 0) const;
+ bool toBool() const;
+ double toDouble(bool *ok = 0) const;
+ float toFloat(bool *ok = 0) const;
+ qreal toReal(bool *ok = 0) const;
+ QByteArray toByteArray() const;
+ QBitArray toBitArray() const;
+ QString toString() const;
+ QStringList toStringList() const;
+ QChar toChar() const;
+ QDate toDate() const;
+ QTime toTime() const;
+ QDateTime toDateTime() const;
+ QList<QVariant> toList() const;
+ QMap<QString, QVariant> toMap() const;
+ QHash<QString, QVariant> toHash() const;
+
+#ifndef QT_NO_GEOM_VARIANT
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+ QRect toRect() const;
+ QSize toSize() const;
+ QSizeF toSizeF() const;
+ QLine toLine() const;
+ QLineF toLineF() const;
+ QRectF toRectF() const;
+#endif
+ QUrl toUrl() const;
+ QLocale toLocale() const;
+#ifndef QT_NO_REGEXP
+ QRegExp toRegExp() const;
+#endif
+#ifndef QT_BOOTSTRAPPED
+ QEasingCurve toEasingCurve() const;
+#endif
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT int &asInt();
+ inline QT3_SUPPORT uint &asUInt();
+ inline QT3_SUPPORT qlonglong &asLongLong();
+ inline QT3_SUPPORT qulonglong &asULongLong();
+ inline QT3_SUPPORT bool &asBool();
+ inline QT3_SUPPORT double &asDouble();
+ inline QT3_SUPPORT QByteArray &asByteArray();
+ inline QT3_SUPPORT QBitArray &asBitArray();
+ inline QT3_SUPPORT QString &asString();
+ inline QT3_SUPPORT QStringList &asStringList();
+ inline QT3_SUPPORT QDate &asDate();
+ inline QT3_SUPPORT QTime &asTime();
+ inline QT3_SUPPORT QDateTime &asDateTime();
+ inline QT3_SUPPORT QList<QVariant> &asList();
+ inline QT3_SUPPORT QMap<QString,QVariant> &asMap();
+ inline QT3_SUPPORT QPoint &asPoint();
+ inline QT3_SUPPORT QRect &asRect();
+ inline QT3_SUPPORT QSize &asSize();
+#endif //QT3_SUPPORT
+
+#ifndef QT_NO_DATASTREAM
+ void load(QDataStream &ds);
+ void save(QDataStream &ds) const;
+#endif
+ static const char *typeToName(Type type);
+ static Type nameToType(const char *name);
+
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT_CONSTRUCTOR QVariant(bool val, int) { create(Bool, &val); }
+ inline QT3_SUPPORT const QByteArray toCString() const { return toByteArray(); }
+ inline QT3_SUPPORT QByteArray &asCString() { return *reinterpret_cast<QByteArray *>(castOrDetach(ByteArray)); }
+#endif
+
+ void *data();
+ const void *constData() const;
+ inline const void *data() const { return constData(); }
+
+ template<typename T>
+ inline void setValue(const T &value);
+
+ template<typename T>
+ inline T value() const
+ { return qvariant_cast<T>(*this); }
+
+ template<typename T>
+ static inline QVariant fromValue(const T &value)
+ { return qVariantFromValue(value); }
+
+ template<typename T>
+ bool canConvert() const
+ { return canConvert(Type(qMetaTypeId<T>())); }
+
+ public:
+#ifndef qdoc
+ struct PrivateShared
+ {
+ inline PrivateShared(void *v) : ptr(v), ref(1) { }
+ void *ptr;
+ QAtomicInt ref;
+ };
+ struct Private
+ {
+ inline Private(): type(Invalid), is_shared(false), is_null(true) { data.ptr = 0; }
+ inline Private(const Private &other)
+ : data(other.data), type(other.type),
+ is_shared(other.is_shared), is_null(other.is_null)
+ {}
+ union Data
+ {
+ char c;
+ int i;
+ uint u;
+ bool b;
+ double d;
+ float f;
+ qreal real;
+ qlonglong ll;
+ qulonglong ull;
+ QObject *o;
+ void *ptr;
+ PrivateShared *shared;
+ } data;
+ uint type : 30;
+ uint is_shared : 1;
+ uint is_null : 1;
+ };
+ public:
+ typedef void (*f_construct)(Private *, const void *);
+ typedef void (*f_clear)(Private *);
+ typedef bool (*f_null)(const Private *);
+#ifndef QT_NO_DATASTREAM
+ typedef void (*f_load)(Private *, QDataStream &);
+ typedef void (*f_save)(const Private *, QDataStream &);
+#endif
+ typedef bool (*f_compare)(const Private *, const Private *);
+ typedef bool (*f_convert)(const QVariant::Private *d, Type t, void *, bool *);
+ typedef bool (*f_canConvert)(const QVariant::Private *d, Type t);
+ typedef void (*f_debugStream)(QDebug, const QVariant &);
+ struct Handler {
+ f_construct construct;
+ f_clear clear;
+ f_null isNull;
+#ifndef QT_NO_DATASTREAM
+ f_load load;
+ f_save save;
+#endif
+ f_compare compare;
+ f_convert convert;
+ f_canConvert canConvert;
+ f_debugStream debugStream;
+ };
+#endif
+
+ inline bool operator==(const QVariant &v) const
+ { return cmp(v); }
+ inline bool operator!=(const QVariant &v) const
+ { return !cmp(v); }
+
+protected:
+ friend inline bool qvariant_cast_helper(const QVariant &, QVariant::Type, void *);
+ friend int qRegisterGuiVariant();
+ friend int qUnregisterGuiVariant();
+ friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
+#endif
+ Private d;
+
+ static const Handler *handler;
+
+ void create(int type, const void *copy);
+#ifdef QT3_SUPPORT
+ void *castOrDetach(Type t);
+#endif
+ bool cmp(const QVariant &other) const;
+
+private:
+ // force compile error, prevent QVariant(bool) to be called
+ inline QVariant(void *) { Q_ASSERT(false); }
+#ifdef QT_NO_CAST_FROM_ASCII
+ // force compile error when implicit conversion is not wanted
+ inline QVariant(const char *) { Q_ASSERT(false); }
+#endif
+#ifndef QT3_SUPPORT
+ // force compile error, prevent QVariant(QVariant::Type, int) to be called
+ inline QVariant(bool, int) { Q_ASSERT(false); }
+#endif
+public:
+ typedef Private DataPtr;
+ inline DataPtr &data_ptr() { return d; }
+};
+
+typedef QList<QVariant> QVariantList;
+typedef QMap<QString, QVariant> QVariantMap;
+typedef QHash<QString, QVariant> QVariantHash;
+
+inline bool qvariant_cast_helper(const QVariant &v, QVariant::Type tp, void *ptr)
+{ return QVariant::handler->convert(&v.d, tp, ptr, 0); }
+
+template <typename T>
+inline QVariant qVariantFromValue(const T &t)
+{
+ return QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t, QTypeInfo<T>::isPointer);
+}
+
+template <>
+inline QVariant qVariantFromValue(const QVariant &t) { return t; }
+
+template <typename T>
+inline void qVariantSetValue(QVariant &v, const T &t)
+{
+ //if possible we reuse the current QVariant private
+ const uint type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
+ QVariant::Private &d = v.data_ptr();
+ if (v.isDetached() && (type == d.type || (type <= uint(QVariant::Char) && d.type <= uint(QVariant::Char)))) {
+ d.type = type;
+ d.is_null = false;
+ T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
+ if (QTypeInfo<T>::isComplex)
+ old->~T();
+ new (old) T(t); //call the copy constructor
+ } else {
+ v = QVariant(type, &t, QTypeInfo<T>::isPointer);
+ }
+}
+
+template <>
+inline void qVariantSetValue<QVariant>(QVariant &v, const QVariant &t)
+{
+ v = t;
+}
+
+
+inline QVariant::QVariant() {}
+inline bool QVariant::isValid() const { return d.type != Invalid; }
+
+#ifdef QT3_SUPPORT
+inline int &QVariant::asInt()
+{ return *reinterpret_cast<int *>(castOrDetach(Int)); }
+inline uint &QVariant::asUInt()
+{ return *reinterpret_cast<uint *>(castOrDetach(UInt)); }
+inline qlonglong &QVariant::asLongLong()
+{ return *reinterpret_cast<qlonglong *>(castOrDetach(LongLong)); }
+inline qulonglong &QVariant::asULongLong()
+{ return *reinterpret_cast<qulonglong *>(castOrDetach(ULongLong)); }
+inline bool &QVariant::asBool()
+{ return *reinterpret_cast<bool *>(castOrDetach(Bool)); }
+inline double &QVariant::asDouble()
+{ return *reinterpret_cast<double *>(castOrDetach(Double)); }
+inline QByteArray& QVariant::asByteArray()
+{ return *reinterpret_cast<QByteArray *>(castOrDetach(ByteArray)); }
+inline QBitArray& QVariant::asBitArray()
+{ return *reinterpret_cast<QBitArray *>(castOrDetach(BitArray)); }
+inline QString& QVariant::asString()
+{ return *reinterpret_cast<QString *>(castOrDetach(String)); }
+inline QStringList& QVariant::asStringList()
+{ return *reinterpret_cast<QStringList *>(castOrDetach(StringList)); }
+inline QDate& QVariant::asDate()
+{ return *reinterpret_cast<QDate *>(castOrDetach(Date)); }
+inline QTime& QVariant::asTime()
+{ return *reinterpret_cast<QTime *>(castOrDetach(Time)); }
+inline QDateTime& QVariant::asDateTime()
+{ return *reinterpret_cast<QDateTime *>(castOrDetach(DateTime)); }
+inline QList<QVariant>& QVariant::asList()
+{ return *reinterpret_cast<QList<QVariant> *>(castOrDetach(List)); }
+inline QMap<QString, QVariant>& QVariant::asMap()
+{ return *reinterpret_cast<QMap<QString, QVariant> *>(castOrDetach(Map)); }
+inline QPoint &QVariant::asPoint()
+{ return *reinterpret_cast<QPoint *>(castOrDetach(Point)); }
+inline QRect &QVariant::asRect()
+{ return *reinterpret_cast<QRect *>(castOrDetach(Rect)); }
+inline QSize &QVariant::asSize()
+{ return *reinterpret_cast<QSize *>(castOrDetach(Size)); }
+#endif //QT3_SUPPORT
+
+template<typename T>
+inline void QVariant::setValue(const T &avalue)
+{ qVariantSetValue(*this, avalue); }
+
+#ifndef QT_NO_DATASTREAM
+Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant& p);
+Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant& p);
+Q_CORE_EXPORT QDataStream& operator>> (QDataStream& s, QVariant::Type& p);
+Q_CORE_EXPORT QDataStream& operator<< (QDataStream& s, const QVariant::Type p);
+#endif
+
+inline bool QVariant::isDetached() const
+{ return !d.is_shared || d.data.shared->ref == 1; }
+
+
+#ifdef qdoc
+ inline bool operator==(const QVariant &v1, const QVariant &v2);
+ inline bool operator!=(const QVariant &v1, const QVariant &v2);
+#else
+
+/* Helper class to add one more level of indirection to prevent
+ implicit casts.
+*/
+class QVariantComparisonHelper
+{
+public:
+ inline QVariantComparisonHelper(const QVariant &var)
+ : v(&var) {}
+private:
+ friend inline bool operator==(const QVariant &, const QVariantComparisonHelper &);
+ const QVariant *v;
+};
+
+inline bool operator==(const QVariant &v1, const QVariantComparisonHelper &v2)
+{
+ return v1.cmp(*v2.v);
+}
+
+inline bool operator!=(const QVariant &v1, const QVariantComparisonHelper &v2)
+{
+ return !operator==(v1, v2);
+}
+#endif
+
+#ifndef QT_MOC
+template<typename T> inline T qvariant_cast(const QVariant &v)
+{
+ const int vid = qMetaTypeId<T>(static_cast<T *>(0));
+ if (vid == v.userType())
+ return *reinterpret_cast<const T *>(v.constData());
+ if (vid < int(QMetaType::User)) {
+ T t;
+ if (qvariant_cast_helper(v, QVariant::Type(vid), &t))
+ return t;
+ }
+ return T();
+}
+
+template<> inline QVariant qvariant_cast<QVariant>(const QVariant &v)
+{
+ if (v.userType() == QMetaType::QVariant)
+ return *reinterpret_cast<const QVariant *>(v.constData());
+ return v;
+}
+
+#ifdef QT_DEPRECATED
+template<typename T>
+inline QT_DEPRECATED T qVariantValue(const QVariant &variant)
+{ return qvariant_cast<T>(variant); }
+
+template<typename T>
+inline QT_DEPRECATED bool qVariantCanConvert(const QVariant &variant)
+{ return variant.template canConvert<T>(); }
+#endif
+
+#endif
+Q_DECLARE_SHARED(QVariant)
+Q_DECLARE_TYPEINFO(QVariant, Q_MOVABLE_TYPE);
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant &);
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QVariant::Type);
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_BUILTIN_METATYPE(QVariantList, QVariantList)
+Q_DECLARE_BUILTIN_METATYPE(QVariantMap, QVariantMap)
+Q_DECLARE_BUILTIN_METATYPE(QVariantHash, QVariantHash)
+
+QT_END_HEADER
+
+#endif // QVARIANT_H
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
new file mode 100644
index 0000000000..a30d2df5f7
--- /dev/null
+++ b/src/corelib/kernel/qvariant_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QVARIANT_P_H
+#define QVARIANT_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.
+//
+
+// takes a type, returns the internal void* pointer cast
+// to a pointer of the input type
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_CC_SUN // Sun CC picks the wrong overload, so introduce awful hack
+
+template <typename T>
+inline T *v_cast(const QVariant::Private *nd, T * = 0)
+{
+ QVariant::Private *d = const_cast<QVariant::Private *>(nd);
+ return ((sizeof(T) > sizeof(QVariant::Private::Data))
+ ? static_cast<T *>(d->data.shared->ptr)
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
+}
+
+#else // every other compiler in this world
+
+template <typename T>
+inline const T *v_cast(const QVariant::Private *d, T * = 0)
+{
+ return ((sizeof(T) > sizeof(QVariant::Private::Data))
+ ? static_cast<const T *>(d->data.shared->ptr)
+ : static_cast<const T *>(static_cast<const void *>(&d->data.c)));
+}
+
+template <typename T>
+inline T *v_cast(QVariant::Private *d, T * = 0)
+{
+ return ((sizeof(T) > sizeof(QVariant::Private::Data))
+ ? static_cast<T *>(d->data.shared->ptr)
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
+}
+
+#endif
+
+
+//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
+template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
+{
+public:
+ QVariantPrivateSharedEx() : QVariant::PrivateShared(&m_t) { }
+ QVariantPrivateSharedEx(const T&t) : QVariant::PrivateShared(&m_t), m_t(t) { }
+
+private:
+ T m_t;
+};
+
+// constructs a new variant if copy is 0, otherwise copy-constructs
+template <class T>
+inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
+{
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ x->data.shared = copy ? new QVariantPrivateSharedEx<T>(*static_cast<const T *>(copy))
+ : new QVariantPrivateSharedEx<T>;
+ x->is_shared = true;
+ } else {
+ if (copy)
+ new (&x->data.ptr) T(*static_cast<const T *>(copy));
+ else
+ new (&x->data.ptr) T;
+ }
+}
+
+template <class T>
+inline void v_construct(QVariant::Private *x, const T &t)
+{
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ x->data.shared = new QVariantPrivateSharedEx<T>(t);
+ x->is_shared = true;
+ } else {
+ new (&x->data.ptr) T(t);
+ }
+}
+
+// deletes the internal structures
+template <class T>
+inline void v_clear(QVariant::Private *d, T* = 0)
+{
+
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ //now we need to cast
+ //because QVariant::PrivateShared doesn't have a virtual destructor
+ delete static_cast<QVariantPrivateSharedEx<T>*>(d->data.shared);
+ } else {
+ v_cast<T>(d)->~T();
+ }
+
+}
+
+Q_CORE_EXPORT const QVariant::Handler *qcoreVariantHandler();
+
+QT_END_NAMESPACE
+
+#endif // QVARIANT_P_H
diff --git a/src/corelib/kernel/qwineventnotifier_p.cpp b/src/corelib/kernel/qwineventnotifier_p.cpp
new file mode 100644
index 0000000000..afdc26502e
--- /dev/null
+++ b/src/corelib/kernel/qwineventnotifier_p.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 "qwineventnotifier_p.h"
+
+#include "qeventdispatcher_win_p.h"
+#include "qcoreapplication.h"
+
+#include <private/qthread_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ \class QWinEventNotifier
+ \brief The QWinEventNotifier class provides support for the Windows Wait functions.
+
+ The QWinEventNotifier class makes it possible to use the wait
+ functions on windows in a asynchronous manner. With this class
+ you can register a HANDLE to an event and get notification when
+ that event becomes signalled. The state of the event is not modified
+ in the process so if it is a manual reset event you will need to
+ reset it after the notification.
+*/
+
+
+QWinEventNotifier::QWinEventNotifier(QObject *parent)
+ : QObject(parent), handleToEvent(0), enabled(false)
+{}
+
+QWinEventNotifier::QWinEventNotifier(HANDLE hEvent, QObject *parent)
+ : QObject(parent), handleToEvent(hEvent), enabled(false)
+{
+ Q_D(QObject);
+ QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(d->threadData->eventDispatcher);
+ Q_ASSERT_X(eventDispatcher, "QWinEventNotifier::QWinEventNotifier()",
+ "Cannot create a win event notifier without a QEventDispatcherWin32");
+ eventDispatcher->registerEventNotifier(this);
+ enabled = true;
+}
+
+QWinEventNotifier::~QWinEventNotifier()
+{
+ setEnabled(false);
+}
+
+void QWinEventNotifier::setHandle(HANDLE hEvent)
+{
+ setEnabled(false);
+ handleToEvent = hEvent;
+}
+
+HANDLE QWinEventNotifier::handle() const
+{
+ return handleToEvent;
+}
+
+bool QWinEventNotifier::isEnabled() const
+{
+ return enabled;
+}
+
+void QWinEventNotifier::setEnabled(bool enable)
+{
+ if (enabled == enable) // no change
+ return;
+ enabled = enable;
+
+ Q_D(QObject);
+ QEventDispatcherWin32 *eventDispatcher = qobject_cast<QEventDispatcherWin32 *>(d->threadData->eventDispatcher);
+ if (!eventDispatcher) // perhaps application is shutting down
+ return;
+
+ if (enabled)
+ eventDispatcher->registerEventNotifier(this);
+ else
+ eventDispatcher->unregisterEventNotifier(this);
+}
+
+bool QWinEventNotifier::event(QEvent * e)
+{
+ if (e->type() == QEvent::ThreadChange) {
+ if (enabled) {
+ QMetaObject::invokeMethod(this, "setEnabled", Qt::QueuedConnection,
+ Q_ARG(bool, enabled));
+ setEnabled(false);
+ }
+ }
+ QObject::event(e); // will activate filters
+ if (e->type() == QEvent::WinEventAct) {
+ emit activated(handleToEvent);
+ return true;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qwineventnotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h
new file mode 100644
index 0000000000..9d7ab6a1c8
--- /dev/null
+++ b/src/corelib/kernel/qwineventnotifier_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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 QWINEVENTNOTIFIER_P_H
+#define QWINEVENTNOTIFIER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qobject.h"
+#include "QtCore/qt_windows.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QWinEventNotifier : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QObject)
+
+public:
+ explicit QWinEventNotifier(QObject *parent = 0);
+ explicit QWinEventNotifier(HANDLE hEvent, QObject *parent = 0);
+ ~QWinEventNotifier();
+
+ void setHandle(HANDLE hEvent);
+ HANDLE handle() const;
+
+ bool isEnabled() const;
+
+public Q_SLOTS:
+ void setEnabled(bool enable);
+
+Q_SIGNALS:
+ void activated(HANDLE hEvent);
+
+protected:
+ bool event(QEvent * e);
+
+private:
+ Q_DISABLE_COPY(QWinEventNotifier)
+
+ HANDLE handleToEvent;
+ bool enabled;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINEVENTNOTIFIER_P_H