Skip to content

Commit f9a2ecd

Browse files
committed
Merge pull request godotengine#111116 from KoBeWi/fdm
Unify FileDialog context menus
2 parents 3b04c84 + 9af58c1 commit f9a2ecd

File tree

3 files changed

+98
-27
lines changed

3 files changed

+98
-27
lines changed

doc/classes/FileDialog.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@
207207
<member name="current_path" type="String" setter="set_current_path" getter="get_current_path">
208208
The currently selected file path of the file dialog.
209209
</member>
210+
<member name="deleting_enabled" type="bool" setter="set_customization_flag_enabled" getter="is_customization_flag_enabled" default="true">
211+
If [code]true[/code], the context menu will show the "Delete" option, which allows moving files and folders to trash.
212+
</member>
210213
<member name="dialog_hide_on_ok" type="bool" setter="set_hide_on_ok" getter="get_hide_on_ok" overrides="AcceptDialog" default="false" />
211214
<member name="display_mode" type="int" setter="set_display_mode" getter="get_display_mode" enum="FileDialog.DisplayMode" default="0">
212215
Display mode of the dialog's file list.
@@ -232,7 +235,7 @@
232235
[b]Note:[/b] Embedded file dialog and Windows file dialog support only file extensions, while Android, Linux, and macOS file dialogs also support MIME types.
233236
</member>
234237
<member name="folder_creation_enabled" type="bool" setter="set_customization_flag_enabled" getter="is_customization_flag_enabled" default="true">
235-
If [code]true[/code], shows the button for creating new directories (when using [constant FILE_MODE_OPEN_DIR], [constant FILE_MODE_OPEN_ANY], or [constant FILE_MODE_SAVE_FILE]).
238+
If [code]true[/code], shows the button for creating new directories (when using [constant FILE_MODE_OPEN_DIR], [constant FILE_MODE_OPEN_ANY], or [constant FILE_MODE_SAVE_FILE]), and the context menu will have the "New Folder..." option.
236239
</member>
237240
<member name="hidden_files_toggle_enabled" type="bool" setter="set_customization_flag_enabled" getter="is_customization_flag_enabled" default="true">
238241
If [code]true[/code], shows the toggle hidden files button.
@@ -359,6 +362,10 @@
359362
If enabled, the [FileDialog] will warn the user before overwriting files in save mode.
360363
Equivalent to [member overwrite_warning_enabled].
361364
</constant>
365+
<constant name="CUSTOMIZATION_DELETE" value="8" enum="Customization">
366+
If enabled, the context menu will show the "Delete" option, which allows moving files and folders to trash.
367+
Equivalent to [member deleting_enabled].
368+
</constant>
362369
</constants>
363370
<theme_items>
364371
<theme_item name="file_disabled_color" data_type="color" type="Color" default="Color(1, 1, 1, 0.25)">

scene/gui/file_dialog.cpp

Lines changed: 81 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,11 @@ int FileDialog::_get_selected_file_idx() {
653653
return selected.is_empty() ? -1 : selected[0];
654654
}
655655

