Long live QScopedPropertyUpdateGroup
A RAII wrapper around Qt::{begin,end}PropertyUpdateGroup().
[ChangeLog][QtCore][QScopedPropertyUpdateGroup] New RAII class
wrapping Qt::beginPropertyUpdateGroup() and
Qt::endPropertyUpdateGroup().
Fixes: QTBUG-110710
Change-Id: If2619e9584dd9d57985d63e3babca75421499ab9
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
bb10
parent
48f0d458a9
commit
224930726b
|
|
@ -1121,7 +1121,7 @@ void QAbstractAnimation::setDirection(Direction direction)
|
|||
return;
|
||||
}
|
||||
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
const QScopedPropertyUpdateGroup guard;
|
||||
const int oldCurrentLoop = d->currentLoop;
|
||||
if (state() == Stopped) {
|
||||
if (direction == Backward) {
|
||||
|
|
@ -1148,7 +1148,6 @@ void QAbstractAnimation::setDirection(Direction direction)
|
|||
if (d->currentLoop != oldCurrentLoop)
|
||||
d->currentLoop.notify();
|
||||
d->direction.notify();
|
||||
Qt::endPropertyUpdateGroup();
|
||||
}
|
||||
|
||||
QBindable<QAbstractAnimation::Direction> QAbstractAnimation::bindableDirection()
|
||||
|
|
|
|||
|
|
@ -2582,7 +2582,7 @@ QBindable<QRegularExpression> QSortFilterProxyModel::bindableFilterRegularExpres
|
|||
void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression ®ularExpression)
|
||||
{
|
||||
Q_D(QSortFilterProxyModel);
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
const QScopedPropertyUpdateGroup guard;
|
||||
const bool regExpChanged = regularExpression != d->filter_regularexpression.value();
|
||||
d->filter_regularexpression.removeBindingUnlessInWrapper();
|
||||
d->filter_casesensitive.removeBindingUnlessInWrapper();
|
||||
|
|
@ -2601,7 +2601,6 @@ void QSortFilterProxyModel::setFilterRegularExpression(const QRegularExpression
|
|||
d->filter_regularexpression.notify();
|
||||
if (cs != updatedCs)
|
||||
d->filter_casesensitive.notify();
|
||||
Qt::endPropertyUpdateGroup();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -2677,7 +2676,7 @@ void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
|
|||
if (cs == d->filter_casesensitive)
|
||||
return;
|
||||
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
const QScopedPropertyUpdateGroup guard;
|
||||
QRegularExpression::PatternOptions options =
|
||||
d->filter_regularexpression.value().patternOptions();
|
||||
options.setFlag(QRegularExpression::CaseInsensitiveOption, cs == Qt::CaseInsensitive);
|
||||
|
|
@ -2690,7 +2689,6 @@ void QSortFilterProxyModel::setFilterCaseSensitivity(Qt::CaseSensitivity cs)
|
|||
d->filter_changed(QSortFilterProxyModelPrivate::Direction::Rows);
|
||||
d->filter_regularexpression.notify();
|
||||
d->filter_casesensitive.notify();
|
||||
Qt::endPropertyUpdateGroup();
|
||||
}
|
||||
|
||||
QBindable<Qt::CaseSensitivity> QSortFilterProxyModel::bindableFilterCaseSensitivity()
|
||||
|
|
|
|||
|
|
@ -185,7 +185,7 @@ Q_CONSTINIT static thread_local QBindingStatus bindingStatus;
|
|||
properties need to be updated, preventing any external observer from noticing an inconsistent
|
||||
state.
|
||||
|
||||
\sa Qt::endPropertyUpdateGroup
|
||||
\sa Qt::endPropertyUpdateGroup, QScopedPropertyUpdateGroup
|
||||
*/
|
||||
void Qt::beginPropertyUpdateGroup()
|
||||
{
|
||||
|
|
@ -205,7 +205,7 @@ void Qt::beginPropertyUpdateGroup()
|
|||
\warning Calling endPropertyUpdateGroup without a preceding call to beginPropertyUpdateGroup
|
||||
results in undefined behavior.
|
||||
|
||||
\sa Qt::beginPropertyUpdateGroup
|
||||
\sa Qt::beginPropertyUpdateGroup, QScopedPropertyUpdateGroup
|
||||
*/
|
||||
void Qt::endPropertyUpdateGroup()
|
||||
{
|
||||
|
|
@ -239,6 +239,41 @@ void Qt::endPropertyUpdateGroup()
|
|||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 6.6
|
||||
\class QScopedPropertyUpdateGroup
|
||||
\inmodule QtCore
|
||||
\ingroup tools
|
||||
\brief RAII class around Qt::beginPropertyUpdateGroup()/Qt::endPropertyUpdateGroup()
|
||||
|
||||
This class calls Qt::beginPropertyUpdateGroup() in its constructor and
|
||||
Qt::endPropertyUpdateGroup() in its destructor, making sure the latter
|
||||
function is reliably called even in the presence of early returns or thrown
|
||||
exceptions.
|
||||
|
||||
\note Qt::endPropertyUpdateGroup() may re-throw exceptions thrown by
|
||||
binding evaluations. This means your application may crash
|
||||
(\c{std::terminate()} called) if another exception is causing
|
||||
QScopedPropertyUpdateGroup's destructor to be called during stack
|
||||
unwinding. If you expect exceptions from binding evaluations, use manual
|
||||
Qt::endPropertyUpdateGroup() calls and \c{try}/\c{catch} blocks.
|
||||
|
||||
\sa QProperty
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QScopedPropertyUpdateGroup::QScopedPropertyUpdateGroup()
|
||||
|
||||
Calls Qt::beginPropertyUpdateGroup().
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QScopedPropertyUpdateGroup::~QScopedPropertyUpdateGroup()
|
||||
|
||||
Calls Qt::endPropertyUpdateGroup().
|
||||
*/
|
||||
|
||||
|
||||
// check everything stored in QPropertyBindingPrivate's union is trivially destructible
|
||||
// (though the compiler would also complain if that weren't the case)
|
||||
static_assert(std::is_trivially_destructible_v<QPropertyBindingSourceLocation>);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,16 @@ Q_CORE_EXPORT void beginPropertyUpdateGroup();
|
|||
Q_CORE_EXPORT void endPropertyUpdateGroup();
|
||||
}
|
||||
|
||||
class [[nodiscard]] QScopedPropertyUpdateGroup
|
||||
{
|
||||
Q_DISABLE_COPY_MOVE(QScopedPropertyUpdateGroup)
|
||||
public:
|
||||
QScopedPropertyUpdateGroup()
|
||||
{ Qt::beginPropertyUpdateGroup(); }
|
||||
~QScopedPropertyUpdateGroup() noexcept(false)
|
||||
{ Qt::endPropertyUpdateGroup(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class QPropertyData : public QUntypedPropertyData
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1782,13 +1782,14 @@ void tst_QProperty::propertyAdaptorBinding()
|
|||
QCOMPARE(object.fooChangedCount, 7);
|
||||
|
||||
// Check update group
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
source.setValue(23);
|
||||
source2.setValue(22);
|
||||
QCOMPARE(object.foo(), 43);
|
||||
QCOMPARE(dest1.value(), 43);
|
||||
QCOMPARE(object.fooChangedCount, 7);
|
||||
Qt::endPropertyUpdateGroup();
|
||||
{
|
||||
const QScopedPropertyUpdateGroup guard;
|
||||
source.setValue(23);
|
||||
source2.setValue(22);
|
||||
QCOMPARE(object.foo(), 43);
|
||||
QCOMPARE(dest1.value(), 43);
|
||||
QCOMPARE(object.fooChangedCount, 7);
|
||||
}
|
||||
QCOMPARE(object.foo(), 45);
|
||||
QCOMPARE(dest1.value(), 45);
|
||||
QCOMPARE(object.fooChangedCount, 8);
|
||||
|
|
@ -2085,27 +2086,29 @@ void tst_QProperty::groupedNotifications()
|
|||
QCOMPARE(nNotifications, 1);
|
||||
|
||||
expected = 2;
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
a = 1;
|
||||
QCOMPARE(b.value(), 0);
|
||||
QCOMPARE(c.value(), 0);
|
||||
QCOMPARE(d.value(), 0);
|
||||
QCOMPARE(nNotifications, 1);
|
||||
Qt::endPropertyUpdateGroup();
|
||||
{
|
||||
const QScopedPropertyUpdateGroup guard;
|
||||
a = 1;
|
||||
QCOMPARE(b.value(), 0);
|
||||
QCOMPARE(c.value(), 0);
|
||||
QCOMPARE(d.value(), 0);
|
||||
QCOMPARE(nNotifications, 1);
|
||||
}
|
||||
QCOMPARE(b.value(), 1);
|
||||
QCOMPARE(c.value(), 1);
|
||||
QCOMPARE(e.value(), 2);
|
||||
QCOMPARE(nNotifications, 2);
|
||||
|
||||
expected = 7;
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
a = 2;
|
||||
d = 3;
|
||||
QCOMPARE(b.value(), 1);
|
||||
QCOMPARE(c.value(), 1);
|
||||
QCOMPARE(d.value(), 3);
|
||||
QCOMPARE(nNotifications, 2);
|
||||
Qt::endPropertyUpdateGroup();
|
||||
{
|
||||
const QScopedPropertyUpdateGroup guard;
|
||||
a = 2;
|
||||
d = 3;
|
||||
QCOMPARE(b.value(), 1);
|
||||
QCOMPARE(c.value(), 1);
|
||||
QCOMPARE(d.value(), 3);
|
||||
QCOMPARE(nNotifications, 2);
|
||||
}
|
||||
QCOMPARE(b.value(), 2);
|
||||
QCOMPARE(c.value(), 2);
|
||||
QCOMPARE(e.value(), 7);
|
||||
|
|
@ -2128,10 +2131,11 @@ void tst_QProperty::groupedNotificationConsistency()
|
|||
j = 1;
|
||||
QVERIFY(!areEqual); // value changed runs before j = 1
|
||||
|
||||
Qt::beginPropertyUpdateGroup();
|
||||
i = 2;
|
||||
j = 2;
|
||||
Qt::endPropertyUpdateGroup();
|
||||
{
|
||||
const QScopedPropertyUpdateGroup guard;
|
||||
i = 2;
|
||||
j = 2;
|
||||
}
|
||||
QVERIFY(areEqual); // value changed runs after everything has been evaluated
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue