summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp7
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp17
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp151
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp5
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp20
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp15
-rw-r--r--src/corelib/doc/src/animation.qdoc20
-rw-r--r--src/corelib/io/qdirlisting.cpp18
-rw-r--r--src/corelib/kernel/qmetaobject.cpp42
-rw-r--r--src/corelib/kernel/qobject.cpp154
-rw-r--r--src/corelib/kernel/qobject_p.h60
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp4
-rw-r--r--src/widgets/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp6
13 files changed, 361 insertions, 158 deletions
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
index b4c6b6ff8a6..73ce8ca02c1 100644
--- a/src/corelib/animation/qpropertyanimation.cpp
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -21,7 +21,12 @@
makes it possible to animate many of Qt's widgets. Let's look at
an example:
- \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp includes
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp class_decl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp first_example
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp main
\note You can also control an animation's lifespan by choosing a
\l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting the
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
index 6328cb00119..db3a9ee2dc0 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qparallelanimationgroup.cpp
@@ -1,10 +1,15 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-//! [0]
- QParallelAnimationGroup *group = new QParallelAnimationGroup;
- group->addAnimation(anim1);
- group->addAnimation(anim2);
+#include <QParallelAnimationGroup>
- group->start();
-//! [0]
+void example(QAbstractAnimation *anim1, QAbstractAnimation *anim2)
+{
+ //! [0]
+ QParallelAnimationGroup *group = new QParallelAnimationGroup;
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+ //! [0]
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
index 4b77ab607db..7f259e99fb8 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qpropertyanimation.cpp
@@ -1,28 +1,102 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QParallelAnimationGroup>
+#include <QSequentialAnimationGroup>
-//! [0]
+//! [includes]
#include <QApplication>
#include <QPushButton>
#include <QPropertyAnimation>
+//![includes]
+
+//! [class_decl]
class MyButtonWidget : public QWidget
{
public:
MyButtonWidget(QWidget *parent = nullptr);
};
+//! [class_decl]
+
+//! [ctor_impl]
MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
{
- QPushButton *button = new QPushButton(tr("Animated Button"), this);
- QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
- anim->setDuration(10000);
- anim->setStartValue(QPoint(0, 0));
- anim->setEndValue(QPoint(100, 250));
- anim->start();
+//![ctor_impl]
+ {
+ //! [first_example]
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->start();
+ //! [first_example]
+ }
+
+ {
+ //! [easing-curve]
+ QPushButton *button = new QPushButton(tr("Animated Button"), this);
+ QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
+ anim->setDuration(10000);
+ anim->setStartValue(QPoint(0, 0));
+ anim->setEndValue(QPoint(100, 250));
+ anim->setEasingCurve(QEasingCurve::OutBounce);
+ anim->start();
+ //! [easing-curve]
+ }
+
+ {
+ //! [animation-group1]
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(100, 250));
+ anim2->setEndValue(QPoint(500, 500));
+
+ QParallelAnimationGroup *parallelAnim = new QParallelAnimationGroup;
+ parallelAnim->addAnimation(anim1);
+ parallelAnim->addAnimation(anim2);
+ parallelAnim->start();
+ //! [animation-group1]
+ }
+
+ {
+ //! [animation-group2]
+ QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
+ QPushButton *clyde = new QPushButton(tr("Clyde"), this);
+
+ QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
+ anim1->setDuration(3000);
+ anim1->setStartValue(QPoint(0, 0));
+ anim1->setEndValue(QPoint(100, 250));
+
+ QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
+ anim2->setDuration(3000);
+ anim2->setStartValue(QPoint(0, 0));
+ anim2->setEndValue(QPoint(200, 250));
+
+ QSequentialAnimationGroup *sequenceAnim = new QSequentialAnimationGroup;
+ sequenceAnim->addAnimation(anim1);
+ sequenceAnim->addAnimation(anim2);
+ sequenceAnim->start();
+ //! [animation-group2]
+ }
+
+//! [ctor_close]
}
+//! [ctor_close]
+
+//! [main]
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
@@ -31,65 +105,4 @@ int main(int argc, char *argv[])
buttonAnimWidget.show();
return a.exec();
}
-//! [0]
-
-
-//! [easing-curve]
-MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
-{
- QPushButton *button = new QPushButton(tr("Animated Button"), this);
- QPropertyAnimation *anim = new QPropertyAnimation(button, "pos", this);
- anim->setDuration(10000);
- anim->setStartValue(QPoint(0, 0));
- anim->setEndValue(QPoint(100, 250));
- anim->setEasingCurve(QEasingCurve::OutBounce);
- anim->start();
-}
-//! [easing-curve]
-
-
-//! [animation-group1]
-MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
-{
- QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
- QPushButton *clyde = new QPushButton(tr("Clyde"), this);
-
- QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
- anim1->setDuration(3000);
- anim1->setStartValue(QPoint(0, 0));
- anim1->setEndValue(QPoint(100, 250));
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
- anim2->setDuration(3000);
- anim2->setStartValue(QPoint(100, 250));
- anim2->setEndValue(QPoint(500, 500));
-
- QParallelAnimationGroup *parallelAnim = new QParallelAnimationGroup;
- parallelAnim->addAnimation(anim1);
- parallelAnim->addAnimation(anim2);
- parallelAnim->start();
-}
-//! [animation-group1]
-
-//! [animation-group2]
-MyButtonWidget::MyButtonWidget(QWidget *parent) : QWidget(parent)
-{
- QPushButton *bonnie = new QPushButton(tr("Bonnie"), this);
- QPushButton *clyde = new QPushButton(tr("Clyde"), this);
-
- QPropertyAnimation *anim1 = new QPropertyAnimation(bonnie, "pos", this);
- anim1->setDuration(3000);
- anim1->setStartValue(QPoint(0, 0));
- anim1->setEndValue(QPoint(100, 250));
-
- QPropertyAnimation *anim2 = new QPropertyAnimation(clyde, "pos", this);
- anim2->setDuration(3000);
- anim2->setStartValue(QPoint(0, 0));
- anim2->setEndValue(QPoint(200, 250));
-
- QSequentialAnimationGroup *sequenceAnim = new QSequentialAnimationGroup;
- sequenceAnim->addAnimation(anim1);
- sequenceAnim->addAnimation(anim2);
- sequenceAnim->start();
-}
-//! [animation-group2]
+//! [main]
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
index a429fe20b2d..c00a723a26c 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qsequentialanimationgroup.cpp
@@ -1,6 +1,10 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QSequentialAnimationGroup>
+
+void example(QAbstractAnimation *anim1, QAbstractAnimation *anim2)
+{
//! [0]
QSequentialAnimationGroup *group = new QSequentialAnimationGroup;
@@ -9,3 +13,4 @@
group->start();
//! [0]
+}
diff --git a/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
index be7f549f655..be7e51e1b44 100644
--- a/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_animation_qvariantanimation.cpp
@@ -1,14 +1,22 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QVariantAnimation>
+#include <QColor>
+
//! [0]
- QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
- {
- ...
- return QColor(...);
- }
- ...
+QVariant myColorInterpolator(const QColor &start, const QColor &end, qreal progress)
+{
+ // ...
+ return QColor(/*...*/);
+}
+// ...
+void someFunc()
+{
+ // ...
qRegisterAnimationInterpolator<QColor>(myColorInterpolator);
+ // ...
+}
//! [0]
//! [1]
diff --git a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
index 4cba70e62d4..56a0532ac21 100644
--- a/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_concurrent_qthreadpool.cpp
@@ -1,6 +1,10 @@
// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+#include <QThreadPool>
+#include <QRunnable>
+#include <QDebug>
+
//! [0]
class HelloWorldTask : public QRunnable
{
@@ -10,7 +14,12 @@ class HelloWorldTask : public QRunnable
}
};
-HelloWorldTask *hello = new HelloWorldTask();
-// QThreadPool takes ownership and deletes 'hello' automatically
-QThreadPool::globalInstance()->start(hello);
+int main()
+{
+ //...
+ HelloWorldTask *hello = new HelloWorldTask();
+ // QThreadPool takes ownership and deletes 'hello' automatically
+ QThreadPool::globalInstance()->start(hello);
+ //...
+}
//! [0]
diff --git a/src/corelib/doc/src/animation.qdoc b/src/corelib/doc/src/animation.qdoc
index d2e182f4806..ba5976f11eb 100644
--- a/src/corelib/doc/src/animation.qdoc
+++ b/src/corelib/doc/src/animation.qdoc
@@ -91,7 +91,12 @@
The following example demonstrates how you can animate a QPushButton
widget:
- \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp includes
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp class_decl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp first_example
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp main
The example animates the \c pos Qt property of a QPushButton, to move
it from the top--left corner of the screen to the end position (250, 250),
@@ -174,7 +179,9 @@
path.
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
\snippet code/src_corelib_animation_qpropertyanimation.cpp easing-curve
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
In this example, the animation follows a curve that makes the
\c button bounce like a ball. QEasingCurve offers a large collection of curves
@@ -199,13 +206,17 @@
The two following examples demonstrate the use of both
QSequentialAnimationGroup and QParallelAnimationGroup:
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
\snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group1
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
A parallel group plays more than one animation at the same time.
Its \l{QAbstractAnimation::}{start()} function starts all
animations that are part of the group.
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
\snippet code/src_corelib_animation_qpropertyanimation.cpp animation-group2
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
As the name suggests, a QSequentialAnimationGroup plays
its animations in sequence. It starts the next animation in
@@ -225,7 +236,12 @@
independent QPropertyAnimation has the QApplication instance as its
parent:
- \snippet code/src_corelib_animation_qpropertyanimation.cpp 0
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp includes
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp class_decl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_impl
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp first_example
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp ctor_close
+ \snippet code/src_corelib_animation_qpropertyanimation.cpp main
\note You can also control the animation's lifespan by choosing a
\l{QAbstractAnimation::DeletionPolicy}{delete policy} while starting it.
diff --git a/src/corelib/io/qdirlisting.cpp b/src/corelib/io/qdirlisting.cpp
index c626033dcdb..1fec92a01e2 100644
--- a/src/corelib/io/qdirlisting.cpp
+++ b/src/corelib/io/qdirlisting.cpp
@@ -510,16 +510,14 @@ bool QDirListingPrivate::matchesFilters(QDirEntryInfo &entryInfo) const
if (!iteratorFlags.testAnyFlag(F::IncludeHidden) && entryInfo.isHidden())
return false;
- if (entryInfo.isSymLink()) {
- // With ResolveSymlinks, we look at the type of the link's target,
- // and exclude broken symlinks (where the target doesn't exist).
- if (iteratorFlags.testAnyFlag(F::ResolveSymlinks)) {
- if (!entryInfo.exists())
- return false;
- } else if (iteratorFlags.testAnyFlags(F::FilesOnly)
- || iteratorFlags.testAnyFlags(F::DirsOnly)) {
- return false; // symlink is not a file or dir
- }
+ // With ResolveSymlinks, we look at the type of the link's target,
+ // and exclude broken symlinks (where the target doesn't exist).
+ if (iteratorFlags.testAnyFlag(F::ResolveSymlinks)) {
+ if (entryInfo.isSymLink() && !entryInfo.exists())
+ return false;
+ } else if ((iteratorFlags.testAnyFlags(F::FilesOnly)
+ || iteratorFlags.testAnyFlags(F::DirsOnly)) && entryInfo.isSymLink()) {
+ return false; // symlink is not a file or dir
}
if (iteratorFlags.testAnyFlag(F::ExcludeOther)
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index de5f27f9619..8684a02b727 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -1733,16 +1733,8 @@ bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *
"queued connections");
return false;
}
- auto event = std::make_unique<QMetaCallEvent>(std::move(slot), nullptr, -1, parameterCount);
- void **args = event->args();
- QMetaType *types = event->types();
-
- for (int i = 1; i < parameterCount; ++i) {
- types[i] = QMetaType(metaTypes[i]);
- args[i] = types[i].create(argv[i]);
- }
-
- QCoreApplication::postEvent(object, event.release());
+ QCoreApplication::postEvent(object, new QQueuedMetaCallEvent(std::move(slot), nullptr, -1,
+ parameterCount, metaTypes, params));
} else if (type == Qt::BlockingQueuedConnection) {
#if QT_CONFIG(thread)
if (receiverInSameThread)
@@ -2889,31 +2881,27 @@ auto QMetaMethodInvoker::invokeImpl(QMetaMethod self, void *target,
return InvokeFailReason::CouldNotQueueParameter;
}
- auto event = std::make_unique<QMetaCallEvent>(idx_offset, idx_relative, callFunction, nullptr, -1, paramCount);
- QMetaType *types = event->types();
- void **args = event->args();
-
+ QVarLengthArray<const QtPrivate::QMetaTypeInterface *> argTypes;
+ argTypes.emplace_back(nullptr); // return type
// fill in the meta types first
for (int i = 1; i < paramCount; ++i) {
- types[i] = QMetaType(methodMetaTypes[i - 1]);
- if (!types[i].iface() && (!MetaTypesAreOptional || metaTypes))
- types[i] = QMetaType(metaTypes[i]);
- if (!types[i].iface())
- types[i] = priv->parameterMetaType(i - 1);
- if (!types[i].iface() && typeNames[i])
- types[i] = QMetaType::fromName(typeNames[i]);
- if (!types[i].iface()) {
+ QMetaType type = QMetaType(methodMetaTypes[i - 1]);
+ if (!type.iface() && (!MetaTypesAreOptional || metaTypes))
+ type = QMetaType(metaTypes[i]);
+ if (!type.iface())
+ type = priv->parameterMetaType(i - 1);
+ if (!type.iface() && typeNames[i])
+ type = QMetaType::fromName(typeNames[i]);
+ if (!type.iface()) {
qWarning("QMetaMethod::invoke: Unable to handle unregistered datatype '%s'",
typeNames[i]);
return InvokeFailReason(int(InvokeFailReason::CouldNotQueueParameter) - i);
}
+ argTypes.emplace_back(type.iface());
}
- // now create copies of our parameters using those meta types
- for (int i = 1; i < paramCount; ++i)
- args[i] = types[i].create(parameters[i]);
-
- QCoreApplication::postEvent(object, event.release());
+ QCoreApplication::postEvent(object, new QQueuedMetaCallEvent(idx_offset, idx_relative, callFunction, nullptr,
+ -1, paramCount, argTypes.data(), parameters));
} else { // blocking queued connection
#if QT_CONFIG(thread)
if (receiverInSameThread()) {
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 888c71f5a49..d67ada64c45 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -599,14 +599,19 @@ QMetaCallEvent::QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotO,
/*!
\internal
*/
+QMetaCallEvent::QMetaCallEvent(const QObject *sender, int signalId, Data &&data)
+ : QAbstractMetaCallEvent(sender, signalId),
+ d(std::move(data)),
+ prealloc_()
+{
+}
+
+/*!
+ \internal
+ */
QMetaCallEvent::~QMetaCallEvent()
{
if (d.nargs_) {
- QMetaType *t = types();
- for (int i = 0; i < d.nargs_; ++i) {
- if (t[i].isValid() && d.args_[i])
- t[i].destroy(d.args_[i]);
- }
if (reinterpret_cast<void *>(d.args_) != reinterpret_cast<void *>(prealloc_))
free(d.args_);
}
@@ -628,6 +633,115 @@ void QMetaCallEvent::placeMetaCall(QObject *object)
}
/*!
+ \internal
+
+ Constructs a QQueuedMetaCallEvent by copying the argument values using their meta-types.
+ */
+QQueuedMetaCallEvent::QQueuedMetaCallEvent(ushort method_offset, ushort method_relative,
+ QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId, int argCount,
+ const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues)
+ : QMetaCallEvent(sender, signalId, {nullptr, nullptr, callFunction, argCount,
+ method_offset, method_relative})
+{
+ allocArgs();
+ copyArgValues(argCount, argTypes, argValues);
+}
+
+/*!
+ \internal
+
+ Constructs a QQueuedMetaCallEvent by copying the argument values using their meta-types.
+ */
+QQueuedMetaCallEvent::QQueuedMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
+ const QObject *sender, int signalId, int argCount,
+ const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues)
+ : QMetaCallEvent(sender, signalId, {QtPrivate::SlotObjUniquePtr(slotObj), nullptr, nullptr, argCount,
+ 0, ushort(-1)})
+{
+ if (d.slotObj_)
+ d.slotObj_->ref();
+ allocArgs();
+ copyArgValues(argCount, argTypes, argValues);
+}
+
+/*!
+ \internal
+
+ Constructs a QQueuedMetaCallEvent by copying the argument values using their meta-types.
+ */
+QQueuedMetaCallEvent::QQueuedMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
+ const QObject *sender, int signalId, int argCount,
+ const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues)
+ : QMetaCallEvent(sender, signalId, {std::move(slotObj), nullptr, nullptr, argCount,
+ 0, ushort(-1)})
+{
+ allocArgs();
+ copyArgValues(argCount, argTypes, argValues);
+}
+
+/*!
+ \internal
+ */
+QQueuedMetaCallEvent::~QQueuedMetaCallEvent()
+{
+ const QMetaType *t = types();
+ int inplaceIndex = 0;
+ for (int i = 0; i < d.nargs_; ++i) {
+ if (t[i].isValid() && d.args_[i]) {
+ if (typeFitsInPlace(t[i]) && inplaceIndex < InplaceValuesCapacity) {
+ // Only destruct
+ void *where = &valuesPrealloc_[inplaceIndex++].storage;
+ t[i].destruct(where);
+ } else {
+ // Destruct and deallocate
+ t[i].destroy(d.args_[i]);
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+ */
+inline void QQueuedMetaCallEvent::copyArgValues(int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues)
+{
+ void **args = d.args_;
+ QMetaType *types = this->types();
+ int inplaceIndex = 0;
+
+ types[0] = QMetaType(); // return type
+ args[0] = nullptr; // return value pointer
+ // no return value
+
+ for (int n = 1; n < argCount; ++n) {
+ types[n] = QMetaType(argTypes[n]);
+ if (typeFitsInPlace(types[n]) && inplaceIndex < InplaceValuesCapacity) {
+ // Copy-construct in place
+ void *where = &valuesPrealloc_[inplaceIndex++].storage;
+ types[n].construct(where, argValues[n]);
+ args[n] = where;
+ } else {
+ // Allocate and copy-construct
+ args[n] = types[n].create(argValues[n]);
+ }
+ }
+}
+
+/*!
+ \internal
+ */
+inline bool QQueuedMetaCallEvent::typeFitsInPlace(const QMetaType type)
+{
+ return (q20::cmp_less_equal(type.sizeOf(), sizeof(ArgValueStorage)) &&
+ q20::cmp_less_equal(type.alignOf(), alignof(ArgValueStorage)));
+}
+
+/*!
\class QSignalBlocker
\brief Exception-safe wrapper around QObject::blockSignals().
\since 5.3
@@ -4069,26 +4183,19 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
SlotObjectGuard slotObjectGuard { c->isSlotObject ? c->slotObj : nullptr };
locker.unlock();
- QMetaCallEvent *ev = c->isSlotObject ?
- new QMetaCallEvent(c->slotObj, sender, signal, nargs) :
- new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal, nargs);
-
- void **args = ev->args();
- QMetaType *types = ev->types();
-
- types[0] = QMetaType(); // return type
- args[0] = nullptr; // return value
-
- if (nargs > 1) {
- for (int n = 1; n < nargs; ++n)
- types[n] = QMetaType(argumentTypes[n - 1]);
-
- for (int n = 1; n < nargs; ++n)
- args[n] = types[n].create(argv[n]);
+ QVarLengthArray<const QtPrivate::QMetaTypeInterface *> argTypes;
+ argTypes.emplace_back(nullptr); // return type
+ for (int n = 1; n < nargs; ++n) {
+ argTypes.emplace_back(QMetaType(argumentTypes[n - 1]).iface()); // convert type ids to QMetaTypeInterfaces
}
+ auto ev = c->isSlotObject ?
+ std::make_unique<QQueuedMetaCallEvent>(c->slotObj,
+ sender, signal, nargs, argTypes.data(), argv) :
+ std::make_unique<QQueuedMetaCallEvent>(c->method_offset, c->method_relative, c->callFunction,
+ sender, signal, nargs, argTypes.data(), argv);
+
if (c->isSingleShot && !QObjectPrivate::removeConnection(c)) {
- delete ev;
return;
}
@@ -4096,11 +4203,10 @@ static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connect
if (!c->isSingleShot && !c->receiver.loadRelaxed()) {
// the connection has been disconnected while we were unlocked
locker.unlock();
- delete ev;
return;
}
- QCoreApplication::postEvent(receiver, ev);
+ QCoreApplication::postEvent(receiver, ev.release());
}
template <bool callbacks_enabled>
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index dca9c1af932..75aeba73583 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -351,7 +351,7 @@ private:
class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent
{
public:
- // blocking queued with latch - args always owned by caller
+ // blocking queued with latch - arguments always remain owned by the caller
QMetaCallEvent(ushort method_offset, ushort method_relative,
QObjectPrivate::StaticMetaCallFunction callFunction,
const QObject *sender, int signalId,
@@ -363,14 +363,17 @@ public:
const QObject *sender, int signalId,
void **args, QLatch *latch);
- // queued - args allocated by event, copied by caller
+ // OLD - queued - args allocated by event, copied by caller
+ Q_DECL_DEPRECATED_X("Remove this constructor once the qtdeclarative patch is merged. Arguments are now copied by the QQueuedMetaCallEvent constructor and not the caller.")
QMetaCallEvent(ushort method_offset, ushort method_relative,
QObjectPrivate::StaticMetaCallFunction callFunction,
const QObject *sender, int signalId,
int nargs);
+ Q_DECL_DEPRECATED_X("Remove this constructor once the qtdeclarative patch is merged. Arguments are now copied by the QQueuedMetaCallEvent constructor and not the caller.")
QMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
const QObject *sender, int signalId,
int nargs);
+ Q_DECL_DEPRECATED_X("Remove this constructor once the qtdeclarative patch is merged. Arguments are now copied by the QQueuedMetaCallEvent constructor and not the caller.")
QMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
const QObject *sender, int signalId,
int nargs);
@@ -378,14 +381,16 @@ public:
~QMetaCallEvent() override;
inline int id() const { return d.method_offset_ + d.method_relative_; }
- inline const void * const* args() const { return d.args_; }
+ Q_DECL_DEPRECATED_X("Remove this function once the qtdeclarative patch is merged. Arguments are now copied by the QQueuedMetaCallEvent constructor and not the caller.")
inline void ** args() { return d.args_; }
- inline const QMetaType *types() const { return reinterpret_cast<QMetaType *>(d.args_ + d.nargs_); }
+ Q_DECL_DEPRECATED_X("Remove this function once the qtdeclarative patch is merged. Arguments are now copied by the QQueuedMetaCallEvent constructor and not the caller.")
inline QMetaType *types() { return reinterpret_cast<QMetaType *>(d.args_ + d.nargs_); }
virtual void placeMetaCall(QObject *object) override;
-private:
+protected:
+ // Move to QQueuedMetaCallEvent once the qtdeclarative patch is merged.
+ // QMetaCallEvent should not alloc anything anymore.
inline void allocArgs();
struct Data {
@@ -396,9 +401,50 @@ private:
ushort method_offset_;
ushort method_relative_;
} d;
- // preallocate enough space for three arguments
- alignas(void *) char prealloc_[3 * sizeof(void *) + 3 * sizeof(QMetaType)];
+
+ inline QMetaCallEvent(const QObject *sender, int signalId, Data &&data);
+ inline void * const *args() const { return d.args_; }
+ inline QMetaType const *types() const { return reinterpret_cast<QMetaType *>(d.args_ + d.nargs_); }
+
+ // Space for 5 argument pointers and types (including 1 return arg).
+ // Contiguous so that we can make one calloc() for both the pointers and the types when necessary.
+ // Move to QQueuedMetaCallEvent once the qtdeclarative patch is merged.
+ alignas(void *) char prealloc_[5 * sizeof(void *) + 5 * sizeof(QMetaType)];
+};
+
+class Q_CORE_EXPORT QQueuedMetaCallEvent : public QMetaCallEvent
+{
+public:
+ // queued - arguments are allocated and copied from argValues by these constructors
+ QQueuedMetaCallEvent(ushort method_offset, ushort method_relative,
+ QObjectPrivate::StaticMetaCallFunction callFunction,
+ const QObject *sender, int signalId,
+ int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues);
+ QQueuedMetaCallEvent(QtPrivate::QSlotObjectBase *slotObj,
+ const QObject *sender, int signalId,
+ int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues);
+ QQueuedMetaCallEvent(QtPrivate::SlotObjUniquePtr slotObj,
+ const QObject *sender, int signalId,
+ int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues);
+
+ ~QQueuedMetaCallEvent() override;
+
+private:
+ inline void copyArgValues(int argCount, const QtPrivate::QMetaTypeInterface * const *argTypes,
+ const void * const *argValues);
+ static inline bool typeFitsInPlace(const QMetaType type);
+
+ struct ArgValueStorage { // size and alignment matching QString, QList, etc
+ static constexpr size_t MaxSize = 3 * sizeof(void *);
+ alignas(void *) char storage[MaxSize];
+ };
+ static constexpr int InplaceValuesCapacity = 3;
+ ArgValueStorage valuesPrealloc_[InplaceValuesCapacity];
};
+// The total QQueuedMetaCallEvent size is 224 bytes which is a 32-byte multiple, efficient for memory allocators.
struct QAbstractDynamicMetaObject;
struct Q_CORE_EXPORT QDynamicMetaObjectData
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index f9d58e4d906..acb63c4aa9b 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -562,6 +562,10 @@ void QMessageBoxPrivate::helperClicked(QPlatformDialogHelper::StandardButton hel
and \l{QMessageBox::standardButtons} {standard buttons} for
accepting a user response.
+ While the parent parameter is optional, specifying it gives a hint
+ to the window manager, which can then take care of positioning, and
+ maintain a proper stacking order of the dialog window.
+
Two APIs for using QMessageBox are provided, the property-based
API, and the static functions. Calling one of the static functions
is the simpler approach, but it is less flexible than using the
diff --git a/src/widgets/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp b/src/widgets/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp
index ebc07025ec0..062e2e5142a 100644
--- a/src/widgets/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp
+++ b/src/widgets/doc/snippets/code/src_gui_dialogs_qmessagebox.cpp
@@ -12,7 +12,7 @@ int ret = QMessageBox::warning(this, tr("My Application"),
//! [2]
-QMessageBox msgBox;
+QMessageBox msgBox(this);
QPushButton *connectButton = msgBox.addButton(tr("Connect"), QMessageBox::ActionRole);
QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort);
@@ -53,13 +53,13 @@ int main(int argc, char *argv[])
//! [4]
//! [5]
-QMessageBox msgBox;
+QMessageBox msgBox(this);
msgBox.setText("The document has been modified.");
msgBox.exec();
//! [5]
//! [6]
-QMessageBox msgBox;
+QMessageBox msgBox(this);
msgBox.setText("The document has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);