diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2020-01-28 01:00:09 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2020-01-28 08:09:51 +0100 |
commit | 082faeff9c4c5a5b10d140b391d30305575a898b (patch) | |
tree | 505d176f243bfa3785a8aeb13138d3eba476175b /src | |
parent | be8c257da9a264994243c120231965ff0008ef09 (diff) | |
parent | 1ed802e3b8a7f236bd277719090f461a87eae78e (diff) | |
download | qtbase-082faeff9c4c5a5b10d140b391d30305575a898b.tar.gz |
Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts:
src/gui/image/qpnghandler.cpp
Change-Id: I8630f363457bb613d8fb88470a71d95d97cdb301
Diffstat (limited to 'src')
26 files changed, 297 insertions, 83 deletions
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index fa2098c757..835fea0c77 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -535,8 +535,25 @@ static QString getRelocatablePrefix() #if defined(QT_STATIC) prefixPath = prefixFromAppDirHelper(); #elif defined(Q_OS_DARWIN) && QT_CONFIG(framework) - CFBundleRef qtCoreBundle = CFBundleGetBundleWithIdentifier( - CFSTR("org.qt-project.QtCore")); + auto qtCoreBundle = CFBundleGetBundleWithIdentifier(CFSTR("org.qt-project.QtCore")); + if (!qtCoreBundle) { + // When running Qt apps over Samba shares, CoreFoundation will fail to find + // the Resources directory inside the bundle, This directory is a symlink, + // and CF relies on readdir() and dtent.dt_type to detect symlinks, which + // does not work reliably for Samba shares. We work around it by manually + // looking for the QtCore bundle. + auto allBundles = CFBundleGetAllBundles(); + auto bundleCount = CFArrayGetCount(allBundles); + for (int i = 0; i < bundleCount; ++i) { + auto bundle = CFBundleRef(CFArrayGetValueAtIndex(allBundles, i)); + auto url = QCFType<CFURLRef>(CFBundleCopyBundleURL(bundle)); + auto path = QCFType<CFStringRef>(CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle)); + if (CFStringHasSuffix(path, CFSTR("/QtCore.framework"))) { + qtCoreBundle = bundle; + break; + } + } + } Q_ASSERT(qtCoreBundle); QCFType<CFURLRef> qtCorePath = CFBundleCopyBundleURL(qtCoreBundle); diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 29b58783d5..9acb978efc 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -1023,7 +1023,7 @@ \value WA_MacNoClickThrough This value is obsolete and has no effect. - \value WA_MacOpaqueSizeGrip Indicates that the native Carbon size grip + \value WA_MacOpaqueSizeGrip Indicates that the native size grip should be opaque instead of transparent (the default). This attribute is only applicable to \macos and is set by the widget's author. diff --git a/src/corelib/serialization/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 500e0aa6be..7ff87885a5 100644 --- a/src/corelib/serialization/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -50,6 +50,7 @@ #endif #include <qstack.h> #include <qbuffer.h> +#include <qscopeguard.h> #ifndef QT_BOOTSTRAPPED #include <qcoreapplication.h> #else @@ -68,6 +69,8 @@ public: \ { return QString::fromLatin1(sourceText); } \ private: #endif +#include <private/qmemory_p.h> + QT_BEGIN_NAMESPACE #include "qxmlstream_p.h" @@ -847,7 +850,7 @@ void QXmlStreamReaderPrivate::init() #endif attributeStack.clear(); attributeStack.reserve(16); - entityParser = nullptr; + entityParser.reset(); hasCheckedStartDocument = false; normalizeLiterals = false; hasSeenTag = false; @@ -880,7 +883,7 @@ void QXmlStreamReaderPrivate::parseEntity(const QString &value) if (!entityParser) - entityParser = new QXmlStreamReaderPrivate(q); + entityParser = qt_make_unique<QXmlStreamReaderPrivate>(q); else entityParser->init(); entityParser->inParseEntity = true; @@ -910,7 +913,6 @@ QXmlStreamReaderPrivate::~QXmlStreamReaderPrivate() #endif free(sym_stack); free(state_stack); - delete entityParser; } @@ -1582,6 +1584,7 @@ QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix) */ void QXmlStreamReaderPrivate::resolveTag() { + const auto attributeStackCleaner = qScopeGuard([this](){ attributeStack.clear(); }); int n = attributeStack.size(); if (namespaceProcessing) { @@ -1649,7 +1652,10 @@ void QXmlStreamReaderPrivate::resolveTag() if (attributes[j].name() == attribute.name() && attributes[j].namespaceUri() == attribute.namespaceUri() && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName())) + { raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName())); + return; + } } } @@ -1680,8 +1686,6 @@ void QXmlStreamReaderPrivate::resolveTag() attribute.m_isDefault = true; attributes.append(attribute); } - - attributeStack.clear(); } void QXmlStreamReaderPrivate::resolvePublicNamespaces() diff --git a/src/corelib/serialization/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h index cde66a48a3..9c94e6d434 100644 --- a/src/corelib/serialization/qxmlstream_p.h +++ b/src/corelib/serialization/qxmlstream_p.h @@ -981,7 +981,7 @@ public: QString resolveUndeclaredEntity(const QString &name); void parseEntity(const QString &value); - QXmlStreamReaderPrivate *entityParser; + std::unique_ptr<QXmlStreamReaderPrivate> entityParser; bool scanAfterLangleBang(); bool scanPublicOrSystem(); diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index fb45b82967..6dbec8ba33 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -734,23 +734,23 @@ static void updateSystemPrivate() globalLocaleData.m_script_id = res.toInt(); res = sys_locale->query(QSystemLocale::DecimalPoint, QVariant()); - if (!res.isNull()) + if (!res.isNull() && !res.toString().isEmpty()) globalLocaleData.m_decimal = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant()); - if (!res.isNull()) + if (!res.isNull() && !res.toString().isEmpty()) globalLocaleData.m_group = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant()); - if (!res.isNull()) + if (!res.isNull() && !res.toString().isEmpty()) globalLocaleData.m_zero = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::NegativeSign, QVariant()); - if (!res.isNull()) + if (!res.isNull() && !res.toString().isEmpty()) globalLocaleData.m_minus = res.toString().at(0).unicode(); res = sys_locale->query(QSystemLocale::PositiveSign, QVariant()); - if (!res.isNull()) + if (!res.isNull() && !res.toString().isEmpty()) globalLocaleData.m_plus = res.toString().at(0).unicode(); } #endif // !QT_NO_SYSTEMLOCALE @@ -4463,6 +4463,8 @@ QStringList QLocale::uiLanguages() const for (const auto entry : qAsConst(uiLanguages)) locales.append(QLocale(entry)); } + if (locales.isEmpty()) + locales.append(systemLocale()->fallbackUiLocale()); } else #endif { diff --git a/src/corelib/text/text.pri b/src/corelib/text/text.pri index 25e281f37a..d2a02059c7 100644 --- a/src/corelib/text/text.pri +++ b/src/corelib/text/text.pri @@ -48,7 +48,7 @@ SOURCES += \ NO_PCH_SOURCES += text/qstring_compat.cpp false: SOURCES += $$NO_PCH_SOURCES # Hack for QtCreator -!nacl:macos: { +!nacl:darwin: { SOURCES += text/qlocale_mac.mm } else:unix { diff --git a/src/gui/doc/src/richtext.qdoc b/src/gui/doc/src/richtext.qdoc index 24fd4240b3..31a2ebf05b 100644 --- a/src/gui/doc/src/richtext.qdoc +++ b/src/gui/doc/src/richtext.qdoc @@ -1269,6 +1269,55 @@ \row \li \c word-spacing \li <width>px \li Specifies an alternate spacing between each word. + \row \li \c line-height + \li <number>[% | px | pt | cm] + \li Specifies the height of a line. It can be one of the + following: + \list + \li fixed line height in pixels, points, or centimeters. + \li a percentage of the current font size. + \endlist + \endtable + + \section1 Qt-specific CSS properties + + Besides the standard CSS properties listed earlier, the following + Qt-specific properties can also be used to style a text block: + + \table + \header \li Property + \li Values + \li Description + \row + \li \c -qt-block-indent + \li \c <number> + \li Indents the text block by the specified no. spaces. + \row + \li \c -qt-list-indent + \li \c <number> + \li Indents the list items by the specified no. of spaces. + \row + \li \c -qt-list-number-prefix + \li \c <string> + \li Prefixes the given string to list number in an HTML ordered list. + \row + \li \c -qt-list-number-suffix + \li <string> + \li Suffixes the given string to list number in an HTML ordered list. + \row + \li \c -qt-paragraph-type + \li \c empty + \li Hides the text block. + \row + \li \c -qt-table-type + \li \c{root | frame} + \li \c root renders the text blocks inline without borders and + indentation, whereas \c frame renders them on a new line + with a frame around. + \row + \li \c -qt-user-state + \li \c <number> + \li Adds it as user data for the text block. \endtable \section1 Supported CSS Selectors diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 251f09fe52..49f9550519 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -916,6 +916,9 @@ bool QPNGImageWriter::writeImage(const QImage& image, int compression_in, const } png_set_error_fn(png_ptr, nullptr, nullptr, qt_png_warning); +#ifdef PNG_BENIGN_ERRORS_SUPPORTED + png_set_benign_errors(png_ptr, 1); +#endif info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 04970a942b..3c6f35bb6d 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -1150,8 +1150,8 @@ QKeyEvent::~QKeyEvent() Note: The native scan code may be 0, even if the key event contains extended information. - Note: On Mac OS/X, this function is not useful, because there is no - way to get the scan code from Carbon or Cocoa. The function always + Note: On \macos, this function is not useful, because there is no + way to get the scan code from the system APIs. The function always returns 1 (or 0 in the case explained above). */ diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index fd2644717e..1c7800358f 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -900,7 +900,7 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) uenv.venv = nullptr; m_javaVM = nullptr; - if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) { + if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_6) != JNI_OK) { __android_log_print(ANDROID_LOG_FATAL, "Qt", "GetEnv failed"); return -1; } @@ -922,5 +922,5 @@ Q_DECL_EXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void */*reserved*/) if (threadSetter.thread()) threadSetter.thread()->setObjectName("QtMainLoopThread"); __android_log_print(ANDROID_LOG_INFO, "Qt", "qt started"); - return JNI_VERSION_1_4; + return JNI_VERSION_1_6; } diff --git a/src/plugins/platforms/wasm/qwasmclipboard.cpp b/src/plugins/platforms/wasm/qwasmclipboard.cpp index fb46f1534f..f02c2c6ccb 100644 --- a/src/plugins/platforms/wasm/qwasmclipboard.cpp +++ b/src/plugins/platforms/wasm/qwasmclipboard.cpp @@ -29,6 +29,7 @@ #include "qwasmclipboard.h" #include "qwasmwindow.h" +#include "qwasmstring.h" #include <emscripten.h> #include <emscripten/html5.h> @@ -40,22 +41,22 @@ using namespace emscripten; // there has got to be a better way... -static QByteArray g_clipboardArray; -static QByteArray g_clipboardFormat; +static QString g_clipboardText; +static QString g_clipboardFormat; static val getClipboardData() { - return val(g_clipboardArray.constData()); + return QWasmString::fromQString(g_clipboardText); } static val getClipboardFormat() { - return val(g_clipboardFormat.constData()); + return QWasmString::fromQString(g_clipboardFormat); } static void pasteClipboardData(emscripten::val format, emscripten::val dataPtr) { - QString formatString = QString::fromStdString(format.as<std::string>()); + QString formatString = QWasmString::toQString(format); QByteArray dataArray = QByteArray::fromStdString(dataPtr.as<std::string>()); QMimeData *mMimeData = new QMimeData; mMimeData->setData(formatString, dataArray); @@ -102,11 +103,10 @@ static void qClipboardPasteTo(val event) bool hasClipboardApi = QWasmIntegration::get()->getWasmClipboard()->hasClipboardApi; val clipdata = hasClipboardApi ? val::global("Module").call<val>("qtGetClipboardData") : - event["clipboardData"].call<val>("getData", std::string("text")); + event["clipboardData"].call<val>("getData", val("text")); - const std::string data = clipdata.as<std::string>(); - if (data.length() > 0) { - QString qstr = QString::fromStdString(data); + const QString qstr = QWasmString::toQString(clipdata); + if (qstr.length() > 0) { QMimeData *mMimeData = new QMimeData; mMimeData->setText(qstr); QWasmClipboard::qWasmClipboardPaste(mMimeData); @@ -133,7 +133,7 @@ QWasmClipboard::QWasmClipboard() QWasmClipboard::~QWasmClipboard() { - g_clipboardArray.clear(); + g_clipboardText.clear(); g_clipboardFormat.clear(); } @@ -148,11 +148,11 @@ QMimeData* QWasmClipboard::mimeData(QClipboard::Mode mode) void QWasmClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode) { if (mimeData->hasText()) { - g_clipboardFormat = mimeData->formats().at(0).toUtf8(); - g_clipboardArray = mimeData->text().toUtf8(); + g_clipboardFormat = mimeData->formats().at(0); + g_clipboardText = mimeData->text(); } else if (mimeData->hasHtml()) { - g_clipboardFormat =mimeData->formats().at(0).toUtf8(); - g_clipboardArray = mimeData->html().toUtf8(); + g_clipboardFormat = mimeData->formats().at(0); + g_clipboardText = mimeData->html(); } QPlatformClipboard::setMimeData(mimeData, mode); @@ -199,13 +199,13 @@ void QWasmClipboard::installEventHandlers(const QString &canvasId) // Fallback path for browsers which do not support direct clipboard access val document = val::global("document"); - val canvas = document.call<val>("getElementById", val(canvasId.toUtf8().constData())); + val canvas = document.call<val>("getElementById", QWasmString::fromQString(canvasId)); - canvas.call<void>("addEventListener", std::string("cut"), + canvas.call<void>("addEventListener", val("cut"), val::module_property("qtClipboardCutTo")); - canvas.call<void>("addEventListener", std::string("copy"), + canvas.call<void>("addEventListener", val("copy"), val::module_property("qtClipboardCopyTo")); - canvas.call<void>("addEventListener", std::string("paste"), + canvas.call<void>("addEventListener", val("paste"), val::module_property("qtClipboardPasteTo")); } @@ -226,6 +226,6 @@ void QWasmClipboard::writeTextToClipboard() val txt = module.call<val>("qtGetClipboardData"); val format = module.call<val>("qtGetClipboardFormat"); val navigator = val::global("navigator"); - navigator["clipboard"].call<void>("writeText", txt.as<std::string>()); + navigator["clipboard"].call<void>("writeText", txt); } } diff --git a/src/plugins/platforms/wasm/qwasmcursor.cpp b/src/plugins/platforms/wasm/qwasmcursor.cpp index c04fa6441a..616456b2fa 100644 --- a/src/plugins/platforms/wasm/qwasmcursor.cpp +++ b/src/plugins/platforms/wasm/qwasmcursor.cpp @@ -29,6 +29,7 @@ #include "qwasmcursor.h" #include "qwasmscreen.h" +#include "qwasmstring.h" #include <QtCore/qdebug.h> #include <QtGui/qwindow.h> @@ -56,11 +57,11 @@ void QWasmCursor::changeCursor(QCursor *windowCursor, QWindow *window) htmlCursorName = "auto"; // Set cursor on the canvas - QByteArray canvasId = QWasmScreen::get(screen)->canvasId().toUtf8(); + val jsCanvasId = QWasmString::fromQString(QWasmScreen::get(screen)->canvasId()); val document = val::global("document"); - val canvas = document.call<val>("getElementById", val(canvasId.constData())); + val canvas = document.call<val>("getElementById", jsCanvasId); val canvasStyle = canvas["style"]; - canvasStyle.set("cursor", emscripten::val(htmlCursorName.constData())); + canvasStyle.set("cursor", val(htmlCursorName.constData())); } QByteArray QWasmCursor::cursorShapeToHtml(Qt::CursorShape shape) diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp index d6ea147ccf..d99c202c48 100644 --- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp +++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp @@ -32,6 +32,7 @@ #include "qwasmcompositor.h" #include "qwasmintegration.h" #include "qwasmclipboard.h" +#include "qwasmstring.h" #include <QtGui/qevent.h> #include <qpa/qwindowsysteminterface.h> @@ -355,9 +356,10 @@ void QWasmEventTranslator::initEventHandlers() if (emscripten::val::global("window")["safari"].isUndefined()) { val document = val::global("document"); - val canvas = document.call<val>("getElementById", val(canvasId)); + val jsCanvasId = QWasmString::fromQString(screen()->canvasId()); + val canvas = document.call<val>("getElementById", jsCanvasId); canvas.call<void>("addEventListener", - std::string("wheel"), + val("wheel"), val::module_property("qtMouseWheelEvent")); } } diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp index 1e9f68027c..fd53cd0bae 100644 --- a/src/plugins/platforms/wasm/qwasmintegration.cpp +++ b/src/plugins/platforms/wasm/qwasmintegration.cpp @@ -36,6 +36,7 @@ #include "qwasmclipboard.h" #include "qwasmservices.h" #include "qwasmoffscreensurface.h" +#include "qwasmstring.h" #include "qwasmwindow.h" #ifndef QT_NO_OPENGL @@ -67,19 +68,19 @@ static void browserBeforeUnload(emscripten::val) static void addCanvasElement(emscripten::val canvas) { - QString canvasId = QString::fromStdString(canvas["id"].as<std::string>()); + QString canvasId = QWasmString::toQString(canvas["id"]); QWasmIntegration::get()->addScreen(canvasId); } static void removeCanvasElement(emscripten::val canvas) { - QString canvasId = QString::fromStdString(canvas["id"].as<std::string>()); + QString canvasId = QWasmString::toQString(canvas["id"]); QWasmIntegration::get()->removeScreen(canvasId); } static void resizeCanvasElement(emscripten::val canvas) { - QString canvasId = QString::fromStdString(canvas["id"].as<std::string>()); + QString canvasId = QWasmString::toQString(canvas["id"]); QWasmIntegration::get()->resizeScreen(canvasId); } @@ -115,11 +116,11 @@ QWasmIntegration::QWasmIntegration() int screenCount = qtCanvaseElements["length"].as<int>(); for (int i = 0; i < screenCount; ++i) { emscripten::val canvas = qtCanvaseElements[i].as<emscripten::val>(); - QString canvasId = QString::fromStdString(canvas["id"].as<std::string>()); + QString canvasId = QWasmString::toQString(canvas["id"]); addScreen(canvasId); } } else if (!canvas.isUndefined()){ - QString canvasId = QString::fromStdString(canvas["id"].as<std::string>()); + QString canvasId = QWasmString::toQString(canvas["id"]); addScreen(canvasId); } diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index d50765e3fb..5e6f94b9ed 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -32,6 +32,8 @@ #include "qwasmeventtranslator.h" #include "qwasmcompositor.h" #include "qwasmintegration.h" +#include "qwasmstring.h" + #include <emscripten/bind.h> #include <emscripten/val.h> @@ -186,7 +188,7 @@ void QWasmScreen::updateQScreenAndCanvasRenderSize() QSizeF canvasSize = cssSize * devicePixelRatio(); val document = val::global("document"); - val canvas = document.call<val>("getElementById", val(canvasId.constData())); + val canvas = document.call<val>("getElementById", QWasmString::fromQString(m_canvasId)); canvas.set("width", canvasSize.width()); canvas.set("height", canvasSize.height()); diff --git a/src/plugins/platforms/wasm/qwasmservices.cpp b/src/plugins/platforms/wasm/qwasmservices.cpp index 9328b8c065..4eee3fe972 100644 --- a/src/plugins/platforms/wasm/qwasmservices.cpp +++ b/src/plugins/platforms/wasm/qwasmservices.cpp @@ -28,6 +28,8 @@ ****************************************************************************/ #include "qwasmservices.h" +#include "qwasmstring.h" + #include <QtCore/QUrl> #include <QtCore/QDebug> @@ -37,8 +39,8 @@ QT_BEGIN_NAMESPACE bool QWasmServices::openUrl(const QUrl &url) { - QByteArray utf8Url = url.toString().toUtf8(); - emscripten::val::global("window").call<void>("open", emscripten::val(utf8Url.constData()), emscripten::val("_blank")); + emscripten::val jsUrl = QWasmString::fromQString(url.toString()); + emscripten::val::global("window").call<void>("open", jsUrl, emscripten::val("_blank")); return true; } diff --git a/src/plugins/platforms/wasm/qwasmstring.cpp b/src/plugins/platforms/wasm/qwasmstring.cpp new file mode 100644 index 0000000000..05b571c459 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmstring.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwasmstring.h" + +QT_BEGIN_NAMESPACE + +using namespace emscripten; + +val QWasmString::fromQString(const QString &str) +{ + static const val UTF16ToString( + val::global("Module")["UTF16ToString"]); + + auto ptr = quintptr(str.utf16()); + return UTF16ToString(val(ptr)); +} + +QString QWasmString::toQString(const val &v) +{ + QString result; + if (!v.isString()) + return result; + + static const val stringToUTF16( + val::global("Module")["stringToUTF16"]); + static const val length("length"); + + result.resize(v[length].as<int>()); + auto ptr = quintptr(result.utf16()); + stringToUTF16(v, val(ptr)); + return result; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wasm/qwasmstring.h b/src/plugins/platforms/wasm/qwasmstring.h new file mode 100644 index 0000000000..de5da92830 --- /dev/null +++ b/src/plugins/platforms/wasm/qwasmstring.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 or (at your option) any later version +** approved by the KDE Free Qt Foundation. The licenses are as published by +** the Free Software Foundation and appearing in the file LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once + +#include <qstring.h> + +#include <emscripten/val.h> + +QT_BEGIN_NAMESPACE + +class QWasmString +{ +public: + static emscripten::val fromQString(const QString &str); + static QString toQString(const emscripten::val &v); +}; +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro index f8c8175525..a12ae06833 100644 --- a/src/plugins/platforms/wasm/wasm.pro +++ b/src/plugins/platforms/wasm/wasm.pro @@ -23,7 +23,8 @@ SOURCES = \ qwasmtheme.cpp \ qwasmclipboard.cpp \ qwasmservices.cpp \ - qwasmoffscreensurface.cpp + qwasmoffscreensurface.cpp \ + qwasmstring.cpp HEADERS = \ qwasmintegration.h \ @@ -39,7 +40,8 @@ HEADERS = \ qwasmtheme.h \ qwasmclipboard.h \ qwasmservices.h \ - qwasmoffscreensurface.h + qwasmoffscreensurface.h \ + qwasmstring.h wasmfonts.files = \ ../../../3rdparty/wasm/Vera.ttf \ diff --git a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp index bba0487452..a45b5f409a 100644 --- a/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp +++ b/src/sql/doc/snippets/sqldatabase/sqldatabase.cpp @@ -249,16 +249,15 @@ void QSqlQueryModel_snippets() } //! [21] - QSqlTableModel model; - model.setTable("employee"); - model.select(); + QSqlQueryModel model; + model.setQuery("SELECT name, salary FROM employee"); int salary = model.record(4).value("salary").toInt(); //! [21] Q_UNUSED(salary); { //! [22] - int salary = model.data(model.index(4, 2)).toInt(); + int salary = model.data(model.index(4, 1)).toInt(); //! [22] Q_UNUSED(salary); } @@ -308,7 +307,8 @@ void QSqlTableModel_snippets() //! [25] QSqlTableModel model; model.setTable("employee"); - QString name = model.record(4).value("name").toString(); + model.select(); + int salary = model.record(4).value("salary").toInt(); //! [25] } } diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index c0b1061c6b..31d0ec985d 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -124,8 +124,8 @@ int QSqlQueryModelPrivate::columnInQuery(int modelColumn) const \snippet sqldatabase/sqldatabase.cpp 21 The code snippet above extracts the \c salary field from record 4 in - the result set of the query \c{SELECT * from employee}. Assuming - that \c salary is column 2, we can rewrite the last line as follows: + the result set of the \c SELECT query. Since \c salary is the 2nd + column (or column index 1), we can rewrite the last line as follows: \snippet sqldatabase/sqldatabase.cpp 22 diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 4b29492134..7d2421d34e 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -222,7 +222,7 @@ bool QSqlTableModelPrivate::exec(const QString &stmt, bool prepStatement, QSqlTableModel can also be used to access a database programmatically, without binding it to a view: - \snippet sqldatabase/sqldatabase.cpp 21 + \snippet sqldatabase/sqldatabase.cpp 25 The code snippet above extracts the \c salary field from record 4 in the result set of the query \c{SELECT * from employee}. diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc index 35bad6786a..50f626e7a6 100644 --- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc @@ -2543,6 +2543,18 @@ See also \l{#height-prop}{height}. + \row + \li \b -qt-background-role + \li \l{#paletterole}{PaletteRole} + \li The \c{background-color} for the subcontrol or widget based on the + chosen role. + + \row + \li \b -qt-style-features + \li \c list + \li The list of CSS properties that you want to apply Qt-specific styles on. + + \note The \c list can only include properties that are not pixmap-based. \endtable \target list of icons diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 68f6b72d20..129569a466 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -2124,7 +2124,8 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool && !(!next && focusProxy && test->isAncestorOf(focusProxy)) && test->isVisibleTo(toplevel) && test->isEnabled() && !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test)) - && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))) { + && (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test)) + && f != focusProxy) { w = test; if (seenWindow) focusWidgetAfterWindow = true; diff --git a/src/widgets/widgets/qscrollarea.cpp b/src/widgets/widgets/qscrollarea.cpp index ce08e3439a..f7a4f8e446 100644 --- a/src/widgets/widgets/qscrollarea.cpp +++ b/src/widgets/widgets/qscrollarea.cpp @@ -490,14 +490,14 @@ void QScrollArea::ensureWidgetVisible(QWidget *childWidget, int xmargin, int yma if (focusRect.width() > visibleRect.width()) d->hbar->setValue(focusRect.center().x() - d->viewport->width() / 2); else if (focusRect.right() > visibleRect.right()) - d->hbar->setValue(focusRect.right() - d->viewport->width()); + d->hbar->setValue(focusRect.right() - d->viewport->width() + 1); else if (focusRect.left() < visibleRect.left()) d->hbar->setValue(focusRect.left()); if (focusRect.height() > visibleRect.height()) d->vbar->setValue(focusRect.center().y() - d->viewport->height() / 2); else if (focusRect.bottom() > visibleRect.bottom()) - d->vbar->setValue(focusRect.bottom() - d->viewport->height()); + d->vbar->setValue(focusRect.bottom() - d->viewport->height() + 1); else if (focusRect.top() < visibleRect.top()) d->vbar->setValue(focusRect.top()); } diff --git a/src/widgets/widgets/qspinbox.cpp b/src/widgets/widgets/qspinbox.cpp index 08428f673e..cbd600ec6c 100644 --- a/src/widgets/widgets/qspinbox.cpp +++ b/src/widgets/widgets/qspinbox.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2020 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -1168,11 +1168,11 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, } else { num = locale.toInt(copy, &ok); if (!ok && (max >= 1000 || min <= -1000)) { - const QChar sep = locale.groupSeparator(); - const QChar doubleSep[2] = {sep, sep}; - if (copy.contains(sep) && !copy.contains(QString(doubleSep, 2))) { + const QString sep(locale.groupSeparator()); + const QString doubleSep = sep + sep; + if (copy.contains(sep) && !copy.contains(doubleSep)) { QString copy2 = copy; - copy2.remove(locale.groupSeparator()); + copy2.remove(sep); num = locale.toInt(copy2, &ok); } } @@ -1314,6 +1314,10 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, const bool plus = max >= 0; const bool minus = min <= 0; + const QString group(locale.groupSeparator()); + const uint groupUcs = (group.size() > 1 && group.at(0).isHighSurrogate() + ? QChar::surrogateToUcs4(group.at(0), group.at(1)) + : group.at(0).unicode()); switch (len) { case 0: state = max != min ? QValidator::Intermediate : QValidator::Invalid; @@ -1360,14 +1364,15 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, } } } else { - const QChar last = copy.at(len - 1); - const QChar secondLast = copy.at(len - 2); - if ((last == locale.groupSeparator() || last.isSpace()) - && (secondLast == locale.groupSeparator() || secondLast.isSpace())) { + const QChar last = copy.back(); + const bool groupEnd = copy.endsWith(group); + const QStringView head(copy.constData(), groupEnd ? len - group.size() : len - 1); + const QChar secondLast = head.back(); + if ((groupEnd || last.isSpace()) && (head.endsWith(group) || secondLast.isSpace())) { state = QValidator::Invalid; QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; goto end; - } else if (last.isSpace() && (!locale.groupSeparator().isSpace() || secondLast.isSpace())) { + } else if (last.isSpace() && (!QChar::isSpace(groupUcs) || secondLast.isSpace())) { state = QValidator::Invalid; QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; goto end; @@ -1381,26 +1386,31 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos, QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok; if (!ok) { - if (locale.groupSeparator().isPrint()) { - if (max < 1000 && min > -1000 && copy.contains(locale.groupSeparator())) { + if (QChar::isPrint(groupUcs)) { + if (max < 1000 && min > -1000 && copy.contains(group)) { state = QValidator::Invalid; QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; goto end; } const int len = copy.size(); - for (int i=0; i<len- 1; ++i) { - if (copy.at(i) == locale.groupSeparator() && copy.at(i + 1) == locale.groupSeparator()) { - QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; - state = QValidator::Invalid; - goto end; + for (int i = 0; i < len - 1;) { + if (QStringView(copy).mid(i).startsWith(group)) { + if (QStringView(copy).mid(i + group.size()).startsWith(group)) { + QSBDEBUG() << __FILE__ << __LINE__<< "state is set to Invalid"; + state = QValidator::Invalid; + goto end; + } + i += group.size(); + } else { + i++; } } QString copy2 = copy; - copy2.remove(locale.groupSeparator()); + copy2.remove(group); num = locale.toDouble(copy2, &ok); - QSBDEBUG() << locale.groupSeparator() << num << copy2 << ok; + QSBDEBUG() << group << num << copy2 << ok; if (!ok) { state = QValidator::Invalid; |