diff --git a/src/gui/model/w-link.hpp b/src/gui/model/w-link.hpp index 9e62c98be..fce69b5f7 100644 --- a/src/gui/model/w-link.hpp +++ b/src/gui/model/w-link.hpp @@ -74,8 +74,7 @@ namespace model { public: ~WLink() { - if (widget_) - disconnect (*widget_); + this->clear(); } WLink() : widget_{nullptr} @@ -83,10 +82,8 @@ namespace model { explicit WLink(TAR& targetWidget) - : widget_{&targetWidget} - { - connect (targetWidget); - } + : widget_{attachTo (targetWidget)} + { } ////////////////////////////TODO copy operations @@ -96,7 +93,6 @@ namespace model { return bool(widget_); } - TAR& operator* () const { @@ -111,6 +107,23 @@ namespace model { return widget_; } + + void + clear() + { + if (widget_) + widget_->remove_destroy_notify_callback (&widget_); + widget_ = nullptr; + } + + void + connect (TAR& otherTarget) + { + if (widget_ == &otherTarget) return; + clear(); + widget_ = attachTo (otherTarget); + } + private: void __ensureAlive() const @@ -120,8 +133,8 @@ namespace model { , LERR_(BOTTOM_VALUE)); } - void - connect (sigc::trackable& target) + TAR* + attachTo (TAR& target) { target.add_destroy_notify_callback (&widget_ ,[](void* p) @@ -131,12 +144,7 @@ namespace model { widgetPtr = nullptr; return p; }); - } - - void - disconnect (sigc::trackable& target) - { - target.remove_destroy_notify_callback (&widget_); + return ⌖ } }; diff --git a/tests/gui/model/w-link-test.cpp b/tests/gui/model/w-link-test.cpp index eb11e1d79..2c9177904 100644 --- a/tests/gui/model/w-link-test.cpp +++ b/tests/gui/model/w-link-test.cpp @@ -32,7 +32,7 @@ #include "lib/format-cout.hpp" //#include "lib/idi/entry-id.hpp" //#include "lib/diff/gen-node.hpp" -//#include "lib/util.hpp" +#include "lib/util.hpp" //#include #include @@ -44,7 +44,7 @@ //using lib::idi::EntryID; //using lib::diff::GenNode; using std::make_unique; -//using util::isSameObject; +using util::isSameObject; //using util::isnil; @@ -61,7 +61,7 @@ namespace test { struct DummyWidget : public sigc::trackable { - X val; + X val = 1 + rand() % 100; }; } @@ -92,10 +92,8 @@ namespace test { verify_standardUsage() { using Wint = DummyWidget; - int r{rand() % 100}; - auto widget = make_unique(); - widget->val = r; + int r = widget->val; WLink link{*widget}; CHECK (link); @@ -112,7 +110,48 @@ namespace test { void verify_reconnect() { - UNIMPLEMENTED ("change connection state"); + using Wint = DummyWidget; + + auto w1 = make_unique(); + auto w2 = make_unique(); + int r1 = w1->val; + int r2 = w2->val; + + WLink l1; + WLink l2{*w1}; + CHECK (not l1); + CHECK ( l2); + + l2->val = r1; + l1.connect(*l2); + ++l1->val; + CHECK (w1->val == r1+1); + CHECK (isSameObject (*l1, *l2)); + + l2.connect(*w2); + CHECK (not isSameObject (*l1, *l2)); + w2->val = r2; + CHECK (r1+1 == l1->val); + CHECK (r2 == l2->val); + + w1.reset(); // kill first widget + CHECK (not l1); + CHECK ( l2); + l2->val *= -10; + l2.clear(); + CHECK (not l1); + CHECK (not l2); + CHECK (-10*r2 == w2->val); + l1.connect(*w2); + l2.connect(*l1); + CHECK (-10*r2 == l2->val); + CHECK (isSameObject (*l1, *l2)); + CHECK (isSameObject (*l1, *w2)); + + // implicitly kill second widget + *w2 = Wint{}; + CHECK (not l1); + CHECK (not l2); }