|
@@ -28,12 +28,13 @@
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
/*************************************************************************/
|
|
/*************************************************************************/
|
|
#include "editor_file_dialog.h"
|
|
#include "editor_file_dialog.h"
|
|
-
|
|
|
|
|
|
+#include "dependency_editor.h"
|
|
#include "editor_resource_preview.h"
|
|
#include "editor_resource_preview.h"
|
|
#include "editor_scale.h"
|
|
#include "editor_scale.h"
|
|
#include "editor_settings.h"
|
|
#include "editor_settings.h"
|
|
#include "os/file_access.h"
|
|
#include "os/file_access.h"
|
|
#include "os/keyboard.h"
|
|
#include "os/keyboard.h"
|
|
|
|
+#include "os/os.h"
|
|
#include "print_string.h"
|
|
#include "print_string.h"
|
|
#include "scene/gui/center_container.h"
|
|
#include "scene/gui/center_container.h"
|
|
#include "scene/gui/label.h"
|
|
#include "scene/gui/label.h"
|
|
@@ -159,6 +160,10 @@ void EditorFileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
|
|
_make_dir();
|
|
_make_dir();
|
|
handled = true;
|
|
handled = true;
|
|
}
|
|
}
|
|
|
|
+ if (ED_IS_SHORTCUT("file_dialog/delete", p_event)) {
|
|
|
|
+ _delete_items();
|
|
|
|
+ handled = true;
|
|
|
|
+ }
|
|
if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) {
|
|
if (ED_IS_SHORTCUT("file_dialog/focus_path", p_event)) {
|
|
dir->grab_focus();
|
|
dir->grab_focus();
|
|
handled = true;
|
|
handled = true;
|
|
@@ -512,6 +517,106 @@ void EditorFileDialog::_item_dc_selected(int p_item) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void EditorFileDialog::_item_list_item_rmb_selected(int p_item, const Vector2 &p_pos) {
|
|
|
|
+
|
|
|
|
+ // Right click on specific file(s) or folder(s).
|
|
|
|
+ item_menu->clear();
|
|
|
|
+ item_menu->set_size(Size2(1, 1));
|
|
|
|
+
|
|
|
|
+ // Allow specific actions only on one item.
|
|
|
|
+ bool single_item_selected = item_list->get_selected_items().size() == 1;
|
|
|
|
+
|
|
|
|
+ // Disallow deleting the .import folder, Godot kills a cat if you do and it is possibly a senseless novice action.
|
|
|
|
+ bool allow_delete = true;
|
|
|
|
+ for (int i = 0; i < item_list->get_item_count(); i++) {
|
|
|
|
+ if (!item_list->is_selected(i)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Dictionary item_meta = item_list->get_item_metadata(i);
|
|
|
|
+ if (item_meta["path"] == "res://.import") {
|
|
|
|
+ allow_delete = false;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (single_item_selected) {
|
|
|
|
+ item_menu->add_icon_item(get_icon("CopyNodePath", "EditorIcons"), TTR("Copy Path"), ITEM_MENU_COPY_PATH);
|
|
|
|
+ }
|
|
|
|
+ if (allow_delete) {
|
|
|
|
+ item_menu->add_icon_item(get_icon("Remove", "EditorIcons"), TTR("Delete"), ITEM_MENU_DELETE, KEY_DELETE);
|
|
|
|
+ }
|
|
|
|
+ if (single_item_selected) {
|
|
|
|
+ item_menu->add_separator();
|
|
|
|
+ item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Show In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (item_menu->get_item_count() > 0) {
|
|
|
|
+ item_menu->set_position(item_list->get_global_position() + p_pos);
|
|
|
|
+ item_menu->popup();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void EditorFileDialog::_item_list_rmb_clicked(const Vector2 &p_pos) {
|
|
|
|
+
|
|
|
|
+ // Right click on folder background. Deselect all files so that actions are applied on the current folder.
|
|
|
|
+ for (int i = 0; i < item_list->get_item_count(); i++) {
|
|
|
|
+ item_list->unselect(i);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ item_menu->clear();
|
|
|
|
+ item_menu->set_size(Size2(1, 1));
|
|
|
|
+
|
|
|
|
+ if (can_create_dir) {
|
|
|
|
+ item_menu->add_icon_item(get_icon("folder", "FileDialog"), TTR("New Folder.."), ITEM_MENU_NEW_FOLDER, KEY_MASK_CMD | KEY_N);
|
|
|
|
+ }
|
|
|
|
+ item_menu->add_icon_item(get_icon("Reload", "EditorIcons"), TTR("Refresh"), ITEM_MENU_REFRESH, KEY_F5);
|
|
|
|
+ item_menu->add_separator();
|
|
|
|
+ item_menu->add_icon_item(get_icon("Filesystem", "EditorIcons"), TTR("Show In File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
|
|
|
|
+
|
|
|
|
+ item_menu->set_position(item_list->get_global_position() + p_pos);
|
|
|
|
+ item_menu->popup();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void EditorFileDialog::_item_menu_id_pressed(int p_option) {
|
|
|
|
+
|
|
|
|
+ switch (p_option) {
|
|
|
|
+
|
|
|
|
+ case ITEM_MENU_COPY_PATH: {
|
|
|
|
+ Dictionary item_meta = item_list->get_item_metadata(item_list->get_current());
|
|
|
|
+ OS::get_singleton()->set_clipboard(item_meta["path"]);
|
|
|
|
+ } break;
|
|
|
|
+
|
|
|
|
+ case ITEM_MENU_DELETE: {
|
|
|
|
+ _delete_items();
|
|
|
|
+ } break;
|
|
|
|
+
|
|
|
|
+ case ITEM_MENU_REFRESH: {
|
|
|
|
+ invalidate();
|
|
|
|
+ } break;
|
|
|
|
+
|
|
|
|
+ case ITEM_MENU_NEW_FOLDER: {
|
|
|
|
+ _make_dir();
|
|
|
|
+ } break;
|
|
|
|
+
|
|
|
|
+ case ITEM_MENU_SHOW_IN_EXPLORER: {
|
|
|
|
+ String path;
|
|
|
|
+ int idx = item_list->get_current();
|
|
|
|
+ if (idx == -1 || item_list->get_selected_items().size() == 0) {
|
|
|
|
+ // Folder background was clicked. Open this folder.
|
|
|
|
+ path = ProjectSettings::get_singleton()->globalize_path(dir_access->get_current_dir());
|
|
|
|
+ } else {
|
|
|
|
+ // Specific item was clicked. Open folders directly, or the folder containing a selected file.
|
|
|
|
+ Dictionary item_meta = item_list->get_item_metadata(idx);
|
|
|
|
+ path = ProjectSettings::get_singleton()->globalize_path(item_meta["path"]);
|
|
|
|
+ if (!item_meta["dir"]) {
|
|
|
|
+ path = path.get_base_dir();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ OS::get_singleton()->shell_open(String("file://") + path);
|
|
|
|
+ } break;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
bool EditorFileDialog::_is_open_should_be_disabled() {
|
|
bool EditorFileDialog::_is_open_should_be_disabled() {
|
|
|
|
|
|
if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE)
|
|
if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE)
|
|
@@ -617,7 +722,7 @@ void EditorFileDialog::update_file_list() {
|
|
|
|
|
|
Dictionary d;
|
|
Dictionary d;
|
|
d["name"] = dir_name;
|
|
d["name"] = dir_name;
|
|
- d["path"] = String();
|
|
|
|
|
|
+ d["path"] = cdir.plus_file(dir_name);
|
|
d["dir"] = true;
|
|
d["dir"] = true;
|
|
|
|
|
|
item_list->set_item_metadata(item_list->get_item_count() - 1, d);
|
|
item_list->set_item_metadata(item_list->get_item_count() - 1, d);
|
|
@@ -657,8 +762,6 @@ void EditorFileDialog::update_file_list() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- String base_dir = dir_access->get_current_dir();
|
|
|
|
-
|
|
|
|
while (!files.empty()) {
|
|
while (!files.empty()) {
|
|
|
|
|
|
bool match = patterns.empty();
|
|
bool match = patterns.empty();
|
|
@@ -679,7 +782,7 @@ void EditorFileDialog::update_file_list() {
|
|
|
|
|
|
if (get_icon_func) {
|
|
if (get_icon_func) {
|
|
|
|
|
|
- Ref<Texture> icon = get_icon_func(base_dir.plus_file(files.front()->get()));
|
|
|
|
|
|
+ Ref<Texture> icon = get_icon_func(cdir.plus_file(files.front()->get()));
|
|
//ti->set_icon(0,icon);
|
|
//ti->set_icon(0,icon);
|
|
if (display_mode == DISPLAY_THUMBNAILS) {
|
|
if (display_mode == DISPLAY_THUMBNAILS) {
|
|
|
|
|
|
@@ -698,12 +801,11 @@ void EditorFileDialog::update_file_list() {
|
|
Dictionary d;
|
|
Dictionary d;
|
|
d["name"] = files.front()->get();
|
|
d["name"] = files.front()->get();
|
|
d["dir"] = false;
|
|
d["dir"] = false;
|
|
- String fullpath = base_dir.plus_file(files.front()->get());
|
|
|
|
-
|
|
|
|
|
|
+ String fullpath = cdir.plus_file(files.front()->get());
|
|
if (display_mode == DISPLAY_THUMBNAILS) {
|
|
if (display_mode == DISPLAY_THUMBNAILS) {
|
|
EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath, this, "_thumbnail_result", fullpath);
|
|
EditorResourcePreview::get_singleton()->queue_resource_preview(fullpath, this, "_thumbnail_result", fullpath);
|
|
}
|
|
}
|
|
- d["path"] = base_dir.plus_file(files.front()->get());
|
|
|
|
|
|
+ d["path"] = fullpath;
|
|
//ti->set_metadata(0,d);
|
|
//ti->set_metadata(0,d);
|
|
item_list->set_item_metadata(item_list->get_item_count() - 1, d);
|
|
item_list->set_item_metadata(item_list->get_item_count() - 1, d);
|
|
|
|
|
|
@@ -723,7 +825,7 @@ void EditorFileDialog::update_file_list() {
|
|
fav_down->set_disabled(true);
|
|
fav_down->set_disabled(true);
|
|
get_ok()->set_disabled(_is_open_should_be_disabled());
|
|
get_ok()->set_disabled(_is_open_should_be_disabled());
|
|
for (int i = 0; i < favorites->get_item_count(); i++) {
|
|
for (int i = 0; i < favorites->get_item_count(); i++) {
|
|
- if (favorites->get_item_metadata(i) == base_dir) {
|
|
|
|
|
|
+ if (favorites->get_item_metadata(i) == cdir) {
|
|
favorites->select(i);
|
|
favorites->select(i);
|
|
favorite->set_pressed(true);
|
|
favorite->set_pressed(true);
|
|
if (i > 0) {
|
|
if (i > 0) {
|
|
@@ -854,27 +956,27 @@ void EditorFileDialog::set_mode(Mode p_mode) {
|
|
case MODE_OPEN_FILE:
|
|
case MODE_OPEN_FILE:
|
|
get_ok()->set_text(TTR("Open"));
|
|
get_ok()->set_text(TTR("Open"));
|
|
set_title(TTR("Open a File"));
|
|
set_title(TTR("Open a File"));
|
|
- makedir->hide();
|
|
|
|
|
|
+ can_create_dir = false;
|
|
break;
|
|
break;
|
|
case MODE_OPEN_FILES:
|
|
case MODE_OPEN_FILES:
|
|
get_ok()->set_text(TTR("Open"));
|
|
get_ok()->set_text(TTR("Open"));
|
|
set_title(TTR("Open File(s)"));
|
|
set_title(TTR("Open File(s)"));
|
|
- makedir->hide();
|
|
|
|
|
|
+ can_create_dir = false;
|
|
break;
|
|
break;
|
|
case MODE_OPEN_DIR:
|
|
case MODE_OPEN_DIR:
|
|
get_ok()->set_text(TTR("Open"));
|
|
get_ok()->set_text(TTR("Open"));
|
|
set_title(TTR("Open a Directory"));
|
|
set_title(TTR("Open a Directory"));
|
|
- makedir->show();
|
|
|
|
|
|
+ can_create_dir = true;
|
|
break;
|
|
break;
|
|
case MODE_OPEN_ANY:
|
|
case MODE_OPEN_ANY:
|
|
get_ok()->set_text(TTR("Open"));
|
|
get_ok()->set_text(TTR("Open"));
|
|
set_title(TTR("Open a File or Directory"));
|
|
set_title(TTR("Open a File or Directory"));
|
|
- makedir->show();
|
|
|
|
|
|
+ can_create_dir = true;
|
|
break;
|
|
break;
|
|
case MODE_SAVE_FILE:
|
|
case MODE_SAVE_FILE:
|
|
get_ok()->set_text(TTR("Save"));
|
|
get_ok()->set_text(TTR("Save"));
|
|
set_title(TTR("Save a File"));
|
|
set_title(TTR("Save a File"));
|
|
- makedir->show();
|
|
|
|
|
|
+ can_create_dir = true;
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -883,6 +985,12 @@ void EditorFileDialog::set_mode(Mode p_mode) {
|
|
} else {
|
|
} else {
|
|
item_list->set_select_mode(ItemList::SELECT_SINGLE);
|
|
item_list->set_select_mode(ItemList::SELECT_SINGLE);
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if (can_create_dir) {
|
|
|
|
+ makedir->show();
|
|
|
|
+ } else {
|
|
|
|
+ makedir->hide();
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
EditorFileDialog::Mode EditorFileDialog::get_mode() const {
|
|
EditorFileDialog::Mode EditorFileDialog::get_mode() const {
|
|
@@ -954,6 +1062,28 @@ void EditorFileDialog::_make_dir() {
|
|
makedirname->grab_focus();
|
|
makedirname->grab_focus();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void EditorFileDialog::_delete_items() {
|
|
|
|
+
|
|
|
|
+ // Collect the selected folders and files to delete and check them in the deletion dependency dialog.
|
|
|
|
+ Vector<String> folders;
|
|
|
|
+ Vector<String> files;
|
|
|
|
+ for (int i = 0; i < item_list->get_item_count(); i++) {
|
|
|
|
+ if (!item_list->is_selected(i)) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ Dictionary item_meta = item_list->get_item_metadata(i);
|
|
|
|
+ if (item_meta["dir"]) {
|
|
|
|
+ folders.push_back(item_meta["path"]);
|
|
|
|
+ } else {
|
|
|
|
+ files.push_back(item_meta["path"]);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (folders.size() + files.size() > 0) {
|
|
|
|
+ remove_dialog->set_size(Size2(1, 1));
|
|
|
|
+ remove_dialog->show(folders, files);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void EditorFileDialog::_select_drive(int p_idx) {
|
|
void EditorFileDialog::_select_drive(int p_idx) {
|
|
|
|
|
|
String d = drives->get_item_text(p_idx);
|
|
String d = drives->get_item_text(p_idx);
|
|
@@ -1181,6 +1311,9 @@ void EditorFileDialog::_bind_methods() {
|
|
|
|
|
|
ClassDB::bind_method(D_METHOD("_item_selected"), &EditorFileDialog::_item_selected);
|
|
ClassDB::bind_method(D_METHOD("_item_selected"), &EditorFileDialog::_item_selected);
|
|
ClassDB::bind_method(D_METHOD("_items_clear_selection"), &EditorFileDialog::_items_clear_selection);
|
|
ClassDB::bind_method(D_METHOD("_items_clear_selection"), &EditorFileDialog::_items_clear_selection);
|
|
|
|
+ ClassDB::bind_method(D_METHOD("_item_list_item_rmb_selected"), &EditorFileDialog::_item_list_item_rmb_selected);
|
|
|
|
+ ClassDB::bind_method(D_METHOD("_item_list_rmb_clicked"), &EditorFileDialog::_item_list_rmb_clicked);
|
|
|
|
+ ClassDB::bind_method(D_METHOD("_item_menu_id_pressed"), &EditorFileDialog::_item_menu_id_pressed);
|
|
ClassDB::bind_method(D_METHOD("_item_db_selected"), &EditorFileDialog::_item_dc_selected);
|
|
ClassDB::bind_method(D_METHOD("_item_db_selected"), &EditorFileDialog::_item_dc_selected);
|
|
ClassDB::bind_method(D_METHOD("_dir_entered"), &EditorFileDialog::_dir_entered);
|
|
ClassDB::bind_method(D_METHOD("_dir_entered"), &EditorFileDialog::_dir_entered);
|
|
ClassDB::bind_method(D_METHOD("_file_entered"), &EditorFileDialog::_file_entered);
|
|
ClassDB::bind_method(D_METHOD("_file_entered"), &EditorFileDialog::_file_entered);
|
|
@@ -1326,6 +1459,7 @@ EditorFileDialog::EditorFileDialog() {
|
|
ED_SHORTCUT("file_dialog/toggle_favorite", TTR("Toggle Favorite"), KEY_MASK_ALT | KEY_F);
|
|
ED_SHORTCUT("file_dialog/toggle_favorite", TTR("Toggle Favorite"), KEY_MASK_ALT | KEY_F);
|
|
ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KEY_MASK_ALT | KEY_V);
|
|
ED_SHORTCUT("file_dialog/toggle_mode", TTR("Toggle Mode"), KEY_MASK_ALT | KEY_V);
|
|
ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KEY_MASK_CMD | KEY_N);
|
|
ED_SHORTCUT("file_dialog/create_folder", TTR("Create Folder"), KEY_MASK_CMD | KEY_N);
|
|
|
|
+ ED_SHORTCUT("file_dialog/delete", TTR("Delete"), KEY_DELETE);
|
|
ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KEY_MASK_CMD | KEY_D);
|
|
ED_SHORTCUT("file_dialog/focus_path", TTR("Focus Path"), KEY_MASK_CMD | KEY_D);
|
|
ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KEY_MASK_CMD | KEY_UP);
|
|
ED_SHORTCUT("file_dialog/move_favorite_up", TTR("Move Favorite Up"), KEY_MASK_CMD | KEY_UP);
|
|
ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KEY_MASK_CMD | KEY_DOWN);
|
|
ED_SHORTCUT("file_dialog/move_favorite_down", TTR("Move Favorite Down"), KEY_MASK_CMD | KEY_DOWN);
|
|
@@ -1432,10 +1566,21 @@ EditorFileDialog::EditorFileDialog() {
|
|
list_vb->add_child(memnew(Label(TTR("Directories & Files:"))));
|
|
list_vb->add_child(memnew(Label(TTR("Directories & Files:"))));
|
|
preview_hb->add_child(list_vb);
|
|
preview_hb->add_child(list_vb);
|
|
|
|
|
|
|
|
+ // Item (files and folders) list with context menu
|
|
|
|
+
|
|
item_list = memnew(ItemList);
|
|
item_list = memnew(ItemList);
|
|
item_list->set_v_size_flags(SIZE_EXPAND_FILL);
|
|
item_list->set_v_size_flags(SIZE_EXPAND_FILL);
|
|
|
|
+ item_list->connect("item_rmb_selected", this, "_item_list_item_rmb_selected");
|
|
|
|
+ item_list->connect("rmb_clicked", this, "_item_list_rmb_clicked");
|
|
|
|
+ item_list->set_allow_rmb_select(true);
|
|
list_vb->add_child(item_list);
|
|
list_vb->add_child(item_list);
|
|
|
|
|
|
|
|
+ item_menu = memnew(PopupMenu);
|
|
|
|
+ item_menu->connect("id_pressed", this, "_item_menu_id_pressed");
|
|
|
|
+ add_child(item_menu);
|
|
|
|
+
|
|
|
|
+ // Other stuff
|
|
|
|
+
|
|
preview_vb = memnew(VBoxContainer);
|
|
preview_vb = memnew(VBoxContainer);
|
|
preview_hb->add_child(preview_vb);
|
|
preview_hb->add_child(preview_vb);
|
|
CenterContainer *prev_cc = memnew(CenterContainer);
|
|
CenterContainer *prev_cc = memnew(CenterContainer);
|
|
@@ -1474,9 +1619,11 @@ EditorFileDialog::EditorFileDialog() {
|
|
confirm_save = memnew(ConfirmationDialog);
|
|
confirm_save = memnew(ConfirmationDialog);
|
|
confirm_save->set_as_toplevel(true);
|
|
confirm_save->set_as_toplevel(true);
|
|
add_child(confirm_save);
|
|
add_child(confirm_save);
|
|
-
|
|
|
|
confirm_save->connect("confirmed", this, "_save_confirm_pressed");
|
|
confirm_save->connect("confirmed", this, "_save_confirm_pressed");
|
|
|
|
|
|
|
|
+ remove_dialog = memnew(DependencyRemoveDialog);
|
|
|
|
+ add_child(remove_dialog);
|
|
|
|
+
|
|
makedialog = memnew(ConfirmationDialog);
|
|
makedialog = memnew(ConfirmationDialog);
|
|
makedialog->set_title(TTR("Create Folder"));
|
|
makedialog->set_title(TTR("Create Folder"));
|
|
VBoxContainer *makevb = memnew(VBoxContainer);
|
|
VBoxContainer *makevb = memnew(VBoxContainer);
|