2 Commits 804f950913 ... e057863f36

Author SHA1 Message Date
  Ivan Baidakou e057863f36 WIP 2 weeks ago
  Ivan Baidakou 7b419410e1 WIP 2 weeks ago

+ 12 - 11
src/presentation/entity.cpp

@@ -14,7 +14,12 @@ using F = presence_t::features_t;
 entity_t::entity_t(path_t path_, entity_t *parent_) noexcept
     : parent{parent_}, path(std::move(path_)), best{nullptr}, entities_monitor{nullptr} {}
 
-entity_t::~entity_t() { clear_children(); }
+entity_t::~entity_t() {
+    clear_children();
+    while (!presences.empty()) {
+        presences.front()->clear_presense();
+    }
+}
 
 void entity_t::clear_children() noexcept {
     for (auto it = children.begin(); it != children.end();) {
@@ -89,13 +94,6 @@ void entity_t::remove_presense(presence_t &item) noexcept {
         }
     }
 
-    if (children.size()) {
-        bool rescan_children = true;
-        while (rescan_children) {
-            bool scan = true;
-            rescan_children = !scan;
-        }
-    }
     bool need_restat = false;
     auto stats = statistics;
     auto own_stats = item.get_own_stats();
@@ -173,13 +171,16 @@ void entity_t::remove_child(entity_t &child) noexcept {
     for (auto r : presences) {
         r->children.clear();
     }
-    push_stats({-child.get_stats(), 0}, nullptr, true);
+    // push_stats({-child.get_stats(), 0}, nullptr, true);
+    auto &child_presences = child.presences;
+    while (!child_presences.empty()) {
+        child_presences.front()->clear_presense();
+    }
 
     if (auto monitor = get_monitor(); monitor) {
         monitor->on_delete(child);
     }
-
-    child.parent = nullptr;
+    // child.parent = nullptr;
     model::intrusive_ptr_release(&child);
 }
 

+ 6 - 1
src/presentation/folder_entity.cpp

@@ -194,4 +194,9 @@ entity_t *folder_entity_t::on_insert(model::file_info_t &file_info) noexcept {
 auto folder_entity_t::get_folder() noexcept -> model::folder_t & { return folder; }
 
 void folder_entity_t::on_update() noexcept { notify_update(); }
-void folder_entity_t::on_delete() noexcept { clear_children(); }
+void folder_entity_t::on_delete() noexcept {
+    clear_children();
+    if (auto monitor = get_monitor(); monitor) {
+        monitor->on_delete(*this);
+    }
+}

+ 3 - 4
src/presentation/folder_presence.cpp

@@ -11,11 +11,10 @@ folder_presence_t::folder_presence_t(folder_entity_t &entity_, model::folder_inf
     : presence_t(&entity_, fi.get_device()), folder_info{fi} {
     link(&fi);
     features = features_t::folder;
-    if (fi.get_device() == entity_.get_folder().get_cluster()->get_device()) {
-        features |= features_t::local;
-    }
+    auto local = fi.get_device() == entity_.get_folder().get_cluster()->get_device();
+    features |= (local ? features_t::local : features_t::peer);
 }
 
-folder_presence_t::~folder_presence_t() {}
+folder_presence_t::~folder_presence_t() { statistics = {}; }
 
 auto folder_presence_t::get_folder_info() noexcept -> model::folder_info_t & { return folder_info; }

+ 6 - 3
src/presentation/presence.cpp

@@ -51,11 +51,14 @@ void presence_t::clear_presense() noexcept {
     }
     if (entity) {
         entity->remove_presense(*this);
-        model::intrusive_ptr_release(entity);
+        if (!(features & F::missing)) {
+            auto ex_entity = entity;
+            model::intrusive_ptr_release(ex_entity);
+        }
+        assert(statistics.size == 0);
+        assert(statistics.entities == 0);
         entity = nullptr;
     }
-    assert(statistics.size == 0);
-    assert(statistics.entities == 0);
 }
 
 void presence_t::link(augmentable_t *augmentable) noexcept { augmentable->set_augmentation(this); }

+ 48 - 61
src/ui-fltk/tree_item/presence_item.cpp

@@ -68,6 +68,17 @@ static auto make_item(presence_item_t *parent, presence_t &presence) -> presence
     return nullptr;
 }
 
+static auto get_host(presence_item_t *self) -> presence_item_t * {
+    auto presence = &self->get_presence();
+    auto parent = presence->get_parent();
+    if (parent) {
+        return static_cast<presence_item_t *>(parent->get_augmentation().get());
+    } else if (presence->get_features() & F::missing) {
+        return static_cast<missing_item_presence_t *>(self)->host;
+    }
+    return nullptr;
+}
+
 void presence_item_t::on_open() {
     if (expanded || !children()) {
         return;
@@ -78,13 +89,13 @@ void presence_item_t::on_open() {
 
     int position = 0;
     auto hide_mask = supervisor.mask_nodes();
-    for (auto p : presence->get_children()) {
-        if (!is_hidden(p, hide_mask)) {
-            auto node = make_item(this, *p);
+    for (auto c : presence->get_children()) {
+        if (!is_hidden(c, hide_mask)) {
+            auto node = make_item(this, *c);
             if (node) {
                 auto tmp_node = insert(prefs(), "", position++);
                 replace_child(tmp_node, node);
-                if (p->get_features() & F::directory) {
+                if (c->get_features() & F::directory) {
                     node->populate_dummy_child();
                 }
                 node->show(hide_mask, false, false);
@@ -113,40 +124,13 @@ int presence_item_t::get_position(const presence_item_t &child, std::uint32_t cu
         if (p == child.presence) {
             break;
         }
-        if (!(p->get_features() & cut_mask)) {
+        if (!is_hidden(p, cut_mask)) {
             ++position;
         }
     }
     return position;
 }
 
-void presence_item_t::do_show(std::uint32_t mask, bool refresh_label) {
-    auto host = parent();
-    if (!host) {
-        auto host = [&]() -> presence_item_t * {
-            auto parent = presence->get_parent();
-            if (parent) {
-                return static_cast<presence_item_t *>(parent->get_augmentation().get());
-            } else if (presence->get_features() & F::missing) {
-                return static_cast<missing_item_presence_t *>(this)->host;
-            }
-            return nullptr;
-        }();
-        if (host) {
-            auto index = host->find_child(this);
-            if (index == -1) {
-                auto position = host->get_position(*this, mask);
-                host->reparent(this, position);
-                update_label();
-                refresh_label = false;
-            }
-        }
-    }
-    if (refresh_label) {
-        update_label();
-    }
-}
-
 presence_item_ptr_t presence_item_t::do_hide() {
     auto host = parent();
     auto r = presence_item_ptr_t(this);
@@ -168,44 +152,47 @@ presence_item_ptr_t presence_item_t::do_hide() {
 }
 
 bool presence_item_t::show(std::uint32_t hide_mask, bool refresh_labels, int32_t depth) {
+    using nodes_storage_t = std::unordered_map<presentation::entity_t *, presence_item_t *>;
     assert(depth >= 0);
     if (is_hidden(presence, hide_mask)) {
         do_hide();
         return false;
     }
-    do_show(hide_mask, refresh_labels);
+    if (refresh_labels) {
+        update_label();
+    }
     if (depth >= 1 && expanded) {
-        auto &children = presence->get_children();
-        auto c = (presence_item_t *)(nullptr);
-        for (int i = 0, j = 0; i < (int)children.size(); ++i) {
-            auto p = children[i];
-            auto child_holder = presence_item_ptr_t();
-            auto item = (presence_item_t *)(nullptr);
-            bool same_name = false;
-            if (j < this->children() && !c) {
-                c = dynamic_cast<presence_item_t *>(child(j));
+        auto nodes = nodes_storage_t();
+        auto deleter = [](nodes_storage_t *nodes) {
+            for (auto it : *nodes) {
+                delete it.second;
             }
-            if (c) {
-                if (c->presence == p) {
-                    item = c;
-                } else {
-                    auto same_name = p->get_entity() == c->presence->get_entity();
-                    if (same_name) {
-                        child_holder = safe_detach(j);
-                        c = {};
-                    }
-                }
+        };
+        auto nodes_guard = std::unique_ptr<nodes_storage_t, decltype(deleter)>(&nodes, deleter);
+        while (children()) {
+            auto child = deparent(0);
+            auto node = dynamic_cast<presence_item_t *>(child);
+            if (!node) {
+                delete child;
             }
-            if (!item) {
-                item = make_item(this, *p);
-                ++j;
+            nodes.emplace(node->get_presence().get_entity(), node);
+        }
+        auto get_or_create_child = [&](presence_t *presence) -> presence_item_t * {
+            auto it = nodes.find(presence->get_entity());
+            if (it != nodes.end() && it->second->presence == presence) {
+                auto ptr = it->second;
+                nodes.erase(it);
+                return ptr;
             }
-            auto shown = item->show(hide_mask, refresh_labels, depth - 1);
-            if (item == c) {
-                c = {};
-                if (shown) {
-                    ++j;
-                }
+            return make_item(this, *presence);
+        };
+        auto &children = presence->get_children();
+        for (int i = 0, j = 0; i < (int)children.size(); ++i) {
+            auto c = children[i];
+            if (!is_hidden(c, hide_mask)) {
+                auto item = get_or_create_child(c);
+                reparent(item, j++);
+                item->show(hide_mask, refresh_labels, depth - 1);
             }
         }
     }

+ 7 - 0
tests/061-presentation.cpp

@@ -1639,6 +1639,13 @@ TEST_CASE("statistics", "[presentation]") {
         f_y_peer.reset();
         REQUIRE(builder.unshare_folder(*fi_peer).apply());
         REQUIRE(deleted_entities.size() == 2);
+
+        deleted_entities.clear();
+        REQUIRE(builder.remove_folder(*folder).apply());
+        REQUIRE(deleted_entities.size() == 3);
+
+        folder.reset();
+        REQUIRE(deleted_entities.size() == 5);
     }
 }