summaryrefslogtreecommitdiff
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:18:55 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:18:55 +0100
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/corelib/kernel
downloadqt4-tools-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz
Long live Qt 4.5!
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri111
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp461
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h107
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher_p.h77
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp2783
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h390
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h150
-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.h155
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2406
-rw-r--r--src/corelib/kernel/qcoreapplication.h279
-rw-r--r--src/corelib/kernel/qcoreapplication_mac.cpp66
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h126
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp1042
-rw-r--r--src/corelib/kernel/qcorecmdlineargs_p.h171
-rw-r--r--src/corelib/kernel/qcoreevent.cpp599
-rw-r--r--src/corelib/kernel/qcoreevent.h363
-rw-r--r--src/corelib/kernel/qcoreglobaldata.cpp55
-rw-r--r--src/corelib/kernel/qcoreglobaldata_p.h72
-rw-r--r--src/corelib/kernel/qcrashhandler.cpp420
-rw-r--r--src/corelib/kernel/qcrashhandler_p.h81
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib.cpp501
-rw-r--r--src/corelib/kernel/qeventdispatcher_glib_p.h115
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp957
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h246
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp1076
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h109
-rw-r--r--src/corelib/kernel/qeventloop.cpp323
-rw-r--r--src/corelib/kernel/qeventloop.h101
-rw-r--r--src/corelib/kernel/qfunctions_p.h75
-rw-r--r--src/corelib/kernel/qfunctions_wince.cpp453
-rw-r--r--src/corelib/kernel/qfunctions_wince.h396
-rw-r--r--src/corelib/kernel/qmath.h139
-rw-r--r--src/corelib/kernel/qmetaobject.cpp2555
-rw-r--r--src/corelib/kernel/qmetaobject.h233
-rw-r--r--src/corelib/kernel/qmetaobject_p.h208
-rw-r--r--src/corelib/kernel/qmetatype.cpp1355
-rw-r--r--src/corelib/kernel/qmetatype.h351
-rw-r--r--src/corelib/kernel/qmimedata.cpp627
-rw-r--r--src/corelib/kernel/qmimedata.h104
-rw-r--r--src/corelib/kernel/qobject.cpp3818
-rw-r--r--src/corelib/kernel/qobject.h480
-rw-r--r--src/corelib/kernel/qobject_p.h225
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.cpp148
-rw-r--r--src/corelib/kernel/qobjectcleanuphandler.h78
-rw-r--r--src/corelib/kernel/qobjectdefs.h465
-rw-r--r--src/corelib/kernel/qpointer.cpp260
-rw-r--r--src/corelib/kernel/qpointer.h168
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp541
-rw-r--r--src/corelib/kernel/qsharedmemory.h119
-rw-r--r--src/corelib/kernel/qsharedmemory_p.h169
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp305
-rw-r--r--src/corelib/kernel/qsharedmemory_win.cpp208
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp321
-rw-r--r--src/corelib/kernel/qsignalmapper.h100
-rw-r--r--src/corelib/kernel/qsocketnotifier.cpp322
-rw-r--r--src/corelib/kernel/qsocketnotifier.h93
-rw-r--r--src/corelib/kernel/qsystemsemaphore.cpp360
-rw-r--r--src/corelib/kernel/qsystemsemaphore.h102
-rw-r--r--src/corelib/kernel/qsystemsemaphore_p.h109
-rw-r--r--src/corelib/kernel/qsystemsemaphore_unix.cpp242
-rw-r--r--src/corelib/kernel/qsystemsemaphore_win.cpp140
-rw-r--r--src/corelib/kernel/qtimer.cpp372
-rw-r--r--src/corelib/kernel/qtimer.h116
-rw-r--r--src/corelib/kernel/qtranslator.cpp827
-rw-r--r--src/corelib/kernel/qtranslator.h98
-rw-r--r--src/corelib/kernel/qtranslator_p.h78
-rw-r--r--src/corelib/kernel/qvariant.cpp3098
-rw-r--r--src/corelib/kernel/qvariant.h605
-rw-r--r--src/corelib/kernel/qvariant_p.h124
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.cpp136
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h94
74 files changed, 34453 insertions, 0 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
new file mode 100644
index 0000000000..d90ecae98d
--- /dev/null
+++ b/src/corelib/kernel/kernel.pri
@@ -0,0 +1,111 @@
+# 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
+
+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
+
+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 {
+ SOURCES += \
+ kernel/qcoreapplication_mac.cpp
+}
+
+mac {
+ SOURCES += \
+ kernel/qcore_mac.cpp
+}
+
+unix {
+ SOURCES += \
+ kernel/qcrashhandler.cpp \
+ kernel/qsharedmemory_unix.cpp \
+ kernel/qsystemsemaphore_unix.cpp
+ HEADERS += \
+ 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 +=$$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)
+}
+
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
new file mode 100644
index 0000000000..51fde17179
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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
+enum { NumberOfBuckets = 8, FirstBucketSize = 8 };
+
+static const int BucketSize[NumberOfBuckets] =
+ { 8, 64, 512, 4096, 32768, 262144, 2097152, 16777216 - 2396744 };
+static const int BucketOffset[NumberOfBuckets] =
+ { 0, 8, 72, 584, 4680, 37448, 299592, 2396744 };
+
+static int FirstBucket[FirstBucketSize] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+static QBasicAtomicPointer<int> timerIds[NumberOfBuckets] =
+ { 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),
+ 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 & 0x00FFFFFF) | ((oldId + 0x01000000) & 0x7f000000);
+}
+
+static inline int bucketOffset(int timerId)
+{
+ 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;
+ }
+}
+
+int QAbstractEventDispatcherPrivate::allocateTimerId()
+{
+ int timerId, newTimerId;
+ do {
+ timerId = nextFreeTimerId;
+
+ // which bucket are we looking in?
+ int which = timerId & 0x00ffffff;
+ int bucket = bucketOffset(which);
+ int at = bucketIndex(bucket, which);
+ int *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 = b[at];
+ } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));
+
+ return timerId;
+}
+
+void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
+{
+ int which = timerId & 0x00ffffff;
+ int bucket = bucketOffset(which);
+ int at = bucketIndex(bucket, which);
+ int *b = timerIds[bucket];
+
+ int freeId, newTimerId;
+ do {
+ freeId = nextFreeTimerId;
+ b[at] = freeId & 0x00ffffff;
+
+ 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 application
+ \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
+
+ \sa setEventFilter(), filterEvent()
+*/
+
+/*!
+ Sets the event filter \a filter. Returns a pointer to the filter
+ function previously defined.
+
+ The event filter is a function that receives all messages taken
+ from the system event loop before the event is dispatched to the
+ respective target. This includes messages that are not sent to Qt
+ objects.
+
+ The function can return true to stop the event to be processed by
+ Qt, or false to continue with the standard event processing.
+
+ Only one filter can be defined, but the filter can use the return
+ value to call the previously set event filter. By default, no
+ filter is set (i.e. the function returns 0).
+*/
+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.
+
+ \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..7daeaad657
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..7909ab48f1
--- /dev/null
+++ b/src/corelib/kernel/qabstracteventdispatcher_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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
+
+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..fd0e105aba
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -0,0 +1,2783 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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.
+ Note that 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
+ 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();
+}
+
+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::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
+ \mainclass
+
+ 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 the items held beneath 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 \link model-view-programming.html Model/View Programming\endlink 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.
+
+ You receive a const pointer to the model 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 or an invalid
+ QModelIndex if there is no sibling at this position.
+
+ \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.
+
+ \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.
+ Note that 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
+ \mainclass
+
+ 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.
+
+ \img 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)
+
+ 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, or QModelIndex()
+ if it has no parent.
+
+ 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.
+
+ \note 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.
+
+ The removeRow() 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.
+
+ Note that this signal must be emitted explicitly when
+ reimplementing the setHeaderData() function.
+
+ If you are changing the number of columns or rows you don't need
+ to emit this signal, but use the begin/end functions (see 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().
+
+ \sa layoutAboutToBeChanged(), dataChanged(), headerDataChanged(), reset(), 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.
+
+ \bold{Tip:} 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
+
+ \bold{Tip:} 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.
+
+ \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 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.
+
+ \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 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.
+
+ \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 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.
+
+ \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 removeRows(), beginRemoveRows()
+*/
+
+/*!
+ \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.
+
+ \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 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.
+
+ \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 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.
+
+ \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 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.
+
+ \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 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.
+
+ Reimplemented 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.type() != QVariant::Invalid)
+ 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. Note that the
+ dataChanged() signal must be emitted explicitly when
+ reimplementing this function.
+
+ \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.
+
+ Returns true if the dropping was successful otherwise false.
+
+ \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. Note that 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;
+}
+
+/*!
+ On models that support this, inserts \a count rows into the model before the
+ given \a row. The 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.
+
+ 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
+ you own API for altering the data.
+
+ \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
+ you 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
+ you 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
+ you 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, and
+ construct a delegate using the model index returned by the buddy item.
+
+ In the default implementation each item is 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 the 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 starts 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,
+ This function can be reimplemented to include other 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: span is not used currently, but will be in the future.
+*/
+
+QSize QAbstractItemModel::span(const QModelIndex &) const
+{
+ return QSize(1, 1);
+}
+
+/*!
+ Called to let the model know that it should submit whatever it has cached
+ to the permanent storage. Typically used for row editing.
+
+ Returns false on error, otherwise true.
+*/
+
+bool QAbstractItemModel::submit()
+{
+ return true;
+}
+
+/*!
+ Called to let the model know that it should discard whatever it has cached.
+ Typically used for row editing.
+*/
+
+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 of items shown beneath it. For vertical headers, the section
+ number typically to the row number of items shown alongside it.
+
+ \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.
+
+ Note that the headerDataChanged() signal must be emitted explicitly
+ when reimplementing this function.
+
+ \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.
+
+ Note that when you are using a QSortFilterProxyModel its indexes have their own
+ internal pointer. It is not advisable to access the internal pointer in the index
+ 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
+
+ \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
+
+ \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);
+}
+
+/*!
+ 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
+
+ \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
+
+ \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);
+}
+
+/*!
+ Resets the model to its original state in any attached views.
+
+ \note The view to which the model is attached to 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.
+
+ 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.
+
+ \sa modelAboutToBeReset(), modelReset()
+*/
+void QAbstractItemModel::reset()
+{
+ Q_D(QAbstractItemModel);
+ emit modelAboutToBeReset();
+ 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
+
+ \bold{Note:} Some general guidelines for subclassing models are
+ available in the \l{Model Subclassing Reference}.
+
+ 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
+
+ \sa {Model Classes}, {Model Subclassing Reference}, 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
+
+ \bold{Note:} Some general guidelines for subclassing models are
+ available in the \l{Model Subclassing Reference}.
+
+ 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
+
+ \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 reset(), 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 reset(), 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..b062768ef0
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel.h
@@ -0,0 +1,390 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+
+#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();
+
+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();
+
+ void beginInsertColumns(const QModelIndex &parent, int first, int last);
+ void endInsertColumns();
+
+ void beginRemoveColumns(const QModelIndex &parent, int first, int last);
+ void endRemoveColumns();
+
+ void reset();
+
+ void changePersistentIndex(const QModelIndex &from, const QModelIndex &to);
+ void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to);
+ QModelIndexList persistentIndexList() const;
+
+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..df1a6cefca
--- /dev/null
+++ b/src/corelib/kernel/qabstractitemmodel_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 Q_CORE_EXPORT 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) {}
+ void removePersistentIndexData(QPersistentModelIndexData *data);
+ 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();
+
+ 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) {}
+ Change(const QModelIndex &p, int f, int l) : parent(p), first(f), last(l) {}
+ QModelIndex parent;
+ int first, last;
+ };
+ 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;
+};
+
+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..40a12c146a
--- /dev/null
+++ b/src/corelib/kernel/qbasictimer.cpp
@@ -0,0 +1,138 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasictimer.h"
+#include "qcoreapplication.h"
+#include "qabstracteventdispatcher.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QBasicTimer
+ \brief The QBasicTimer class provides timer events for objects.
+
+ \ingroup time
+ \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.
+
+ 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, has not yet timed
+ out, 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..1146b6219e
--- /dev/null
+++ b/src/corelib/kernel/qbasictimer.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..1681b09b10
--- /dev/null
+++ b/src/corelib/kernel/qcore_mac.cpp
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <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..54c9aaa5af
--- /dev/null
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -0,0 +1,155 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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
+
+#include <ApplicationServices/ApplicationServices.h>
+
+#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/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
new file mode 100644
index 0000000000..b3f9f1ae7d
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -0,0 +1,2406 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreevent.h"
+#include "qeventloop.h"
+#include "qcorecmdlineargs_p.h"
+#include <qdatastream.h>
+#include <qdatetime.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 <qlibraryinfo.h>
+#include <private/qfactoryloader_p.h>
+
+#ifdef 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
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
+extern QString qAppFileName();
+#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 = postRList();
+ 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)
+ : QObjectPrivate(), argc(aargc), argv(aargv), application_type(0), eventFilter(0),
+ in_exec(false), aboutToQuitEmitted(false)
+{
+ 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_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()
+{
+#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_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);
+}
+#endif
+
+void QCoreApplicationPrivate::appendApplicationPathToLibraryPaths()
+{
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ QStringList *app_libpaths = coreappdata()->app_libpaths;
+ Q_ASSERT(app_libpaths);
+ QString app_location( QCoreApplication::applicationFilePath() );
+ app_location.truncate(app_location.lastIndexOf(QLatin1Char('/')));
+ app_location = QDir(app_location).canonicalPath();
+ if (app_location != QLibraryInfo::location(QLibraryInfo::PluginsPath) && QFile::exists(app_location) && !app_libpaths->contains(app_location))
+ 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.
+
+ \ingroup application
+ \mainclass
+
+ 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.
+
+ The command line arguments which QCoreApplication's constructor
+ should be called with are accessible using arguments(). The
+ event loop is started with a call to exec(). Long running
+ operations can call processEvents() to keep the application
+ responsive.
+
+ Some Qt classes, such as QString, can be used without a
+ QCoreApplication object. However, in general, we recommend that
+ you create a QCoreApplication or a QApplication object in your \c
+ main() function as early as possible. The application will enter
+ the event loop when exec() is called. exit() will not return
+ until the event loop exits, e.g., when quit() is called.
+
+ An application has an applicationDirPath() and an
+ applicationFilePath(). 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().
+
+ The class provides a quit() slot and an aboutToQuit() signal.
+
+ 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(). Library paths (see
+ QLibrary) can be retrieved with libraryPaths() and manipulated by
+ setLibraryPaths(), addLibraryPath(), and removeLibraryPath().
+
+ \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))
+{
+ init();
+ QCoreApplicationPrivate::eventDispatcher->startingUp();
+}
+
+extern void set_winapp_name();
+
+// ### 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
+
+#ifdef Q_WS_WIN
+ // Get the application name/instance if qWinMain() was not invoked
+ set_winapp_name();
+#endif
+
+ Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
+ QCoreApplication::self = this;
+
+#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
+
+ qt_startup_hook();
+}
+
+/*!
+ 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::globalInstance()->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);
+}
+
+/*!
+ 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
+
+#if defined(QT_NO_EXCEPTIONS)
+ bool returnValue = notify(receiver, event);
+#else
+ bool returnValue;
+ try {
+ returnValue = notify(receiver, event);
+ } catch(...) {
+ --threadData->loopLevel;
+ throw;
+ }
+#endif
+
+#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 send to
+ any object is all threads.
+
+ 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
+
+#ifdef QT3_SUPPORT
+ if (event->type() == QEvent::ChildRemoved && !receiver->d_func()->pendingChildInsertedEvents.isEmpty())
+ receiver->d_func()->removePendingChildInsertedEvents(static_cast<QChildEvent *>(event)->child());
+#endif // QT3_SUPPORT
+
+ 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;
+ QTime 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 modify or delete 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 modify or delete 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();
+ }
+
+ // if this is one of the compressible events, do compression
+ if (receiver->d_func()->postedEvents
+ && self && self->compressEvent(event, receiver, &data->postEventList)) {
+ data->postEventList.mutex.unlock();
+ return;
+ }
+
+ event->posted = true;
+ ++receiver->d_func()->postedEvents;
+ 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));
+ }
+
+ 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));
+ }
+ data->canWait = false;
+ data->postEventList.mutex.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;
+ QCoreApplicationPrivate::removePostedEvents_unlocked(receiver, eventType, data);
+}
+
+void QCoreApplicationPrivate::removePostedEvents_unlocked(QObject *receiver,
+ int eventType,
+ QThreadData *data)
+{
+ 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()->removePendingChildInsertedEvents(0);
+#endif
+ pe.event->posted = false;
+ delete 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());
+ }
+}
+
+
+/*!
+ 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;
+}
+
+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.
+
+ \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 == QString())
+ d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
+ 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 != QString())
+ return d->cachedApplicationFilePath;
+
+#if defined( Q_WS_WIN )
+ QFileInfo filePath;
+ QT_WA({
+ wchar_t module_name[MAX_PATH+1];
+ GetModuleFileNameW(0, module_name, MAX_PATH);
+ module_name[MAX_PATH] = 0;
+ filePath = QString::fromUtf16((ushort *)module_name);
+ }, {
+ char module_name[MAX_PATH+1];
+ GetModuleFileNameA(0, module_name, MAX_PATH);
+ module_name[MAX_PATH] = 0;
+ filePath = QString::fromLocal8Bit(module_name);
+ });
+
+ d->cachedApplicationFilePath = filePath.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_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(QLatin1String(":"));
+ 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();
+#else
+ // UNIX
+ 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 i.e. 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.
+
+ \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 = QT_WA_INLINE(QString::fromUtf16((unsigned short *)GetCommandLineW()), QString::fromLocal8Bit(GetCommandLineA()));
+
+#if defined(Q_OS_WINCE)
+ wchar_t tempFilename[MAX_PATH+1];
+ if (GetModuleFileNameW(0, tempFilename, MAX_PATH)) {
+ tempFilename[MAX_PATH] = 0;
+ cmdline.prepend(QString(QLatin1String("\"")) + QString::fromUtf16((unsigned short *)tempFilename) + QString(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" ||
+ l1arg == "-direct3d")
+ ;
+ else if (l1arg.startsWith("-style="))
+ ;
+ else if (l1arg == "-style" ||
+ l1arg == "-session" ||
+ l1arg == "-graphicssystem")
+ ++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;
+}
+
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+
+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 (QFile::exists(installPathPlugins)) {
+ // Make sure we convert from backslashes to slashes.
+ installPathPlugins = QDir(installPathPlugins).canonicalPath();
+ if (!app_libpaths->contains(installPathPlugins))
+ app_libpaths->append(installPathPlugins);
+ }
+
+ // 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()) {
+#ifdef Q_OS_WIN
+ 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.
+
+ \sa libraryPaths(), addLibraryPath(), removeLibraryPath(), QLibrary
+ */
+void QCoreApplication::setLibraryPaths(const QStringList &paths)
+{
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ QMutexLocker locker(libraryPathMutex());
+ if (!coreappdata()->app_libpaths)
+ coreappdata()->app_libpaths = new QStringList;
+ *(coreappdata()->app_libpaths) = paths;
+ QFactoryLoader::refreshAll();
+#endif
+}
+
+/*!
+ 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.
+
+ \sa removeLibraryPath(), libraryPaths(), setLibraryPaths()
+ */
+void QCoreApplication::addLibraryPath(const QString &path)
+{
+#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ 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);
+ QFactoryLoader::refreshAll();
+ }
+#endif
+}
+
+/*!
+ 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 !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS)
+ 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
+}
+
+#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)
+
+ Sets the event filter \a filter. Returns a pointer to the filter
+ function previously defined.
+
+ The event filter is a function that is called for every message
+ received in all threads. This does \e not include messages to
+ objects that are not handled by Qt.
+
+ The function can return true to stop the event to be processed by
+ Qt, or false to continue with the standard event processing.
+
+ Only one filter can be defined, but the filter can use the return
+ value to call the previously set event filter. By default, no
+ filter is set (i.e., the function returns 0).
+
+ \sa installEventFilter()
+*/
+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..f7175ae84b
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -0,0 +1,279 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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:
+ QCoreApplication(int &argc, char **argv);
+ ~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
+
+#ifdef Q_OS_UNIX
+ 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;
+
+ 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..4e34a10095
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_mac.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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..9490ad7dd5
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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"
+
+QT_BEGIN_NAMESPACE
+
+typedef QList<QTranslator*> QTranslatorList;
+
+class QAbstractEventDispatcher;
+
+class Q_CORE_EXPORT QCoreApplicationPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QCoreApplication)
+
+public:
+ QCoreApplicationPrivate(int &aargc, char **aargv);
+ ~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);
+ static void removePostedEvents_unlocked(QObject *receiver, int type, QThreadData *data);
+
+#if !defined (QT_NO_DEBUG) || defined (QT_MAC_FRAMEWORK_BUILD)
+ 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;
+
+ 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); }
+};
+
+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..225821f073
--- /dev/null
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -0,0 +1,1042 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreapplication.h"
+#include "qcoreapplication_p.h"
+#include "qstringlist.h"
+#include "qt_windows.h"
+#include "qvector.h"
+#include "qmutex.h"
+#include "qcorecmdlineargs_p.h"
+#include <private/qthread_p.h>
+#include <ctype.h>
+
+QT_BEGIN_NAMESPACE
+
+// ############### DON'T EXPORT HERE!!!
+Q_CORE_EXPORT char appFileName[MAX_PATH+1]; // application file name
+Q_CORE_EXPORT char theAppName[MAX_PATH+1]; // application name
+Q_CORE_EXPORT HINSTANCE appInst = 0; // handle to app instance
+Q_CORE_EXPORT HINSTANCE appPrevInst = 0; // handle to prev app instance
+Q_CORE_EXPORT int appCmdShow = 0;
+bool usingWinMain = false; // whether the qWinMain() is used or not
+
+Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle
+{
+ return appInst;
+}
+
+Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app handle
+{
+ return appPrevInst;
+}
+
+void set_winapp_name()
+{
+ static bool already_set = false;
+ if (!already_set) {
+ already_set = true;
+#ifndef Q_OS_WINCE
+ GetModuleFileNameA(0, appFileName, sizeof(appFileName));
+ appFileName[sizeof(appFileName)-1] = 0;
+#else
+ QString afm;
+ afm.resize(sizeof(appFileName));
+ afm.resize(GetModuleFileName(0, (wchar_t *) (afm.unicode()), sizeof(appFileName)));
+ memcpy(appFileName, afm.toLatin1(), sizeof(appFileName));
+#endif
+ const char *p = strrchr(appFileName, '\\'); // skip path
+ if (p)
+ memcpy(theAppName, p+1, qstrlen(p));
+ int l = qstrlen(theAppName);
+ if ((l > 4) && !qstricmp(theAppName + l - 4, ".exe"))
+ theAppName[l-4] = '\0'; // drop .exe extension
+ }
+}
+
+Q_CORE_EXPORT QString qAppFileName() // get application file name
+{
+ return QString::fromLatin1(appFileName);
+}
+
+QString QCoreApplicationPrivate::appName() const
+{
+ if (!theAppName[0])
+ set_winapp_name();
+ return QString::fromLatin1(theAppName);
+}
+
+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();
+ QT_WA({
+ QString s(QString::fromLocal8Bit(str));
+ s += QLatin1String("\n");
+ OutputDebugStringW((TCHAR*)s.utf16());
+ }, {
+ QByteArray s(str);
+ s += "\n";
+ OutputDebugStringA(s.data());
+ })
+ 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
+
+ set_winapp_name();
+
+ argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
+ // Get Windows parameters
+
+ appInst = instance;
+ appPrevInst = prevInstance;
+ appCmdShow = cmdShow;
+}
+
+/*!
+ 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 {
+ 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" },
+ { 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
+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
+
+Q_CORE_EXPORT 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_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((uint)winPos->hwndInsertAfter,
+ FLAG_STRING((uint)HWND_BOTTOM, "HWND_BOTTOM"),
+ FLAG_STRING((int)HWND_NOTOPMOST, "HWND_NOTOPMOST"),
+ FLAG_STRING((uint)HWND_TOP, "HWND_TOP"),
+ FLAG_STRING((int)HWND_TOPMOST, "HWND_TOPMOST"),
+ FLAG_STRING());
+ if (hwndAfter.size() == 0)
+ hwndAfter = QString::number((uint)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..d1ca3f84f8
--- /dev/null
+++ b/src/corelib/kernel/qcorecmdlineargs_p.h
@@ -0,0 +1,171 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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)
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "QtCore/qvector.h"
+#include "qt_windows.h"
+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;
+}
+
+static inline QStringList qWinCmdArgs(QString cmdLine) // not const-ref: this might be modified
+{
+ QStringList args;
+
+ int argc = 0;
+ QVector<ushort*> argv = qWinCmdLine<ushort>((ushort*)cmdLine.utf16(), cmdLine.length(), argc);
+ for (int a = 0; a < argc; ++a) {
+ args << QString::fromUtf16(argv[a]);
+ }
+
+ return args;
+}
+
+static inline QStringList qCmdLineArgs(int argc, char *argv[])
+{
+ Q_UNUSED(argc)
+ Q_UNUSED(argv)
+ QString cmdLine = QT_WA_INLINE(
+ QString::fromUtf16((unsigned short*)GetCommandLineW()),
+ QString::fromLocal8Bit(GetCommandLineA())
+ );
+ return qWinCmdArgs(cmdLine);
+}
+
+#else // !Q_OS_WIN
+
+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
+
+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..3fcfc98c50
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -0,0 +1,599 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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
+ \ingroup environment
+
+ 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 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.
+ \value GraphicsSceneDragLeave The cursor leaves a graphics scene during a drag and drop operation.
+ \value GraphicsSceneDragMove A drag and drop operation is in progress over a scene.
+ \value GraphicsSceneDrop A drag and drop operation is completed over a scene.
+ \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 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 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.
+
+ 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 NetworkReplyUpdated
+ \omitvalue FutureCallOut
+ \omitvalue CocoaRequestModal
+*/
+
+/*!
+ 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 propgated 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..5487703d75
--- /dev/null
+++ b/src/corelib/kernel/qcoreevent.h
@@ -0,0 +1,363 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOREEVENT_H
+#define QCOREEVENT_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qbytearray.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEventPrivate;
+class Q_CORE_EXPORT QEvent // event base class
+{
+ QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+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,
+ CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window
+
+ // 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;
+};
+
+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..c756b6ae3b
--- /dev/null
+++ b/src/corelib/kernel/qcoreglobaldata.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcoreglobaldata_p.h"
+
+#include <QtDebug>
+
+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..b4904ab1e9
--- /dev/null
+++ b/src/corelib/kernel/qcoreglobaldata_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..7350b66ec0
--- /dev/null
+++ b/src/corelib/kernel/qcrashhandler.cpp
@@ -0,0 +1,420 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*************************************************************************
+ *
+ * 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;
+#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..d41e6370eb
--- /dev/null
+++ b/src/corelib/kernel/qcrashhandler_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..3fd768a45e
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_glib.cpp
@@ -0,0 +1,501 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_glib_p.h"
+#include "qeventdispatcher_unix_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;
+};
+
+static gboolean timerSourcePrepare(GSource *source, gint *timeout)
+{
+ gint dummy;
+ if (!timeout)
+ timeout = &dummy;
+
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+
+ 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 timerSourceCheck(GSource *source)
+{
+ GTimerSource *src = reinterpret_cast<GTimerSource *>(source);
+
+ if (src->timerList.isEmpty()
+ || (src->processEventsFlags & QEventLoop::X11ExcludeTimers))
+ return false;
+
+ if (src->timerList.updateCurrentTime() < src->timerList.first()->timeout)
+ return false;
+
+ return true;
+}
+
+static gboolean timerSourceDispatch(GSource *source, GSourceFunc, gpointer)
+{
+ (void) reinterpret_cast<GTimerSource *>(source)->timerList.activateTimers();
+ return true; // ??? don't remove, right again?
+}
+
+static GSourceFuncs timerSourceFuncs = {
+ timerSourcePrepare,
+ timerSourceCheck,
+ timerSourceDispatch,
+ NULL,
+ NULL,
+ NULL
+};
+
+struct GPostEventSource
+{
+ GSource source;
+ QAtomicInt serialNumber;
+ int lastSerialNumber;
+};
+
+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();
+ 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()) {
+ 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();
+ }
+ }
+
+ postEventSource = reinterpret_cast<GPostEventSource *>(g_source_new(&postEventSourceFuncs,
+ sizeof(GPostEventSource)));
+ postEventSource->serialNumber = 1;
+ 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 timerSource
+ timerSource = reinterpret_cast<GTimerSource *>(g_source_new(&timerSourceFuncs,
+ sizeof(GTimerSource)));
+ (void) new (&timerSource->timerList) QTimerInfoList();
+ timerSource->processEventsFlags = QEventLoop::AllEvents;
+ g_source_set_can_recurse(&timerSource->source, true);
+ g_source_attach(&timerSource->source, mainContext);
+}
+
+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;
+
+ // 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);
+ 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;
+
+ 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("QEventDispatcherUNIX::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("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(QEventDispatcherGlib);
+ return d->timerSource->timerList.unregisterTimer(timerId);
+}
+
+bool QEventDispatcherGlib::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(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..a2e6c3b967
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_glib_p.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+
+class Q_CORE_EXPORT QEventDispatcherGlibPrivate : public QAbstractEventDispatcherPrivate
+{
+
+public:
+ QEventDispatcherGlibPrivate(GMainContext *context = 0);
+ GMainContext *mainContext;
+ GPostEventSource *postEventSource;
+ GSocketNotifierSource *socketNotifierSource;
+ GTimerSource *timerSource;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVENTDISPATCHER_GLIB_P_H
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
new file mode 100644
index 0000000000..6aa3b56fa7
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -0,0 +1,957 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qcoreapplication.h"
+#include "qpair.h"
+#include "qsocketnotifier.h"
+#include "qthread.h"
+
+#include "qeventdispatcher_unix_p.h"
+#include <private/qthread_p.h>
+#include <private/qcoreapplication_p.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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;
+}
+
+
+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");
+}
+
+
+QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate()
+{
+ extern Qt::HANDLE qt_application_thread_id;
+ mainThread = (QThread::currentThreadId() == qt_application_thread_id);
+
+ // initialize the common parts of the event loop
+#ifdef Q_OS_INTEGRITY
+ // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead
+ if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1)
+ perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair");
+#else
+ if (pipe(thread_pipe) == -1)
+ perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe");
+#endif
+
+ initThreadPipeFD(thread_pipe[0]);
+ initThreadPipeFD(thread_pipe[1]);
+
+ sn_highest = -1;
+
+ interrupt = false;
+}
+
+QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate()
+{
+ // cleanup the common parts of the event loop
+ close(thread_pipe[0]);
+ close(thread_pipe[1]);
+
+ // 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.at(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)) {
+ char c[16];
+ while (::read(thread_pipe[0], c, sizeof(c)) > 0)
+ ;
+ 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.at(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)
+ useMonotonicTimers = false;
+
+# if (_POSIX_MONOTONIC_CLOCK == 0)
+ // detect if the system support monotonic timers
+ long x = sysconf(_SC_MONOTONIC_CLOCK);
+ useMonotonicTimers = x >= 200112L;
+# endif
+
+ getTime(currentTime);
+
+ if (!useMonotonicTimers) {
+ // not using monotonic timers, initialize the timeChanged() machinery
+ previousTime = currentTime;
+
+ 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;
+ }
+#else
+ // using monotonic timers unconditionally
+ getTime(currentTime);
+#endif
+
+ firstTimerInfo = currentTimerInfo = 0;
+}
+
+timeval QTimerInfoList::updateCurrentTime()
+{
+ getTime(currentTime);
+ return currentTime;
+}
+
+#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED)
+
+/*
+ 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)
+{
+ tms unused;
+ clock_t currentTicks = times(&unused);
+
+ int elapsedTicks = currentTicks - previousTicks;
+ timeval elapsedTime = currentTime - previousTime;
+ int elapsedMsecTicks = (elapsedTicks * 1000) / ticksPerSecond;
+ int deltaMsecs = (elapsedTime.tv_sec * 1000 + elapsedTime.tv_usec / 1000)
+ - elapsedMsecTicks;
+
+ if (delta) {
+ delta->tv_sec = deltaMsecs / 1000;
+ delta->tv_usec = (deltaMsecs % 1000) * 1000;
+ }
+ 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.
+
+ return (qAbs(deltaMsecs) - msPerTick) * 10 > elapsedMsecTicks;
+}
+
+void QTimerInfoList::getTime(timeval &t)
+{
+#if !defined(QT_NO_CLOCK_MONOTONIC) && !defined(QT_BOOTSTRAPPED)
+ if (useMonotonicTimers) {
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ t.tv_sec = ts.tv_sec;
+ t.tv_usec = ts.tv_nsec / 1000;
+ return;
+ }
+#endif
+
+ gettimeofday(&t, 0);
+ // NTP-related fix
+ while (t.tv_usec >= 1000000l) {
+ t.tv_usec -= 1000000l;
+ ++t.tv_sec;
+ }
+ while (t.tv_usec < 0l) {
+ if (t.tv_sec > 0l) {
+ t.tv_usec += 1000000l;
+ --t.tv_sec;
+ } else {
+ t.tv_usec = 0l;
+ break;
+ }
+ }
+}
+
+void QTimerInfoList::repairTimersIfNeeded()
+{
+ if (useMonotonicTimers)
+ return;
+ timeval delta;
+ if (timeChanged(&delta))
+ timerRepair(delta);
+}
+
+#else // !(_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(QT_BOOTSTRAPPED)
+
+void QTimerInfoList::getTime(timeval &t)
+{
+ timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ t.tv_sec = ts.tv_sec;
+ t.tv_usec = ts.tv_nsec / 1000;
+}
+
+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();
+
+ if (isEmpty())
+ return false;
+
+ QTimerInfo *t = first(); // first waiting timer
+ 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->inTimerEvent = false;
+
+ 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 == currentTimerInfo)
+ currentTimerInfo = 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 == currentTimerInfo)
+ currentTimerInfo = 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
+
+ bool firstTime = true;
+ timeval currentTime;
+ int n_act = 0, maxCount = count();
+
+ QTimerInfo *saveFirstTimerInfo = firstTimerInfo;
+ QTimerInfo *saveCurrentTimerInfo = currentTimerInfo;
+ firstTimerInfo = currentTimerInfo = 0;
+
+ while (maxCount--) {
+ currentTime = updateCurrentTime();
+ if (firstTime) {
+ repairTimersIfNeeded();
+ firstTime = false;
+ }
+
+ if (isEmpty())
+ break;
+
+ 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->inTimerEvent) {
+ // send event, but don't allow it to recurse
+ currentTimerInfo->inTimerEvent = true;
+
+ QTimerEvent e(currentTimerInfo->id);
+ QCoreApplication::sendEvent(currentTimerInfo->obj, &e);
+
+ if (currentTimerInfo)
+ currentTimerInfo->inTimerEvent = false;
+ }
+ }
+
+ firstTimerInfo = saveFirstTimerInfo;
+ currentTimerInfo = saveCurrentTimerInfo;
+
+ return n_act;
+}
+
+QEventDispatcherUNIX::QEventDispatcherUNIX(QObject *parent)
+ : QAbstractEventDispatcher(*new QEventDispatcherUNIXPrivate, parent)
+{ }
+
+QEventDispatcherUNIX::QEventDispatcherUNIX(QEventDispatcherUNIXPrivate &dd, QObject *parent)
+ : QAbstractEventDispatcher(dd, parent)
+{ }
+
+QEventDispatcherUNIX::~QEventDispatcherUNIX()
+{ }
+
+int QEventDispatcherUNIX::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
+ timeval *timeout)
+{
+ Q_D(QEventDispatcherUNIX);
+ if (timeout) {
+ // handle the case where select returns with a timeout, too
+ // soon.
+ timeval tvStart = d->timerList.currentTime;
+ timeval tvCurrent = tvStart;
+ timeval originalTimeout = *timeout;
+
+ int nsel;
+ do {
+ timeval tvRest = originalTimeout + tvStart - tvCurrent;
+ nsel = ::select(nfds, readfds, writefds, exceptfds, &tvRest);
+ d->timerList.getTime(tvCurrent);
+ } while (nsel == 0 && (tvCurrent - tvStart) < originalTimeout);
+
+ return nsel;
+ }
+
+ return ::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()
+{
+ while (!list.isEmpty())
+ delete list.takeFirst();
+}
+
+/*****************************************************************************
+ 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.at(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.at(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.first()->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.at(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;
+ ::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..41329cfac8
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/qpodlist_p.h"
+
+#include <sys/types.h>
+#include <sys/time.h>
+#if !defined(Q_OS_HPUX) || defined(__ia64)
+#include <sys/select.h>
+#endif
+#include <unistd.h>
+
+QT_BEGIN_NAMESPACE
+#if !defined(_POSIX_MONOTONIC_CLOCK)
+# define _POSIX_MONOTONIC_CLOCK -1
+#endif
+
+// Internal operator functions for timevals
+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;
+ if ((t1.tv_usec += t2.tv_usec) >= 1000000l) {
+ ++t1.tv_sec;
+ t1.tv_usec -= 1000000l;
+ }
+ return t1;
+}
+inline timeval operator+(const timeval &t1, const timeval &t2)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec + t2.tv_sec;
+ if ((tmp.tv_usec = t1.tv_usec + t2.tv_usec) >= 1000000l) {
+ ++tmp.tv_sec;
+ tmp.tv_usec -= 1000000l;
+ }
+ return tmp;
+}
+inline timeval operator-(const timeval &t1, const timeval &t2)
+{
+ timeval tmp;
+ tmp.tv_sec = t1.tv_sec - t2.tv_sec;
+ if ((tmp.tv_usec = t1.tv_usec - t2.tv_usec) < 0l) {
+ --tmp.tv_sec;
+ tmp.tv_usec += 1000000l;
+ }
+ return tmp;
+}
+
+// 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
+ bool inTimerEvent;
+};
+
+class QTimerInfoList : public QList<QTimerInfo*>
+{
+#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED)
+ bool useMonotonicTimers;
+
+ timeval previousTime;
+ clock_t previousTicks;
+ int ticksPerSecond;
+ int msPerTick;
+
+ bool timeChanged(timeval *delta);
+#endif
+
+ // state variables used by activateTimers()
+ QTimerInfo *firstTimerInfo, *currentTimerInfo;
+
+public:
+ QTimerInfoList();
+
+ void getTime(timeval &t);
+
+ 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 Q_CORE_EXPORT QSockNot
+{
+ QSocketNotifier *obj;
+ int fd;
+ fd_set *queue;
+};
+
+class Q_CORE_EXPORT 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..880e95ca7a
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -0,0 +1,1076 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventdispatcher_win_p.h"
+
+#include "qcoreapplication.h"
+#include "qhash.h"
+#include "qlibrary.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
+
+#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 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)QLibrary::resolve(QLatin1String("winmm"), "timeSetEvent");
+ qtimeKillEvent = (ptimeKillEvent)QLibrary::resolve(QLatin1String("winmm"), "timeKillEvent");
+#else
+ qtimeSetEvent = (ptimeSetEvent)QLibrary::resolve(QLatin1String("Mmtimer"), "timeSetEvent");
+ qtimeKillEvent = (ptimeKillEvent)QLibrary::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;
+
+ // timers
+ WinTimerVec timerVec;
+ WinTimerDict timerDict;
+ void registerTimer(WinTimerInfo *t);
+ void unregisterTimer(WinTimerInfo *t);
+ void sendTimerEvent(int timerId);
+
+ // socket notifiers
+ QSNDict sn_read;
+ QSNDict sn_write;
+ QSNDict sn_except;
+ void doWsaAsyncSelect(int socket);
+
+ // event notifier
+ QWinEventNotifier wakeUpNotifier;
+
+ QList<QWinEventNotifier *> winEventNotifierList;
+ void activateEventNotifier(QWinEventNotifier * wen);
+
+ QList<MSG> queuedUserInputEvents;
+ QList<MSG> queuedSocketEvents;
+};
+
+QEventDispatcherWin32Private::QEventDispatcherWin32Private()
+ : threadId(GetCurrentThreadId()), interrupt(false), internalHwnd(0)
+{
+ resolveTimerAPI();
+
+ wakeUpNotifier.setHandle(QT_WA_INLINE(CreateEventW(0, FALSE, FALSE, 0),
+ CreateEventA(0, FALSE, FALSE, 0)));
+ if (!wakeUpNotifier.handle())
+ qWarning("QEventDispatcher: Creating QEventDispatcherWin32Private wakeup event failed");
+}
+
+QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
+{
+ wakeUpNotifier.setEnabled(false);
+ CloseHandle(wakeUpNotifier.handle());
+ if (internalHwnd)
+ DestroyWindow(internalHwnd);
+ QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc));
+#if !defined(Q_OS_WINCE)
+ UnregisterClassA(className.constData(), qWinAppInst());
+#else
+ UnregisterClassW(reinterpret_cast<const wchar_t *> (QString::fromLatin1(className.constData()).utf16())
+ , qWinAppInst());
+#endif
+}
+
+void QEventDispatcherWin32Private::activateEventNotifier(QWinEventNotifier * wen)
+{
+ QEvent event(QEvent::WinEventAct);
+ QCoreApplication::sendEvent(wen, &event);
+}
+
+
+Q_CORE_EXPORT bool winPeekMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax, UINT wRemoveMsg)
+{
+ QT_WA({ return PeekMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); } ,
+ { return PeekMessageA(msg, hWnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); });
+}
+
+Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ QT_WA({ return PostMessage(hWnd, msg, wParam, lParam); } ,
+ { return PostMessageA(hWnd, msg, wParam, lParam); });
+}
+
+Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
+ UINT wMsgFilterMax)
+{
+ QT_WA({ return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax); } ,
+ { return GetMessageA(msg, hWnd, wMsgFilterMin, wMsgFilterMax); });
+}
+
+// This function is called by a workerthread
+void WINAPI 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 CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp)
+{
+ if (message == WM_NCCREATE) {
+ return true;
+ } else if (message == WM_USER) {
+
+ // socket notifier message
+ MSG msg;
+ msg.hwnd = hwnd;
+ msg.message = message;
+ msg.wParam = wp;
+ msg.lParam = lp;
+
+ QCoreApplication *app = QCoreApplication::instance();
+ long result;
+ if (app && app->filterEvent(&msg, &result))
+ return result;
+
+ 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) {
+
+ #ifdef GWLP_USERDATA
+ QEventDispatcherWin32 *eventDispatcher =
+ (QEventDispatcherWin32 *) GetWindowLongPtrA(hwnd, GWLP_USERDATA);
+ #else
+ QEventDispatcherWin32 *eventDispatcher =
+ (QEventDispatcherWin32 *) GetWindowLongA(hwnd, GWL_USERDATA);
+ #endif
+ if (eventDispatcher) {
+ QEventDispatcherWin32Private *d = eventDispatcher->d_func();
+ 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_TIMER) {
+
+ MSG msg;
+ msg.hwnd = hwnd;
+ msg.message = message;
+ msg.wParam = wp;
+ msg.lParam = lp;
+
+ QCoreApplication *app = QCoreApplication::instance();
+ Q_ASSERT_X(app, "qt_interal_proc", "Timer fired, but no QCoreApplication");
+ if (!app) {
+ KillTimer(hwnd, wp);
+ return 0;
+ }
+
+ long result;
+ if (app->filterEvent(&msg, &result))
+ return result;
+
+ QEventDispatcherWin32 *eventDispatcher =
+ qobject_cast<QEventDispatcherWin32 *>(QAbstractEventDispatcher::instance());
+ Q_ASSERT(eventDispatcher != 0);
+ QEventDispatcherWin32Private *d = eventDispatcher->d_func();
+ d->sendTimerEvent(wp);
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, message, wp, lp);
+}
+
+static HWND qt_create_internal_window(const QEventDispatcherWin32 *eventDispatcher)
+{
+ HINSTANCE hi = qWinAppInst();
+#if defined(Q_OS_WINCE)
+ WNDCLASS wc;
+#else
+ WNDCLASSA wc;
+#endif
+ wc.style = 0;
+ wc.lpfnWndProc = qt_internal_proc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = 0;
+ wc.hInstance = hi;
+ wc.hIcon = 0;
+ wc.hCursor = 0;
+ wc.hbrBackground = 0;
+ wc.lpszMenuName = NULL;
+
+ // make sure that multiple Qt's can coexist in the same process
+ QByteArray className = "QEventDispatcherWin32_Internal_Widget" + QByteArray::number(quintptr(qt_internal_proc));
+#if defined(Q_OS_WINCE)
+ QString tmp = QString::fromLatin1(className.data());
+ wc.lpszClassName = reinterpret_cast<const wchar_t *> (tmp.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
+ hi, // application
+ 0); // windows creation data.
+#else
+ wc.lpszClassName = className.constData();
+ RegisterClassA(&wc);
+ HWND wnd = CreateWindowA(wc.lpszClassName, // classname
+ wc.lpszClassName, // window name
+ 0, // style
+ 0, 0, 0, 0, // geometry
+ 0, // parent
+ 0, // menu handle
+ hi, // application
+ 0); // windows creation data.
+#endif
+
+
+#ifdef GWLP_USERDATA
+ SetWindowLongPtrA(wnd, GWLP_USERDATA, (LONG_PTR)eventDispatcher);
+#else
+ SetWindowLongA(wnd, GWL_USERDATA, (LONG)eventDispatcher);
+#endif
+
+ if (!wnd) {
+ qWarning("QEventDispatcher: Failed to create QEventDispatcherWin32 internal window: %d\n", (int)GetLastError());
+ }
+ return wnd;
+}
+
+void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
+{
+ Q_ASSERT(internalHwnd);
+
+ Q_Q(QEventDispatcherWin32);
+
+ int ok = 0;
+
+ if (t->interval > 10 || !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 avaiable
+ 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)
+{
+ // mark timer as unused
+ if (!QObjectPrivate::get(t->obj)->inThreadChangeEvent)
+ 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_USER : 0, sn_event);
+}
+
+void QEventDispatcherWin32::createInternalHwnd()
+{
+ Q_D(QEventDispatcherWin32);
+
+ Q_ASSERT(!d->internalHwnd);
+ if (d->internalHwnd)
+ return;
+ d->internalHwnd = qt_create_internal_window(this);
+
+ // 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));
+}
+
+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;
+ do {
+ QCoreApplicationPrivate::sendPostedEvents(0, 0, d->threadData);
+
+ 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 = winPeekMessage(&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)) {
+ // queue user input events for later processing
+ haveMessage = false;
+ d->queuedUserInputEvents.append(msg);
+ }
+ if (haveMessage && (flags & QEventLoop::ExcludeSocketNotifiers)
+ && (msg.message == WM_USER && 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) {
+ 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);
+ QT_WA({
+ DispatchMessage(&msg);
+ } , {
+ DispatchMessageA(&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
+ QThreadData *data = d->threadData;
+ canWait = (!retVal
+ && data->canWait
+ && !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);
+ 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);
+
+ return retVal;
+}
+
+bool QEventDispatcherWin32::hasPendingEvents()
+{
+ MSG msg;
+ return qGlobalPostedEventsCount() || winPeekMessage(&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);
+ SetEvent(d->wakeUpNotifier.handle());
+}
+
+void QEventDispatcherWin32::interrupt()
+{
+ Q_D(QEventDispatcherWin32);
+ d->interrupt = true;
+ wakeUp();
+}
+
+void QEventDispatcherWin32::flush()
+{ }
+
+
+void QEventDispatcherWin32::startingUp()
+{
+ Q_D(QEventDispatcherWin32);
+
+ if (d->wakeUpNotifier.handle()) d->wakeUpNotifier.setEnabled(true);
+}
+
+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
+ while (!d->timerDict.isEmpty())
+ unregisterTimer((*(d->timerDict.begin()))->timerId);
+}
+
+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) {
+ QTimerEvent te(zte->timerId());
+ QCoreApplication::sendEvent(t->obj, &te);
+ WinTimerInfo *tn = d->timerDict.value(zte->timerId());
+ if (tn && t == tn)
+ QCoreApplication::postEvent(this, new QZeroTimerEvent(zte->timerId()));
+ }
+ 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..aec0f7db3b
--- /dev/null
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 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 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 CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp);
+};
+
+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..92bdf733e7
--- /dev/null
+++ b/src/corelib/kernel/qeventloop.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventloop.h"
+
+#include "qabstracteventdispatcher.h"
+#include "qcoreapplication.h"
+#include "qdatetime.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);
+ 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);
+
+ // remove posted quit events when entering a new event loop
+ if (qApp->thread() == thread())
+ QCoreApplication::removePostedEvents(qApp, 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
+ 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
+ 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;
+
+ QTime 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..81ec339d7f
--- /dev/null
+++ b/src/corelib/kernel/qeventloop.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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_p.h b/src/corelib/kernel/qfunctions_p.h
new file mode 100644
index 0000000000..15f5fec44d
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// 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"
+#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_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp
new file mode 100644
index 0000000000..1c929c7e26
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_wince.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#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 *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::fromUtf16(reinterpret_cast<const ushort *> (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*)fn.utf16(), oflag, pmode );
+}
+
+int qt_wince__wopen( const WCHAR *filename, int oflag, int /*pmode*/ )
+{
+ WCHAR *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;
+}
+
+HRESULT qt_wince_CoInitialize(void* reserved)
+{
+ return CoInitializeEx(reserved, 0);
+}
+
+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 *file, int mode)
+{
+ // ### Does not work properly, what about just adding one property?
+ if(mode&_S_IWRITE) {
+ return SetFileAttributes(file, FILE_ATTRIBUTE_NORMAL);
+ } else if((mode&_S_IREAD) && !(mode&_S_IWRITE)) {
+ return SetFileAttributes(file, FILE_ATTRIBUTE_READONLY);
+ }
+ return false;
+}
+
+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) {
+ unsigned int mid = ((unsigned) (low + high)) >> 1;
+ int c = compare(key, (char*)base + mid * size);
+ if (c < 0)
+ high = mid - 1;
+ else if (c > 0)
+ low = mid + 1;
+ else
+ return (char*) base + mid * size;
+ }
+ return (NULL);
+}
+
+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..123bd23f82
--- /dev/null
+++ b/src/corelib/kernel/qfunctions_wince.h
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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
+
+#define SetWindowLongA SetWindowLong
+#define GetWindowLongA GetWindowLong
+#define SendMessageA SendMessage
+
+#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 *path, int pmode );
+int qt_wince__wopen( const WCHAR *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 );
+int qt_wince_open( const char *filename, int oflag, int pmode );
+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);
+HRESULT qt_wince_CoInitialize(void* reserved);
+
+bool qt_wince__chmod(const char *file, int mode);
+bool qt_wince__wchmod(const WCHAR *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 CoInitialize(a) qt_wince_CoInitialize(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.h b/src/corelib/kernel/qmath.h
new file mode 100644
index 0000000000..d8e0230f78
--- /dev/null
+++ b/src/corelib/kernel/qmath.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMATH_H
+#define QMATH_H
+
+#include <math.h>
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+inline int qCeil(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return int(ceilf(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(v));
+ else
+#endif
+ return int(floor(v));
+}
+
+inline qreal qSin(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return sinf(v);
+ else
+#endif
+ return sin(v);
+}
+
+inline qreal qCos(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return cosf(v);
+ else
+#endif
+ return cos(v);
+}
+
+inline qreal qAcos(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return acosf(v);
+ else
+#endif
+ return acos(v);
+}
+
+inline qreal qSqrt(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return sqrtf(v);
+ else
+#endif
+ return sqrt(v);
+}
+
+inline qreal qLn(qreal v)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return logf(v);
+ else
+#endif
+ return log(v);
+}
+
+inline qreal qPow(qreal x, qreal y)
+{
+#ifdef QT_USE_MATH_H_FLOATS
+ if (sizeof(qreal) == sizeof(float))
+ return powf(x, y);
+ else
+#endif
+ return pow(x, y);
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMATH_H
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
new file mode 100644
index 0000000000..719398c948
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -0,0 +1,2555 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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
+*/
+
+// do not touch without touching the moc as well
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000
+};
+
+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
+};
+
+struct QMetaObjectPrivate
+{
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ int propertyCount, propertyData;
+ int enumeratorCount, enumeratorData;
+ int constructorCount, constructorData;
+};
+
+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
+{
+ QVarLengthArray<char, 512> sig;
+ sig.append(className(), qstrlen(className()));
+ 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
+{
+ if (priv(d.data)->revision < 2)
+ return 0;
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(d.extradata);
+ if (!extra || !extra->static_metacall)
+ return 0;
+ return extra->static_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 const_cast<QObject*>(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;
+}
+
+/*!
+ \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) {
+ if (strcmp(constructor, d.stringdata
+ + d.data[priv(d.data)->constructorData + 5*i]) == 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
+{
+ int i = -1;
+ const QMetaObject *m = this;
+ while (m && i < 0) {
+ for (i = priv(m->d.data)->methodCount-1; i >= 0; --i)
+ if (strcmp(method, m->d.stringdata
+ + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) {
+ i += m->methodOffset();
+ break;
+ }
+ m = m->d.superdata;
+ }
+ 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
+{
+ int i = -1;
+ const QMetaObject *m = this;
+ while (m && i < 0) {
+ for (i = priv(m->d.data)->methodCount-1; i >= 0; --i)
+ if ((m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodSignal
+ && strcmp(signal, m->d.stringdata
+ + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) {
+ i += m->methodOffset();
+ break;
+ }
+ m = m->d.superdata;
+ }
+#ifndef QT_NO_DEBUG
+ if (i >= 0 && m && m->d.superdata) {
+ int conflict = m->d.superdata->indexOfMethod(signal);
+ if (conflict >= 0)
+ qWarning("QMetaObject::indexOfSignal:%s: Conflict with %s::%s",
+ m->d.stringdata, m->d.superdata->d.stringdata, signal);
+ }
+#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
+{
+ int i = -1;
+ const QMetaObject *m = this;
+ while (m && i < 0) {
+ for (i = priv(m->d.data)->methodCount-1; i >= 0; --i)
+ if ((m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodSlot
+ && strcmp(slot, m->d.stringdata
+ + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) {
+ i += m->methodOffset();
+ break;
+ }
+ m = m->d.superdata;
+ }
+ return i;
+}
+
+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) {
+ const QMetaObject **e;
+ if (priv(self->d.data)->revision < 2) {
+ e = (const QMetaObject**)(self->d.extradata);
+ } else {
+ const QMetaObjectExtraData *extra = (const QMetaObjectExtraData*)(self->d.extradata);
+ e = extra->objects;
+ }
+ if (e) {
+ while (*e) {
+ if (const QMetaObject *m =QMetaObject_findMetaObject((*e), name))
+ 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
+{
+ int i = -1;
+ const QMetaObject *m = this;
+ while (m && i < 0) {
+ for (i = priv(m->d.data)->enumeratorCount-1; i >= 0; --i)
+ if (strcmp(name, m->d.stringdata
+ + m->d.data[priv(m->d.data)->enumeratorData + 4*i]) == 0) {
+ i += m->enumeratorOffset();
+ break;
+ }
+ m = m->d.superdata;
+ }
+ return i;
+}
+
+/*!
+ Finds property \a name and returns its index; otherwise returns
+ -1.
+
+ \sa property(), propertyCount(), propertyOffset()
+*/
+int QMetaObject::indexOfProperty(const char *name) const
+{
+ int i = -1;
+ const QMetaObject *m = this;
+ while (m && i < 0) {
+ for (i = priv(m->d.data)->propertyCount-1; i >= 0; --i)
+ if (strcmp(name, m->d.stringdata
+ + m->d.data[priv(m->d.data)->propertyData + 3*i]) == 0) {
+ i += m->propertyOffset();
+ break;
+ }
+ m = m->d.superdata;
+ }
+ return i;
+}
+
+/*!
+ 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((int)strlen(type));
+ 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));
+ char stackbuf[64];
+ char *buf = (len >= 64 ? new char[len+1] : stackbuf);
+ qRemoveWhitespace(method, buf);
+ char *d = buf;
+
+ result.reserve(len);
+
+ int argdepth = 0;
+ int templdepth = 0;
+ while (*d) {
+ if (argdepth == 1)
+ d = qNormalizeType(d, templdepth, result);
+ if (*d == '(')
+ ++argdepth;
+ if (*d == ')')
+ --argdepth;
+ result += *d++;
+ }
+
+ if (buf != stackbuf)
+ delete [] buf;
+ 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::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())
+ 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);
+}
+
+/*!
+ 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.
+
+ \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;
+
+ // 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;
+ }
+
+ // 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 methodIndex = ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset();
+ if (connectionType == Qt::DirectConnection) {
+ return object->qt_metacall(QMetaObject::InvokeMetaMethod, methodIndex, param) < 0;
+ } else {
+ 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 *));
+ int *types = (int *) qMalloc(paramCount * sizeof(int));
+ 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;
+ }
+ }
+
+ if (connectionType == Qt::QueuedConnection) {
+ QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
+ 0,
+ -1,
+ nargs,
+ types,
+ args));
+ } else {
+ if (currentThread == objectThread) {
+ qWarning("QMetaMethod::invoke: Dead lock detected in "
+ "BlockingQueuedConnection: Receiver is %s(%p)",
+ mobj->className(), object);
+ }
+
+ // blocking queued connection
+#ifdef QT_NO_THREAD
+ QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
+ 0,
+ -1,
+ nargs,
+ types,
+ args));
+#else
+ QSemaphore semaphore;
+ QCoreApplication::postEvent(object, new QMetaCallEvent(methodIndex,
+ 0,
+ -1,
+ nargs,
+ types,
+ args,
+ &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
+
+ 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.
+
+ You get property meta-data through an object's meta-object. See
+ QMetaObject::property() and QMetaObject::propertyCount() for
+ details.
+
+ \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;
+ }
+
+ 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());
+}
+
+/*!
+ 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();
+ }
+ }
+ QVariant value;
+ void *argv[2] = { 0, &value };
+ if (t == QVariant::LastType) {
+ argv[0] = &value;
+ } else {
+ value = QVariant(t, (void*)0);
+ argv[0] = value.data();
+ }
+ const_cast<QObject*>(object)->qt_metacall(QMetaObject::ReadProperty,
+ idx + mobj->propertyOffset(),
+ argv);
+ if (argv[1] == 0)
+ // "value" was changed
+ 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;
+ }
+
+ void *argv[2] = { 0, &v };
+ if (t == QVariant::LastType)
+ argv[0] = &v;
+ else
+ argv[0] = v.data();
+ object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv);
+ return true;
+}
+
+/*!
+ 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 };
+ object->qt_metacall(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();
+}
+
+/*!
+ 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;
+ }
+}
+
+/*!
+ 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 };
+ const_cast<QObject*>(object)->qt_metacall(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 };
+ const_cast<QObject*>(object)->qt_metacall(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 };
+ const_cast<QObject*>(object)->qt_metacall(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 };
+ const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyUser,
+ idx + mobj->propertyOffset(), argv);
+ }
+ return b;
+}
+
+/*!
+ \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 };
+ const_cast<QObject*>(object)->qt_metacall(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.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h
new file mode 100644
index 0000000000..18c488a242
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject.h
@@ -0,0 +1,233 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+
+ 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;
+};
+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;
+
+ 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 isFlagType() const;
+ bool isEnumType() const;
+ QMetaEnum enumerator() const;
+
+ bool hasNotifySignal() const;
+ QMetaMethod notifySignal() const;
+ int notifySignalIndex() 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..2e0dbb2a30
--- /dev/null
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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>
+
+QT_BEGIN_NAMESPACE
+
+#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))) { // 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);
+ }
+
+ 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);
+ }
+ 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) {
+ result += normalizeTypeInternal(tt, t-1, fixScope, false);
+ result += c;
+ if (*t == '>')
+ result += ' '; // avoid >>
+ break;
+ }
+ }
+ }
+ }
+
+ 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..4d7d3094a8
--- /dev/null
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -0,0 +1,1355 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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"
+
+#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 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 User Base value for user types
+
+ \omitvalue FirstCoreExtType
+ \omitvalue FirstGuiType
+ \omitvalue LastCoreExtType
+ \omitvalue LastCoreType
+ \omitvalue LastGuiType
+
+ 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()
+*/
+
+/* Note: these MUST be in the order of the enums */
+static const struct { const char * typeName; int type; } types[] = {
+
+ /* All Core types */
+ {"void", QMetaType::Void},
+ {"bool", QMetaType::Bool},
+ {"int", QMetaType::Int},
+ {"uint", QMetaType::UInt},
+ {"qlonglong", QMetaType::LongLong},
+ {"qulonglong", QMetaType::ULongLong},
+ {"double", QMetaType::Double},
+ {"QChar", QMetaType::QChar},
+ {"QVariantMap", QMetaType::QVariantMap},
+ {"QVariantList", QMetaType::QVariantList},
+ {"QString", QMetaType::QString},
+ {"QStringList", QMetaType::QStringList},
+ {"QByteArray", QMetaType::QByteArray},
+ {"QBitArray", QMetaType::QBitArray},
+ {"QDate", QMetaType::QDate},
+ {"QTime", QMetaType::QTime},
+ {"QDateTime", QMetaType::QDateTime},
+ {"QUrl", QMetaType::QUrl},
+ {"QLocale", QMetaType::QLocale},
+ {"QRect", QMetaType::QRect},
+ {"QRectF", QMetaType::QRectF},
+ {"QSize", QMetaType::QSize},
+ {"QSizeF", QMetaType::QSizeF},
+ {"QLine", QMetaType::QLine},
+ {"QLineF", QMetaType::QLineF},
+ {"QPoint", QMetaType::QPoint},
+ {"QPointF", QMetaType::QPointF},
+ {"QRegExp", QMetaType::QRegExp},
+ {"QVariantHash", QMetaType::QVariantHash},
+
+ /* All GUI types */
+ {"QColorGroup", 63},
+ {"QFont", QMetaType::QFont},
+ {"QPixmap", QMetaType::QPixmap},
+ {"QBrush", QMetaType::QBrush},
+ {"QColor", QMetaType::QColor},
+ {"QPalette", QMetaType::QPalette},
+ {"QIcon", QMetaType::QIcon},
+ {"QImage", QMetaType::QImage},
+ {"QPolygon", QMetaType::QPolygon},
+ {"QRegion", QMetaType::QRegion},
+ {"QBitmap", QMetaType::QBitmap},
+ {"QCursor", QMetaType::QCursor},
+ {"QSizePolicy", QMetaType::QSizePolicy},
+ {"QKeySequence", QMetaType::QKeySequence},
+ {"QPen", QMetaType::QPen},
+ {"QTextLength", QMetaType::QTextLength},
+ {"QTextFormat", QMetaType::QTextFormat},
+ {"QMatrix", QMetaType::QMatrix},
+ {"QTransform", QMetaType::QTransform},
+
+ /* All Metatype builtins */
+ {"void*", QMetaType::VoidStar},
+ {"long", QMetaType::Long},
+ {"short", QMetaType::Short},
+ {"char", QMetaType::Char},
+ {"ulong", QMetaType::ULong},
+ {"ushort", QMetaType::UShort},
+ {"uchar", QMetaType::UChar},
+ {"float", QMetaType::Float},
+ {"QObject*", QMetaType::QObjectStar},
+ {"QWidget*", QMetaType::QWidgetStar},
+
+ /* Type aliases - order doesn't matter */
+ {"unsigned long", QMetaType::ULong},
+ {"unsigned int", QMetaType::UInt},
+ {"unsigned short", QMetaType::UShort},
+ {"unsigned char", QMetaType::UChar},
+ {"long long", QMetaType::LongLong},
+ {"unsigned long long", QMetaType::ULongLong},
+ {"qint8", QMetaType::Char},
+ {"quint8", QMetaType::UChar},
+ {"qint16", QMetaType::Short},
+ {"quint16", QMetaType::UShort},
+ {"qint32", QMetaType::Int},
+ {"quint32", QMetaType::UInt},
+ {"qint64", QMetaType::LongLong},
+ {"quint64", QMetaType::ULongLong},
+ {"QList<QVariant>", QMetaType::QVariantList},
+ {"QMap<QString,QVariant>", QMetaType::QVariantMap},
+ {"QHash<QString,QVariant>", QMetaType::QVariantHash},
+ // let QMetaTypeId2 figure out the type at compile time
+ {"qreal", QMetaTypeId2<qreal>::MetaType},
+
+ {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
+};
+
+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;
+
+ QVector<QCustomTypeInfo> *ct = customTypes();
+ if (!ct)
+ return;
+ QWriteLocker locker(customTypesLock());
+ QCustomTypeInfo &inf = (*ct)[idx - User];
+ inf.saveOp = saveOp;
+ inf.loadOp = loadOp;
+}
+#endif
+
+/*!
+ 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
+ Same as QMetaType::type(), but doesn't lock the mutex.
+*/
+static int qMetaTypeType_unlocked(const QByteArray &typeName)
+{
+ int i = 0;
+ while (types[i].typeName && strcmp(typeName.constData(), types[i].typeName))
+ ++i;
+ if (!types[i].type) {
+ const QVector<QCustomTypeInfo> * const ct = customTypes();
+ if (!ct)
+ return 0;
+
+ for (int v = 0; v < ct->count(); ++v) {
+ if (ct->at(v).typeName == typeName)
+ return v + QMetaType::User;
+ }
+ }
+ return types[i].type;
+}
+
+/*! \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
+
+ QWriteLocker locker(customTypesLock());
+ static int currentIdx = User;
+ int idx = qMetaTypeType_unlocked(normalizedTypeName);
+
+ if (!idx) {
+ idx = currentIdx++;
+ ct->resize(ct->count() + 1);
+ QCustomTypeInfo &inf = (*ct)[idx - User];
+ inf.typeName = normalizedTypeName;
+ inf.constr = constructor;
+ inf.destr = destructor;
+ }
+ return idx;
+}
+
+/*!
+ \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;
+ }
+ }
+}
+
+/*!
+ 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)
+{
+#ifdef QT_NO_QOBJECT
+ const NS(QByteArray) normalizedTypeName = typeName;
+#else
+ const NS(QByteArray) normalizedTypeName = QMetaObject::normalizedType(typeName);
+#endif
+
+ QReadLocker locker(customTypesLock());
+ return qMetaTypeType_unlocked(normalizedTypeName);
+}
+
+#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;
+#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
+#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:
+ 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;
+#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
+#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:
+ 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
+
+/*!
+ 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));
+#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
+ 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);
+#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
+ 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;
+#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
+ 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 to 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
+
+ \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..648f933425
--- /dev/null
+++ b/src/corelib/kernel/qmetatype.h
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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, LastCoreType = 28 /* QVariantHash */,
+
+ 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,
+ LastGuiType = 81 /* QTransform */,
+
+ FirstCoreExtType = 128 /* VoidStar */,
+ VoidStar = 128, Long = 129, Short = 130, Char = 131, ULong = 132,
+ UShort = 133, UChar = 134, Float = 135, QObjectStar = 136, QWidgetStar = 137,
+ LastCoreExtType = 137 /* QWidgetStar */,
+
+ 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);
+#endif
+ static int registerType(const char *typeName, Destructor destructor,
+ Constructor constructor);
+ 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>
+int qRegisterMetaType(const char *typeName
+#ifndef qdoc
+ , T * /* dummy */ = 0
+#endif
+)
+{
+ 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
+
+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(); }
+};
+
+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
+}
+
+#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); \
+ 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 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;
+
+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(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
+
+#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)
+
+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..f1c8e53fd0
--- /dev/null
+++ b/src/corelib/kernel/qmimedata.cpp
@@ -0,0 +1,627 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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.type() == QVariant::Invalid)
+ 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 withing 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..47c50750ee
--- /dev/null
+++ b/src/corelib/kernel/qmimedata.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..05015c0c15
--- /dev/null
+++ b/src/corelib/kernel/qobject.cpp
@@ -0,0 +1,3818 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qobject.h"
+#include "qobject_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 <private/qorderedmutexlocker_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 = static_cast<int *>(qMalloc((typeNames.count() + 1) * sizeof(int)));
+ 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());
+ qFree(types);
+ return 0;
+ }
+ }
+ types[typeNames.count()] = 0;
+
+ return types;
+}
+
+extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
+{
+}
+
+extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
+{
+}
+
+QObjectPrivate::QObjectPrivate(int version)
+ : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0)
+{
+ if (version != QObjectPrivateVersion)
+ qFatal("Cannot mix incompatible Qt libraries");
+
+ // 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;
+ inEventHandler = false;
+ inThreadChangeEvent = false;
+ deleteWatch = 0;
+}
+
+QObjectPrivate::~QObjectPrivate()
+{
+ if (deleteWatch)
+ *deleteWatch = 1;
+#ifndef QT_NO_USERDATA
+ if (extraData)
+ qDeleteAll(extraData->userData);
+ delete extraData;
+#endif
+}
+
+
+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;
+}
+
+
+
+
+
+#ifdef QT3_SUPPORT
+void QObjectPrivate::sendPendingChildInsertedEvents()
+{
+ Q_Q(QObject);
+ for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) {
+ QObject *c = pendingChildInsertedEvents.at(i);
+ if (!c)
+ continue;
+ QChildEvent childEvent(QEvent::ChildInserted, c);
+ QCoreApplication::sendEvent(q, &childEvent);
+ }
+ pendingChildInsertedEvents.clear();
+}
+
+void QObjectPrivate::removePendingChildInsertedEvents(QObject *child)
+{
+ if (!child) {
+ pendingChildInsertedEvents.clear();
+ return;
+ }
+
+ // the QObject destructor calls QObject::removeChild, which calls
+ // QCoreApplication::sendEvent() 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 this is a child remove event and the child insert hasn't
+ // been dispatched yet, kill that insert
+ for (int i = 0; i < pendingChildInsertedEvents.size(); ++i) {
+ QObject *&c = pendingChildInsertedEvents[i];
+ if (c == child)
+ c = 0;
+ }
+}
+#endif
+
+
+class QObjectConnectionListVector : public QVector<QObjectPrivate::ConnectionList>
+{
+public:
+ bool orphaned;
+ bool dirty;
+ int inUse;
+ QObjectPrivate::ConnectionList allsignals;
+
+ QObjectConnectionListVector()
+ : QVector<QObjectPrivate::ConnectionList>(), orphaned(false), dirty(false), inUse(0)
+ { }
+
+ const QObjectPrivate::ConnectionList &at(int at) const
+ {
+ if (at < 0)
+ return allsignals;
+ return QVector<QObjectPrivate::ConnectionList>::at(at);
+ }
+ QObjectPrivate::ConnectionList &operator[](int at)
+ {
+ if (at < 0)
+ return allsignals;
+ return QVector<QObjectPrivate::ConnectionList>::operator[](at);
+ }
+};
+
+bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
+{
+ Q_Q(const QObject);
+ int signal_index = q->metaObject()->indexOfSignal(signal);
+ if (signal_index < 0)
+ return false;
+ QMutexLocker locker(&threadData->mutex);
+ if (connectionLists) {
+ if (signal_index < connectionLists->count()) {
+ const ConnectionList &connectionList = connectionLists->at(signal_index);
+ for (int i = 0; i < connectionList.count(); ++i) {
+ const QObjectPrivate::Connection &c = connectionList.at(i);
+ if (c.receiver && c.receiver == receiver)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+QObjectList QObjectPrivate::receiverList(const char *signal) const
+{
+ Q_Q(const QObject);
+ QObjectList returnValue;
+ int signal_index = q->metaObject()->indexOfSignal(signal);
+ if (signal_index < 0)
+ return returnValue;
+ QMutexLocker locker(&threadData->mutex);
+ if (connectionLists) {
+ if (signal_index < connectionLists->count()) {
+ const ConnectionList &connectionList = connectionLists->at(signal_index);
+ for (int i = 0; i < connectionList.count(); ++i) {
+ const QObjectPrivate::Connection &c = connectionList.at(i);
+ if (c.receiver)
+ returnValue << c.receiver;
+ }
+ }
+ }
+ return returnValue;
+}
+
+QObjectList QObjectPrivate::senderList() const
+{
+ QObjectList returnValue;
+ QMutexLocker locker(&threadData->mutex);
+ for (int i = 0; i < senders.count(); ++i)
+ returnValue << senders.at(i).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];
+ connectionList.append(*c);
+
+ cleanConnectionLists();
+}
+
+void QObjectPrivate::removeReceiver(int signal, QObject *receiver)
+{
+ if (!connectionLists)
+ return;
+
+ if (signal >= connectionLists->count())
+ return;
+
+ ConnectionList &connectionList = (*connectionLists)[signal];
+ for (int i = 0; i < connectionList.count(); ++i) {
+ Connection &c = connectionList[i];
+ if (c.receiver == receiver) {
+ c.receiver = 0;
+ if (c.argumentTypes && c.argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ qFree(c.argumentTypes);
+ c.argumentTypes = 0;
+ }
+ connectionLists->dirty = true;
+ }
+ }
+}
+
+void QObjectPrivate::cleanConnectionLists()
+{
+ if (connectionLists->dirty && !connectionLists->inUse) {
+ // remove broken connections
+ for (int signal = -1; signal < connectionLists->count(); ++signal) {
+ QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal];
+ for (int i = 0; i < connectionList.count(); ++i) {
+ const QObjectPrivate::Connection &c = connectionList.at(i);
+ if (!c.receiver)
+ connectionList.removeAt(i--);
+ }
+ }
+ connectionLists->dirty = false;
+ }
+}
+
+void QObjectPrivate::refSender(QObject *sender, int signal)
+{
+ for (int i = 0; i < senders.count(); ++i) {
+ Sender &s = senders[i];
+ if (s.sender == sender && s.signal == signal) {
+ ++s.ref;
+ return;
+ }
+ }
+
+ Sender s = { sender, signal, 1 };
+ senders.append(s);
+}
+
+void QObjectPrivate::derefSender(QObject *sender, int signal)
+{
+ for (int i = 0; i < senders.count(); ++i) {
+ Sender &s = senders[i];
+ if (s.sender == sender && s.signal == signal) {
+ if (--s.ref == 0) {
+ senders.removeAt(i);
+ break;
+ }
+ }
+ }
+ // Q_ASSERT_X(false, "QObjectPrivate::derefSender", "sender not found");
+}
+
+void QObjectPrivate::removeSender(QObject *sender, int signal)
+{
+ for (int i = 0; i < senders.count(); ++i) {
+ Sender &s = senders[i];
+ if (s.sender == sender && s.signal == signal) {
+ senders.removeAt(i);
+ return;
+ }
+ }
+ // Q_ASSERT_X(false, "QObjectPrivate::removeSender", "sender not found");
+}
+
+QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
+ Sender *sender)
+{
+ Sender *previousSender = receiver->d_func()->currentSender;
+ receiver->d_func()->currentSender = sender;
+ return previousSender;
+}
+
+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;
+}
+
+
+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());
+ hash->insert(*ptr, ptr);
+}
+
+/*!\internal
+ */
+void QMetaObject::removeGuard(QObject **ptr)
+{
+ if (!*ptr)
+ return;
+ GuardHash *hash = guardHash();
+ if (!hash)
+ return;
+ QMutexLocker locker(guardHashLock());
+ GuardHash::iterator it = hash->find(*ptr);
+ const GuardHash::iterator end = hash->end();
+ for (; it.key() == *ptr && it != end; ++it) {
+ if (it.value() == ptr) {
+ (void) hash->erase(it);
+ break;
+ }
+ }
+}
+
+/*!\internal
+ */
+void QMetaObject::changeGuard(QObject **ptr, QObject *o)
+{
+ GuardHash *hash = guardHash();
+ if (!hash) {
+ *ptr = 0;
+ return;
+ }
+ QMutexLocker locker(guardHashLock());
+ if (*ptr) {
+ GuardHash::iterator it = hash->find(*ptr);
+ const GuardHash::iterator end = hash->end();
+ for (; it.key() == *ptr && it != end; ++it) {
+ if (it.value() == ptr) {
+ (void) hash->erase(it);
+ break;
+ }
+ }
+ }
+ *ptr = o;
+ if (*ptr)
+ hash->insert(*ptr, ptr);
+}
+
+/*! \internal
+ */
+void QObjectPrivate::clearGuards(QObject *object)
+{
+ GuardHash *hash = guardHash();
+ if (hash) {
+ QMutexLocker locker(guardHashLock());
+ 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(int id, const QObject *sender, int signalId,
+ int nargs, int *types, void **args, QSemaphore *semaphore)
+ : QEvent(MetaCall), id_(id), sender_(sender), signalId_(signalId),
+ nargs_(nargs), types_(types), args_(args), semaphore_(semaphore)
+{ }
+
+/*! \internal
+ */
+QMetaCallEvent::~QMetaCallEvent()
+{
+ for (int i = 0; i < nargs_; ++i) {
+ if (types_[i] && args_[i])
+ QMetaType::destroy(types_[i], args_[i]);
+ }
+ if (types_) qFree(types_);
+ if (args_) qFree(args_);
+#ifndef QT_NO_THREAD
+ if (semaphore_)
+ semaphore_->release();
+#endif
+}
+
+/*! \internal
+ */
+int QMetaCallEvent::placeMetaCall(QObject *object)
+{
+ return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_);
+}
+
+/*!
+ \class QObject
+ \brief The QObject class is the base class of all Qt objects.
+
+ \ingroup objectmodel
+ \mainclass
+ \reentrant
+
+ QObject is the heart of the \l{Qt 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 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 \l{Qt 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.
+
+ \section2 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.
+
+ \section2 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.
+
+ \sa QMetaObject, QPointer, QObjectCleanupHandler, Q_DISABLE_COPY()
+ {Object Trees and Object 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);
+ qt_addObject(d_ptr->q_ptr = this);
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ if (!check_parent_thread(parent, parent ? parent->d_func()->threadData : 0, d->threadData))
+ parent = 0;
+ setParent(parent);
+}
+
+#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 (!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);
+ qt_addObject(d_ptr->q_ptr = this);
+ d->threadData = (parent && !parent->thread()) ? parent->d_func()->threadData : QThreadData::current();
+ d->threadData->ref();
+ 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);
+ }
+}
+
+/*!
+ 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);
+ if (d->wasDeleted) {
+#if defined(QT_DEBUG)
+ qWarning("QObject: Double deletion detected");
+#endif
+ return;
+ }
+ d->wasDeleted = true;
+
+ d->blockSig = 0; // unblock signals so we always emit destroyed()
+
+ if (!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);
+ }
+
+ emit destroyed(this);
+
+ {
+ QMutexLocker locker(&d->threadData->mutex);
+
+ // set ref to zero to indicate that this object has been deleted
+ if (d->currentSender != 0)
+ d->currentSender->ref = 0;
+ d->currentSender = 0;
+
+ // disconnect all receivers
+ if (d->connectionLists) {
+ ++d->connectionLists->inUse;
+ for (int signal = -1; signal < d->connectionLists->count(); ++signal) {
+ QObjectPrivate::ConnectionList &connectionList = (*d->connectionLists)[signal];
+ for (int i = 0; i < connectionList.count(); ++i) {
+ QObjectPrivate::Connection *c = &connectionList[i];
+ if (!c->receiver)
+ continue;
+
+ QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
+ c = &connectionList[i];
+ if (c->receiver)
+ c->receiver->d_func()->removeSender(this, signal);
+ if (needToUnlock)
+ m->unlock();
+
+ if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ qFree(c->argumentTypes);
+ c->argumentTypes = 0;
+ }
+ c->receiver = 0;
+ }
+ }
+
+ if (!--d->connectionLists->inUse) {
+ delete d->connectionLists;
+ } else {
+ d->connectionLists->orphaned = true;
+ }
+ d->connectionLists = 0;
+ }
+
+ // disconnect all senders
+ for (int i = 0; i < d->senders.count(); ++i) {
+ QObjectPrivate::Sender *s = &d->senders[i];
+ if (!s->sender)
+ continue;
+
+ QMutex *m = &s->sender->d_func()->threadData->mutex;
+ bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
+ s = &d->senders[i];
+ if (s->sender)
+ s->sender->d_func()->removeReceiver(s->signal, this);
+ if (needToUnlock)
+ m->unlock();
+ }
+
+ d->senders.clear();
+ }
+
+ if (d->pendTimer) {
+ // unregister pending timers
+ if (d->threadData->eventDispatcher)
+ d->threadData->eventDispatcher->unregisterTimers(this);
+ }
+
+#ifdef QT3_SUPPORT
+ d->pendingChildInsertedEvents.clear();
+#endif
+
+ d->eventFilters.clear();
+
+ if (!d->children.isEmpty())
+ d->deleteChildren();
+
+ qt_removeObject(this);
+
+ QMutexLocker locker2(&d->threadData->postEventList.mutex);
+ if (d->postedEvents > 0)
+ QCoreApplicationPrivate::removePostedEvents_unlocked(this, 0, d->threadData);
+ locker2.unlock();
+
+ if (d->parent) // remove it from parent object
+ d->setParent_helper(0);
+
+ d->threadData->deref();
+
+#ifdef QT_JAMBI_BUILD
+ if (d->inEventHandler) {
+ qWarning("QObject: Do not delete object, '%s', during its event handler!",
+ objectName().isNull() ? "unnamed" : qPrintable(objectName()));
+ }
+#endif
+
+ delete d;
+ d_ptr = 0;
+}
+
+
+/*!
+ \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.
+
+ 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
+
+ (\l QLayoutItem is not a QObject.)
+
+ Consider using qobject_cast<Type *>(object) instead. The method
+ is both faster and safer.
+
+ \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);
+ d->objectName = name;
+}
+
+
+#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:
+ {
+ d_func()->inEventHandler = false;
+ 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
+ try {
+ mce->placeMetaCall(this);
+ } catch (...) {
+ QObjectPrivate::resetCurrentSender(this, &currentSender, previousSender);
+ throw;
+ }
+#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",
+ d->threadData->thread, currentData->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->eventDispatcher->wakeUp();
+
+ // the current emitting thread shouldn't restore currentSender after calling moveToThread()
+ if (currentSender)
+ currentSender->ref = 0;
+ currentSender = 0;
+
+ // the current event thread also shouldn't restore the delete watch
+ inEventHandler = false;
+ if (deleteWatch)
+ *deleteWatch = 1;
+ deleteWatch = 0;
+
+ // 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
+
+ \warning This function is not available with MSVC 6. Use
+ qFindChild() instead if you need to support that version of the
+ compiler.
+
+ \sa findChildren(), qFindChild()
+*/
+
+/*!
+ \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
+
+ \warning This function is not available with MSVC 6. Use
+ qFindChildren() instead if you need to support that version of the
+ compiler.
+
+ \sa findChild(), qFindChildren()
+*/
+
+/*!
+ \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.
+
+ \warning This function is not available with MSVC 6. Use
+ qFindChildren() instead if you need to support that version of the
+ compiler.
+*/
+
+/*!
+ \fn T qFindChild(const QObject *obj, const QString &name)
+ \relates QObject
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). It is
+ provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ \sa QObject::findChild()
+*/
+
+/*!
+ \fn QList<T> qFindChildren(const QObject *obj, const QString &name)
+ \relates QObject
+
+ This function is equivalent to
+ \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). It is
+ provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ \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). It is
+ provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+*/
+
+/*!
+ \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). It is
+ provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ \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). It is
+ provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ \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 (parent->d_func()->pendingChildInsertedEvents.isEmpty()) {
+ QCoreApplication::postEvent(parent,
+ new QEvent(QEvent::ChildInsertedRequest),
+ Qt::HighEventPriority);
+ }
+ parent->d_func()->pendingChildInsertedEvents.append(q);
+#endif
+ }
+ }
+ }
+}
+
+/*!
+ \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.
+
+ See the sections below on Disambiguation and Handling Plurals for more
+ information about the optional \a disambiguation and \a n parameters.
+
+ QObject and its subclasses obtain translated strings from any translator
+ objects that have been installed on the application object; see the
+ QTranslator documentation for details about this mechanism.
+
+ A translatable string is referenced by its translation context;
+ this is the name of the QObject subclass whose tr() function is invoked,
+ as in the following example:
+
+ \snippet mainwindows/sdi/mainwindow.cpp implicit tr context
+ \dots
+
+ Here, the context is \c MainWindow because it is the \c MainWindow::tr()
+ function that is invoked. Translation contexts can be given explicitly
+ by fully qualifying the call to tr(); for example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp explicit tr context
+
+ This call obtains the translated text for "Page up" from the \c QScrollBar
+ context.
+
+ \section1 Defining Translation Contexts
+
+ The translation context for QObject and each QObject subclass is the
+ class name itself. Developers subclassing QObject must use the
+ Q_OBJECT macro in their class definition to override the translation
+ context. This macro sets the context to the name of the subclass.
+
+ If Q_OBJECT is not used in a class definition, the context will be
+ inherited from the base class. For example, since all QObject-based
+ classes in Qt provide a context, a new QWidget subclass defined without
+ a Q_OBJECT macro will use the "QWidget" context if its tr() function
+ is invoked.
+
+ \section1 Translator Comments
+
+ Developers can include information about each translatable string to
+ help translators with the translation process. These are extracted
+ when \l lupdate is used to process the source files. The recommended
+ way to add comments is to annotate the tr() calls in your code with
+ comments of the form:
+
+ \tt{//: ...}
+
+ or
+
+ \tt{/*: ... \starslash}
+
+ Examples:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 40
+
+ In these examples, the comments will be associated with the strings
+ passed to tr() in the context of each call.
+
+ \section1 Disambiguation
+
+ 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
+
+ \section1 Character Encodings
+
+ You can set the encoding for \a sourceText by calling QTextCodec::setCodecForTr().
+ By default \a sourceText is assumed to be in Latin-1 encoding.
+
+ \section1 Handling Plurals
+
+ If \a n >= 0, all occurrences of \c %n in the resulting string
+ are replaced with a decimal representation of \a n. In addition,
+ depending on \a n's value, the translation text may vary.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 18
+
+ The table below shows what string is returned depending on the
+ active translation:
+
+ \table
+ \header \o \o{3,1} Active Translation
+ \header \o \a n \o No Translation \o French \o English
+ \row \o 0 \o "0 message(s) saved" \o "0 message sauvegard\unicode{0xE9}" \o "0 message\bold{s} saved"
+ \row \o 1 \o "1 message(s) saved" \o "1 message sauvegard\unicode{0xE9}" \o "1 message saved"
+ \row \o 2 \o "2 message(s) saved" \o "2 message\bold{s} sauvegard\unicode{0xE9}\bold{s}" \o "2 message\bold{s} saved"
+ \row \o 37 \o "37 message(s) saved" \o "37 message\bold{s} sauvegard\unicode{0xE9}\bold{s}" \o "37 message\bold{s} saved"
+ \endtable
+
+ This idiom is more flexible than the traditional approach; e.g.,
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 19
+
+ because it also works with target languages that have several
+ plural forms (e.g., Irish has a special "dual" form that should
+ be used when \c n is 2), and it handles the \e n == 0 case
+ correctly for languages such as French that require the singular.
+ See the \l{Qt Linguist Manual} for details.
+
+ Instead of \c %n, you can use \c %Ln to produce a localized
+ representation of \a n. The conversion uses the default locale,
+ set using QLocale::setDefault(). (If no default locale was
+ specified, the "C" locale 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.
+
+ \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 ":"\0", loc ? loc : "\0");
+ else
+ qWarning("Object::%s: No such %s %s::%s%s%s",
+ func, type, object->metaObject()->className(), method+1,
+ loc ? " in ":"\0", loc ? loc : "\0");
+
+}
+
+
+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 QSignalMapper
+*/
+
+QObject *QObject::sender() const
+{
+ Q_D(const QObject);
+
+ QMutexLocker(&d->threadData->mutex);
+ if (!d->currentSender)
+ return 0;
+
+ // Return 0 if d->currentSender isn't in d->senders
+ bool found = false;
+ for (int i = 0; !found && i < d->senders.count(); ++i)
+ found = (d->senders.at(i).sender == d->currentSender->sender);
+ if (!found)
+ return 0;
+ return d->currentSender->sender;
+}
+
+/*!
+ 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
+{
+ 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
+ const QMetaObject *smeta = this->metaObject();
+ int signal_index = smeta->indexOfSignal(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(&d->threadData->mutex);
+ if (d->connectionLists) {
+ if (signal_index < d->connectionLists->count()) {
+ const QObjectPrivate::ConnectionList &connectionList =
+ d->connectionLists->at(signal_index);
+ for (int i = 0; i < connectionList.count(); ++i) {
+ const QObjectPrivate::Connection &c = connectionList.at(i);
+ receivers += c.receiver ? 1 : 0;
+ }
+ }
+ }
+ }
+ return receivers;
+}
+
+/*!
+ \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 an arbitrary order 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.
+
+ For every connection you make, a signal is emitted; two signals are emitted
+ for duplicate connections. You can break all of these connections with a
+ single disconnect() call.
+
+ 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 = smeta->indexOfSignal(signal);
+ if (signal_index < 0) {
+ // check for normalized signatures
+ tmp_signal_name = QMetaObject::normalizedSignature(signal - 1);
+ signal = tmp_signal_name.constData() + 1;
+
+ signal_index = smeta->indexOfSignal(signal);
+ if (signal_index < 0) {
+ err_method_notfound(sender, signal_arg, "connect");
+ err_info_about_objects("connect", sender, receiver);
+ return false;
+ }
+ }
+
+ 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 = -1;
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index = rmeta->indexOfSlot(method);
+ break;
+ case QSIGNAL_CODE:
+ method_index = rmeta->indexOfSignal(method);
+ break;
+ }
+ if (method_index < 0) {
+ // check for normalized methods
+ tmp_method_name = QMetaObject::normalizedSignature(method);
+ method = tmp_method_name.constData();
+ switch (membcode) {
+ case QSLOT_CODE:
+ method_index = rmeta->indexOfSlot(method);
+ break;
+ case QSIGNAL_CODE:
+ method_index = rmeta->indexOfSignal(method);
+ break;
+ }
+ }
+
+ if (method_index < 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 || type == Qt::BlockingQueuedConnection)
+ && !(types = queuedConnectionTypes(smeta->method(signal_index).parameterTypes())))
+ return false;
+
+#ifndef QT_NO_DEBUG
+ {
+ QMetaMethod smethod = smeta->method(signal_index);
+ QMetaMethod rmethod = rmeta->method(method_index);
+ if (warnCompat) {
+ if(smethod.attributes() & QMetaMethod::Compatibility) {
+ if (!(rmethod.attributes() & QMetaMethod::Compatibility))
+ qWarning("QObject::connect: Connecting from COMPAT signal (%s::%s)", smeta->className(), signal);
+ } else if(rmethod.attributes() & QMetaMethod::Compatibility && membcode != QSIGNAL_CODE) {
+ qWarning("QObject::connect: Connecting from %s::%s to COMPAT slot (%s::%s)",
+ smeta->className(), signal, rmeta->className(), method);
+ }
+ }
+ }
+#endif
+ QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);
+ const_cast<QObject*>(sender)->connectNotify(signal - 1);
+ 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) {
+ signal_name = QMetaObject::normalizedSignature(signal);
+ signal = signal_name;
+
+ 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) {
+ method_name = QMetaObject::normalizedSignature(method);
+ method = method_name;
+ 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 = smeta->indexOfSignal(signal);
+ if (signal_index < smeta->methodOffset())
+ continue;
+ signal_found = true;
+ }
+
+ if (!method) {
+ res |= QMetaObject::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 |= QMetaObject::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;
+}
+
+
+/*!
+ \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
+
+ \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)
+{
+ QObject *s = const_cast<QObject *>(sender);
+ QObject *r = const_cast<QObject *>(receiver);
+
+ QOrderedMutexLocker locker(&s->d_func()->threadData->mutex,
+ &r->d_func()->threadData->mutex);
+
+#if defined(Q_CC_HPACC) && defined(QT_ARCH_PARISC)
+ QObjectPrivate::Connection c;
+ c.receiver = r;
+ c.method = method_index;
+ c.connectionType = type;
+ c.argumentTypes = types;
+#else
+ QObjectPrivate::Connection c = { r, method_index, type, Q_BASIC_ATOMIC_INITIALIZER(types) };
+#endif
+ s->d_func()->addConnection(signal_index, &c);
+ r->d_func()->refSender(s, signal_index);
+
+ if (signal_index < 0)
+ sender->d_func()->connectedSignals = ~0u;
+ else if (signal_index < 32)
+ sender->d_func()->connectedSignals |= (1 << signal_index);
+
+ return true;
+}
+
+
+/*!\internal
+ */
+bool QMetaObject::disconnect(const QObject *sender, int signal_index,
+ const QObject *receiver, int method_index)
+{
+ if (!sender)
+ return false;
+
+ QObject *s = const_cast<QObject *>(sender);
+ QObject *r = const_cast<QObject *>(receiver);
+
+ QMutex *senderMutex = &s->d_func()->threadData->mutex;
+ QMutex *receiverMutex = r ? &r->d_func()->threadData->mutex : 0;
+ QOrderedMutexLocker locker(senderMutex, receiverMutex);
+
+ QObjectConnectionListVector *connectionLists = s->d_func()->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::ConnectionList &connectionList = (*connectionLists)[signal_index];
+ for (int i = 0; i < connectionList.count(); ++i) {
+ QObjectPrivate::Connection *c = &connectionList[i];
+ if (c->receiver
+ && (r == 0 || (c->receiver == r
+ && (method_index < 0 || c->method == method_index)))) {
+ QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ if (!receiverMutex && senderMutex != m) {
+ // need to relock this receiver and sender in the correct order
+ bool needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = &connectionList[i];
+ if (c->receiver)
+ c->receiver->d_func()->derefSender(s, signal_index);
+ if (needToUnlock)
+ m->unlock();
+ } else {
+ // no need to unlock
+ c->receiver->d_func()->derefSender(s, signal_index);
+ }
+ if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ qFree(c->argumentTypes);
+ c->argumentTypes = 0;
+ }
+ c->receiver = 0;
+
+ success = true;
+ connectionLists->dirty = true;
+ }
+ }
+ }
+ } else if (signal_index < connectionLists->count()) {
+ QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index];
+ for (int i = 0; i < connectionList.count(); ++i) {
+ QObjectPrivate::Connection *c = &connectionList[i];
+ if (c->receiver
+ && (r == 0 || (c->receiver == r
+ && (method_index < 0 || c->method == method_index)))) {
+ QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ if (!receiverMutex && senderMutex != m) {
+ // need to relock this receiver and sender in the correct order
+ bool needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = &connectionList[i];
+ if (c->receiver)
+ c->receiver->d_func()->derefSender(s, signal_index);
+ if (needToUnlock)
+ m->unlock();
+ } else {
+ // no need to unlock
+ c->receiver->d_func()->derefSender(s, signal_index);
+ }
+ if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ qFree(c->argumentTypes);
+ c->argumentTypes = 0;
+ }
+ c->receiver = 0;
+
+ 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 = qFindChildren<QObject *>(o, 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;
+ const QMetaObject *smo = co->metaObject();
+ int sigIndex = smo->indexOfMethod(slot + len + 4);
+ if (sigIndex < 0) { // search for compatible signals
+ int slotlen = qstrlen(slot + len + 4) - 1;
+ for (int k = 0; k < co->metaObject()->methodCount(); ++k) {
+ if (smo->method(k).methodType() != QMetaMethod::Signal)
+ continue;
+
+ if (!qstrncmp(smo->method(k).signature(), slot + len + 4, slotlen)) {
+ sigIndex = k;
+ break;
+ }
+ }
+ }
+ if (sigIndex < 0)
+ continue;
+ if (QMetaObject::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, const QObjectPrivate::Connection &c,
+ void **argv, QSemaphore *semaphore = 0)
+{
+ if (!c.argumentTypes || c.argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ QMetaMethod m = sender->metaObject()->method(signal);
+ QObjectPrivate::Connection &x = const_cast<QObjectPrivate::Connection &>(c);
+ int *tmp = queuedConnectionTypes(m.parameterTypes());
+ if (!tmp) // cannot queue arguments
+ tmp = &DIRECT_CONNECTION_ONLY;
+ if (!x.argumentTypes.testAndSetOrdered(0, tmp)) {
+ if (tmp != &DIRECT_CONNECTION_ONLY)
+ qFree(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));
+ void **args = (void **) qMalloc(nargs*sizeof(void *));
+ 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,
+ sender,
+ signal,
+ nargs,
+ types,
+ args,
+ semaphore));
+}
+
+static void blocking_activate(QObject *sender, int signal, const QObjectPrivate::Connection &c, void **argv)
+{
+ if (QThread::currentThread() == c.receiver->thread()) {
+ qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
+ "Sender is %s(%p), receiver is %s(%p)",
+ sender->metaObject()->className(), sender,
+ c.receiver->metaObject()->className(), c.receiver);
+ }
+
+#ifdef QT_NO_THREAD
+ queued_activate(sender, signal, c, argv);
+#else
+ QSemaphore semaphore;
+ queued_activate(sender, signal, c, argv, &semaphore);
+ QMutex *mutex = &QThreadData::get2(sender->thread())->mutex;
+ mutex->unlock();
+ semaphore.acquire();
+ mutex->lock();
+#endif
+}
+
+/*!\internal
+ */
+void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv)
+{
+ if (sender->d_func()->blockSig)
+ return;
+
+ void *empty_argv[] = { 0 };
+ if (qt_signal_spy_callback_set.signal_begin_callback != 0) {
+ qt_signal_spy_callback_set.signal_begin_callback(sender, from_signal_index,
+ argv ? argv : empty_argv);
+ }
+
+ QMutexLocker locker(&sender->d_func()->threadData->mutex);
+ QThreadData *currentThreadData = QThreadData::current();
+
+ QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
+ if (!connectionLists) {
+ if (qt_signal_spy_callback_set.signal_end_callback != 0)
+ qt_signal_spy_callback_set.signal_end_callback(sender, from_signal_index);
+ return;
+ }
+ ++connectionLists->inUse;
+
+ // emit signals in the following order: from_signal_index <= signals <= to_signal_index, signal < 0
+ for (int signal = from_signal_index;
+ (signal >= from_signal_index && signal <= to_signal_index) || (signal == -2);
+ (signal == to_signal_index ? signal = -2 : ++signal))
+ {
+ if (signal >= connectionLists->count()) {
+ signal = to_signal_index;
+ continue;
+ }
+ int count = connectionLists->at(signal).count();
+ for (int i = 0; i < count; ++i) {
+ const QObjectPrivate::Connection *c = &connectionLists->at(signal)[i];
+ if (!c->receiver)
+ continue;
+
+ QObject * const receiver = c->receiver;
+
+ // determine if this connection should be sent immediately or
+ // put into the event queue
+ if ((c->connectionType == Qt::AutoConnection
+ && (currentThreadData != sender->d_func()->threadData
+ || receiver->d_func()->threadData != sender->d_func()->threadData))
+ || (c->connectionType == Qt::QueuedConnection)) {
+ queued_activate(sender, signal, *c, argv);
+ continue;
+ } else if (c->connectionType == Qt::BlockingQueuedConnection) {
+ blocking_activate(sender, signal, *c, argv);
+ continue;
+ }
+
+ const int method = c->method;
+ QObjectPrivate::Sender currentSender;
+ currentSender.sender = sender;
+ currentSender.signal = signal < 0 ? from_signal_index : signal;
+ currentSender.ref = 1;
+ QObjectPrivate::Sender *previousSender = 0;
+ if (currentThreadData == receiver->d_func()->threadData)
+ previousSender = QObjectPrivate::setCurrentSender(receiver, &currentSender);
+ 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)
+ receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+#else
+ try {
+ receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv);
+ } catch (...) {
+ locker.relock();
+
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned && !connectionLists->inUse)
+ delete connectionLists;
+ throw;
+ }
+#endif
+
+ locker.relock();
+
+ if (qt_signal_spy_callback_set.slot_end_callback != 0)
+ qt_signal_spy_callback_set.slot_end_callback(receiver, method);
+
+ QObjectPrivate::resetCurrentSender(receiver, &currentSender, previousSender);
+
+ if (connectionLists->orphaned)
+ break;
+ }
+
+ if (connectionLists->orphaned)
+ break;
+ }
+
+ --connectionLists->inUse;
+ Q_ASSERT(connectionLists->inUse >= 0);
+ if (connectionLists->orphaned) {
+ if (!connectionLists->inUse)
+ delete connectionLists;
+ } else {
+ 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, from_signal_index);
+}
+
+
+/*!\internal
+ */
+void QMetaObject::activate(QObject *sender, int signal_index, void **argv)
+{
+ if (signal_index < 32
+ && !qt_signal_spy_callback_set.signal_begin_callback
+ && !qt_signal_spy_callback_set.signal_end_callback) {
+ uint signal_mask = 1 << signal_index;
+ if ((sender->d_func()->connectedSignals & signal_mask) == 0)
+ // nothing connected to these signals, and no spy
+ return;
+ }
+ activate(sender, signal_index, signal_index, argv);
+}
+
+/*!\internal
+ */
+void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_signal_index,
+ void **argv)
+{
+ int signal_index = m->methodOffset() + local_signal_index;
+ if (signal_index < 32
+ && !qt_signal_spy_callback_set.signal_begin_callback
+ && !qt_signal_spy_callback_set.signal_end_callback) {
+ uint signal_mask = 1 << signal_index;
+ if ((sender->d_func()->connectedSignals & signal_mask) == 0)
+ // nothing connected to these signals, and no spy
+ return;
+ }
+ activate(sender, signal_index, signal_index, argv);
+}
+
+/*!\internal
+ */
+void QMetaObject::activate(QObject *sender, const QMetaObject *m,
+ int from_local_signal_index, int to_local_signal_index, void **argv)
+{
+ int offset = m->methodOffset();
+ int from_signal_index = offset + from_local_signal_index;
+ int to_signal_index = offset + to_local_signal_index;
+ if (to_signal_index < 32
+ && !qt_signal_spy_callback_set.signal_begin_callback
+ && !qt_signal_spy_callback_set.signal_end_callback) {
+ uint signal_mask = (1 << (to_signal_index + 1)) - 1;
+ signal_mask ^= (1 << from_signal_index) - 1;
+ if ((sender->d_func()->connectedSignals & signal_mask) == 0)
+ // nothing connected to these signals, and no spy
+ return;
+ }
+ activate(sender, from_signal_index, to_signal_index, argv);
+}
+
+
+/*****************************************************************************
+ 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(&d->threadData->mutex);
+
+ // first, look for connections where this object is the sender
+ qDebug(" SIGNALS OUT");
+
+ if (d->connectionLists) {
+ for (int signal_index = 0; signal_index < d->connectionLists->count(); ++signal_index) {
+ const QMetaMethod signal = metaObject()->method(signal_index);
+ qDebug(" signal: %s", signal.signature());
+
+ // receivers
+ const QObjectPrivate::ConnectionList &connectionList = d->connectionLists->at(signal_index);
+ for (int i = 0; i < connectionList.count(); ++i) {
+ const QObjectPrivate::Connection &c = connectionList.at(i);
+ if (!c.receiver) {
+ qDebug(" <Disconnected receiver>");
+ 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());
+ }
+ }
+ } else {
+ qDebug( " <None>" );
+ }
+
+ // now look for connections where this object is the receiver
+ qDebug(" SIGNALS IN");
+
+ if (!d->senders.isEmpty()) {
+ for (int i = 0; i < d->senders.count(); ++i) {
+ const QObjectPrivate::Sender &s = d->senders.at(i);
+ const QMetaObject *senderMetaObject = s.sender->metaObject();
+ const QMetaMethod signal = senderMetaObject->method(s.signal);
+ qDebug(" <-- %s::%s %s",
+ senderMetaObject->className(),
+ s.sender->objectName().isEmpty() ? "unnamed" : qPrintable(s.sender->objectName()),
+ signal.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.
+
+ Example:
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qobject.cpp 39
+
+ \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 *>.
+*/
+
+#ifdef QT_JAMBI_BUILD
+class QDPtrAccessor : public QObject {
+public:
+ QObjectData *d() const { return d_ptr; }
+};
+#endif
+
+void qDeleteInEventHandler(QObject *o)
+{
+#ifdef QT_JAMBI_BUILD
+ if (!o)
+ return;
+ ((QDPtrAccessor *) o)->d()->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..dbec0a6b1a
--- /dev/null
+++ b/src/corelib/kernel/qobject.h
@@ -0,0 +1,480 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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
+
+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;
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+template<typename T> inline T qFindChild(const QObject *o, const QString &name = QString(), T = 0);
+template<typename T> inline QList<T> qFindChildren(const QObject *o, const QString &name = QString(), T = 0);
+# ifndef QT_NO_REGEXP
+template<typename T> inline QList<T> qFindChildren(const QObject *o, const QRegExp &re, T = 0);
+# endif
+#else
+template<typename T> inline T qFindChild(const QObject *, const QString & = QString());
+template<typename T> inline QList<T> qFindChildren(const QObject *, const QString & = QString());
+# ifndef QT_NO_REGEXP
+template<typename T> inline QList<T> qFindChildren(const QObject *, const QRegExp &);
+# endif
+#endif
+
+class 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;
+ uint inThreadChangeEvent : 1;
+ uint unused : 23;
+ int postedEvents;
+};
+
+
+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);
+
+#ifndef QT_NO_MEMBER_TEMPLATES
+ template<typename T>
+ inline T findChild(const QString &aName = QString()) const
+ { return qFindChild<T>(this, aName); }
+
+ template<typename T>
+ inline QList<T> findChildren(const QString &aName = QString()) const
+ { return qFindChildren<T>(this, aName); }
+
+#ifndef QT_NO_REGEXP
+ template<typename T>
+ inline QList<T> findChildren(const QRegExp &re) const
+ { return qFindChildren<T>(this, re); }
+#endif
+#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
+ );
+ 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);
+ 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 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:
+ 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
+
+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);
+
+#if defined Q_CC_MSVC && _MSC_VER < 1300
+
+template<typename T>
+inline T qFindChild(const QObject *o, const QString &name, T)
+{ return static_cast<T>(qt_qFindChild_helper(o, name, ((T)0)->staticMetaObject)); }
+
+template<typename T>
+inline QList<T> qFindChildren(const QObject *o, const QString &name, T)
+{
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(o, name, 0, ((T)0)->staticMetaObject, u.voidList);
+ return list;
+}
+
+template<typename T>
+inline T qFindChild(const QObject *o, const QString &name)
+{ return qFindChild<T>(o, name, T(0)); }
+
+template<typename T>
+inline T qFindChild(const QObject *o)
+{ return qFindChild<T>(o, QString(), T(0)); }
+
+template<typename T>
+inline QList<T> qFindChildren(const QObject *o, const QString &name)
+{ return qFindChildren<T>(o, name, T(0)); }
+
+template<typename T>
+inline QList<T> qFindChildren(const QObject *o)
+{ return qFindChildren<T>(o, QString(), T(0)); }
+
+#ifndef QT_NO_REGEXP
+template<typename T>
+inline QList<T> qFindChildren(const QObject *o, const QRegExp &re, T)
+{
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(o, 0, &re, ((T)0)->staticMetaObject, u.voidList);
+ return list;
+}
+
+template<typename T>
+inline QList<T> qFindChildren(const QObject *o, const QRegExp &re)
+{ return qFindChildren<T>(o, re, T(0)); }
+
+#endif
+
+#ifdef Q_MOC_RUN
+# define Q_DECLARE_INTERFACE(IFace, IId) Q_DECLARE_INTERFACE(IFace, IId)
+#endif // Q_MOC_RUN
+
+
+template <class T> inline T qobject_cast_helper(QObject *object, T)
+{ return static_cast<T>(((T)0)->staticMetaObject.cast(object)); }
+
+template <class T> inline T qobject_cast_helper(const QObject *object, T)
+{ return static_cast<T>(const_cast<const QObject *>(((T)0)->staticMetaObject.cast(const_cast<QObject *>(object)))); }
+
+template <class T>
+inline T qobject_cast(QObject *object)
+{ return qobject_cast_helper<T>(object, T(0)); }
+
+template <class T>
+inline T qobject_cast(const QObject *object)
+{ return qobject_cast_helper<T>(object, T(0)); }
+
+#ifndef Q_MOC_RUN
+# define Q_DECLARE_INTERFACE(IFace, IId) \
+ template <> inline IFace *qobject_cast_helper<IFace *>(QObject *object, IFace *) \
+ { return (IFace *)(object ? object->qt_metacast(IId) : 0); } \
+ template <> inline IFace *qobject_cast_helper<IFace *>(const QObject *object, IFace *) \
+ { return (IFace *)(object ? const_cast<QObject *>(object)->qt_metacast(IId) : 0); }
+#endif // Q_MOC_RUN
+
+#else
+
+template<typename T>
+inline T qFindChild(const QObject *o, const QString &name)
+{ return static_cast<T>(qt_qFindChild_helper(o, name, reinterpret_cast<T>(0)->staticMetaObject)); }
+
+template<typename T>
+inline QList<T> qFindChildren(const QObject *o, const QString &name)
+{
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(o, name, 0, reinterpret_cast<T>(0)->staticMetaObject, u.voidList);
+ return list;
+}
+
+#ifndef QT_NO_REGEXP
+template<typename T>
+inline QList<T> qFindChildren(const QObject *o, const QRegExp &re)
+{
+ QList<T> list;
+ union {
+ QList<T> *typedList;
+ QList<void *> *voidList;
+ } u;
+ u.typedList = &list;
+ qt_qFindChildren_helper(o, QString(), &re, reinterpret_cast<T>(0)->staticMetaObject, u.voidList);
+ return list;
+}
+#endif
+
+template <class T>
+inline T qobject_cast(QObject *object)
+{
+#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)
+ reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(object));
+#endif
+ return static_cast<T>(reinterpret_cast<T>(0)->staticMetaObject.cast(object));
+}
+
+template <class T>
+inline T qobject_cast(const QObject *object)
+{
+ // this will cause a compilation error if T is not const
+ register T ptr = static_cast<T>(object);
+ Q_UNUSED(ptr);
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) && !defined(QT_NO_QOBJECT_CHECK)
+ reinterpret_cast<T>(0)->qt_check_for_QOBJECT_macro(*reinterpret_cast<T>(const_cast<QObject *>(object)));
+#endif
+ return static_cast<T>(const_cast<QObject *>(reinterpret_cast<T>(0)->staticMetaObject.cast(const_cast<QObject *>(object))));
+}
+
+
+#ifndef Q_MOC_RUN
+# define Q_DECLARE_INTERFACE(IFace, 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
+
+#endif
+
+#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..b324334d0f
--- /dev/null
+++ b/src/corelib/kernel/qobject_p.h
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/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;
+
+/* 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;
+
+inline QObjectData::~QObjectData() {}
+
+enum { QObjectPrivateVersion = QT_VERSION };
+
+class Q_CORE_EXPORT QObjectPrivate : public QObjectData
+{
+ Q_DECLARE_PUBLIC(QObject)
+
+public:
+ QObjectPrivate(int version = QObjectPrivateVersion);
+ virtual ~QObjectPrivate();
+
+#ifdef QT3_SUPPORT
+ QList<QObject *> pendingChildInsertedEvents;
+ void sendPendingChildInsertedEvents();
+ void removePendingChildInsertedEvents(QObject *child);
+#else
+ // preserve binary compatibility with code compiled without Qt 3 support
+ QList<QObject *> unused;
+#endif
+
+ // id of the thread that owns the object
+ QThreadData *threadData;
+ void moveToThread_helper();
+ void setThreadData_helper(QThreadData *currentData, QThreadData *targetData);
+ void _q_reregisterTimers(void *pointer);
+
+ struct Sender
+ {
+ QObject *sender;
+ int signal;
+ int ref;
+ };
+
+ // object currently activating the object
+ Sender *currentSender;
+
+ QObject *currentChildBeingDeleted;
+
+ bool isSender(const QObject *receiver, const char *signal) const;
+ QObjectList receiverList(const char *signal) const;
+ QObjectList senderList() const;
+
+ QList<QPointer<QObject> > eventFilters;
+
+ void setParent_helper(QObject *);
+
+ void deleteChildren();
+
+ static void clearGuards(QObject *);
+
+ struct ExtraData
+ {
+#ifndef QT_NO_USERDATA
+ QVector<QObjectUserData *> userData;
+#endif
+ QList<QByteArray> propertyNames;
+ QList<QVariant> propertyValues;
+ };
+ ExtraData *extraData;
+ mutable quint32 connectedSignals;
+
+ QString objectName;
+
+ // Note: you must hold the signalSlotLock() before accessing the lists below or calling the functions
+ struct Connection
+ {
+ QObject *receiver;
+ int method;
+ uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
+ QBasicAtomicPointer<int> argumentTypes;
+ };
+ typedef QList<Connection> ConnectionList;
+
+ QObjectConnectionListVector *connectionLists;
+ void addConnection(int signal, Connection *c);
+ void removeReceiver(int signal, QObject *receiver);
+ void cleanConnectionLists();
+
+ QList<Sender> senders;
+ void refSender(QObject *sender, int signal);
+ void derefSender(QObject *sender, int signal);
+ void removeSender(QObject *sender, int signal);
+
+ static Sender *setCurrentSender(QObject *receiver,
+ Sender *sender);
+ static void resetCurrentSender(QObject *receiver,
+ Sender *currentSender,
+ Sender *previousSender);
+ static int *setDeleteWatch(QObjectPrivate *d, int *newWatch);
+ static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch);
+
+ int *deleteWatch;
+
+ static QObjectPrivate *get(QObject *o) {
+ return o->d_func();
+ }
+};
+
+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(int id, const QObject *sender, int signalId,
+ int nargs = 0, int *types = 0, void **args = 0, QSemaphore *semaphore = 0);
+ ~QMetaCallEvent();
+
+ inline int id() const { return id_; }
+ inline const QObject *sender() const { return sender_; }
+ inline int signalId() const { return signalId_; }
+ inline void **args() const { return args_; }
+
+ virtual int placeMetaCall(QObject *object);
+
+private:
+ int id_;
+ const QObject *sender_;
+ int signalId_;
+ int nargs_;
+ int *types_;
+ void **args_;
+ QSemaphore *semaphore_;
+};
+
+class Q_CORE_EXPORT 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);
+
+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..d2241ad186
--- /dev/null
+++ b/src/corelib/kernel/qobjectcleanuphandler.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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..67db5d3389
--- /dev/null
+++ b/src/corelib/kernel/qobjectcleanuphandler.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..3a22323aaa
--- /dev/null
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -0,0 +1,465 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 61
+#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_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_MEMBER_TEMPLATES) || 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_MEMBER_TEMPLATES
+
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT \
+public: \
+ Q_OBJECT_CHECK \
+ static const QMetaObject staticMetaObject; \
+ virtual const QMetaObject *metaObject() const; \
+ virtual void *qt_metacast(const char *); \
+ QT_TR_FUNCTIONS \
+ virtual int qt_metacall(QMetaObject::Call, int, void **); \
+private:
+/* tmake ignore Q_OBJECT */
+#define Q_OBJECT_FAKE Q_OBJECT
+/* tmake ignore Q_GADGET */
+#define Q_GADGET \
+public: \
+ static const QMetaObject staticMetaObject; \
+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_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__)
+# define METHOD(a) qFlagLocation("0"#a QLOCATION)
+# define SLOT(a) qFlagLocation("1"#a QLOCATION)
+# define SIGNAL(a) qFlagLocation("2"#a QLOCATION)
+#else
+# define METHOD(a) "0"#a
+# 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 <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;
+
+#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);
+ // 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);
+ static void activate(QObject *sender, int from_signal_index, int to_signal_index, void **argv);
+ 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);
+ // 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;
+
+#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;
+};
+
+struct QMetaObjectExtraData
+{
+ const QMetaObject **objects;
+ int (*static_metacall)(QMetaObject::Call, int, void **);
+};
+
+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..99a8e4b421
--- /dev/null
+++ b/src/corelib/kernel/qpointer.cpp
@@ -0,0 +1,260 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPointer
+ \brief The QPointer class is a template class that provides guarded pointers to QObjects.
+
+ \ingroup objectmodel
+ \mainclass
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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)
+
+ 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..ec4a623c30
--- /dev/null
+++ b/src/corelib/kernel/qpointer.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..98530798b2
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -0,0 +1,541 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdir.h>
+#include <qcryptographichash.h>
+
+#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
+ */
+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;
+#else
+ return QDir::tempPath() + QLatin1Char('/') + result;
+#endif
+}
+#endif // QT_NO_SHAREDMEMORY && QT_NO_SHAREDMEMORY
+
+#ifndef QT_NO_SHAREDMEMORY
+
+/*!
+ \class QSharedMemory
+ \ingroup ipc
+ \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.
+
+ \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.
+ */
+
+/*!
+ \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() 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 a new \a key for this shared memory object. If \a key and the
+ current key are the same, the function returns without doing
+ anything. 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() isAttached()
+ */
+void QSharedMemory::setKey(const QString &key)
+{
+ Q_D(QSharedMemory);
+ if (key == d->key)
+ return;
+
+ if (isAttached())
+ detach();
+ d->cleanHandle();
+ d->key = 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 to this shared memory. The key is the
+ identifier used by the operating system to identify the shared
+ memory segment. When QSharedMemory is used for interprocess
+ communication, the key is how each process attaches to the shared
+ memory segment through which the IPC occurs.
+
+ \sa setKey()
+ */
+QString QSharedMemory::key() const
+{
+ Q_D(const QSharedMemory);
+ return d->key;
+}
+
+/*!
+ Creates a shared memory segment of \a size bytes with the key passed
+ to the constructor or set with setKey(), 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->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(). 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->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->tryLocker(&lock, QLatin1String("QSharedMemory::detach")))
+ return false;
+#endif
+
+ if (d->detach()) {
+ d->size = 0;
+ return true;
+ }
+ return false;
+}
+
+/*!
+ 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 either that you have ignored a false return from create()
+ or attach(), 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..481a8153cb
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory.h
@@ -0,0 +1,119 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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;
+
+ 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..08f0321ad8
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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>
+#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;
+ 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();
+
+ void setErrorString(const QString &function);
+
+#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;
+#else
+ key_t unix_key;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SHAREDMEMORY
+
+#endif // QSHAREDMEMORY_P_H
+
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
new file mode 100644
index 0000000000..487c6530dd
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qsharedmemory.h"
+#include "qsharedmemory_p.h"
+#include "qsystemsemaphore.h"
+#include <qdir.h>
+#include <qdebug.h>
+
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+#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>
+
+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 exists").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 (key.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
+ QString fileName = makePlatformSafeKey(key);
+ if (!QFile::exists(fileName)) {
+ errorString = QSharedMemory::tr("%1: unix key file doesn't exists").arg(QLatin1String("QSharedMemory::handle:"));
+ error = QSharedMemory::NotFound;
+ return 0;
+ }
+
+ unix_key = ftok(QFile::encodeName(fileName).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 = 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(makePlatformSafeKey(key));
+ 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(makePlatformSafeKey(key));
+ return false;
+ }
+
+ // create
+ if (-1 == shmget(handle(), 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(makePlatformSafeKey(key));
+ return false;
+ }
+
+ return true;
+}
+
+bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode)
+{
+ // grab the shared memory segment id
+ if (!handle())
+ return false;
+
+ int id = shmget(handle(), 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660));
+ 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;
+
+ // Get the number of current attachments
+ if (!handle())
+ return false;
+ int id = shmget(handle(), 0, 0444);
+ unix_key = 0;
+
+ 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
+ struct shmid_ds shmid_ds;
+ 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(makePlatformSafeKey(key)))
+ 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..b71fbd023a
--- /dev/null
+++ b/src/corelib/kernel/qsharedmemory_win.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 exists").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");
+ QString safeKey = makePlatformSafeKey(key);
+ if (safeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: unable to make key").arg(function);
+ return false;
+ }
+#ifndef Q_OS_WINCE
+ QT_WA({
+ hand = OpenFileMappingW(FILE_MAP_ALL_ACCESS, false, (TCHAR*)safeKey.utf16());
+ }, {
+ hand = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, safeKey.toLocal8Bit().constData());
+ });
+#else
+ // This works for opening a mapping too, but always opens it with read/write access in
+ // attach as it seems.
+ hand = CreateFileMappingW(INVALID_HANDLE_VALUE,
+ 0, PAGE_READWRITE, 0, 0, (TCHAR*)safeKey.utf16());
+#endif
+ if (!hand) {
+ setErrorString(function);
+ return false;
+ }
+ }
+ return hand;
+}
+
+bool QSharedMemoryPrivate::cleanHandle()
+{
+ if (hand != 0 && !CloseHandle(hand)) {
+ hand = 0;
+ return false;
+ setErrorString(QLatin1String("QSharedMemory::cleanHandle"));
+ }
+ hand = 0;
+ return true;
+}
+
+bool QSharedMemoryPrivate::create(int size)
+{
+ // Get a windows acceptable key
+ QString safeKey = makePlatformSafeKey(key);
+ QString function = QLatin1String("QSharedMemory::create");
+ if (safeKey.isEmpty()) {
+ error = QSharedMemory::KeyError;
+ errorString = QSharedMemory::tr("%1: key error").arg(function);
+ return false;
+ }
+
+ // Create the file mapping.
+ QT_WA( {
+ hand = CreateFileMappingW(INVALID_HANDLE_VALUE,
+ 0, PAGE_READWRITE, 0, size, (TCHAR*)safeKey.utf16());
+ }, {
+ hand = CreateFileMappingA(INVALID_HANDLE_VALUE,
+ 0, PAGE_READWRITE, 0, size, safeKey.toLocal8Bit().constData());
+ } );
+ 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;
+
+ // 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..23c6ba7a8e
--- /dev/null
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -0,0 +1,321 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 io
+ \mainclass
+
+ 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..ab84b5619a
--- /dev/null
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..0ff9c8e124
--- /dev/null
+++ b/src/corelib/kernel/qsocketnotifier.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 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..b1fa290f0e
--- /dev/null
+++ b/src/corelib/kernel/qsocketnotifier.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp
new file mode 100644
index 0000000000..e8426b3698
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsystemsemaphore.h"
+#include "qsystemsemaphore_p.h"
+#include <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_SYSTEMSEMAPHORE
+
+/*!
+ \class QSystemSemaphore
+ \ingroup ipc
+ \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.
+ \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, \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();
+ delete d;
+}
+
+/*!
+ \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, 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, 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();
+#ifndef Q_OS_WIN
+ // 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..5a02072982
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSYSTEMSEMAPHORE_H
+#define QSYSTEMSEMAPHORE_H
+
+#include <QtCore/qstring.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)
+ 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..81d4f10d5e
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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
+
+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);
+#else
+ key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open);
+#endif
+ void setErrorString(const QString &function);
+ void cleanHandle();
+ bool modifySemaphore(int count);
+
+ QString key;
+ QString fileName;
+ int initialValue;
+#ifdef Q_OS_WIN
+ HANDLE semaphore;
+ HANDLE semaphoreLock;
+#else
+ int semaphore;
+ bool createdFile;
+ bool createdSemaphore;
+ key_t unix_key;
+#endif
+
+ QString errorString;
+ QSystemSemaphore::SystemSemaphoreError error;
+};
+
+#endif // QT_NO_SYSTEMSEMAPHORE
+
+
+QT_END_NAMESPACE
+#endif // QSYSTEMSEMAPHORE_P_H
+
diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp
new file mode 100644
index 0000000000..a7802eefe4
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp
@@ -0,0 +1,242 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 <fcntl.h>
+#include <errno.h>
+#include <sys/shm.h>
+
+#include <sys/sem.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
+
+// We have to define this as on some sem.h will have it
+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 */
+};
+
+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;
+ if (-1 == semop(semaphore, &operation, 1)) {
+ // 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..59123449f9
--- /dev/null
+++ b/src/corelib/kernel/qsystemsemaphore_win.cpp
@@ -0,0 +1,140 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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) {
+ QString safeName = makeKeyFileName();
+ QT_WA({
+ semaphore = CreateSemaphoreW(0, initialValue, MAXLONG, (TCHAR*)safeName.utf16());
+ }, {
+ semaphore = CreateSemaphoreA(0, initialValue, MAXLONG, safeName.toLocal8Bit().constData());
+ });
+ 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/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
new file mode 100644
index 0000000000..01e81abcd3
--- /dev/null
+++ b/src/corelib/kernel/qtimer.cpp
@@ -0,0 +1,372 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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 time
+ \ingroup events
+ \mainclass
+
+ 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 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.
+
+ Note that QTimer's accuracy depends on the underlying operating
+ system and hardware. Most platforms support an accuracy of
+ 1 millisecond, but Windows 98 supports only 55. If Qt is
+ unable to deliver the requested number of timer clicks, it will
+ silently discard some.
+
+ 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)
+{
+ setInterval(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);
+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)
+ (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..26afe2d01b
--- /dev/null
+++ b/src/corelib/kernel/qtimer.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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..cdddf3626a
--- /dev/null
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -0,0 +1,827 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+
+#include "qtranslator.h"
+
+#ifndef QT_NO_TRANSLATION
+
+#include "qfileinfo.h"
+#include "qstring.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"
+
+#if defined(Q_OS_UNIX)
+#define QT_USE_MMAP
+#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;
+ // 0 means anything, "" means empty
+ return !found || (qstrncmp((const char *)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;
+ }
+
+ 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;
+}
+
+extern bool qt_detectRTLLanguage();
+
+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 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
+ \ingroup environment
+ \mainclass
+
+ 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::instance()->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.
+
+ 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())
+ break;
+
+ realname = prefix + fname;
+ fi.setFile(realname);
+ if (fi.isReadable())
+ 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.
+
+ 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);
+}
+
+/*!
+ \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::fromUtf16((const ushort *)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(sourceText) + comment);
+
+ 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));
+}
+
+/*!
+ \since 4.5
+
+ 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.
+*/
+
+#endif // QT_NO_TRANSLATION
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qtranslator.h b/src/corelib/kernel/qtranslator.h
new file mode 100644
index 0000000000..08eb99418d
--- /dev/null
+++ b/src/corelib/kernel/qtranslator.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 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 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..77ec8f5eb6
--- /dev/null
+++ b/src/corelib/kernel/qtranslator_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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_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..b4427c05a8
--- /dev/null
+++ b/src/corelib/kernel/qvariant.cpp
@@ -0,0 +1,3098 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvariant.h"
+#include "qbitarray.h"
+#include "qbytearray.h"
+#include "qdatastream.h"
+#include "qdebug.h"
+#include "qmap.h"
+#include "qdatetime.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 const void *constDataHelper(const QVariant::Private &d)
+{
+ switch (d.type) {
+ case QVariant::Int:
+ return &d.data.i;
+ case QVariant::UInt:
+ return &d.data.u;
+ case QVariant::Bool:
+ return &d.data.b;
+ case QVariant::LongLong:
+ return &d.data.ll;
+ case QVariant::ULongLong:
+ return &d.data.ull;
+ case QVariant::Double:
+ return &d.data.d;
+ default:
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
+ }
+}
+
+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
+ 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 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:
+ x->is_shared = true;
+ x->data.shared = new QVariant::PrivateShared(QMetaType::construct(x->type, copy));
+ if (!x->data.shared->ptr)
+ x->type = QVariant::Invalid;
+ 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
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Double:
+ 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
+ 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:
+ 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 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);
+ 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);
+
+ /* 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);
+ if (typeName[qstrlen(typeName) - 1] == '*')
+ return *static_cast<void **>(a->data.shared->ptr) ==
+ *static_cast<void **>(b->data.shared->ptr);
+
+ return a->data.shared->ptr == b->data.shared->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(*static_cast<float *>(d->data.shared->ptr));
+ 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::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(*static_cast<float *>(d->data.shared->ptr), '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;
+ 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(*static_cast<float *>(d->data.shared->ptr), '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 = *static_cast<float *>(d->data.shared->ptr);
+ 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:
+#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
+ *f = (double)(qlonglong)qMetaTypeUNumber(d);
+#else
+ *f = double(qMetaTypeUNumber(d));
+#endif
+ break;
+ default:
+ *f = 0.0;
+ return false;
+ }
+ break;
+ }
+ case QMetaType::Float: {
+ float *f = static_cast<float *>(result);
+ switch (d->type) {
+ case QVariant::String:
+ *f = float(v_cast<QString>(d)->toDouble(ok));
+ break;
+ case QVariant::ByteArray:
+ *f = float(v_cast<QByteArray>(d)->toDouble(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:
+#if defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET)
+ *f = (float)(qlonglong)qMetaTypeUNumber(d);
+#else
+ *f = float(qMetaTypeUNumber(d));
+#endif
+ 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.type()) {
+ 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 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;
+ 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 misc
+ \ingroup shared
+ \mainclass
+
+ 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 have
+ a defined type with no 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 qVariantValue() 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 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 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 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 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 qVariantFromValue()
+ instead to construct variants from the pointer types represented by
+ \c QMetaType::VoidStar, \c QMetaType::QObjectStar and
+ \c QMetaType::QWidgetStar.
+
+ \sa qVariantFromValue(), 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.type > Char && (!d.is_shared || !d.data.shared->ref.deref()))
+ 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) {
+ 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.
+*/
+
+/*!
+ \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(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; }
+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)
+{ create(ByteArray, &val); }
+QVariant::QVariant(const QBitArray &val)
+{ create(BitArray, &val); }
+QVariant::QVariant(const QString &val)
+{ create(String, &val); }
+QVariant::QVariant(const QChar &val)
+{ create (Char, &val); }
+QVariant::QVariant(const QLatin1String &val)
+{ QString str(val); create(String, &str); }
+QVariant::QVariant(const QStringList &val)
+{ create(StringList, &val); }
+
+QVariant::QVariant(const QDate &val)
+{ create(Date, &val); }
+QVariant::QVariant(const QTime &val)
+{ create(Time, &val); }
+QVariant::QVariant(const QDateTime &val)
+{ create(DateTime, &val); }
+QVariant::QVariant(const QList<QVariant> &list)
+{ create(List, &list); }
+QVariant::QVariant(const QMap<QString, QVariant> &map)
+{ create(Map, &map); }
+QVariant::QVariant(const QHash<QString, QVariant> &hash)
+{ create(Hash, &hash); }
+#ifndef QT_NO_GEOM_VARIANT
+QVariant::QVariant(const QPoint &pt) { create(Point, &pt); }
+QVariant::QVariant(const QPointF &pt) { create (PointF, &pt); }
+QVariant::QVariant(const QRectF &r) { create (RectF, &r); }
+QVariant::QVariant(const QLineF &l) { create (LineF, &l); }
+QVariant::QVariant(const QLine &l) { create (Line, &l); }
+QVariant::QVariant(const QRect &r) { create(Rect, &r); }
+QVariant::QVariant(const QSize &s) { create(Size, &s); }
+QVariant::QVariant(const QSizeF &s) { create(SizeF, &s); }
+#endif
+QVariant::QVariant(const QUrl &u) { create(Url, &u); }
+QVariant::QVariant(const QLocale &l) { create(Locale, &l); }
+#ifndef QT_NO_REGEXP
+QVariant::QVariant(const QRegExp &regExp) { create(RegExp, &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::QTransform.
+
+ 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) {
+ 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::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())
+ 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 = 35 };
+static const uint 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
+};
+
+/*!
+ 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 (d.type == QVariant::Invalid) {
+ // 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 *>(constDataHelper(d)))) {
+ 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 (d.type == QVariant::Invalid) {
+ s << QString();
+ return;
+ }
+
+ if (!QMetaType::save(s, d.type, constDataHelper(d))) {
+ 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);
+}
+
+/*!
+ \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, QVariant::Type t,
+ const QVariant::Handler *handler, bool *ok, const T& val)
+{
+ if (ok)
+ *ok = true;
+ if (d.type == t)
+ return val;
+
+ T ret;
+ if (!handler->convert(&d, 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, Int, 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, UInt, 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, LongLong, 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, ULongLong, 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 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, Double, handler, ok, d.data.d);
+}
+
+/*!
+ 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,
+
+/*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*/ 0,
+
+/*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
+
+};
+
+/*!
+ 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
+{
+ if (d.type == uint(t))
+ return true;
+
+ if (d.type > QVariant::LastCoreType || t > QVariant::LastCoreType) {
+ switch (uint(t)) {
+ case QVariant::Int:
+ return d.type == QVariant::KeySequence
+ || d.type == QMetaType::ULong
+ || d.type == QMetaType::Long
+ || d.type == QMetaType::UShort
+ || d.type == QMetaType::UChar
+ || d.type == QMetaType::Char
+ || d.type == QMetaType::Short;
+ case QVariant::Image:
+ return d.type == QVariant::Pixmap || d.type == QVariant::Bitmap;
+ case QVariant::Pixmap:
+ return d.type == QVariant::Image || d.type == QVariant::Bitmap
+ || d.type == QVariant::Brush;
+ case QVariant::Bitmap:
+ return d.type == QVariant::Pixmap || d.type == QVariant::Image;
+ case QVariant::ByteArray:
+ return d.type == QVariant::Color;
+ case QVariant::String:
+ return d.type == QVariant::KeySequence || d.type == QVariant::Font
+ || d.type == QVariant::Color;
+ case QVariant::KeySequence:
+ return d.type == QVariant::String || d.type == QVariant::Int;
+ case QVariant::Font:
+ return d.type == QVariant::String;
+ case QVariant::Color:
+ return d.type == QVariant::String || d.type == QVariant::ByteArray
+ || d.type == QVariant::Brush;
+ case QVariant::Brush:
+ return d.type == QVariant::Color || d.type == QVariant::Pixmap;
+ case QMetaType::Long:
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ case QMetaType::ULong:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::Float:
+ return qCanConvertMatrix[QVariant::Int] & (1 << d.type) || d.type == QVariant::Int;
+ default:
+ return false;
+ }
+ }
+
+ if(t == String && d.type == StringList)
+ return v_cast<QStringList>(&d)->count() == 1;
+ else
+ return qCanConvertMatrix[t] & (1 << d.type);
+}
+
+/*!
+ 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(toDouble(), v.toDouble());
+ 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 constDataHelper(d);
+}
+
+/*!
+ \fn const void* QVariant::data() const
+
+ \internal
+*/
+
+/*! \internal */
+void* QVariant::data()
+{
+ detach();
+ return const_cast<void *>(constDataHelper(d));
+}
+
+
+#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
+
+ \warning This function is not available with MSVC 6. Use
+ qVariantSetValue() instead if you need to support that version of
+ the compiler.
+
+ \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
+
+ \warning This function is not available with MSVC 6. Use
+ qVariantValue() or qvariant_cast() instead if you need to support
+ that version of the compiler.
+
+ \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
+
+ \warning This function is not available with MSVC 6. Use
+ qVariantCanConvert() instead if you need to support that version
+ of the compiler.
+
+ \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.
+
+ \warning This function is not available with MSVC 6. Use
+ qVariantFromValue() instead if you need to support that version
+ of the compiler.
+
+ \sa setValue(), value()
+*/
+
+/*!
+ \fn QVariant qVariantFromValue(const T &value)
+ \relates QVariant
+
+ 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). It
+ is provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ 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
+
+ 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). It
+ is provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ \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 qVariantValue().
+
+ \sa qVariantValue(), QVariant::value()
+*/
+
+/*! \fn T qVariantValue(const QVariant &value)
+ \relates QVariant
+
+ 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). It is
+ provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ \sa QVariant::value(), qvariant_cast()
+*/
+
+/*! \fn bool qVariantCanConvert(const QVariant &value)
+ \relates QVariant
+
+ 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). It
+ is provided as a work-around for MSVC 6, which doesn't support
+ member template functions.
+
+ \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..d7b7e3c0b1
--- /dev/null
+++ b/src/corelib/kernel/qvariant.h
@@ -0,0 +1,605 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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 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;
+
+#ifndef QT_NO_MEMBER_TEMPLATES
+template <typename T>
+inline QVariant qVariantFromValue(const T &);
+
+template <typename T>
+inline void qVariantSetValue(QVariant &, const T &);
+
+template<typename T>
+inline T qVariantValue(const QVariant &);
+
+template<typename T>
+inline bool qVariantCanConvert(const QVariant &);
+#endif
+
+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,
+ LastCoreType = Hash,
+
+ // 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,
+ LastGuiType = Transform,
+
+ 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(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);
+#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
+ QVariant(Qt::GlobalColor color);
+
+ QVariant& operator=(const QVariant &other);
+
+ 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;
+ 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
+
+#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(); }
+
+#ifndef QT_NO_MEMBER_TEMPLATES
+ template<typename T>
+ inline void setValue(const T &value);
+
+ template<typename T>
+ inline T value() const
+ { return qVariantValue<T>(*this); }
+
+ template<typename T>
+ static inline QVariant fromValue(const T &value)
+ { return qVariantFromValue(value); }
+
+ template<typename T>
+ bool canConvert() const
+ { return qVariantCanConvert<T>(*this); }
+#endif
+
+ 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;
+ qlonglong ll;
+ qulonglong ull;
+ 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);
+}
+
+template <>
+inline QVariant qVariantFromValue(const QVariant &t) { return t; }
+
+template <typename T>
+inline void qVariantSetValue(QVariant &v, const T &t)
+{
+ v = QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &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
+
+#ifndef QT_NO_MEMBER_TEMPLATES
+template<typename T>
+inline void QVariant::setValue(const T &avalue)
+{ qVariantSetValue(*this, avalue); }
+#endif
+
+#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
+#if !defined qdoc && defined Q_CC_MSVC && _MSC_VER < 1300
+
+template<typename T> T qvariant_cast(const QVariant &v, T * = 0)
+{
+ 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<typename T>
+inline T qVariantValue(const QVariant &variant, T *t = 0)
+{ return qvariant_cast<T>(variant, t); }
+
+template<typename T>
+inline bool qVariantCanConvert(const QVariant &variant, T *t = 0)
+{
+ return variant.canConvert(static_cast<QVariant::Type>(qMetaTypeId<T>(t)));
+}
+#else
+
+template<typename T> 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<typename T>
+inline T qVariantValue(const QVariant &variant)
+{ return qvariant_cast<T>(variant); }
+
+template<typename T>
+inline bool qVariantCanConvert(const QVariant &variant)
+{
+ return variant.canConvert(static_cast<QVariant::Type>(
+ qMetaTypeId<T>(static_cast<T *>(0))));
+}
+#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..727a390f2b
--- /dev/null
+++ b/src/corelib/kernel/qvariant_p.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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>
+
+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
+
+// 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 QVariant::PrivateShared(new T(*static_cast<const T *>(copy)))
+ : new QVariant::PrivateShared(new T);
+ x->is_shared = true;
+ } else {
+ if (copy)
+ new (&x->data.ptr) T(*static_cast<const T *>(copy));
+ else
+ new (&x->data.ptr) T;
+ }
+}
+
+// deletes the internal structures
+template <class T>
+inline void v_clear(QVariant::Private *d, T* = 0)
+{
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ delete v_cast<T>(d);
+ delete d->data.shared;
+ } else {
+ v_cast<T>(d)->~T();
+ }
+}
+
+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..dfbae7a65c
--- /dev/null
+++ b/src/corelib/kernel/qwineventnotifier_p.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "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.
+
+ \ingroup io
+
+ 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..458c71c70e
--- /dev/null
+++ b/src/corelib/kernel/qwineventnotifier_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef 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