diff options
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/qabstractitemmodel.cpp | 31 | ||||
-rw-r--r-- | src/corelib/kernel/qabstractitemmodel_p.h | 1 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 89 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 3 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qtimer.cpp | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 18 |
7 files changed, 109 insertions, 40 deletions
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 935c0aa..6d6caf5 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,6 +467,37 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +/*! + \internal + return true if \a value contains a numerical type + + This function is used by our Q{Tree,Widget,Table}WidgetModel classes to sort. + We cannot rely on QVariant::canConvert because this would take strings as double + and then not sort strings correctly +*/ +bool QAbstractItemModelPrivate::canConvertToDouble(const QVariant &value) +{ + switch (value.userType()) { + case QVariant::Bool: + case QVariant::Int: + case QVariant::UInt: + case QVariant::LongLong: + case QVariant::ULongLong: + case QVariant::Double: + case QVariant::Char: + case QMetaType::Float: + case QMetaType::Short: + case QMetaType::UShort: + case QMetaType::UChar: + case QMetaType::ULong: + case QMetaType::Long: + return true; + default: + return false; + } + return false; +} + void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data) { if (data->index.isValid()) { diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index 27f1b28..70c35cb 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -89,6 +89,7 @@ public: void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last); void columnsRemoved(const QModelIndex &parent, int first, int last); static QAbstractItemModel *staticEmptyModel(); + static bool canConvertToDouble(const QVariant &value); inline QModelIndex createIndex(int row, int column, void *data = 0) const { return q_func()->createIndex(row, column, data); diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 5e33a71..55d70c1 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -123,7 +123,7 @@ extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *) } QObjectPrivate::QObjectPrivate(int version) - : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0) + : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0), senders(0) { if (version != QObjectPrivateVersion) qFatal("Cannot mix incompatible Qt libraries"); @@ -143,6 +143,7 @@ QObjectPrivate::QObjectPrivate(int version) inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; + hasGuards = false; } QObjectPrivate::~QObjectPrivate() @@ -287,8 +288,8 @@ QObjectList QObjectPrivate::senderList() const { QObjectList returnValue; QMutexLocker locker(signalSlotLock(q_func())); - for (int i = 0; i < senders.count(); ++i) - returnValue << senders.at(i)->sender; + for (Connection *c = senders; c; c = c->next) + returnValue << c->sender; return returnValue; } @@ -359,6 +360,7 @@ void QMetaObject::addGuard(QObject **ptr) return; } QMutexLocker locker(guardHashLock()); + QObjectPrivate::get(*ptr)->hasGuards = true; hash->insert(*ptr, ptr); } @@ -374,12 +376,17 @@ void QMetaObject::removeGuard(QObject **ptr) QMutexLocker locker(guardHashLock()); GuardHash::iterator it = hash->find(*ptr); const GuardHash::iterator end = hash->end(); + bool more = false; //if the QObject has more pointer attached to it. for (; it.key() == *ptr && it != end; ++it) { if (it.value() == ptr) { - (void) hash->erase(it); + it = hash->erase(it); + if (!more) more = (it != end && it.key() == *ptr); break; } + more = true; } + if (!more) + QObjectPrivate::get(*ptr)->hasGuards = false; } /*!\internal @@ -393,24 +400,33 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) } QMutexLocker locker(guardHashLock()); if (*ptr) { + bool more = false; //if the QObject has more pointer attached to it. GuardHash::iterator it = hash->find(*ptr); const GuardHash::iterator end = hash->end(); for (; it.key() == *ptr && it != end; ++it) { if (it.value() == ptr) { - (void) hash->erase(it); + it = hash->erase(it); + if (!more) more = (it != end && it.key() == *ptr); break; } + more = true; } + if (!more) + QObjectPrivate::get(*ptr)->hasGuards = false; } *ptr = o; - if (*ptr) + if (*ptr) { hash->insert(*ptr, ptr); + QObjectPrivate::get(*ptr)->hasGuards = true; + } } /*! \internal */ void QObjectPrivate::clearGuards(QObject *object) { + if (!QObjectPrivate::get(object)->hasGuards) + return; GuardHash *hash = guardHash(); if (hash) { QMutexLocker locker(guardHashLock()); @@ -756,8 +772,10 @@ QObject::~QObject() QMutex *m = signalSlotLock(c->receiver); bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); c = connectionList[i]; - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -774,29 +792,25 @@ QObject::~QObject() } // disconnect all senders - for (int i = 0; i < d->senders.count(); ) { - QObjectPrivate::Connection *s = d->senders[i]; - - QMutex *m = signalSlotLock(s->sender); + QObjectPrivate::Connection *node = d->senders; + while (node) { + QMutex *m = signalSlotLock(node->sender); + node->prev = &node; bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m); - if (m < locker.mutex()) { - if (i >= d->senders.count() || s != d->senders[i]) { - if (needToUnlock) - m->unlock(); - continue; - } + //the node has maybe been removed while the mutex was unlocked in relock? + if (!node || signalSlotLock(node->sender) != m) { + m->unlock(); + continue; } - s->receiver = 0; - QObjectConnectionListVector *senderLists = s->sender->d_func()->connectionLists; + node->receiver = 0; + QObjectConnectionListVector *senderLists = node->sender->d_func()->connectionLists; if (senderLists) senderLists->dirty = true; if (needToUnlock) m->unlock(); - ++i; + node = node->next; } - - d->senders.clear(); } if (d->pendTimer) { @@ -2281,8 +2295,8 @@ QObject *QObject::sender() const // 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); + for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next) + found = (c->sender == d->currentSender->sender); if (!found) return 0; return d->currentSender->sender; @@ -2799,9 +2813,13 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, c->method = method_index; c->connectionType = type; c->argumentTypes = types; + c->prev = &r->d_func()->senders; + c->next = *c->prev; + *c->prev = c; + if (c->next) + c->next->prev = &c->next; s->d_func()->addConnection(signal_index, c); - r->d_func()->senders.append(c); if (signal_index < 0) sender->d_func()->connectedSignals = ~0u; @@ -2851,8 +2869,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); c = connectionList[i]; } - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -2878,8 +2898,10 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index, needToUnlock = QOrderedMutexLocker::relock(senderMutex, m); c = connectionList[i]; } - if (c->receiver) - c->receiver->d_func()->senders.removeOne(c); + if (c->receiver) { + *c->prev = c->next; + if (c->next) c->next->prev = c->prev; + } if (needToUnlock) m->unlock(); @@ -3417,9 +3439,8 @@ void QObject::dumpObjectInfo() // 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::Connection *s = d->senders.at(i); + if (d->senders) { + for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) { const QMetaMethod slot = metaObject()->method(s->method); qDebug(" <-- %s::%s %s", s->sender->metaObject()->className(), @@ -3427,7 +3448,7 @@ void QObject::dumpObjectInfo() slot.signature()); } } else { - qDebug(" <None>"); + qDebug(" <None>"); } #endif } diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index dbec0a6..b1f41ad 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -106,7 +106,8 @@ public: uint receiveChildEvents : 1; uint inEventHandler : 1; uint inThreadChangeEvent : 1; - uint unused : 23; + uint hasGuards : 1; //true iff there is one or more QPointer attached to this object + uint unused : 22; int postedEvents; }; diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 96d79af..d699061 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -152,6 +152,9 @@ public: int method; uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking QBasicAtomicPointer<int> argumentTypes; + //senders linked list + Connection *next; + Connection **prev; ~Connection(); }; typedef QList<Connection *> ConnectionList; @@ -160,7 +163,7 @@ public: void addConnection(int signal, Connection *c); void cleanConnectionLists(); - ConnectionList senders; + Connection *senders; //linked list; static Sender *setCurrentSender(QObject *receiver, Sender *sender); diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 8ca53b9..29bdf7e 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -251,7 +251,7 @@ void QTimer::stop() /*! - \reimp + \reimp */ void QTimer::timerEvent(QTimerEvent *e) { diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 2ff9818..a3434a4 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -591,6 +591,15 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, ok = &dummy; switch (uint(t)) { + case QVariant::Url: + switch (d->type) { + case QVariant::String: + *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d)); + break; + default: + return false; + } + break; case QVariant::String: { QString *str = static_cast<QString *>(result); switch (d->type) { @@ -640,6 +649,8 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result, if (v_cast<QStringList>(d)->count() == 1) *str = v_cast<QStringList>(d)->at(0); break; + case QVariant::Url: + *str = v_cast<QUrl>(d)->toString(); default: return false; } @@ -1823,7 +1834,7 @@ QVariant::Type QVariant::nameToType(const char *name) #ifndef QT_NO_DATASTREAM enum { MapFromThreeCount = 35 }; -static const uint map_from_three[MapFromThreeCount] = +static const ushort map_from_three[MapFromThreeCount] = { QVariant::Invalid, QVariant::Map, @@ -2484,7 +2495,8 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = /*QString*/ 1 << QVariant::StringList | 1 << QVariant::ByteArray | 1 << QVariant::Int | 1 << QVariant::UInt | 1 << QVariant::Bool | 1 << QVariant::Double | 1 << QVariant::Date | 1 << QVariant::Time | 1 << QVariant::DateTime - | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char, + | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char + | 1 << QVariant::Url, /*QStringList*/ 1 << QVariant::List | 1 << QVariant::String, @@ -2499,7 +2511,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = /*QDateTime*/ 1 << QVariant::String | 1 << QVariant::Date, -/*QUrl*/ 0, +/*QUrl*/ 1 << QVariant::String, /*QLocale*/ 0, |