2 Commits f61784c8a8 ... 8465a55530

Author SHA1 Message Date
  Ivan Baidakou 8465a55530 fltk, dynamically insert nodes into tree 1 week ago
  Ivan Baidakou fbb47aef5f core, file iterator take into account about folder paused state 1 week ago

+ 68 - 64
src/model/misc/file_iterator.cpp

@@ -56,34 +56,36 @@ file_info_t *file_iterator_t::next_need_cloning() noexcept {
         auto &files_map = fi.peer_folder->get_file_infos();
         auto local_folder = fi.peer_folder->get_folder()->get_folder_infos().by_device(*cluster.get_device());
 
-        while (files_scan < files_map.size()) {
-            if (it == files_map.end()) {
-                it = files_map.begin();
-            }
-            auto &file = it->item;
-            ++files_scan;
-            ++it;
-
-            if (!file->is_locally_locked() && !file->is_invalid() && file->is_global() && !file->is_invalid()) {
-                auto local = file->local_file();
-                bool need_clone = !local;
-                if (local) {
-                    if (local->is_local()) {
-                        using V = version_relation_t;
-                        auto result = compare(file->get_version(), local->get_version());
-                        need_clone = result == V::newer && file->is_locally_available();
-                    }
-                } else {
-                    need_clone = file->get_size() == 0;
+        if (!local_folder->get_folder()->is_paused()) {
+            while (files_scan < files_map.size()) {
+                if (it == files_map.end()) {
+                    it = files_map.begin();
                 }
-                if (need_clone) {
-                    fi.guarded_clones.emplace(file->get_name(), new guard_t(file, *this));
-                    return file.get();
+                auto &file = it->item;
+                ++files_scan;
+                ++it;
+
+                if (!file->is_locally_locked() && !file->is_invalid() && file->is_global() && !file->is_invalid()) {
+                    auto local = file->local_file();
+                    bool need_clone = !local;
+                    if (local) {
+                        if (local->is_local()) {
+                            using V = version_relation_t;
+                            auto result = compare(file->get_version(), local->get_version());
+                            need_clone = result == V::newer && file->is_locally_available();
+                        }
+                    } else {
+                        need_clone = file->get_size() == 0;
+                    }
+                    if (need_clone) {
+                        fi.guarded_clones.emplace(file->get_name(), new guard_t(file, *this));
+                        return file.get();
+                    }
                 }
-            }
 
-            if (files_scan == files_map.size()) {
-                break;
+                if (files_scan == files_map.size()) {
+                    break;
+                }
             }
         }
         folder_index = (folder_index + 1) % folders_count;
@@ -112,56 +114,58 @@ file_info_t *file_iterator_t::next_need_sync() noexcept {
         auto &files_map = fi.peer_folder->get_file_infos();
 
         // check other files
-        while (files_scan < files_map.size()) {
-            if (it == files_map.end()) {
-                it = files_map.begin();
-            }
-            auto &file = it->item;
-            ++files_scan;
-            ++it;
+        if (!local_folder->get_folder()->is_paused()) {
+            while (files_scan < files_map.size()) {
+                if (it == files_map.end()) {
+                    it = files_map.begin();
+                }
+                auto &file = it->item;
+                ++files_scan;
+                ++it;
 
-            if (file->is_locally_locked()) {
-                continue;
-            }
+                if (file->is_locally_locked()) {
+                    continue;
+                }
 
-            if (file->is_unreachable()) {
-                continue;
-            }
+                if (file->is_unreachable()) {
+                    continue;
+                }
 
-            if (file->is_invalid()) {
-                continue;
-            }
+                if (file->is_invalid()) {
+                    continue;
+                }
 
-            if (file->is_locally_available()) {
-                continue;
-            }
+                if (file->is_locally_available()) {
+                    continue;
+                }
 
-            if (!file->get_size()) {
-                continue;
-            }
+                if (!file->get_size()) {
+                    continue;
+                }
 
-            if (!file->is_global()) {
-                continue;
-            }
+                if (!file->is_global()) {
+                    continue;
+                }
 
-            auto accept = true;
+                auto accept = true;
 
-            if (auto local = file->local_file(); local) {
-                if (!local->is_local()) {
-                    accept = false; // file is not has been scanned
-                } else {
-                    using V = version_relation_t;
-                    auto result = compare(file->get_version(), local->get_version());
-                    accept = result == V::newer;
+                if (auto local = file->local_file(); local) {
+                    if (!local->is_local()) {
+                        accept = false; // file is not has been scanned
+                    } else {
+                        using V = version_relation_t;
+                        auto result = compare(file->get_version(), local->get_version());
+                        accept = result == V::newer;
+                    }
                 }
-            }
 
-            auto &seen_sequence = fi.committed_map[file];
-            accept = accept && seen_sequence < file->get_sequence();
+                auto &seen_sequence = fi.committed_map[file];
+                accept = accept && seen_sequence < file->get_sequence();
 
-            if (accept) {
-                fi.guarded_syncs.emplace(file->get_name(), new guard_t(file, *this));
-                return file.get();
+                if (accept) {
+                    fi.guarded_syncs.emplace(file->get_name(), new guard_t(file, *this));
+                    return file.get();
+                }
             }
         }
         folder_index = (folder_index + 1) % folders_count;

+ 31 - 0
src/ui-fltk/app_supervisor.cpp

@@ -1,6 +1,7 @@
 #include "app_supervisor.h"
 #include "main_window.h"
 #include "tree_item/devices.h"
+#include "tree_item/folder.h"
 #include "tree_item/folders.h"
 #include "tree_item/ignored_devices.h"
 #include "tree_item/peer_device.h"
@@ -15,6 +16,8 @@
 #include "model/diff/modify/add_ignored_device.h"
 #include "model/diff/modify/add_pending_device.h"
 #include "model/diff/modify/add_pending_folders.h"
+#include "model/diff/modify/clone_file.h"
+#include "model/diff/modify/finish_file_ack.h"
 #include "model/diff/modify/upsert_folder.h"
 #include "model/diff/modify/upsert_folder_info.h"
 #include "model/diff/modify/update_peer.h"
@@ -341,6 +344,34 @@ auto app_supervisor_t::operator()(const model::diff::modify::add_ignored_device_
     return diff.visit_next(*this, custom);
 }
 
+auto app_supervisor_t::operator()(const model::diff::modify::clone_file_t &diff, void *custom) noexcept
+    -> outcome::result<void> {
+    auto folder = cluster->get_folders().by_id(diff.folder_id);
+    auto folder_info = folder->get_folder_infos().by_device(*cluster->get_device());
+    auto generic_augmnetation = folder_info->get_augmentation();
+    auto augmentation = static_cast<augmentation_base_t *>(generic_augmnetation.get());
+    auto folder_entry = static_cast<tree_item::folder_t *>(augmentation->get_owner());
+    auto file_info = folder_info->get_file_infos().by_name(diff.proto_file.name());
+    auto path = bfs::path(file_info->get_name());
+    auto dir = folder_entry->locate_dir(path.parent_path());
+    dir->add_entry(*file_info);
+    return diff.visit_next(*this, custom);
+}
+
+auto app_supervisor_t::operator()(const model::diff::modify::finish_file_ack_t &diff, void *custom) noexcept
+    -> outcome::result<void> {
+    auto folder = cluster->get_folders().by_id(diff.folder_id);
+    auto folder_info = folder->get_folder_infos().by_device(*cluster->get_device());
+    auto generic_augmnetation = folder_info->get_augmentation();
+    auto augmentation = static_cast<augmentation_base_t *>(generic_augmnetation.get());
+    auto folder_entry = static_cast<tree_item::folder_t *>(augmentation->get_owner());
+    auto file_info = folder_info->get_file_infos().by_name(diff.proto_file.name());
+    auto path = bfs::path(file_info->get_name());
+    auto dir = folder_entry->locate_dir(path.parent_path());
+    dir->add_entry(*file_info);
+    return diff.visit_next(*this, custom);
+}
+
 auto app_supervisor_t::operator()(const model::diff::modify::upsert_folder_t &diff, void *custom) noexcept
     -> outcome::result<void> {
     auto &folder = *cluster->get_folders().by_id(diff.db.id());

+ 2 - 0
src/ui-fltk/app_supervisor.h

@@ -148,6 +148,8 @@ struct app_supervisor_t : rf::supervisor_fltk_t, private model::diff::cluster_vi
     outcome::result<void> operator()(const model::diff::modify::add_pending_folders_t &, void *) noexcept override;
     outcome::result<void> operator()(const model::diff::modify::add_pending_device_t &, void *) noexcept override;
     outcome::result<void> operator()(const model::diff::modify::add_ignored_device_t &, void *) noexcept override;
+    outcome::result<void> operator()(const model::diff::modify::clone_file_t &, void *) noexcept override;
+    outcome::result<void> operator()(const model::diff::modify::finish_file_ack_t &, void *) noexcept override;
     outcome::result<void> operator()(const model::diff::modify::update_peer_t &, void *) noexcept override;
     outcome::result<void> operator()(const model::diff::modify::upsert_folder_t &, void *) noexcept override;
     outcome::result<void> operator()(const model::diff::modify::upsert_folder_info_t &, void *) noexcept override;

+ 56 - 18
src/ui-fltk/tree_item/entry.cpp

@@ -28,24 +28,34 @@ entry_t *entry_t::locate_own_dir(std::string_view name) {
     }
 
     auto it = dirs_map.find(name);
-    assert(it != dirs_map.end());
-    return it->second;
+    if (it != dirs_map.end()) {
+        return it->second;
+    }
+
+    auto label = std::string(name);
+    auto node = within_tree([&]() -> entry_t * { return make_entry(nullptr, label); });
+    node->update_label();
+
+    auto name_provider = [this](int index) { return std::string_view(child(index)->label()); };
+    auto pos = bisect(node->label(), 0, dirs_count - 1, children(), name_provider);
+    auto tmp_node = insert(prefs(), "", pos);
+    replace_child(tmp_node, node);
+    tree()->close(node);
+    dirs_map[label] = node;
+
+    ++dirs_count;
+    assert(dirs_count <= children());
+    return node;
 }
 
 void entry_t::add_entry(model::file_info_t &file) {
     bool deleted = file.is_deleted();
     bool show_deleted = supervisor.get_app_config().fltk_config.display_deleted;
     auto name_provider = [this](int index) { return std::string_view(child(index)->label()); };
-    auto start_index = int{0};
-    auto end_index = int{0};
     auto t = tree();
-    auto node = within_tree([&]() -> entry_t * { return make_entry(file); });
+    auto node = within_tree([&]() -> entry_t * { return make_entry(&file, file.get_path().filename().string()); });
     node->update_label();
-    auto name = std::string(node->label());
 
-    if (file.is_dir()) {
-        dirs_map[name] = node;
-    }
     if (deleted) {
         deleted_items.emplace(node);
     }
@@ -60,12 +70,13 @@ void entry_t::add_entry(model::file_info_t &file) {
 void entry_t::remove_child(tree_item_t *child) { remove_node(static_cast<entry_t *>(child)); }
 
 void entry_t::remove_node(entry_t *child) {
-    auto &entry = *child->get_entry();
-    if (entry.is_dir()) {
+    auto entry = child->get_entry();
+    if ((entry && entry->is_dir()) || !entry) {
         --dirs_count;
+        assert(dirs_count >= 0);
     }
     if (child->augmentation) {
-        if (entry.is_deleted()) {
+        if (entry && entry->is_deleted()) {
             deleted_items.emplace(child);
         } else {
             auto it = deleted_items.find(child);
@@ -85,7 +96,7 @@ void entry_t::remove_node(entry_t *child) {
     }
 }
 
-void entry_t::insert_node(entry_t *node) {
+bool entry_t::insert_node(entry_t *node) {
     auto name_provider = [this](int index) { return std::string_view(child(index)->label()); };
     auto start_index = int{0};
     auto end_index = int{0};
@@ -93,19 +104,44 @@ void entry_t::insert_node(entry_t *node) {
 
     if (directory) {
         end_index = dirs_count - 1;
-        ++dirs_count;
     } else {
         start_index = dirs_count;
         end_index = children() - 1;
     }
 
     auto pos = bisect(node->label(), start_index, end_index, children(), name_provider);
-    auto tmp_node = insert(prefs(), "", pos);
-    replace_child(tmp_node, node);
+    bool exists = false;
+    if (directory && pos <= end_index) {
+        auto previous = reinterpret_cast<entry_t *>(child(pos));
+        if (previous->label() == std::string_view(node->label())) {
+            assert(previous->dirs_count <= previous->children());
+            for (auto i = 0; previous->children(); ++i) {
+                auto c = previous->deparent(0);
+                node->reparent(c, i);
+            }
+            assert(!previous->children());
+            node->dirs_count = previous->dirs_count;
+            node->dirs_map = std::move(previous->dirs_map);
+            node->orphaned_items = std::move(previous->orphaned_items);
+            node->deleted_items = std::move(previous->deleted_items);
+            previous->augmentation.reset();
+            remove_node(previous);
+        }
+    }
 
-    if (directory) {
-        tree()->close(node);
+    if (!exists) {
+        auto tmp_node = insert(prefs(), "", pos);
+        replace_child(tmp_node, node);
+
+        if (directory) {
+            auto name = std::string(node->label());
+            dirs_map[name] = node;
+            ++dirs_count;
+            tree()->close(node);
+        }
     }
+
+    return exists;
 }
 
 void entry_t::show_deleted(bool value) {
@@ -165,3 +201,5 @@ void entry_t::make_hierarchy(model::file_infos_map_t &files_map) {
     }
     tree()->redraw();
 }
+
+void entry_t::assign(entry_t &) { assert(0 && "should not happen"); }

+ 3 - 2
src/ui-fltk/tree_item/entry.h

@@ -27,15 +27,16 @@ struct entry_t : tree_item_t {
     virtual void add_entry(model::file_info_t &file);
     virtual void show_deleted(bool value);
     virtual void apply(const entry_visitor_t &visitor, void *data);
+    virtual void assign(entry_t &);
 
     void remove_child(tree_item_t *child) override;
 
     void remove_node(entry_t *child);
-    void insert_node(entry_t *node);
+    bool insert_node(entry_t *node);
 
     void make_hierarchy(model::file_infos_map_t &files);
 
-    virtual entry_t *make_entry(model::file_info_t &file) = 0;
+    virtual entry_t *make_entry(model::file_info_t *file, std::string filename) = 0;
 
     int dirs_count;
     dirs_map_t dirs_map;

+ 4 - 2
src/ui-fltk/tree_item/folder.cpp

@@ -180,7 +180,7 @@ struct table_t : content::folder_table_t {
         scan_finish_cell->update(scan_finish);
 
         auto entries_size = std::size_t{0};
-        for (auto& it: static_cast<folder_t&>(container).folder_info->get_file_infos()) {
+        for (auto &it : static_cast<folder_t &>(container).folder_info->get_file_infos()) {
             entries_size += it.item->get_size();
         }
         auto entries_count = description.get_file_infos().size();
@@ -241,4 +241,6 @@ bool folder_t::on_select() {
 
 auto folder_t::get_entry() -> model::file_info_t * { return nullptr; }
 
-auto folder_t::make_entry(model::file_info_t &file) -> entry_t * { return new local_entry_t(supervisor, tree(), file); }
+auto folder_t::make_entry(model::file_info_t *file, std::string filename) -> entry_t * {
+    return new local_entry_t(supervisor, tree(), file, std::move(filename));
+}

+ 1 - 1
src/ui-fltk/tree_item/folder.h

@@ -13,7 +13,7 @@ struct folder_t final : entry_t {
     void update_label() override;
 
     model::file_info_t *get_entry() override;
-    entry_t *make_entry(model::file_info_t &file) override;
+    entry_t *make_entry(model::file_info_t *file, std::string filename) override;
 
     model::folder_t &folder;
     model::folder_info_t *folder_info;

+ 43 - 28
src/ui-fltk/tree_item/local_entry.cpp

@@ -4,50 +4,65 @@
 using namespace syncspirit::fltk;
 using namespace syncspirit::fltk::tree_item;
 
-local_entry_t::local_entry_t(app_supervisor_t &supervisor, Fl_Tree *tree, model::file_info_t &entry_)
-    : parent_t(supervisor, tree, true), entry{entry_} {
-    entry.set_augmentation(get_proxy());
+local_entry_t::local_entry_t(app_supervisor_t &supervisor, Fl_Tree *tree, model::file_info_t *entry_,
+                             std::string filename_)
+    : parent_t(supervisor, tree, true), entry{entry_}, filename{std::move(filename_)} {
+    if (entry) {
+        entry->set_augmentation(get_proxy());
+    }
 }
 
 void local_entry_t::update_label() {
-    auto &entry = *get_entry();
-    auto name = get_entry()->get_path().filename().string();
-    label(name.c_str());
-    if (entry.is_deleted()) {
-        labelfgcolor(FL_DARK1);
-    } else if (entry.is_global()) {
-        labelfgcolor(FL_GREEN);
-    } else {
-        labelfgcolor(FL_BLACK);
+    if (entry) {
+        filename = get_entry()->get_path().filename().string();
+        if (entry->is_deleted()) {
+            labelfgcolor(FL_DARK1);
+        } else if (entry->is_global()) {
+            labelfgcolor(FL_GREEN);
+        } else {
+            labelfgcolor(FL_BLACK);
+        }
     }
+    label(filename.c_str());
     tree()->redraw();
 }
 
 bool local_entry_t::on_select() {
-    content = supervisor.replace_content([&](content_t *content) -> content_t * {
-        auto prev = content->get_widget();
-        int x = prev->x(), y = prev->y(), w = prev->w(), h = prev->h();
-        return new content::remote_file_table_t(*this, x, y, w, h);
-    });
+    if (entry) {
+        content = supervisor.replace_content([&](content_t *content) -> content_t * {
+            auto prev = content->get_widget();
+            int x = prev->x(), y = prev->y(), w = prev->w(), h = prev->h();
+            return new content::remote_file_table_t(*this, x, y, w, h);
+        });
+    }
     return true;
 }
 
 void local_entry_t::on_update() {
     parent_t::on_update();
-    auto &entry = *get_entry();
-    if (entry.is_deleted()) {
-        auto host = static_cast<entry_t *>(parent());
-        bool show_deleted = supervisor.get_app_config().fltk_config.display_deleted;
-        if (!show_deleted) {
-            host->remove_child(this);
-        } else {
-            host->deleted_items.emplace(this);
+    if (entry) {
+        if (entry->is_deleted()) {
+            auto host = static_cast<entry_t *>(parent());
+            bool show_deleted = supervisor.get_app_config().fltk_config.display_deleted;
+            if (!show_deleted) {
+                host->remove_child(this);
+            } else {
+                host->deleted_items.emplace(this);
+            }
         }
     }
 }
 
-auto local_entry_t::get_entry() -> model::file_info_t * { return &entry; }
+auto local_entry_t::get_entry() -> model::file_info_t * { return entry; }
+
+auto local_entry_t::make_entry(model::file_info_t *file, std::string filename) -> entry_t * {
+    return new local_entry_t(supervisor, tree(), file, std::move(filename));
+}
 
-auto local_entry_t::make_entry(model::file_info_t &file) -> entry_t * {
-    return new local_entry_t(supervisor, tree(), file);
+void local_entry_t::assign(entry_t &new_entry) {
+    auto &e = dynamic_cast<local_entry_t &>(new_entry);
+    entry = e.entry;
+    entry->set_augmentation(get_proxy());
+    e.get_proxy()->release_onwer();
+    on_update();
 }

+ 5 - 3
src/ui-fltk/tree_item/local_entry.h

@@ -6,16 +6,18 @@ namespace syncspirit::fltk::tree_item {
 
 struct local_entry_t final : entry_t {
     using parent_t = entry_t;
-    local_entry_t(app_supervisor_t &supervisor, Fl_Tree *tree, model::file_info_t &entry);
+    local_entry_t(app_supervisor_t &supervisor, Fl_Tree *tree, model::file_info_t *entry, std::string filename);
 
     bool on_select() override;
     void update_label() override;
     void on_update() override;
 
     model::file_info_t *get_entry() override;
-    entry_t *make_entry(model::file_info_t &file) override;
+    entry_t *make_entry(model::file_info_t *file, std::string) override;
+    void assign(entry_t &) override;
 
-    model::file_info_t &entry;
+    model::file_info_t *entry;
+    std::string filename;
 };
 
 }; // namespace syncspirit::fltk::tree_item

+ 0 - 0
src/ui-fltk/tree_item/peer_entry.cpp


Some files were not shown because too many files changed in this diff