diff --git a/src/directories.cc b/src/directories.cc index 82d9dba..80db07c 100644 --- a/src/directories.cc +++ b/src/directories.cc @@ -3,7 +3,7 @@ #include "logging.h" #include "singletons.h" #include -#include "boost/algorithm/string.hpp" +#include #include //TODO: remove using namespace std; //TODO: remove @@ -19,31 +19,46 @@ Directories::Directories() { tree_store = Gtk::TreeStore::create(column_record); tree_view.set_model(tree_store); tree_view.append_column("", column_record.name); - tree_store->set_sort_column(0, Gtk::SortType::SORT_ASCENDING); + tree_store->set_sort_column(column_record.id, Gtk::SortType::SORT_ASCENDING); tree_view.signal_row_activated().connect([this](const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column){ INFO("Directory navigation"); auto iter = tree_store->get_iter(path); if (iter) { - Gtk::TreeModel::Row row = *iter; - std::string upath = Glib::ustring(row[column_record.path]); - boost::filesystem::path fs_path(upath); - if (boost::filesystem::is_directory(fs_path)) { + auto path_str=iter->get_value(column_record.path); + if (boost::filesystem::is_directory(boost::filesystem::path(path_str))) { tree_view.row_expanded(path) ? tree_view.collapse_row(path) : tree_view.expand_row(path, false); } else { - std::stringstream sstm; - sstm << row[column_record.path]; if(on_row_activated) - on_row_activated(sstm.str()); + on_row_activated(path_str); } } }); + + tree_view.signal_test_expand_row().connect([this](const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path){ + if(iter->children().begin()->get_value(column_record.path)=="") { + add_path(iter->get_value(column_record.path), *iter); + } + return false; + }); + tree_view.signal_row_collapsed().connect([this](const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path){ + auto children=iter->children(); + if(children) { + while(children) { + tree_store->erase(children.begin()); + } + tree_store->append(iter->children()); + } + }); } void Directories::open_folder(const boost::filesystem::path& dir_path) { + if(dir_path!="") + tree_store->clear(); + auto new_path=dir_path; INFO("Open folder"); - if(new_path=="") { + if(dir_path=="") { if(current_path=="") return; new_path=current_path; @@ -56,8 +71,6 @@ void Directories::open_folder(const boost::filesystem::path& dir_path) { }); } - tree_store->clear(); - if(dir_path!="") cmake=std::unique_ptr(new CMake(new_path)); auto project=cmake->get_functions_parameters("project"); @@ -65,19 +78,44 @@ void Directories::open_folder(const boost::filesystem::path& dir_path) { tree_view.get_column(0)->set_title(project[0].second[0]); else tree_view.get_column(0)->set_title(""); - add_paths(new_path, Gtk::TreeModel::Row(), 0); + add_path(new_path, Gtk::TreeModel::Row()); for(auto &path: expanded_paths) tree_view.expand_row(path, false); current_path=new_path; - if(selected_path!="") - select_path(selected_path); DEBUG("Folder opened"); } void Directories::select_path(const boost::filesystem::path &path) { + if(current_path=="") + return; + + if(path.string().substr(0, current_path.string().size())!=current_path.string()) + return; + + if(boost::filesystem::is_directory(path)) + return; + + std::list paths; + auto parent_path=path.parent_path(); + paths.emplace_front(parent_path); + while(parent_path!=current_path) { + parent_path=parent_path.parent_path(); + paths.emplace_front(parent_path); + } + + for(auto &a_path: paths) { + tree_store->foreach_iter([this, &a_path](const Gtk::TreeModel::iterator& iter){ + if(iter->get_value(column_record.path)==a_path.string()) { + add_path(a_path, *iter); + return true; + } + return false; + }); + } + tree_store->foreach_iter([this, &path](const Gtk::TreeModel::iterator& iter){ if(iter->get_value(column_record.path)==path.string()) { auto tree_path=Gtk::TreePath(iter); @@ -106,37 +144,54 @@ bool Directories::ignored(std::string path) { return false; } -void Directories::add_paths(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &parent, unsigned row_id) { - boost::filesystem::directory_iterator end_itr; - Gtk::TreeModel::Row child; - Gtk::TreeModel::Row row; - DEBUG(""); - // Fill the treeview - for(boost::filesystem::directory_iterator itr(dir_path);itr != end_itr;++itr) { - if (!ignored(itr->path().filename().string())) { - if (boost::filesystem::is_directory(itr->status())) { - if (boost::filesystem::canonical(itr->path()) > boost::filesystem::canonical(dir_path)) { // is child - child = *(tree_store->append(parent.children())); - std::string col_id("a"+itr->path().filename().string()); - child[column_record.id] = col_id; - child[column_record.name] = itr->path().filename().string(); - child[column_record.path] = itr->path().string(); - add_paths(itr->path(), child, row_id); - } else { - row = *(tree_store->append()); - std::string col_id("a"+itr->path().filename().string()); - row[column_record.path] = itr->path().string(); - row[column_record.id] = col_id; - row[column_record.name] = itr->path().filename().string(); - add_paths(itr->path(), parent, row_id); +void Directories::add_path(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &parent) { + auto children=tree_store->children(); + if(parent) + children=parent.children(); + if(children) { + if(children.begin()->get_value(column_record.path)=="") { + tree_store->erase(parent->children().begin()); + } + } + std::unordered_set not_deleted; + boost::filesystem::directory_iterator end_it; + for(boost::filesystem::directory_iterator it(dir_path);it!=end_it;it++) { + auto filename=it->path().filename().string(); + if (!ignored(filename)) { + bool already_added=false; + if(children) { + for(auto &child: children) { + if(child.get_value(column_record.name)==filename) { + not_deleted.emplace(filename); + already_added=true; + break; + } + } + } + if(!already_added) { + auto child = tree_store->append(children); + not_deleted.emplace(filename); + child->set_value(column_record.name, filename); + child->set_value(column_record.path, it->path().string()); + if (boost::filesystem::is_directory(*it)) { + child->set_value(column_record.id, "a"+filename); + tree_store->append(child->children()); } - } else { // is a file - child = *(tree_store->append(parent.children())); - std::string col_id("b"+itr->path().filename().string()); - child[column_record.id] = col_id; - child[column_record.name] = itr->path().filename().string(); - child[column_record.path] = itr->path().string(); + else + child->set_value(column_record.id, "b"+filename); } } } + if(children) { + auto last_it=children.begin(); + for(auto it=children.begin();it!=children.end();it++) { + if(not_deleted.count(it->get_value(column_record.name))==0) { + tree_store->erase(it); + it=last_it; + } + last_it=it; + } + } + else + tree_store->append(children); } diff --git a/src/directories.h b/src/directories.h index d8dcb77..4b7b557 100644 --- a/src/directories.h +++ b/src/directories.h @@ -22,9 +22,9 @@ public: add(name); add(path); } - Gtk::TreeModelColumn id; - Gtk::TreeModelColumn name; - Gtk::TreeModelColumn path; + Gtk::TreeModelColumn id; + Gtk::TreeModelColumn name; + Gtk::TreeModelColumn path; }; Directories(); @@ -36,7 +36,7 @@ public: boost::filesystem::path current_path; private: - void add_paths(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &row, unsigned depth); + void add_path(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &row); bool ignored(std::string path); Gtk::TreeView tree_view; Glib::RefPtr tree_store;