Merge pull request #13446 from gad-o/duplicate_file
Add duplicate option to filesystem dock
This commit is contained in:
commit
5b54690323
2 changed files with 106 additions and 0 deletions
|
@ -806,6 +806,39 @@ void FileSystemDock::_try_move_item(const FileOrFolder &p_item, const String &p_
|
||||||
memdelete(da);
|
memdelete(da);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileSystemDock::_try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const {
|
||||||
|
//Ensure folder paths end with "/"
|
||||||
|
String old_path = (p_item.is_file || p_item.path.ends_with("/")) ? p_item.path : (p_item.path + "/");
|
||||||
|
String new_path = (p_item.is_file || p_new_path.ends_with("/")) ? p_new_path : (p_new_path + "/");
|
||||||
|
|
||||||
|
if (new_path == old_path) {
|
||||||
|
return;
|
||||||
|
} else if (old_path == "res://") {
|
||||||
|
EditorNode::get_singleton()->add_io_error(TTR("Cannot move/rename resources root."));
|
||||||
|
return;
|
||||||
|
} else if (!p_item.is_file && new_path.begins_with(old_path)) {
|
||||||
|
//This check doesn't erroneously catch renaming to a longer name as folder paths always end with "/"
|
||||||
|
EditorNode::get_singleton()->add_io_error(TTR("Cannot move a folder into itself.\n") + old_path + "\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||||
|
print_line("Duplicating " + old_path + " -> " + new_path);
|
||||||
|
Error err = da->copy(old_path, new_path);
|
||||||
|
if (err == OK) {
|
||||||
|
//Move/Rename any corresponding import settings too
|
||||||
|
if (p_item.is_file && FileAccess::exists(old_path + ".import")) {
|
||||||
|
err = da->copy(old_path + ".import", new_path + ".import");
|
||||||
|
if (err != OK) {
|
||||||
|
EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + ".import\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
EditorNode::get_singleton()->add_io_error(TTR("Error duplicating:\n") + old_path + "\n");
|
||||||
|
}
|
||||||
|
memdelete(da);
|
||||||
|
}
|
||||||
|
|
||||||
void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const {
|
void FileSystemDock::_update_dependencies_after_move(const Map<String, String> &p_renames) const {
|
||||||
//The following code assumes that the following holds:
|
//The following code assumes that the following holds:
|
||||||
// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
|
// 1) EditorFileSystem contains the old paths/folder structure from before the rename/move.
|
||||||
|
@ -888,6 +921,39 @@ void FileSystemDock::_rename_operation_confirm() {
|
||||||
_rescan();
|
_rescan();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileSystemDock::_duplicate_operation_confirm() {
|
||||||
|
|
||||||
|
String new_name = duplicate_dialog_text->get_text().strip_edges();
|
||||||
|
if (new_name.length() == 0) {
|
||||||
|
EditorNode::get_singleton()->show_warning(TTR("No name provided."));
|
||||||
|
return;
|
||||||
|
} else if (new_name.find("/") != -1 || new_name.find("\\") != -1 || new_name.find(":") != -1) {
|
||||||
|
EditorNode::get_singleton()->show_warning(TTR("Name contains invalid characters."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String old_path = to_duplicate.path.ends_with("/") ? to_duplicate.path.substr(0, to_duplicate.path.length() - 1) : to_rename.path;
|
||||||
|
String new_path = old_path.get_base_dir().plus_file(new_name);
|
||||||
|
if (old_path == new_path) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Present a more user friendly warning for name conflict
|
||||||
|
DirAccess *da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
|
||||||
|
if (da->file_exists(new_path) || da->dir_exists(new_path)) {
|
||||||
|
EditorNode::get_singleton()->show_warning(TTR("A file or folder with this name already exists."));
|
||||||
|
memdelete(da);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memdelete(da);
|
||||||
|
|
||||||
|
_try_duplicate_item(to_duplicate, new_name);
|
||||||
|
|
||||||
|
//Rescan everything
|
||||||
|
print_line("call rescan!");
|
||||||
|
_rescan();
|
||||||
|
}
|
||||||
|
|
||||||
void FileSystemDock::_move_operation_confirm(const String &p_to_path) {
|
void FileSystemDock::_move_operation_confirm(const String &p_to_path) {
|
||||||
|
|
||||||
Map<String, String> renames;
|
Map<String, String> renames;
|
||||||
|
@ -1003,6 +1069,27 @@ void FileSystemDock::_file_option(int p_option) {
|
||||||
//2) warn
|
//2) warn
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case FILE_DUPLICATE: {
|
||||||
|
int idx = files->get_current();
|
||||||
|
if (idx < 0 || idx >= files->get_item_count())
|
||||||
|
break;
|
||||||
|
|
||||||
|
to_duplicate.path = files->get_item_metadata(idx);
|
||||||
|
to_duplicate.is_file = !to_duplicate.path.ends_with("/");
|
||||||
|
if (to_duplicate.is_file) {
|
||||||
|
String name = to_duplicate.path.get_file();
|
||||||
|
duplicate_dialog->set_title(TTR("Duplicating file:") + " " + name);
|
||||||
|
duplicate_dialog_text->set_text(name);
|
||||||
|
duplicate_dialog_text->select(0, name.find_last("."));
|
||||||
|
} else {
|
||||||
|
String name = to_duplicate.path.substr(0, to_duplicate.path.length() - 1).get_file();
|
||||||
|
duplicate_dialog->set_title(TTR("Duplicating folder:") + " " + name);
|
||||||
|
duplicate_dialog_text->set_text(name);
|
||||||
|
duplicate_dialog_text->select(0, name.length());
|
||||||
|
}
|
||||||
|
duplicate_dialog->popup_centered_minsize(Size2(250, 80) * EDSCALE);
|
||||||
|
duplicate_dialog_text->grab_focus();
|
||||||
|
} break;
|
||||||
case FILE_INFO: {
|
case FILE_INFO: {
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -1459,6 +1546,7 @@ void FileSystemDock::_files_list_rmb_select(int p_item, const Vector2 &p_pos) {
|
||||||
if (num_items == 1) {
|
if (num_items == 1) {
|
||||||
file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH);
|
file_options->add_item(TTR("Copy Path"), FILE_COPY_PATH);
|
||||||
file_options->add_item(TTR("Rename.."), FILE_RENAME);
|
file_options->add_item(TTR("Rename.."), FILE_RENAME);
|
||||||
|
file_options->add_item(TTR("Duplicate.."), FILE_DUPLICATE);
|
||||||
}
|
}
|
||||||
file_options->add_item(TTR("Move To.."), FILE_MOVE);
|
file_options->add_item(TTR("Move To.."), FILE_MOVE);
|
||||||
file_options->add_item(TTR("Delete"), FILE_REMOVE);
|
file_options->add_item(TTR("Delete"), FILE_REMOVE);
|
||||||
|
@ -1570,6 +1658,7 @@ void FileSystemDock::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileSystemDock::_make_dir_confirm);
|
ClassDB::bind_method(D_METHOD("_make_dir_confirm"), &FileSystemDock::_make_dir_confirm);
|
||||||
ClassDB::bind_method(D_METHOD("_move_operation_confirm"), &FileSystemDock::_move_operation_confirm);
|
ClassDB::bind_method(D_METHOD("_move_operation_confirm"), &FileSystemDock::_move_operation_confirm);
|
||||||
ClassDB::bind_method(D_METHOD("_rename_operation_confirm"), &FileSystemDock::_rename_operation_confirm);
|
ClassDB::bind_method(D_METHOD("_rename_operation_confirm"), &FileSystemDock::_rename_operation_confirm);
|
||||||
|
ClassDB::bind_method(D_METHOD("_duplicate_operation_confirm"), &FileSystemDock::_duplicate_operation_confirm);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_search_changed"), &FileSystemDock::_search_changed);
|
ClassDB::bind_method(D_METHOD("_search_changed"), &FileSystemDock::_search_changed);
|
||||||
|
|
||||||
|
@ -1743,6 +1832,17 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
|
||||||
rename_dialog->register_text_enter(rename_dialog_text);
|
rename_dialog->register_text_enter(rename_dialog_text);
|
||||||
rename_dialog->connect("confirmed", this, "_rename_operation_confirm");
|
rename_dialog->connect("confirmed", this, "_rename_operation_confirm");
|
||||||
|
|
||||||
|
duplicate_dialog = memnew(ConfirmationDialog);
|
||||||
|
VBoxContainer *duplicate_dialog_vb = memnew(VBoxContainer);
|
||||||
|
duplicate_dialog->add_child(duplicate_dialog_vb);
|
||||||
|
|
||||||
|
duplicate_dialog_text = memnew(LineEdit);
|
||||||
|
duplicate_dialog_vb->add_margin_child(TTR("Name:"), duplicate_dialog_text);
|
||||||
|
duplicate_dialog->get_ok()->set_text(TTR("Duplicate"));
|
||||||
|
add_child(duplicate_dialog);
|
||||||
|
duplicate_dialog->register_text_enter(duplicate_dialog_text);
|
||||||
|
duplicate_dialog->connect("confirmed", this, "_duplicate_operation_confirm");
|
||||||
|
|
||||||
make_dir_dialog = memnew(ConfirmationDialog);
|
make_dir_dialog = memnew(ConfirmationDialog);
|
||||||
make_dir_dialog->set_title(TTR("Create Folder"));
|
make_dir_dialog->set_title(TTR("Create Folder"));
|
||||||
VBoxContainer *make_folder_dialog_vb = memnew(VBoxContainer);
|
VBoxContainer *make_folder_dialog_vb = memnew(VBoxContainer);
|
||||||
|
|
|
@ -70,6 +70,7 @@ private:
|
||||||
FILE_MOVE,
|
FILE_MOVE,
|
||||||
FILE_RENAME,
|
FILE_RENAME,
|
||||||
FILE_REMOVE,
|
FILE_REMOVE,
|
||||||
|
FILE_DUPLICATE,
|
||||||
FILE_REIMPORT,
|
FILE_REIMPORT,
|
||||||
FILE_INFO,
|
FILE_INFO,
|
||||||
FILE_NEW_FOLDER,
|
FILE_NEW_FOLDER,
|
||||||
|
@ -120,6 +121,8 @@ private:
|
||||||
EditorDirDialog *move_dialog;
|
EditorDirDialog *move_dialog;
|
||||||
ConfirmationDialog *rename_dialog;
|
ConfirmationDialog *rename_dialog;
|
||||||
LineEdit *rename_dialog_text;
|
LineEdit *rename_dialog_text;
|
||||||
|
ConfirmationDialog *duplicate_dialog;
|
||||||
|
LineEdit *duplicate_dialog_text;
|
||||||
ConfirmationDialog *make_dir_dialog;
|
ConfirmationDialog *make_dir_dialog;
|
||||||
LineEdit *make_dir_dialog_text;
|
LineEdit *make_dir_dialog_text;
|
||||||
|
|
||||||
|
@ -136,6 +139,7 @@ private:
|
||||||
is_file(p_is_file) {}
|
is_file(p_is_file) {}
|
||||||
};
|
};
|
||||||
FileOrFolder to_rename;
|
FileOrFolder to_rename;
|
||||||
|
FileOrFolder to_duplicate;
|
||||||
Vector<FileOrFolder> to_move;
|
Vector<FileOrFolder> to_move;
|
||||||
|
|
||||||
Vector<String> history;
|
Vector<String> history;
|
||||||
|
@ -172,10 +176,12 @@ private:
|
||||||
void _get_all_files_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files) const;
|
void _get_all_files_in_dir(EditorFileSystemDirectory *efsd, Vector<String> &files) const;
|
||||||
void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const;
|
void _find_remaps(EditorFileSystemDirectory *efsd, const Map<String, String> &renames, Vector<String> &to_remaps) const;
|
||||||
void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) const;
|
void _try_move_item(const FileOrFolder &p_item, const String &p_new_path, Map<String, String> &p_renames) const;
|
||||||
|
void _try_duplicate_item(const FileOrFolder &p_item, const String &p_new_path) const;
|
||||||
void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
|
void _update_dependencies_after_move(const Map<String, String> &p_renames) const;
|
||||||
|
|
||||||
void _make_dir_confirm();
|
void _make_dir_confirm();
|
||||||
void _rename_operation_confirm();
|
void _rename_operation_confirm();
|
||||||
|
void _duplicate_operation_confirm();
|
||||||
void _move_operation_confirm(const String &p_to_path);
|
void _move_operation_confirm(const String &p_to_path);
|
||||||
|
|
||||||
void _file_option(int p_option);
|
void _file_option(int p_option);
|
||||||
|
|
Loading…
Reference in a new issue