From cdc5f47aeba94ba083a81dc681a09a351809e528 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 5 Apr 2017 21:11:12 -0700 Subject: Restore compatibility with Qt 5.7.0 and 5.6.1 QSysInfo::productType() returned "osx" for all versions of macOS, even 10.12. Change 3e2bde35786 was incorrect. [ChangeLog][Important Behavior Changes] QSysInfo::productType() and QFileSelector behavior on macOS was restored to match what Qt used to return in version 5.7.0 and earlier. The behavior found in Qt 5.6.2, 5.7.1 and 5.8.0 is removed. [ChangeLog][Future Compatibility Notice] The identifiers that QSysInfo::productType() and QFileSelector will use to identify macOS systems will change in Qt 6.0 to match the Apple naming guidelines which will be current then. Task-number: QTBUG-59849 Change-Id: Ib0e40a7a3ebc44329f23fffd14b2b39392210c4f Reviewed-by: Jake Petroules --- src/corelib/global/qglobal.cpp | 20 ++++++++++++-------- src/corelib/io/qfileselector.cpp | 10 +++++----- .../corelib/io/qfileselector/platforms/+mac/test2 | 0 .../corelib/io/qfileselector/platforms/+mac/test5 | 0 .../corelib/io/qfileselector/platforms/+macos/test | 0 .../corelib/io/qfileselector/platforms/+macos/test2 | 0 .../corelib/io/qfileselector/platforms/+osx/test2 | 0 .../corelib/io/qfileselector/platforms/+osx/test4 | 0 .../platforms/+unix/+darwin/+mac/+macos/test | 0 .../platforms/+unix/+darwin/+mac/+osx/+macos/test | 0 tests/auto/corelib/io/qfileselector/platforms/test4 | 0 tests/auto/corelib/io/qfileselector/platforms/test5 | 0 .../auto/corelib/io/qfileselector/qfileselector.qrc | 10 +++++++++- .../corelib/io/qfileselector/tst_qfileselector.cpp | 8 ++++++++ 14 files changed, 34 insertions(+), 14 deletions(-) delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+mac/test2 create mode 100644 tests/auto/corelib/io/qfileselector/platforms/+mac/test5 create mode 100644 tests/auto/corelib/io/qfileselector/platforms/+macos/test create mode 100644 tests/auto/corelib/io/qfileselector/platforms/+macos/test2 delete mode 100644 tests/auto/corelib/io/qfileselector/platforms/+osx/test2 create mode 100644 tests/auto/corelib/io/qfileselector/platforms/+osx/test4 create mode 100644 tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+macos/test create mode 100644 tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/+macos/test create mode 100644 tests/auto/corelib/io/qfileselector/platforms/test4 create mode 100644 tests/auto/corelib/io/qfileselector/platforms/test5 diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 6b3cb502e5..9a779305d2 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -2652,12 +2652,14 @@ QString QSysInfo::kernelVersion() to determine the distribution name and returns that. If determining the distribution name failed, it returns "unknown". - \b{Darwin, \macos, iOS, tvOS, and watchOS note}: this function returns - "macos" for \macos systems, "ios" for iOS systems, "tvos" for tvOS systems, - "watchos" for watchOS systems, and "darwin" in case the system could not - be determined. + \b{\macos note}: this function returns "osx" for all \macos systems, + regardless of Apple naming convention. The returned string will be updated + for Qt 6. Note that this function erroneously returned "macos" for \macos + 10.12 in Qt versions 5.6.2, 5.7.1, and 5.8.0. - \b{OS X note}: this function returns "osx" for versions of \macos prior to 10.12. + \b{Darwin, iOS, tvOS, and watchOS note}: this function returns "ios" for + iOS systems, "tvos" for tvOS systems, "watchos" for watchOS systems, and + "darwin" in case the system could not be determined. \b{FreeBSD note}: this function returns "debian" for Debian/kFreeBSD and "unknown" otherwise. @@ -2692,10 +2694,12 @@ QString QSysInfo::productType() #elif defined(Q_OS_WATCHOS) return QStringLiteral("watchos"); #elif defined(Q_OS_MACOS) - const QAppleOperatingSystemVersion version = qt_apple_os_version(); - if (version.major == 10 && version.minor < 12) - return QStringLiteral("osx"); + // ### Qt6: remove fallback +# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) return QStringLiteral("macos"); +# else + return QStringLiteral("osx"); +# endif #elif defined(Q_OS_DARWIN) return QStringLiteral("darwin"); diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 920281cef7..22995db07d 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -366,6 +366,7 @@ void QFileSelectorPrivate::updateSelectors() QStringList QFileSelectorPrivate::platformSelectors() { // similar, but not identical to QSysInfo::osType + // ### Qt6: remove macOS fallbacks to "mac" and the future compatibility QStringList ret; #if defined(Q_OS_WIN) // can't fall back to QSysInfo because we need both "winphone" and "winrt" for the Windows Phone case @@ -387,12 +388,11 @@ QStringList QFileSelectorPrivate::platformSelectors() # endif # endif QString productName = QSysInfo::productType(); -# ifdef Q_OS_MACOS - if (productName != QLatin1String("osx")) - ret << QStringLiteral("osx"); // compatibility -# endif if (productName != QLatin1String("unknown")) - ret << productName; // "opensuse", "fedora", "macos", "ios", "android" + ret << productName; // "opensuse", "fedora", "osx", "ios", "android" +# if defined(Q_OS_MACOS) + ret << QStringLiteral("macos"); // future compatibility +# endif #endif return ret; } diff --git a/tests/auto/corelib/io/qfileselector/platforms/+mac/test2 b/tests/auto/corelib/io/qfileselector/platforms/+mac/test2 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+mac/test5 b/tests/auto/corelib/io/qfileselector/platforms/+mac/test5 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+macos/test b/tests/auto/corelib/io/qfileselector/platforms/+macos/test new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+macos/test2 b/tests/auto/corelib/io/qfileselector/platforms/+macos/test2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+osx/test2 b/tests/auto/corelib/io/qfileselector/platforms/+osx/test2 deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+osx/test4 b/tests/auto/corelib/io/qfileselector/platforms/+osx/test4 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+macos/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+macos/test new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/+macos/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+darwin/+mac/+osx/+macos/test new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/test4 b/tests/auto/corelib/io/qfileselector/platforms/test4 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/test5 b/tests/auto/corelib/io/qfileselector/platforms/test5 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/auto/corelib/io/qfileselector/qfileselector.qrc b/tests/auto/corelib/io/qfileselector/qfileselector.qrc index ab7a4d7f23..ea9b8270e0 100644 --- a/tests/auto/corelib/io/qfileselector/qfileselector.qrc +++ b/tests/auto/corelib/io/qfileselector/qfileselector.qrc @@ -15,6 +15,7 @@ platforms/test platforms/+unix/+android/test platforms/+unix/+darwin/+mac/+ios/test + platforms/+unix/+darwin/+mac/+osx/+macos/test platforms/+unix/+darwin/+mac/+osx/test platforms/+unix/+darwin/+mac/test platforms/+unix/+darwin/test @@ -27,6 +28,7 @@ platforms/+windows/test platforms/+android/test platforms/+ios/test + platforms/+macos/test platforms/+osx/test platforms/+darwin/test platforms/+mac/test @@ -39,7 +41,7 @@ platforms/test2 platforms/+android/test2 platforms/+ios/test2 - platforms/+osx/test2 + platforms/+macos/test2 platforms/+haiku/test2 platforms/+linux/test2 platforms/+wince/test2 @@ -50,5 +52,11 @@ platforms/test3 platforms/+windows/test3 platforms/+unix/test3 + + + platforms/test4 + platforms/+osx/test4 + platforms/test5 + platforms/+mac/test5 diff --git a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp index e5ede1ad06..f2d09429cc 100644 --- a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp +++ b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp @@ -126,6 +126,14 @@ void tst_QFileSelector::basicTest_data() QTest::newRow("platform3") << QString(":/platforms/test3") << QStringList() << expectedPlatform3File; +#ifdef Q_OS_MACOS + // special case for compatibility code + QTest::newRow("osx-compat") << QString(":/platforms/test4") << QStringList() + << ":/platforms/+osx/test4"; + QTest::newRow("mac-compat") << QString(":/platforms/test5") << QStringList() + << ":/platforms/+mac/test5"; +#endif + QString resourceTestPath(":/extras/test"); QString custom1("custom1"); QTest::newRow("custom1-noselector") << resourceTestPath << QStringList() -- cgit v1.2.3 From 11ed95ac9c12ee2b20b5c6f6be68d0b6387c0e70 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 30 Mar 2017 19:13:58 +0200 Subject: Improve QStringBuilder docs - Mention you can build QByteArrays, too - Nicer list of types that can be used, separate for QByteArray and QString Change-Id: Ia91445f0cb4872bab12a55f4812c283e9c38dba4 Reviewed-by: Edward Welbourne Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qstringbuilder.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp index de12de19cb..70152a9202 100644 --- a/src/corelib/tools/qstringbuilder.cpp +++ b/src/corelib/tools/qstringbuilder.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE \reentrant \since 4.6 - \brief The QStringBuilder class is a template class that provides a facility to build up QStrings from smaller chunks. + \brief The QStringBuilder class is a template class that provides a facility to build up QStrings and QByteArrays from smaller chunks. \ingroup tools \ingroup shared @@ -58,22 +58,34 @@ QT_BEGIN_NAMESPACE To build a QString by multiple concatenations, QString::operator+() - is typically used. This causes \e{n - 1} reallocations when building - a string from \e{n} chunks. + is typically used. This causes \e{n - 1} allocations when building + a string from \e{n} chunks. The same is true for QByteArray. QStringBuilder uses expression templates to collect the individual chunks, compute the total size, allocate the required amount of - memory for the final QString object, and copy the chunks into the + memory for the final string object, and copy the chunks into the allocated memory. The QStringBuilder class is not to be used explicitly in user code. Instances of the class are created as return values of the - operator%() function, acting on objects of type QString, - QLatin1String, QStringRef, QChar, QCharRef, - QLatin1Char, and \c char. + operator%() function, acting on objects of the following types: + + For building QStrings: + + \li QString, QStringRef, + \li QChar, QCharRef, QLatin1Char, + \li QLatin1String, + \li QByteArray, \c char, \c{const char[]}. + + The types in the last list point are only available when + QT_NO_CAST_FROM_ASCII is not defined. + + For building QByteArrays: + + \li QByteArray, \c char, \c{const char[]}. Concatenating strings with operator%() generally yields better - performance then using \c QString::operator+() on the same chunks + performance than using \c QString::operator+() on the same chunks if there are three or more of them, and performs equally well in other cases. -- cgit v1.2.3 From bdd5a67e6543aa4159ab4aa4b466baa453b622aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Mon, 9 May 2016 20:01:36 +0200 Subject: QtWidgets: Don't open submenus when mouse is moving between actions Don't set the current action during closing submenu when mouse moved more than one action in the menu to the top or to the bottom. Task-number: QTBUG-53215 Change-Id: I2383363bc48f644df046198662dfa4d080fe3f1d Reviewed-by: Shawn Rutledge --- src/widgets/widgets/qmenu.cpp | 10 +++++++--- src/widgets/widgets/qmenu_p.h | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 1925b58326..6da56c926c 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -632,6 +632,7 @@ void QMenuSloppyState::reset() m_enabled = false; m_first_mouse = true; m_init_guard = false; + m_use_reset_action = true; m_uni_dir_discarded_count = 0; m_time.stop(); m_reset_action = Q_NULLPTR; @@ -684,6 +685,7 @@ void QMenuSloppyState::setSubMenuPopup(const QRect &actionRect, QAction *resetAc { m_enabled = true; m_init_guard = true; + m_use_reset_action = true; m_time.stop(); m_action_rect = actionRect; m_sub_menu = subMenu; @@ -744,10 +746,12 @@ void QMenuSloppyState::timeout() if (m_sub_menu) menu_priv->hideMenu(m_sub_menu); - if (reallyHasMouse) - menu_priv->setCurrentAction(m_reset_action,0); - else + if (reallyHasMouse) { + if (m_use_reset_action) + menu_priv->setCurrentAction(m_reset_action, 0); + } else { menu_priv->setCurrentAction(Q_NULLPTR, 0); + } } //return the top causedPopup.widget that is not a QMenu diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h index 898fa3161b..0bce269831 100644 --- a/src/widgets/widgets/qmenu_p.h +++ b/src/widgets/widgets/qmenu_p.h @@ -95,6 +95,7 @@ public: , m_select_other_actions(false) , m_first_mouse(true) , m_init_guard(false) + , m_use_reset_action(true) , m_uni_dir_discarded_count(0) , m_uni_dir_fail_at_count(0) , m_timeout(0) @@ -182,9 +183,17 @@ public: QSetValueOnDestroy setFirstMouse(m_first_mouse, false); QSetValueOnDestroy setPreviousPoint(m_previous_point, mousePos); - if (resetAction && resetAction->isSeparator()) + if (resetAction && resetAction->isSeparator()) { m_reset_action = Q_NULLPTR; - else { + m_use_reset_action = true; + } else if (m_reset_action != resetAction) { + if (m_use_reset_action && resetAction) { + const QList actions = m_menu->actions(); + const int resetIdx = actions.indexOf(resetAction); + const int originIdx = actions.indexOf(m_origin_action); + if (resetIdx > -1 && originIdx > -1 && qAbs(resetIdx - originIdx) > 1) + m_use_reset_action = false; + } m_reset_action = resetAction; } @@ -249,6 +258,7 @@ private: bool m_init_guard; bool m_discard_state_when_entering_parent; bool m_dont_start_time_on_leave; + bool m_use_reset_action; short m_uni_dir_discarded_count; short m_uni_dir_fail_at_count; short m_timeout; -- cgit v1.2.3 From b727f11c2e4e8d4dd9dbd512f34ce7f95fd077fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Tue, 17 Jan 2017 15:49:07 +0100 Subject: QFontconfigDatabase: properly parse desktop environment variable $XDG_CURRENT_DESKTOP is defined as a colon-separated list of desktop strings, thus we can't check for equality, but split it and check if it contains the desktop environments we care about. Change-Id: Ia9ab0f28654a3e1a68b918794a079f3974f85642 Reviewed-by: Shawn Rutledge Reviewed-by: Dmitry Shachnev --- .../fontdatabases/fontconfig/qfontconfigdatabase.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 2c5ce3e87d..98dce03ae6 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -900,7 +900,13 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef bool forcedAntialiasSetting = !antialias; const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services(); - bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY")); + bool useXftConf = false; + + if (services) { + const QList desktopEnv = services->desktopEnvironment().split(':'); + useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY"); + } + if (useXftConf && !forcedAntialiasSetting) { void *antialiasResource = QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled", -- cgit v1.2.3 From feaaca456b1b9f5f6ba84f0aa3cb7e93dfb862cf Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 12 Apr 2017 14:12:10 +0100 Subject: QLocale: do not test for Q_OS_MAC before including qglobal.h Found by clazy. Change-Id: I66b6698c309720891db83626e18c5e1baca19091 Reviewed-by: Thiago Macieira --- src/corelib/tools/qlocale.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index c183224c82..c23c84534f 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -38,13 +38,13 @@ ** ****************************************************************************/ +#include "qglobal.h" + #if !defined(QWS) && defined(Q_OS_MAC) # include "private/qcore_mac_p.h" # include #endif -#include "qglobal.h" - #include "qplatformdefs.h" #include "qdatastream.h" -- cgit v1.2.3 From 98e0cb0a28845fd6b808c25d2e049f8da1f9867c Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Thu, 19 Jan 2017 11:36:59 +0100 Subject: Doc: updated QSyntaxHighlighter documentation and use QRegularExpression The documentation of QSyntaxHighlighter still uses the deprecated QRegExp class. This patch updates the code samples as well as cleanup some typos. Change-Id: I87b525fddb560b7c5bb38f96d9aaceadb594f76c Reviewed-by: Sze Howe Koh --- examples/widgets/doc/src/syntaxhighlighter.qdoc | 19 +++++------ .../richtext/syntaxhighlighter/highlighter.cpp | 37 +++++++++++----------- .../richtext/syntaxhighlighter/highlighter.h | 7 ++-- src/gui/text/qsyntaxhighlighter.cpp | 2 +- 4 files changed, 33 insertions(+), 32 deletions(-) diff --git a/examples/widgets/doc/src/syntaxhighlighter.qdoc b/examples/widgets/doc/src/syntaxhighlighter.qdoc index 0554f7d9d4..8583d86114 100644 --- a/examples/widgets/doc/src/syntaxhighlighter.qdoc +++ b/examples/widgets/doc/src/syntaxhighlighter.qdoc @@ -29,8 +29,8 @@ \example richtext/syntaxhighlighter \title Syntax Highlighter Example \ingroup examples-richtext - \brief The Syntax Highligher example shows how to perform - simple syntax highlighing. + \brief The Syntax Highlighter example shows how to perform + simple syntax highlighting. \brief The Syntax Highlighter example shows how to perform simple syntax highlighting by subclassing the QSyntaxHighlighter class. @@ -64,8 +64,9 @@ and define your own highlighting rules. We have chosen to store our highlighting rules using a private - struct: A rule consists of a QRegExp pattern and a QTextCharFormat - instance. The various rules are then stored using a QVector. + struct: A rule consists of a QRegularExpression pattern and a + QTextCharFormat instance. The various rules are then stored using a + QVector. The QTextCharFormat class provides formatting information for characters in a QTextDocument specifying the visual properties of @@ -78,7 +79,7 @@ When subclassing the QSyntaxHighlighter class you must pass the parent parameter to the base class constructor. The parent is the - text document upon which the syntax highligning will be + text document upon which the syntax highlighting will be applied. In this example, we have also chosen to define our highlighting rules in the constructor: @@ -138,11 +139,11 @@ First we apply the syntax highlighting rules that we stored in the \c highlightingRules vector. For each rule (i.e. for each HighlightingRule object) we search for the pattern in the given - textblock using the QString::indexOf() function. When the first + text block using the QString::indexOf() function. When the first occurrence of the pattern is found, we use the - QRegExp::matchedLength() function to determine the string that - will be formatted. QRegExp::matchedLength() returns the length of - the last matched string, or -1 if there was no match. + QRegularExpressionMatch::capturedLength() function to determine the string + that will be formatted. QRegularExpressionMatch::capturedLength() returns + the length of the last matched string, or 0 if there was no match. To perform the actual formatting the QSyntaxHighlighter class provides the \l {QSyntaxHighlighter::setFormat()}{setFormat()} diff --git a/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp b/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp index 183708bc06..6c420c328a 100644 --- a/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp +++ b/examples/widgets/richtext/syntaxhighlighter/highlighter.cpp @@ -68,9 +68,9 @@ Highlighter::Highlighter(QTextDocument *parent) << "\\bslots\\b" << "\\bstatic\\b" << "\\bstruct\\b" << "\\btemplate\\b" << "\\btypedef\\b" << "\\btypename\\b" << "\\bunion\\b" << "\\bunsigned\\b" << "\\bvirtual\\b" - << "\\bvoid\\b" << "\\bvolatile\\b"; + << "\\bvoid\\b" << "\\bvolatile\\b" << "\\bbool\\b"; foreach (const QString &pattern, keywordPatterns) { - rule.pattern = QRegExp(pattern); + rule.pattern = QRegularExpression(pattern); rule.format = keywordFormat; highlightingRules.append(rule); //! [0] //! [1] @@ -80,14 +80,14 @@ Highlighter::Highlighter(QTextDocument *parent) //! [2] classFormat.setFontWeight(QFont::Bold); classFormat.setForeground(Qt::darkMagenta); - rule.pattern = QRegExp("\\bQ[A-Za-z]+\\b"); + rule.pattern = QRegularExpression("\\bQ[A-Za-z]+\\b"); rule.format = classFormat; highlightingRules.append(rule); //! [2] //! [3] singleLineCommentFormat.setForeground(Qt::red); - rule.pattern = QRegExp("//[^\n]*"); + rule.pattern = QRegularExpression("//[^\n]*"); rule.format = singleLineCommentFormat; highlightingRules.append(rule); @@ -96,7 +96,7 @@ Highlighter::Highlighter(QTextDocument *parent) //! [4] quotationFormat.setForeground(Qt::darkGreen); - rule.pattern = QRegExp("\".*\""); + rule.pattern = QRegularExpression("\".*\""); rule.format = quotationFormat; highlightingRules.append(rule); //! [4] @@ -104,14 +104,14 @@ Highlighter::Highlighter(QTextDocument *parent) //! [5] functionFormat.setFontItalic(true); functionFormat.setForeground(Qt::blue); - rule.pattern = QRegExp("\\b[A-Za-z0-9_]+(?=\\()"); + rule.pattern = QRegularExpression("\\b[A-Za-z0-9_]+(?=\\()"); rule.format = functionFormat; highlightingRules.append(rule); //! [5] //! [6] - commentStartExpression = QRegExp("/\\*"); - commentEndExpression = QRegExp("\\*/"); + commentStartExpression = QRegularExpression("/\\*"); + commentEndExpression = QRegularExpression("\\*/"); } //! [6] @@ -119,12 +119,10 @@ Highlighter::Highlighter(QTextDocument *parent) void Highlighter::highlightBlock(const QString &text) { foreach (const HighlightingRule &rule, highlightingRules) { - QRegExp expression(rule.pattern); - int index = expression.indexIn(text); - while (index >= 0) { - int length = expression.matchedLength(); - setFormat(index, length, rule.format); - index = expression.indexIn(text, index + length); + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); } } //! [7] //! [8] @@ -134,22 +132,23 @@ void Highlighter::highlightBlock(const QString &text) //! [9] int startIndex = 0; if (previousBlockState() != 1) - startIndex = commentStartExpression.indexIn(text); + startIndex = text.indexOf(commentStartExpression); //! [9] //! [10] while (startIndex >= 0) { //! [10] //! [11] - int endIndex = commentEndExpression.indexIn(text, startIndex); - int commentLength; + QRegularExpressionMatch match = commentEndExpression.match(text, startIndex); + int endIndex = match.capturedStart(); + int commentLength = 0; if (endIndex == -1) { setCurrentBlockState(1); commentLength = text.length() - startIndex; } else { commentLength = endIndex - startIndex - + commentEndExpression.matchedLength(); + + match.capturedLength(); } setFormat(startIndex, commentLength, multiLineCommentFormat); - startIndex = commentStartExpression.indexIn(text, startIndex + commentLength); + startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); } } //! [11] diff --git a/examples/widgets/richtext/syntaxhighlighter/highlighter.h b/examples/widgets/richtext/syntaxhighlighter/highlighter.h index 39141615fc..0a24224b56 100644 --- a/examples/widgets/richtext/syntaxhighlighter/highlighter.h +++ b/examples/widgets/richtext/syntaxhighlighter/highlighter.h @@ -53,6 +53,7 @@ #include #include +#include QT_BEGIN_NAMESPACE class QTextDocument; @@ -72,13 +73,13 @@ protected: private: struct HighlightingRule { - QRegExp pattern; + QRegularExpression pattern; QTextCharFormat format; }; QVector highlightingRules; - QRegExp commentStartExpression; - QRegExp commentEndExpression; + QRegularExpression commentStartExpression; + QRegularExpression commentEndExpression; QTextCharFormat keywordFormat; QTextCharFormat classFormat; diff --git a/src/gui/text/qsyntaxhighlighter.cpp b/src/gui/text/qsyntaxhighlighter.cpp index 8834afc80e..fcda17605f 100644 --- a/src/gui/text/qsyntaxhighlighter.cpp +++ b/src/gui/text/qsyntaxhighlighter.cpp @@ -292,7 +292,7 @@ void QSyntaxHighlighterPrivate::reformatBlock(const QTextBlock &block) /*! Constructs a QSyntaxHighlighter with the given \a parent. - If the parent is a QTextEdit, it installs the syntaxhighlighter on the + If the parent is a QTextEdit, it installs the syntax highlighter on the parents document. The specified QTextEdit also becomes the owner of the QSyntaxHighlighter. */ -- cgit v1.2.3 From 5662234afaf23d88e1f3fa4bee2a59b61bd0c267 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 14 Apr 2017 12:39:20 +0200 Subject: QMatrix4x4: fix aliasing problem in operator*= When multiplying a QMatrix4x4 by itself, we were clobbering the very matrix we read from. Employ read-caching to avoid this aliasing problem. [ChangeLog][QtGui][QMatrix4x4] operator*=() now calculates the correct result even if the RHS and LHS are the same object. Change-Id: I8534d56cfdd62c336577125127f05173fcec2873 Reviewed-by: Sean Harmer --- src/gui/math3d/qmatrix4x4.h | 3 ++- tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h index aca685920e..4db96d07c0 100644 --- a/src/gui/math3d/qmatrix4x4.h +++ b/src/gui/math3d/qmatrix4x4.h @@ -423,8 +423,9 @@ inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other) return *this; } -inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other) +inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& o) { + const QMatrix4x4 other = o; // prevent aliasing when &o == this ### Qt 6: take o by value flagBits |= other.flagBits; if (flagBits < Rotation2D) { diff --git a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp index aea97a916e..c2c04b69c5 100644 --- a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp +++ b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp @@ -1227,6 +1227,10 @@ void tst_QMatrixNxN::multiply4x4() QMatrix4x4 m5; m5 = m1 * m2; QVERIFY(isSame(m5, (const float *)m3Values)); + + QMatrix4x4 m1xm1 = m1 * m1; + m1 *= m1; + QCOMPARE(m1, m1xm1); } // Test matrix multiplication for 4x3 matrices. -- cgit v1.2.3 From d1210281e41008ce2e3510aa5cfb3ebea1c57734 Mon Sep 17 00:00:00 2001 From: Ihor Dutchak Date: Mon, 17 Apr 2017 00:35:38 +0300 Subject: Fix undefined behavior in QSharedPointer::create() Initialize a deleter for a new object, created by QSharedPointer::create(), only after the object is actually constructed. [ChangeLog][QtCore][QSharedPointer] Fixed undefined behavior when creating an object with QSharedPointer::create() and its conscructor throws an exception. Task-number: QTBUG-49824 Change-Id: I07f77a78ff468d9b45b8ef133278e8cdd96a0647 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qsharedpointer_impl.h | 5 ++- .../tools/qsharedpointer/tst_qsharedpointer.cpp | 50 ++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 5738413bfb..373fc3a662 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -260,6 +260,7 @@ namespace QtSharedPointer { internalSafetyCheckRemove(self); deleter(self); } + static void noDeleter(ExternalRefCountData *) { } static inline ExternalRefCountData *create(T **ptr, DestroyerFn destroy) { @@ -433,11 +434,13 @@ public: # else typename Private::DestroyerFn destroy = &Private::deleter; # endif + typename Private::DestroyerFn noDestroy = &Private::noDeleter; QSharedPointer result(Qt::Uninitialized); - result.d = Private::create(&result.value, destroy); + result.d = Private::create(&result.value, noDestroy); // now initialize the data new (result.data()) T(std::forward(arguments)...); + result.d->destroyer = destroy; result.d->setQObjectShared(result.value, true); # ifdef QT_SHAREDPOINTER_TRACK_POINTERS internalSafetyCheckAdd(result.d, result.value); diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index d0a0feb125..7850478602 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -97,6 +97,8 @@ private slots: void qvariantCast(); void sharedFromThis(); + void constructorThrow(); + void threadStressTest_data(); void threadStressTest(); void validConstructs(); @@ -2594,6 +2596,54 @@ void tst_QSharedPointer::sharedFromThis() QCOMPARE(Data::destructorCounter, destructions + 6); } +#ifndef QT_NO_EXCEPTIONS +class ThrowData: public Data +{ +public: + static int childDestructorCounter; + static int childGenerationCounter; + + ThrowData() + { + childGenerationCounter++; + throw QStringLiteral("Dummy exception"); + } + + ~ThrowData() + { + childDestructorCounter++; + } +}; +int ThrowData::childDestructorCounter = 0; +int ThrowData::childGenerationCounter = 0; +#endif // !QT_NO_EXCEPTIONS + +void tst_QSharedPointer::constructorThrow() +{ +#ifndef QT_NO_EXCEPTIONS + int generation = Data::generationCounter; + int destructorCounter = Data::destructorCounter; + + int childGeneration = ThrowData::childGenerationCounter; + int childDestructorCounter = ThrowData::childDestructorCounter; + + QSharedPointer ptr; + QVERIFY_EXCEPTION_THROWN(ptr = QSharedPointer::create(), QString); + QVERIFY(ptr.isNull()); + QCOMPARE(ThrowData::childGenerationCounter, childGeneration + 1); + // destructor should never be called, if a constructor throws + // an exception + QCOMPARE(ThrowData::childDestructorCounter, childDestructorCounter); + + QCOMPARE(Data::generationCounter, generation + 1); + // but base class constructor doesn't throw, so base class destructor + // should be called + QCOMPARE(Data::destructorCounter, destructorCounter + 1); +#else + QSKIP("Needs exceptions"); +#endif // !QT_NO_EXCEPTIONS +} + namespace ReentrancyWhileDestructing { struct IB { -- cgit v1.2.3