Merge remote-tracking branch 'origin/5.11' into 5.12.0

Conflicts:
	src/imports/settings/qqmlsettings.cpp
	src/quick/items/qquickwindow.cpp
	tools/qmlplugindump/main.cpp

Change-Id: I3e5dae4de25b2da961a572b3a4bd151181d211c9
This commit is contained in:
Liang Qi 2018-10-30 09:43:14 +01:00
commit 502447e15b
12 changed files with 232 additions and 38 deletions

View File

@ -74,10 +74,14 @@
false, the item's size will be fixed to its preferred size. Otherwise, it will grow or shrink
between its minimum and maximum size as the layout is resized.
\note It is not recommended to have bindings to the x, y, width, or height properties of items
in a layout, since this would conflict with the goals of Layout, and can also cause binding
loops.
\note Do not bind to the x, y, width, or height properties of items in a layout,
as this would conflict with the goals of Layout, and can also cause binding loops.
The width and height properties are used by the layout engine to store the current
size of items as calculated from the minimum/preferred/maximum attached properties,
and can be ovewritten each time the items are laid out. Use
\l {Layout::preferredWidth}{Layout.preferredWidth} and
\l {Layout::preferredHeight}{Layout.preferredHeight}, or \l {Item::}{implicitWidth}
and \l {Item::}{implicitHeight} to specify the preferred size of items.
\sa GridLayout
\sa RowLayout

View File

@ -39,10 +39,12 @@
#include "qqmlsettings_p.h"
#include <qcoreevent.h>
#include <qcoreapplication.h>
#include <qloggingcategory.h>
#include <qsettings.h>
#include <qpointer.h>
#include <qjsvalue.h>
#include <qqmlinfo.h>
#include <qdebug.h>
#include <qhash.h>
@ -271,6 +273,26 @@ QSettings *QQmlSettingsPrivate::instance() const
if (!settings) {
QQmlSettings *q = const_cast<QQmlSettings*>(q_func());
settings = fileName.isEmpty() ? new QSettings(q) : new QSettings(fileName, QSettings::IniFormat, q);
if (settings->status() != QSettings::NoError) {
// TODO: can't print out the enum due to the following error:
// error: C2666: 'QQmlInfo::operator <<': 15 overloads have similar conversions
qmlWarning(q) << "Failed to initialize QSettings instance. Status code is: " << int(settings->status());
if (settings->status() == QSettings::AccessError) {
QVector<QString> missingIdentifiers;
if (QCoreApplication::organizationName().isEmpty())
missingIdentifiers.append(QLatin1String("organizationName"));
if (QCoreApplication::organizationDomain().isEmpty())
missingIdentifiers.append(QLatin1String("organizationDomain"));
if (QCoreApplication::applicationName().isEmpty())
missingIdentifiers.append(QLatin1String("applicationName"));
if (!missingIdentifiers.isEmpty())
qmlWarning(q) << "The following application identifiers have not been set: " << missingIdentifiers;
}
return settings;
}
if (!category.isEmpty())
settings->beginGroup(category);
if (initialized)

View File

@ -462,6 +462,8 @@ Unlike an ordinary property, an alias has the following restrictions:
\li The \e {alias reference} is not optional,
unlike the optional default value for an ordinary property; the alias reference
must be provided when the alias is first declared.
\li It cannot refer to \l {Attached Properties and Attached Signal Handlers}
{attached properties}.
\li It cannot refer to grouped properties; the following code will not work:
\code
property alias color: rectangle.border.color

View File

@ -205,14 +205,16 @@ QAccessible::Role QAccessibleQuickItem::role() const
// Workaround for setAccessibleRole() not working for
// Text items. Text items are special since they are defined
// entirely from C++ (setting the role from QML works.)
if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
return QAccessible::StaticText;
QAccessible::Role role = QAccessible::NoRole;
if (item())
role = QQuickItemPrivate::get(item())->accessibleRole();
if (role == QAccessible::NoRole)
role = QAccessible::Client;
if (role == QAccessible::NoRole) {
if (qobject_cast<QQuickText*>(const_cast<QQuickItem *>(item())))
role = QAccessible::StaticText;
else
role = QAccessible::Client;
}
return role;
}

View File

@ -450,6 +450,8 @@ protected:
Qt::MouseButton m_button = Qt::NoButton;
Qt::MouseButtons m_pressedButtons;
friend class QQuickWindowPrivate;
Q_DISABLE_COPY(QQuickPointerEvent)
};

View File

