Mercurial > hgweb.cgi > drn
changeset 920:6435a3ad605a
Adds the feature to null the QtPtr object when the observed object is destroyed.
Adds the ability to assign an ObserverPtr null.
line wrap: on
line diff
--- a/src/conversion/unit-tests/CurrencyConverter-unit-tests.cpp Wed Nov 02 20:50:10 2022 +0100 +++ b/src/conversion/unit-tests/CurrencyConverter-unit-tests.cpp Mon Nov 07 20:27:19 2022 +0100 @@ -30,6 +30,8 @@ using drn::conversion::CurrencyConverter; #include <foundation/Error.h> using drn::foundation::Error; +#include <foundation/QtMemory.hpp> +using drn::foundation::QtPtr; namespace drn @@ -41,6 +43,10 @@ struct CurrencySourceTest : CurrencySource { + CurrencySourceTest(QtPtr<QObject> parent) : + CurrencySource{parent} + {} + QMOCK_MEMBER_FUNCTION(double, fetch, const Iso4217Codes&, const Iso4217Codes&) }; @@ -48,7 +54,7 @@ { Q_OBJECT - CurrencySourceTest source_; + CurrencySourceTest source_{nullptr}; private slots: //{ lookUp Tests
--- a/src/desktop-ui/external/desktop-ui/CurrencyCodeWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/external/desktop-ui/CurrencyCodeWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -44,7 +44,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/external/desktop-ui/EventFrequencyEntryWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/external/desktop-ui/EventFrequencyEntryWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -38,7 +38,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/external/desktop-ui/MainWindow.cpp Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/external/desktop-ui/MainWindow.cpp Mon Nov 07 20:27:19 2022 +0100 @@ -111,7 +111,7 @@ const qint32 MainWindow::statusBarTimeOut_{5000}; const QString MainWindow::budgetFileExtentionFilter_{ - QObject::tr("Budget Files (%1);;All Files (*.*)").arg(budgetFileExtention_) + QObject::tr("Budget Files (%1);All Files (*.*)").arg(budgetFileExtention_) }; void MainWindow::onShowAbout()
--- a/src/desktop-ui/external/desktop-ui/VerticalLabel.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/external/desktop-ui/VerticalLabel.h Mon Nov 07 20:27:19 2022 +0100 @@ -34,7 +34,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/AccountEntryWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/AccountEntryWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -54,7 +54,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/BankAccountsWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/BankAccountsWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -50,7 +50,7 @@ template<typename> class Optional; template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/BankEntryWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/BankEntryWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -44,7 +44,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/BudgetItemsDueWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/BudgetItemsDueWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -42,7 +42,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/ConfigureDialog.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/ConfigureDialog.h Mon Nov 07 20:27:19 2022 +0100 @@ -39,7 +39,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/DashboardWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/DashboardWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -56,7 +56,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/DebtEntryWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/DebtEntryWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -65,7 +65,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/GoalEntryWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/GoalEntryWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -72,7 +72,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/MonthlyTotalsWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/MonthlyTotalsWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -47,7 +47,7 @@ { template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/desktop-ui/internal/PostBudgetItemEntryWidget.h Wed Nov 02 20:50:10 2022 +0100 +++ b/src/desktop-ui/internal/PostBudgetItemEntryWidget.h Mon Nov 07 20:27:19 2022 +0100 @@ -71,7 +71,7 @@ template<typename> class Optional; template<typename> -struct QtPtr;; +class QtPtr; } namespace desktop_ui
--- a/src/foundation/external/foundation/ObserverPtr.hpp Wed Nov 02 20:50:10 2022 +0100 +++ b/src/foundation/external/foundation/ObserverPtr.hpp Mon Nov 07 20:27:19 2022 +0100 @@ -49,6 +49,7 @@ ObserverPtr& operator=(const ObserverPtr&) = default; ObserverPtr& operator=(ObserverPtr&&) = default; ObserverPtr& operator=(ObservedType* const observe); + ObserverPtr& operator=(const std::nullptr_t); bool operator==(const std::nullptr_t) const; bool operator==(const ObserverPtr& other) const; bool operator==(const ObservedType* observed) const; @@ -69,7 +70,7 @@ * @brief An accessor to the object being observed. */ ObservedType* observed() const; - // TODO: add operator& + // TODO: add operator& // TODO: then .observed is not needed in QtMemory. }; template<typename ObservedType> @@ -107,6 +108,15 @@ } template<typename ObservedType> +drn::foundation::ObserverPtr<ObservedType>& drn::foundation::ObserverPtr<ObservedType>::operator=( + const std::nullptr_t +) +{ + this->observed_ = nullptr; + return *this; +} + +template<typename ObservedType> bool drn::foundation::ObserverPtr<ObservedType>::operator==(const std::nullptr_t) const { return this->observed_ == nullptr;
--- a/src/foundation/external/foundation/QtMemory.hpp Wed Nov 02 20:50:10 2022 +0100 +++ b/src/foundation/external/foundation/QtMemory.hpp Mon Nov 07 20:27:19 2022 +0100 @@ -20,6 +20,7 @@ #ifndef DRN_FOUNDATION_QTMEMORY_HPP_ #define DRN_FOUNDATION_QTMEMORY_HPP_ +#include <QMetaObject> #include <QObject> #include <cassert> @@ -38,9 +39,15 @@ struct UniqueQtPtr; template<typename ObjectType> -struct QtPtr : ObserverPtr<ObjectType> +class QtPtr : public ObserverPtr<ObjectType> { - QtPtr(ObjectType* const observe = nullptr); + QMetaObject::Connection connection_; + +public: + QtPtr( + ObjectType* const observe = nullptr, + QMetaObject::Connection connection = {} + ); // TODO: this should not be used instead the UniqueQtPtr should be only available. QtPtr(const std::unique_ptr<ObjectType>& observe); QtPtr(const UniqueQtPtr<ObjectType>& observe); @@ -48,6 +55,7 @@ QtPtr(QtPtr&&) noexcept = default; QtPtr& operator=(const QtPtr&) = default; QtPtr& operator=(QtPtr&&) noexcept = default; + ~QtPtr(); using ObserverPtr<ObjectType>::observed; using ObserverPtr<ObjectType>::operator*; using ObserverPtr<ObjectType>::operator->; @@ -107,35 +115,31 @@ }} template<typename ObjectType> -drn::foundation::QtPtr<ObjectType>::QtPtr(ObjectType* const observe) : - ObserverPtr<ObjectType>{observe} -{ - // TODO: - // ::QObject::connect( - // observe, - // &::QObject::destroyed, - // this, - // [this] (::QObject* obj) - // { - // assert( - // dynamic_cast<::QObject*>(this->observed()) == obj - // && "Should be the same object being destroyed."); - // *this = nullptr; - // } - // ); -} +drn::foundation::QtPtr<ObjectType>::QtPtr( + ObjectType* const observe, + QMetaObject::Connection connection +) : + ObserverPtr<ObjectType>{observe}, + connection_{connection} +{} template<typename ObjectType> drn::foundation::QtPtr<ObjectType>::QtPtr(const std::unique_ptr<ObjectType>& observe) : - drn::foundation::QtPtr<ObjectType>{observe.get()} + drn::foundation::QtPtr<ObjectType>{observe.get()} // TODO: setup connection {} template<typename ObjectType> drn::foundation::QtPtr<ObjectType>::QtPtr(const UniqueQtPtr<ObjectType>& observe) : - drn::foundation::QtPtr<ObjectType>{observe.observed()} + drn::foundation::QtPtr<ObjectType>{observe.observed()} // TODO: setup connection {} template<typename ObjectType> +drn::foundation::QtPtr<ObjectType>::~QtPtr() +{ + QObject::disconnect(this->connection_); +} + +template<typename ObjectType> drn::foundation::UniqueQtPtr<ObjectType>::UniqueQtPtr(ObjectType* const obj) : std::unique_ptr<ObjectType, void(*)(ObjectType*)>{ obj, @@ -172,7 +176,22 @@ drn::foundation::QtPtr<BaseType> >::type drn::foundation::makeQtPtr(ObjectArgTypes&& ... objectArgs) { + static_assert( + std::is_base_of<::QObject, ObjectType>::value, + "Only pointers to Qt objects that can be released by Qt are allowed." + ); QtPtr<BaseType> obj{new ObjectType{std::forward<ObjectArgTypes>(objectArgs)...}}; + auto connection{ + ::QObject::connect( + obj.observed(), + &::QObject::destroyed, + [obj] (::QObject* o) mutable + { + assert(obj.observed() == o && "Should be the same object being destroyed."); + obj = nullptr; + } + ) + }; assert(obj->parent() != nullptr && "All Qt objects must have a parent."); return obj; }