diff options
author | Water-Team <water@pad.test.qt.nokia.com> | 2011-06-29 21:42:03 (GMT) |
---|---|---|
committer | Water-Team <water@pad.test.qt.nokia.com> | 2011-06-29 21:42:03 (GMT) |
commit | 0a8daa8845325fba9cf2ec973eb6bab8a2853dd5 (patch) | |
tree | 504c698037ee6283f1b5dbc6fa658bb2bfffb99a /src/corelib | |
parent | 680023c4921019614948c277cde5498645836cb9 (diff) | |
parent | 6b3f2a3b96d01dc339d07a076300d29616603b28 (diff) | |
download | Qt-0a8daa8845325fba9cf2ec973eb6bab8a2853dd5.zip Qt-0a8daa8845325fba9cf2ec973eb6bab8a2853dd5.tar.gz Qt-0a8daa8845325fba9cf2ec973eb6bab8a2853dd5.tar.bz2 |
Merge branch '4.8-upstream' into master-water
Diffstat (limited to 'src/corelib')
45 files changed, 765 insertions, 211 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index c144871..84d68e5 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1648,64 +1648,13 @@ static const unsigned int qt_one = 1; const int QSysInfo::ByteOrder = ((*((unsigned char *) &qt_one) == 0) ? BigEndian : LittleEndian); #endif -#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) +#if !defined(QWS) && defined(Q_OS_MAC) QT_BEGIN_INCLUDE_NAMESPACE #include "private/qcore_mac_p.h" #include "qnamespace.h" QT_END_INCLUDE_NAMESPACE -Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref) -{ - return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0); -} - -// Don't use this function, it won't work in 10.5 (Leopard) and up -Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec) -{ - FSRef fsref; - OSErr ret = qt_mac_create_fsref(file, &fsref); - if (ret == noErr) - ret = FSGetCatalogInfo(&fsref, kFSCatInfoNone, 0, 0, spec, 0); - return ret; -} - -Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding encoding=0, int len=-1) -{ - if(len == -1) - len = s.length(); -#if 0 - UnicodeMapping mapping; - mapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, - kTextEncodingDefaultVariant, - kUnicode16BitFormat); - mapping.otherEncoding = (encoding ? encoding : ); - mapping.mappingVersion = kUnicodeUseLatestMapping; - - UnicodeToTextInfo info; - OSStatus err = CreateUnicodeToTextInfo(&mapping, &info); - if(err != noErr) { - qDebug("Qt: internal: Unable to create pascal string '%s'::%d [%ld]", - s.left(len).latin1(), (int)encoding, err); - return; - } - const int unilen = len * 2; - const UniChar *unibuf = (UniChar *)s.unicode(); - ConvertFromUnicodeToPString(info, unilen, unibuf, str); - DisposeUnicodeToTextInfo(&info); -#else - Q_UNUSED(encoding); - CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding()); -#endif -} - -Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) { - return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); -} -#endif //!defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) - -#if !defined(QWS) && defined(Q_OS_MAC) - static QSysInfo::MacVersion macVersion() { #ifndef QT_NO_CORESERVICES @@ -2105,7 +2054,7 @@ static void mac_default_handler(const char *msg) { if (qt_is_gui_used) { Str255 pmsg; - qt_mac_to_pascal_string(msg, pmsg); + qt_mac_to_pascal_string(QString::fromAscii(msg), pmsg); DebugStr(pmsg); } else { fprintf(stderr, msg); @@ -2883,8 +2832,8 @@ int qrand() \relates <QtGlobal> \since 4.8 - \brief Hints the compiler that the enclosed condition is likely to evaluate - to \c true. + \brief Hints to the compiler that the enclosed condition, \a expr, is + likely to evaluate to \c true. Use of this macro can help the compiler to optimize the code. @@ -2900,8 +2849,8 @@ int qrand() \relates <QtGlobal> \since 4.8 - \brief Hints the compiler that the enclosed condition is likely to evaluate - to \c false. + \brief Hints to the compiler that the enclosed condition, \a expr, is + likely to evaluate to \c false. Use of this macro can help the compiler to optimize the code. diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 32b3e6b..1f5f537 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -173,7 +173,6 @@ namespace QT_NAMESPACE {} RELIANT - Reliant UNIX DYNIX - DYNIX/ptx QNX - QNX - QNX6 - QNX RTP 6.1 LYNX - LynxOS BSD4 - Any BSD 4.4 system UNIX - Any UNIX BSD/SYSV system @@ -2746,17 +2745,6 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_CONCURRENT_FILTER #endif -#ifdef Q_OS_QNX -// QNX doesn't have SYSV style shared memory. Multiprocess QWS apps, -// shared fonts and QSystemSemaphore + QSharedMemory are not available -# define QT_NO_QWS_MULTIPROCESS -# define QT_NO_QWS_SHARE_FONTS -# define QT_NO_SYSTEMSEMAPHORE -# define QT_NO_SHAREDMEMORY -// QNX currently doesn't support forking in a thread, so disable QProcess -# define QT_NO_PROCESS -#endif - #if defined (__ELF__) # if defined (Q_OS_LINUX) || defined (Q_OS_SOLARIS) || defined (Q_OS_FREEBSD) || defined (Q_OS_OPENBSD) || defined (Q_OS_IRIX) # define Q_OF_ELF diff --git a/src/corelib/io/qbuffer.cpp b/src/corelib/io/qbuffer.cpp index 38e406b..35e7b68 100644 --- a/src/corelib/io/qbuffer.cpp +++ b/src/corelib/io/qbuffer.cpp @@ -333,23 +333,18 @@ bool QBuffer::open(OpenMode flags) { Q_D(QBuffer); - if ((flags & Append) == Append) + if ((flags & (Append | Truncate)) != 0) flags |= WriteOnly; - setOpenMode(flags); - if (!(isReadable() || isWritable())) { - qWarning("QFile::open: File access not specified"); + if ((flags & (ReadOnly | WriteOnly)) == 0) { + qWarning("QBuffer::open: Buffer access not specified"); return false; } - if ((flags & QIODevice::Truncate) == QIODevice::Truncate) { + if ((flags & Truncate) == Truncate) d->buf->resize(0); - } - if ((flags & QIODevice::Append) == QIODevice::Append) // append to end of buffer - seek(d->buf->size()); - else - seek(0); + d->ioIndex = (flags & Append) == Append ? d->buf->size() : 0; - return true; + return QIODevice::open(flags); } /*! diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp index 8c27430..b397c1a 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/io/qdatastream.cpp @@ -584,8 +584,9 @@ void QDataStream::setByteOrder(ByteOrder bo) \value Qt_4_3 Version 9 (Qt 4.3) \value Qt_4_4 Version 10 (Qt 4.4) \value Qt_4_5 Version 11 (Qt 4.5) - \value Qt_4_6 Version 12 (Qt 4.6) + \value Qt_4_6 Version 12 (Qt 4.6, Qt 4.7, Qt 4.8) \value Qt_4_7 Same as Qt_4_6. + \value Qt_4_8 Same as Qt_4_6. \sa setVersion(), version() */ diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 9d6641c..66edf58 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -1656,6 +1656,8 @@ bool QFile::atEnd() const } /*! + \fn bool QFile::seek(qint64 pos) + For random-access devices, this function sets the current position to \a pos, returning true on success, or false if an error occurred. For sequential devices, the default behavior is to do nothing and diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 9590e39..97669ac 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -196,7 +196,7 @@ static bool _q_resolveEntryAndCreateLegacyEngine_recursive(QFileSystemEntry &ent Resolves the \a entry (see QDir::searchPaths) and returns an engine for it, but never a QFSFileEngine. - \returns a file engine that can be used to access the entry. Returns 0 if + Returns a file engine that can be used to access the entry. Returns 0 if QFileSystemEngine API should be used to query and interact with the file system object. */ diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index f1e0758..b0ebfbd 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -180,7 +180,8 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, return QFileSystemEntry(slowCanonicalized(absoluteName(entry).filePath())); #else char *ret = 0; -# if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES) +# if defined(Q_OS_MAC) +# if !defined(QT_NO_CORESERVICES) // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { ret = realpath(entry.nativeFilePath().constData(), (char*)0); @@ -197,9 +198,13 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry, return QFileSystemEntry(ret); } } -# else +# else + ret = (char*)malloc(PATH_MAX); + realpath(entry.nativeFilePath().constData(), (char*)ret); +# endif //!defined(QT_NO_CORESERVICES) +# else ret = realpath(entry.nativeFilePath().constData(), (char*)0); -# endif +# endif //defined(Q_OS_MAC) if (ret) { data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute; data.entryFlags |= QFileSystemMetaData::ExistsAttribute; diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp index 6ae6e38..4ae7cf8 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.cpp +++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp @@ -57,13 +57,15 @@ #include <sys/types.h> #include <CoreFoundation/CFRunLoop.h> #include <CoreFoundation/CFUUID.h> +#if !defined( QT_NO_CORESERVICES ) #include <CoreServices/CoreServices.h> +#endif #include <AvailabilityMacros.h> #include <private/qcore_mac_p.h> QT_BEGIN_NAMESPACE -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // Static operator overloading so for the sake of some convieniece. // They only live in this compilation unit to avoid polluting Qt in general. static bool operator==(const struct ::timespec &left, const struct ::timespec &right) @@ -152,7 +154,7 @@ QFSEventsFileSystemWatcherEngine::QFSEventsFileSystemWatcherEngine() QFSEventsFileSystemWatcherEngine::~QFSEventsFileSystemWatcherEngine() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // I assume that at this point, QFileSystemWatcher has already called stop // on me, so I don't need to invalidate or stop my stream, simply // release it. @@ -171,7 +173,7 @@ QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths, QStringList *files, QStringList *directories) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) stop(); wait(); QMutexLocker locker(&mutex); @@ -257,7 +259,7 @@ QStringList QFSEventsFileSystemWatcherEngine::addPaths(const QStringList &paths, void QFSEventsFileSystemWatcherEngine::warmUpFSEvents() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // This function assumes that the mutex has already been grabbed before calling it. // It exits with the mutex still locked (Q_ASSERT(mutex.isLocked()) ;-). start(); @@ -269,7 +271,7 @@ QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &pat QStringList *files, QStringList *directories) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) stop(); wait(); QMutexLocker locker(&mutex); @@ -336,7 +338,7 @@ QStringList QFSEventsFileSystemWatcherEngine::removePaths(const QStringList &pat #endif } -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) void QFSEventsFileSystemWatcherEngine::updateList(PathInfoList &list, bool directory, bool emitSignals) { PathInfoList::iterator End = list.end(); @@ -396,7 +398,7 @@ void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef , const FSEventStreamEventFlags eventFlags[], const FSEventStreamEventId []) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) QFSEventsFileSystemWatcherEngine *watcher = static_cast<QFSEventsFileSystemWatcherEngine *>(clientCallBackInfo); QMutexLocker locker(&watcher->mutex); CFArrayRef paths = static_cast<CFArrayRef>(eventPaths); @@ -431,7 +433,7 @@ void QFSEventsFileSystemWatcherEngine::fseventsCallback(ConstFSEventStreamRef , void QFSEventsFileSystemWatcherEngine::stop() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) QMutexLocker locker(&mutex); stopFSStream(fsStream); if (threadsRunLoop) { @@ -443,13 +445,13 @@ void QFSEventsFileSystemWatcherEngine::stop() void QFSEventsFileSystemWatcherEngine::updateFiles() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) QMutexLocker locker(&mutex); updateHash(filePathInfoHash); updateHash(dirPathInfoHash); if (filePathInfoHash.isEmpty() && dirPathInfoHash.isEmpty()) { // Everything disappeared before we got to start, don't bother. -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) // Code duplicated from stop(), with the exception that we // don't wait on waitForStop here. Doing this will lead to // a deadlock since this function is called from the worker @@ -467,7 +469,7 @@ void QFSEventsFileSystemWatcherEngine::updateFiles() void QFSEventsFileSystemWatcherEngine::run() { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) threadsRunLoop = CFRunLoopGetCurrent(); FSEventStreamScheduleWithRunLoop(fsStream, threadsRunLoop, kCFRunLoopDefaultMode); bool startedOK = FSEventStreamStart(fsStream); diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h index 2466a6e..515c32e 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -74,7 +74,7 @@ typedef uint64_t FSEventStreamEventId; QT_BEGIN_NAMESPACE -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined(QT_NO_CORESERVICES) // Yes, I use a stat64 element here. QFileInfo requires too much knowledge about implementation // details to be used as a long-standing record. Since I'm going to have to store this information, I can // do the stat myself too. @@ -117,7 +117,7 @@ private: QMutex mutex; QWaitCondition waitCondition; QWaitCondition waitForStop; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 && !defined( QT_NO_CORESERVICES ) PathHash filePathInfoHash; PathHash dirPathInfoHash; void updateHash(PathHash &pathHash); diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 4894754..0d23a27 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -472,10 +472,10 @@ qint64 QFSFileEngine::size() const return d->nativeSize(); } +#ifndef Q_OS_WIN /*! \internal */ -#ifndef Q_OS_WIN qint64 QFSFileEnginePrivate::sizeFdFh() const { Q_Q(const QFSFileEngine); diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 70a70c2..4b689c5 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -751,12 +751,16 @@ QProcessPrivate::QProcessPrivate() sequenceNumber = 0; exitCode = 0; exitStatus = QProcess::NormalExit; +#ifndef Q_OS_QNX startupSocketNotifier = 0; +#endif deathNotifier = 0; notifier = 0; pipeWriter = 0; +#ifndef Q_OS_QNX childStartedPipe[0] = INVALID_Q_PIPE; childStartedPipe[1] = INVALID_Q_PIPE; +#endif deathPipe[0] = INVALID_Q_PIPE; deathPipe[1] = INVALID_Q_PIPE; exitCode = 0; @@ -825,11 +829,13 @@ void QProcessPrivate::cleanup() qDeleteInEventHandler(stdinChannel.notifier); stdinChannel.notifier = 0; } +#ifndef Q_OS_QNX if (startupSocketNotifier) { startupSocketNotifier->setEnabled(false); qDeleteInEventHandler(startupSocketNotifier); startupSocketNotifier = 0; } +#endif if (deathNotifier) { deathNotifier->setEnabled(false); qDeleteInEventHandler(deathNotifier); @@ -842,7 +848,9 @@ void QProcessPrivate::cleanup() destroyPipe(stdoutChannel.pipe); destroyPipe(stderrChannel.pipe); destroyPipe(stdinChannel.pipe); +#ifndef Q_OS_QNX destroyPipe(childStartedPipe); +#endif destroyPipe(deathPipe); #ifdef Q_OS_UNIX serial = 0; @@ -1077,8 +1085,10 @@ bool QProcessPrivate::_q_startupNotification() qDebug("QProcessPrivate::startupNotification()"); #endif +#ifndef Q_OS_QNX if (startupSocketNotifier) startupSocketNotifier->setEnabled(false); +#endif if (processStarted()) { q->setProcessState(QProcess::Running); emit q->started(); diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 9adb331..f24a7bc 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -288,11 +288,15 @@ public: QRingBuffer errorReadBuffer; QRingBuffer writeBuffer; +#ifndef Q_OS_QNX Q_PIPE childStartedPipe[2]; +#endif Q_PIPE deathPipe[2]; void destroyPipe(Q_PIPE pipe[2]); +#ifndef Q_OS_QNX QSocketNotifier *startupSocketNotifier; +#endif QSocketNotifier *deathNotifier; // the wonderful windows notifier @@ -301,8 +305,10 @@ public: QWinEventNotifier *processFinishedNotifier; void startProcess(); -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && !defined(Q_OS_QNX) void execChild(const char *workingDirectory, char **path, char **argv, char **envp); +#elif defined(Q_OS_QNX) + pid_t spawnChild(const char *workingDirectory, char **argv, char **envp); #endif bool processStarted(); void terminateProcess(); diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index 07e3087..725e4c5 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -105,6 +105,10 @@ QT_END_NAMESPACE #include <errno.h> #include <stdlib.h> #include <string.h> +#ifdef Q_OS_QNX +# include <spawn.h> +#endif + QT_BEGIN_NAMESPACE @@ -521,16 +525,6 @@ static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environm return envp; } -// under QNX RTOS we have to use vfork() when multithreading -inline pid_t qt_fork() -{ -#if defined(Q_OS_QNX) - return vfork(); -#else - return fork(); -#endif -} - #ifdef Q_OS_MAC Q_GLOBAL_STATIC(QMutex, cfbundleMutex); #endif @@ -550,15 +544,18 @@ void QProcessPrivate::startProcess() !createChannel(stdoutChannel) || !createChannel(stderrChannel)) return; +#if !defined(Q_OS_QNX) qt_create_pipe(childStartedPipe); +#endif qt_create_pipe(deathPipe); if (threadData->eventDispatcher) { +#if !defined(Q_OS_QNX) startupSocketNotifier = new QSocketNotifier(childStartedPipe[0], QSocketNotifier::Read, q); QObject::connect(startupSocketNotifier, SIGNAL(activated(int)), q, SLOT(_q_startupNotification())); - +#endif deathNotifier = new QSocketNotifier(deathPipe[0], QSocketNotifier::Read, q); QObject::connect(deathNotifier, SIGNAL(activated(int)), @@ -650,7 +647,11 @@ void QProcessPrivate::startProcess() // Start the process manager, and fork off the child process. processManager()->lock(); - pid_t childPid = qt_fork(); +#if defined(Q_OS_QNX) + pid_t childPid = spawnChild(workingDirPtr, argv, envp); +#else + pid_t childPid = fork(); +#endif int lastForkErrno = errno; if (childPid != 0) { // Clean up duplicated memory. @@ -668,7 +669,7 @@ void QProcessPrivate::startProcess() if (childPid < 0) { // Cleanup, report error and return #if defined (QPROCESS_DEBUG) - qDebug("qt_fork failed: %s", qPrintable(qt_error_string(lastForkErrno))); + qDebug("fork() failed: %s", qPrintable(qt_error_string(lastForkErrno))); #endif processManager()->unlock(); q->setProcessState(QProcess::NotRunning); @@ -679,11 +680,13 @@ void QProcessPrivate::startProcess() return; } +#if !defined(Q_OS_QNX) // Start the child. if (childPid == 0) { execChild(workingDirPtr, path, argv, envp); ::_exit(-1); } +#endif // Register the child. In the mean time, we can get a SIGCHLD, so we need // to keep the lock held to avoid a race to catch the child. @@ -694,14 +697,15 @@ void QProcessPrivate::startProcess() // parent // close the ends we don't use and make all pipes non-blocking ::fcntl(deathPipe[0], F_SETFL, ::fcntl(deathPipe[0], F_GETFL) | O_NONBLOCK); +#if !defined(Q_OS_QNX) qt_safe_close(childStartedPipe[1]); childStartedPipe[1] = -1; +#endif if (stdinChannel.pipe[0] != -1) { qt_safe_close(stdinChannel.pipe[0]); stdinChannel.pipe[0] = -1; } - if (stdinChannel.pipe[1] != -1) ::fcntl(stdinChannel.pipe[1], F_SETFL, ::fcntl(stdinChannel.pipe[1], F_GETFL) | O_NONBLOCK); @@ -709,7 +713,6 @@ void QProcessPrivate::startProcess() qt_safe_close(stdoutChannel.pipe[1]); stdoutChannel.pipe[1] = -1; } - if (stdoutChannel.pipe[0] != -1) ::fcntl(stdoutChannel.pipe[0], F_SETFL, ::fcntl(stdoutChannel.pipe[0], F_GETFL) | O_NONBLOCK); @@ -721,6 +724,7 @@ void QProcessPrivate::startProcess() ::fcntl(stderrChannel.pipe[0], F_SETFL, ::fcntl(stderrChannel.pipe[0], F_GETFL) | O_NONBLOCK); } +#if !defined(Q_OS_QNX) void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp) { ::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored @@ -728,17 +732,17 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv Q_Q(QProcess); // copy the stdin socket (without closing on exec) - qt_safe_dup2(stdinChannel.pipe[0], fileno(stdin), 0); + qt_safe_dup2(stdinChannel.pipe[0], QT_FILENO(stdin), 0); // copy the stdout and stderr if asked to if (processChannelMode != QProcess::ForwardedChannels) { - qt_safe_dup2(stdoutChannel.pipe[1], fileno(stdout), 0); + qt_safe_dup2(stdoutChannel.pipe[1], QT_FILENO(stdout), 0); // merge stdout and stderr if asked to if (processChannelMode == QProcess::MergedChannels) { - qt_safe_dup2(fileno(stdout), fileno(stderr), 0); + qt_safe_dup2(QT_FILENO(stdout), QT_FILENO(stderr), 0); } else { - qt_safe_dup2(stderrChannel.pipe[1], fileno(stderr), 0); + qt_safe_dup2(stderrChannel.pipe[1], QT_FILENO(stderr), 0); } } @@ -807,6 +811,87 @@ bool QProcessPrivate::processStarted() return i <= 0; } +#else // Q_OS_QNX + +static pid_t doSpawn(int fd_count, int fd_map[], char **argv, char **envp, bool spawn_detached) +{ + // A multi threaded QNX Process can't fork so we call spawn() instead. + + struct inheritance inherit; + memset(&inherit, 0, sizeof(inherit)); + inherit.flags |= SPAWN_SETSID; + inherit.flags |= SPAWN_CHECK_SCRIPT; + if (spawn_detached) + inherit.flags |= SPAWN_NOZOMBIE; + inherit.flags |= SPAWN_SETSIGDEF; + sigaddset(&inherit.sigdefault, SIGPIPE); // reset the signal that we ignored + + pid_t childPid; + EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); + if (childPid == -1) { + inherit.flags |= SPAWN_SEARCH_PATH; + EINTR_LOOP(childPid, ::spawn(argv[0], fd_count, fd_map, &inherit, argv, envp)); + } + + return childPid; +} + +pid_t QProcessPrivate::spawnChild(const char *workingDir, char **argv, char **envp) +{ + Q_Q(QProcess); + + const int fd_count = 3; + int fd_map[fd_count]; + switch (processChannelMode) { + case QProcess::ForwardedChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = QT_FILENO(stdout); + fd_map[2] = QT_FILENO(stderr); + break; + case QProcess::MergedChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = stdoutChannel.pipe[1]; + fd_map[2] = stdoutChannel.pipe[1]; + break; + case QProcess::SeparateChannels: + fd_map[0] = stdinChannel.pipe[0]; + fd_map[1] = stdoutChannel.pipe[1]; + fd_map[2] = stderrChannel.pipe[1]; + break; + } + + // enter the working directory + char *oldWorkingDir = 0; + char buff[PATH_MAX + 1]; + if (workingDir) { + oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1); + QT_CHDIR(workingDir); + } + + pid_t childPid = doSpawn(fd_count, fd_map, argv, envp, false); + + if (oldWorkingDir) + QT_CHDIR(oldWorkingDir); + + if (childPid != -1) { + q->setProcessState(QProcess::Running); + QMetaObject::invokeMethod(q, "_q_startupNotification", Qt::QueuedConnection); + } + + return childPid; +} + +bool QProcessPrivate::processStarted() +{ + return processState == QProcess::Running; +} + +bool QProcessPrivate::waitForStarted(int /*msecs*/) +{ + return processStarted(); +} +#endif // Q_OS_QNX + qint64 QProcessPrivate::bytesAvailableFromStdout() const { int nbytes = 0; @@ -924,6 +1009,7 @@ static int qt_timeout_value(int msecs, int elapsed) return timeout < 0 ? 0 : timeout; } +#if !defined(Q_OS_QNX) bool QProcessPrivate::waitForStarted(int msecs) { Q_Q(QProcess); @@ -951,6 +1037,7 @@ bool QProcessPrivate::waitForStarted(int msecs) #endif return startedEmitted; } +#endif // Q_OS_QNX bool QProcessPrivate::waitForReadyRead(int msecs) { @@ -972,8 +1059,10 @@ bool QProcessPrivate::waitForReadyRead(int msecs) int nfds = deathPipe[0]; FD_SET(deathPipe[0], &fdread); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -994,10 +1083,12 @@ bool QProcessPrivate::waitForReadyRead(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif bool readyReadEmitted = false; if (stdoutChannel.pipe[0] != -1 && FD_ISSET(stdoutChannel.pipe[0], &fdread)) { @@ -1044,8 +1135,10 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) int nfds = deathPipe[0]; FD_SET(deathPipe[0], &fdread); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -1068,10 +1161,12 @@ bool QProcessPrivate::waitForBytesWritten(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) return _q_canWrite(); @@ -1109,8 +1204,10 @@ bool QProcessPrivate::waitForFinished(int msecs) FD_ZERO(&fdread); FD_ZERO(&fdwrite); +#if !defined(Q_OS_QNX) if (processState == QProcess::Starting) add_fd(nfds, childStartedPipe[0], &fdread); +#endif if (stdoutChannel.pipe[0] != -1) add_fd(nfds, stdoutChannel.pipe[0], &fdread); @@ -1134,10 +1231,12 @@ bool QProcessPrivate::waitForFinished(int msecs) return false; } +#if !defined(Q_OS_QNX) if (childStartedPipe[0] != -1 && FD_ISSET(childStartedPipe[0], &fdread)) { if (!_q_startupNotification()) return false; } +#endif if (stdinChannel.pipe[1] != -1 && FD_ISSET(stdinChannel.pipe[1], &fdwrite)) _q_canWrite(); @@ -1199,6 +1298,47 @@ void QProcessPrivate::_q_notified() { } +#if defined(Q_OS_QNX) +bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) +{ + QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory); + + // enter the working directory + char *oldWorkingDir = 0; + char buff[PATH_MAX + 1]; + if (!encodedWorkingDirectory.isEmpty()) { + oldWorkingDir = QT_GETCWD(buff, PATH_MAX + 1); + QT_CHDIR(encodedWorkingDirectory.constData()); + } + + const int fd_count = 3; + int fd_map[fd_count] = { QT_FILENO(stdin), QT_FILENO(stdout), QT_FILENO(stderr) }; + + QList<QByteArray> enc_args; + enc_args.append(QFile::encodeName(program)); + for (int i = 0; i < arguments.size(); ++i) + enc_args.append(arguments.at(i).toLocal8Bit()); + + const int argc = enc_args.size(); + QScopedArrayPointer<char*> raw_argv(new char*[argc + 1]); + for (int i = 0; i < argc; ++i) + raw_argv[i] = const_cast<char *>(enc_args.at(i).data()); + raw_argv[argc] = 0; + + char **envp = 0; // inherit environment + + pid_t childPid = doSpawn(fd_count, fd_map, raw_argv.data(), envp, true); + if (pid && childPid != -1) + *pid = childPid; + + if (oldWorkingDir) + QT_CHDIR(oldWorkingDir); + + return childPid != -1; +} + +#else + bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) { processManager()->start(); @@ -1212,7 +1352,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a int pidPipe[2]; qt_safe_pipe(pidPipe); - pid_t childPid = qt_fork(); + pid_t childPid = fork(); if (childPid == 0) { struct sigaction noaction; memset(&noaction, 0, sizeof(noaction)); @@ -1224,7 +1364,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a qt_safe_close(startedPipe[0]); qt_safe_close(pidPipe[0]); - pid_t doubleForkPid = qt_fork(); + pid_t doubleForkPid = fork(); if (doubleForkPid == 0) { qt_safe_close(pidPipe[1]); @@ -1312,6 +1452,7 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a qt_safe_close(pidPipe[0]); return success; } +#endif // Q_OS_QNX void QProcessPrivate::initializeProcessManager() { diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 83b49ce..8813656 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -6105,7 +6105,7 @@ bool QUrl::isDetached() const "//servername/path/to/file.txt". Note that only certain platforms can actually open this file using QFile::open(). - \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators + \sa toLocalFile(), isLocalFile(), QDir::toNativeSeparators() */ QUrl QUrl::fromLocalFile(const QString &localFile) { diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp index 0814c1a..490031f 100644 --- a/src/corelib/kernel/qcore_mac.cpp +++ b/src/corelib/kernel/qcore_mac.cpp @@ -41,22 +41,22 @@ #include <private/qcore_mac_p.h> #include <new> -#include "qvarlengtharray.h" QT_BEGIN_NAMESPACE QString QCFString::toQString(CFStringRef str) { - if(!str) + if (!str) return QString(); + CFIndex length = CFStringGetLength(str); - const UniChar *chars = CFStringGetCharactersPtr(str); - if (chars) - return QString(reinterpret_cast<const QChar *>(chars), length); + if (length == 0) + return QString(); + + QString string(length, Qt::Uninitialized); + CFStringGetCharacters(str, CFRangeMake(0, length), reinterpret_cast<UniChar *>(const_cast<QChar *>(string.unicode()))); - QVarLengthArray<UniChar> buffer(length); - CFStringGetCharacters(str, CFRangeMake(0, length), buffer.data()); - return QString(reinterpret_cast<const QChar *>(buffer.constData()), length); + return string; } QCFString::operator QString() const @@ -74,9 +74,68 @@ CFStringRef QCFString::toCFStringRef(const QString &string) QCFString::operator CFStringRef() const { - if (!type) - const_cast<QCFString*>(this)->type = toCFStringRef(string); + if (!type) { + if (string.d->data != string.d->array) + const_cast<QCFString*>(this)->string.realloc(); // ### Qt5: do we really need this stupid user protection? + const_cast<QCFString*>(this)->type = + CFStringCreateWithCharactersNoCopy(0, + reinterpret_cast<const UniChar *>(string.unicode()), + string.length(), + kCFAllocatorNull); + } return type; } + +#ifndef QT_NO_CORESERVICES +void qt_mac_to_pascal_string(const QString &s, Str255 str, TextEncoding encoding, int len) +{ + if(len == -1) + len = s.length(); +#if 0 + UnicodeMapping mapping; + mapping.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, + kTextEncodingDefaultVariant, + kUnicode16BitFormat); + mapping.otherEncoding = (encoding ? encoding : ); + mapping.mappingVersion = kUnicodeUseLatestMapping; + + UnicodeToTextInfo info; + OSStatus err = CreateUnicodeToTextInfo(&mapping, &info); + if(err != noErr) { + qDebug("Qt: internal: Unable to create pascal string '%s'::%d [%ld]", + s.left(len).latin1(), (int)encoding, err); + return; + } + const int unilen = len * 2; + const UniChar *unibuf = (UniChar *)s.unicode(); + ConvertFromUnicodeToPString(info, unilen, unibuf, str); + DisposeUnicodeToTextInfo(&info); +#else + Q_UNUSED(encoding); + CFStringGetPascalString(QCFString(s), str, 256, CFStringGetSystemEncoding()); +#endif +} + +QString qt_mac_from_pascal_string(const Str255 pstr) +{ + return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); +} + +OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref) +{ + return FSPathMakeRef(reinterpret_cast<const UInt8 *>(file.toUtf8().constData()), fsref, 0); +} + +// Don't use this function, it won't work in 10.5 (Leopard) and up +OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec) +{ + FSRef fsref; + OSErr ret = qt_mac_create_fsref(file, &fsref); + if (ret == noErr) + ret = FSGetCatalogInfo(&fsref, kFSCatInfoNone, 0, 0, spec, 0); + return ret; +} +#endif // QT_NO_CORESERVICES + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index adbad83..df269ec 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -148,6 +148,16 @@ private: QString string; }; + +#ifndef QT_NO_CORESERVICES +Q_CORE_EXPORT void qt_mac_to_pascal_string(const QString &s, Str255 str, TextEncoding encoding = 0, int len = -1); +Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr); + +Q_CORE_EXPORT OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref); +// Don't use this function, it won't work in 10.5 (Leopard) and up +Q_CORE_EXPORT OSErr qt_mac_create_fsspec(const QString &file, FSSpec *spec); +#endif // QT_NO_CORESERVICES + QT_END_NAMESPACE #if (MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7694a0f..18a5eae 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -98,6 +98,12 @@ # include <taskLib.h> #endif +#ifdef Q_OS_QNX +# include <sys/neutrino.h> +# include <pthread.h> +# include <sched.h> +#endif + QT_BEGIN_NAMESPACE class QMutexUnlocker @@ -353,6 +359,22 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint qt_application_thread_id = QThread::currentThreadId(); #endif +#ifdef Q_OS_QNX + // make the kernel attempt to emulate an instruction with a misaligned access + // if the attempt fails, it faults with a SIGBUS + int tv = -1; + ThreadCtl(_NTO_TCTL_ALIGN_FAULT, &tv); + + // without Round Robin drawn intensive apps will hog the cpu + // and make the system appear frozen + int sched_policy; + sched_param param; + if (pthread_getschedparam(0, &sched_policy, ¶m) == 0 && sched_policy != SCHED_RR) { + sched_policy = SCHED_RR; + pthread_setschedparam(0, sched_policy, ¶m); + } +#endif + // note: this call to QThread::currentThread() may end up setting theMainThread! if (QThread::currentThread() != theMainThread) qWarning("WARNING: QApplication was not created in the main() thread."); @@ -1266,20 +1288,7 @@ void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority) // delete the event on exceptions to protect against memory leaks till the event is // properly owned in the postEventList QScopedPointer<QEvent> eventDeleter(event); - if (data->postEventList.isEmpty() || data->postEventList.last().priority >= priority) { - // optimization: we can simply append if the last event in - // the queue has higher or equal priority - data->postEventList.append(QPostEvent(receiver, event, priority)); - } else { - // insert event in descending priority order, using upper - // bound for a given priority (to ensure proper ordering - // of events with the same priority) - QPostEventList::iterator begin = data->postEventList.begin() - + data->postEventList.insertionOffset, - end = data->postEventList.end(); - QPostEventList::iterator at = qUpperBound(begin, end, priority); - data->postEventList.insert(at, QPostEvent(receiver, event, priority)); - } + data->postEventList.addEvent(QPostEvent(receiver, event, priority)); eventDeleter.take(); event->posted = true; ++receiver->d_func()->postedEvents; @@ -1439,7 +1448,7 @@ void QCoreApplicationPrivate::sendPostedEvents(QObject *receiver, int event_type // cannot send deferred delete if (!event_type && !receiver) { // don't lose the event - data->postEventList.append(pe); + data->postEventList.addEvent(pe); const_cast<QPostEvent &>(pe).event = 0; } continue; diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index a4948c1..88618c3 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1482,7 +1482,7 @@ void QObjectPrivate::setThreadData_helper(QThreadData *currentData, QThreadData continue; if (pe.receiver == q) { // move this post event to the targetList - targetData->postEventList.append(pe); + targetData->postEventList.addEvent(pe); const_cast<QPostEvent &>(pe).event = 0; ++eventsMoved; } @@ -1790,6 +1790,7 @@ QObjectList QObject::queryList(const char *inheritsClass, /*! \fn T qFindChild(const QObject *obj, const QString &name) \relates QObject + \overload qFindChildren() \obsolete This function is equivalent to @@ -1805,6 +1806,7 @@ QObjectList QObject::queryList(const char *inheritsClass, /*! \fn QList<T> qFindChildren(const QObject *obj, const QString &name) \relates QObject + \overload qFindChildren() \obsolete This function is equivalent to @@ -1834,38 +1836,6 @@ QObjectList QObject::queryList(const char *inheritsClass, /*! \internal - \fn T qFindChild(const QObject *obj, const QString &name = QString(), T dummy = 0) - \relates QObject - \overload qFindChildren() - - This function is equivalent to - \a{obj}->\l{QObject::findChild()}{findChild}<T>(\a name). - - \note This function was provided as a workaround for MSVC 6 - which did not support member template functions. It is advised - to use the other form in new code. - - \sa QObject::findChild() -*/ - -/*! - \internal - \fn QList<T> qFindChildren(const QObject *obj, const QString &name = QString(), T dummy = 0) - \relates QObject - \overload qFindChildren() - - This function is equivalent to - \a{obj}->\l{QObject::findChildren()}{findChildren}<T>(\a name). - - \note This function was provided as a workaround for MSVC 6 - which did not support member template functions. It is advised - to use the other form in new code. - - \sa QObject::findChildren() -*/ - -/*! - \internal */ void qt_qFindChildren_helper(const QObject *parent, const QString &name, const QRegExp *re, const QMetaObject &mo, QList<void*> *list) @@ -2419,20 +2389,22 @@ int QObject::receivers(const char *signal) const This helper function calculates signal and method index for the given member in the specified class. - \li If member.mobj is 0 then both signalIndex and methodIndex are set to -1. + \list + \o If member.mobj is 0 then both signalIndex and methodIndex are set to -1. - \li If specified member is not a member of obj instance class (or one of + \o If specified member is not a member of obj instance class (or one of its parent classes) then both signalIndex and methodIndex are set to -1. + \endlist This function is used by QObject::connect and QObject::disconnect which are working with QMetaMethod. - \param[out] signalIndex is set to the signal index of member. If the member + \a signalIndex is set to the signal index of member. If the member specified is not signal this variable is set to -1. - \param[out] methodIndex is set to the method index of the member. If the - member is not a method of the object specified by obj param this variable - is set to -1. + \a methodIndex is set to the method index of the member. If the + member is not a method of the object specified by the \a obj argument this + variable is set to -1. */ void QMetaObjectPrivate::memberIndexes(const QObject *obj, const QMetaMethod &member, @@ -2689,9 +2661,9 @@ bool QObject::connect(const QObject *sender, const char *signal, Qt::ConnectionType type) but it uses QMetaMethod to specify signal and method. - \see connect(const QObject *sender, const char *signal, - const QObject *receiver, const char *method, - Qt::ConnectionType type) + \sa connect(const QObject *sender, const char *signal, + const QObject *receiver, const char *method, + Qt::ConnectionType type) */ bool QObject::connect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method, @@ -2987,7 +2959,7 @@ bool QObject::disconnect(const QObject *sender, const char *signal, In the same way 0 can be used for \a receiver in the meaning "any receiving object". In this case method shoud also be QMetaMethod(). \a sender parameter should be never 0. - \see disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) + \sa disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method) */ bool QObject::disconnect(const QObject *sender, const QMetaMethod &signal, const QObject *receiver, const QMetaMethod &method) diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index d274fa3..15d81b9 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -345,6 +345,11 @@ public: }; #endif +#ifdef qdoc +T qFindChild(const QObject *o, const QString &name = QString()); +QList<T> qFindChildren(const QObject *oobj, const QString &name = QString()); +QList<T> qFindChildren(const QObject *o, const QRegExp &re); +#endif #ifdef QT_DEPRECATED template<typename T> inline QT_DEPRECATED T qFindChild(const QObject *o, const QString &name = QString()) diff --git a/src/corelib/kernel/qsharedmemory.cpp b/src/corelib/kernel/qsharedmemory.cpp index 2882279..371974c 100644 --- a/src/corelib/kernel/qsharedmemory.cpp +++ b/src/corelib/kernel/qsharedmemory.cpp @@ -80,6 +80,8 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, return result; #elif defined(Q_OS_SYMBIAN) return result.left(KMaxKernelName); +#elif defined(QT_POSIX_IPC) + return QLatin1Char('/') + result; #else return QDir::tempPath() + QLatin1Char('/') + result; #endif @@ -117,6 +119,9 @@ QSharedMemoryPrivate::makePlatformSafeKey(const QString &key, process crashes without running the QSharedMemory destructor, the shared memory segment survives the crash. + \o QNX: Due to possible race conditions in the POSIX IPC implementation, create() + should be called prior to any attach() calls (even across multiple threads). + \o HP-UX: Only one attach to a shared memory segment is allowed per process. This means that QSharedMemory should not be used across multiple threads in the same process in HP-UX. diff --git a/src/corelib/kernel/qsharedmemory_p.h b/src/corelib/kernel/qsharedmemory_p.h index 21b8612..780e52e 100644 --- a/src/corelib/kernel/qsharedmemory_p.h +++ b/src/corelib/kernel/qsharedmemory_p.h @@ -135,6 +135,8 @@ public: const QString &prefix = QLatin1String("qipc_sharedmemory_")); #ifdef Q_OS_WIN HANDLE handle(); +#elif defined(QT_POSIX_IPC) + int handle(); #else key_t handle(); #endif @@ -166,6 +168,8 @@ private: HANDLE hand; #elif defined(Q_OS_SYMBIAN) RChunk chunk; +#elif defined(QT_POSIX_IPC) + int hand; #else key_t unix_key; #endif diff --git a/src/corelib/kernel/qsharedmemory_unix.cpp b/src/corelib/kernel/qsharedmemory_unix.cpp index e991ce9..a086acd 100644 --- a/src/corelib/kernel/qsharedmemory_unix.cpp +++ b/src/corelib/kernel/qsharedmemory_unix.cpp @@ -50,8 +50,12 @@ #ifndef QT_NO_SHAREDMEMORY #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/shm.h> +#else +#include <sys/mman.h> #include <sys/stat.h> +#endif #include <fcntl.h> #include <unistd.h> #endif // QT_NO_SHAREDMEMORY @@ -70,7 +74,11 @@ QSharedMemoryPrivate::QSharedMemoryPrivate() #ifndef QT_NO_SYSTEMSEMAPHORE systemSemaphore(QString()), lockedByMe(false), #endif +#ifndef QT_POSIX_IPC unix_key(0) +#else + hand(0) +#endif { } @@ -91,12 +99,18 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) errorString = QSharedMemory::tr("%1: doesn't exist").arg(function); error = QSharedMemory::NotFound; break; + case EAGAIN: case EMFILE: + case ENFILE: case ENOMEM: case ENOSPC: errorString = QSharedMemory::tr("%1: out of resources").arg(function); error = QSharedMemory::OutOfResources; break; + case EOVERFLOW: + errorString = QSharedMemory::tr("%1: invalid size").arg(function); + error = QSharedMemory::InvalidSize; + break; default: errorString = QSharedMemory::tr("%1: unknown error %2").arg(function).arg(errno); error = QSharedMemory::UnknownError; @@ -112,6 +126,7 @@ void QSharedMemoryPrivate::setErrorString(const QString &function) If not already made create the handle used for accessing the shared memory. */ +#ifndef QT_POSIX_IPC key_t QSharedMemoryPrivate::handle() { // already made @@ -140,6 +155,20 @@ key_t QSharedMemoryPrivate::handle() } return unix_key; } +#else +int QSharedMemoryPrivate::handle() +{ + // don't allow making handles on empty keys + QString safeKey = makePlatformSafeKey(key); + if (safeKey.isEmpty()) { + errorString = QSharedMemory::tr("%1: key is empty").arg(QLatin1String("QSharedMemory::handle")); + error = QSharedMemory::KeyError; + return 0; + } + + return 1; +} +#endif // QT_POSIX_IPC #endif // QT_NO_SHAREDMEMORY @@ -155,6 +184,7 @@ key_t QSharedMemoryPrivate::handle() */ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) { +#ifndef QT_POSIX_IPC if (QFile::exists(fileName)) return 0; @@ -168,6 +198,11 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) qt_safe_close(fd); } return 1; +#else + Q_UNUSED(fileName); + // nothing to do + return -1; +#endif } #endif // QT_NO_SHAREDMEMORY && QT_NO_SYSTEMSEMAPHORE @@ -175,11 +210,17 @@ int QSharedMemoryPrivate::createUnixKeyFile(const QString &fileName) void QSharedMemoryPrivate::cleanHandle() { +#ifndef QT_POSIX_IPC unix_key = 0; +#else + qt_safe_close(hand); + hand = 0; +#endif } bool QSharedMemoryPrivate::create(int size) { +#ifndef QT_POSIX_IPC // build file if needed int built = createUnixKeyFile(nativeKey); if (built == -1) { @@ -211,12 +252,46 @@ bool QSharedMemoryPrivate::create(int size) QFile::remove(nativeKey); return false; } +#else + if (!handle()) + return false; + + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + + int fd; + EINTR_LOOP(fd, shm_open(shmName.constData(), O_RDWR | O_CREAT | O_EXCL, 0666)); + if (fd == -1) { + QString function = QLatin1String("QSharedMemory::create"); + switch (errno) { + case ENAMETOOLONG: + case EINVAL: + errorString = QSharedMemory::tr("%1: bad name").arg(function); + error = QSharedMemory::KeyError; + break; + default: + setErrorString(function); + } + return false; + } + + // the size may only be set once; ignore errors + int ret; + EINTR_LOOP(ret, ftruncate(fd, size)); + if (ret == -1) { + setErrorString(QLatin1String("QSharedMemory::create (ftruncate)")); + qt_safe_close(fd); + return false; + } + + qt_safe_close(fd); +#endif // QT_POSIX_IPC return true; } bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) { +#ifndef QT_POSIX_IPC // grab the shared memory segment id int id = shmget(unix_key, 0, (mode == QSharedMemory::ReadOnly ? 0444 : 0660)); if (-1 == id) { @@ -240,12 +315,55 @@ bool QSharedMemoryPrivate::attach(QSharedMemory::AccessMode mode) setErrorString(QLatin1String("QSharedMemory::attach (shmctl)")); return false; } +#else + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + + int oflag = (mode == QSharedMemory::ReadOnly ? O_RDONLY : O_RDWR); + mode_t omode = (mode == QSharedMemory::ReadOnly ? 0444 : 0660); + + EINTR_LOOP(hand, shm_open(shmName.constData(), oflag, omode)); + if (hand == -1) { + QString function = QLatin1String("QSharedMemory::attach (shm_open)"); + switch (errno) { + case ENAMETOOLONG: + case EINVAL: + errorString = QSharedMemory::tr("%1: bad name").arg(function); + error = QSharedMemory::KeyError; + break; + default: + setErrorString(function); + } + hand = 0; + return false; + } + + // grab the size + QT_STATBUF st; + if (QT_FSTAT(hand, &st) == -1) { + setErrorString(QLatin1String("QSharedMemory::attach (fstat)")); + cleanHandle(); + return false; + } + size = st.st_size; + + // grab the memory + int mprot = (mode == QSharedMemory::ReadOnly ? PROT_READ : PROT_READ | PROT_WRITE); + memory = mmap(0, size, mprot, MAP_SHARED, hand, 0); + if (memory == MAP_FAILED || !memory) { + setErrorString(QLatin1String("QSharedMemory::attach (mmap)")); + cleanHandle(); + memory = 0; + size = 0; + return false; + } +#endif // QT_POSIX_IPC return true; } bool QSharedMemoryPrivate::detach() { +#ifndef QT_POSIX_IPC // detach from the memory segment if (-1 == shmdt(memory)) { QString function = QLatin1String("QSharedMemory::detach"); @@ -292,6 +410,31 @@ bool QSharedMemoryPrivate::detach() if (!QFile::remove(nativeKey)) return false; } +#else + // detach from the memory segment + if (munmap(memory, size) == -1) { + setErrorString(QLatin1String("QSharedMemory::detach (munmap)")); + return false; + } + memory = 0; + size = 0; + + // get the number of current attachments + int shm_nattch = 0; + QT_STATBUF st; + if (QT_FSTAT(hand, &st) == 0) { + // subtract 2 from linkcount: one for our own open and one for the dir entry + shm_nattch = st.st_nlink - 2; + } + cleanHandle(); + // if there are no attachments then unlink the shared memory + if (shm_nattch == 0) { + QByteArray shmName = QFile::encodeName(makePlatformSafeKey(key)); + if (shm_unlink(shmName.constData()) == -1 && errno != ENOENT) + setErrorString(QLatin1String("QSharedMemory::detach (shm_unlink)")); + } +#endif // QT_POSIX_IPC + return true; } diff --git a/src/corelib/kernel/qsystemsemaphore.cpp b/src/corelib/kernel/qsystemsemaphore.cpp index 98ee6f4..ae30348 100644 --- a/src/corelib/kernel/qsystemsemaphore.cpp +++ b/src/corelib/kernel/qsystemsemaphore.cpp @@ -151,6 +151,11 @@ QT_BEGIN_NAMESPACE creates a new semaphore for that key and sets its resource count to \a initialValue. + In QNX, if the \a mode is \l {QSystemSemaphore::} {Create} and the + system already has a semaphore identified by \a key, that semaphore + will be deleted and the new one will be created for that key with + a resource count set to \a initialValue. + In Windows and in Symbian, \a mode is ignored, and the system always tries to create a semaphore for the specified \a key. If the system does not already have a semaphore identified as \a key, it creates the @@ -234,7 +239,7 @@ void QSystemSemaphore::setKey(const QString &key, int initialValue, AccessMode m return; d->error = NoError; d->errorString = QString(); -#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) +#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN) && !defined(QT_POSIX_IPC) // optimization to not destroy/create the file & semaphore if (key == d->key && mode == Create && d->createdSemaphore && d->createdFile) { d->initialValue = initialValue; diff --git a/src/corelib/kernel/qsystemsemaphore_p.h b/src/corelib/kernel/qsystemsemaphore_p.h index 3e5f737..d84d416 100644 --- a/src/corelib/kernel/qsystemsemaphore_p.h +++ b/src/corelib/kernel/qsystemsemaphore_p.h @@ -61,6 +61,9 @@ #ifndef Q_OS_WINCE # include <sys/types.h> #endif +#ifdef QT_POSIX_IPC +# include <semaphore.h> +#endif #ifdef Q_OS_SYMBIAN class RSemaphore; @@ -84,6 +87,9 @@ public: #elif defined(Q_OS_SYMBIAN) int handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); void setErrorString(const QString &function,int err = 0); +#elif defined(QT_POSIX_IPC) + bool handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); + void setErrorString(const QString &function); #else key_t handle(QSystemSemaphore::AccessMode mode = QSystemSemaphore::Open); void setErrorString(const QString &function); @@ -99,6 +105,9 @@ public: HANDLE semaphoreLock; #elif defined(Q_OS_SYMBIAN) RSemaphore semaphore; +#elif defined(QT_POSIX_IPC) + sem_t *semaphore; + bool createdSemaphore; #else key_t unix_key; int semaphore; diff --git a/src/corelib/kernel/qsystemsemaphore_unix.cpp b/src/corelib/kernel/qsystemsemaphore_unix.cpp index 704afaf..e060eb2 100644 --- a/src/corelib/kernel/qsystemsemaphore_unix.cpp +++ b/src/corelib/kernel/qsystemsemaphore_unix.cpp @@ -50,7 +50,9 @@ #include <sys/types.h> #include <sys/ipc.h> +#ifndef QT_POSIX_IPC #include <sys/sem.h> +#endif #include <fcntl.h> #include <errno.h> @@ -67,7 +69,11 @@ QT_BEGIN_NAMESPACE QSystemSemaphorePrivate::QSystemSemaphorePrivate() : +#ifndef QT_POSIX_IPC unix_key(-1), semaphore(-1), createdFile(false), +#else + semaphore(SEM_FAILED), +#endif createdSemaphore(false), error(QSystemSemaphore::NoError) { } @@ -90,10 +96,18 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function) error = QSystemSemaphore::NotFound; break; case ERANGE: + case ENOMEM: case ENOSPC: + case EMFILE: + case ENFILE: + case EOVERFLOW: errorString = QCoreApplication::translate("QSystemSemaphore", "%1: out of resources").arg(function); error = QSystemSemaphore::OutOfResources; break; + case ENAMETOOLONG: + errorString = QCoreApplication::translate("QSystemSemaphore", "%1: name error").arg(function); + error = QSystemSemaphore::KeyError; + break; default: errorString = QCoreApplication::translate("QSystemSemaphore", "%1: unknown error %2").arg(function).arg(errno); error = QSystemSemaphore::UnknownError; @@ -109,6 +123,7 @@ void QSystemSemaphorePrivate::setErrorString(const QString &function) Initialise the semaphore */ +#ifndef QT_POSIX_IPC key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) { if (-1 != unix_key) @@ -170,6 +185,54 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) return unix_key; } +#else +bool QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) +{ + if (semaphore != SEM_FAILED) + return true; // we already have a semaphore + + if (fileName.isEmpty()) { + errorString = QCoreApplication::tr("%1: key is empty", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle")); + error = QSystemSemaphore::KeyError; + return false; + } + + QByteArray semName = QFile::encodeName(fileName); + + // Always try with O_EXCL so we know whether we created the semaphore. + int oflag = O_CREAT | O_EXCL; + for (int tryNum = 0, maxTries = 1; tryNum < maxTries; ++tryNum) { + do { + semaphore = sem_open(semName.constData(), oflag, 0666, initialValue); + } while (semaphore == SEM_FAILED && errno == EINTR); + if (semaphore == SEM_FAILED && errno == EEXIST) { + if (mode == QSystemSemaphore::Create) { + if (sem_unlink(semName.constData()) == -1 && errno != ENOENT) { + setErrorString(QLatin1String("QSystemSemaphore::handle (sem_unlink)")); + return false; + } + // Race condition: the semaphore might be recreated before + // we call sem_open again, so we'll retry several times. + maxTries = 3; + } else { + // Race condition: if it no longer exists at the next sem_open + // call, we won't realize we created it, so we'll leak it later. + oflag &= ~O_EXCL; + maxTries = 2; + } + } else { + break; + } + } + if (semaphore == SEM_FAILED) { + setErrorString(QLatin1String("QSystemSemaphore::handle")); + return false; + } + + createdSemaphore = (oflag & O_EXCL) != 0; + return true; +} +#endif // QT_POSIX_IPC /*! \internal @@ -178,6 +241,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode) */ void QSystemSemaphorePrivate::cleanHandle() { +#ifndef QT_POSIX_IPC unix_key = -1; // remove the file if we made it @@ -198,6 +262,27 @@ void QSystemSemaphorePrivate::cleanHandle() } createdSemaphore = false; } +#else + if (semaphore != SEM_FAILED) { + if (sem_close(semaphore) == -1) { + setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_close)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_close failed."); +#endif + } + semaphore = SEM_FAILED; + } + + if (createdSemaphore) { + if (sem_unlink(QFile::encodeName(fileName).constData()) == -1 && errno != ENOENT) { + setErrorString(QLatin1String("QSystemSemaphore::cleanHandle (sem_unlink)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::cleanHandle sem_unlink failed."); +#endif + } + createdSemaphore = false; + } +#endif // QT_POSIX_IPC } /*! @@ -205,6 +290,7 @@ void QSystemSemaphorePrivate::cleanHandle() */ bool QSystemSemaphorePrivate::modifySemaphore(int count) { +#ifndef QT_POSIX_IPC if (-1 == handle()) return false; @@ -229,6 +315,44 @@ bool QSystemSemaphorePrivate::modifySemaphore(int count) #endif return false; } +#else + if (!handle()) + return false; + + if (count > 0) { + int cnt = count; + do { + if (sem_post(semaphore) == -1) { + setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_post)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::modify sem_post failed") << count << errno; +#endif + // rollback changes to preserve the SysV semaphore behavior + for ( ; cnt < count; ++cnt) { + register int res; + EINTR_LOOP(res, sem_wait(semaphore)); + } + return false; + } + --cnt; + } while (cnt > 0); + } else { + register int res; + EINTR_LOOP(res, sem_wait(semaphore)); + if (res == -1) { + // If the semaphore was removed be nice and create it and then modifySemaphore again + if (errno == EINVAL || errno == EIDRM) { + semaphore = SEM_FAILED; + return modifySemaphore(count); + } + setErrorString(QLatin1String("QSystemSemaphore::modifySemaphore (sem_wait)")); +#ifdef QSYSTEMSEMAPHORE_DEBUG + qDebug() << QLatin1String("QSystemSemaphore::modify sem_wait failed") << count << errno; +#endif + return false; + } + } +#endif // QT_POSIX_IPC return true; } diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 3c8704c..0edcb3b 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -205,6 +205,9 @@ QTimer::~QTimer() Starts or restarts the timer with the timeout specified in \l interval. + If the timer is already running, it will be + \l{QTimer::stop()}{stopped} and restarted. + If \l singleShot is true, the timer will be activated only once. */ void QTimer::start() @@ -218,6 +221,12 @@ void QTimer::start() /*! Starts or restarts the timer with a timeout interval of \a msec milliseconds. + + If the timer is already running, it will be + \l{QTimer::stop()}{stopped} and restarted. + + If \l singleShot is true, the timer will be activated only once. + */ void QTimer::start(int msec) { diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 4504eab..d255422 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -600,7 +600,7 @@ static QString find_translation(const QLocale & locale, /*! \since 4.8 - Loads \a filename + \a prefix + \a \l{QLocale::uiLanguages()}{ui language + Loads \a filename + \a prefix + \l{QLocale::uiLanguages()}{ui language name} + \a suffix (".qm" if the \a suffix is not specified), which may be an absolute file name or relative to \a directory. Returns true if the translation is successfully loaded; otherwise returns false. @@ -618,7 +618,7 @@ static QString find_translation(const QLocale & locale, \endlist For example, an application running in the locale with the following - l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call + \l{QLocale::uiLanguages()}{ui languages} - "es", "fr-CA", "de" might call load(QLocale::system(), "foo", ".", "/opt/foolib", ".qm"). load() would replace '-' (dash) with '_' (underscore) in the ui language and then try to open the first existing readable file from this list: @@ -637,8 +637,8 @@ static QString find_translation(const QLocale & locale, \o \c /opt/foolib/foo \endlist - For OSs where file system is case sensitive, QTranslator also tries to load - a lower-cased version of the locale name. + On operating systems where file system is case sensitive, QTranslator also + tries to load a lower-cased version of the locale name. */ bool QTranslator::load(const QLocale & locale, const QString & filename, diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp index 03ab047..49fb46b 100644 --- a/src/corelib/thread/qmutexpool.cpp +++ b/src/corelib/thread/qmutexpool.cpp @@ -123,7 +123,8 @@ QMutexPool *QMutexPool::instance() return globalMutexPool(); } -/*! \fn QMutexPool::get(void *address) +/*! + \fn QMutexPool::get(const void *address) Returns a QMutex from the pool. QMutexPool uses the value \a address to determine which mutex is returned from the pool. */ diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index 02a63bb..5dfc946 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -434,6 +434,12 @@ bool QThread::isRunning() const { Q_D(const QThread); QMutexLocker locker(&d->mutex); +#ifdef Q_OS_SYMBIAN + // app shutdown on Symbian can terminate threads and invalidate their stacks without notification, + // check the thread is still alive. + if (d->data->symbian_thread_handle.Handle() && d->data->symbian_thread_handle.ExitType() != EExitPending) + return false; +#endif return d->running; } diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h index 13df3e6..461d93d 100644 --- a/src/corelib/thread/qthread_p.h +++ b/src/corelib/thread/qthread_p.h @@ -93,6 +93,8 @@ inline bool operator<(const QPostEvent &pe, int priority) return priority < pe.priority; } +// This class holds the list of posted events. +// The list has to be kept sorted by priority class QPostEventList : public QList<QPostEvent> { public: @@ -109,6 +111,25 @@ public: inline QPostEventList() : QList<QPostEvent>(), recursion(0), startOffset(0), insertionOffset(0) { } + + void addEvent(const QPostEvent &ev) { + int priority = ev.priority; + if (isEmpty() || last().priority >= priority) { + // optimization: we can simply append if the last event in + // the queue has higher or equal priority + append(ev); + } else { + // insert event in descending priority order, using upper + // bound for a given priority (to ensure proper ordering + // of events with the same priority) + QPostEventList::iterator at = qUpperBound(begin() + insertionOffset, end(), priority); + insert(at, ev); + } + } +private: + //hides because they do not keep that list sorted. addEvent must be used + using QList<QPostEvent>::append; + using QList<QPostEvent>::insert; }; #ifndef QT_NO_THREAD diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 839a396..765969e 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -479,6 +479,11 @@ void QThread::usleep(unsigned long usecs) // sched_priority is OUT only static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority) { +#ifdef Q_OS_QNX + // without Round Robin drawn intensive apps will hog the cpu + // and make the system appear frozen + *sched_policy = SCHED_RR; +#endif #ifdef SCHED_IDLE if (priority == QThread::IdlePriority) { *sched_policy = SCHED_IDLE; diff --git a/src/corelib/tools/qlist.cpp b/src/corelib/tools/qlist.cpp index 1c1d684..36a9c60 100644 --- a/src/corelib/tools/qlist.cpp +++ b/src/corelib/tools/qlist.cpp @@ -590,10 +590,10 @@ void **QListData::erase(void **xi) \sa operator=() */ -/*! \fn QList::QList(std::initializer_list<T> args) +/*! \fn inline QList::QList(std::initializer_list<T> args) \since 4.8 - Construct a list from a std::initilizer_list. + Construct a list from the std::initializer_list specified by \a args. This constructor is only enabled if the compiler supports C++0x */ diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 5a2e153..d791529 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -934,7 +934,7 @@ QLocale::Country QLocale::country() const name() will not contain it for compatibility reasons. Use bcp47Name() instead if you need a full locale name. - \sa QLocale(const QString &), language(), script(), country(), bcp47Name() + \sa QLocale(), language(), script(), country(), bcp47Name() */ QString QLocale::name() const diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc index 34e4fb3..fd139c3 100644 --- a/src/corelib/tools/qlocale.qdoc +++ b/src/corelib/tools/qlocale.qdoc @@ -769,6 +769,8 @@ \value Weekdays a QList<Qt::DayOfWeek> specifying the regular weekdays \value LocaleChanged this type is queried whenever the system locale is changed. \value ListToSeparatedString a string that represents a join of a given QStringList with a locale-defined separator. + \value NativeLanguageName a string that represents the name of the native language. + \value NativeCountryName a string that represents the name of the native country. */ /*! diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h index c0cf219..9f03606 100644 --- a/src/corelib/tools/qpoint.h +++ b/src/corelib/tools/qpoint.h @@ -93,7 +93,7 @@ public: private: friend class QTransform; // ### Qt 5; remove the ifdef and just have the same order on all platforms. -#if defined(Q_OS_MAC) +#if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES) int yp; int xp; #else diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp index 8ce6b57..9277a3e 100644 --- a/src/corelib/tools/qscopedpointer.cpp +++ b/src/corelib/tools/qscopedpointer.cpp @@ -252,10 +252,9 @@ QT_BEGIN_NAMESPACE */ /*! - \fn QScopedArrayPointer::QScopedArrayPointer(T *p = 0) + \fn QScopedArrayPointer::QScopedArrayPointer() - Constructs this QScopedArrayPointer instance and sets its pointer - to \a p. + Constructs a QScopedArrayPointer instance. */ /*! diff --git a/src/corelib/tools/qscopedvaluerollback.cpp b/src/corelib/tools/qscopedvaluerollback.cpp index a9bbdb3..1ad47f4 100644 --- a/src/corelib/tools/qscopedvaluerollback.cpp +++ b/src/corelib/tools/qscopedvaluerollback.cpp @@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE /*! \class QScopedValueRollback - \brief The QScopedValueRollback resets a variable to its previous value on destruction + \brief The QScopedValueRollback class resets a variable to its previous value on destruction. \since 4.8 \ingroup misc @@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE /*! \fn QScopedValueRollback::QScopedValueRollback(T &var) - Stores the previous value of var internally, for revert on destruction. + Stores the previous value of \a var internally, for revert on destruction. */ /*! diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 0edf291..ee45cfd 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -837,6 +837,25 @@ int QString::grow(int size) \sa QString::const_iterator */ +/*! + \typedef QString::const_reference + + The QString::const_reference typedef provides an STL-style + const reference for QString. +*/ +/*! + \typedef QString::reference + + The QString::const_reference typedef provides an STL-style + reference for QString. +*/ +/*! + \typedef QString::value_type + + The QString::const_reference typedef provides an STL-style + value type for QString. +*/ + /*! \fn QString::iterator QString::begin() Returns an \l{STL-style iterator} pointing to the first character in @@ -3561,6 +3580,28 @@ static inline __m128i mergeQuestionMarks(__m128i chunk) { const __m128i questionMark = _mm_set1_epi16('?'); +# ifdef __SSE4_2__ + // compare the unsigned shorts for the range 0x0100-0xFFFF + // note on the use of _mm_cmpestrm: + // The MSDN documentation online (http://technet.microsoft.com/en-us/library/bb514080.aspx) + // says for range search the following: + // For each character c in a, determine whether b0 <= c <= b1 or b2 <= c <= b3 + // + // However, all examples on the Internet, including from Intel + // (see http://software.intel.com/en-us/articles/xml-parsing-accelerator-with-intel-streaming-simd-extensions-4-intel-sse4/) + // put the range to be searched first + // + // Disassembly and instruction-level debugging with GCC and ICC show + // that they are doing the right thing. Inverting the arguments in the + // instruction does cause a bunch of test failures. + + const int mode = _SIDD_UWORD_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK; + const __m128i rangeMatch = _mm_cvtsi32_si128(0xffff0100); + const __m128i offLimitMask = _mm_cmpestrm(rangeMatch, 2, chunk, 8, mode); + + // replace the non-Latin 1 characters in the chunk with question marks + chunk = _mm_blendv_epi8(chunk, questionMark, offLimitMask); +# else // SSE has no compare instruction for unsigned comparison. // The variables must be shiffted + 0x8000 to be compared const __m128i signedBitOffset = _mm_set1_epi16(0x8000); @@ -3584,6 +3625,7 @@ static inline __m128i mergeQuestionMarks(__m128i chunk) // merge offLimitQuestionMark and correctBytes to have the result chunk = _mm_or_si128(correctBytes, offLimitQuestionMark); # endif +# endif return chunk; } #endif @@ -9117,7 +9159,7 @@ QByteArray QStringRef::toUtf8() const UCS-4 is a Unicode codec and is lossless. All characters from this string can be encoded in UCS-4. - \sa fromUtf8(), toAscii(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray() + \sa toAscii(), toLatin1(), toLocal8Bit(), QTextCodec */ QVector<uint> QStringRef::toUcs4() const { diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index c61d09e..bf0a0ad 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -639,6 +639,7 @@ private: static Data *fromAscii_helper(const char *str, int size = -1); void replace_helper(uint *indices, int nIndices, int blen, const QChar *after, int alen); friend class QCharRef; + friend class QCFString; friend class QTextCodec; friend class QStringRef; friend struct QAbstractConcatenable; diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp index fb06736..1cc7e5d 100644 --- a/src/corelib/tools/qstringbuilder.cpp +++ b/src/corelib/tools/qstringbuilder.cpp @@ -142,7 +142,8 @@ QT_BEGIN_NAMESPACE characters. */ -/*! \fn QStringBuilder::operator QString() const +/*! + \fn operator QStringBuilder::QString() const Converts the \c QLatin1Literal into a \c QString object. */ @@ -161,6 +162,8 @@ void QAbstractConcatenable::convertFromAscii(const char *a, int len, QChar *&out } #endif if (len == -1) { + if (!a) + return; while (*a) *out++ = QLatin1Char(*a++); } else { diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 709d84a..594ab2f 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -352,6 +352,8 @@ template <> struct QConcatenable<const char *> : private QAbstractConcatenable #endif static inline void appendTo(const char *a, char *&out) { + if (!a) + return; while (*a) *out++ = *a++; } diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp index 5997574..8b47137 100644 --- a/src/corelib/tools/qstringlist.cpp +++ b/src/corelib/tools/qstringlist.cpp @@ -683,7 +683,7 @@ int QtPrivate::QStringList_removeDuplicates(QStringList *that) /*! \fn QStringList::QStringList(std::initializer_list<QString> args) \since 4.8 - Construct a list from a std::initilizer_list. + Construct a list from a std::initializer_list given by \a args. This constructor is only enabled if the compiler supports C++0x */ diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index b2dc7d6..b1d7a1a 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -337,6 +337,20 @@ Typedef for const T &. Provided for STL compatibility. */ +/*! + \typedef QVarLengthArray::const_iterator + \since 4.7 + + Typedef for const T *. Provided for STL compatibility. +*/ + +/*! + \typedef QVarLengthArray::iterator + \since 4.7 + + Typedef for T *. Provided for STL compatibility. +*/ + /*! \fn void QVarLengthArray::prepend(const T &value) \since 4.8 @@ -501,7 +515,7 @@ \relates QVarLengthArray \since 4.8 - Returns true if the two array are equal; + Returns true if the two arrays, specified by \a left and \a right, are equal. Two arrays are considered equal if they contain the same values in the same order. @@ -516,7 +530,7 @@ \relates QVarLengthArray \since 4.8 - Returns true if the two array are different; + Returns true if the two arrays, specified by \a left and \a right, are \e not equal. Two arrays are considered equal if they contain the same values in the same order. diff --git a/src/corelib/tools/qvector.cpp b/src/corelib/tools/qvector.cpp index 8c4dd06..98a2412 100644 --- a/src/corelib/tools/qvector.cpp +++ b/src/corelib/tools/qvector.cpp @@ -277,7 +277,7 @@ int QVectorData::grow(int sizeofTypedData, int size, int sizeofT, bool excessive /*! \fn QVector::QVector(std::initializer_list<T> args) \since 4.8 - Construct a vector from a std::initilizer_list. + Construct a vector from the std::initilizer_list given by \a args. This constructor is only enabled if the compiler supports C++0x */ diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 19626af..caaffd3 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -646,6 +646,11 @@ QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const parser has reached the end element, the current element becomes the parent element. + You can traverse a document by repeatedly calling this function while + ensuring that the stream reader is not at the end of the document: + + \snippet doc/src/snippets/xml/streamreader/traverse.cpp traverse document + This is a convenience function for when you're only concerned with parsing XML elements. The \l{QXmlStream Bookmarks Example} makes extensive use of this function. |