Rework DependencyRemoveDialog for deleting folders
DependencyRemoveDialog now takes two lists (files and folders) to delete. Sort the folders above files in DependencyRemoveDialog & use some more icons. Stop files which will be deleted from also being listed as having broken dependencies. Add right-click option for removing folder to filesystem folder tree.
This commit is contained in:
parent
716e5b2943
commit
40d1866b05
|
@ -337,92 +337,142 @@ DependencyEditorOwners::DependencyEditorOwners() {
|
|||
|
||||
///////////////////////
|
||||
|
||||
void DependencyRemoveDialog::_fill_owners(EditorFileSystemDirectory *efsd) {
|
||||
void DependencyRemoveDialog::_find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder) {
|
||||
if (!efsd)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < efsd->get_subdir_count(); ++i) {
|
||||
_find_files_in_removed_folder(efsd->get_subdir(i), p_folder);
|
||||
}
|
||||
for (int i = 0; i < efsd->get_file_count(); i++) {
|
||||
String file = efsd->get_file_path(i);
|
||||
ERR_FAIL_COND(all_remove_files.has(file)); //We are deleting a directory which is contained in a directory we are deleting...
|
||||
all_remove_files[file] = p_folder; //Point the file to the ancestor directory we are deleting so we know what to parent it under in the tree.
|
||||
}
|
||||
}
|
||||
|
||||
void DependencyRemoveDialog::_find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed) {
|
||||
if (!efsd)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < efsd->get_subdir_count(); i++) {
|
||||
_fill_owners(efsd->get_subdir(i));
|
||||
_find_all_removed_dependencies(efsd->get_subdir(i), p_removed);
|
||||
}
|
||||
|
||||
for (int i = 0; i < efsd->get_file_count(); i++) {
|
||||
const String path = efsd->get_file_path(i);
|
||||
|
||||
Vector<String> deps = efsd->get_file_deps(i);
|
||||
//print_line(":::"+efsd->get_file_path(i));
|
||||
Set<String> met;
|
||||
for (int j = 0; j < deps.size(); j++) {
|
||||
if (files.has(deps[j])) {
|
||||
met.insert(deps[j]);
|
||||
}
|
||||
}
|
||||
if (!met.size())
|
||||
//It doesn't matter if a file we are about to delete will have some of its dependencies removed too
|
||||
if (all_remove_files.has(path))
|
||||
continue;
|
||||
|
||||
exist = true;
|
||||
|
||||
Ref<Texture> icon;
|
||||
String type = efsd->get_file_type(i);
|
||||
if (!has_icon(type, "EditorIcons")) {
|
||||
icon = get_icon("Object", "EditorIcons");
|
||||
} else {
|
||||
icon = get_icon(type, "EditorIcons");
|
||||
}
|
||||
|
||||
for (Set<String>::Element *E = met.front(); E; E = E->next()) {
|
||||
|
||||
String which = E->get();
|
||||
if (!files[which]) {
|
||||
TreeItem *ti = owners->create_item(owners->get_root());
|
||||
ti->set_text(0, which.get_file());
|
||||
files[which] = ti;
|
||||
Vector<String> all_deps = efsd->get_file_deps(i);
|
||||
for (int j = 0; j < all_deps.size(); ++j) {
|
||||
if (all_remove_files.has(all_deps[j])) {
|
||||
RemovedDependency dep;
|
||||
dep.file = path;
|
||||
dep.file_type = efsd->get_file_type(i);
|
||||
dep.dependency = all_deps[j];
|
||||
dep.dependency_folder = all_remove_files[all_deps[j]];
|
||||
p_removed.push_back(dep);
|
||||
}
|
||||
TreeItem *ti = owners->create_item(files[which]);
|
||||
ti->set_text(0, efsd->get_file_path(i));
|
||||
ti->set_icon(0, icon);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DependencyRemoveDialog::show(const Vector<String> &to_erase) {
|
||||
|
||||
exist = false;
|
||||
void DependencyRemoveDialog::_build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed) {
|
||||
owners->clear();
|
||||
files.clear();
|
||||
owners->create_item(); // root
|
||||
for (int i = 0; i < to_erase.size(); i++) {
|
||||
files[to_erase[i]] = NULL;
|
||||
|
||||
Map<String, TreeItem *> tree_items;
|
||||
for (int i = 0; i < p_removed.size(); i++) {
|
||||
RemovedDependency rd = p_removed[i];
|
||||
|
||||
//Ensure that the dependency is already in the tree
|
||||
if (!tree_items.has(rd.dependency)) {
|
||||
if (rd.dependency_folder.length() > 0) {
|
||||
//Ensure the ancestor folder is already in the tree
|
||||
if (!tree_items.has(rd.dependency_folder)) {
|
||||
TreeItem *folder_item = owners->create_item(owners->get_root());
|
||||
folder_item->set_text(0, rd.dependency_folder);
|
||||
folder_item->set_icon(0, get_icon("Folder", "EditorIcons"));
|
||||
tree_items[rd.dependency_folder] = folder_item;
|
||||
}
|
||||
TreeItem *dependency_item = owners->create_item(tree_items[rd.dependency_folder]);
|
||||
dependency_item->set_text(0, rd.dependency);
|
||||
dependency_item->set_icon(0, get_icon("Warning", "EditorIcons"));
|
||||
tree_items[rd.dependency] = dependency_item;
|
||||
} else {
|
||||
TreeItem *dependency_item = owners->create_item(owners->get_root());
|
||||
dependency_item->set_text(0, rd.dependency);
|
||||
dependency_item->set_icon(0, get_icon("Warning", "EditorIcons"));
|
||||
tree_items[rd.dependency] = dependency_item;
|
||||
}
|
||||
}
|
||||
|
||||
//List this file under this dependency
|
||||
Ref<Texture> icon = has_icon(rd.file_type, "EditorIcons") ? get_icon(rd.file_type, "EditorIcons") : get_icon("Object", "EditorIcons");
|
||||
TreeItem *file_item = owners->create_item(tree_items[rd.dependency]);
|
||||
file_item->set_text(0, rd.file);
|
||||
file_item->set_icon(0, icon);
|
||||
}
|
||||
}
|
||||
|
||||
void DependencyRemoveDialog::show(const Vector<String> &p_folders, const Vector<String> &p_files) {
|
||||
all_remove_files.clear();
|
||||
to_delete.clear();
|
||||
owners->clear();
|
||||
|
||||
for (int i = 0; i < p_folders.size(); ++i) {
|
||||
String folder = p_folders[i].ends_with("/") ? p_folders[i] : (p_folders[i] + "/");
|
||||
_find_files_in_removed_folder(EditorFileSystem::get_singleton()->get_filesystem_path(folder), folder);
|
||||
to_delete.push_back(folder);
|
||||
}
|
||||
for (int i = 0; i < p_files.size(); ++i) {
|
||||
all_remove_files[p_files[i]] = String();
|
||||
to_delete.push_back(p_files[i]);
|
||||
}
|
||||
|
||||
_fill_owners(EditorFileSystem::get_singleton()->get_filesystem());
|
||||
Vector<RemovedDependency> removed_deps;
|
||||
_find_all_removed_dependencies(EditorFileSystem::get_singleton()->get_filesystem(), removed_deps);
|
||||
removed_deps.sort();
|
||||
|
||||
if (exist) {
|
||||
owners->show();
|
||||
text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"));
|
||||
popup_centered_minsize(Size2(500, 220));
|
||||
} else {
|
||||
if (removed_deps.empty()) {
|
||||
owners->hide();
|
||||
text->set_text(TTR("Remove selected files from the project? (no undo)"));
|
||||
popup_centered_minsize(Size2(400, 100));
|
||||
} else {
|
||||
_build_removed_dependency_tree(removed_deps);
|
||||
owners->show();
|
||||
text->set_text(TTR("The files being removed are required by other resources in order for them to work.\nRemove them anyway? (no undo)"));
|
||||
popup_centered_minsize(Size2(500, 350));
|
||||
}
|
||||
}
|
||||
|
||||
void DependencyRemoveDialog::ok_pressed() {
|
||||
|
||||
bool changed = false;
|
||||
|
||||
for (Map<String, TreeItem *>::Element *E = files.front(); E; E = E->next()) {
|
||||
|
||||
if (ResourceCache::has(E->key())) {
|
||||
Resource *res = ResourceCache::get(E->key());
|
||||
bool files_only = true;
|
||||
for (int i = 0; i < to_delete.size(); ++i) {
|
||||
if (to_delete[i].ends_with("/")) {
|
||||
files_only = false;
|
||||
} else if (ResourceCache::has(to_delete[i])) {
|
||||
Resource *res = ResourceCache::get(to_delete[i]);
|
||||
res->set_path(""); //clear reference to path
|
||||
}
|
||||
String fpath = OS::get_singleton()->get_resource_dir() + E->key().replace_first("res://", "/");
|
||||
OS::get_singleton()->move_to_trash(fpath);
|
||||
changed = true;
|
||||
|
||||
String path = OS::get_singleton()->get_resource_dir() + to_delete[i].replace_first("res://", "/");
|
||||
print_line("Moving to trash: " + path);
|
||||
Error err = OS::get_singleton()->move_to_trash(path);
|
||||
if (err != OK) {
|
||||
EditorNode::get_singleton()->add_io_error(TTR("Cannot remove:\n") + to_delete[i] + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
if (files_only) {
|
||||
//If we only deleted files we should only need to tell the file system about the files we touched.
|
||||
for (int i = 0; i < to_delete.size(); ++i) {
|
||||
EditorFileSystem::get_singleton()->update_file(to_delete[i]);
|
||||
}
|
||||
} else {
|
||||
EditorFileSystem::get_singleton()->scan_changes();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,14 +84,33 @@ class DependencyRemoveDialog : public ConfirmationDialog {
|
|||
|
||||
Label *text;
|
||||
Tree *owners;
|
||||
bool exist;
|
||||
Map<String, TreeItem *> files;
|
||||
void _fill_owners(EditorFileSystemDirectory *efsd);
|
||||
|
||||
Map<String, String> all_remove_files;
|
||||
Vector<String> to_delete;
|
||||
|
||||
struct RemovedDependency {
|
||||
String file;
|
||||
String file_type;
|
||||
String dependency;
|
||||
String dependency_folder;
|
||||
|
||||
bool operator<(const RemovedDependency &p_other) const {
|
||||
if (dependency_folder.empty() != p_other.dependency_folder.empty()) {
|
||||
return p_other.dependency_folder.empty();
|
||||
} else {
|
||||
return dependency < p_other.dependency;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void _find_files_in_removed_folder(EditorFileSystemDirectory *efsd, const String &p_folder);
|
||||
void _find_all_removed_dependencies(EditorFileSystemDirectory *efsd, Vector<RemovedDependency> &p_removed);
|
||||
void _build_removed_dependency_tree(const Vector<RemovedDependency> &p_removed);
|
||||
|
||||
void ok_pressed();
|
||||
|
||||
public:
|
||||
void show(const Vector<String> &to_erase);
|
||||
void show(const Vector<String> &p_folders, const Vector<String> &p_files);
|
||||
DependencyRemoveDialog();
|
||||
};
|
||||
|
||||
|
|
|
@ -937,26 +937,25 @@ void FileSystemDock::_file_option(int p_option) {
|
|||
rename_dialog_text->grab_focus();
|
||||
} break;
|
||||
case FILE_REMOVE: {
|
||||
|
||||
Vector<String> torem;
|
||||
Vector<String> remove_files;
|
||||
Vector<String> remove_folders;
|
||||
|
||||
for (int i = 0; i < files->get_item_count(); i++) {
|
||||
|
||||
String path = files->get_item_metadata(i);
|
||||
if (!files->is_selected(i))
|
||||
continue;
|
||||
torem.push_back(path);
|
||||
if (files->is_selected(i) && path != "res://") {
|
||||
if (path.ends_with("/")) {
|
||||
remove_folders.push_back(path);
|
||||
} else {
|
||||
remove_files.push_back(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (torem.empty()) {
|
||||
EditorNode::get_singleton()->show_warning(TTR("No files selected!"));
|
||||
break;
|
||||
if (remove_files.size() + remove_folders.size() > 0) {
|
||||
remove_dialog->show(remove_folders, remove_files);
|
||||
//1) find if used
|
||||
//2) warn
|
||||
}
|
||||
|
||||
remove_dialog->show(torem);
|
||||
//1) find if used
|
||||
//2) warn
|
||||
|
||||
} break;
|
||||
case FILE_INFO: {
|
||||
|
||||
|
@ -1044,6 +1043,15 @@ void FileSystemDock::_folder_option(int p_option) {
|
|||
rename_dialog_text->grab_focus();
|
||||
}
|
||||
} break;
|
||||
case FOLDER_REMOVE: {
|
||||
Vector<String> remove_folders;
|
||||
Vector<String> remove_files;
|
||||
String path = item->get_metadata(tree->get_selected_column());
|
||||
if (path != "res://") {
|
||||
remove_folders.push_back(path);
|
||||
remove_dialog->show(remove_folders, remove_files);
|
||||
}
|
||||
} break;
|
||||
case FOLDER_COPY_PATH: {
|
||||
String path = item->get_metadata(tree->get_selected_column());
|
||||
OS::get_singleton()->set_clipboard(path);
|
||||
|
@ -1099,6 +1107,7 @@ void FileSystemDock::_dir_rmb_pressed(const Vector2 &p_pos) {
|
|||
if (fpath != "res://") {
|
||||
folder_options->add_item(TTR("Rename.."), FOLDER_RENAME);
|
||||
folder_options->add_item(TTR("Move To.."), FOLDER_MOVE);
|
||||
folder_options->add_item(TTR("Delete"), FOLDER_REMOVE);
|
||||
}
|
||||
folder_options->add_separator();
|
||||
folder_options->add_item(TTR("Show In File Manager"), FOLDER_SHOW_IN_EXPLORER);
|
||||
|
|
|
@ -81,6 +81,7 @@ private:
|
|||
FOLDER_COLLAPSE_ALL,
|
||||
FOLDER_MOVE,
|
||||
FOLDER_RENAME,
|
||||
FOLDER_REMOVE,
|
||||
FOLDER_SHOW_IN_EXPLORER,
|
||||
FOLDER_COPY_PATH
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue