diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-08-04 08:33:52 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-08-04 09:02:17 (GMT) |
commit | 4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1 (patch) | |
tree | b34985c5716d98f01b9f36fd4a98f2ac9710099f /src/corelib/kernel | |
parent | a0df97c03f26a38af17a42fb44ad6910536c8857 (diff) | |
parent | 2076f150995e541308b1d8da936b3e12ab68b886 (diff) | |
download | Qt-4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1.zip Qt-4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1.tar.gz Qt-4aafbd6222e7aeafd59a4a4356ba8c53b2bfa1d1.tar.bz2 |
Merge commit 'qt/master-stable'
Conflicts:
config.tests/unix/openssl/openssl.pri
demos/embedded/embedded.pro
examples/itemviews/chart/chart.pro
examples/network/network.pro
examples/painting/painterpaths/painterpaths.pro
examples/threads/mandelbrot/mandelbrot.pro
qmake/project.cpp
src/3rdparty/libtiff/libtiff/tif_config.h
src/corelib/arch/arch.pri
src/corelib/global/qglobal.cpp
src/corelib/kernel/kernel.pri
src/corelib/kernel/qcore_unix_p.h
src/corelib/kernel/qobject.cpp
src/corelib/thread/qthread_unix.cpp
src/corelib/tools/qsharedpointer_impl.h
src/corelib/tools/tools.pri
src/gui/kernel/qaction.h
src/gui/kernel/qapplication.cpp
src/gui/painting/qregion.h
src/gui/widgets/qlineedit.cpp
src/gui/widgets/qlineedit_p.h
src/network/socket/qnativesocketengine_unix.cpp
tests/auto/qdir/tst_qdir.cpp
tests/auto/qdiriterator/tst_qdiriterator.cpp
tests/auto/qhttp/qhttp.pro
tests/auto/qline/qline.pro
tests/auto/qnetworkreply/tst_qnetworkreply.cpp
tests/auto/qresourceengine/qresourceengine.pro
tests/auto/qsharedpointer/qsharedpointer.pro
tests/auto/qstring/qstring.pro
tests/auto/qtcpsocket/qtcpsocket.pro
tests/auto/qtcpsocket/tst_qtcpsocket.cpp
Diffstat (limited to 'src/corelib/kernel')
-rw-r--r-- | src/corelib/kernel/kernel.pri | 12 | ||||
-rw-r--r-- | src/corelib/kernel/qabstractitemmodel.cpp | 48 | ||||
-rw-r--r-- | src/corelib/kernel/qabstractitemmodel.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qabstractitemmodel_p.h | 5 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_unix.cpp | 11 | ||||
-rw-r--r-- | src/corelib/kernel/qcore_unix_p.h | 63 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 8 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix.cpp | 68 | ||||
-rw-r--r-- | src/corelib/kernel/qeventdispatcher_unix_p.h | 61 | ||||
-rw-r--r-- | src/corelib/kernel/qfunctions_p.h | 2 | ||||
-rw-r--r-- | src/corelib/kernel/qfunctions_vxworks.cpp | 202 | ||||
-rw-r--r-- | src/corelib/kernel/qfunctions_vxworks.h | 153 | ||||
-rw-r--r-- | src/corelib/kernel/qguard_p.h | 157 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.cpp | 107 | ||||
-rw-r--r-- | src/corelib/kernel/qmetaobject.h | 4 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.cpp | 142 | ||||
-rw-r--r-- | src/corelib/kernel/qobject.h | 11 | ||||
-rw-r--r-- | src/corelib/kernel/qobject_p.h | 45 | ||||
-rw-r--r-- | src/corelib/kernel/qobjectdefs.h | 5 |
19 files changed, 982 insertions, 126 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 4b7baef..124b2b3 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -32,7 +32,8 @@ HEADERS += \ kernel/qsharedmemory_p.h \ kernel/qsystemsemaphore.h \ kernel/qsystemsemaphore_p.h \ - kernel/qfunctions_p.h + kernel/qfunctions_p.h \ + kernel/qguard_p.h SOURCES += \ kernel/qabstracteventdispatcher.cpp \ @@ -54,7 +55,7 @@ SOURCES += \ kernel/qcoreglobaldata.cpp \ kernel/qsharedmemory.cpp \ kernel/qsystemsemaphore.cpp \ - kernel/qpointer.cpp + kernel/qpointer.cpp win32 { SOURCES += \ @@ -128,3 +129,10 @@ symbian { kernel/qcore_symbian_p.h } +vxworks { + SOURCES += \ + kernel/qfunctions_vxworks.cpp + HEADERS += \ + kernel/qfunctions_vxworks.h +} + diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 3d9263e..bc95c60 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -467,6 +467,27 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel() return qEmptyModel(); } +namespace { + struct DefaultRoleNames : public QHash<int, QByteArray> + { + DefaultRoleNames() { + (*this)[Qt::DisplayRole] = "display"; + (*this)[Qt::DecorationRole] = "decoration"; + (*this)[Qt::EditRole] = "edit"; + (*this)[Qt::ToolTipRole] = "toolTip"; + (*this)[Qt::StatusTipRole] = "statusTip"; + (*this)[Qt::WhatsThisRole] = "whatsThis"; + } + }; +} + +Q_GLOBAL_STATIC(DefaultRoleNames, qDefaultRoleNames) + +const QHash<int,QByteArray> &QAbstractItemModelPrivate::defaultRoleNames() +{ + return *qDefaultRoleNames(); +} + /*! \internal return true if \a value contains a numerical type @@ -1863,6 +1884,33 @@ QSize QAbstractItemModel::span(const QModelIndex &) const } /*! + Sets the model's role names to \a roleNames. + + This function is provided to allow mapping of role identifiers to + role property names in Declarative UI. This function must be called + before the model is used. Modifying the role names after the model + has been set may result in undefined behaviour. + + \sa roleNames() +*/ +void QAbstractItemModel::setRoleNames(const QHash<int,QByteArray> &roleNames) +{ + Q_D(QAbstractItemModel); + d->roleNames = roleNames; +} + +/*! + Returns the model's role names. + + \sa setRoleNames() +*/ +const QHash<int,QByteArray> &QAbstractItemModel::roleNames() const +{ + Q_D(const QAbstractItemModel); + return d->roleNames; +} + +/*! Called to let the model know that it should submit whatever it has cached to the permanent storage. Typically used for row editing. diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h index dc7d7bd..a6bbff4 100644 --- a/src/corelib/kernel/qabstractitemmodel.h +++ b/src/corelib/kernel/qabstractitemmodel.h @@ -220,6 +220,8 @@ public: Qt::MatchFlags(Qt::MatchStartsWith|Qt::MatchWrap)) const; virtual QSize span(const QModelIndex &index) const; + const QHash<int,QByteArray> &roleNames() const; + #ifdef Q_NO_USING_KEYWORD inline QObject *parent() const { return QObject::parent(); } #else @@ -282,6 +284,8 @@ protected: void changePersistentIndexList(const QModelIndexList &from, const QModelIndexList &to); QModelIndexList persistentIndexList() const; + void setRoleNames(const QHash<int,QByteArray> &roleNames); + private: Q_DECLARE_PRIVATE(QAbstractItemModel) Q_DISABLE_COPY(QAbstractItemModel) diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h index c047f95..6a29723 100644 --- a/src/corelib/kernel/qabstractitemmodel_p.h +++ b/src/corelib/kernel/qabstractitemmodel_p.h @@ -78,7 +78,7 @@ class Q_CORE_EXPORT QAbstractItemModelPrivate : public QObjectPrivate Q_DECLARE_PUBLIC(QAbstractItemModel) public: - QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1) {} + QAbstractItemModelPrivate() : QObjectPrivate(), supportedDragActions(-1), roleNames(defaultRoleNames()) {} void removePersistentIndexData(QPersistentModelIndexData *data); void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last); void rowsInserted(const QModelIndex &parent, int first, int last); @@ -144,6 +144,9 @@ public: } persistent; Qt::DropActions supportedDragActions; + + QHash<int,QByteArray> roleNames; + static const QHash<int,QByteArray> &defaultRoleNames(); }; QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index 28c1d9c..b57d385 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -41,11 +41,14 @@ #include "qcore_unix_p.h" -#include <sys/select.h> -#include <sys/time.h> -#include <stdlib.h> +#ifndef Q_OS_VXWORKS +# include <sys/select.h> +# include <sys/time.h> +#else +# include <selectLib.h> +#endif -#include "qeventdispatcher_unix_p.h" // for the timeval operators +#include <stdlib.h> #ifdef Q_OS_MAC #include <mach/mach_time.h> diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h index 28bc34a..e301c92 100644 --- a/src/corelib/kernel/qcore_unix_p.h +++ b/src/corelib/kernel/qcore_unix_p.h @@ -67,6 +67,10 @@ #include <errno.h> #include <fcntl.h> +#if defined(Q_OS_VXWORKS) +# include <ioLib.h> +#endif + struct sockaddr; #if defined(Q_OS_LINUX) && defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0204 @@ -110,6 +114,51 @@ using namespace QT_PREPEND_NAMESPACE(QtLibcSupplement); QT_BEGIN_NAMESPACE +// Internal operator functions for timevals +inline timeval &normalizedTimeval(timeval &t) +{ + while (t.tv_usec > 1000000l) { + ++t.tv_sec; + t.tv_usec -= 1000000l; + } + while (t.tv_usec < 0l) { + --t.tv_sec; + t.tv_usec += 1000000l; + } + return t; +} +inline bool operator<(const timeval &t1, const timeval &t2) +{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); } +inline bool operator==(const timeval &t1, const timeval &t2) +{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; } +inline timeval &operator+=(timeval &t1, const timeval &t2) +{ + t1.tv_sec += t2.tv_sec; + t1.tv_usec += t2.tv_usec; + return normalizedTimeval(t1); +} +inline timeval operator+(const timeval &t1, const timeval &t2) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec + t2.tv_sec; + tmp.tv_usec = t1.tv_usec + t2.tv_usec; + return normalizedTimeval(tmp); +} +inline timeval operator-(const timeval &t1, const timeval &t2) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1); + tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000); + return normalizedTimeval(tmp); +} +inline timeval operator*(const timeval &t1, int mul) +{ + timeval tmp; + tmp.tv_sec = t1.tv_sec * mul; + tmp.tv_usec = t1.tv_usec * mul; + return normalizedTimeval(tmp); +} + // don't call QT_OPEN or ::open // call qt_safe_open static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777) @@ -129,6 +178,7 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07 #undef QT_OPEN #define QT_OPEN qt_safe_open +#ifndef Q_OS_VXWORKS // no POSIX pipes in VxWorks // don't call ::pipe // call qt_safe_pipe static inline int qt_safe_pipe(int pipefd[2], int flags = 0) @@ -164,6 +214,8 @@ static inline int qt_safe_pipe(int pipefd[2], int flags = 0) return 0; } +#endif // Q_OS_VXWORKS + // don't call dup or fcntl(F_DUPFD) static inline int qt_safe_dup(int oldfd, int atleast = 0, int flags = FD_CLOEXEC) { @@ -238,8 +290,8 @@ static inline int qt_safe_close(int fd) #undef QT_CLOSE #define QT_CLOSE qt_safe_close -// Open C does not (yet?) implement these on Symbian OS -#ifndef Q_OS_SYMBIAN +// Open C does not (yet?) implement these on Symbian OS and VxWorks doesn't have processes +#if !defined(Q_OS_SYMBIAN) && !defined(Q_OS_VXWORKS) static inline int qt_safe_execve(const char *filename, char *const argv[], char *const envp[]) { @@ -263,6 +315,7 @@ static inline int qt_safe_execvp(const char *file, char *const argv[]) } #endif +#ifndef Q_OS_VXWORKS // no processes on VxWorks static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) { register int ret; @@ -270,6 +323,12 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options) return ret; } +#endif // Q_OS_VXWORKS + +#if !defined(_POSIX_MONOTONIC_CLOCK) +# define _POSIX_MONOTONIC_CLOCK -1 +#endif + bool qt_gettime_is_monotonic(); timeval qt_gettime(); Q_CORE_EXPORT int qt_safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept, diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 5865dc3..b84ad53 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -61,6 +61,7 @@ #include <private/qthread_p.h> #include <qlibraryinfo.h> #include <private/qfactoryloader_p.h> +#include <private/qfunctions_p.h> #ifdef Q_OS_SYMBIAN # include <exception> @@ -88,6 +89,10 @@ # include <locale.h> #endif +#ifdef Q_OS_VXWORKS +# include <taskLib.h> +#endif + QT_BEGIN_NAMESPACE class QLockedMutexUnlocker @@ -1917,8 +1922,9 @@ qint64 QCoreApplication::applicationPid() { #if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) return GetCurrentProcessId(); +#elif defined(Q_OS_VXWORKS) + return (pid_t) taskIdCurrent; #else - // UNIX return getpid(); #endif } diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index c3979e8..78a2b0b 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -55,6 +55,16 @@ #include <stdio.h> #include <stdlib.h> +// VxWorks doesn't correctly set the _POSIX_... options +#if defined(Q_OS_VXWORKS) +# if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK <= 0) +# undef _POSIX_MONOTONIC_CLOCK +# define _POSIX_MONOTONIC_CLOCK 1 +# endif +# include <pipeDrv.h> +# include <selectLib.h> +#endif + #if (_POSIX_MONOTONIC_CLOCK-0 <= 0) || defined(QT_BOOTSTRAPPED) # include <sys/times.h> #endif @@ -77,7 +87,7 @@ static void signalHandler(int sig) } -#ifdef Q_OS_INTEGRITY +#if defined(Q_OS_INTEGRITY) || defined(Q_OS_VXWORKS) static void initThreadPipeFD(int fd) { int ret = fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -98,20 +108,47 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() { extern Qt::HANDLE qt_application_thread_id; mainThread = (QThread::currentThreadId() == qt_application_thread_id); + bool pipefail = false; // initialize the common parts of the event loop -#ifdef Q_OS_INTEGRITY +#if defined(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) + if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); - - initThreadPipeFD(thread_pipe[0]); - initThreadPipeFD(thread_pipe[1]); + pipefail = true; + } else { + initThreadPipeFD(thread_pipe[0]); + initThreadPipeFD(thread_pipe[1]); + } +#elif defined(Q_OS_VXWORKS) + char name[20]; + qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent)); + + // make sure there is no pipe with this name + pipeDevDelete(name, true); + // create the pipe + if (pipeDevCreate(name, 128 /*maxMsg*/, 1 /*maxLength*/) != OK) { + perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe device"); + pipefail = true; + } else { + if ((thread_pipe[0] = open(name, O_RDWR, 0)) < 0) { + perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); + pipefail = true; + } else { + initThreadPipeFD(thread_pipe[0]); + thread_pipe[1] = thread_pipe[0]; + } + } #else - if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) + if (qt_safe_pipe(thread_pipe, O_NONBLOCK) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create thread pipe"); + pipefail = true; + } #endif + if (pipefail) + qFatal("QEventDispatcherUNIXPrivate(): Can not continue without a thread pipe"); + sn_highest = -1; interrupt = false; @@ -119,9 +156,18 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() { +#if defined(Q_OS_VXWORKS) + close(thread_pipe[0]); + + char name[20]; + qsnprintf(name, sizeof(name), "/pipe/qt_%08x", int(taskIdCurrent)); + + pipeDevDelete(name, true); +#else // cleanup the common parts of the event loop close(thread_pipe[0]); close(thread_pipe[1]); +#endif // cleanup timers qDeleteAll(timerList); @@ -226,9 +272,15 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, // select doesn't immediately return next time int nevents = 0; if (nsel > 0 && FD_ISSET(thread_pipe[0], &sn_vec[0].select_fds)) { +#if defined(Q_OS_VXWORKS) + char c[16]; + ::read(thread_pipe[0], c, sizeof(c)); + ::ioctl(thread_pipe[0], FIOFLUSH, 0); +#else char c[16]; while (::read(thread_pipe[0], c, sizeof(c)) > 0) ; +#endif if (!wakeUps.testAndSetRelease(1, 0)) { // hopefully, this is dead code qWarning("QEventDispatcherUNIX: internal error, wakeUps.testAndSetRelease(1, 0) failed!"); @@ -313,7 +365,7 @@ timeval qAbs(const timeval &t) */ bool QTimerInfoList::timeChanged(timeval *delta) { - tms unused; + struct tms unused; clock_t currentTicks = times(&unused); clock_t elapsedTicks = currentTicks - previousTicks; diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index fedbccf..a52af00 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -56,65 +56,20 @@ #include "QtCore/qabstracteventdispatcher.h" #include "QtCore/qlist.h" #include "private/qabstracteventdispatcher_p.h" +#include "private/qcore_unix_p.h" #include "private/qpodlist_p.h" #include "QtCore/qvarlengtharray.h" -#include <sys/types.h> -#include <sys/time.h> -#if !defined(Q_OS_HPUX) || defined(__ia64) -#include <sys/select.h> +#if defined(Q_OS_VXWORKS) +# include <sys/times.h> +#else +# include <sys/time.h> +# if !defined(Q_OS_HPUX) || defined(__ia64) +# include <sys/select.h> +# endif #endif -#include <unistd.h> QT_BEGIN_NAMESPACE -#if !defined(_POSIX_MONOTONIC_CLOCK) -# define _POSIX_MONOTONIC_CLOCK -1 -#endif - -// Internal operator functions for timevals -inline timeval &normalizedTimeval(timeval &t) -{ - while (t.tv_usec > 1000000l) { - ++t.tv_sec; - t.tv_usec -= 1000000l; - } - while (t.tv_usec < 0l) { - --t.tv_sec; - t.tv_usec += 1000000l; - } - return t; -} -inline bool operator<(const timeval &t1, const timeval &t2) -{ return t1.tv_sec < t2.tv_sec || (t1.tv_sec == t2.tv_sec && t1.tv_usec < t2.tv_usec); } -inline bool operator==(const timeval &t1, const timeval &t2) -{ return t1.tv_sec == t2.tv_sec && t1.tv_usec == t2.tv_usec; } -inline timeval &operator+=(timeval &t1, const timeval &t2) -{ - t1.tv_sec += t2.tv_sec; - t1.tv_usec += t2.tv_usec; - return normalizedTimeval(t1); -} -inline timeval operator+(const timeval &t1, const timeval &t2) -{ - timeval tmp; - tmp.tv_sec = t1.tv_sec + t2.tv_sec; - tmp.tv_usec = t1.tv_usec + t2.tv_usec; - return normalizedTimeval(tmp); -} -inline timeval operator-(const timeval &t1, const timeval &t2) -{ - timeval tmp; - tmp.tv_sec = t1.tv_sec - (t2.tv_sec - 1); - tmp.tv_usec = t1.tv_usec - (t2.tv_usec + 1000000); - return normalizedTimeval(tmp); -} -inline timeval operator*(const timeval &t1, int mul) -{ - timeval tmp; - tmp.tv_sec = t1.tv_sec * mul; - tmp.tv_usec = t1.tv_usec * mul; - return normalizedTimeval(tmp); -} // internal timer info struct QTimerInfo { diff --git a/src/corelib/kernel/qfunctions_p.h b/src/corelib/kernel/qfunctions_p.h index a7f2f9d..ad44a15 100644 --- a/src/corelib/kernel/qfunctions_p.h +++ b/src/corelib/kernel/qfunctions_p.h @@ -57,6 +57,8 @@ #if defined(Q_OS_WINCE) # include "QtCore/qfunctions_wince.h" +#elif defined(Q_OS_VXWORKS) +# include "QtCore/qfunctions_vxworks.h" #endif #ifdef Q_CC_RVCT diff --git a/src/corelib/kernel/qfunctions_vxworks.cpp b/src/corelib/kernel/qfunctions_vxworks.cpp new file mode 100644 index 0000000..6d5e7cc --- /dev/null +++ b/src/corelib/kernel/qfunctions_vxworks.cpp @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** 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 "qglobal.h" + +#ifdef Q_OS_VXWORKS + +#include "qplatformdefs.h" +#include "qfunctions_vxworks.h" + +#include <vmLib.h> +#include <selectLib.h> +#include <ioLib.h> + +QT_USE_NAMESPACE + +#ifdef __cplusplus +extern "C" { +#endif + +// no lfind() - used by the TIF image format +void *lfind(const void* key, const void* base, size_t* elements, size_t size, + int (*compare)(const void*, const void*)) +{ + const char* current = (char*) base; + const char* const end = (char*) (current + (*elements) * size); + while (current != end) { + if (compare(current, key) == 0) + return (void*)current; + current += size; + } + return 0; +} + + +// no rand_r(), but rand() +// NOTE: this implementation is wrong for multi threaded applications, +// but there is no way to get it right on VxWorks (in kernel mode) +int rand_r(unsigned int * /*seedp*/) +{ + return rand(); +} + +// no usleep() support +int usleep(unsigned int usec) +{ + div_t dt = div(usec, 1000000); + struct timespec ts = { dt.quot, dt.rem * 1000 }; + + return nanosleep(&ts, 0); +} + + +// gettimeofday() is declared, but is missing from the library +// It IS however defined in the Curtis-Wright X11 libraries, so +// we have to make the symbol 'weak' +#if defined(Q_CC_DIAB) +# pragma weak gettimeofday +#endif +int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) +{ + // the compiler will optimize this and will only use one code path + if (sizeof(struct timeval) == sizeof(struct timespec)) { + int res = clock_gettime(CLOCK_REALTIME, (struct timespec *) tv); + if (!res) + tv->tv_usec /= 1000; + return res; + } else { + struct timespec ts; + + int res = clock_gettime(CLOCK_REALTIME, &ts); + if (!res) { + tv->tv_sec = ts.tv_sec; + tv->tv_usec = ts.tv_nsec / 1000; + } + return res; + } +} + +// neither getpagesize() or sysconf(_SC_PAGESIZE) are available +int getpagesize() +{ + return vmPageSizeGet(); +} + +// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h) +int symlink(const char *, const char *) +{ + errno = EIO; + return -1; +} + +ssize_t readlink(const char *, char *, size_t) +{ + errno = EIO; + return -1; +} + +// there's no truncate(), but ftruncate() support... +int truncate(const char *path, off_t length) +{ + int fd = open(path, O_WRONLY, 00777); + if (fd >= 0) { + int res = ftruncate(fd, length); + int en = errno; + close(fd); + errno = en; + return res; + } + // errno is already set by open + return -1; +} + + + +// VxWorks doesn't know about passwd & friends. +// in order to avoid patching the unix fs path everywhere +// we introduce some dummy functions that simulate a single +// 'root' user on the system. + +uid_t getuid() +{ + return 0; +} + +gid_t getgid() +{ + return 0; +} + +uid_t geteuid() +{ + return 0; +} + +struct passwd *getpwuid(uid_t uid) +{ + static struct passwd pwbuf = { "root", 0, 0, 0, 0, 0, 0 }; + + if (uid == 0) { + return &pwbuf; + } else { + errno = ENOENT; + return 0; + } +} + +struct group *getgrgid(gid_t gid) +{ + static struct group grbuf = { "root", 0, 0, 0 }; + + if (gid == 0) { + return &grbuf; + } else { + errno = ENOENT; + return 0; + } +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // Q_OS_VXWORKS diff --git a/src/corelib/kernel/qfunctions_vxworks.h b/src/corelib/kernel/qfunctions_vxworks.h new file mode 100644 index 0000000..cc98948 --- /dev/null +++ b/src/corelib/kernel/qfunctions_vxworks.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the 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_VXWORKS_H +#define QFUNCTIONS_VXWORKS_H +#ifdef Q_OS_VXWORKS + +#include <unistd.h> +#include <pthread.h> +#include <dirent.h> +#include <signal.h> +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/times.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <netinet/in.h> +#ifndef QT_NO_IPV6IFNAME +#include <net/if.h> +#endif + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +#ifdef QT_BUILD_CORE_LIB +QT_MODULE(Core) +#endif + +QT_END_NAMESPACE +QT_END_HEADER + + +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif + +#ifndef NSIG +#define NSIG _NSIGS +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// isascii is missing (sometimes!!) +#ifndef isascii +inline int isascii(int c) { return (c & 0x7f); } +#endif + +// no lfind() - used by the TIF image format +void *lfind(const void* key, const void* base, size_t* elements, size_t size, + int (*compare)(const void*, const void*)); + +// no rand_r(), but rand() +// NOTE: this implementation is wrong for multi threaded applications, +// but there is no way to get it right on VxWorks (in kernel mode) +int rand_r(unsigned int * /*seedp*/); + +// no usleep() support +int usleep(unsigned int); + +// gettimeofday() is declared, but is missing from the library. +// It IS however defined in the Curtis-Wright X11 libraries, so +// we have to make the symbol 'weak' +int gettimeofday(struct timeval *tv, void /*struct timezone*/ *) __attribute__((weak)); + +// neither getpagesize() or sysconf(_SC_PAGESIZE) are available +int getpagesize(); + +// symlinks are not supported (lstat is now just a call to stat - see qplatformdefs.h) +int symlink(const char *, const char *); +ssize_t readlink(const char *, char *, size_t); + +// there's no truncate(), but ftruncate() support... +int truncate(const char *path, off_t length); + +// VxWorks doesn't know about passwd & friends. +// in order to avoid patching the unix fs path everywhere +// we introduce some dummy functions that simulate a single +// 'root' user on the system. + +uid_t getuid(); +gid_t getgid(); +uid_t geteuid(); + +struct passwd { + char *pw_name; /* user name */ + char *pw_passwd; /* user password */ + uid_t pw_uid; /* user ID */ + gid_t pw_gid; /* group ID */ + char *pw_gecos; /* real name */ + char *pw_dir; /* home directory */ + char *pw_shell; /* shell program */ +}; + +struct group { + char *gr_name; /* group name */ + char *gr_passwd; /* group password */ + gid_t gr_gid; /* group ID */ + char **gr_mem; /* group members */ +}; + +struct passwd *getpwuid(uid_t uid); +struct group *getgrgid(gid_t gid); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // Q_OS_VXWORKS +#endif // QFUNCTIONS_VXWORKS_H diff --git a/src/corelib/kernel/qguard_p.h b/src/corelib/kernel/qguard_p.h new file mode 100644 index 0000000..6af01ac --- /dev/null +++ b/src/corelib/kernel/qguard_p.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the 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 http://www.qtsoftware.com/contact. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGUARD_P_H +#define QGUARD_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/qglobal.h" + +QT_BEGIN_NAMESPACE + +class QObject; +template<class T> +class QGuard +{ + QObject *o; + QGuard<QObject> *next; + QGuard<QObject> **prev; + friend void q_guard_addGuard(QGuard<QObject> *); + friend void q_guard_removeGuard(QGuard<QObject> *); + friend class QObjectPrivate; +public: + inline QGuard(); + inline QGuard(T *); + inline QGuard(const QGuard<T> &); + inline virtual ~QGuard(); + + inline QGuard<T> &operator=(const QGuard<T> &o); + inline QGuard<T> &operator=(T *); + + 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)); } + +protected: + virtual void objectDestroyed(T *) {} +}; + +QT_END_NAMESPACE + +#include "private/qobject_p.h" + +QT_BEGIN_NAMESPACE + +inline void q_guard_addGuard(QGuard<QObject> *); +inline void q_guard_removeGuard(QGuard<QObject> *); + +template<class T> +QGuard<T>::QGuard() +: o(0), next(0), prev(0) +{ +} + +template<class T> +QGuard<T>::QGuard(T *g) +: o(g), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); +} + +template<class T> +QGuard<T>::QGuard(const QGuard<T> &g) +: o(g.o), next(0), prev(0) +{ + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); +} + +template<class T> +QGuard<T>::~QGuard() +{ + if (prev) q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = 0; +} + +template<class T> +QGuard<T> &QGuard<T>::operator=(const QGuard<T> &g) +{ + if (g.o != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = g.o; + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); + } + return *this; +} + +template<class T> +inline QGuard<T> &QGuard<T>::operator=(T *g) +{ + if (g != o) { + if (prev) + q_guard_removeGuard(reinterpret_cast<QGuard<QObject> *>(this)); + o = g; + if (o) q_guard_addGuard(reinterpret_cast<QGuard<QObject> *>(this)); + } + return *this; +} + +QT_END_NAMESPACE + +#endif // QGUARD_P_H diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 08cecaf..9ff0bc1 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -148,7 +148,9 @@ enum PropertyFlags { Resettable = 0x00000004, EnumOrFlag = 0x00000008, StdCppSet = 0x00000100, -// Override = 0x00000200, +// Override = 0x00000200, + Constant = 0x00000400, + Final = 0x00000800, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, @@ -179,6 +181,10 @@ enum MethodFlags { MethodScriptable = 0x40 }; +enum MetaObjectFlags { + DynamicMetaObject = 0x01 +}; + struct QMetaObjectPrivate { int revision; @@ -188,6 +194,7 @@ struct QMetaObjectPrivate int propertyCount, propertyData; int enumeratorCount, enumeratorData; int constructorCount, constructorData; + int flags; }; static inline const QMetaObjectPrivate *priv(const uint* data) @@ -277,6 +284,17 @@ int QMetaObject::static_metacall(Call cl, int idx, void **argv) const } /*! + \internal +*/ +int QMetaObject::metacall(QObject *object, Call cl, int idx, void **argv) +{ + if (QMetaObject *mo = object->d_ptr->metaObject) + return static_cast<QAbstractDynamicMetaObject*>(mo)->metaCall(cl, idx, argv); + else + return object->qt_metacall(cl, idx, argv); +} + +/*! \fn const char *QMetaObject::className() const Returns the class name. @@ -696,6 +714,14 @@ int QMetaObject::indexOfProperty(const char *name) const } m = m->d.superdata; } + + if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){ + QAbstractDynamicMetaObject *me = + const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this)); + + i = me->createProperty(name, 0); + } + return i; } @@ -1326,6 +1352,16 @@ int QMetaMethod::attributes() const } /*! + Returns this method's index. +*/ +int QMetaMethod::methodIndex() const +{ + if (!mobj) + return -1; + return ((handle - priv(mobj->d.data)->methodData) / 5) + mobj->methodOffset(); +} + +/*! Returns the access specification of this method (private, protected, or public). @@ -1525,7 +1561,7 @@ bool QMetaMethod::invoke(QObject *object, // 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; + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, methodIndex, param) < 0; } else { if (returnValue.data()) { qWarning("QMetaMethod::invoke: Unable to invoke methods with return values in " @@ -2040,6 +2076,16 @@ int QMetaProperty::userType() const } /*! + Returns this property's index. +*/ +int QMetaProperty::propertyIndex() const +{ + if (!mobj) + return -1; + return idx + mobj->propertyOffset(); +} + +/*! Returns true if the property's type is an enumeration value that is used as a flag; otherwise returns false. @@ -2151,9 +2197,8 @@ QVariant QMetaProperty::read(const QObject *object) const value = QVariant(t, (void*)0); argv[0] = value.data(); } - const_cast<QObject*>(object)->qt_metacall(QMetaObject::ReadProperty, - idx + mobj->propertyOffset(), - argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::ReadProperty, + idx + mobj->propertyOffset(), argv); if (status != -1) return value; @@ -2224,7 +2269,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const argv[0] = &v; else argv[0] = v.data(); - object->qt_metacall(QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::WriteProperty, idx + mobj->propertyOffset(), argv); return status; } @@ -2241,7 +2286,7 @@ bool QMetaProperty::reset(QObject *object) const if (!object || !mobj || !isResettable()) return false; void *argv[] = { 0 }; - object->qt_metacall(QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(object, QMetaObject::ResetProperty, idx + mobj->propertyOffset(), argv); return true; } @@ -2355,8 +2400,8 @@ bool QMetaProperty::isDesignable(const QObject *object) const bool b = flags & Designable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyDesignable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyDesignable, + idx + mobj->propertyOffset(), argv); } return b; @@ -2381,8 +2426,8 @@ bool QMetaProperty::isScriptable(const QObject *object) const bool b = flags & Scriptable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyScriptable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyScriptable, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2405,8 +2450,8 @@ bool QMetaProperty::isStored(const QObject *object) const bool b = flags & Stored; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyStored, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyStored, + idx + mobj->propertyOffset(), argv); } return b; } @@ -2432,13 +2477,41 @@ bool QMetaProperty::isUser(const QObject *object) const bool b = flags & User; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyUser, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyUser, + idx + mobj->propertyOffset(), argv); } return b; } /*! + Returns true if the property is constant; otherwise returns false. + + A property is constant if the \c{Q_PROPERTY()}'s \c CONSTANT attribute + is set. +*/ +bool QMetaProperty::isConstant() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Constant; +} + +/*! + Returns true if the property is final; otherwise returns false. + + A property is final if the \c{Q_PROPERTY()}'s \c FINAL attribute + is set. +*/ +bool QMetaProperty::isFinal() const +{ + if (!mobj) + return false; + int flags = mobj->d.data[handle + 2]; + return flags & Final; +} + +/*! \obsolete Returns true if the property is editable for the given \a object; @@ -2458,8 +2531,8 @@ bool QMetaProperty::isEditable(const QObject *object) const bool b = flags & Editable; if (object) { void *argv[] = { &b }; - const_cast<QObject*>(object)->qt_metacall(QMetaObject::QueryPropertyEditable, - idx + mobj->propertyOffset(), argv); + QMetaObject::metacall(const_cast<QObject*>(object), QMetaObject::QueryPropertyEditable, + idx + mobj->propertyOffset(), argv); } return b; } diff --git a/src/corelib/kernel/qmetaobject.h b/src/corelib/kernel/qmetaobject.h index 000ba6e..419fe06 100644 --- a/src/corelib/kernel/qmetaobject.h +++ b/src/corelib/kernel/qmetaobject.h @@ -69,6 +69,7 @@ public: MethodType methodType() const; enum Attributes { Compatibility = 0x1, Cloned = 0x2, Scriptable = 0x4 }; int attributes() const; + int methodIndex() const; inline const QMetaObject *enclosingMetaObject() const { return mobj; } @@ -178,6 +179,7 @@ public: const char *typeName() const; QVariant::Type type() const; int userType() const; + int propertyIndex() const; bool isReadable() const; bool isWritable() const; @@ -187,6 +189,8 @@ public: bool isStored(const QObject *obj = 0) const; bool isEditable(const QObject *obj = 0) const; bool isUser(const QObject *obj = 0) const; + bool isConstant() const; + bool isFinal() const; bool isFlagType() const; bool isEnumType() const; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 3aa9193..e849227 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), senders(0) + : threadData(0), currentSender(0), declarativeData(0), connectionLists(0), senders(0) { if (version != QObjectPrivateVersion) qFatal("Cannot mix incompatible Qt libraries"); @@ -139,15 +139,19 @@ QObjectPrivate::QObjectPrivate(int version) receiveChildEvents = true; postedEvents = 0; extraData = 0; - connectedSignals = 0; + for (uint i = 0; i < (sizeof connectedSignals / sizeof connectedSignals[0]); ++i) + connectedSignals[i] = 0; inEventHandler = false; inThreadChangeEvent = false; deleteWatch = 0; + objectGuards = 0; + metaObject = 0; hasGuards = false; } QObjectPrivate::~QObjectPrivate() { + delete static_cast<QAbstractDynamicMetaObject*>(metaObject); if (deleteWatch) *deleteWatch = 1; #ifndef QT_NO_USERDATA @@ -427,8 +431,24 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o) */ void QObjectPrivate::clearGuards(QObject *object) { - if (!QObjectPrivate::get(object)->hasGuards) + QObjectPrivate *priv = QObjectPrivate::get(object); + QGuard<QObject> *guard = priv->objectGuards; + while (guard) { + guard->o = 0; + guard = guard->next; + } + while (priv->objectGuards) { + guard = priv->objectGuards; + guard->prev = 0; + if (guard->next) guard->next->prev = &priv->objectGuards; + priv->objectGuards = guard->next; + guard->next = 0; + guard->objectDestroyed(object); + } + + if (!priv->hasGuards) return; + GuardHash *hash = 0; QMutex *mutex = 0; QT_TRY { @@ -479,7 +499,7 @@ QMetaCallEvent::~QMetaCallEvent() */ int QMetaCallEvent::placeMetaCall(QObject *object) { - return object->qt_metacall(QMetaObject::InvokeMetaMethod, id_, args_); + return QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, id_, args_); } /*! @@ -844,6 +864,14 @@ QObject::~QObject() d->eventFilters.clear(); + // As declarativeData is in a union with currentChildBeingDeleted, this must + // be done (and declarativeData set back to 0) before deleting children. + if(d->declarativeData) { + QDeclarativeData *dd = d->declarativeData; + d->declarativeData = 0; + dd->destroyed(this); + } + if (!d->children.isEmpty()) d->deleteChildren(); @@ -1850,12 +1878,13 @@ void QObjectPrivate::deleteChildren() // 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); + QObject *child = children.at(i); children[i] = 0; - delete currentChildBeingDeleted; + if (child) + child->d_func()->parent = 0; + delete child; } children.clear(); - currentChildBeingDeleted = 0; wasDeleted = reallyWasDeleted; } @@ -1866,20 +1895,14 @@ void QObjectPrivate::setParent_helper(QObject *o) 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. + const int index = parentD->children.indexOf(q); + if (parentD->wasDeleted) { + parentD->children[index] = 0; } 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); - } + parentD->children.removeAt(index); + if (sendChildEvents && parentD->receiveChildEvents) { + QChildEvent e(QEvent::ChildRemoved, q); + QCoreApplication::sendEvent(parent, &e); } } } @@ -2867,10 +2890,16 @@ bool QMetaObject::connect(const QObject *sender, int signal_index, s->d_func()->addConnection(signal_index, c); - if (signal_index < 0) - sender->d_func()->connectedSignals = ~0u; - else if (signal_index < 32) - sender->d_func()->connectedSignals |= (1 << signal_index); + if (signal_index < 0) { + for (uint i = 0; i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0] ); ++i) + sender->d_func()->connectedSignals[i] = ~0u; + } else if (signal_index < (int)sizeof sender->d_func()->connectedSignals * 8) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + sender->d_func()->connectedSignals[n] |= (1 << (signal_index - n * 8 + * sizeof sender->d_func()->connectedSignals[0])); + } + return true; } @@ -3158,10 +3187,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal } #if defined(QT_NO_EXCEPTIONS) - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); #else QT_TRY { - receiver->qt_metacall(QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); + metacall(receiver, QMetaObject::InvokeMetaMethod, method, argv ? argv : empty_argv); } QT_CATCH(...) { locker.relock(); @@ -3210,11 +3239,12 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal */ void QMetaObject::activate(QObject *sender, int signal_index, void **argv) { - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !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) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3227,11 +3257,12 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void **argv) { int signal_index = m->methodOffset() + local_signal_index; - if (signal_index < 32 + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !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) + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) // nothing connected to these signals, and no spy return; } @@ -3243,21 +3274,59 @@ void QMetaObject::activate(QObject *sender, const QMetaObject *m, int local_sign void QMetaObject::activate(QObject *sender, const QMetaObject *m, int from_local_signal_index, int to_local_signal_index, void **argv) { + Q_ASSERT(from_local_signal_index <= to_local_signal_index); 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 + + if (to_signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 && !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) + + uint n = (from_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (from_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + uint nt = (to_signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint mt = 1 << (to_signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + bool connected = false; + quint32 *connectedSignals = sender->d_func()->connectedSignals; + for (uint i = 0; !connected && i < (sizeof sender->d_func()->connectedSignals + / sizeof sender->d_func()->connectedSignals[0]); ++i) { + uint mask = 0; + if (i > n) + mask = ~0u; + else if (i == n) + mask = ~(m -1); + if (i > nt) + mask = 0; + else if (i == nt) + mask &= (mt << 1) - 1; + connected = connectedSignals[i] & mask; + } + if (!connected) // nothing connected to these signals, and no spy return; } activate(sender, from_signal_index, to_signal_index, argv); } +/*! \internal + + Returns true if the signal with index \a signal_index from object \a sender is connected. + Signals with indices above a certain range are always considered connected (see connectedSignals + in QObjectPrivate). If a signal spy is installed, all signals are considered connected. +*/ +bool QMetaObject::isConnected(QObject *sender, int signal_index) { + if (signal_index < (int)sizeof(sender->d_func()->connectedSignals) * 8 + && !qt_signal_spy_callback_set.signal_begin_callback + && !qt_signal_spy_callback_set.signal_end_callback) { + uint n = (signal_index / (8 * sizeof sender->d_func()->connectedSignals[0])); + uint m = 1 << (signal_index - n * 8 * sizeof sender->d_func()->connectedSignals[0]); + if ((sender->d_func()->connectedSignals[n] & m) == 0) + // nothing connected to these signals, and no spy + return false; + } + return true; +} /***************************************************************************** Properties @@ -3864,6 +3933,7 @@ void qDeleteInEventHandler(QObject *o) delete o; } + QT_END_NAMESPACE #include "moc_qobject.cpp" diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 74a5904..a9f005b 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -110,6 +110,7 @@ public: uint hasGuards : 1; //true iff there is one or more QPointer attached to this object uint unused : 22; int postedEvents; + QMetaObject *metaObject; // assert dynamic }; @@ -380,6 +381,9 @@ inline QList<T> qFindChildren(const QObject *o, const QRegExp &re) #endif // Q_MOC_RUN +template <class T> inline const char * qobject_interface_iid() +{ return 0; } + template <class T> inline T qobject_cast_helper(QObject *object, T) { return static_cast<T>(((T)0)->staticMetaObject.cast(object)); } @@ -396,6 +400,8 @@ inline T qobject_cast(const QObject *object) #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid<IFace *>() \ + { return IId; } \ template <> inline IFace *qobject_cast_helper<IFace *>(QObject *object, IFace *) \ { return (IFace *)(object ? object->qt_metacast(IId) : 0); } \ template <> inline IFace *qobject_cast_helper<IFace *>(const QObject *object, IFace *) \ @@ -459,8 +465,13 @@ inline T qobject_cast(const QObject *object) } +template <class T> inline const char * qobject_interface_iid() +{ return 0; } + #ifndef Q_MOC_RUN # define Q_DECLARE_INTERFACE(IFace, IId) \ + template <> inline const char *qobject_interface_iid<IFace *>() \ + { return IId; } \ template <> inline IFace *qobject_cast<IFace *>(QObject *object) \ { return reinterpret_cast<IFace *>((object ? object->qt_metacast(IId) : 0)); } \ template <> inline IFace *qobject_cast<IFace *>(const QObject *object) \ diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h index 07c397f..0b41c9a 100644 --- a/src/corelib/kernel/qobject_p.h +++ b/src/corelib/kernel/qobject_p.h @@ -60,6 +60,7 @@ #include "QtCore/qvector.h" #include "QtCore/qreadwritelock.h" #include "QtCore/qvariant.h" +#include "private/qguard_p.h" QT_BEGIN_NAMESPACE @@ -85,6 +86,13 @@ inline QObjectData::~QObjectData() {} enum { QObjectPrivateVersion = QT_VERSION }; +class QDeclarativeData +{ +public: + virtual ~QDeclarativeData() {} + virtual void destroyed(QObject *) {} +}; + class Q_CORE_EXPORT QObjectPrivate : public QObjectData { Q_DECLARE_PUBLIC(QObject) @@ -117,7 +125,7 @@ public: // object currently activating the object Sender *currentSender; - QObject *currentChildBeingDeleted; + QDeclarativeData *declarativeData; bool isSender(const QObject *receiver, const char *signal) const; QObjectList receiverList(const char *signal) const; @@ -140,7 +148,7 @@ public: QList<QVariant> propertyValues; }; ExtraData *extraData; - mutable quint32 connectedSignals; + mutable quint32 connectedSignals[2]; QString objectName; @@ -174,12 +182,37 @@ public: static void resetDeleteWatch(QObjectPrivate *d, int *oldWatch, int deleteWatch); int *deleteWatch; + QGuard<QObject> *objectGuards; static QObjectPrivate *get(QObject *o) { return o->d_func(); } }; +inline void q_guard_addGuard(QGuard<QObject> *g) +{ + QObjectPrivate *p = QObjectPrivate::get(g->o); + if (p->wasDeleted) { + qWarning("QGuard: cannot add guard to deleted object"); + g->o = 0; + return; + } + + g->next = p->objectGuards; + p->objectGuards = g; + g->prev = &p->objectGuards; + if (g->next) + g->next->prev = &g->next; +} + +inline void q_guard_removeGuard(QGuard<QObject> *g) +{ + if (g->next) g->next->prev = g->prev; + *g->prev = g->next; + g->next = 0; + g->prev = 0; +} + Q_DECLARE_TYPEINFO(QObjectPrivate::Connection, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QObjectPrivate::Sender, Q_MOVABLE_TYPE); @@ -220,6 +253,14 @@ private: void Q_CORE_EXPORT qDeleteInEventHandler(QObject *o); + +struct Q_CORE_EXPORT QAbstractDynamicMetaObject : public QMetaObject +{ + virtual ~QAbstractDynamicMetaObject() {} + virtual int metaCall(QMetaObject::Call, int _id, void **) { return _id; } + virtual int createProperty(const char *, const char *) { return -1; } +}; + QT_END_NAMESPACE #endif // QOBJECT_P_H diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index 9187765..1ae46d5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -334,6 +334,9 @@ struct Q_CORE_EXPORT QMetaObject 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); + + static bool isConnected(QObject *sender, int signal_index); + // internal guarded pointers static void addGuard(QObject **ptr); static void removeGuard(QObject **ptr); @@ -428,6 +431,7 @@ struct Q_CORE_EXPORT QMetaObject }; int static_metacall(Call, int, void **) const; + static int metacall(QObject *, Call, int, void **); #ifdef QT3_SUPPORT QT3_SUPPORT const char *superClassName() const; @@ -439,6 +443,7 @@ struct Q_CORE_EXPORT QMetaObject const uint *data; const void *extradata; } d; + }; struct QMetaObjectExtraData |