diff options
Diffstat (limited to 'src/corelib')
-rw-r--r-- | src/corelib/animation/qabstractanimation.cpp | 3 | ||||
-rw-r--r-- | src/corelib/itemmodels/qsortfilterproxymodel.cpp | 6 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.cpp | 39 | ||||
-rw-r--r-- | src/corelib/kernel/qproperty.h | 10 |
4 files changed, 50 insertions, 8 deletions
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp index 46ed60d6d1..4965ed4fd5 100644 --- a/src/corelib/animation/qabstractanimation.cpp +++ b/src/corelib/animation/qabstractanimation.cpp @@ -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() diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp index bf1c2dbd97..db1ed95182 100644 --- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp +++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp @@ -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() diff --git a/src/corelib/kernel/qproperty.cpp b/src/corelib/kernel/qproperty.cpp index 8b14390bc6..4708a92b9e 100644 --- a/src/corelib/kernel/qproperty.cpp +++ b/src/corelib/kernel/qproperty.cpp @@ -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>); diff --git a/src/corelib/kernel/qproperty.h b/src/corelib/kernel/qproperty.h index 5d8b908f31..dd18d95c50 100644 --- a/src/corelib/kernel/qproperty.h +++ b/src/corelib/kernel/qproperty.h @@ -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 { |