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:
commit
502447e15b
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -450,6 +450,8 @@ protected:
|
|||
Qt::MouseButton m_button = Qt::NoButton;
|
||||
Qt::MouseButtons m_pressedButtons;
|
||||
|
||||
friend class QQuickWindowPrivate;
|
||||
|
||||
Q_DISABLE_COPY(QQuickPointerEvent)
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
|
|
|
@ -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!
|
||||
|
|
Loading…
Reference in New Issue