diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b6976c25..24b48511 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -98,6 +98,8 @@ set(DOCKSLIBS_SRCS controllers/TabBar.h View.cpp View.h + ViewGuard.cpp + ViewGuard.h ViewWrapper.cpp ViewWrapper.h Controller.cpp diff --git a/src/ViewGuard.cpp b/src/ViewGuard.cpp new file mode 100644 index 00000000..e1b63d6f --- /dev/null +++ b/src/ViewGuard.cpp @@ -0,0 +1,57 @@ +#include "ViewGuard.h" +#include "View.h" + +using namespace KDDockWidgets; + +ViewGuard::ViewGuard(View *view) + : v(view && view->inDtor() ? nullptr : view) +{ + if (v) { + m_onDestroy = v->beingDestroyed.connect([this] { + v = nullptr; + }); + } +} + +ViewGuard::operator bool() const +{ + return !isNull(); +} + +bool ViewGuard::isNull() const +{ + return v == nullptr; +} + +View *ViewGuard::operator->() +{ + return v; +} + +void ViewGuard::clear() +{ + v = nullptr; +} + +View *ViewGuard::view() const +{ + return v; +} + +ViewGuard& ViewGuard::operator=(View *view) +{ + if (view == v) { + return *this; + } + + // Remove the pervious connection + if (m_onDestroy.isActive()) + m_onDestroy.disconnect(); + + v = view; + + m_onDestroy = v->beingDestroyed.connect([this] { + v = nullptr; + }); + return *this; +} diff --git a/src/ViewGuard.h b/src/ViewGuard.h new file mode 100644 index 00000000..18a300c5 --- /dev/null +++ b/src/ViewGuard.h @@ -0,0 +1,33 @@ +#ifndef KDDW_VIEW_GUARD_H +#define KDDW_VIEW_GUARD_H + +#include "docks_export.h" + +#include "kdbindings/signal.h" + +namespace KDDockWidgets { +class View; + +/// @brief This class provides a weak reference to a view +/// i.e., it becomes null automatically once a View is destroyed +class DOCKS_EXPORT ViewGuard +{ +public: + ViewGuard(View *v); + + operator bool() const; + View *operator->(); + void clear(); + bool isNull() const; + View *view() const; + + ViewGuard& operator=(View *); + +private: + View *v = nullptr; + KDBindings::ConnectionHandle m_onDestroy; +}; + +} + +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9f9c3a4c..bc59be32 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -49,3 +49,6 @@ endif() # tests_launcher add_executable(tests_launcher tests_launcher.cpp) target_link_libraries(tests_launcher Qt${Qt_VERSION_MAJOR}::Core) + +add_executable(tst_viewguard tst_viewguard.cpp) +target_link_libraries(tst_viewguard kddockwidgets) diff --git a/tests/tst_viewguard.cpp b/tests/tst_viewguard.cpp new file mode 100644 index 00000000..48fba622 --- /dev/null +++ b/tests/tst_viewguard.cpp @@ -0,0 +1,29 @@ +#include + +#include +#include + +using namespace KDDockWidgets; + +void test(bool cond, const char *stmt, int line) +{ + if (!cond) { + printf("[FAILED] %s line; %d\n", stmt, line); + exit(1); + } +} +#define TEST(cond) test(cond, #cond, __LINE__) + +int main() +{ + ViewGuard g(nullptr); + TEST(g.isNull()); + + { + Views::ViewWrapper_qtwidgets wv(static_cast(nullptr)); + g = &wv; + TEST(!g.isNull()); + } + + TEST(g.isNull()); +}