summaryrefslogtreecommitdiffstats
path: root/src/corelib/kernel
diff options
context:
space:
mode:
authorThierry Bastian <thierry.bastian@nokia.com>2009-05-22 09:28:05 (GMT)
committerThierry Bastian <thierry.bastian@nokia.com>2009-05-22 09:28:05 (GMT)
commitd0ac49ec731f0781ba48f8f5d8ce04e19ce0010d (patch)
treeba6df139b3c343bb9352423770a99f218f62bd45 /src/corelib/kernel
parent72798fc4dfc1af73cde542f9017dfec5cb020173 (diff)
parent8ad5020940f10d4ecc5c5e8b3b9656531cb84ef3 (diff)
downloadQt-d0ac49ec731f0781ba48f8f5d8ce04e19ce0010d.zip
Qt-d0ac49ec731f0781ba48f8f5d8ce04e19ce0010d.tar.gz
Qt-d0ac49ec731f0781ba48f8f5d8ce04e19ce0010d.tar.bz2
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into kinetic-animations
Conflicts: src/corelib/kernel/kernel.pri src/corelib/kernel/qvariant_p.h src/corelib/tools/tools.pri src/gui/graphicsview/qgraphicsitem.cpp src/gui/graphicsview/qgraphicsitem.h src/gui/graphicsview/qgraphicswidget.h src/gui/gui.pro
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r--src/corelib/kernel/kernel.pri9
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp33
-rw-r--r--src/corelib/kernel/qfunctions_wince.cpp5
-rw-r--r--src/corelib/kernel/qfunctions_wince.h5
-rw-r--r--src/corelib/kernel/qobject.cpp316
-rw-r--r--src/corelib/kernel/qobject_p.h13
-rw-r--r--src/corelib/kernel/qsharedmemory.cpp4
-rw-r--r--src/corelib/kernel/qsharedmemory_unix.cpp7
-rw-r--r--src/corelib/kernel/qtimer.cpp2
-rw-r--r--src/corelib/kernel/qvariant.cpp168
-rw-r--r--src/corelib/kernel/qvariant.h15
-rw-r--r--src/corelib/kernel/qvariant_p.h43
12 files changed, 308 insertions, 312 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index b34e59d..ecef555 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -51,10 +51,11 @@ SOURCES += \
kernel/qtimer.cpp \
kernel/qtranslator.cpp \
kernel/qvariant.cpp \
- kernel/qcoreglobaldata.cpp \
- kernel/qsharedmemory.cpp \
- kernel/qsystemsemaphore.cpp
-
+ kernel/qcoreglobaldata.cpp \
+ kernel/qsharedmemory.cpp \
+ kernel/qsystemsemaphore.cpp \
+ kernel/qpointer.cpp
+
win32 {
SOURCES += \
kernel/qeventdispatcher_win.cpp \
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index a23b2dd..77ef096 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -377,12 +377,12 @@ QString qAppName()
QLibrary) can be retrieved with libraryPaths() and manipulated by
setLibraryPaths(), addLibraryPath(), and removeLibraryPath().
- On Unix/Linux Qt is configured to use the system local settings by
- default. This can cause a conflict when using POSIX functions, for
- instance, when converting between data types such as floats and
- strings, since the notation may differ between locales. To get
- around this problem call the POSIX function setlocale(LC_NUMERIC,"C")
- right after initializing QApplication or QCoreApplication to reset
+ On Unix/Linux Qt is configured to use the system local settings by
+ default. This can cause a conflict when using POSIX functions, for
+ instance, when converting between data types such as floats and
+ strings, since the notation may differ between locales. To get
+ around this problem call the POSIX function setlocale(LC_NUMERIC,"C")
+ right after initializing QApplication or QCoreApplication to reset
the locale that is used for number formatting to "C"-locale.
\sa QApplication, QAbstractEventDispatcher, QEventLoop,
@@ -556,6 +556,20 @@ void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
QCoreApplicationPrivate::attribs |= 1 << attribute;
else
QCoreApplicationPrivate::attribs &= ~(1 << attribute);
+#ifdef Q_OS_MAC
+ // Turn on the no native menubar here, since we used to
+ // do this implicitly. We DO NOT flip it off if someone sets
+ // it to false.
+ // Ideally, we'd have magic that would be something along the lines of
+ // "follow MacPluginApplication" unless explicitly set.
+ // Considering this attribute isn't only at the beginning
+ // it's unlikely it will ever be a problem, but I want
+ // to have the behavior documented here.
+ if (attribute == Qt::AA_MacPluginApplication && on
+ && !testAttribute(Qt::AA_DontUseNativeMenuBar)) {
+ setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+ }
+#endif
}
/*!
@@ -1696,7 +1710,7 @@ QString QCoreApplication::applicationDirPath()
}
QCoreApplicationPrivate *d = self->d_func();
- if (d->cachedApplicationDirPath == QString())
+ if (d->cachedApplicationDirPath.isNull())
d->cachedApplicationDirPath = QFileInfo(applicationFilePath()).path();
return d->cachedApplicationDirPath;
}
@@ -1724,7 +1738,7 @@ QString QCoreApplication::applicationFilePath()
}
QCoreApplicationPrivate *d = self->d_func();
- if (d->cachedApplicationFilePath != QString())
+ if (!d->cachedApplicationFilePath.isNull())
return d->cachedApplicationFilePath;
#if defined( Q_WS_WIN )
@@ -1908,8 +1922,7 @@ QStringList QCoreApplication::arguments()
l1arg == "-qdebug" ||
l1arg == "-reverse" ||
l1arg == "-stylesheet" ||
- l1arg == "-widgetcount" ||
- l1arg == "-direct3d")
+ l1arg == "-widgetcount")
;
else if (l1arg.startsWith("-style="))
;
diff --git a/src/corelib/kernel/qfunctions_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp
index 1c929c7..e0f7687 100644
--- a/src/corelib/kernel/qfunctions_wince.cpp
+++ b/src/corelib/kernel/qfunctions_wince.cpp
@@ -285,11 +285,6 @@ int qt_wince_SetErrorMode(int 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);
diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h
index 123bd23..5f08bb3 100644
--- a/src/corelib/kernel/qfunctions_wince.h
+++ b/src/corelib/kernel/qfunctions_wince.h
@@ -199,7 +199,9 @@ 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);
+#ifndef CoInitialize
+#define CoInitialize(x) CoInitializeEx(x, COINIT_MULTITHREADED)
+#endif
bool qt_wince__chmod(const char *file, int mode);
bool qt_wince__wchmod(const WCHAR *file, int mode);
@@ -376,7 +378,6 @@ typedef DWORD OLE_COLOR;
#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)
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 05015c0..cfd8493 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -58,6 +58,7 @@
#include <qsemaphore.h>
#include <private/qorderedmutexlocker_p.h>
+#include <private/qmutexpool_p.h>
#include <new>
@@ -70,7 +71,7 @@ static int DIRECT_CONNECTION_ONLY = 0;
static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
{
- int *types = static_cast<int *>(qMalloc((typeNames.count() + 1) * sizeof(int)));
+ int *types = new int [typeNames.count() + 1];
for (int i = 0; i < typeNames.count(); ++i) {
const QByteArray typeName = typeNames.at(i);
if (typeName.endsWith('*'))
@@ -82,7 +83,7 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
"(Make sure '%s' is registered using qRegisterMetaType().)",
typeName.constData(), typeName.constData());
- qFree(types);
+ delete [] types;
return 0;
}
}
@@ -91,12 +92,35 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
return types;
}
+QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
+QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+/** \internal
+ * mutex to be locked when accessing the connectionlists or the senders list
+ */
+static QMutex *signalSlotLock(const QObject *o)
+{
+ if (!signalSlotMutexes) {
+ QMutexPool *mp = new QMutexPool;
+ if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
+ delete mp;
+ }
+ }
+ return signalSlotMutexes->get(o);
+}
+
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
{
+ objectCount.ref();
}
extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
{
+ if(!objectCount.deref()) {
+ QMutexPool *old = signalSlotMutexes;
+ signalSlotMutexes.testAndSetAcquire(old, 0);
+ delete old;
+ }
}
QObjectPrivate::QObjectPrivate(int version)
@@ -216,19 +240,20 @@ public:
}
};
+// Used by QAccessibleWidget
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);
+ QMutexLocker locker(signalSlotLock(q));
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)
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (c->receiver == receiver)
return true;
}
}
@@ -236,6 +261,7 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
return false;
}
+// Used by QAccessibleWidget
QObjectList QObjectPrivate::receiverList(const char *signal) const
{
Q_Q(const QObject);
@@ -243,26 +269,27 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const
int signal_index = q->metaObject()->indexOfSignal(signal);
if (signal_index < 0)
return returnValue;
- QMutexLocker locker(&threadData->mutex);
+ QMutexLocker locker(signalSlotLock(q));
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;
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (c->receiver)
+ returnValue << c->receiver;
}
}
}
return returnValue;
}
+// Used by QAccessibleWidget
QObjectList QObjectPrivate::senderList() const
{
QObjectList returnValue;
- QMutexLocker locker(&threadData->mutex);
+ QMutexLocker locker(signalSlotLock(q_func()));
for (int i = 0; i < senders.count(); ++i)
- returnValue << senders.at(i).sender;
+ returnValue << senders.at(i)->sender;
return returnValue;
}
@@ -274,33 +301,11 @@ void QObjectPrivate::addConnection(int signal, Connection *c)
connectionLists->resize(signal + 1);
ConnectionList &connectionList = (*connectionLists)[signal];
- connectionList.append(*c);
+ 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) {
@@ -308,55 +313,17 @@ void QObjectPrivate::cleanConnectionLists()
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)
+ QObjectPrivate::Connection *c = connectionList.at(i);
+ if (!c->receiver) {
+ delete c;
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)
{
@@ -769,7 +736,7 @@ QObject::~QObject()
emit destroyed(this);
{
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
// set ref to zero to indicate that this object has been deleted
if (d->currentSender != 0)
@@ -782,23 +749,21 @@ QObject::~QObject()
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)
+ QObjectPrivate::Connection *c = connectionList[i];
+ if (!c->receiver) {
+ delete c;
continue;
+ }
- QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(c->receiver);
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
- c = &connectionList[i];
+ c = connectionList[i];
if (c->receiver)
- c->receiver->d_func()->removeSender(this, signal);
+ c->receiver->d_func()->senders.removeOne(c);
if (needToUnlock)
m->unlock();
- if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c->argumentTypes);
- c->argumentTypes = 0;
- }
- c->receiver = 0;
+ delete c;
}
}
@@ -811,18 +776,26 @@ QObject::~QObject()
}
// disconnect all senders
- for (int i = 0; i < d->senders.count(); ++i) {
- QObjectPrivate::Sender *s = &d->senders[i];
- if (!s->sender)
- continue;
+ for (int i = 0; i < d->senders.count(); ) {
+ QObjectPrivate::Connection *s = d->senders[i];
- QMutex *m = &s->sender->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(s->sender);
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
- s = &d->senders[i];
- if (s->sender)
- s->sender->d_func()->removeReceiver(s->signal, this);
+ if (m < locker.mutex()) {
+ if (i >= d->senders.count() || s != d->senders[i]) {
+ if (needToUnlock)
+ m->unlock();
+ continue;
+ }
+ }
+ s->receiver = 0;
+ QObjectConnectionListVector *senderLists = s->sender->d_func()->connectionLists;
+ if (senderLists)
+ senderLists->dirty = true;
+
if (needToUnlock)
m->unlock();
+ ++i;
}
d->senders.clear();
@@ -866,6 +839,12 @@ QObject::~QObject()
d_ptr = 0;
}
+QObjectPrivate::Connection::~Connection()
+{
+ if (argumentTypes != &DIRECT_CONNECTION_ONLY)
+ delete [] argumentTypes;
+}
+
/*!
\fn QMetaObject *QObject::metaObject() const
@@ -2297,14 +2276,14 @@ QObject *QObject::sender() const
{
Q_D(const QObject);
- QMutexLocker(&d->threadData->mutex);
+ QMutexLocker(signalSlotLock(this));
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);
+ found = (d->senders.at(i)->sender == d->currentSender->sender);
if (!found)
return 0;
return d->currentSender->sender;
@@ -2353,14 +2332,14 @@ int QObject::receivers(const char *signal) const
}
Q_D(const QObject);
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
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;
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ receivers += c->receiver ? 1 : 0;
}
}
}
@@ -2793,20 +2772,18 @@ bool QMetaObject::connect(const QObject *sender, int signal_index,
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
- QOrderedMutexLocker locker(&s->d_func()->threadData->mutex,
- &r->d_func()->threadData->mutex);
+ QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
+ c->sender = s;
+ c->receiver = r;
+ c->method = method_index;
+ c->connectionType = type;
+ c->argumentTypes = types;
-#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);
+ QOrderedMutexLocker locker(signalSlotLock(sender),
+ signalSlotLock(receiver));
+
+ s->d_func()->addConnection(signal_index, c);
+ r->d_func()->senders.append(c);
if (signal_index < 0)
sender->d_func()->connectedSignals = ~0u;
@@ -2828,8 +2805,8 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
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;
+ QMutex *senderMutex = signalSlotLock(sender);
+ QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
QOrderedMutexLocker locker(senderMutex, receiverMutex);
QObjectConnectionListVector *connectionLists = s->d_func()->connectionLists;
@@ -2845,27 +2822,23 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
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];
+ 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;
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = false;
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;
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = connectionList[i];
}
+ if (c->receiver)
+ c->receiver->d_func()->senders.removeOne(c);
+
+ if (needToUnlock)
+ m->unlock();
+
c->receiver = 0;
success = true;
@@ -2876,27 +2849,22 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
} 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];
+ 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;
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = false;
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;
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = connectionList[i];
}
+ if (c->receiver)
+ c->receiver->d_func()->senders.removeOne(c);
+
+ if (needToUnlock)
+ m->unlock();
c->receiver = 0;
success = true;
@@ -2979,32 +2947,31 @@ void QMetaObject::connectSlotsByName(QObject *o)
}
}
-static void queued_activate(QObject *sender, int signal, const QObjectPrivate::Connection &c,
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c,
void **argv, QSemaphore *semaphore = 0)
{
- if (!c.argumentTypes || c.argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ 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 (!c->argumentTypes.testAndSetOrdered(0, tmp)) {
if (tmp != &DIRECT_CONNECTION_ONLY)
- qFree(tmp);
+ delete [] tmp;
}
}
- if (c.argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
+ if (c->argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
return;
int nargs = 1; // include return type
- while (c.argumentTypes[nargs-1])
+ 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,
+ args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
+ QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method,
sender,
signal,
nargs,
@@ -3013,13 +2980,13 @@ static void queued_activate(QObject *sender, int signal, const QObjectPrivate::C
semaphore));
}
-static void blocking_activate(QObject *sender, int signal, const QObjectPrivate::Connection &c, void **argv)
+static void blocking_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
{
- if (QThread::currentThread() == c.receiver->thread()) {
+ 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);
+ c->receiver->metaObject()->className(), c->receiver);
}
#ifdef QT_NO_THREAD
@@ -3027,7 +2994,7 @@ static void blocking_activate(QObject *sender, int signal, const QObjectPrivate:
#else
QSemaphore semaphore;
queued_activate(sender, signal, c, argv, &semaphore);
- QMutex *mutex = &QThreadData::get2(sender->thread())->mutex;
+ QMutex *mutex = signalSlotLock(sender);
mutex->unlock();
semaphore.acquire();
mutex->lock();
@@ -3047,7 +3014,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
argv ? argv : empty_argv);
}
- QMutexLocker locker(&sender->d_func()->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(sender));
QThreadData *currentThreadData = QThreadData::current();
QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
@@ -3069,7 +3036,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
}
int count = connectionLists->at(signal).count();
for (int i = 0; i < count; ++i) {
- const QObjectPrivate::Connection *c = &connectionLists->at(signal)[i];
+ QObjectPrivate::Connection *c = connectionLists->at(signal)[i];
if (!c->receiver)
continue;
@@ -3081,10 +3048,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
&& (currentThreadData != sender->d_func()->threadData
|| receiver->d_func()->threadData != sender->d_func()->threadData))
|| (c->connectionType == Qt::QueuedConnection)) {
- queued_activate(sender, signal, *c, argv);
+ queued_activate(sender, signal, c, argv);
continue;
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
- blocking_activate(sender, signal, *c, argv);
+ blocking_activate(sender, signal, c, argv);
continue;
}
@@ -3399,7 +3366,7 @@ void QObject::dumpObjectInfo()
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
Q_D(QObject);
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
// first, look for connections where this object is the sender
qDebug(" SIGNALS OUT");
@@ -3412,16 +3379,16 @@ void QObject::dumpObjectInfo()
// 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) {
+ 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);
+ 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()),
+ c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
method.signature());
}
}
@@ -3434,13 +3401,12 @@ void QObject::dumpObjectInfo()
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());
+ const QObjectPrivate::Connection *s = d->senders.at(i);
+ const QMetaMethod slot = metaObject()->method(s->method);
+ qDebug(" <-- %s::%s %s",
+ s->sender->metaObject()->className(),
+ s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
+ slot.signature());
}
} else {
qDebug(" <None>");
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index b324334..96d79af 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -114,7 +114,6 @@ public:
int signal;
int ref;
};
-
// object currently activating the object
Sender *currentSender;
@@ -148,22 +147,20 @@ public:
// Note: you must hold the signalSlotLock() before accessing the lists below or calling the functions
struct Connection
{
+ QObject *sender;
QObject *receiver;
int method;
uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
QBasicAtomicPointer<int> argumentTypes;
+ ~Connection();
};
- typedef QList<Connection> ConnectionList;
+ 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);
+ ConnectionList senders;
static Sender *setCurrentSender(QObject *receiver,
Sender *sender);
@@ -208,7 +205,7 @@ private:
QSemaphore *semaphore_;
};
-class Q_CORE_EXPORT QBoolBlocker
+class QBoolBlocker
{
public:
inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp
index 9853079..87e154f 100644
--- a/src/corelib/kernel/qsharedmemory.cpp
+++ b/src/corelib/kernel/qsharedmemory.cpp
@@ -129,6 +129,10 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key,
detached from the segment, and no references to the segment
remain. Do not mix using QtSharedMemory and QSharedMemory. Port
everything to QSharedMemory.
+
+ \warning QSharedMemory changes the key in a Qt-specific way.
+ It is therefore currently not possible to use the shared memory of
+ non-Qt applications with QSharedMemory.
*/
/*!
diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp
index 487c653..cd248dc 100644
--- a/src/corelib/kernel/qsharedmemory_unix.cpp
+++ b/src/corelib/kernel/qsharedmemory_unix.cpp
@@ -47,12 +47,9 @@
#include <qdir.h>
#include <qdebug.h>
-#include <errno.h>
-
-QT_BEGIN_NAMESPACE
-
#ifndef QT_NO_SHAREDMEMORY
+#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
@@ -61,6 +58,8 @@ QT_BEGIN_NAMESPACE
#include <fcntl.h>
#include <unistd.h>
+QT_BEGIN_NAMESPACE
+
QSharedMemoryPrivate::QSharedMemoryPrivate()
: QObjectPrivate(), memory(0), size(0), error(QSharedMemory::NoError),
#ifndef QT_NO_SYSTEMSEMAPHORE
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 01e81ab..4b3feb0 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -77,7 +77,7 @@ QT_BEGIN_NAMESPACE
In multithreaded applications, you can use QTimer in any thread
that has an event loop. To start an event loop from a non-GUI
- thread, use QThread::exec(). Qt uses the the timer's
+ thread, use QThread::exec(). Qt uses the timer's
\l{QObject::thread()}{thread affinity} to determine which thread
will emit the \l{QTimer::}{timeout()} signal. Because of this, you
must start and stop the timer in its thread; it is not possible to
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index b4427c0..2ff9818 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -71,27 +71,6 @@ QT_BEGIN_NAMESPACE
# 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;
@@ -179,6 +158,9 @@ static void construct(QVariant::Private *x, const void *copy)
case QVariant::Double:
x->data.d = copy ? *static_cast<const double*>(copy) : 0.0;
break;
+ case QMetaType::Float:
+ x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
+ break;
case QVariant::LongLong:
x->data.ll = copy ? *static_cast<const qlonglong *>(copy) : Q_INT64_C(0);
break;
@@ -274,6 +256,7 @@ static void clear(QVariant::Private *d)
case QVariant::LongLong:
case QVariant::ULongLong:
case QVariant::Double:
+ case QMetaType::Float:
break;
case QVariant::Invalid:
case QVariant::UserType:
@@ -342,6 +325,7 @@ static bool isNull(const QVariant::Private *d)
case QVariant::ULongLong:
case QVariant::Bool:
case QVariant::Double:
+ case QMetaType::Float:
break;
}
return d->is_null;
@@ -433,6 +417,8 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b)
return a->data.b == b->data.b;
case QVariant::Double:
return a->data.d == b->data.d;
+ case QMetaType::Float:
+ return a->data.f == b->data.f;
case QVariant::Date:
return *v_cast<QDate>(a) == *v_cast<QDate>(b);
case QVariant::Time:
@@ -491,7 +477,7 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
case QMetaType::Long:
return qlonglong(*static_cast<long *>(d->data.shared->ptr));
case QMetaType::Float:
- return qRound64(*static_cast<float *>(d->data.shared->ptr));
+ return qRound64(d->data.f);
case QVariant::Double:
return qRound64(d->data.d);
}
@@ -628,7 +614,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*str = QString::number(qMetaTypeUNumber(d));
break;
case QMetaType::Float:
- *str = QString::number(*static_cast<float *>(d->data.shared->ptr), 'g', FLT_DIG);
+ *str = QString::number(d->data.f, 'g', FLT_DIG);
break;
case QVariant::Double:
*str = QString::number(d->data.d, 'g', DBL_DIG);
@@ -799,7 +785,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*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);
+ *ba = QByteArray::number(d->data.f, 'g', FLT_DIG);
break;
case QMetaType::Char:
case QMetaType::UChar:
@@ -901,7 +887,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*f = double(d->data.b);
break;
case QMetaType::Float:
- *f = *static_cast<float *>(d->data.shared->ptr);
+ *f = double(d->data.f);
break;
case QVariant::LongLong:
case QVariant::Int:
@@ -1035,7 +1021,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
static void streamDebug(QDebug dbg, const QVariant &v)
{
- switch (v.type()) {
+ switch (v.userType()) {
case QVariant::Int:
dbg.nospace() << v.toInt();
break;
@@ -1048,6 +1034,9 @@ static void streamDebug(QDebug dbg, const QVariant &v)
case QVariant::ULongLong:
dbg.nospace() << v.toULongLong();
break;
+ case QMetaType::Float:
+ dbg.nospace() << qVariantValue<float>(v);
+ break;
case QVariant::Double:
dbg.nospace() << v.toDouble();
break;
@@ -1187,8 +1176,9 @@ const QVariant::Handler *QVariant::handler = &qt_kernel_variant_handler;
and versatile, but may prove less memory and speed efficient than
storing specific types in standard data structures.
- QVariant also supports the notion of null values, where you have
- a defined type with no value set.
+ QVariant also supports the notion of null values, where you can
+ have a defined type with no value set. However, note that QVariant
+ types can only be cast when they have had a value set.
\snippet doc/src/snippets/code/src_corelib_kernel_qvariant.cpp 1
@@ -1355,7 +1345,7 @@ void QVariant::create(int type, const void *copy)
QVariant::~QVariant()
{
- if (d.type > Char && (!d.is_shared || !d.data.shared->ref.deref()))
+ if (d.type > Char && d.type != QMetaType::Float && (!d.is_shared || !d.data.shared->ref.deref()))
handler->clear(&d);
}
@@ -1371,7 +1361,7 @@ QVariant::QVariant(const QVariant &p)
{
if (d.is_shared) {
d.data.shared->ref.ref();
- } else if (p.d.type > Char) {
+ } else if (p.d.type > Char && p.d.type != QMetaType::Float) {
handler->construct(&d, p.constData());
d.is_null = p.d.is_null;
}
@@ -1565,6 +1555,12 @@ QVariant::QVariant(const char *val)
*/
/*!
+ \fn QVariant::QVariant(float 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.
@@ -1619,44 +1615,44 @@ QVariant::QVariant(double val)
{ d.is_null = false; d.type = Double; d.data.d = val; }
QVariant::QVariant(const QByteArray &val)
-{ create(ByteArray, &val); }
+{ d.is_null = false; d.type = ByteArray; v_construct<QByteArray>(&d, val); }
QVariant::QVariant(const QBitArray &val)
-{ create(BitArray, &val); }
+{ d.is_null = false; d.type = BitArray; v_construct<QBitArray>(&d, val); }
QVariant::QVariant(const QString &val)
-{ create(String, &val); }
+{ d.is_null = false; d.type = String; v_construct<QString>(&d, val); }
QVariant::QVariant(const QChar &val)
-{ create (Char, &val); }
+{ d.is_null = false; d.type = Char; v_construct<QChar>(&d, val); }
QVariant::QVariant(const QLatin1String &val)
-{ QString str(val); create(String, &str); }
+{ QString str(val); d.is_null = false; d.type = String; v_construct<QString>(&d, str); }
QVariant::QVariant(const QStringList &val)
-{ create(StringList, &val); }
+{ d.is_null = false; d.type = StringList; v_construct<QStringList>(&d, val); }
QVariant::QVariant(const QDate &val)
-{ create(Date, &val); }
+{ d.is_null = false; d.type = Date; v_construct<QDate>(&d, val); }
QVariant::QVariant(const QTime &val)
-{ create(Time, &val); }
+{ d.is_null = false; d.type = Time; v_construct<QTime>(&d, val); }
QVariant::QVariant(const QDateTime &val)
-{ create(DateTime, &val); }
+{ d.is_null = false; d.type = DateTime; v_construct<QDateTime>(&d, val); }
QVariant::QVariant(const QList<QVariant> &list)
-{ create(List, &list); }
+{ d.is_null = false; d.type = List; v_construct<QVariantList>(&d, list); }
QVariant::QVariant(const QMap<QString, QVariant> &map)
-{ create(Map, &map); }
+{ d.is_null = false; d.type = Map; v_construct<QVariantMap>(&d, map); }
QVariant::QVariant(const QHash<QString, QVariant> &hash)
-{ create(Hash, &hash); }
+{ d.is_null = false; d.type = Hash; v_construct<QVariantHash>(&d, 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); }
+QVariant::QVariant(const QPoint &pt) { d.is_null = false; d.type = Point; v_construct<QPoint>(&d, pt); }
+QVariant::QVariant(const QPointF &pt) { d.is_null = false; d.type = PointF; v_construct<QPointF>(&d, pt); }
+QVariant::QVariant(const QRectF &r) { d.is_null = false; d.type = RectF; v_construct<QRectF>(&d, r); }
+QVariant::QVariant(const QLineF &l) { d.is_null = false; d.type = LineF; v_construct<QLineF>(&d, l); }
+QVariant::QVariant(const QLine &l) { d.is_null = false; d.type = Line; v_construct<QLine>(&d, l); }
+QVariant::QVariant(const QRect &r) { d.is_null = false; d.type = Rect; v_construct<QRect>(&d, r); }
+QVariant::QVariant(const QSize &s) { d.is_null = false; d.type = Size; v_construct<QSize>(&d, s); }
+QVariant::QVariant(const QSizeF &s) { d.is_null = false; d.type = SizeF; v_construct<QSizeF>(&d, s); }
#endif
-QVariant::QVariant(const QUrl &u) { create(Url, &u); }
-QVariant::QVariant(const QLocale &l) { create(Locale, &l); }
+QVariant::QVariant(const QUrl &u) { d.is_null = false; d.type = Url; v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QLocale &l) { d.is_null = false; d.type = Locale; v_construct<QLocale>(&d, l); }
#ifndef QT_NO_REGEXP
-QVariant::QVariant(const QRegExp &regExp) { create(RegExp, &regExp); }
+QVariant::QVariant(const QRegExp &regExp) { d.is_null = false; d.type = RegExp; v_construct<QRegExp>(&d, regExp); }
#endif
QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); }
@@ -1721,7 +1717,7 @@ QVariant& QVariant::operator=(const QVariant &variant)
if (variant.d.is_shared) {
variant.d.data.shared->ref.ref();
d = variant.d;
- } else if (variant.d.type > Char) {
+ } else if (variant.d.type > Char && variant.d.type != QMetaType::Float) {
d.type = variant.d.type;
handler->construct(&d, variant.constData());
d.is_null = variant.d.is_null;
@@ -1907,7 +1903,7 @@ void QVariant::load(QDataStream &s)
}
// const cast is safe since we operate on a newly constructed variant
- if (!QMetaType::load(s, d.type, const_cast<void *>(constDataHelper(d)))) {
+ if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) {
s.setStatus(QDataStream::ReadCorruptData);
qWarning("QVariant::load: unable to load type %d.", d.type);
}
@@ -1947,7 +1943,7 @@ void QVariant::save(QDataStream &s) const
return;
}
- if (!QMetaType::save(s, d.type, constDataHelper(d))) {
+ if (!QMetaType::save(s, d.type, constData())) {
Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
qWarning("QVariant::save: unable to save type %d.", d.type);
}
@@ -2565,57 +2561,63 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
*/
bool QVariant::canConvert(Type t) const
{
- if (d.type == uint(t))
+ //we can treat floats as double
+ //the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
+ //which can't be handled by qCanConvertMatrix
+ //In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
+ const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
+ if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
+
+ if (currentType == uint(t))
return true;
- if (d.type > QVariant::LastCoreType || t > QVariant::LastCoreType) {
+ if (currentType > 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;
+ return currentType == QVariant::KeySequence
+ || currentType == QMetaType::ULong
+ || currentType == QMetaType::Long
+ || currentType == QMetaType::UShort
+ || currentType == QMetaType::UChar
+ || currentType == QMetaType::Char
+ || currentType == QMetaType::Short;
case QVariant::Image:
- return d.type == QVariant::Pixmap || d.type == QVariant::Bitmap;
+ return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
case QVariant::Pixmap:
- return d.type == QVariant::Image || d.type == QVariant::Bitmap
- || d.type == QVariant::Brush;
+ return currentType == QVariant::Image || currentType == QVariant::Bitmap
+ || currentType == QVariant::Brush;
case QVariant::Bitmap:
- return d.type == QVariant::Pixmap || d.type == QVariant::Image;
+ return currentType == QVariant::Pixmap || currentType == QVariant::Image;
case QVariant::ByteArray:
- return d.type == QVariant::Color;
+ return currentType == QVariant::Color;
case QVariant::String:
- return d.type == QVariant::KeySequence || d.type == QVariant::Font
- || d.type == QVariant::Color;
+ return currentType == QVariant::KeySequence || currentType == QVariant::Font
+ || currentType == QVariant::Color;
case QVariant::KeySequence:
- return d.type == QVariant::String || d.type == QVariant::Int;
+ return currentType == QVariant::String || currentType == QVariant::Int;
case QVariant::Font:
- return d.type == QVariant::String;
+ return currentType == QVariant::String;
case QVariant::Color:
- return d.type == QVariant::String || d.type == QVariant::ByteArray
- || d.type == QVariant::Brush;
+ return currentType == QVariant::String || currentType == QVariant::ByteArray
+ || currentType == QVariant::Brush;
case QVariant::Brush:
- return d.type == QVariant::Color || d.type == QVariant::Pixmap;
+ return currentType == QVariant::Color || currentType == QVariant::Pixmap;
case QMetaType::Long:
case QMetaType::Char:
case QMetaType::UChar:
case QMetaType::ULong:
case QMetaType::Short:
case QMetaType::UShort:
- case QMetaType::Float:
- return qCanConvertMatrix[QVariant::Int] & (1 << d.type) || d.type == QVariant::Int;
+ return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int;
default:
return false;
}
}
- if(t == String && d.type == StringList)
+ if(t == String && currentType == StringList)
return v_cast<QStringList>(&d)->count() == 1;
else
- return qCanConvertMatrix[t] & (1 << d.type);
+ return qCanConvertMatrix[t] & (1 << currentType);
}
/*!
@@ -2726,7 +2728,7 @@ bool QVariant::cmp(const QVariant &v) const
const void *QVariant::constData() const
{
- return constDataHelper(d);
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
}
/*!
@@ -2739,7 +2741,7 @@ const void *QVariant::constData() const
void* QVariant::data()
{
detach();
- return const_cast<void *>(constDataHelper(d));
+ return const_cast<void *>(constData());
}
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index d7b7e3c..d73fcbc 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -181,6 +181,7 @@ class Q_CORE_EXPORT QVariant
QVariant(qulonglong ull);
QVariant(bool b);
QVariant(double d);
+ QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; }
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN_CONSTRUCTOR QVariant(const char *str);
#endif
@@ -349,6 +350,7 @@ class Q_CORE_EXPORT QVariant
uint u;
bool b;
double d;
+ float f;
qlonglong ll;
qulonglong ull;
void *ptr;
@@ -443,7 +445,18 @@ 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);
+ //if possible we reuse the current QVariant private
+ const int type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
+ QVariant::Private &d = v.data_ptr();
+ if (type <= int(QVariant::Char) || (type == d.type && v.isDetached())) {
+ d.type = type;
+ T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
+ if (QTypeInfo<T>::isComplex)
+ old->~T();
+ new (old) T(t); //call the copy constructor
+ } else {
+ v = QVariant(type, &t);
+ }
}
inline QVariant::QVariant() {}
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 0764fe3..033b760 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -60,8 +60,6 @@
QT_BEGIN_NAMESPACE
-extern Q_CORE_EXPORT const QVariant::Handler *qExtendedVariantHandler;
-
#ifdef Q_CC_SUN // Sun CC picks the wrong overload, so introduce awful hack
template <typename T>
@@ -70,7 +68,7 @@ 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)
- : reinterpret_cast<T*>(&d->data.c));
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
}
#else // every other compiler in this world
@@ -80,7 +78,7 @@ 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)
- : reinterpret_cast<const T *>(&d->data.c));
+ : static_cast<const T *>(static_cast<const void *>(&d->data.c)));
}
template <typename T>
@@ -88,15 +86,17 @@ inline T *v_cast(QVariant::Private *d, T * = 0)
{
return ((sizeof(T) > sizeof(QVariant::Private::Data))
? static_cast<T *>(d->data.shared->ptr)
- : reinterpret_cast<T *>(&d->data.c));
+ : static_cast<T *>(static_cast<void *>(&d->data.c)));
}
#endif
-//a simple template that avoids to allocate 2 buffers when creating a QVariant
+
+//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
{
public:
+ QVariantPrivateSharedEx() : QVariant::PrivateShared(&m_t) { }
QVariantPrivateSharedEx(const T&t) : QVariant::PrivateShared(&m_t), m_t(t) { }
private:
@@ -105,14 +105,12 @@ private:
// constructs a new variant if copy is 0, otherwise copy-constructs
template <class T>
-inline void v_construct(QVariant::Private *x, const T& t)
+inline void v_construct(QVariant::Private *x, const T &t)
{
- x->type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
if (sizeof(T) > sizeof(QVariant::Private::Data)) {
x->data.shared = new QVariantPrivateSharedEx<T>(t);
x->is_shared = true;
} else {
- x->is_shared = false;
new (&x->data.ptr) T(t);
}
}
@@ -120,24 +118,31 @@ inline void v_construct(QVariant::Private *x, const T& t)
template <class T>
inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
{
- if (copy) {
- v_construct<T>(x, *reinterpret_cast<const T*>(copy));
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ x->data.shared = copy ? new QVariantPrivateSharedEx<T>(*static_cast<const T *>(copy))
+ : new QVariantPrivateSharedEx<T>;
+ x->is_shared = true;
} else {
- T t;
- v_construct<T>(x, t);
+ 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)
{
- //now we need to call the destructor in any case
- //because QVariant::PrivateShared doesn't have a virtual destructor
- v_cast<T>(d)->~T();
- if (sizeof(T) > sizeof(QVariant::Private::Data))
- delete d->data.shared;
+
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ //now we need to cast
+ //because QVariant::PrivateShared doesn't have a virtual destructor
+ delete static_cast<QVariantPrivateSharedEx<T>*>(d->data.shared);
+ } else {
+ v_cast<T>(d)->~T();
+ }
+
}
QT_END_NAMESPACE