diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-22 09:04:29 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-04-22 09:25:54 +0200 |
commit | aed5a7168354c6ae47687d20b4bd3f0adcc14f8e (patch) | |
tree | d2060479a7c12fdba8c1955e5d363754feffabb8 /src/corelib | |
parent | d3d10cf23d61f4a011f1a7e9abdee1a92717e80f (diff) | |
parent | 628fa13ea4d6ff0e2e2ee76c9adfc78676de3c59 (diff) |
Merge remote-tracking branch 'origin/5.5' into dev
Conflicts:
src/corelib/statemachine/qstatemachine.cpp
src/corelib/statemachine/qstatemachine_p.h
src/gui/painting/qdrawhelper.cpp
src/plugins/platforms/xcb/qxcbnativeinterface.cpp
src/plugins/platforms/xcb/qxcbwindow.cpp
src/plugins/platforms/xcb/qxcbwindow.h
src/testlib/qtestblacklist.cpp
src/tools/qdoc/node.cpp
src/tools/qdoc/node.h
tests/auto/gui/painting/qcolor/tst_qcolor.cpp
Change-Id: I6c78b7b162001712d5774293f501b06b4ff32684
Diffstat (limited to 'src/corelib')
67 files changed, 948 insertions, 767 deletions
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index bf4e8f26f3..5a1ba51f65 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -323,6 +323,8 @@ static bool setByteOrder(iconv_t cd) if (iconv(cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) { return false; } +#else + Q_UNUSED(cd); #endif // NO_BOM return true; diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc index d1509346c0..cbb2d4efb3 100644 --- a/src/corelib/doc/src/resource-system.qdoc +++ b/src/corelib/doc/src/resource-system.qdoc @@ -136,7 +136,7 @@ \image resources.png Building resources into an application Currently, Qt always stores the data directly in the executable, - even on Windows and Mac OS X, where the operating system provides + even on Windows, OS X, and iOS, where the operating system provides native support for resources. This might change in a future Qt release. diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 33a24a3866..f8a8a436be 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -921,7 +921,7 @@ # endif // Q_OS_QNX # if (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC) && defined(__GNUC_LIBSTD__) \ && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402) -// Mac OS X: Apple has not updated libstdc++ since 2007, which means it does not have +// Apple has not updated libstdc++ since 2007, which means it does not have // <initializer_list> or std::move. Let's disable these features # undef Q_COMPILER_INITIALIZER_LISTS # undef Q_COMPILER_RVALUE_REFS @@ -937,7 +937,7 @@ # endif # endif # if defined(Q_COMPILER_THREADSAFE_STATICS) && defined(Q_OS_MAC) -// Mac OS X: Apple's low-level implementation of the C++ support library +// Apple's low-level implementation of the C++ support library // (libc++abi.dylib, shared between libstdc++ and libc++) has deadlocks. The // C++11 standard requires the deadlocks to be removed, so this will eventually // be fixed; for now, let's disable this. diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index c766b4d1c3..32b2a26992 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -492,6 +492,7 @@ public: AA_UseOpenGLES = 16, AA_UseSoftwareOpenGL = 17, AA_ShareOpenGLContexts = 18, + AA_SetPalette = 19, // Add new attributes before this line AA_AttributeCount diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index daf55cfd3a..6340dfeb65 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -111,7 +111,7 @@ shown in any menus unless specifically set by the QAction::iconVisibleInMenu property. Menus that are currently open or menus already created in the native - Mac OS X menubar \e{may not} pick up a change in this attribute. Changes + OS X menubar \e{may not} pick up a change in this attribute. Changes in the QAction::iconVisibleInMenu property will always be picked up. \value AA_NativeWindows Ensures that widgets have native windows. @@ -129,9 +129,9 @@ \value AA_DontUseNativeMenuBar All menubars created while this attribute is set to true won't be used as a native menubar (e.g, the menubar at - the top of the main screen on Mac OS X or at the bottom in Windows CE). + the top of the main screen on OS X or at the bottom in Windows CE). - \value AA_MacDontSwapCtrlAndMeta On Mac OS X by default, Qt swaps the + \value AA_MacDontSwapCtrlAndMeta On OS X by default, Qt swaps the Control and Meta (Command) keys (i.e., whenever Control is pressed, Qt sends Meta, and whenever Meta is pressed Control is sent). When this attribute is true, Qt will not do the flip. \l QKeySequence::StandardKey @@ -194,6 +194,9 @@ instances that belong to different top-level windows. This value has been added in Qt 5.4. + \value AA_SetPalette Indicates whether a palette was explicitly set on the + QApplication/QGuiApplication. This value has been added in Qt 5.5. + The following values are obsolete: \value AA_ImmediateWidgetCreation This attribute is no longer fully @@ -294,7 +297,7 @@ \omitvalue KeyboardModifierMask - \note On Mac OS X, the \c ControlModifier value corresponds to + \note On OS X, the \c ControlModifier value corresponds to the Command keys on the Macintosh keyboard, and the \c MetaModifier value corresponds to the Control keys. The \c KeypadModifier value will also be set when an arrow key is pressed as the arrow keys are considered part of the @@ -312,7 +315,7 @@ This enum provides shorter names for the keyboard modifier keys supported by Qt. - \note On Mac OS X, the \c CTRL value corresponds to + \note On OS X, the \c CTRL value corresponds to the Command keys on the Macintosh keyboard, and the \c META value corresponds to the Control keys. @@ -913,34 +916,34 @@ \value WA_MacOpaqueSizeGrip Indicates that the native Carbon size grip should be opaque instead of transparent (the default). This attribute - is only applicable to Mac OS X and is set by the widget's author. + is only applicable to OS X and is set by the widget's author. \value WA_MacShowFocusRect Indicates that this widget should get a QFocusFrame around it. Some widgets draw their own focus halo regardless of this attribute. Not that the QWidget::focusPolicy also plays the main role in whether something is given focus or not, this only controls whether or not this gets the focus - frame. This attribute is only applicable to Mac OS X. + frame. This attribute is only applicable to OS X. \value WA_MacNormalSize Indicates the widget should have the - normal size for widgets in Mac OS X. This attribute is only - applicable to Mac OS X. + normal size for widgets in OS X. This attribute is only + applicable to OS X. \value WA_MacSmallSize Indicates the widget should have the small - size for widgets in Mac OS X. This attribute is only applicable to - Mac OS X. + size for widgets in OS X. This attribute is only applicable to + OS X. \value WA_MacMiniSize Indicates the widget should have the mini - size for widgets in Mac OS X. This attribute is only applicable to - Mac OS X. + size for widgets in OS X. This attribute is only applicable to + OS X. \value WA_MacVariableSize Indicates the widget can choose between alternative sizes for widgets to avoid clipping. - This attribute is only applicable to Mac OS X. + This attribute is only applicable to OS X. \value WA_MacBrushedMetal Indicates the widget should be drawn in the brushed metal style as supported by the windowing system. This - attribute is only applicable to Mac OS X. + attribute is only applicable to OS X. \omitvalue WA_MacMetalStyle @@ -1090,14 +1093,14 @@ \b Warning: This flag must \e never be set or cleared by the widget's author. \value WA_WindowModified Indicates that the window is marked as modified. - On some platforms this flag will do nothing, on others (including Mac OS X + On some platforms this flag will do nothing, on others (including OS X and Windows) the window will take a modified appearance. This flag is set or cleared by QWidget::setWindowModified(). \value WA_WindowPropagation Makes a toplevel window inherit font and palette from its parent. - \value WA_MacAlwaysShowToolWindow On Mac OS X, show the tool window even + \value WA_MacAlwaysShowToolWindow On OS X, show the tool window even when the application is not active. By default, all tool windows are hidden when the application is inactive. @@ -1280,8 +1283,8 @@ \value Key_PageUp \value Key_PageDown \value Key_Shift - \value Key_Control On Mac OS X, this corresponds to the Command keys. - \value Key_Meta On Mac OS X, this corresponds to the Control keys. + \value Key_Control On OS X, this corresponds to the Command keys. + \value Key_Meta On OS X, this corresponds to the Control keys. On Windows keyboards, this key is mapped to the Windows key. \value Key_Alt @@ -1919,7 +1922,7 @@ \value TabFocus the widget accepts focus by tabbing. \value ClickFocus the widget accepts focus by clicking. \value StrongFocus the widget accepts focus by both tabbing - and clicking. On Mac OS X this will also + and clicking. On OS X this will also be indicate that the widget accepts tab focus when in 'Text/List focus mode'. \value WheelFocus like Qt::StrongFocus plus the widget accepts @@ -2025,7 +2028,7 @@ system supports it, a tool window can be decorated with a somewhat lighter frame. It can also be combined with Qt::FramelessWindowHint. - On Mac OS X, tool windows correspond to the + On OS X, tool windows correspond to the \l{http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/hitb-wind_cont_concept/chapter_2_section_2.html}{Floating} class of windows. This means that the window lives on a level above normal windows; it impossible to put a normal @@ -2114,10 +2117,10 @@ \value WindowContextHelpButtonHint Adds a context help button to dialogs. On some platforms this implies Qt::WindowSystemMenuHint for it to work. - \value MacWindowToolBarButtonHint On Mac OS X adds a tool bar button (i.e., + \value MacWindowToolBarButtonHint On OS X adds a tool bar button (i.e., the oblong button that is on the top right of windows that have toolbars). - \value WindowFullscreenButtonHint On Mac OS X adds a fullscreen button. + \value WindowFullscreenButtonHint On OS X adds a fullscreen button. \value BypassGraphicsProxyWidget Prevents the window and its children from automatically embedding themselves into a QGraphicsProxyWidget if the @@ -2141,7 +2144,7 @@ that support _NET_WM_STATE_BELOW atom. If a window always on the bottom has a parent, the parent will also be left on the bottom. This window hint is currently not implemented - for Mac OS X. + for OS X. \value WindowOkButtonHint Adds an OK button to the window decoration of a dialog. Only supported for Windows CE. @@ -2985,7 +2988,7 @@ \value CoarseTimer Coarse timers try to keep accuracy within 5% of the desired interval \value VeryCoarseTimer Very coarse timers only keep full second accuracy - On UNIX (including Linux and Mac OS X), Qt will keep millisecond accuracy + On UNIX (including Linux, OS X, and iOS), Qt will keep millisecond accuracy for Qt::PreciseTimer. For Qt::CoarseTimer, the interval will be adjusted up to 5% to align the timer with other timers that are expected to fire at or around the same time. The objective is to make most timers wake up at the diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 45e81a6cdc..07270eb790 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -299,7 +299,7 @@ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName) the file system (i.e. not a file or directory). \value FileType The file is a regular file to the file system (i.e. not a link or directory) - \value BundleType The file is a Mac OS X bundle implies DirectoryType + \value BundleType OS X and iOS: the file is a bundle; implies DirectoryType \value DirectoryType The file is a directory in the file system (i.e. not a link or file). diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 7fa53bd850..3a9ae2ee6d 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -219,7 +219,7 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt if ((qt_cmp_si_sort_flags & QDir::DirsLast) && (f1->item.isDir() != f2->item.isDir())) return !f1->item.isDir(); - int r = 0; + qint64 r = 0; int sortBy = (qt_cmp_si_sort_flags & QDir::SortByMask) | (qt_cmp_si_sort_flags & QDir::Type); @@ -1818,8 +1818,8 @@ QFileInfoList QDir::drives() } /*! - Returns the native directory separator: "/" under Unix (including - Mac OS X) and "\\" under Windows. + Returns the native directory separator: "/" under Unix + and "\\" under Windows. You do not need to use this function to build file paths. If you always use "/", Qt will translate your paths to conform to the diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index 5cc1e82e75..ce1684a943 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -199,9 +199,9 @@ QAbstractFileEngine *QFilePrivate::engine() const \section1 Platform Specific Issues - File permissions are handled differently on Linux/Mac OS X and + File permissions are handled differently on Unix-like systems and Windows. In a non \l{QIODevice::isWritable()}{writable} - directory on Linux, files cannot be created. This is not always + directory on Unix-like systems, files cannot be created. This is not always the case on Windows, where, for instance, the 'My Documents' directory usually is not writable, but it is still possible to create files in it. diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index bf83464eab..8a86ec5858 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -234,7 +234,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) isSymLink(). The symLinkTarget() function provides the name of the file the symlink points to. - On Unix (including Mac OS X), the symlink has the same size() has + On Unix (including OS X and iOS), the symlink has the same size() has the file it points to, because Unix handles symlinks transparently; similarly, opening a symlink using QFile effectively opens the link's target. For example: @@ -753,7 +753,7 @@ QString QFileInfo::fileName() const \since 4.3 Returns the name of the bundle. - On Mac OS X this returns the proper localized name for a bundle if the + On OS X and iOS this returns the proper localized name for a bundle if the path isBundle(). On all other platforms an empty QString is returned. Example: @@ -1029,7 +1029,7 @@ bool QFileInfo::isDir() const /*! \since 4.3 Returns \c true if this object points to a bundle or to a symbolic - link to a bundle on Mac OS X; otherwise returns \c false. + link to a bundle on OS X and iOS; otherwise returns \c false. \sa isDir(), isSymLink(), isFile() */ @@ -1050,7 +1050,7 @@ bool QFileInfo::isBundle() const Returns \c true if this object points to a symbolic link (or to a shortcut on Windows); otherwise returns \c false. - On Unix (including Mac OS X), opening a symlink effectively opens + On Unix (including OS X and iOS), opening a symlink effectively opens the \l{symLinkTarget()}{link's target}. On Windows, it opens the \c .lnk file itself. diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp index 4817266a31..df41457a18 100644 --- a/src/corelib/io/qfilesystemengine.cpp +++ b/src/corelib/io/qfilesystemengine.cpp @@ -323,7 +323,7 @@ void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry) } } #elif defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4) - // BSD4 includes Mac OS X + // BSD4 includes OS X and iOS // ### This will clear all entry flags and knownFlagsMask switch (entry.d_type) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index 44a270d1fd..c4fb709ddf 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -432,7 +432,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM what |= QFileSystemMetaData::DirectoryType; } if (what & QFileSystemMetaData::HiddenAttribute) { - // Mac OS >= 10.5: st_flags & UF_HIDDEN + // OS X >= 10.5: st_flags & UF_HIDDEN what |= QFileSystemMetaData::PosixStatFlags; } #endif // defined(Q_OS_MACX) diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 221cea3bea..5cca3c323e 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -1218,7 +1218,7 @@ QString QFileSystemEngine::rootPath() ret = QDir::fromNativeSeparators(QString::fromWCharArray(finalWinPath.GetRawBuffer(nullptr))); #else - QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData()); + QString ret = QString::fromLatin1(qgetenv("SystemDrive")); if (ret.isEmpty()) ret = QLatin1String("c:"); ret.append(QLatin1Char('/')); @@ -1253,12 +1253,12 @@ QString QFileSystemEngine::homePath() } #endif if (ret.isEmpty() || !QFile::exists(ret)) { - ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData()); + ret = QString::fromLocal8Bit(qgetenv("USERPROFILE")); if (ret.isEmpty() || !QFile::exists(ret)) { - ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE").constData()) - + QString::fromLocal8Bit(qgetenv("HOMEPATH").constData()); + ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE")) + + QString::fromLocal8Bit(qgetenv("HOMEPATH")); if (ret.isEmpty() || !QFile::exists(ret)) { - ret = QString::fromLocal8Bit(qgetenv("HOME").constData()); + ret = QString::fromLocal8Bit(qgetenv("HOME")); if (ret.isEmpty() || !QFile::exists(ret)) { #if defined(Q_OS_WINCE) ret = QLatin1String("\\My Documents"); diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 753f271a63..0bd46400d3 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -185,7 +185,7 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re the file system monitor. Also note that your process may have other file descriptors open in addition to the ones for files being monitored, and these other open descriptors also count in - the total. Mac OS X 10.5 and up use a different backend and do not + the total. OS X 10.5 and up use a different backend and do not suffer from this issue. diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h index 57dac802e8..13d1782913 100644 --- a/src/corelib/io/qfilesystemwatcher.h +++ b/src/corelib/io/qfilesystemwatcher.h @@ -62,16 +62,8 @@ public: QStringList directories() const; Q_SIGNALS: - void fileChanged(const QString &path -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void directoryChanged(const QString &path -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void fileChanged(const QString &path, QPrivateSignal); + void directoryChanged(const QString &path, QPrivateSignal); private: Q_PRIVATE_SLOT(d_func(), void _q_fileChanged(const QString &path, bool removed)) diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 13ede56d2a..ddbd24338b 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -603,7 +603,7 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len) result = fread(data + readBytes, 1, size_t(len - readBytes), fh); eof = feof(fh); if (retry && eof && result == 0) { - // On Mac OS, this is needed, e.g., if a file was written to + // On OS X, this is needed, e.g., if a file was written to // through another stream since our last read. See test // tst_QFile::appendAndRead QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream. @@ -875,7 +875,7 @@ bool QFSFileEngine::supportsExtension(Extension extension) const /*! \fn QFileInfoList QFSFileEngine::drives() For Windows, returns the list of drives in the file system as a list - of QFileInfo objects. On unix, Mac OS X and Windows CE, only the + of QFileInfo objects. On Unix and Windows CE, only the root path is returned. On Windows, this function returns all drives (A:\, C:\, D:\, etc.). diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 7a87a78c60..47484ad596 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -666,7 +666,7 @@ bool QIODevice::seek(qint64 pos) For some devices, atEnd() can return true even though there is more data to read. This special case only applies to devices that generate data in direct response to you calling read() (e.g., \c /dev or \c /proc files on - Unix and Mac OS X, or console input / \c stdin on all platforms). + Unix and OS X, or console input / \c stdin on all platforms). \sa bytesAvailable(), read(), isSequential() */ @@ -989,8 +989,8 @@ QByteArray QIODevice::readAll() // Size is unknown, read incrementally. qint64 readResult; do { - result.resize(result.size() + QIODEVICE_BUFFERSIZE); - readResult = read(result.data() + readBytes, result.size() - readBytes); + result.resize(readBytes + QIODEVICE_BUFFERSIZE); + readResult = read(result.data() + readBytes, QIODEVICE_BUFFERSIZE); if (readResult > 0 || readBytes == 0) readBytes += readResult; } while (readResult > 0); diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index c663681aaa..b817a24c74 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -102,7 +102,7 @@ static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1); /*! \internal Checks that the OS isn't using POSIX locks to emulate flock(). - Mac OS X is one of those. + OS X is one of those. */ static bool fcntlWorksAfterFlock() { diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp index 4631a00f5f..e6bc7caaeb 100644 --- a/src/corelib/io/qloggingcategory.cpp +++ b/src/corelib/io/qloggingcategory.cpp @@ -159,7 +159,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift) by QStandardPaths::GenericConfigLocation, e.g. \list - \li on Mac OS X: \c ~/Library/Preferences + \li on OS X and iOS: \c ~/Library/Preferences \li on Unix: \c ~/.config, \c /etc/xdg \li on Windows: \c %LOCALAPPDATA%, \c %ProgramData%, \l QCoreApplication::applicationDirPath(), diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 80eb08b01b..38bd588c37 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -36,6 +36,9 @@ #include <qdebug.h> #include <qdir.h> +#if defined(Q_OS_WIN) +#include <qtimer.h> +#endif #if defined QPROCESS_DEBUG #include <qstring.h> #include <ctype.h> @@ -819,7 +822,7 @@ QProcessPrivate::QProcessPrivate() emittedReadyRead = false; emittedBytesWritten = false; #ifdef Q_OS_WIN - notifier = 0; + stdinWriteTrigger = 0; processFinishedNotifier = 0; #endif // Q_OS_WIN } @@ -848,6 +851,10 @@ void QProcessPrivate::cleanup() delete pid; pid = 0; } + if (stdinWriteTrigger) { + delete stdinWriteTrigger; + stdinWriteTrigger = 0; + } if (processFinishedNotifier) { delete processFinishedNotifier; processFinishedNotifier = 0; @@ -878,12 +885,6 @@ void QProcessPrivate::cleanup() delete deathNotifier; deathNotifier = 0; } -#ifdef Q_OS_WIN - if (notifier) { - delete notifier; - notifier = 0; - } -#endif closeChannel(&stdoutChannel); closeChannel(&stderrChannel); closeChannel(&stdinChannel); @@ -1953,10 +1954,24 @@ qint64 QProcess::writeData(const char *data, qint64 len) return 0; } +#if defined(Q_OS_WIN) + if (!d->stdinWriteTrigger) { + d->stdinWriteTrigger = new QTimer; + d->stdinWriteTrigger->setSingleShot(true); + QObjectPrivate::connect(d->stdinWriteTrigger, &QTimer::timeout, + d, &QProcessPrivate::_q_canWrite); + } +#endif + if (len == 1) { d->stdinChannel.buffer.putChar(*data); +#ifdef Q_OS_WIN + if (!d->stdinWriteTrigger->isActive()) + d->stdinWriteTrigger->start(); +#else if (d->stdinChannel.notifier) d->stdinChannel.notifier->setEnabled(true); +#endif #if defined QPROCESS_DEBUG qDebug("QProcess::writeData(%p \"%s\", %lld) == 1 (written to buffer)", data, qt_prettyDebug(data, len, 16).constData(), len); @@ -1966,8 +1981,13 @@ qint64 QProcess::writeData(const char *data, qint64 len) char *dest = d->stdinChannel.buffer.reserve(len); memcpy(dest, data, len); +#ifdef Q_OS_WIN + if (!d->stdinWriteTrigger->isActive()) + d->stdinWriteTrigger->start(); +#else if (d->stdinChannel.notifier) d->stdinChannel.notifier->setEnabled(true); +#endif #if defined QPROCESS_DEBUG qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)", data, qt_prettyDebug(data, len, 16).constData(), len, len); diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h index 65af469c18..078217ea0b 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -223,30 +223,14 @@ public Q_SLOTS: void kill(); Q_SIGNALS: - void started( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void started(QPrivateSignal); void finished(int exitCode); // ### Qt 6: merge the two signals with a default value void finished(int exitCode, QProcess::ExitStatus exitStatus); void error(QProcess::ProcessError error); - void stateChanged(QProcess::ProcessState state -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void stateChanged(QProcess::ProcessState state, QPrivateSignal); - void readyReadStandardOutput( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void readyReadStandardError( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void readyReadStandardOutput(QPrivateSignal); + void readyReadStandardError(QPrivateSignal); protected: void setProcessState(ProcessState state); @@ -266,7 +250,6 @@ private: Q_PRIVATE_SLOT(d_func(), bool _q_canWrite()) Q_PRIVATE_SLOT(d_func(), bool _q_startupNotification()) Q_PRIVATE_SLOT(d_func(), bool _q_processDied()) - Q_PRIVATE_SLOT(d_func(), void _q_notified()) friend class QProcessManager; }; diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h index 5654b404fe..f6bd64fb87 100644 --- a/src/corelib/io/qprocess_p.h +++ b/src/corelib/io/qprocess_p.h @@ -303,7 +303,6 @@ public: bool _q_canWrite(); bool _q_startupNotification(); bool _q_processDied(); - void _q_notified(); QProcess::ProcessChannel processChannel; QProcess::ProcessChannelMode processChannelMode; @@ -342,8 +341,7 @@ public: int forkfd; #ifdef Q_OS_WIN - // the wonderful windows notifier - QTimer *notifier; + QTimer *stdinWriteTrigger; QWinEventNotifier *processFinishedNotifier; #endif diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index d9ed8d5d43..ed0193c256 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1110,10 +1110,6 @@ bool QProcessPrivate::waitForDeadChild() return true; } -void QProcessPrivate::_q_notified() -{ -} - #if defined(QPROCESS_USE_SPAWN) bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid) { diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp index 563286e3e9..cef961ecbd 100644 --- a/src/corelib/io/qprocess_win.cpp +++ b/src/corelib/io/qprocess_win.cpp @@ -41,7 +41,6 @@ #include <qelapsedtimer.h> #include <qfileinfo.h> #include <qregexp.h> -#include <qtimer.h> #include <qwineventnotifier.h> #include <private/qthread_p.h> #include <qdebug.h> @@ -58,8 +57,6 @@ QT_BEGIN_NAMESPACE //#define QPROCESS_DEBUG -#define NOTIFYTIMEOUT 100 - static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe) { // Anomymous pipes do not support asynchronous I/O. Thus we @@ -543,9 +540,6 @@ void QProcessPrivate::startProcess() processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q); QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied())); processFinishedNotifier->setEnabled(true); - notifier = new QTimer(q); - QObject::connect(notifier, SIGNAL(timeout()), q, SLOT(_q_notified())); - notifier->start(NOTIFYTIMEOUT); } _q_startupNotification(); @@ -810,6 +804,8 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen) if (!stdinChannel.writer) { stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q); + QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite, + this, &QProcessPrivate::_q_canWrite); stdinChannel.writer->start(); } @@ -828,17 +824,6 @@ bool QProcessPrivate::waitForWrite(int msecs) return false; } -void QProcessPrivate::_q_notified() -{ - notifier->stop(); - - if (!stdinChannel.buffer.isEmpty() && (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0))) - _q_canWrite(); - - if (processState != QProcess::NotRunning) - notifier->start(NOTIFYTIMEOUT); -} - bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid) { QString args = qt_create_commandline(program, arguments); diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp index bf19c81f25..53767758c2 100644 --- a/src/corelib/io/qprocess_wince.cpp +++ b/src/corelib/io/qprocess_wince.cpp @@ -288,10 +288,6 @@ bool QProcessPrivate::waitForWrite(int msecs) return false; } -void QProcessPrivate::_q_notified() -{ -} - bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid) { Q_UNUSED(workingDir); diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 780f57c1c7..afe68125d4 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1915,7 +1915,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, Users normally expect an application to remember its settings (window sizes and positions, options, etc.) across sessions. This information is often stored in the system registry on Windows, - and in XML preferences files on Mac OS X. On Unix systems, in the + and in property list files on OS X and iOS. On Unix systems, in the absence of a standard, many applications (including the KDE applications) use INI text files. @@ -1960,8 +1960,8 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, \snippet settings/settings.cpp 4 (Here, we also specify the organization's Internet domain. When - the Internet domain is set, it is used on Mac OS X instead of the - organization name, since Mac OS X applications conventionally use + the Internet domain is set, it is used on OS X and iOS instead of the + organization name, since OS X and iOS applications conventionally use Internet domains to identify themselves. If no domain is set, a fake domain is derived from the organization name. See the \l{Platform-Specific Notes} below for details.) @@ -2019,7 +2019,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, Setting keys can contain any Unicode characters. The Windows registry and INI files use case-insensitive keys, whereas the - Carbon Preferences API on Mac OS X uses case-sensitive keys. To + CFPreferences API on OS X and iOS uses case-sensitive keys. To avoid portability problems, follow these simple rules: \list 1 @@ -2222,7 +2222,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, in the application's home directory. If the file format is IniFormat, the following files are - used on Unix and Mac OS X: + used on Unix, OS X, and iOS: \list 1 \li \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini}) @@ -2250,7 +2250,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, in the application's home directory. The paths for the \c .ini and \c .conf files can be changed using - setPath(). On Unix and Mac OS X, the user can override them by + setPath(). On Unix, OS X, and iOS the user can override them by setting the \c XDG_CONFIG_HOME environment variable; see setPath() for details. @@ -2267,7 +2267,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, You can then use the QSettings object to read and write settings in the file. - On Mac OS X, you can access XML-based \c .plist files by passing + On OS X and iOS, you can access property list \c .plist files by passing QSettings::NativeFormat as second argument. For example: \snippet code/src_corelib_io_qsettings.cpp 3 @@ -2321,13 +2321,13 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, limitations is to store the settings using the IniFormat instead of the NativeFormat. - \li On Mac OS X, allKeys() will return some extra keys for global + \li On OS X and iOS, allKeys() will return some extra keys for global settings that apply to all applications. These keys can be read using value() but cannot be changed, only shadowed. Calling setFallbacksEnabled(false) will hide these global settings. - \li On Mac OS X, the CFPreferences API used by QSettings expects + \li On OS X and iOS, the CFPreferences API used by QSettings expects Internet domain names rather than organization names. To provide a uniform API, QSettings derives a fake domain name from the organization name (unless the organization name @@ -2344,7 +2344,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, \snippet code/src_corelib_io_qsettings.cpp 7 - \li On Mac OS X, permissions to access settings not belonging to the + \li On OS X, permissions to access settings not belonging to the current user (i.e. SystemScope) have changed with 10.7 (Lion). Prior to that version, users having admin rights could access these. For 10.7 and 10.8 (Mountain Lion), only root can. However, 10.9 (Mavericks) changes @@ -2384,7 +2384,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile, \value NativeFormat Store the settings using the most appropriate storage format for the platform. On Windows, this means the system registry; - on Mac OS X, this means the CFPreferences + on OS X and iOS, this means the CFPreferences API; on Unix, this means textual configuration files in INI format. \value IniFormat Store the settings in INI files. @@ -2547,7 +2547,7 @@ QSettings::QSettings(Format format, Scope scope, const QString &organization, If \a format is QSettings::NativeFormat, the meaning of \a fileName depends on the platform. On Unix, \a fileName is the - name of an INI file. On Mac OS X, \a fileName is the name of a + name of an INI file. On OS X and iOS, \a fileName is the name of a \c .plist file. On Windows, \a fileName is a path in the system registry. @@ -2600,7 +2600,7 @@ QSettings::QSettings(const QString &fileName, Format format, QObject *parent) called, the QSettings object will not be able to read or write any settings, and status() will return AccessError. - On Mac OS X, if both a name and an Internet domain are specified + On OS X and iOS, if both a name and an Internet domain are specified for the organization, the domain is preferred over the name. On other platforms, the name is preferred over the domain. @@ -3116,7 +3116,7 @@ bool QSettings::isWritable() const exists, the previous value is overwritten. Note that the Windows registry and INI files use case-insensitive - keys, whereas the Carbon Preferences API on Mac OS X uses + keys, whereas the CFPreferences API on OS X and iOS uses case-sensitive keys. To avoid portability problems, see the \l{Section and Key Syntax} rules. @@ -3155,7 +3155,7 @@ void QSettings::setValue(const QString &key, const QVariant &value) \snippet code/src_corelib_io_qsettings.cpp 25 Note that the Windows registry and INI files use case-insensitive - keys, whereas the Carbon Preferences API on Mac OS X uses + keys, whereas the CFPreferences API on OS X and iOS uses case-sensitive keys. To avoid portability problems, see the \l{Section and Key Syntax} rules. @@ -3190,7 +3190,7 @@ void QSettings::remove(const QString &key) relative to that group. Note that the Windows registry and INI files use case-insensitive - keys, whereas the Carbon Preferences API on Mac OS X uses + keys, whereas the CFPreferences API on OS X and iOS uses case-sensitive keys. To avoid portability problems, see the \l{Section and Key Syntax} rules. @@ -3252,7 +3252,7 @@ bool QSettings::event(QEvent *event) returned. Note that the Windows registry and INI files use case-insensitive - keys, whereas the Carbon Preferences API on Mac OS X uses + keys, whereas the CFPreferences API on OS X and iOS uses case-sensitive keys. To avoid portability problems, see the \l{Section and Key Syntax} rules. @@ -3355,18 +3355,18 @@ void QSettings::setUserIniPath(const QString &dir) \row \li SystemScope \li \c /etc/xdg \row \li{1,2} Qt for Embedded Linux \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/Settings \row \li SystemScope \li \c /etc/xdg - \row \li{1,2} Mac OS X \li{1,2} IniFormat \li UserScope \li \c $HOME/.config + \row \li{1,2} OS X and iOS \li{1,2} IniFormat \li UserScope \li \c $HOME/.config \row \li SystemScope \li \c /etc/xdg \endtable - The default UserScope paths on Unix and Mac OS X (\c + The default UserScope paths on Unix, OS X, and iOS (\c $HOME/.config or $HOME/Settings) can be overridden by the user by setting the \c XDG_CONFIG_HOME environment variable. The default SystemScope - paths on Unix and Mac OS X (\c /etc/xdg) can be overridden when + paths on Unix, OS X, and iOS (\c /etc/xdg) can be overridden when building the Qt library using the \c configure script's \c -sysconfdir flag (see QLibraryInfo for details). - Setting the NativeFormat paths on Windows and Mac OS X has no + Setting the NativeFormat paths on Windows, OS X, and iOS has no effect. \warning This function doesn't affect existing QSettings objects. diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index d120d7569a..7823787711 100644 --- a/src/corelib/io/qstorageinfo_unix.cpp +++ b/src/corelib/io/qstorageinfo_unix.cpp @@ -122,7 +122,11 @@ public: inline QByteArray device() const; private: #if defined(Q_OS_BSD4) +# if defined(Q_OS_NETBSD) + struct statvfs *stat_buf; +# else struct statfs *stat_buf; +# endif int entryCount; int currentIndex; #elif defined(Q_OS_SOLARIS) @@ -206,7 +210,7 @@ inline bool QStorageIterator::isValid() const inline bool QStorageIterator::next() { - return ::getmntent(fp, &mnt) == Q_NULLPTR; + return ::getmntent(fp, &mnt) == 0; } inline QString QStorageIterator::rootPath() const diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index c4f705e858..5ca7bd0123 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -246,82 +246,26 @@ Q_SIGNALS: void layoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); void layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); - void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void rowsInserted(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal); + void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal); - void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void rowsRemoved(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal); + void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal); - void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void columnsInserted(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal); + void columnsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal); - void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void columnsRemoved(const QModelIndex &parent, int first, int last -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal); + void columnsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal); - void modelAboutToBeReset( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void modelReset( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void modelAboutToBeReset(QPrivateSignal); + void modelReset(QPrivateSignal); - void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal); + void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row, QPrivateSignal); - void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal); + void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column, QPrivateSignal); public Q_SLOTS: virtual bool submit(); diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h index afd5a1f616..dc8d2d4dc8 100644 --- a/src/corelib/itemmodels/qabstractproxymodel.h +++ b/src/corelib/itemmodels/qabstractproxymodel.h @@ -92,11 +92,7 @@ public: Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE; Q_SIGNALS: - void sourceModelChanged( -#if !defined(qdoc) - QPrivateSignal -#endif - ); + void sourceModelChanged(QPrivateSignal); protected Q_SLOTS: void resetInternalData(); diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 5057c0415a..05d58ac028 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -695,7 +695,7 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p) If you are doing graphical changes inside a loop that does not return to the event loop on asynchronous window systems like X11 - or double buffered window systems like Mac OS X, and you want to + or double buffered window systems like Quartz (OS X and iOS), and you want to visualize these changes immediately (e.g. Splash Screens), call this function. @@ -2002,7 +2002,7 @@ void QCoreApplicationPrivate::setApplicationFilePath(const QString &path) directory, and you run the \c{regexp} example, this function will return "C:/Qt/examples/tools/regexp". - On Mac OS X this will point to the directory actually containing the + On OS X and iOS this will point to the directory actually containing the executable, which may be inside of an application bundle (if the application is bundled). diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h index e1fc364cd1..1cd835daae 100644 --- a/src/corelib/kernel/qcoreapplication.h +++ b/src/corelib/kernel/qcoreapplication.h @@ -171,11 +171,7 @@ public Q_SLOTS: static void quit(); Q_SIGNALS: - void aboutToQuit( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void aboutToQuit(QPrivateSignal); void organizationNameChanged(); void organizationDomainChanged(); diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp index 4649c151f7..396d2f740a 100644 --- a/src/corelib/kernel/qcoreapplication_win.cpp +++ b/src/corelib/kernel/qcoreapplication_win.cpp @@ -184,28 +184,6 @@ Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance, #ifndef QT_NO_QOBJECT -void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId) -{ - QThreadData *data = object->d_func()->threadData; - - QMutexLocker locker(&data->postEventList.mutex); - if (data->postEventList.size() == 0) - return; - for (int i = 0; i < data->postEventList.size(); ++i) { - const QPostEvent & pe = data->postEventList.at(i); - if (pe.receiver == object - && pe.event - && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent) - && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) { - --pe.receiver->d_func()->postedEvents; - pe.event->posted = false; - delete pe.event; - const_cast<QPostEvent &>(pe).event = 0; - return; - } - } -} - #if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM) /***************************************************************************** Convenience functions for convert WM_* messages into human readable strings, @@ -1050,4 +1028,28 @@ QDebug operator<<(QDebug dbg, const MSG &msg) #endif // !defined(Q_OS_WINRT) +#ifndef QT_NO_QOBJECT +void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId) +{ + QThreadData *data = object->d_func()->threadData; + + QMutexLocker locker(&data->postEventList.mutex); + if (data->postEventList.size() == 0) + return; + for (int i = 0; i < data->postEventList.size(); ++i) { + const QPostEvent &pe = data->postEventList.at(i); + if (pe.receiver == object + && pe.event + && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent) + && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) { + --pe.receiver->d_func()->postedEvents; + pe.event->posted = false; + delete pe.event; + const_cast<QPostEvent &>(pe).event = 0; + return; + } + } +} +#endif // QT_NO_QOBJECT + QT_END_NAMESPACE diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index 0a68de8871..98514c56af 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -167,7 +167,7 @@ QT_BEGIN_NAMESPACE \value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area. \value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area. \value NonClientAreaMouseMove A mouse move occurred outside the client area. - \value MacSizeChange The user changed his widget sizes (Mac OS X only). + \value MacSizeChange The user changed his widget sizes (OS X only). \value MetaCall An asynchronous method invocation via QMetaObject::invokeMethod(). \value ModifiedChange Widgets modification state has been changed. \value MouseButtonDblClick Mouse press again (QMouseEvent). @@ -211,7 +211,7 @@ QT_BEGIN_NAMESPACE \omitvalue ThemeChange \value ThreadChange The object is moved to another thread. This is the last event sent to this object in the previous thread. See QObject::moveToThread(). \value Timer Regular timer events (QTimerEvent). - \value ToolBarChange The toolbar button is toggled on Mac OS X. + \value ToolBarChange The toolbar button is toggled on OS X. \value ToolTip A tooltip was requested (QHelpEvent). \value ToolTipChange The widget's tooltip has changed. \value TouchBegin Beginning of a sequence of touch-screen or track-pad events (QTouchEvent). diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp index e0ce53bff1..796daaa50a 100644 --- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp +++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp @@ -49,6 +49,8 @@ #define qEventDispatcherDebug QT_NO_QDEBUG_MACRO() #endif +QT_BEGIN_NAMESPACE + class BpsChannelScopeSwitcher { public: diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp index 5e4ef937b9..cc8e961be1 100644 --- a/src/corelib/kernel/qeventdispatcher_winrt.cpp +++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp @@ -54,62 +54,20 @@ using namespace ABI::Windows::ApplicationModel::Core; QT_BEGIN_NAMESPACE -class QZeroTimerEvent : public QTimerEvent -{ -public: - explicit inline QZeroTimerEvent(int timerId) - : QTimerEvent(timerId) - { t = QEvent::ZeroTimerEvent; } -}; - -struct WinRTTimerInfo // internal timer info -{ - WinRTTimerInfo(int timerId, int timerInterval, Qt::TimerType timerType, QObject *object, QEventDispatcherWinRT *dispatcher) - : isFinished(false), id(timerId), interval(timerInterval), timerType(timerType), obj(object), inTimerEvent(false), dispatcher(dispatcher) - { - } - - void cancel() +#define INTERRUPT_HANDLE 0 +#define INVALID_TIMER_ID -1 + +struct WinRTTimerInfo : public QAbstractEventDispatcher::TimerInfo { + WinRTTimerInfo(int timerId = INVALID_TIMER_ID, int interval = 0, Qt::TimerType timerType = Qt::CoarseTimer, + QObject *obj = 0, quint64 tt = 0) : + QAbstractEventDispatcher::TimerInfo(timerId, interval, timerType), + inEvent(false), object(obj), targetTime(tt) { - if (isFinished) { - delete this; - return; - } - isFinished = true; - if (!timer) - return; - - HRESULT hr = timer->Cancel(); - RETURN_VOID_IF_FAILED("Failed to cancel timer"); } - HRESULT timerExpired(IThreadPoolTimer *) - { - if (isFinished) - return S_OK; - if (dispatcher) - QCoreApplication::postEvent(dispatcher, new QTimerEvent(id)); - return S_OK; - } - - HRESULT timerDestroyed(IThreadPoolTimer *) - { - if (isFinished) - delete this; - else - isFinished = true; - return S_OK; - } - - bool isFinished; - int id; - int interval; - Qt::TimerType timerType; - quint64 timeout; // - when to actually fire - QObject *obj; // - object to receive events - bool inTimerEvent; - ComPtr<IThreadPoolTimer> timer; - QPointer<QEventDispatcherWinRT> dispatcher; + bool inEvent; + QObject *object; + quint64 targetTime; }; class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate @@ -121,13 +79,63 @@ public: ~QEventDispatcherWinRTPrivate(); private: - QHash<int, WinRTTimerInfo*> timerDict; - ComPtr<IThreadPoolTimerStatics> timerFactory; ComPtr<ICoreDispatcher> coreDispatcher; QPointer<QThread> thread; - bool interrupt; + QHash<int, QObject *> timerIdToObject; + QVector<WinRTTimerInfo> timerInfos; + QHash<HANDLE, int> timerHandleToId; + QHash<int, HANDLE> timerIdToHandle; + QHash<int, HANDLE> timerIdToCancelHandle; + + void addTimer(int id, int interval, Qt::TimerType type, QObject *obj, + HANDLE handle, HANDLE cancelHandle) + { + // Zero timer events do not need these handles. + if (interval > 0) { + timerHandleToId.insert(handle, id); + timerIdToHandle.insert(id, handle); + timerIdToCancelHandle.insert(id, cancelHandle); + } + timerIdToObject.insert(id, obj); + const quint64 targetTime = qt_msectime() + interval; + const WinRTTimerInfo info(id, interval, type, obj, targetTime); + if (id >= timerInfos.size()) + timerInfos.resize(id + 1); + timerInfos[id] = info; + timerIdToObject.insert(id, obj); + } + + bool removeTimer(int id) + { + if (id >= timerInfos.size()) + return false; + + WinRTTimerInfo &info = timerInfos[id]; + if (info.timerId == INVALID_TIMER_ID) + return false; + + if (info.interval > 0 && (!timerIdToHandle.contains(id) || !timerIdToCancelHandle.contains(id))) + return false; + + info.timerId = INVALID_TIMER_ID; + + // Remove invalid timerinfos from the vector's end, if the timer with the highest id was removed + int lastTimer = timerInfos.size() - 1; + while (lastTimer >= 0 && timerInfos.at(lastTimer).timerId == INVALID_TIMER_ID) + --lastTimer; + if (lastTimer >= 0 && lastTimer != timerInfos.size() - 1) + timerInfos.resize(lastTimer + 1); + timerIdToObject.remove(id); + // ... remove handle from all lists + if (info.interval > 0) { + HANDLE handle = timerIdToHandle.take(id); + timerHandleToId.remove(handle); + SetEvent(timerIdToCancelHandle.take(id)); + } + return true; + } void fetchCoreDispatcher() { @@ -183,8 +191,7 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) if (d->thread && d->thread != QThread::currentThread()) d->fetchCoreDispatcher(); - bool didProcess = false; - forever { + do { // Process native events if (d->coreDispatcher) { boolean hasThreadAccess; @@ -197,23 +204,32 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags) } // Dispatch accumulated user events - didProcess = sendPostedEvents(flags); - if (didProcess) - break; + if (sendPostedEvents(flags)) + return true; - if (d->interrupt) - break; + emit aboutToBlock(); + const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector(); + DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 1, TRUE); + if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) { + const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0); + const int timerId = d->timerHandleToId.value(handle); + if (timerId == INTERRUPT_HANDLE) + break; - // Short sleep if there is nothing to do - if (!(flags & QEventLoop::WaitForMoreEvents)) - break; + WinRTTimerInfo &info = d->timerInfos[timerId]; + Q_ASSERT(info.timerId != INVALID_TIMER_ID); - emit aboutToBlock(); - WaitForSingleObjectEx(GetCurrentThread(), 1, FALSE); + QCoreApplication::postEvent(this, new QTimerEvent(timerId)); + + // Update timer's targetTime + const quint64 targetTime = qt_msectime() + info.interval; + info.targetTime = targetTime; + emit awake(); + return true; + } emit awake(); - } - d->interrupt = false; - return didProcess; + } while (flags & QEventLoop::WaitForMoreEvents); + return false; } bool QEventDispatcherWinRT::sendPostedEvents(QEventLoop::ProcessEventsFlags flags) @@ -246,104 +262,121 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy { Q_UNUSED(timerType); -#ifndef QT_NO_DEBUG if (timerId < 1 || interval < 0 || !object) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT::registerTimer: invalid arguments"); +#endif return; } else if (object->thread() != thread() || thread() != QThread::currentThread()) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT::registerTimer: timers cannot be started from another thread"); +#endif return; } -#endif Q_D(QEventDispatcherWinRT); - - WinRTTimerInfo *t = new WinRTTimerInfo(timerId, interval, timerType, object, this); - t->timeout = qt_msectime() + interval; - d->timerDict.insert(t->id, t); - // Don't use timer factory for zero-delay timers if (interval == 0u) { - QCoreApplication::postEvent(this, new QZeroTimerEvent(timerId)); + d->addTimer(timerId, interval, timerType, object, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE); + QCoreApplication::postEvent(this, new QTimerEvent(timerId)); return; } TimeSpan period; period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units + IThreadPoolTimer *timer; + const HANDLE handle = CreateEventEx(NULL, NULL, NULL, SYNCHRONIZE|EVENT_MODIFY_STATE); + const HANDLE cancelHandle = CreateEventEx(NULL, NULL, NULL, SYNCHRONIZE|EVENT_MODIFY_STATE); HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion( - Callback<ITimerElapsedHandler>(t, &WinRTTimerInfo::timerExpired).Get(), period, - Callback<ITimerDestroyedHandler>(t, &WinRTTimerInfo::timerDestroyed).Get(), &t->timer); + Callback<ITimerElapsedHandler>([handle, cancelHandle](IThreadPoolTimer *timer) { + DWORD cancelResult = WaitForSingleObjectEx(cancelHandle, 0, TRUE); + if (cancelResult == WAIT_OBJECT_0) { + timer->Cancel(); + return S_OK; + } + if (!SetEvent(handle)) { + Q_ASSERT_X(false, "QEventDispatcherWinRT::registerTimer", + "SetEvent should never fail here"); + return S_OK; + } + return S_OK; + }).Get(), period, + Callback<ITimerDestroyedHandler>([handle, cancelHandle](IThreadPoolTimer *) { + CloseHandle(handle); + CloseHandle(cancelHandle); + return S_OK; + }).Get(), &timer); if (FAILED(hr)) { qErrnoWarning(hr, "Failed to create periodic timer"); - delete t; - d->timerDict.remove(t->id); + CloseHandle(handle); + CloseHandle(cancelHandle); return; } + d->addTimer(timerId, interval, timerType, object, handle, cancelHandle); } bool QEventDispatcherWinRT::unregisterTimer(int timerId) { -#ifndef QT_NO_DEBUG if (timerId < 1) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT::unregisterTimer: invalid argument"); +#endif return false; } if (thread() != QThread::currentThread()) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT::unregisterTimer: timers cannot be stopped from another thread"); +#endif return false; } -#endif + // As we post all timer events internally, they have to pe removed to prevent stray events + QCoreApplicationPrivate::removePostedTimerEvent(this, timerId); Q_D(QEventDispatcherWinRT); - - WinRTTimerInfo *t = d->timerDict.take(timerId); - if (!t) - return false; - - t->cancel(); - return true; + return d->removeTimer(timerId); } bool QEventDispatcherWinRT::unregisterTimers(QObject *object) { -#ifndef QT_NO_DEBUG if (!object) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT::unregisterTimers: invalid argument"); +#endif return false; } QThread *currentThread = QThread::currentThread(); if (object->thread() != thread() || thread() != currentThread) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT::unregisterTimers: timers cannot be stopped from another thread"); +#endif return false; } -#endif Q_D(QEventDispatcherWinRT); - for (QHash<int, WinRTTimerInfo *>::iterator it = d->timerDict.begin(); it != d->timerDict.end();) { - if (it.value()->obj == object) { - it.value()->cancel(); - it = d->timerDict.erase(it); - continue; - } - ++it; + foreach (int id, d->timerIdToObject.keys()) { + if (d->timerIdToObject.value(id) == object) + unregisterTimer(id); } + return true; } QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTimers(QObject *object) const { if (!object) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT:registeredTimers: invalid argument"); +#endif return QList<TimerInfo>(); } Q_D(const QEventDispatcherWinRT); - QList<TimerInfo> list; - foreach (const WinRTTimerInfo *t, d->timerDict) { - if (t->obj == object) - list.append(TimerInfo(t->id, t->interval, t->timerType)); + QList<TimerInfo> timerInfos; + foreach (const WinRTTimerInfo &info, d->timerInfos) { + if (info.object == object) + timerInfos.append(info); } - return list; + return timerInfos; } bool QEventDispatcherWinRT::registerEventNotifier(QWinEventNotifier *notifier) @@ -361,27 +394,30 @@ void QEventDispatcherWinRT::unregisterEventNotifier(QWinEventNotifier *notifier) int QEventDispatcherWinRT::remainingTime(int timerId) { -#ifndef QT_NO_DEBUG if (timerId < 1) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT::remainingTime: invalid argument"); +#endif return -1; } -#endif Q_D(QEventDispatcherWinRT); - if (WinRTTimerInfo *t = d->timerDict.value(timerId)) { - const quint64 currentTime = qt_msectime(); - if (currentTime < t->timeout) { - // time to wait - return t->timeout - currentTime; - } else { - return 0; - } - } - + const WinRTTimerInfo timerInfo = d->timerInfos.at(timerId); + if (timerInfo.timerId == INVALID_TIMER_ID) { #ifndef QT_NO_DEBUG - qWarning("QEventDispatcherWinRT::remainingTime: timer id %d not found", timerId); + qWarning("QEventDispatcherWinRT::remainingTime: timer id %d not found", timerId); #endif + return -1; + } + + const quint64 currentTime = qt_msectime(); + if (currentTime < timerInfo.targetTime) { + // time to wait + return timerInfo.targetTime - currentTime; + } else { + return 0; + } + return -1; } @@ -392,7 +428,7 @@ void QEventDispatcherWinRT::wakeUp() void QEventDispatcherWinRT::interrupt() { Q_D(QEventDispatcherWinRT); - d->interrupt = true; + SetEvent(d->timerIdToHandle.value(INTERRUPT_HANDLE)); } void QEventDispatcherWinRT::flush() @@ -405,55 +441,60 @@ void QEventDispatcherWinRT::startingUp() void QEventDispatcherWinRT::closingDown() { - Q_D(QEventDispatcherWinRT); - d->timerDict.clear(); } bool QEventDispatcherWinRT::event(QEvent *e) { Q_D(QEventDispatcherWinRT); - bool ret = false; switch (e->type()) { - case QEvent::ZeroTimerEvent: - ret = true; - // fall through case QEvent::Timer: { QTimerEvent *timerEvent = static_cast<QTimerEvent *>(e); const int id = timerEvent->timerId(); - if (WinRTTimerInfo *t = d->timerDict.value(id)) { - if (t->inTimerEvent) // but don't allow event to recurse - break; - t->inTimerEvent = true; + Q_ASSERT(id < d->timerInfos.size()); + WinRTTimerInfo &info = d->timerInfos[id]; + Q_ASSERT(info.timerId != INVALID_TIMER_ID); - QTimerEvent te(id); - QCoreApplication::sendEvent(t->obj, &te); + if (info.inEvent) // but don't allow event to recurse + break; + info.inEvent = true; - if (t = d->timerDict.value(id)) { - if (t->interval == 0 && t->inTimerEvent) { - // post the next zero timer event as long as the timer was not restarted - QCoreApplication::postEvent(this, new QZeroTimerEvent(id)); - } - t->inTimerEvent = false; - } + QTimerEvent te(id); + QCoreApplication::sendEvent(d->timerIdToObject.value(id), &te); + + // The timer might have been removed in the meanwhile + if (id >= d->timerInfos.size()) + break; + + info = d->timerInfos[id]; + if (info.timerId == INVALID_TIMER_ID) + break; + + if (info.interval == 0 && info.inEvent) { + // post the next zero timer event as long as the timer was not restarted + QCoreApplication::postEvent(this, new QTimerEvent(id)); } + info.inEvent = false; } default: break; } - return ret ? true : QAbstractEventDispatcher::event(e); + return QAbstractEventDispatcher::event(e); } QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate() - : interrupt(false) { CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory); - if (FAILED(hr)) - qWarning("QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate: Could not obtain timer factory: %lx", hr); + Q_ASSERT_SUCCEEDED(hr); + HANDLE interruptHandle = CreateEventEx(NULL, NULL, NULL, SYNCHRONIZE|EVENT_MODIFY_STATE); + timerIdToHandle.insert(INTERRUPT_HANDLE, interruptHandle); + timerHandleToId.insert(interruptHandle, INTERRUPT_HANDLE); + timerInfos.reserve(256); } QEventDispatcherWinRTPrivate::~QEventDispatcherWinRTPrivate() { + CloseHandle(timerIdToHandle.value(INTERRUPT_HANDLE)); CoUninitialize(); } diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index d4a69ee4b9..3b70ef92ed 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -872,13 +872,17 @@ static inline int qMetaTypeStaticType(const char *typeName, int length) \internal Similar to QMetaType::type(), but only looks in the custom set of types, and doesn't lock the mutex. + The extra \a firstInvalidIndex parameter is an easy way to avoid + iterating over customTypes() a second time in registerNormalizedType(). */ -static int qMetaTypeCustomType_unlocked(const char *typeName, int length) +static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = 0) { const QVector<QCustomTypeInfo> * const ct = customTypes(); if (!ct) return QMetaType::UnknownType; + if (firstInvalidIndex) + *firstInvalidIndex = -1; for (int v = 0; v < ct->count(); ++v) { const QCustomTypeInfo &customInfo = ct->at(v); if ((length == customInfo.typeName.size()) @@ -887,6 +891,8 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length) return customInfo.alias; return v + QMetaType::User; } + if (firstInvalidIndex && (*firstInvalidIndex < 0) && customInfo.typeName.isEmpty()) + *firstInvalidIndex = v; } return QMetaType::UnknownType; } @@ -907,6 +913,39 @@ int QMetaType::registerType(const char *typeName, Deleter deleter, /*! \internal + \since 5.5 + + Unregisters the user type with the given \a typeId and all its aliases. + Returns \c true if the type was unregistered or \c false otherwise. + + This function was added for QML to be able to deregister types after + they are unloaded to prevent an infinite increase in custom types for + applications that are unloading/reloading components often. + */ +bool QMetaType::unregisterType(int type) +{ + QWriteLocker locker(customTypesLock()); + QVector<QCustomTypeInfo> *ct = customTypes(); + + // check if user type + if ((type < User) || ((type - User) >= ct->size())) + return false; + + // only types without Q_DECLARE_METATYPE can be unregistered + if (ct->data()[type - User].flags & WasDeclaredAsMetaType) + return false; + + // invalidate type and all its alias entries + for (int v = 0; v < ct->count(); ++v) { + if (((v + User) == type) || (ct->at(v).alias == type)) + ct->data()[v].typeName.clear(); + } + return true; +} + + +/*! + \internal \since 5.0 Registers a user type for marshalling, with \a typeName, a \a @@ -977,8 +1016,10 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, int previousFlags = 0; if (idx == UnknownType) { QWriteLocker locker(customTypesLock()); + int posInVector = -1; idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(), - normalizedTypeName.size()); + normalizedTypeName.size(), + &posInVector); if (idx == UnknownType) { QCustomTypeInfo inf; inf.typeName = normalizedTypeName; @@ -992,8 +1033,13 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName, inf.size = size; inf.flags = flags; inf.metaObject = metaObject; - idx = ct->size() + User; - ct->append(inf); + if (posInVector == -1) { + idx = ct->size() + User; + ct->append(inf); + } else { + idx = posInVector + User; + ct->data()[posInVector] = inf; + } return idx; } @@ -1075,14 +1121,19 @@ int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeNam if (idx == UnknownType) { QWriteLocker locker(customTypesLock()); + int posInVector = -1; idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(), - normalizedTypeName.size()); + normalizedTypeName.size(), + &posInVector); if (idx == UnknownType) { QCustomTypeInfo inf; inf.typeName = normalizedTypeName; inf.alias = aliasId; - ct->append(inf); + if (posInVector == -1) + ct->append(inf); + else + ct->data()[posInVector] = inf; return aliasId; } } diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index aa8d826ed9..1e2a860d8c 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -484,6 +484,7 @@ public: int size, QMetaType::TypeFlags flags, const QMetaObject *metaObject); + static bool unregisterType(int type); static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter, Creator creator, Destructor destructor, diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 31c749dc13..fb4c5cceb9 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1394,7 +1394,7 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */) \sa signalsBlocked() */ -bool QObject::blockSignals(bool block) +bool QObject::blockSignals(bool block) Q_DECL_NOTHROW { Q_D(QObject); bool previous = d->blockSig; @@ -1475,7 +1475,7 @@ void QObject::moveToThread(QThread *targetThread) currentData->thread, d->threadData->thread, targetData ? targetData->thread : Q_NULLPTR); #ifdef Q_OS_MAC - qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. " + qWarning("You might be loading two sets of Qt binaries into the same process. " "Check that all plugins are compiled against the right Qt binaries. Export " "DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded."); #endif diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 42d18d6c41..5f61dd984f 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -137,8 +137,8 @@ public: inline bool isWidgetType() const { return d_ptr->isWidget; } inline bool isWindowType() const { return d_ptr->isWindow; } - inline bool signalsBlocked() const { return d_ptr->blockSig; } - bool blockSignals(bool b); + inline bool signalsBlocked() const Q_DECL_NOTHROW { return d_ptr->blockSig; } + bool blockSignals(bool b) Q_DECL_NOTHROW; QThread *thread() const; void moveToThread(QThread *thread); @@ -413,11 +413,7 @@ public: Q_SIGNALS: void destroyed(QObject * = 0); - void objectNameChanged(const QString &objectName -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void objectNameChanged(const QString &objectName, QPrivateSignal); public: inline QObject *parent() const { return d_ptr->parent; } @@ -552,17 +548,17 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *); class QSignalBlocker { public: - inline explicit QSignalBlocker(QObject *o); - inline explicit QSignalBlocker(QObject &o); + inline explicit QSignalBlocker(QObject *o) Q_DECL_NOTHROW; + inline explicit QSignalBlocker(QObject &o) Q_DECL_NOTHROW; inline ~QSignalBlocker(); #ifdef Q_COMPILER_RVALUE_REFS - inline QSignalBlocker(QSignalBlocker &&other); - inline QSignalBlocker &operator=(QSignalBlocker &&other); + inline QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW; + inline QSignalBlocker &operator=(QSignalBlocker &&other) Q_DECL_NOTHROW; #endif - inline void reblock(); - inline void unblock(); + inline void reblock() Q_DECL_NOTHROW; + inline void unblock() Q_DECL_NOTHROW; private: Q_DISABLE_COPY(QSignalBlocker) QObject * m_o; @@ -570,20 +566,20 @@ private: bool m_inhibited; }; -QSignalBlocker::QSignalBlocker(QObject *o) +QSignalBlocker::QSignalBlocker(QObject *o) Q_DECL_NOTHROW : m_o(o), m_blocked(o && o->blockSignals(true)), m_inhibited(false) {} -QSignalBlocker::QSignalBlocker(QObject &o) +QSignalBlocker::QSignalBlocker(QObject &o) Q_DECL_NOTHROW : m_o(&o), m_blocked(o.blockSignals(true)), m_inhibited(false) {} #ifdef Q_COMPILER_RVALUE_REFS -QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) +QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW : m_o(other.m_o), m_blocked(other.m_blocked), m_inhibited(other.m_inhibited) @@ -591,7 +587,7 @@ QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) other.m_o = 0; } -QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) +QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW { if (this != &other) { // if both *this and other block the same object's signals: @@ -614,13 +610,13 @@ QSignalBlocker::~QSignalBlocker() m_o->blockSignals(m_blocked); } -void QSignalBlocker::reblock() +void QSignalBlocker::reblock() Q_DECL_NOTHROW { if (m_o) m_o->blockSignals(true); m_inhibited = false; } -void QSignalBlocker::unblock() +void QSignalBlocker::unblock() Q_DECL_NOTHROW { if (m_o) m_o->blockSignals(m_blocked); m_inhibited = true; diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp index e4f7339e6c..f91a6d02d6 100644 --- a/src/corelib/kernel/qppsattribute.cpp +++ b/src/corelib/kernel/qppsattribute.cpp @@ -37,6 +37,8 @@ #include <QDebug> #include <QVariant> +QT_BEGIN_NAMESPACE + /////////////////////////// // // QPpsAttributePrivate @@ -298,3 +300,5 @@ QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute) return dbg; } + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h index 528cbbc0ca..5ed0daaad0 100644 --- a/src/corelib/kernel/qppsattribute_p.h +++ b/src/corelib/kernel/qppsattribute_p.h @@ -57,8 +57,6 @@ class QPpsAttribute; typedef QList<QPpsAttribute> QPpsAttributeList; typedef QMap<QString, QPpsAttribute> QPpsAttributeMap; -Q_DECLARE_METATYPE(QPpsAttributeList) -Q_DECLARE_METATYPE(QPpsAttributeMap) class Q_CORE_EXPORT QPpsAttribute { @@ -128,4 +126,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute); QT_END_NAMESPACE +Q_DECLARE_METATYPE(QPpsAttributeList) +Q_DECLARE_METATYPE(QPpsAttributeMap) + #endif // QPPSATTRIBUTE_P_H diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp index e9b455bfba..76508f12c5 100644 --- a/src/corelib/kernel/qppsobject.cpp +++ b/src/corelib/kernel/qppsobject.cpp @@ -50,6 +50,8 @@ #include <sys/pps.h> +QT_BEGIN_NAMESPACE + /////////////////////////////////////////////////////////////////////////////// static inline void safeAssign(bool *pointer, bool value) { @@ -954,3 +956,5 @@ int QPpsObject::sendMessage(const QString &path, const QByteArray &ppsData) return EOK; } + +QT_END_NAMESPACE diff --git a/src/corelib/kernel/qsocketnotifier.h b/src/corelib/kernel/qsocketnotifier.h index c6e9d1e13f..4bafbfa69f 100644 --- a/src/corelib/kernel/qsocketnotifier.h +++ b/src/corelib/kernel/qsocketnotifier.h @@ -59,11 +59,7 @@ public Q_SLOTS: void setEnabled(bool); Q_SIGNALS: - void activated(int socket -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void activated(int socket, QPrivateSignal); protected: bool event(QEvent *) Q_DECL_OVERRIDE; diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h index dc948228b4..163ef75291 100644 --- a/src/corelib/kernel/qtimer.h +++ b/src/corelib/kernel/qtimer.h @@ -141,11 +141,7 @@ public Q_SLOTS: void stop(); Q_SIGNALS: - void timeout( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void timeout(QPrivateSignal); protected: void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE; diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h index 07a0b29d97..95fdff07ce 100644 --- a/src/corelib/kernel/qwineventnotifier.h +++ b/src/corelib/kernel/qwineventnotifier.h @@ -61,11 +61,7 @@ public Q_SLOTS: void setEnabled(bool enable); Q_SIGNALS: - void activated(HANDLE hEvent -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); + void activated(HANDLE hEvent, QPrivateSignal); protected: bool event(QEvent * e); diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index b919e1c48a..bec7a79e8f 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -238,7 +238,7 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent) The MIME type database is provided by the freedesktop.org shared-mime-info project. If the MIME type database cannot be found on the system, as is the case - on most Windows and Mac OS X systems, Qt will use its own copy of it. + on most Windows, OS X, and iOS systems, Qt will use its own copy of it. Applications which want to define custom MIME types need to install an XML file into the locations searched for MIME definitions. diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index c843d029af..920e02ae5a 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -599,7 +599,7 @@ bool QLibraryPrivate::loadPlugin() \row \li Unix/Linux \li \c .so \row \li AIX \li \c .a \row \li HP-UX \li \c .sl, \c .so (HP-UXi) - \row \li Mac OS X \li \c .dylib, \c .bundle, \c .so + \row \li OS X and iOS \li \c .dylib, \c .bundle, \c .so \endtable Trailing versioning numbers on Unix are ignored. @@ -836,7 +836,7 @@ QLibrary::QLibrary(QObject *parent) We recommend omitting the file's suffix in \a fileName, since QLibrary will automatically look for the file with the appropriate suffix in accordance with the platform, e.g. ".so" on Unix, - ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.) + ".dylib" on OS X and iOS, and ".dll" on Windows. (See \l{fileName}.) */ QLibrary::QLibrary(const QString& fileName, QObject *parent) :QObject(parent), d(0), did_load(false) @@ -853,7 +853,7 @@ QLibrary::QLibrary(const QString& fileName, QObject *parent) We recommend omitting the file's suffix in \a fileName, since QLibrary will automatically look for the file with the appropriate suffix in accordance with the platform, e.g. ".so" on Unix, - ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.) + ".dylib" on OS X and iOS, and ".dll" on Windows. (See \l{fileName}.) */ QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent) :QObject(parent), d(0), did_load(false) @@ -869,7 +869,7 @@ QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent) We recommend omitting the file's suffix in \a fileName, since QLibrary will automatically look for the file with the appropriate suffix in accordance with the platform, e.g. ".so" on Unix, - ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.) + ".dylib" on OS X and iOS, and ".dll" on Windows. (See \l{fileName}.) */ QLibrary::QLibrary(const QString& fileName, const QString &version, QObject *parent) :QObject(parent), d(0), did_load(false) diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 2800656c13..2756414d70 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -139,7 +139,7 @@ QPluginLoader::QPluginLoader(QObject *parent) To be loadable, the file's suffix must be a valid suffix for a loadable library in accordance with the platform, e.g. \c .so on - Unix, - \c .dylib on Mac OS X, and \c .dll on Windows. The suffix + Unix, - \c .dylib on OS X and iOS, and \c .dll on Windows. The suffix can be verified with QLibrary::isLibrary(). \sa setFileName() diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h index b6eb742acb..592c841c18 100644 --- a/src/corelib/statemachine/qabstractstate.h +++ b/src/corelib/statemachine/qabstractstate.h @@ -58,16 +58,8 @@ public: bool active() const; Q_SIGNALS: - void entered( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void exited( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void entered(QPrivateSignal); + void exited(QPrivateSignal); void activeChanged(bool active); protected: diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h index 0f1bbdad71..768a364a4b 100644 --- a/src/corelib/statemachine/qabstracttransition.h +++ b/src/corelib/statemachine/qabstracttransition.h @@ -78,21 +78,9 @@ public: #endif Q_SIGNALS: - void triggered( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void targetStateChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void targetStatesChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void triggered(QPrivateSignal); + void targetStateChanged(QPrivateSignal); + void targetStatesChanged(QPrivateSignal); protected: virtual bool eventTest(QEvent *event) = 0; diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h index 31f0d3121b..549be15ab0 100644 --- a/src/corelib/statemachine/qhistorystate.h +++ b/src/corelib/statemachine/qhistorystate.h @@ -65,16 +65,8 @@ public: void setHistoryType(HistoryType type); Q_SIGNALS: - void defaultStateChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void historyTypeChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void defaultStateChanged(QPrivateSignal); + void historyTypeChanged(QPrivateSignal); protected: void onEntry(QEvent *event) Q_DECL_OVERRIDE; diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h index 8b9e63404a..bc56f4e9b7 100644 --- a/src/corelib/statemachine/qsignaltransition.h +++ b/src/corelib/statemachine/qsignaltransition.h @@ -67,16 +67,8 @@ protected: bool event(QEvent *e) Q_DECL_OVERRIDE; Q_SIGNALS: - void senderObjectChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void signalChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void senderObjectChanged(QPrivateSignal); + void signalChanged(QPrivateSignal); private: Q_DISABLE_COPY(QSignalTransition) diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h index b1f2ad05bc..a74c782027 100644 --- a/src/corelib/statemachine/qstate.h +++ b/src/corelib/statemachine/qstate.h @@ -103,31 +103,11 @@ public: #endif Q_SIGNALS: - void finished( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void propertiesAssigned( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void childModeChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void initialStateChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void errorStateChanged( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void finished(QPrivateSignal); + void propertiesAssigned(QPrivateSignal); + void childModeChanged(QPrivateSignal); + void initialStateChanged(QPrivateSignal); + void errorStateChanged(QPrivateSignal); protected: void onEntry(QEvent *event) Q_DECL_OVERRIDE; diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index a681688d46..f103bec591 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -177,6 +177,98 @@ QT_BEGIN_NAMESPACE // #define QSTATEMACHINE_DEBUG // #define QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG +/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : + +function isDescendant(state1, state2) + +Returns 'true' if state1 is a descendant of state2 (a child, or a child of a child, or a child of a +child of a child, etc.) Otherwise returns 'false'. +*/ +static inline bool isDescendant(const QAbstractState *state1, const QAbstractState *state2) +{ + Q_ASSERT(state1 != 0); + + for (QAbstractState *it = state1->parentState(); it != 0; it = it->parentState()) { + if (it == state2) + return true; + } + + return false; +} + +static bool containsDecendantOf(const QSet<QAbstractState *> &states, const QAbstractState *node) +{ + Q_FOREACH (QAbstractState *s, states) + if (isDescendant(s, node)) + return true; + + return false; +} + +/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : + +function getProperAncestors(state1, state2) + +If state2 is null, returns the set of all ancestors of state1 in ancestry order (state1's parent +followed by the parent's parent, etc. up to an including the <scxml> element). If state2 is +non-null, returns in ancestry order the set of all ancestors of state1, up to but not including +state2. (A "proper ancestor" of a state is its parent, or the parent's parent, or the parent's +parent's parent, etc.))If state2 is state1's parent, or equal to state1, or a descendant of state1, +this returns the empty set. +*/ +static QVector<QState*> getProperAncestors(const QAbstractState *state, const QAbstractState *upperBound) +{ + Q_ASSERT(state != 0); + QVector<QState*> result; + result.reserve(16); + for (QState *it = state->parentState(); it && it != upperBound; it = it->parentState()) { + result.append(it); + } + return result; +} + +/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : + +function getEffectiveTargetStates(transition) + +Returns the states that will be the target when 'transition' is taken, dereferencing any history states. + +function getEffectiveTargetStates(transition) + targets = new OrderedSet() + for s in transition.target + if isHistoryState(s): + if historyValue[s.id]: + targets.union(historyValue[s.id]) + else: + targets.union(getEffectiveTargetStates(s.transition)) + else: + targets.add(s) + return targets +*/ +static QSet<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *transition) +{ + QSet<QAbstractState *> targets; + foreach (QAbstractState *s, transition->targetStates()) { + if (QHistoryState *historyState = QStateMachinePrivate::toHistoryState(s)) { + QList<QAbstractState*> historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration; + if (!historyConfiguration.isEmpty()) { + // There is a saved history, so apply that. + targets.unite(historyConfiguration.toSet()); + } else if (QAbstractState *defaultState = historyState->defaultState()) { + // Qt does not support initial transitions, but uses the default state of the history state for this. + targets.insert(defaultState); + } else { + // Woops, we found a history state without a default state. That's not valid! + QStateMachinePrivate *m = QStateMachinePrivate::get(historyState->machine()); + m->setError(QStateMachine::NoDefaultStateInHistoryStateError, historyState); + } + } else { + targets.insert(s); + } + } + return targets; +} + template <class T> static uint qHash(const QPointer<T> &p) { return qHash(p.data()); } @@ -246,21 +338,30 @@ static int indexOfDescendant(QState *s, QAbstractState *desc) QList<QAbstractState*> childStates = QStatePrivate::get(s)->childStates(); for (int i = 0; i < childStates.size(); ++i) { QAbstractState *c = childStates.at(i); - if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) { + if ((c == desc) || isDescendant(desc, c)) { return i; } } return -1; } +bool QStateMachinePrivate::transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2) +{ + QState *s1 = t1->sourceState(), *s2 = t2->sourceState(); + if (s1 == s2) + return QStatePrivate::get(s1)->transitions().indexOf(t1) < QStatePrivate::get(s2)->transitions().indexOf(t2); + else + return stateEntryLessThan(t1->sourceState(), t2->sourceState()); +} + bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2) { if (s1->parent() == s2->parent()) { return s1->parent()->children().indexOf(s1) < s2->parent()->children().indexOf(s2); - } else if (isDescendantOf(s1, s2)) { + } else if (isDescendant(s1, s2)) { return false; - } else if (isDescendantOf(s2, s1)) { + } else if (isDescendant(s2, s1)) { return true; } else { Q_ASSERT(s1->machine() != 0); @@ -276,9 +377,9 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState if (s1->parent() == s2->parent()) { return s2->parent()->children().indexOf(s2) < s1->parent()->children().indexOf(s1); - } else if (isDescendantOf(s1, s2)) { + } else if (isDescendant(s1, s2)) { return true; - } else if (isDescendantOf(s2, s1)) { + } else if (isDescendant(s2, s1)) { return false; } else { Q_ASSERT(s1->machine() != 0); @@ -289,17 +390,20 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState } } -QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) const +QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states, bool onlyCompound) const { if (states.isEmpty()) return 0; - QList<QState*> ancestors = properAncestors(states.at(0), rootState()->parentState()); + QVector<QState*> ancestors = getProperAncestors(states.at(0), rootState()->parentState()); for (int i = 0; i < ancestors.size(); ++i) { QState *anc = ancestors.at(i); + if (onlyCompound && !isCompound(anc)) + continue; + bool ok = true; for (int j = states.size() - 1; (j > 0) && ok; --j) { const QAbstractState *s = states.at(j); - if (!isDescendantOf(s, anc)) + if (!isDescendant(s, anc)) ok = false; } if (ok) @@ -308,40 +412,26 @@ QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) cons return 0; } -bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const +QState *QStateMachinePrivate::findLCCA(const QList<QAbstractState*> &states) const { - QSet<QAbstractTransition*>::const_iterator it; - for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) { - QAbstractTransition *t = *it; - QList<QAbstractState*> lst = t->targetStates(); - if (!lst.isEmpty()) { - lst.prepend(t->sourceState()); - QAbstractState *lca = findLCA(lst); - if (isDescendantOf(s, lca)) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q_func() << ':' << transitions << "preempts selection of a transition from" - << s << "because" << s << "is a descendant of" << lca; -#endif - return true; - } - } - } - return false; + return findLCA(states, true); } -QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event) const +QList<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event) { Q_Q(const QStateMachine); - QSet<QAbstractTransition*> enabledTransitions; - QSet<QAbstractState*>::const_iterator it; + + QVarLengthArray<QAbstractState *> configuration_sorted; + foreach (QAbstractState *s, configuration) { + if (isAtomic(s)) + configuration_sorted.append(s); + } + std::sort(configuration_sorted.begin(), configuration_sorted.end(), stateEntryLessThan); + + QList<QAbstractTransition*> enabledTransitions; const_cast<QStateMachine*>(q)->beginSelectTransitions(event); - for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - QAbstractState *state = *it; - if (!isAtomic(state)) - continue; - if (isPreempted(state, enabledTransitions)) - continue; - QList<QState*> lst = properAncestors(state, rootState()->parentState()); + foreach (QAbstractState *state, configuration_sorted) { + QVector<QState*> lst = getProperAncestors(state, Q_NULLPTR); if (QState *grp = toStandardState(state)) lst.prepend(grp); bool found = false; @@ -354,28 +444,93 @@ QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event #ifdef QSTATEMACHINE_DEBUG qDebug() << q << ": selecting transition" << t; #endif - enabledTransitions.insert(t); + enabledTransitions.append(t); found = true; break; } } } } + + if (!enabledTransitions.isEmpty()) { + removeConflictingTransitions(enabledTransitions); +#ifdef QSTATEMACHINE_DEBUG + qDebug() << q << ": enabled transitions after removing conflicts:" << enabledTransitions; +#endif + } const_cast<QStateMachine*>(q)->endSelectTransitions(event); return enabledTransitions; } +/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : + +function removeConflictingTransitions(enabledTransitions): + filteredTransitions = new OrderedSet() + // toList sorts the transitions in the order of the states that selected them + for t1 in enabledTransitions.toList(): + t1Preempted = false; + transitionsToRemove = new OrderedSet() + for t2 in filteredTransitions.toList(): + if computeExitSet([t1]).hasIntersection(computeExitSet([t2])): + if isDescendant(t1.source, t2.source): + transitionsToRemove.add(t2) + else: + t1Preempted = true + break + if not t1Preempted: + for t3 in transitionsToRemove.toList(): + filteredTransitions.delete(t3) + filteredTransitions.add(t1) + + return filteredTransitions +*/ +void QStateMachinePrivate::removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions) +{ + QList<QAbstractTransition*> filteredTransitions; + filteredTransitions.reserve(enabledTransitions.size()); + std::sort(enabledTransitions.begin(), enabledTransitions.end(), transitionStateEntryLessThan); + + Q_FOREACH (QAbstractTransition *t1, enabledTransitions) { + bool t1Preempted = false; + QVarLengthArray<QAbstractTransition *> transitionsToRemove; + QSet<QAbstractState*> exitSetT1 = computeExitSet_Unordered(QList<QAbstractTransition*>() << t1); + Q_FOREACH (QAbstractTransition *t2, filteredTransitions) { + QSet<QAbstractState*> exitSetT2 = computeExitSet_Unordered(QList<QAbstractTransition*>() << t2); + if (!exitSetT1.intersect(exitSetT2).isEmpty()) { + if (isDescendant(t1->sourceState(), t2->sourceState())) { + transitionsToRemove.append(t2); + } else { + t1Preempted = true; + break; + } + } + } + if (!t1Preempted) { + Q_FOREACH (QAbstractTransition *t3, transitionsToRemove) + filteredTransitions.removeAll(t3); + filteredTransitions.append(t1); + } + } + + enabledTransitions = filteredTransitions; +} + void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')'; qDebug() << q_func() << ": configuration before exiting states:" << configuration; #endif - QList<QAbstractState*> exitedStates = computeStatesToExit(enabledTransitions); + QList<QAbstractState*> exitedStates = computeExitSet(enabledTransitions); QHash<RestorableId, QVariant> pendingRestorables = computePendingRestorables(exitedStates); QSet<QAbstractState*> statesForDefaultEntry; - QList<QAbstractState*> enteredStates = computeStatesToEnter(enabledTransitions, statesForDefaultEntry); + QList<QAbstractState*> enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry); + +#ifdef QSTATEMACHINE_DEBUG + qDebug() << q_func() << ": computed exit set:" << exitedStates; + qDebug() << q_func() << ": computed entry set:" << enteredStates; +#endif QHash<QAbstractState*, QList<QPropertyAssignment> > assignmentsForEnteredStates = computePropertyAssignments(enteredStates, pendingRestorables); @@ -409,38 +564,63 @@ void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransit #endif } -QList<QAbstractState*> QStateMachinePrivate::computeStatesToExit(const QList<QAbstractTransition*> &enabledTransitions) +/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : + +procedure computeExitSet(enabledTransitions) + +For each transition t in enabledTransitions, if t is targetless then do nothing, else compute the +transition's domain. (This will be the source state in the case of internal transitions) or the +least common compound ancestor state of the source state and target states of t (in the case of +external transitions. Add to the statesToExit set all states in the configuration that are +descendants of the domain. + +function computeExitSet(transitions) + statesToExit = new OrderedSet + for t in transitions: + if (t.target): + domain = getTransitionDomain(t) + for s in configuration: + if isDescendant(s,domain): + statesToExit.add(s) + return statesToExit +*/ +QList<QAbstractState*> QStateMachinePrivate::computeExitSet(const QList<QAbstractTransition*> &enabledTransitions) +{ + QList<QAbstractState*> statesToExit_sorted = computeExitSet_Unordered(enabledTransitions).toList(); + std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan); + return statesToExit_sorted; +} + +QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions) { QSet<QAbstractState*> statesToExit; -// QSet<QAbstractState*> statesToSnapshot; for (int i = 0; i < enabledTransitions.size(); ++i) { QAbstractTransition *t = enabledTransitions.at(i); - QList<QAbstractState*> lst = t->targetStates(); - if (lst.isEmpty()) - continue; - lst.prepend(t->sourceState()); - QAbstractState *lca = findLCA(lst); - if (lca == 0) { - setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState()); - lst = pendingErrorStates.toList(); + QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t).toList(); + QAbstractState *domain = getTransitionDomain(t, effectiveTargetStates); + if (domain == Q_NULLPTR && !t->targetStates().isEmpty()) { + // So we didn't find the least common ancestor for the source and target states of the + // transition. If there were not target states, that would be fine: then the transition + // will fire any events or signals, but not exit the state. + // + // However, there are target states, so it's either a node without a parent (or parent's + // parent, etc), or the state belongs to a different state machine. Either way, this + // makes the state machine invalid. + if (error == QStateMachine::NoError) + setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState()); + QList<QAbstractState *> lst = pendingErrorStates.toList(); lst.prepend(t->sourceState()); - lca = findLCA(lst); - Q_ASSERT(lca != 0); + domain = findLCCA(lst); + Q_ASSERT(domain != 0); } - { - QSet<QAbstractState*>::const_iterator it; - for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - QAbstractState *s = *it; - if (isDescendantOf(s, lca)) - statesToExit.insert(s); - } + Q_FOREACH (QAbstractState* s, configuration) { + if (isDescendant(s, domain)) + statesToExit.insert(s); } } - QList<QAbstractState*> statesToExit_sorted = statesToExit.toList(); - std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan); - return statesToExit_sorted; + return statesToExit; } void QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractState*> &statesToExit_sorted, @@ -457,7 +637,7 @@ void QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractState* for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { QAbstractState *s0 = *it; if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) { - if (isAtomic(s0) && isDescendantOf(s0, s)) + if (isAtomic(s0) && isDescendant(s0, s)) QHistoryStatePrivate::get(h)->configuration.append(s0); } else if (s0->parentState() == s) { QHistoryStatePrivate::get(h)->configuration.append(s0); @@ -500,30 +680,20 @@ void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<Q } } -QList<QAbstractState*> QStateMachinePrivate::computeStatesToEnter(const QList<QAbstractTransition *> &enabledTransitions, - QSet<QAbstractState *> &statesForDefaultEntry) +QList<QAbstractState*> QStateMachinePrivate::computeEntrySet(const QList<QAbstractTransition *> &enabledTransitions, + QSet<QAbstractState *> &statesForDefaultEntry) { QSet<QAbstractState*> statesToEnter; if (pendingErrorStates.isEmpty()) { - for (int i = 0; i < enabledTransitions.size(); ++i) { - QAbstractTransition *t = enabledTransitions.at(i); - QList<QAbstractState*> lst = t->targetStates(); - if (lst.isEmpty()) - continue; - QAbstractState *src = t->sourceState(); - if (src) - lst.prepend(src); - QState *lca = findLCA(lst); - for (int j = src ? 1 : 0; j < lst.size(); ++j) { - QAbstractState *s = lst.at(j); - addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry); + Q_FOREACH (QAbstractTransition *t, enabledTransitions) { + Q_FOREACH (QAbstractState *s, t->targetStates()) { + addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); } - if (isParallel(lca)) { - QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates(); - foreach (QAbstractState* child,lcac) { - if (!statesToEnter.contains(child)) - addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry); - } + + QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t).toList(); + QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates); + Q_FOREACH (QAbstractState *s, effectiveTargetStates) { + addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry); } } } @@ -542,6 +712,51 @@ QList<QAbstractState*> QStateMachinePrivate::computeStatesToEnter(const QList<QA return statesToEnter_sorted; } +/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : + +function getTransitionDomain(transition) + +Return the compound state such that 1) all states that are exited or entered as a result of taking +'transition' are descendants of it 2) no descendant of it has this property. + +function getTransitionDomain(t) + tstates = getEffectiveTargetStates(t) + if not tstates: + return null + elif t.type == "internal" and isCompoundState(t.source) and tstates.every(lambda s: isDescendant(s,t.source)): + return t.source + else: + return findLCCA([t.source].append(tstates)) +*/ +QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t, const QList<QAbstractState *> &effectiveTargetStates) const +{ + if (effectiveTargetStates.isEmpty()) + return 0; + +#if 0 + // Qt only has external transitions, so skip the special case for the internal transitions + if (QState *tSource = t->sourceState()) { + if (isCompound(tSource)) { + bool allDescendants = true; + Q_FOREACH (QAbstractState *s, effectiveTargetStates) { + if (!isDescendant(s, tSource)) { + allDescendants = false; + break; + } + } + + if (allDescendants) + return tSource; + } + } +#endif + + QList<QAbstractState *> states(effectiveTargetStates); + if (QAbstractState *src = t->sourceState()) + states.prepend(src); + return findLCCA(states); +} + void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted, const QList<QAbstractState*> &statesToEnter_sorted, const QSet<QAbstractState*> &statesForDefaultEntry, @@ -610,10 +825,9 @@ void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState QState *parent = s->parentState(); if (parent) { if (parent != rootState()) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": emitting finished signal for" << parent; -#endif - QStatePrivate::get(parent)->emitFinished(); + QFinalState *finalState = qobject_cast<QFinalState *>(s); + Q_ASSERT(finalState); + emitStateFinished(parent, finalState); } QState *grandparent = parent->parentState(); if (grandparent && isParallel(grandparent)) { @@ -627,10 +841,9 @@ void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState } } if (allChildStatesFinal && (grandparent != rootState())) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": emitting finished signal for" << grandparent; -#endif - QStatePrivate::get(grandparent)->emitFinished(); + QFinalState *finalState = qobject_cast<QFinalState *>(s); + Q_ASSERT(finalState); + emitStateFinished(grandparent, finalState); } } } @@ -719,30 +932,126 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root, } } -void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QState *root, +/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ has a bug. See + * QTBUG-44963 for details. The algorithm here is as described in + * http://www.w3.org/Voice/2013/scxml-irp/SCXML.htm as of Friday March 13, 2015. + +procedure addDescendantStatesToEnter(state,statesToEnter,statesForDefaultEntry, defaultHistoryContent): + if isHistoryState(state): + if historyValue[state.id]: + for s in historyValue[state.id]: + addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) + for s in historyValue[state.id]: + addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent) + else: + defaultHistoryContent[state.parent.id] = state.transition.content + for s in state.transition.target: + addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) + for s in state.transition.target: + addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent) + else: + statesToEnter.add(state) + if isCompoundState(state): + statesForDefaultEntry.add(state) + for s in state.initial.transition.target: + addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent) + for s in state.initial.transition.target: + addAncestorStatesToEnter(s, state, statesToEnter, statesForDefaultEntry, defaultHistoryContent) + else: + if isParallelState(state): + for child in getChildStates(state): + if not statesToEnter.some(lambda s: isDescendant(s,child)): + addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent) +*/ +void QStateMachinePrivate::addDescendantStatesToEnter(QAbstractState *state, + QSet<QAbstractState*> &statesToEnter, + QSet<QAbstractState*> &statesForDefaultEntry) +{ + if (QHistoryState *h = toHistoryState(state)) { + QList<QAbstractState*> historyConfiguration = QHistoryStatePrivate::get(h)->configuration; + if (!historyConfiguration.isEmpty()) { + Q_FOREACH (QAbstractState *s, historyConfiguration) + addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); + Q_FOREACH (QAbstractState *s, historyConfiguration) + addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry); + +#ifdef QSTATEMACHINE_DEBUG + qDebug() << q_func() << ": restoring" + << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow") + << "history from" << state << ':' << historyConfiguration; +#endif + } else { + QList<QAbstractState*> defaultHistoryContent; + if (QHistoryStatePrivate::get(h)->defaultState) + defaultHistoryContent.append(QHistoryStatePrivate::get(h)->defaultState); + + if (defaultHistoryContent.isEmpty()) { + setError(QStateMachine::NoDefaultStateInHistoryStateError, h); + } else { + Q_FOREACH (QAbstractState *s, defaultHistoryContent) + addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); + Q_FOREACH (QAbstractState *s, defaultHistoryContent) + addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry); +#ifdef QSTATEMACHINE_DEBUG + qDebug() << q_func() << ": initial history targets for" << state << ':' << defaultHistoryContent; +#endif + } + } + } else { + if (state == rootState()) { + // Error has already been set by exitStates(). + Q_ASSERT(error != QStateMachine::NoError); + return; + } + statesToEnter.insert(state); + if (isCompound(state)) { + statesForDefaultEntry.insert(state); + if (QAbstractState *initial = toStandardState(state)->initialState()) { + Q_ASSERT(initial->machine() == q_func()); + + // Qt does not support initial transitions (which is a problem for parallel states). + // The way it simulates this for other states, is by having a single initial state. + statesForDefaultEntry.insert(initial); + + addDescendantStatesToEnter(initial, statesToEnter, statesForDefaultEntry); + addAncestorStatesToEnter(initial, state, statesToEnter, statesForDefaultEntry); + } else { + setError(QStateMachine::NoInitialStateError, state); + return; + } + } else if (isParallel(state)) { + QState *grp = toStandardState(state); + Q_FOREACH (QAbstractState *child, QStatePrivate::get(grp)->childStates()) { + if (!containsDecendantOf(statesToEnter, child)) + addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry); + } + } + } +} + + +/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ : + +procedure addAncestorStatesToEnter(state, ancestor, statesToEnter, statesForDefaultEntry, defaultHistoryContent) + for anc in getProperAncestors(state,ancestor): + statesToEnter.add(anc) + if isParallelState(anc): + for child in getChildStates(anc): + if not statesToEnter.some(lambda s: isDescendant(s,child)): + addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent) +*/ +void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor, QSet<QAbstractState*> &statesToEnter, QSet<QAbstractState*> &statesForDefaultEntry) { - QList<QState*> ancs = properAncestors(s, root); - for (int i = 0; i < ancs.size(); ++i) { - QState *anc = ancs.at(i); + Q_FOREACH (QState *anc, getProperAncestors(s, ancestor)) { if (!anc->parentState()) continue; statesToEnter.insert(anc); if (isParallel(anc)) { - QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates(); - for (int j = 0; j < lst.size(); ++j) { - QAbstractState *child = lst.at(j); - bool hasDescendantInList = false; - QSet<QAbstractState*>::const_iterator it; - for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) { - if (isDescendantOf(*it, child)) { - hasDescendantInList = true; - break; - } - } - if (!hasDescendantInList) - addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry); + Q_FOREACH (QAbstractState *child, QStatePrivate::get(anc)->childStates()) { + if (!containsDecendantOf(statesToEnter, child)) + addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry); } } } @@ -780,27 +1089,6 @@ bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const || (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState())); } - -bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other) -{ - Q_ASSERT(state != 0); - for (QAbstractState *s = state->parentState(); s != 0; s = s->parentState()) { - if (s == other) - return true; - } - return false; -} - -QList<QState*> QStateMachinePrivate::properAncestors(const QAbstractState *state, const QState *upperBound) -{ - Q_ASSERT(state != 0); - QList<QState*> result; - for (QState *s = state->parentState(); s && s != upperBound; s = s->parentState()) { - result.append(s); - } - return result; -} - QState *QStateMachinePrivate::toStandardState(QAbstractState *state) { if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState)) @@ -1082,6 +1370,9 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta Q_ASSERT(currentErrorState != rootState()); if (currentErrorState != 0) { +#ifdef QSTATEMACHINE_DEBUG + qDebug() << q << ": entering error state" << currentErrorState << "from" << currentContext; +#endif QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext); addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); } else { @@ -1385,8 +1676,7 @@ void QStateMachinePrivate::_q_start() executeTransitionContent(&nullEvent, transitions); QList<QAbstractState*> exitedStates = QList<QAbstractState*>(); QSet<QAbstractState*> statesForDefaultEntry; - QList<QAbstractState*> enteredStates = computeStatesToEnter(transitions, - statesForDefaultEntry); + QList<QAbstractState*> enteredStates = computeEntrySet(transitions, statesForDefaultEntry); QHash<RestorableId, QVariant> pendingRestorables; QHash<QAbstractState*, QList<QPropertyAssignment> > assignmentsForEnteredStates = computePropertyAssignments(enteredStates, pendingRestorables); @@ -1440,7 +1730,7 @@ void QStateMachinePrivate::_q_process() processing = false; break; } - QSet<QAbstractTransition*> enabledTransitions; + QList<QAbstractTransition*> enabledTransitions; QEvent *e = new QEvent(QEvent::None); enabledTransitions = selectTransitions(e); if (enabledTransitions.isEmpty()) { @@ -1477,7 +1767,7 @@ void QStateMachinePrivate::_q_process() if (!enabledTransitions.isEmpty()) { didChange = true; q->beginMicrostep(e); - microstep(e, enabledTransitions.toList()); + microstep(e, enabledTransitions); q->endMicrostep(e); } else { @@ -1666,6 +1956,18 @@ void QStateMachinePrivate::endMacrostep(bool didChange) } +void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guiltyState) +{ + Q_UNUSED(guiltyState); + Q_ASSERT(guiltyState); + +#ifdef QSTATEMACHINE_DEBUG + qDebug() << q << ": emitting finished signal for" << forState; +#endif + + QStatePrivate::get(forState)->emitFinished(); +} + namespace _QStateMachine_Internal{ class GoToStateTransition : public QAbstractTransition diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h index 7837e6ec5f..d6c3b7bfa7 100644 --- a/src/corelib/statemachine/qstatemachine.h +++ b/src/corelib/statemachine/qstatemachine.h @@ -145,16 +145,8 @@ public Q_SLOTS: void setRunning(bool running); Q_SIGNALS: - void started( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void stopped( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void started(QPrivateSignal); + void stopped(QPrivateSignal); void runningChanged(bool running); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index b7f2644255..a66232ee88 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -100,8 +100,10 @@ public: static QStateMachinePrivate *get(QStateMachine *q); - QState *findLCA(const QList<QAbstractState*> &states) const; + QState *findLCA(const QList<QAbstractState*> &states, bool onlyCompound = false) const; + QState *findLCCA(const QList<QAbstractState*> &states) const; + static bool transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2); static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2); static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2); @@ -122,16 +124,17 @@ public: void clearHistory(); QAbstractTransition *createInitialTransition() const; + void removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions); void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList); virtual void noMicrostep(); virtual void processedPendingEvents(bool didChange); virtual void beginMacrostep(); virtual void endMacrostep(bool didChange); - bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const; - QSet<QAbstractTransition*> selectTransitions(QEvent *event) const; + QList<QAbstractTransition *> selectTransitions(QEvent *event); void exitStates(QEvent *event, const QList<QAbstractState *> &statesToExit_sorted, const QHash<QAbstractState*, QList<QPropertyAssignment> > &assignmentsForEnteredStates); - QList<QAbstractState*> computeStatesToExit(const QList<QAbstractTransition*> &enabledTransitions); + QList<QAbstractState*> computeExitSet(const QList<QAbstractTransition*> &enabledTransitions); + QSet<QAbstractState*> computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions); void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList); void enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted, const QList<QAbstractState*> &statesToEnter_sorted, @@ -141,12 +144,17 @@ public: , const QList<QAbstractAnimation*> &selectedAnimations #endif ); - QList<QAbstractState*> computeStatesToEnter(const QList<QAbstractTransition*> &enabledTransitions, - QSet<QAbstractState*> &statesForDefaultEntry); + QList<QAbstractState*> computeEntrySet(const QList<QAbstractTransition*> &enabledTransitions, + QSet<QAbstractState*> &statesForDefaultEntry); + QAbstractState *getTransitionDomain(QAbstractTransition *t, + const QList<QAbstractState *> &effectiveTargetStates) const; + void addDescendantStatesToEnter(QAbstractState *state, + QSet<QAbstractState*> &statesToEnter, + QSet<QAbstractState*> &statesForDefaultEntry); void addStatesToEnter(QAbstractState *s, QState *root, QSet<QAbstractState*> &statesToEnter, QSet<QAbstractState*> &statesForDefaultEntry); - void addAncestorStatesToEnter(QAbstractState *s, QState *root, + void addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor, QSet<QAbstractState*> &statesToEnter, QSet<QAbstractState*> &statesForDefaultEntry); @@ -160,8 +168,6 @@ public: static bool isParallel(const QAbstractState *s); bool isCompound(const QAbstractState *s) const; bool isAtomic(const QAbstractState *s) const; - static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other); - static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound); void goToState(QAbstractState *targetState); @@ -192,6 +198,8 @@ public: void processEvents(EventProcessingMode processingMode); void cancelAllDelayedEvents(); + virtual void emitStateFinished(QState *forState, QFinalState *guiltyState); + #ifndef QT_NO_PROPERTIES class RestorableId { QPointer<QObject> guard; diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp index 0ea8c4c00f..e6477bf5e0 100644 --- a/src/corelib/thread/qreadwritelock.cpp +++ b/src/corelib/thread/qreadwritelock.cpp @@ -136,27 +136,11 @@ void QReadWriteLock::lockForRead() { QMutexLocker lock(&d->mutex); - Qt::HANDLE self = 0; - if (d->recursive) { - self = QThread::currentThreadId(); - - QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); - if (it != d->currentReaders.end()) { - ++it.value(); - ++d->accessCount; - Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()", - "Overflow in lock counter"); - return; - } - } - while (d->accessCount < 0 || d->waitingWriters) { ++d->waitingReaders; d->readerWait.wait(&d->mutex); --d->waitingReaders; } - if (d->recursive) - d->currentReaders.insert(self, 1); ++d->accessCount; Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()", "Overflow in lock counter"); @@ -182,24 +166,8 @@ bool QReadWriteLock::tryLockForRead() { QMutexLocker lock(&d->mutex); - Qt::HANDLE self = 0; - if (d->recursive) { - self = QThread::currentThreadId(); - - QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); - if (it != d->currentReaders.end()) { - ++it.value(); - ++d->accessCount; - Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", - "Overflow in lock counter"); - return true; - } - } - if (d->accessCount < 0) return false; - if (d->recursive) - d->currentReaders.insert(self, 1); ++d->accessCount; Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter"); @@ -230,20 +198,6 @@ bool QReadWriteLock::tryLockForRead(int timeout) { QMutexLocker lock(&d->mutex); - Qt::HANDLE self = 0; - if (d->recursive) { - self = QThread::currentThreadId(); - - QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); - if (it != d->currentReaders.end()) { - ++it.value(); - ++d->accessCount; - Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", - "Overflow in lock counter"); - return true; - } - } - while (d->accessCount < 0 || d->waitingWriters) { ++d->waitingReaders; bool success = d->readerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout)); @@ -251,8 +205,6 @@ bool QReadWriteLock::tryLockForRead(int timeout) if (!success) return false; } - if (d->recursive) - d->currentReaders.insert(self, 1); ++d->accessCount; Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter"); @@ -412,15 +364,6 @@ void QReadWriteLock::unlock() bool unlocked = false; if (d->accessCount > 0) { // releasing a read lock - if (d->recursive) { - Qt::HANDLE self = QThread::currentThreadId(); - QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self); - if (it != d->currentReaders.end()) { - if (--it.value() <= 0) - d->currentReaders.erase(it); - } - } - unlocked = --d->accessCount == 0; } else if (d->accessCount < 0 && ++d->accessCount == 0) { // released a write lock diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h index e57c0e403f..15a6d1f57e 100644 --- a/src/corelib/thread/qreadwritelock_p.h +++ b/src/corelib/thread/qreadwritelock_p.h @@ -69,7 +69,6 @@ struct QReadWriteLockPrivate bool recursive; Qt::HANDLE currentWriter; - QHash<Qt::HANDLE, int> currentReaders; }; QT_END_NAMESPACE diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 58755b9625..bfc469583d 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -106,16 +106,8 @@ public: static void usleep(unsigned long); Q_SIGNALS: - void started( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); - void finished( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void started(QPrivateSignal); + void finished(QPrivateSignal); protected: virtual void run(); diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 996ed1779d..77093c9cf1 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -400,7 +400,7 @@ int QThread::idealThreadCount() Q_DECL_NOTHROW cores = (int)psd.psd_proc_cnt; } #elif defined(Q_OS_BSD4) - // FreeBSD, OpenBSD, NetBSD, BSD/OS, Mac OS X + // FreeBSD, OpenBSD, NetBSD, BSD/OS, OS X, iOS size_t len = sizeof(cores); int mib[2]; mib[0] = CTL_HW; diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h index 9cd241a87b..f8539ca07a 100644 --- a/src/corelib/tools/qbytearraylist.h +++ b/src/corelib/tools/qbytearraylist.h @@ -55,6 +55,10 @@ class QByteArrayList : public QList<QByteArray> template <> struct QListSpecialMethods<QByteArray> #endif { +#ifndef Q_QDOC +protected: + ~QListSpecialMethods() {} +#endif public: inline QByteArray join() const { return QtPrivate::QByteArrayList_join(self(), 0, 0); } diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp index 82f890478d..41e8b4854d 100644 --- a/src/corelib/tools/qelapsedtimer.cpp +++ b/src/corelib/tools/qelapsedtimer.cpp @@ -131,7 +131,7 @@ QT_BEGIN_NAMESPACE \value SystemTime The human-readable system time. This clock is not monotonic. \value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow. \value TickCounter The system's tick counter, used on Windows systems. This clock may overflow. - \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow. + \value MachAbsoluteTime The Mach kernel's absolute time (OS X and iOS). This clock is monotonic and does not overflow. \value PerformanceCounter The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow. \section2 SystemTime @@ -173,8 +173,8 @@ QT_BEGIN_NAMESPACE \section2 MachAbsoluteTime This clock type is based on the absolute time presented by Mach kernels, - such as that found on Mac OS X. This clock type is presented separately - from MonotonicClock since Mac OS X is also a Unix system and may support + such as that found on OS X. This clock type is presented separately + from MonotonicClock since OS X and iOS are also Unix systems and may support a POSIX monotonic clock with values differing from the Mach absolute time. diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 85e4570f45..1e002633df 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -63,8 +63,13 @@ QT_BEGIN_NAMESPACE template <typename T> class QVector; template <typename T> class QSet; -template <typename T> struct QListSpecialMethods { }; +template <typename T> struct QListSpecialMethods +{ +protected: + ~QListSpecialMethods() {} +}; template <> struct QListSpecialMethods<QByteArray>; +template <> struct QListSpecialMethods<QString>; struct Q_CORE_EXPORT QListData { // tags for tag-dispatching of QList implementations, diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h index 66110b88f6..2db2ad869c 100644 --- a/src/corelib/tools/qscopedvaluerollback.h +++ b/src/corelib/tools/qscopedvaluerollback.h @@ -43,21 +43,19 @@ class QScopedValueRollback { public: explicit QScopedValueRollback(T &var) : - varRef(var) + varRef(var), oldValue(var) { - oldValue = varRef; } explicit QScopedValueRollback(T &var, T value) : - varRef(var) + varRef(var), oldValue(var) { - oldValue = varRef; - varRef = value; + varRef = qMove(value); } ~QScopedValueRollback() { - varRef = oldValue; + varRef = qMove(oldValue); } void commit() diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 63139c97fd..373d25c6ad 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5348,7 +5348,7 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2, platform-dependent manner. Use this function to present sorted lists of strings to the user. - On Mac OS X since Qt 4.3, this function compares according the + On OS X and iOS this function compares according the "Order for sorted lists" setting in the International preferences panel. \sa compare(), QLocale @@ -7816,7 +7816,7 @@ QString QString::multiArg(int numArgs, const QString **args) const Constructs a new QString containing a copy of the \a string CFString. - \note this function is only available on Mac OS X and iOS. + \note this function is only available on OS X and iOS. */ /*! \fn CFStringRef QString::toCFString() const @@ -7825,7 +7825,7 @@ QString QString::multiArg(int numArgs, const QString **args) const Creates a CFString from a QString. The caller owns the CFString and is responsible for releasing it. - \note this function is only available on Mac OS X and iOS. + \note this function is only available on OS X and iOS. */ /*! \fn QString QString::fromNSString(const NSString *string) @@ -7833,7 +7833,7 @@ QString QString::multiArg(int numArgs, const QString **args) const Constructs a new QString containing a copy of the \a string NSString. - \note this function is only available on Mac OS X and iOS. + \note this function is only available on OS X and iOS. */ /*! \fn NSString QString::toNSString() const @@ -7841,7 +7841,7 @@ QString QString::multiArg(int numArgs, const QString **args) const Creates a NSString from a QString. The NSString is autoreleased. - \note this function is only available on Mac OS X and iOS. + \note this function is only available on OS X and iOS. */ /*! \fn bool QString::isSimpleText() const @@ -9052,7 +9052,7 @@ QStringRef QStringRef::appendTo(QString *string) const platform-dependent manner. Use this function to present sorted lists of strings to the user. - On Mac OS X, this function compares according the + On OS X and iOS, this function compares according the "Order for sorted lists" setting in the International prefereces panel. \sa compare(), QLocale diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h index 89785208c8..8288e430fa 100644 --- a/src/corelib/tools/qstringlist.h +++ b/src/corelib/tools/qstringlist.h @@ -57,6 +57,10 @@ class QStringList : public QList<QString> template <> struct QListSpecialMethods<QString> #endif { +#ifndef Q_QDOC +protected: + ~QListSpecialMethods() {} +#endif public: inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive); inline int removeDuplicates(); diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h index 388e88d641..21139b37a8 100644 --- a/src/corelib/tools/qtimeline.h +++ b/src/corelib/tools/qtimeline.h @@ -115,26 +115,10 @@ public Q_SLOTS: void toggleDirection(); Q_SIGNALS: - void valueChanged(qreal x -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void frameChanged(int -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void stateChanged(QTimeLine::State newState -#if !defined(Q_QDOC) - , QPrivateSignal -#endif - ); - void finished( -#if !defined(Q_QDOC) - QPrivateSignal -#endif - ); + void valueChanged(qreal x, QPrivateSignal); + void frameChanged(int, QPrivateSignal); + void stateChanged(QTimeLine::State newState, QPrivateSignal); + void finished(QPrivateSignal); protected: void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index c2ee99a2d8..3627045a40 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -183,7 +183,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz); given moment then you should use a Qt::TimeSpec of Qt::LocalTime. The method systemTimeZoneId() returns the current system IANA time zone - ID which on OSX and Linux will always be correct. On Windows this ID is + ID which on Unix-like systems will always be correct. On Windows this ID is translated from the Windows system ID using an internal translation table and the user's selected country. As a consequence there is a small chance any Windows install may have IDs not known by Qt, in which case |