@ -2548,6 +2548,10 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
}
for (QQuickItem *item : targetItems) {
if (!event->m_event) {
qWarning("event went missing during delivery! (nested sendEvent() is not allowed)");
break;
}
hasFiltered.clear();
if (!handlersOnly && sendFilteredPointerEvent(event, item)) {
if (event->isAccepted()) {
@ -2562,6 +2566,10 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event,
// nor to any item which already had a chance to filter.
if (skipDelivery.contains(item))
continue;
if (!event->m_event) {
qWarning("event went missing during delivery! (nested sendEvent() is not allowed)");
break;
}
deliverMatchingPointsToItem(item, event, handlersOnly);
if (event->allPointsAccepted())
handlersOnly = true;

View File

@ -230,6 +230,9 @@ QSGGeometry *QSGBasicInternalImageNode::updateGeometry(const QRectF &targetRect,
++vCells;
if (innerTargetRect.bottom() != targetRect.bottom())
++vCells;
if (hCells * vCells * 4 >= 0x10000)
qWarning("QTBUG-58924 - Too many tiles in QSGInternalImageNode, rendering will be partially missing.");
QVarLengthArray<X, 32> xData(2 * hCells);
QVarLengthArray<Y, 32> yData(2 * vCells);
X *xs = xData.data();

View File

@ -53,6 +53,7 @@ private slots:
void categories();
void siblings();
void initial();
void noApplicationIdentifiersSet();
};
// ### Replace keyValueMap("foo", "bar") with QVariantMap({{"foo", "bar"}})
@ -147,10 +148,6 @@ void tst_QQmlSettings::initTestCase()
{
QQmlDataTest::initTestCase();
QCoreApplication::setApplicationName("tst_QQmlSettings");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setOrganizationDomain("qt-project.org");
qmlRegisterType<CppObject>("Qt.test", 1, 0, "CppObject");
}
@ -158,6 +155,10 @@ void tst_QQmlSettings::init()
{
QSettings settings;
settings.clear();
QCoreApplication::setApplicationName("tst_QQmlSettings");
QCoreApplication::setOrganizationName("QtProject");
QCoreApplication::setOrganizationDomain("qt-project.org");
}
void tst_QQmlSettings::cleanup()
@ -481,6 +482,31 @@ void tst_QQmlSettings::initial()
QCOMPARE(settings->property("value").toString(), QStringLiteral("initial"));
}
void tst_QQmlSettings::noApplicationIdentifiersSet()
{
#ifdef Q_OS_MACOS
QSKIP("macOS doesn't complain about empty application identifiers");
#endif
QCoreApplication::setApplicationName(QString());
QCoreApplication::setOrganizationName(QString());
QCoreApplication::setOrganizationDomain(QString());
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*QML Settings: Failed to initialize QSettings instance. Status code is: 1"));
// Can't set an empty applicationName because QCoreApplication won't allow it, which is why it's not listed here.
QTest::ignoreMessage(QtWarningMsg, QRegularExpression(".*QML Settings: The following application identifiers have not been set: QVector\\(\"organizationName\", \"organizationDomain\"\\)"));
QQmlEngine engine;
QQmlComponent component(&engine, testFileUrl("basic.qml"));
QScopedPointer<QObject> root(component.create());
QVERIFY(root.data());
// The value of the QML property will be true because it defaults to it...
QVERIFY(root->property("success").toBool());
QSettings settings;
// ... but the settings' value should be false because it was never loaded.
QVERIFY(!settings.value("success").toBool());
}
QTEST_MAIN(tst_QQmlSettings)
#include "tst_qqmlsettings.moc"

View File

@ -42,9 +42,11 @@
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlproperty.h>
#include <QtQuick/private/qquickaccessibleattached_p.h>
#include <QtQuick/private/qquicklistview_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include "../../shared/util.h"
#include "../shared/visualtestutil.h"
#define EXPECT(cond) \
do { \
@ -224,6 +226,72 @@ void tst_QQuickAccessible::quickAttachedProperties()
}
delete object;
}
// Check overriding of attached role for Text
{
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nText {\n"
"Accessible.role: Accessible.Button\n"
"Accessible.name: \"TextButton\"\n"
"Accessible.description: \"Text Button\"\n"
"}", QUrl());
QObject *object = component.create();
QVERIFY(object != nullptr);
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(object);
QVERIFY(attachedObject);
if (attachedObject) {
QVariant p = attachedObject->property("role");
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toInt(), int(QAccessible::PushButton));
p = attachedObject->property("name");
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toString(), QLatin1String("TextButton"));
p = attachedObject->property("description");
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toString(), QLatin1String("Text Button"));
}
delete object;
}
// Check overriding of attached role for Text
{
QQmlEngine engine;
QQmlComponent component(&engine);
component.setData("import QtQuick 2.0\nListView {\n"
"id: list\n"
"model: 5\n"
"delegate: Text {\n"
"objectName: \"acc_text\"\n"
"Accessible.role: Accessible.Button\n"
"Accessible.name: \"TextButton\"\n"
"Accessible.description: \"Text Button\"\n"
"}\n"
"}", QUrl());
QObject *object = component.create();
QVERIFY(object != nullptr);
QQuickListView *listview = qobject_cast<QQuickListView *>(object);
QVERIFY(listview != nullptr);
QQuickItem *contentItem = listview->contentItem();
QQuickText *childItem = QQuickVisualTestUtil::findItem<QQuickText>(contentItem, "acc_text");
QVERIFY(childItem != nullptr);
QObject *attachedObject = QQuickAccessibleAttached::attachedProperties(childItem);
QVERIFY(attachedObject);
if (attachedObject) {
QVariant p = attachedObject->property("role");
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toInt(), int(QAccessible::PushButton));
p = attachedObject->property("name");
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toString(), QLatin1String("TextButton"));
p = attachedObject->property("description");
QCOMPARE(p.isNull(), false);
QCOMPARE(p.toString(), QLatin1String("Text Button"));
}
delete object;
}
QTestAccessibility::clearEvents();
}

