From 19a91b4a3531d331362fcefd87c43366ae142f57 Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Wed, 18 Feb 2015 14:49:44 +0300 Subject: Doc: Fix using Apple-related terminology in Qt Core MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the name "OS X" instead of "Mac OS X", "Mac OS" and "OSX", and mention iOS. Replace "Carbon Preferences API" by "CFPreferences API" in the QSettings documentation. Change-Id: Ia7f9fb874276c7c445a1649df521b96ff43daa0c Reviewed-by: Oswald Buddenhagen Reviewed-by: Venugopal Shivashankar Reviewed-by: Topi Reiniƶ --- src/corelib/doc/src/resource-system.qdoc | 2 +- src/corelib/global/qcompilerdetection.h | 4 +-- src/corelib/global/qnamespace.qdoc | 50 +++++++++++++++---------------- src/corelib/io/qabstractfileengine.cpp | 2 +- src/corelib/io/qdir.cpp | 4 +-- src/corelib/io/qfile.cpp | 4 +-- src/corelib/io/qfileinfo.cpp | 8 ++--- src/corelib/io/qfilesystemengine.cpp | 2 +- src/corelib/io/qfilesystemengine_unix.cpp | 2 +- src/corelib/io/qfilesystemwatcher.cpp | 2 +- src/corelib/io/qfsfileengine.cpp | 4 +-- src/corelib/io/qiodevice.cpp | 2 +- src/corelib/io/qlockfile_unix.cpp | 2 +- src/corelib/io/qloggingcategory.cpp | 2 +- src/corelib/io/qsettings.cpp | 42 +++++++++++++------------- src/corelib/kernel/qcoreapplication.cpp | 4 +-- src/corelib/kernel/qcoreevent.cpp | 4 +-- src/corelib/kernel/qobject.cpp | 2 +- src/corelib/mimetypes/qmimedatabase.cpp | 2 +- src/corelib/plugin/qlibrary.cpp | 8 ++--- src/corelib/plugin/qpluginloader.cpp | 2 +- src/corelib/thread/qthread_unix.cpp | 2 +- src/corelib/tools/qelapsedtimer.cpp | 6 ++-- src/corelib/tools/qstring.cpp | 12 ++++---- src/corelib/tools/qtimezone.cpp | 2 +- 25 files changed, 88 insertions(+), 88 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc index 91ce8afcf8..b7f84f5b5e 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 d144c4faad..3b9b7934bc 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -902,7 +902,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 // or std::move. Let's disable these features # undef Q_COMPILER_INITIALIZER_LISTS # undef Q_COMPILER_RVALUE_REFS @@ -918,7 +918,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.qdoc b/src/corelib/global/qnamespace.qdoc index f7992b436c..3f9526c788 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 @@ -294,7 +294,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 +312,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 +913,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 +1090,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 +1280,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 +1919,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 @@ -2012,7 +2012,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 @@ -2101,10 +2101,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 @@ -2128,7 +2128,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. @@ -2912,7 +2912,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 9468464cac..363657ed18 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 a5e189a825..4fc2be2ecb 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -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 d3411abf10..cbe6baf5cc 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 98c36f4a82..130d35e984 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 b06017e57f..d9f3367ef0 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 bfa4483ca7..0cec40a3ce 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -412,7 +412,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/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 4bca8d90a0..d2be96291c 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/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index a126690240..b0dd3d76cf 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 35911934df..a3e89a7b89 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -669,7 +669,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() */ diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 3ed973494b..bf1015a7be 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 79d20601a6..eb43e397bc 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/qsettings.cpp b/src/corelib/io/qsettings.cpp index ebca7d57ff..a230427ee8 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1916,7 +1916,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. @@ -1961,8 +1961,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.) @@ -2020,7 +2020,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 @@ -2223,7 +2223,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}) @@ -2251,7 +2251,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. @@ -2268,7 +2268,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 @@ -2322,13 +2322,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 @@ -2345,7 +2345,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 @@ -2385,7 +2385,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. @@ -2548,7 +2548,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. @@ -2601,7 +2601,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. @@ -3117,7 +3117,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. @@ -3156,7 +3156,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. @@ -3191,7 +3191,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. @@ -3253,7 +3253,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. @@ -3356,18 +3356,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/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index aea82fd48b..dcd6cad33d 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -663,7 +663,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. @@ -1975,7 +1975,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/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index c0094fb7f2..990b1089c7 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). @@ -210,7 +210,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/qobject.cpp b/src/corelib/kernel/qobject.cpp index f2ceb7081c..b3abcd8b35 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -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/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp index c5103ebe59..b2c3834743 100644 --- a/src/corelib/mimetypes/qmimedatabase.cpp +++ b/src/corelib/mimetypes/qmimedatabase.cpp @@ -237,7 +237,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 832ee250c7..bdb61339ad 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -594,7 +594,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. @@ -831,7 +831,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) @@ -848,7 +848,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) @@ -864,7 +864,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 f850394984..dc2a6d57b0 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/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index e4338e10b4..d17403df7a 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -406,7 +406,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/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp index 52875bc9fe..fb6c9bd3a0 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/qstring.cpp b/src/corelib/tools/qstring.cpp index 9921d5cfbb..189caf8bd7 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -5288,7 +5288,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 @@ -7713,7 +7713,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 @@ -7722,7 +7722,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) @@ -7730,7 +7730,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 @@ -7738,7 +7738,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 @@ -8915,7 +8915,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/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp index 8f3db74131..5685e92447 100644 --- a/src/corelib/tools/qtimezone.cpp +++ b/src/corelib/tools/qtimezone.cpp @@ -179,7 +179,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 -- cgit v1.2.3 From 20c651d8b8c18ed123b84162fe4531eb4f414509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Sun, 29 Mar 2015 16:02:53 +0100 Subject: Fix QNX and Blackberry -qtnamespace build Task-number: QTBUG-43569 Change-Id: I81a560d1508de4d808a807f1febdc17619cf4dda Reviewed-by: Rafael Roquetto --- src/corelib/kernel/qeventdispatcher_blackberry.cpp | 2 ++ src/corelib/kernel/qppsattribute.cpp | 4 ++++ src/corelib/kernel/qppsattribute_p.h | 5 +++-- src/corelib/kernel/qppsobject.cpp | 4 ++++ 4 files changed, 13 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp index 047e3dff07..7a70f5cb58 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/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp index 09d8d1bb0c..b77ea0b643 100644 --- a/src/corelib/kernel/qppsattribute.cpp +++ b/src/corelib/kernel/qppsattribute.cpp @@ -37,6 +37,8 @@ #include #include +QT_BEGIN_NAMESPACE + /////////////////////////// // // QPpsAttributePrivate @@ -297,3 +299,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 209a8c3101..73beb7c96f 100644 --- a/src/corelib/kernel/qppsattribute_p.h +++ b/src/corelib/kernel/qppsattribute_p.h @@ -57,8 +57,6 @@ class QPpsAttribute; typedef QList QPpsAttributeList; typedef QMap 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 9a5ae3c7a4..612e756881 100644 --- a/src/corelib/kernel/qppsobject.cpp +++ b/src/corelib/kernel/qppsobject.cpp @@ -50,6 +50,8 @@ #include +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 -- cgit v1.2.3 From 7c149dd86944b3669420832b2b14fac00327d4b7 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 28 Mar 2015 15:03:18 +0200 Subject: Prevent memory overgrowth while reading from a sequential device After flushing the internal buffer, QIODevice::readAll() attempts to read the device incrementally. On each iteration, the result buffer size is increased by a constant value independently from the number of read bytes. This lead to unreasonable growth of the buffer if these additional conditions were met: - readData() requests new data from the device on every call; - highly loaded device provides at least one byte on each request. Instead of constant resizing, keep the size of free block to avoid a possible memory exhaustion. Task-number: QTBUG-44286 Change-Id: I637e2d0e05bd900a1bb9517af2fe7d8038c75a35 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qiodevice.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index 7a87a78c60..43ad8d9316 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -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); -- cgit v1.2.3 From bc00e6da8477a5fc0e547733effef9db944f3eab Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 9 Apr 2015 00:22:06 +0000 Subject: QIconvCodec: fix compilation when NO_BOM is defined. qiconvcodec.cpp:305:34: error: unused parameter 'cd' [-Werror,-Wunused-parameter] Change-Id: I27eaacb532114dd188c4ffff13d330b64b4feaa6 Reviewed-by: Lars Knoll --- src/corelib/codecs/qiconvcodec.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/corelib') 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; -- cgit v1.2.3 From 24b3d82efff7709073bb74e1420d16a8b7312997 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 30 Mar 2015 11:30:47 +0200 Subject: QStateMachine: move QState::finished() emision into method. By moving the code for QState::finished() emission into a virtual method which also receives the QFinalState that caused the emission, subclasses can hook in and do some extra processing. Change-Id: Id19947c09e196a0df4edb87d71b74b0600c78867 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 26 ++++++++++++++++++-------- src/corelib/statemachine/qstatemachine_p.h | 2 ++ 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 760ac59bf4..375fe6c8e8 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -610,10 +610,9 @@ void QStateMachinePrivate::enterStates(QEvent *event, const QListparentState(); if (parent) { if (parent != rootState()) { -#ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": emitting finished signal for" << parent; -#endif - QStatePrivate::get(parent)->emitFinished(); + QFinalState *finalState = qobject_cast(s); + Q_ASSERT(finalState); + emitStateFinished(parent, finalState); } QState *grandparent = parent->parentState(); if (grandparent && isParallel(grandparent)) { @@ -627,10 +626,9 @@ void QStateMachinePrivate::enterStates(QEvent *event, const QListemitFinished(); + QFinalState *finalState = qobject_cast(s); + Q_ASSERT(finalState); + emitStateFinished(grandparent, finalState); } } } @@ -1619,6 +1617,18 @@ void QStateMachinePrivate::cancelAllDelayedEvents() delayedEvents.clear(); } +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_p.h b/src/corelib/statemachine/qstatemachine_p.h index 3a93c47c5b..1c885d1a36 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -188,6 +188,8 @@ public: void processEvents(EventProcessingMode processingMode); void cancelAllDelayedEvents(); + virtual void emitStateFinished(QState *forState, QFinalState *guiltyState); + #ifndef QT_NO_PROPERTIES class RestorableId { QPointer guard; -- cgit v1.2.3 From ab8d20532039674ac749186c1773bc0d33cf19cf Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Mon, 16 Mar 2015 11:20:55 +0100 Subject: QStateMachine: move methods out of Private class. Also rename them to match the names in the scxml standard, and add the relevant description from the standard to the methods. Change-Id: I495832358f5836ed6ea04bf43061d42e29f4f743 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 88 ++++++++++++++++++------------ src/corelib/statemachine/qstatemachine_p.h | 2 - 2 files changed, 54 insertions(+), 36 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 375fe6c8e8..2fff03d8c1 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -177,6 +177,47 @@ 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; +} + +/* 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 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 getProperAncestors(const QAbstractState *state, const QAbstractState *upperBound) +{ + Q_ASSERT(state != 0); + QVector result; + result.reserve(16); + for (QState *it = state->parentState(); it && it != upperBound; it = it->parentState()) { + result.append(it); + } + return result; +} + template static uint qHash(const QPointer &p) { return qHash(p.data()); } @@ -246,7 +287,7 @@ static int indexOfDescendant(QState *s, QAbstractState *desc) QList 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; } } @@ -258,9 +299,9 @@ bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState 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 +317,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); @@ -293,13 +334,13 @@ QState *QStateMachinePrivate::findLCA(const QList &states) cons { if (states.isEmpty()) return 0; - QList ancestors = properAncestors(states.at(0), rootState()->parentState()); + QVector ancestors = getProperAncestors(states.at(0), rootState()->parentState()); for (int i = 0; i < ancestors.size(); ++i) { QState *anc = ancestors.at(i); 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) @@ -317,7 +358,7 @@ bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSetsourceState()); QAbstractState *lca = findLCA(lst); - if (isDescendantOf(s, lca)) { + if (isDescendant(s, lca)) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ':' << transitions << "preempts selection of a transition from" << s << "because" << s << "is a descendant of" << lca; @@ -341,7 +382,7 @@ QSet QStateMachinePrivate::selectTransitions(QEvent *event continue; if (isPreempted(state, enabledTransitions)) continue; - QList lst = properAncestors(state, rootState()->parentState()); + QVector lst = getProperAncestors(state, rootState()->parentState()); if (QState *grp = toStandardState(state)) lst.prepend(grp); bool found = false; @@ -433,7 +474,7 @@ QList QStateMachinePrivate::computeStatesToExit(const QList::const_iterator it; for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { QAbstractState *s = *it; - if (isDescendantOf(s, lca)) + if (isDescendant(s, lca)) statesToExit.insert(s); } } @@ -457,7 +498,7 @@ void QStateMachinePrivate::exitStates(QEvent *event, const QListhistoryType == 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); @@ -721,7 +762,7 @@ void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QState *r QSet &statesToEnter, QSet &statesForDefaultEntry) { - QList ancs = properAncestors(s, root); + QVector ancs = getProperAncestors(s, root); for (int i = 0; i < ancs.size(); ++i) { QState *anc = ancs.at(i); if (!anc->parentState()) @@ -734,7 +775,7 @@ void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QState *r bool hasDescendantInList = false; QSet::const_iterator it; for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) { - if (isDescendantOf(*it, child)) { + if (isDescendant(*it, child)) { hasDescendantInList = true; break; } @@ -778,27 +819,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 QStateMachinePrivate::properAncestors(const QAbstractState *state, const QState *upperBound) -{ - Q_ASSERT(state != 0); - QList 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)) diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index 1c885d1a36..d0cc56bc2a 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -156,8 +156,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 properAncestors(const QAbstractState *s, const QState *upperBound); void goToState(QAbstractState *targetState); -- cgit v1.2.3 From e616bd2641b9cf6a18cabeae3f9c425f91bfc4b3 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Tue, 17 Mar 2015 13:23:51 +0100 Subject: QStateMachine: fix history state restoration. When a history state is entered that has an actual saved history (so not the initial state), the entry set was calculated wrongly in some cases. See the bug report for the specific case. The fix is to fully implement the standard, so method names in the private class are updated to reflect the names as used in the standard. Note that, as mentioned in the bug report, the algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ has a bug. What is implemented is the fixed algorithm as described in the current working draft as of Friday March 13, 2015. This draft can be found at: http://www.w3.org/Voice/2013/scxml-irp/SCXML.htm [ChangeLog][QtCore] Fixed an issue where a history state restore would activate too many states, possibly putting the state machine in an invalid state. Change-Id: Ibb5491b2fdcf3a167c223fa8c9c4aad302dbb795 Task-number: QTBUG-44963 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/statemachine/qstatemachine.cpp | 266 ++++++++++++++++++++++++----- src/corelib/statemachine/qstatemachine_p.h | 14 +- 2 files changed, 235 insertions(+), 45 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 2fff03d8c1..477fa83705 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -196,6 +196,15 @@ static inline bool isDescendant(const QAbstractState *state1, const QAbstractSta return false; } +static bool containsDecendantOf(const QSet &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) @@ -218,6 +227,41 @@ static QVector getProperAncestors(const QAbstractState *state, const QA 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 getEffectiveTargetStates(QAbstractTransition *transition) +{ + QSet targets; + foreach (QAbstractState *s, transition->targetStates()) { + if (QHistoryState *historyState = QStateMachinePrivate::toHistoryState(s)) { + QList historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration; + if (!historyConfiguration.isEmpty()) + targets.unite(historyConfiguration.toSet()); + else if (QAbstractState *defaultState = historyState->defaultState()) + targets.insert(defaultState); // Qt does not support initial transitions, but uses the default state of the history state for this. + } else { + targets.insert(s); + } + } + return targets; +} + template static uint qHash(const QPointer &p) { return qHash(p.data()); } @@ -330,13 +374,16 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState } } -QState *QStateMachinePrivate::findLCA(const QList &states) const +QState *QStateMachinePrivate::findLCA(const QList &states, bool onlyCompound) const { if (states.isEmpty()) return 0; QVector 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); @@ -349,6 +396,11 @@ QState *QStateMachinePrivate::findLCA(const QList &states) cons return 0; } +QState *QStateMachinePrivate::findLCCA(const QList &states) const +{ + return findLCA(states, true); +} + bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet &transitions) const { QSet::const_iterator it; @@ -416,7 +468,7 @@ void QStateMachinePrivate::microstep(QEvent *event, const QList pendingRestorables = computePendingRestorables(exitedStates); QSet statesForDefaultEntry; - QList enteredStates = computeStatesToEnter(enabledTransitions, statesForDefaultEntry); + QList enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry); QHash > assignmentsForEnteredStates = computePropertyAssignments(enteredStates, pendingRestorables); @@ -541,30 +593,22 @@ void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList QStateMachinePrivate::computeStatesToEnter(const QList &enabledTransitions, - QSet &statesForDefaultEntry) +QList QStateMachinePrivate::computeEntrySet(const QList &enabledTransitions, + QSet &statesForDefaultEntry) { QSet statesToEnter; if (pendingErrorStates.isEmpty()) { - for (int i = 0; i < enabledTransitions.size(); ++i) { - QAbstractTransition *t = enabledTransitions.at(i); - QList 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 lcac = QStatePrivate::get(lca)->childStates(); - foreach (QAbstractState* child,lcac) { - if (!statesToEnter.contains(child)) - addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry); - } +#ifdef QSTATEMACHINE_DEBUG + qDebug() << "computed entry set after descendants:" << statesToEnter; +#endif + QList effectiveTargetStates = getEffectiveTargetStates(t).toList(); + QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates); + Q_FOREACH (QAbstractState *s, effectiveTargetStates) { + addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry); } } } @@ -583,6 +627,51 @@ QList QStateMachinePrivate::computeStatesToEnter(const QList &effectiveTargetStates) +{ + 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 states(effectiveTargetStates); + if (QAbstractState *src = t->sourceState()) + states.prepend(src); + return findLCCA(states); +} + void QStateMachinePrivate::enterStates(QEvent *event, const QList &exitedStates_sorted, const QList &statesToEnter_sorted, const QSet &statesForDefaultEntry, @@ -758,30 +847,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 &statesToEnter, + QSet &statesForDefaultEntry) +{ + if (QHistoryState *h = toHistoryState(state)) { + QList 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 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 &statesToEnter, QSet &statesForDefaultEntry) { - QVector ancs = getProperAncestors(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 lst = QStatePrivate::get(anc)->childStates(); - for (int j = 0; j < lst.size(); ++j) { - QAbstractState *child = lst.at(j); - bool hasDescendantInList = false; - QSet::const_iterator it; - for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) { - if (isDescendant(*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); } } } @@ -1403,8 +1588,7 @@ void QStateMachinePrivate::_q_start() executeTransitionContent(&nullEvent, transitions); QList exitedStates = QList(); QSet statesForDefaultEntry; - QList enteredStates = computeStatesToEnter(transitions, - statesForDefaultEntry); + QList enteredStates = computeEntrySet(transitions, statesForDefaultEntry); QHash pendingRestorables; QHash > assignmentsForEnteredStates = computePropertyAssignments(enteredStates, pendingRestorables); diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index d0cc56bc2a..a8f0745730 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -100,7 +100,8 @@ public: static QStateMachinePrivate *get(QStateMachine *q); - QState *findLCA(const QList &states) const; + QState *findLCA(const QList &states, bool onlyCompound = false) const; + QState *findLCCA(const QList &states) const; static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2); static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2); @@ -137,12 +138,17 @@ public: , const QList &selectedAnimations #endif ); - QList computeStatesToEnter(const QList &enabledTransitions, - QSet &statesForDefaultEntry); + QList computeEntrySet(const QList &enabledTransitions, + QSet &statesForDefaultEntry); + QAbstractState *getTransitionDomain(QAbstractTransition *t, + const QList &effectiveTargetStates); + void addDescendantStatesToEnter(QAbstractState *state, + QSet &statesToEnter, + QSet &statesForDefaultEntry); void addStatesToEnter(QAbstractState *s, QState *root, QSet &statesToEnter, QSet &statesForDefaultEntry); - void addAncestorStatesToEnter(QAbstractState *s, QState *root, + void addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor, QSet &statesToEnter, QSet &statesForDefaultEntry); -- cgit v1.2.3 From b2f6406b6f3c6374df2751a4669fbe51f04d09e7 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 18 Mar 2015 12:44:22 +0100 Subject: QStateMachine: remove conflicting transitions after selection. After selecting all (enabled) transitions for a microstep, filter out any conflicting transition. The actual conflict resulution is done by ordering the transitions in order of the states that selected them. For example: if an event would trigger two transitions in a parallel state where one would exit that state and the other would not, this filtering prevents the state machine from selecting both states (as this case is an invalid state of the whole machine). This also fixes the exit set calculation for parallel states when one of its substates is exited and subsequently re-entered in the same transition. Previously, the parallel state was not exited, and subsequent re-entry was ignored (because it was still active). Now it is correctly exited and re-entered. A side-effect of the transition ordering mentioned above is it also fixes the non-deterministic behavior of which of the conflicting transitions is taken. [ChangeLog][QtCore] Fixed an issue where the state machine could end up in an invalid state when transitions from a parallel state were not checked for conflicts. [ChangeLog][QtCore] Fixed a case where a parallel state was not exited and re-entered when one of its substates was exited and subsequently re-entered. [ChangeLog][QtCore] Fixed the non-deterministic behavior of picking a transition from a set of conflicting transitions. Task-number: QTBUG-44783 Change-Id: I2ee72b6a2f552077bfa7aa4d369474ab62f4c2f0 Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Kevin Funk --- src/corelib/statemachine/qstatemachine.cpp | 214 ++++++++++++++++++++--------- src/corelib/statemachine/qstatemachine_p.h | 10 +- 2 files changed, 157 insertions(+), 67 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index 477fa83705..eec3febbfe 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -251,10 +251,17 @@ static QSet getEffectiveTargetStates(QAbstractTransition *tran foreach (QAbstractState *s, transition->targetStates()) { if (QHistoryState *historyState = QStateMachinePrivate::toHistoryState(s)) { QList historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration; - if (!historyConfiguration.isEmpty()) + if (!historyConfiguration.isEmpty()) { + // There is a saved history, so apply that. targets.unite(historyConfiguration.toSet()); - else if (QAbstractState *defaultState = historyState->defaultState()) - targets.insert(defaultState); // Qt does not support initial transitions, but uses the default state of the history state for this. + } 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); } @@ -338,6 +345,15 @@ static int indexOfDescendant(QState *s, QAbstractState *desc) 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()) { @@ -401,40 +417,21 @@ QState *QStateMachinePrivate::findLCCA(const QList &states) con return findLCA(states, true); } -bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet &transitions) const +QList QStateMachinePrivate::selectTransitions(QEvent *event) { - QSet::const_iterator it; - for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) { - QAbstractTransition *t = *it; - QList lst = t->targetStates(); - if (!lst.isEmpty()) { - lst.prepend(t->sourceState()); - QAbstractState *lca = findLCA(lst); - if (isDescendant(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; - } - } + Q_Q(const QStateMachine); + + QVarLengthArray configuration_sorted; + foreach (QAbstractState *s, configuration) { + if (isAtomic(s)) + configuration_sorted.append(s); } - return false; -} + std::sort(configuration_sorted.begin(), configuration_sorted.end(), stateEntryLessThan); -QSet QStateMachinePrivate::selectTransitions(QEvent *event) const -{ - Q_Q(const QStateMachine); - QSet enabledTransitions; - QSet::const_iterator it; + QList enabledTransitions; const_cast(q)->beginSelectTransitions(event); - for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - QAbstractState *state = *it; - if (!isAtomic(state)) - continue; - if (isPreempted(state, enabledTransitions)) - continue; - QVector lst = getProperAncestors(state, rootState()->parentState()); + foreach (QAbstractState *state, configuration_sorted) { + QVector lst = getProperAncestors(state, Q_NULLPTR); if (QState *grp = toStandardState(state)) lst.prepend(grp); bool found = false; @@ -447,29 +444,94 @@ QSet 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(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 &enabledTransitions) +{ + QList filteredTransitions; + filteredTransitions.reserve(enabledTransitions.size()); + std::sort(enabledTransitions.begin(), enabledTransitions.end(), transitionStateEntryLessThan); + + Q_FOREACH (QAbstractTransition *t1, enabledTransitions) { + bool t1Preempted = false; + QVarLengthArray transitionsToRemove; + QSet exitSetT1 = computeExitSet_Unordered(QList() << t1); + Q_FOREACH (QAbstractTransition *t2, filteredTransitions) { + QSet exitSetT2 = computeExitSet_Unordered(QList() << 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 &enabledTransitions) { #ifdef QSTATEMACHINE_DEBUG qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')'; qDebug() << q_func() << ": configuration before exiting states:" << configuration; #endif - QList exitedStates = computeStatesToExit(enabledTransitions); + QList exitedStates = computeExitSet(enabledTransitions); QHash pendingRestorables = computePendingRestorables(exitedStates); QSet statesForDefaultEntry; QList enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry); +#ifdef QSTATEMACHINE_DEBUG + qDebug() << q_func() << ": computed exit set:" << exitedStates; + qDebug() << q_func() << ": computed entry set:" << enteredStates; +#endif + QHash > assignmentsForEnteredStates = computePropertyAssignments(enteredStates, pendingRestorables); if (!pendingRestorables.isEmpty()) { @@ -502,38 +564,63 @@ void QStateMachinePrivate::microstep(QEvent *event, const QList QStateMachinePrivate::computeStatesToExit(const QList &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 QStateMachinePrivate::computeExitSet(const QList &enabledTransitions) +{ + QList statesToExit_sorted = computeExitSet_Unordered(enabledTransitions).toList(); + std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan); + return statesToExit_sorted; +} + +QSet QStateMachinePrivate::computeExitSet_Unordered(const QList &enabledTransitions) { QSet statesToExit; -// QSet statesToSnapshot; for (int i = 0; i < enabledTransitions.size(); ++i) { QAbstractTransition *t = enabledTransitions.at(i); - QList 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 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 lst = pendingErrorStates.toList(); lst.prepend(t->sourceState()); - lca = findLCA(lst); - Q_ASSERT(lca != 0); + domain = findLCCA(lst); + Q_ASSERT(domain != 0); } - { - QSet::const_iterator it; - for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) { - QAbstractState *s = *it; - if (isDescendant(s, lca)) - statesToExit.insert(s); - } + Q_FOREACH (QAbstractState* s, configuration) { + if (isDescendant(s, domain)) + statesToExit.insert(s); } } - QList 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 &statesToExit_sorted, @@ -602,9 +689,7 @@ QList QStateMachinePrivate::computeEntrySet(const QListtargetStates()) { addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry); } -#ifdef QSTATEMACHINE_DEBUG - qDebug() << "computed entry set after descendants:" << statesToEnter; -#endif + QList effectiveTargetStates = getEffectiveTargetStates(t).toList(); QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates); Q_FOREACH (QAbstractState *s, effectiveTargetStates) { @@ -643,7 +728,7 @@ function getTransitionDomain(t) else: return findLCCA([t.source].append(tstates)) */ -QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t, const QList &effectiveTargetStates) +QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t, const QList &effectiveTargetStates) const { if (effectiveTargetStates.isEmpty()) return 0; @@ -1285,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() << currentErrorState << currentContext); addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry); } else { @@ -1640,7 +1728,7 @@ void QStateMachinePrivate::_q_process() processing = false; break; } - QSet enabledTransitions; + QList enabledTransitions; QEvent *e = new QEvent(QEvent::None); enabledTransitions = selectTransitions(e); if (enabledTransitions.isEmpty()) { @@ -1676,7 +1764,7 @@ void QStateMachinePrivate::_q_process() } if (!enabledTransitions.isEmpty()) { q->beginMicrostep(e); - microstep(e, enabledTransitions.toList()); + microstep(e, enabledTransitions); q->endMicrostep(e); } #ifdef QSTATEMACHINE_DEBUG diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h index a8f0745730..a88f95f1f5 100644 --- a/src/corelib/statemachine/qstatemachine_p.h +++ b/src/corelib/statemachine/qstatemachine_p.h @@ -103,6 +103,7 @@ public: QState *findLCA(const QList &states, bool onlyCompound = false) const; QState *findLCCA(const QList &states) const; + static bool transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2); static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2); static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2); @@ -123,12 +124,13 @@ public: void clearHistory(); QAbstractTransition *createInitialTransition() const; + void removeConflictingTransitions(QList &enabledTransitions); void microstep(QEvent *event, const QList &transitionList); - bool isPreempted(const QAbstractState *s, const QSet &transitions) const; - QSet selectTransitions(QEvent *event) const; + QList selectTransitions(QEvent *event); void exitStates(QEvent *event, const QList &statesToExit_sorted, const QHash > &assignmentsForEnteredStates); - QList computeStatesToExit(const QList &enabledTransitions); + QList computeExitSet(const QList &enabledTransitions); + QSet computeExitSet_Unordered(const QList &enabledTransitions); void executeTransitionContent(QEvent *event, const QList &transitionList); void enterStates(QEvent *event, const QList &exitedStates_sorted, const QList &statesToEnter_sorted, @@ -141,7 +143,7 @@ public: QList computeEntrySet(const QList &enabledTransitions, QSet &statesForDefaultEntry); QAbstractState *getTransitionDomain(QAbstractTransition *t, - const QList &effectiveTargetStates); + const QList &effectiveTargetStates) const; void addDescendantStatesToEnter(QAbstractState *state, QSet &statesToEnter, QSet &statesForDefaultEntry); -- cgit v1.2.3 From 96cc8eec9b32f4e80c2d748687c485bc79133d39 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Thu, 9 Apr 2015 11:24:15 +0200 Subject: remove the "wonderful Windows notifier" from QProcess Remove the 100 ms timer that was used to nudge QProcess to write data to the child's stdin. Instead, react on the canWrite() signal of QWindowsPipeWriter. QProcess::writeData needs to call _q_canWrite via the event loop to start the write operation. The socket notifier code was never in use on Windows. Task-number: QTBUG-45457 Change-Id: I99c956ba5f2169f80068eee206543ceb9788b2e0 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qprocess.cpp | 34 +++++++++++++++++++++++++++------- src/corelib/io/qprocess.h | 1 - src/corelib/io/qprocess_p.h | 4 +--- src/corelib/io/qprocess_unix.cpp | 4 ---- src/corelib/io/qprocess_win.cpp | 19 ++----------------- src/corelib/io/qprocess_wince.cpp | 4 ---- 6 files changed, 30 insertions(+), 36 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp index 7d7cdef203..ead04791e5 100644 --- a/src/corelib/io/qprocess.cpp +++ b/src/corelib/io/qprocess.cpp @@ -36,6 +36,9 @@ #include #include +#if defined(Q_OS_WIN) +#include +#endif #if defined QPROCESS_DEBUG #include #include @@ -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..54cf37b717 100644 --- a/src/corelib/io/qprocess.h +++ b/src/corelib/io/qprocess.h @@ -266,7 +266,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 46b557d6e0..69b631f7e7 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -1111,10 +1111,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 #include #include -#include #include #include #include @@ -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); -- cgit v1.2.3 From a02c04a51b34fc780fa680383f2aee3b3f37fa51 Mon Sep 17 00:00:00 2001 From: Niclas Rosenvik Date: Mon, 13 Apr 2015 13:03:53 +0200 Subject: qstorageinfo_unix.cpp: fixes for NetBSD and solaris NetBSD uses struct statvfs ** as first argument to getmntinfo. see: http://netbsd.gw.com/cgi-bin/man-cgi?getmntinfo getmntent on solaris and sunos returns an integer not a pointer. see: http://www.unix.com/man-page/opensolaris/3c/getmntent/ see: https://smartos.org/man/3C/getmntent Change-Id: Ic01da0edcf1f55617294e5a86b8459669e82c1b1 Reviewed-by: Thiago Macieira --- src/corelib/io/qstorageinfo_unix.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp index 45b32830cd..7b8f608050 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 -- cgit v1.2.3 From 666486b3efec871301b82244ec661e1eaa6cca9c Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 10 Apr 2015 10:07:51 +0200 Subject: Fix performance of recursive read-write locks The implementation used an expensive QHash to keep track of reading threads, for seemingly no good reason. Change-Id: Iffa5b18d80f56b8ff22d39aa6bc3d52c2e3ed0ef Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira --- src/corelib/thread/qreadwritelock.cpp | 57 ----------------------------------- src/corelib/thread/qreadwritelock_p.h | 1 - 2 files changed, 58 deletions(-) (limited to 'src/corelib') 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::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::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::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::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 currentReaders; }; QT_END_NAMESPACE -- cgit v1.2.3 From 91dfab223a64385f6c0d010deafbdc8b2eb69968 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Tue, 24 Mar 2015 22:20:48 +0100 Subject: Add support for unregistering of custom meta types. This patch addresses a specific Qml problem, where the meta types list will grow indefinitely when unloading and reloading Qml components over and over (in an failed effort to save memory). The implementation is not specific to Qml though, but will cater to all use-cases where registered types may not live until the application's termination. Change-Id: Ic0224dcd19aeb559715ef088b22a30509be2456b Reviewed-by: Simon Hausmann --- src/corelib/kernel/qmetatype.cpp | 63 ++++++++++++++++++++++++++++++++++++---- src/corelib/kernel/qmetatype.h | 1 + 2 files changed, 58 insertions(+), 6 deletions(-) (limited to 'src/corelib') 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 * 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; } @@ -905,6 +911,39 @@ int QMetaType::registerType(const char *typeName, Deleter deleter, QtMetaTypePrivate::QMetaTypeFunctionHelper::Construct, 0, TypeFlags(), 0); } +/*! + \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 *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 @@ -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, -- cgit v1.2.3 From 198190b76baffce9b983d03749e64af6f8428e49 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 15 Apr 2015 11:31:20 +0200 Subject: QList: make QListSpecialMethods dtors protected QList publicly inherits from QListSpecialMethods. Thus, any specialisation of QListSpecialMethods should make their destructor protected, to avoid deletion through a pointer to QListSpecialMethods invoking UB. Change-Id: I7e317606f84826cc0faf1bfc05dee97da6eaf2eb Reviewed-by: Thiago Macieira --- src/corelib/tools/qbytearraylist.h | 4 ++++ src/corelib/tools/qlist.h | 7 ++++++- src/corelib/tools/qstringlist.h | 4 ++++ 3 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/corelib') 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 template <> struct QListSpecialMethods #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/qlist.h b/src/corelib/tools/qlist.h index 57e67d52d7..f5ff952f97 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -62,8 +62,13 @@ QT_BEGIN_NAMESPACE template class QVector; template class QSet; -template struct QListSpecialMethods { }; +template struct QListSpecialMethods +{ +protected: + ~QListSpecialMethods() {} +}; template <> struct QListSpecialMethods; +template <> struct QListSpecialMethods; struct Q_CORE_EXPORT QListData { // tags for tag-dispatching of QList implementations, 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 template <> struct QListSpecialMethods #endif { +#ifndef Q_QDOC +protected: + ~QListSpecialMethods() {} +#endif public: inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive); inline int removeDuplicates(); -- cgit v1.2.3 From d3dfb8d8f13b8e878778ebf4980a3b192b4b7a08 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 16 Apr 2015 11:18:21 +0200 Subject: QSignalBlocker: mark all functions as noexcept Consequently, mark also QObject::isSignalsBlocked() and QObject::blockSignals() as noexcept. Change-Id: Iaf44674bbf54eeb2bb5f267eb7caa916eccbf7fb Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qobject.cpp | 2 +- src/corelib/kernel/qobject.h | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index 774e46ea33..1836405b9c 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -1395,7 +1395,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; diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h index 42d18d6c41..ecea13fc4a 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); @@ -552,17 +552,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 +570,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 +591,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 +614,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; -- cgit v1.2.3 From fb144aabbf29c583986e8e4147bd0084efb26ef2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 16 Apr 2015 11:19:59 +0200 Subject: QScopedValueRollback: use ctor-init-list Avoids calls to the default ctor for member 'oldValue'. Change-Id: Ieb9570b74e4a46b28c04625fac3ce267074c4a76 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qscopedvaluerollback.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h index 66110b88f6..0265665d94 100644 --- a/src/corelib/tools/qscopedvaluerollback.h +++ b/src/corelib/tools/qscopedvaluerollback.h @@ -43,15 +43,13 @@ 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; } -- cgit v1.2.3 From 1ae657344c5e8e7f19eaff0f300e870d0cd1afa1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 16 Apr 2015 11:20:42 +0200 Subject: QScopedValueRollback: add two strategic qMove()s Use moves instead of copies when the rhs is no longer needed afterwards. Change-Id: If053bfce03b886099688452ada74f6a6f36db5c2 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qscopedvaluerollback.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/corelib') diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h index 0265665d94..2db2ad869c 100644 --- a/src/corelib/tools/qscopedvaluerollback.h +++ b/src/corelib/tools/qscopedvaluerollback.h @@ -50,12 +50,12 @@ public: explicit QScopedValueRollback(T &var, T value) : varRef(var), oldValue(var) { - varRef = value; + varRef = qMove(value); } ~QScopedValueRollback() { - varRef = oldValue; + varRef = qMove(oldValue); } void commit() -- cgit v1.2.3 From 28dcb7101e0038007bf9c2e1e17f9588b5264943 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 16 Apr 2015 19:54:52 +0200 Subject: QFileSystemEngine: optimize from...(qgetenv()) Use the QByteArray overload, which no longer calls strlen(), but uses the QByteArray length. No danger of embedded NULs, because environment variables cannot contain NULs. Change-Id: I33fe479adfce2624c7042608e8e0a5c5b54a85db Reviewed-by: Thiago Macieira --- src/corelib/io/qfilesystemengine_win.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/corelib') 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"); -- cgit v1.2.3 From d0c96c65ec5e25b1b43885a8c32a886a9b6aa834 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 17 Apr 2015 09:06:04 +0200 Subject: Rework WinRT timer handling The former way of timer handling caused heap corruptions as the timer callbacks tried to access the event dispatcher after it was freed. So instead of accessing the timers inside the callbacks we use native events to signal their expiration and also to cancel them. Task-number: QTBUG-44973 Change-Id: Ib9348651c0545cc4393f0396601f9a5bb183c996 Reviewed-by: Andrew Knight --- src/corelib/kernel/qcoreapplication_win.cpp | 46 ++-- src/corelib/kernel/qeventdispatcher_winrt.cpp | 327 +++++++++++++++----------- 2 files changed, 208 insertions(+), 165 deletions(-) (limited to 'src/corelib') 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(pe.event)->timerId() == timerId) { - --pe.receiver->d_func()->postedEvents; - pe.event->posted = false; - delete pe.event; - const_cast(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(pe.event)->timerId() == timerId) { + --pe.receiver->d_func()->postedEvents; + pe.event->posted = false; + delete pe.event; + const_cast(pe).event = 0; + return; + } + } +} +#endif // QT_NO_QOBJECT + QT_END_NAMESPACE 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 timer; - QPointer dispatcher; + bool inEvent; + QObject *object; + quint64 targetTime; }; class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate @@ -121,13 +79,63 @@ public: ~QEventDispatcherWinRTPrivate(); private: - QHash timerDict; - ComPtr timerFactory; ComPtr coreDispatcher; QPointer thread; - bool interrupt; + QHash timerIdToObject; + QVector timerInfos; + QHash timerHandleToId; + QHash timerIdToHandle; + QHash 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 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(t, &WinRTTimerInfo::timerExpired).Get(), period, - Callback(t, &WinRTTimerInfo::timerDestroyed).Get(), &t->timer); + Callback([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([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::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 QEventDispatcherWinRT::registeredTimers(QObject *object) const { if (!object) { +#ifndef QT_NO_DEBUG qWarning("QEventDispatcherWinRT:registeredTimers: invalid argument"); +#endif return QList(); } Q_D(const QEventDispatcherWinRT); - QList list; - foreach (const WinRTTimerInfo *t, d->timerDict) { - if (t->obj == object) - list.append(TimerInfo(t->id, t->interval, t->timerType)); + QList 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(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(); } -- cgit v1.2.3 From 6526a4e1367fa134ff29952fcbdd0d7cc937003f Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 17 Apr 2015 10:29:04 +0200 Subject: qdoc: Remove #ifdef Q_QDOC for uses of QPrivateSignal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signals marked with QPrivateSignal had the QPrivateSignal marker ifdefed out for qdoc. This is no longer necessary, so the #ifdefs are removed. Change-Id: Idb334ed311c6ed6883d7b7b5a3fcdede60c4a1f8 Task-number: QTBUG-45535 Reviewed-by: Oswald Buddenhagen Reviewed-by: Giuseppe D'Angelo Reviewed-by: Topi Reiniƶ --- src/corelib/io/qfilesystemwatcher.h | 12 +--- src/corelib/io/qprocess.h | 24 ++------ src/corelib/itemmodels/qabstractitemmodel.h | 84 +++++--------------------- src/corelib/itemmodels/qabstractproxymodel.h | 6 +- src/corelib/kernel/qcoreapplication.h | 6 +- src/corelib/kernel/qobject.h | 6 +- src/corelib/kernel/qsocketnotifier.h | 6 +- src/corelib/kernel/qtimer.h | 6 +- src/corelib/kernel/qwineventnotifier.h | 6 +- src/corelib/statemachine/qabstractstate.h | 12 +--- src/corelib/statemachine/qabstracttransition.h | 18 +----- src/corelib/statemachine/qhistorystate.h | 12 +--- src/corelib/statemachine/qsignaltransition.h | 12 +--- src/corelib/statemachine/qstate.h | 30 ++------- src/corelib/statemachine/qstatemachine.h | 12 +--- src/corelib/thread/qthread.h | 12 +--- src/corelib/tools/qtimeline.h | 24 ++------ 17 files changed, 48 insertions(+), 240 deletions(-) (limited to 'src/corelib') 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/qprocess.h b/src/corelib/io/qprocess.h index 54cf37b717..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); 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 &parents = QList(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint); void layoutAboutToBeChanged(const QList &parents = QList(), 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.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/qobject.h b/src/corelib/kernel/qobject.h index ecea13fc4a..5f61dd984f 100644 --- a/src/corelib/kernel/qobject.h +++ b/src/corelib/kernel/qobject.h @@ -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; } 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/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.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/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/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; -- cgit v1.2.3 From 8fb881900c7bb7895e7a2109a7dc880954bcf3a9 Mon Sep 17 00:00:00 2001 From: Harald Hvaal Date: Sat, 28 Mar 2015 21:03:29 +0100 Subject: Enable checking for whether the system palette was explicitly set In order to obey a palette set globally on QApplication, an application attribute for checking if it's set at all is added. Task-number: QTBUG-39800 Change-Id: I26b965e6e18e0e1ca4df03cf343b3527df3636b2 Reviewed-by: J-P Nurmi Reviewed-by: Friedemann Kleint --- src/corelib/global/qnamespace.h | 1 + src/corelib/global/qnamespace.qdoc | 3 +++ 2 files changed, 4 insertions(+) (limited to 'src/corelib') diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 745fb442f2..79ddf81b38 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 8ebe0da11f..f9d968d47b 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -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 -- cgit v1.2.3 From ad03511256a8279a8f55069e5a3a3465a9e122ec Mon Sep 17 00:00:00 2001 From: Nikita Baryshnikov Date: Thu, 9 Apr 2015 13:41:19 +0300 Subject: QDir: fix int overflow This caused reverse order of session items in qt creator. Introduced in ba287c55ef179b073482453298f513992b54c11e. Change-Id: I5c37ca6a1ef4753b6449eb9e87b4def5ea858677 Reviewed-by: Marc Mutz --- src/corelib/io/qdir.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/corelib') diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 8380404219..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); -- cgit v1.2.3