656+
String FileDialog::_get_item_path(int p_idx) const {
657+
const Dictionary meta = file_list->get_item_metadata(p_idx);
658+
return ProjectSettings::get_singleton()->globalize_path(dir_access->get_current_dir().path_join(meta["name"]));
659+
}
660+
656661
void FileDialog::_file_list_multi_selected(int p_item, bool p_selected) {
657662
if (p_selected) {
658663
_file_list_selected(p_item);
@@ -715,13 +720,32 @@ void FileDialog::update_file_name() {
715720
}
716721

717722
void FileDialog::_item_menu_id_pressed(int p_option) {
723+
int selected = _get_selected_file_idx();
718724
switch (p_option) {
725+
case ITEM_MENU_COPY_PATH: {
726+
if (selected > -1) {
727+
DisplayServer::get_singleton()->clipboard_set(_get_item_path(selected));
728+
}
729+
} break;
730+
731+
case ITEM_MENU_DELETE: {
732+
if (selected > -1) {
733+
delete_dialog->popup_centered(Size2(250, 80));
734+
}
735+
} break;
736+
737+
case ITEM_MENU_REFRESH: {
738+
invalidate();
739+
} break;
740+
741+
case ITEM_MENU_NEW_FOLDER: {
742+
_make_dir();
743+
} break;
744+
719745
case ITEM_MENU_SHOW_IN_EXPLORER: {
720746
String path;
721-
int selected = _get_selected_file_idx();
722747
if (selected > -1) {
723-
Dictionary d = file_list->get_item_metadata(selected);
724-
path = ProjectSettings::get_singleton()->globalize_path(dir_access->get_current_dir().path_join(d["name"]));
748+
path = _get_item_path(selected);
725749
} else {
726750
path = ProjectSettings::get_singleton()->globalize_path(dir_access->get_current_dir());
727751
}
@@ -730,12 +754,11 @@ void FileDialog::_item_menu_id_pressed(int p_option) {
730754
} break;
731755

732756
case ITEM_MENU_SHOW_BUNDLE_CONTENT: {
733-
int selected = _get_selected_file_idx();
734757
if (selected == -1) {
735758
return;
736759
}
737-
Dictionary d = file_list->get_item_metadata(selected);
738-
_change_dir(d["name"]);
760+
Dictionary meta = file_list->get_item_metadata(selected);
761+
_change_dir(meta["name"]);
739762
if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES || mode == FILE_MODE_OPEN_DIR || mode == FILE_MODE_OPEN_ANY) {
740763
filename_edit->set_text("");
741764
}
@@ -746,36 +769,55 @@ void FileDialog::_item_menu_id_pressed(int p_option) {
746769

747770
void FileDialog::_empty_clicked(const Vector2 &p_pos, MouseButton p_button) {
748771
if (p_button == MouseButton::RIGHT) {
749-
item_menu->clear();
750-
#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
751-
// Opening the system file manager is not supported on the Android and web editors.
752-
item_menu->add_item(ETR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
753-
754-
item_menu->set_position(file_list->get_screen_position() + p_pos);
755-
item_menu->reset_size();
756-
item_menu->popup();
757-
#endif
772+
_popup_menu(p_pos, -1);
758773
} else if (p_button == MouseButton::LEFT) {
759774
deselect_all();
760775
}
761776
}
762777

763778
void FileDialog::_item_clicked(int p_item, const Vector2 &p_pos, MouseButton p_button) {
764779
if (p_button == MouseButton::RIGHT) {
765-
item_menu->clear();
766-
#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
767-
// Opening the system file manager is not supported on the Android and web editors.
768-
Dictionary d = file_list->get_item_metadata(p_item);
769-
if (d["bundle"]) {
770-
item_menu->add_item(ETR("Show Package Contents"), ITEM_MENU_SHOW_BUNDLE_CONTENT);
780+
_popup_menu(p_pos, p_item);
781+
}
782+
}
783+
784+
void FileDialog::_popup_menu(const Vector2 &p_pos, int p_for_item) {
785+
item_menu->clear();
786+
787+
if (p_for_item > -1) {
788+
item_menu->add_item(ETR("Copy Path"), ITEM_MENU_COPY_PATH);
789+
if (customization_flags[CUSTOMIZATION_DELETE]) {
790+
item_menu->add_item(ETR("Delete"), ITEM_MENU_DELETE);
771791
}
772-
item_menu->add_item(ETR("Open in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
792+
} else {
793+
if (can_create_folders) {
794+
item_menu->add_item(ETR("New Folder..."), ITEM_MENU_NEW_FOLDER);
795+
}
796+
item_menu->add_item(ETR("Refresh"), ITEM_MENU_REFRESH);
797+
}
798+
799+
#if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
800+
// Opening the system file manager is not supported on the Android and web editors.
801+
item_menu->add_separator();
773802

774-
item_menu->set_position(file_list->get_screen_position() + p_pos);
775-
item_menu->reset_size();
776-
item_menu->popup();
803+
Dictionary meta;
804+
if (p_for_item > -1) {
805+
meta = file_list->get_item_metadata(p_for_item);
806+
}
807+
808+
item_menu->add_item((p_for_item == -1 || meta["dir"]) ? ETR("Open in File Manager") : ETR("Show in File Manager"), ITEM_MENU_SHOW_IN_EXPLORER);
809+
if (meta["bundle"]) {
810+
item_menu->add_item(ETR("Show Package Contents"), ITEM_MENU_SHOW_BUNDLE_CONTENT);
811+
}
777812
#endif
813+
814+
if (item_menu->get_item_count() == 0) {
815+
return;
778816
}
817+
818+
item_menu->set_position(file_list->get_screen_position() + p_pos);
819+
item_menu->reset_size();
820+
item_menu->popup();
779821
}
780822

781823
void FileDialog::update_file_list() {
@@ -1063,6 +1105,11 @@ void FileDialog::_file_list_select_first() {
10631105
}
10641106
}
10651107

1108+
void FileDialog::_delete_confirm() {
1109+
OS::get_singleton()->move_to_trash(_get_item_path(_get_selected_file_idx()));
1110+
invalidate();
1111+
}
1112+
10661113
void FileDialog::_filename_filter_selected() {
10671114
int selected = _get_selected_file_idx();
10681115
if (selected > -1) {
@@ -1518,7 +1565,8 @@ void FileDialog::_setup_button(Button *p_button, const Ref<Texture2D> &p_icon) {
15181565
}
15191566

15201567
void FileDialog::_update_make_dir_visible() {
1521-
make_dir_container->set_visible(customization_flags[CUSTOMIZATION_CREATE_FOLDER] && mode != FILE_MODE_OPEN_FILE && mode != FILE_MODE_OPEN_FILES);
1568+
can_create_folders = customization_flags[CUSTOMIZATION_CREATE_FOLDER] && mode != FILE_MODE_OPEN_FILE && mode != FILE_MODE_OPEN_FILES;
1569+
make_dir_container->set_visible(can_create_folders);
15221570
}
15231571

15241572
FileDialog::Access FileDialog::get_access() const {
@@ -2058,6 +2106,7 @@ void FileDialog::_bind_methods() {
20582106
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "recent_list_enabled"), "set_customization_flag_enabled", "is_customization_flag_enabled", CUSTOMIZATION_RECENT);
20592107
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "layout_toggle_enabled"), "set_customization_flag_enabled", "is_customization_flag_enabled", CUSTOMIZATION_LAYOUT);
20602108
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "overwrite_warning_enabled"), "set_customization_flag_enabled", "is_customization_flag_enabled", CUSTOMIZATION_OVERWRITE_WARNING);
2109+
ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "deleting_enabled"), "set_customization_flag_enabled", "is_customization_flag_enabled", CUSTOMIZATION_DELETE);
20612110

20622111
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_dir", PROPERTY_HINT_DIR, "", PROPERTY_USAGE_NONE), "set_current_dir", "get_current_dir");
20632112
ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_file", PROPERTY_HINT_FILE_PATH, "*", PROPERTY_USAGE_NONE), "set_current_file", "get_current_file");
@@ -2089,6 +2138,7 @@ void FileDialog::_bind_methods() {
20892138
BIND_ENUM_CONSTANT(CUSTOMIZATION_RECENT);
20902139
BIND_ENUM_CONSTANT(CUSTOMIZATION_LAYOUT);
20912140
BIND_ENUM_CONSTANT(CUSTOMIZATION_OVERWRITE_WARNING);
2141+
BIND_ENUM_CONSTANT(CUSTOMIZATION_DELETE);
20922142

20932143
BIND_THEME_ITEM(Theme::DATA_TYPE_CONSTANT, FileDialog, thumbnail_size);
20942144
BIND_THEME_ITEM(Theme::DATA_TYPE_ICON, FileDialog, parent_folder);
@@ -2495,6 +2545,11 @@ FileDialog::FileDialog() {
24952545
add_child(confirm_save, false, INTERNAL_MODE_FRONT);
24962546
confirm_save->connect(SceneStringName(confirmed), callable_mp(this, &FileDialog::_save_confirm_pressed));
24972547

2548+
delete_dialog = memnew(ConfirmationDialog);
2549+
delete_dialog->set_text(ETR("Delete the selected file?\nDepending on your filesystem configuration, the files will either be moved to the system trash or deleted permanently."));
2550+
add_child(delete_dialog, false, INTERNAL_MODE_FRONT);
2551+
delete_dialog->connect(SceneStringName(confirmed), callable_mp(this, &FileDialog::_delete_confirm));
2552+
24982553
make_dir_dialog = memnew(ConfirmationDialog);
24992554
make_dir_dialog->set_title(ETR("Create Folder"));
25002555
add_child(make_dir_dialog, false, INTERNAL_MODE_FRONT);

scene/gui/file_dialog.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ class FileDialog : public ConfirmationDialog {
131131

132132
enum ItemMenu {
133133
ITEM_MENU_COPY_PATH,
134+
ITEM_MENU_DELETE,
135+
ITEM_MENU_REFRESH,
136+
ITEM_MENU_NEW_FOLDER,
134137
ITEM_MENU_SHOW_IN_EXPLORER,
135138
ITEM_MENU_SHOW_BUNDLE_CONTENT,
136139
};
@@ -144,6 +147,7 @@ class FileDialog : public ConfirmationDialog {
144147
CUSTOMIZATION_RECENT,
145148
CUSTOMIZATION_LAYOUT,
146149
CUSTOMIZATION_OVERWRITE_WARNING,
150+
CUSTOMIZATION_DELETE,
147151
CUSTOMIZATION_MAX
148152
};
149153

@@ -163,6 +167,7 @@ class FileDialog : public ConfirmationDialog {
163167
static inline DisplayMode default_display_mode = DISPLAY_THUMBNAILS;
164168
bool show_hidden_files = false;
165169
bool use_native_dialog = false;
170+
bool can_create_folders = true;
166171
bool customization_flags[CUSTOMIZATION_MAX]; // Initialized to true in the constructor.
167172

168173
inline static LocalVector<String> global_favorites;
@@ -241,6 +246,7 @@ class FileDialog : public ConfirmationDialog {
241246
FlowContainer *flow_checkbox_options = nullptr;
242247
GridContainer *grid_select_options = nullptr;
243248

249+
ConfirmationDialog *delete_dialog = nullptr;
244250
ConfirmationDialog *make_dir_dialog = nullptr;
245251
LineEdit *new_dir_name = nullptr;
246252
AcceptDialog *mkdirerr = nullptr;
@@ -289,10 +295,12 @@ class FileDialog : public ConfirmationDialog {
289295
void _item_menu_id_pressed(int p_option);
290296
void _empty_clicked(const Vector2 &p_pos, MouseButton p_button);
291297
void _item_clicked(int p_item, const Vector2 &p_pos, MouseButton p_button);
298+
void _popup_menu(const Vector2 &p_pos, int p_for_item);
292299

293300
void _focus_file_text();
294301

295302
int _get_selected_file_idx();
303+
String _get_item_path(int p_idx) const;
296304
void _file_list_multi_selected(int p_item, bool p_selected);
297305
void _file_list_selected(int p_item);
298306
void _file_list_item_activated(int p_item);
@@ -307,6 +315,7 @@ class FileDialog : public ConfirmationDialog {
307315
void _filename_filter_changed();
308316
void _filename_filter_selected();
309317
void _file_list_select_first();
318+
void _delete_confirm();
310319
void _make_dir();
311320
void _make_dir_confirm();
312321
void _go_up();

0 commit comments

Comments
 (0)