View File

@ -0,0 +1,49 @@
import QtQuick 2.11
import QtQuick.Window 2.11
import Test 1.0
Window {
id: window
visible: true
width: 200
height: 200
property EventSender sender: EventSender { }
Item {
width: 200
height: 200
MouseArea {
anchors.fill: parent
}
Item {
width: 200
height: 200
Rectangle {
width: 200
height: 100
color: "red"
MouseArea {
anchors.fill: parent
onPressed: sender.sendMouseClick(window, 50, 50)
}
}
Rectangle {
y: 100
width: 200
height: 100
color: "yellow"
MouseArea {
anchors.fill: parent
onPressed: sender.sendMouseClick(window, 50, 50)
}
}
}
}
}

View File

@ -98,6 +98,22 @@ private:
qreal m_radius;
};
class EventSender : public QObject {
Q_OBJECT
public:
Q_INVOKABLE void sendMouseClick(QObject* obj ,qreal x , qreal y) {
{
QMouseEvent event(QEvent::MouseButtonPress, QPointF(x , y), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
qApp->sendEvent(obj, &event);
}
{
QMouseEvent event(QEvent::MouseButtonRelease, QPointF(x , y), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
qApp->sendEvent(obj, &event);
}
}
};
class tst_QQuickMouseArea: public QQmlDataTest
{
Q_OBJECT
@ -106,6 +122,7 @@ public:
: device(nullptr)
{
qmlRegisterType<CircleMask>("Test", 1, 0, "CircleMask");
qmlRegisterType<EventSender>("Test", 1, 0, "EventSender");
}
private slots:
@ -165,6 +182,7 @@ private slots:
void pressOneAndTapAnother_data();
void pressOneAndTapAnother();
void mask();
void nestedEventDelivery();
private:
int startDragDistance() const {
@ -2298,6 +2316,21 @@ void tst_QQuickMouseArea::mask()
QCOMPARE(window.rootObject()->property("clicked").toInt(), 1);
}
void tst_QQuickMouseArea::nestedEventDelivery() // QTBUG-70898
{
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("nestedSendEvent.qml"));
QScopedPointer<QQuickWindow> window(qmlobject_cast<QQuickWindow *>(c.create()));
QVERIFY(window.data());
// Click each MouseArea and verify that it doesn't crash
QByteArray message = "event went missing during delivery! (nested sendEvent() is not allowed)";
QTest::ignoreMessage(QtWarningMsg, message);
QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50,50));
QTest::ignoreMessage(QtWarningMsg, message); // twice though, actually
QTest::mouseClick(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(50,150));
}
QTEST_MAIN(tst_QQuickMouseArea)
#include "tst_qquickmousearea.moc"

View File

@ -66,9 +66,6 @@
#include <QtGui/private/qsimulatorconnection_p.h>
#endif
#ifdef Q_OS_UNIX
#include <signal.h>
#endif
#ifdef Q_OS_WIN
# if !defined(Q_CC_MINGW)
# include <crtdbg.h>
@ -750,17 +747,6 @@ enum ExitCode {
EXIT_IMPORTERROR = 3
};
#ifdef Q_OS_UNIX
Q_NORETURN void sigSegvHandler(int) {
fprintf(stderr, "Error: SEGV\n");
if (!currentProperty.isEmpty())
fprintf(stderr, "While processing the property '%s', which probably has uninitialized data.\n", currentProperty.toLatin1().constData());
if (!inObjectInstantiation.isEmpty())
fprintf(stderr, "While instantiating the object '%s'.\n", inObjectInstantiation.toLatin1().constData());
exit(EXIT_SEGV);
}
#endif
void printUsage(const QString &appName)
{
std::cerr << qPrintable(QString(
@ -985,17 +971,6 @@ int main(int argc, char *argv[])
#endif // Q_OS_WIN && !Q_CC_MINGW
// The default message handler might not print to console on some systems. Enforce this.
qInstallMessageHandler(printDebugMessage);
#ifdef Q_OS_UNIX
// qmldump may crash, but we don't want any crash handlers to pop up
// therefore we intercept the segfault and just exit() ourselves
struct sigaction sigAction;
sigemptyset(&sigAction.sa_mask);
sigAction.sa_handler = &sigSegvHandler;
sigAction.sa_flags = 0;
sigaction(SIGSEGV, &sigAction, nullptr);
#endif
#ifdef QT_SIMULATOR
// Running this application would bring up the Qt Simulator (since it links Qt GUI), avoid that!