2016-06-18 14:46:12 +02:00
/**************************************************************************/
/* editor_file_dialog.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2015-05-31 06:59:42 +02:00
# include "editor_file_dialog.h"
2019-07-25 11:09:57 +02:00
2022-02-12 02:46:22 +01:00
# include "core/config/project_settings.h"
2021-06-11 14:51:48 +02:00
# include "core/io/file_access.h"
2018-09-11 18:13:45 +02:00
# include "core/os/keyboard.h"
# include "core/os/os.h"
2023-04-07 18:59:49 +02:00
# include "editor/dependency_editor.h"
2022-02-12 02:46:22 +01:00
# include "editor/editor_file_system.h"
2022-07-27 20:51:03 +02:00
# include "editor/editor_node.h"
2022-02-12 02:46:22 +01:00
# include "editor/editor_resource_preview.h"
# include "editor/editor_settings.h"
2023-11-13 11:15:25 +01:00
# include "editor/filesystem_dock.h"
2024-01-15 13:14:55 +01:00
# include "editor/themes/editor_scale.h"
2016-05-30 05:28:29 +02:00
# include "scene/gui/center_container.h"
2024-03-21 09:42:38 +01:00
# include "scene/gui/check_box.h"
# include "scene/gui/grid_container.h"
2015-05-31 06:59:42 +02:00
# include "scene/gui/label.h"
# include "scene/gui/margin_container.h"
2022-11-19 12:45:49 +01:00
# include "scene/gui/option_button.h"
# include "scene/gui/separator.h"
# include "scene/gui/split_container.h"
# include "scene/gui/texture_rect.h"
2020-03-03 14:36:29 +01:00
# include "servers/display_server.h"
2015-05-31 06:59:42 +02:00
2020-04-02 01:20:12 +02:00
EditorFileDialog : : GetIconFunc EditorFileDialog : : get_icon_func = nullptr ;
2023-02-17 22:37:38 +01:00
EditorFileDialog : : GetIconFunc EditorFileDialog : : get_thumbnail_func = nullptr ;
2015-05-31 06:59:42 +02:00
2020-04-02 01:20:12 +02:00
EditorFileDialog : : RegisterFunc EditorFileDialog : : register_func = nullptr ;
EditorFileDialog : : RegisterFunc EditorFileDialog : : unregister_func = nullptr ;
2015-05-31 06:59:42 +02:00
2024-03-21 09:42:38 +01:00
void EditorFileDialog : : _native_popup ( ) {
// Show native dialog directly.
String root ;
if ( access = = ACCESS_RESOURCES ) {
root = ProjectSettings : : get_singleton ( ) - > get_resource_path ( ) ;
} else if ( access = = ACCESS_USERDATA ) {
root = OS : : get_singleton ( ) - > get_user_data_dir ( ) ;
}
DisplayServer : : get_singleton ( ) - > file_dialog_with_options_show ( get_title ( ) , ProjectSettings : : get_singleton ( ) - > globalize_path ( dir - > get_text ( ) ) , root , file - > get_text ( ) . get_file ( ) , show_hidden_files , DisplayServer : : FileDialogMode ( mode ) , filters , _get_options ( ) , callable_mp ( this , & EditorFileDialog : : _native_dialog_cb ) ) ;
}
void EditorFileDialog : : popup ( const Rect2i & p_rect ) {
_update_option_controls ( ) ;
bool use_native = DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_NATIVE_DIALOG_FILE ) & & ( bool ( EDITOR_GET ( " interface/editor/use_native_file_dialogs " ) ) | | OS : : get_singleton ( ) - > is_sandboxed ( ) ) ;
if ( ! side_vbox & & use_native ) {
_native_popup ( ) ;
} else {
// Show custom file dialog (full dialog or side menu only).
_update_side_menu_visibility ( use_native ) ;
ConfirmationDialog : : popup ( p_rect ) ;
}
}
void EditorFileDialog : : set_visible ( bool p_visible ) {
if ( p_visible ) {
bool use_native = DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_NATIVE_DIALOG_FILE ) & & ( bool ( EDITOR_GET ( " interface/editor/use_native_file_dialogs " ) ) | | OS : : get_singleton ( ) - > is_sandboxed ( ) ) ;
_update_option_controls ( ) ;
if ( ! side_vbox & & use_native ) {
_native_popup ( ) ;
} else {
// Show custom file dialog (full dialog or side menu only).
_update_side_menu_visibility ( use_native ) ;
ConfirmationDialog : : set_visible ( p_visible ) ;
}
} else {
ConfirmationDialog : : set_visible ( p_visible ) ;
}
}
void EditorFileDialog : : _native_dialog_cb ( bool p_ok , const Vector < String > & p_files , int p_filter , const Dictionary & p_selected_options ) {
if ( ! p_ok ) {
file - > set_text ( " " ) ;
emit_signal ( SNAME ( " canceled " ) ) ;
return ;
}
if ( p_files . is_empty ( ) ) {
return ;
}
Vector < String > files = p_files ;
if ( access ! = ACCESS_FILESYSTEM ) {
for ( String & file_name : files ) {
file_name = ProjectSettings : : get_singleton ( ) - > localize_path ( file_name ) ;
}
}
String f = files [ 0 ] ;
if ( mode = = FILE_MODE_OPEN_FILES ) {
emit_signal ( SNAME ( " files_selected " ) , files ) ;
} else {
if ( mode = = FILE_MODE_SAVE_FILE ) {
if ( p_filter > = 0 & & p_filter < filters . size ( ) ) {
bool valid = false ;
String flt = filters [ p_filter ] . get_slice ( " ; " , 0 ) ;
int filter_slice_count = flt . get_slice_count ( " , " ) ;
for ( int j = 0 ; j < filter_slice_count ; j + + ) {
String str = ( flt . get_slice ( " , " , j ) . strip_edges ( ) ) ;
if ( f . match ( str ) ) {
valid = true ;
break ;
}
}
if ( ! valid & & filter_slice_count > 0 ) {
String str = ( flt . get_slice ( " , " , 0 ) . strip_edges ( ) ) ;
f + = str . substr ( 1 , str . length ( ) - 1 ) ;
}
}
emit_signal ( SNAME ( " file_selected " ) , f ) ;
} else if ( ( mode = = FILE_MODE_OPEN_ANY | | mode = = FILE_MODE_OPEN_FILE ) & & dir_access - > file_exists ( f ) ) {
emit_signal ( SNAME ( " file_selected " ) , f ) ;
} else if ( mode = = FILE_MODE_OPEN_ANY | | mode = = FILE_MODE_OPEN_DIR ) {
emit_signal ( SNAME ( " dir_selected " ) , f ) ;
}
}
file - > set_text ( f ) ;
dir - > set_text ( f . get_base_dir ( ) ) ;
selected_options = p_selected_options ;
filter - > select ( p_filter ) ;
}
2020-07-11 18:45:19 +02:00
void EditorFileDialog : : popup_file_dialog ( ) {
popup_centered_clamped ( Size2 ( 1050 , 700 ) * EDSCALE , 0.8 ) ;
2022-01-03 10:08:03 +01:00
_focus_file_text ( ) ;
}
void EditorFileDialog : : _focus_file_text ( ) {
int lp = file - > get_text ( ) . rfind ( " . " ) ;
if ( lp ! = - 1 ) {
file - > select ( 0 , lp ) ;
file - > grab_focus ( ) ;
}
2020-07-11 18:45:19 +02:00
}
2015-05-31 06:59:42 +02:00
VBoxContainer * EditorFileDialog : : get_vbox ( ) {
return vbox ;
}
2022-09-01 17:52:49 +02:00
void EditorFileDialog : : _update_theme_item_cache ( ) {
ConfirmationDialog : : _update_theme_item_cache ( ) ;
2023-08-13 02:33:39 +02:00
theme_cache . parent_folder = get_editor_theme_icon ( SNAME ( " ArrowUp " ) ) ;
theme_cache . forward_folder = get_editor_theme_icon ( SNAME ( " Forward " ) ) ;
theme_cache . back_folder = get_editor_theme_icon ( SNAME ( " Back " ) ) ;
theme_cache . reload = get_editor_theme_icon ( SNAME ( " Reload " ) ) ;
theme_cache . toggle_hidden = get_editor_theme_icon ( SNAME ( " GuiVisibilityVisible " ) ) ;
theme_cache . favorite = get_editor_theme_icon ( SNAME ( " Favorites " ) ) ;
theme_cache . mode_thumbnails = get_editor_theme_icon ( SNAME ( " FileThumbnail " ) ) ;
theme_cache . mode_list = get_editor_theme_icon ( SNAME ( " FileList " ) ) ;
theme_cache . favorites_up = get_editor_theme_icon ( SNAME ( " MoveUp " ) ) ;
theme_cache . favorites_down = get_editor_theme_icon ( SNAME ( " MoveDown " ) ) ;
2024-02-25 17:51:50 +01:00
theme_cache . create_folder = get_editor_theme_icon ( SNAME ( " FolderCreate " ) ) ;
2023-08-13 02:33:39 +02:00
theme_cache . folder = get_editor_theme_icon ( SNAME ( " Folder " ) ) ;
2022-09-06 19:09:32 +02:00
theme_cache . folder_icon_color = get_theme_color ( SNAME ( " folder_icon_color " ) , SNAME ( " FileDialog " ) ) ;
2022-09-01 17:52:49 +02:00
2023-08-13 02:33:39 +02:00
theme_cache . action_copy = get_editor_theme_icon ( SNAME ( " ActionCopy " ) ) ;
theme_cache . action_delete = get_editor_theme_icon ( SNAME ( " Remove " ) ) ;
theme_cache . filesystem = get_editor_theme_icon ( SNAME ( " Filesystem " ) ) ;
theme_cache . folder_medium_thumbnail = get_editor_theme_icon ( SNAME ( " FolderMediumThumb " ) ) ;
theme_cache . file_medium_thumbnail = get_editor_theme_icon ( SNAME ( " FileMediumThumb " ) ) ;
theme_cache . folder_big_thumbnail = get_editor_theme_icon ( SNAME ( " FolderBigThumb " ) ) ;
theme_cache . file_big_thumbnail = get_editor_theme_icon ( SNAME ( " FileBigThumb " ) ) ;
theme_cache . progress [ 0 ] = get_editor_theme_icon ( " Progress1 " ) ;
theme_cache . progress [ 1 ] = get_editor_theme_icon ( " Progress2 " ) ;
theme_cache . progress [ 2 ] = get_editor_theme_icon ( " Progress3 " ) ;
theme_cache . progress [ 3 ] = get_editor_theme_icon ( " Progress4 " ) ;
theme_cache . progress [ 4 ] = get_editor_theme_icon ( " Progress5 " ) ;
theme_cache . progress [ 5 ] = get_editor_theme_icon ( " Progress6 " ) ;
theme_cache . progress [ 6 ] = get_editor_theme_icon ( " Progress7 " ) ;
theme_cache . progress [ 7 ] = get_editor_theme_icon ( " Progress8 " ) ;
2022-09-01 17:52:49 +02:00
}
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : _notification ( int p_what ) {
2022-02-16 00:52:32 +01:00
switch ( p_what ) {
case NOTIFICATION_THEME_CHANGED :
case Control : : NOTIFICATION_LAYOUT_DIRECTION_CHANGED :
case NOTIFICATION_TRANSLATION_CHANGED : {
_update_icons ( ) ;
2022-09-01 17:52:49 +02:00
invalidate ( ) ;
2022-02-16 00:52:32 +01:00
} break ;
case NOTIFICATION_PROCESS : {
if ( preview_waiting ) {
preview_wheel_timeout - = get_process_delta_time ( ) ;
if ( preview_wheel_timeout < = 0 ) {
preview_wheel_index + + ;
if ( preview_wheel_index > = 8 ) {
preview_wheel_index = 0 ;
}
2022-09-01 17:52:49 +02:00
Ref < Texture2D > frame = theme_cache . progress [ preview_wheel_index ] ;
2022-02-16 00:52:32 +01:00
preview - > set_texture ( frame ) ;
preview_wheel_timeout = 0.1 ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
}
2022-02-16 00:52:32 +01:00
} break ;
case EditorSettings : : NOTIFICATION_EDITOR_SETTINGS_CHANGED : {
2022-11-23 00:14:08 +01:00
if ( ! EditorSettings : : get_singleton ( ) - > check_changed_settings_in_group ( " filesystem/file_dialog " ) ) {
break ;
}
2022-10-18 16:43:37 +02:00
bool is_showing_hidden = EDITOR_GET ( " filesystem/file_dialog/show_hidden_files " ) ;
2022-02-16 00:52:32 +01:00
if ( show_hidden_files ! = is_showing_hidden ) {
set_show_hidden_files ( is_showing_hidden ) ;
}
2022-10-18 16:43:37 +02:00
set_display_mode ( ( DisplayMode ) EDITOR_GET ( " filesystem/file_dialog/display_mode " ) . operator int ( ) ) ;
2022-02-16 00:52:32 +01:00
// DO NOT CALL UPDATE FILE LIST HERE, ALL HUNDREDS OF HIDDEN DIALOGS WILL RESPOND, CALL INVALIDATE INSTEAD
invalidate ( ) ;
} break ;
case NOTIFICATION_VISIBILITY_CHANGED : {
if ( ! is_visible ( ) ) {
2022-01-11 14:59:52 +01:00
set_process_shortcut_input ( false ) ;
2022-02-16 00:52:32 +01:00
}
2022-09-06 02:54:34 +02:00
invalidate ( ) ; // For consistency with the standard FileDialog.
2022-02-16 00:52:32 +01:00
} break ;
case NOTIFICATION_WM_WINDOW_FOCUS_IN : {
// Check if the current directory was removed externally (much less likely to happen while editor window is focused).
String previous_dir = get_current_dir ( ) ;
while ( ! dir_access - > dir_exists ( get_current_dir ( ) ) ) {
_go_up ( ) ;
// In case we can't go further up, use some fallback and break.
if ( get_current_dir ( ) = = previous_dir ) {
_dir_submitted ( OS : : get_singleton ( ) - > get_user_data_dir ( ) ) ;
break ;
}
2022-01-12 00:53:52 +01:00
}
2022-02-16 00:52:32 +01:00
} break ;
2015-05-31 06:59:42 +02:00
}
}
2022-01-11 14:59:52 +01:00
void EditorFileDialog : : shortcut_input ( const Ref < InputEvent > & p_event ) {
2021-04-05 08:52:21 +02:00
ERR_FAIL_COND ( p_event . is_null ( ) ) ;
2017-05-20 17:38:03 +02:00
Ref < InputEventKey > k = p_event ;
2015-12-29 00:36:48 +01:00
2020-03-06 18:00:16 +01:00
if ( k . is_valid ( ) ) {
2017-05-20 17:38:03 +02:00
if ( k - > is_pressed ( ) ) {
2016-06-18 19:32:04 +02:00
bool handled = false ;
2015-12-29 00:36:48 +01:00
2016-06-18 19:32:04 +02:00
if ( ED_IS_SHORTCUT ( " file_dialog/go_back " , p_event ) ) {
_go_back ( ) ;
handled = true ;
}
if ( ED_IS_SHORTCUT ( " file_dialog/go_forward " , p_event ) ) {
_go_forward ( ) ;
handled = true ;
}
if ( ED_IS_SHORTCUT ( " file_dialog/go_up " , p_event ) ) {
_go_up ( ) ;
handled = true ;
}
if ( ED_IS_SHORTCUT ( " file_dialog/refresh " , p_event ) ) {
invalidate ( ) ;
handled = true ;
}
if ( ED_IS_SHORTCUT ( " file_dialog/toggle_hidden_files " , p_event ) ) {
2020-10-06 15:42:25 +02:00
set_show_hidden_files ( ! show_hidden_files ) ;
2016-06-18 19:32:04 +02:00
handled = true ;
}
if ( ED_IS_SHORTCUT ( " file_dialog/toggle_favorite " , p_event ) ) {
2019-06-09 22:41:45 +02:00
_favorite_pressed ( ) ;
2016-06-18 19:32:04 +02:00
handled = true ;
}
if ( ED_IS_SHORTCUT ( " file_dialog/toggle_mode " , p_event ) ) {
if ( mode_thumbnails - > is_pressed ( ) ) {
set_display_mode ( DISPLAY_LIST ) ;
} else {
set_display_mode ( DISPLAY_THUMBNAILS ) ;
}
handled = true ;
}
if ( ED_IS_SHORTCUT ( " file_dialog/create_folder " , p_event ) ) {
_make_dir ( ) ;
handled = true ;
}
2017-12-02 01:37:32 +01:00
if ( ED_IS_SHORTCUT ( " file_dialog/delete " , p_event ) ) {
_delete_items ( ) ;
handled = true ;
}
2016-06-18 19:32:04 +02:00
if ( ED_IS_SHORTCUT ( " file_dialog/focus_path " , p_event ) ) {
dir - > grab_focus ( ) ;
2023-08-30 20:11:21 +02:00
dir - > select_all ( ) ;
2016-06-18 19:32:04 +02:00
handled = true ;
}
2016-06-28 16:12:07 +02:00
if ( ED_IS_SHORTCUT ( " file_dialog/move_favorite_up " , p_event ) ) {
2016-06-18 19:32:04 +02:00
_favorite_move_up ( ) ;
handled = true ;
}
2016-06-28 16:12:07 +02:00
if ( ED_IS_SHORTCUT ( " file_dialog/move_favorite_down " , p_event ) ) {
2016-06-18 19:32:04 +02:00
_favorite_move_down ( ) ;
handled = true ;
2015-12-29 00:36:48 +01:00
}
2016-06-18 19:32:04 +02:00
if ( handled ) {
2020-03-06 18:00:16 +01:00
set_input_as_handled ( ) ;
2016-06-18 19:32:04 +02:00
}
2015-12-29 00:36:48 +01:00
}
}
}
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : set_enable_multiple_selection ( bool p_enable ) {
2015-06-06 14:44:38 +02:00
item_list - > set_select_mode ( p_enable ? ItemList : : SELECT_MULTI : ItemList : : SELECT_SINGLE ) ;
2015-05-31 06:59:42 +02:00
} ;
Vector < String > EditorFileDialog : : get_selected_files ( ) const {
Vector < String > list ;
2015-06-06 14:44:38 +02:00
for ( int i = 0 ; i < item_list - > get_item_count ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( item_list - > is_selected ( i ) ) {
2015-06-06 14:44:38 +02:00
list . push_back ( item_list - > get_item_text ( i ) ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
}
2015-05-31 06:59:42 +02:00
return list ;
} ;
void EditorFileDialog : : update_dir ( ) {
2020-02-10 09:19:29 +01:00
if ( drives - > is_visible ( ) ) {
2022-01-24 12:12:46 +01:00
if ( dir_access - > get_current_dir ( ) . is_network_share_path ( ) ) {
_update_drives ( false ) ;
drives - > add_item ( RTR ( " Network " ) ) ;
2022-03-12 01:06:45 +01:00
drives - > set_item_disabled ( - 1 , true ) ;
2022-01-24 12:12:46 +01:00
drives - > select ( drives - > get_item_count ( ) - 1 ) ;
} else {
drives - > select ( dir_access - > get_current_drive ( ) ) ;
}
2020-02-10 09:19:29 +01:00
}
dir - > set_text ( dir_access - > get_current_dir ( false ) ) ;
2017-11-24 19:12:18 +01:00
2018-09-11 08:32:14 +02:00
// Disable "Open" button only when selecting file(s) mode.
2020-12-14 19:37:30 +01:00
get_ok_button ( ) - > set_disabled ( _is_open_should_be_disabled ( ) ) ;
2018-09-11 08:32:14 +02:00
switch ( mode ) {
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_FILE :
case FILE_MODE_OPEN_FILES :
2023-09-01 17:18:51 +02:00
file - > set_text ( " " ) ;
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Open " ) ) ;
2018-09-11 08:32:14 +02:00
break ;
2023-07-30 12:09:54 +02:00
case FILE_MODE_OPEN_ANY :
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_DIR :
2023-09-01 17:18:51 +02:00
file - > set_text ( " " ) ;
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Select Current Folder " ) ) ;
2018-09-11 08:32:14 +02:00
break ;
2020-03-06 18:00:16 +01:00
case FILE_MODE_SAVE_FILE :
2018-09-26 13:13:56 +02:00
// FIXME: Implement, or refactor to avoid duplication with set_mode
break ;
2018-09-11 08:32:14 +02:00
}
2015-05-31 06:59:42 +02:00
}
2024-02-15 17:25:58 +01:00
void EditorFileDialog : : _dir_submitted ( const String & p_dir ) {
2015-05-31 06:59:42 +02:00
dir_access - > change_dir ( p_dir ) ;
invalidate ( ) ;
update_dir ( ) ;
2015-06-06 14:44:38 +02:00
_push_history ( ) ;
2015-05-31 06:59:42 +02:00
}
2021-06-16 18:43:34 +02:00
void EditorFileDialog : : _file_submitted ( const String & p_file ) {
2015-05-31 06:59:42 +02:00
_action_pressed ( ) ;
}
void EditorFileDialog : : _save_confirm_pressed ( ) {
2022-08-30 02:34:01 +02:00
String f = dir_access - > get_current_dir ( ) . path_join ( file - > get_text ( ) ) ;
2015-06-06 14:44:38 +02:00
_save_to_recent ( ) ;
2015-05-31 06:59:42 +02:00
hide ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " file_selected " ) , f ) ;
2015-05-31 06:59:42 +02:00
}
void EditorFileDialog : : _post_popup ( ) {
ConfirmationDialog : : _post_popup ( ) ;
2020-10-13 20:28:45 +02:00
// Check if the current path doesn't exist and correct it.
String current = dir_access - > get_current_dir ( ) ;
while ( ! dir_access - > dir_exists ( current ) ) {
current = current . get_base_dir ( ) ;
}
set_current_dir ( current ) ;
2020-05-14 16:41:43 +02:00
if ( mode = = FILE_MODE_SAVE_FILE ) {
2015-05-31 06:59:42 +02:00
file - > grab_focus ( ) ;
2020-05-14 16:41:43 +02:00
} else {
2015-06-06 14:44:38 +02:00
item_list - > grab_focus ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
2020-03-06 18:00:16 +01:00
if ( mode = = FILE_MODE_OPEN_DIR ) {
2019-10-26 17:29:22 +02:00
file_box - > set_visible ( false ) ;
} else {
file_box - > set_visible ( true ) ;
}
2022-09-06 02:54:34 +02:00
if ( ! get_current_file ( ) . is_empty ( ) ) {
2022-08-30 02:34:01 +02:00
_request_single_thumbnail ( get_current_dir ( ) . path_join ( get_current_file ( ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
2022-09-06 02:54:34 +02:00
local_history . clear ( ) ;
local_history_pos = - 1 ;
_push_history ( ) ;
2015-06-06 14:44:38 +02:00
2022-01-11 14:59:52 +01:00
set_process_shortcut_input ( true ) ;
2015-06-06 14:44:38 +02:00
}
2019-06-11 20:43:37 +02:00
void EditorFileDialog : : _thumbnail_result ( const String & p_path , const Ref < Texture2D > & p_preview , const Ref < Texture2D > & p_small_preview , const Variant & p_udata ) {
2020-05-14 16:41:43 +02:00
if ( display_mode = = DISPLAY_LIST | | p_preview . is_null ( ) ) {
2015-06-06 14:44:38 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
for ( int i = 0 ; i < item_list - > get_item_count ( ) ; i + + ) {
Dictionary d = item_list - > get_item_metadata ( i ) ;
String pname = d [ " path " ] ;
if ( pname = = p_path ) {
item_list - > set_item_icon ( i , p_preview ) ;
2019-06-11 20:43:37 +02:00
item_list - > set_item_tag_icon ( i , Ref < Texture2D > ( ) ) ;
2015-06-06 14:44:38 +02:00
}
}
2015-05-31 06:59:42 +02:00
}
2019-06-11 20:43:37 +02:00
void EditorFileDialog : : _thumbnail_done ( const String & p_path , const Ref < Texture2D > & p_preview , const Ref < Texture2D > & p_small_preview , const Variant & p_udata ) {
2015-05-31 06:59:42 +02:00
set_process ( false ) ;
preview_waiting = false ;
if ( p_preview . is_valid ( ) & & get_current_path ( ) = = p_path ) {
preview - > set_texture ( p_preview ) ;
2015-06-06 14:44:38 +02:00
if ( display_mode = = DISPLAY_THUMBNAILS ) {
preview_vb - > hide ( ) ;
} else {
preview_vb - > show ( ) ;
}
2015-05-31 06:59:42 +02:00
} else {
preview_vb - > hide ( ) ;
2019-06-11 20:43:37 +02:00
preview - > set_texture ( Ref < Texture2D > ( ) ) ;
2015-05-31 06:59:42 +02:00
}
}
void EditorFileDialog : : _request_single_thumbnail ( const String & p_path ) {
2022-02-03 01:21:52 +01:00
if ( ! FileAccess : : exists ( p_path ) | | ! previews_enabled ) {
2015-12-12 23:21:43 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-12-12 23:21:43 +01:00
2015-05-31 06:59:42 +02:00
set_process ( true ) ;
preview_waiting = true ;
preview_wheel_timeout = 0 ;
2019-03-02 13:33:54 +01:00
EditorResourcePreview : : get_singleton ( ) - > queue_resource_preview ( p_path , this , " _thumbnail_done " , p_path ) ;
2015-05-31 06:59:42 +02:00
}
void EditorFileDialog : : _action_pressed ( ) {
2024-03-21 09:42:38 +01:00
// Accept side menu properties and show native dialog.
if ( side_vbox & & DisplayServer : : get_singleton ( ) - > has_feature ( DisplayServer : : FEATURE_NATIVE_DIALOG_FILE ) & & ( bool ( EDITOR_GET ( " interface/editor/use_native_file_dialogs " ) ) | | OS : : get_singleton ( ) - > is_sandboxed ( ) ) ) {
hide ( ) ;
_native_popup ( ) ;
return ;
}
// Accept selection in the custom dialog.
2020-03-06 18:00:16 +01:00
if ( mode = = FILE_MODE_OPEN_FILES ) {
2015-05-31 06:59:42 +02:00
String fbase = dir_access - > get_current_dir ( ) ;
2020-02-17 22:06:54 +01:00
Vector < String > files ;
2015-06-06 14:44:38 +02:00
for ( int i = 0 ; i < item_list - > get_item_count ( ) ; i + + ) {
2020-05-14 16:41:43 +02:00
if ( item_list - > is_selected ( i ) ) {
2022-08-30 02:34:01 +02:00
files . push_back ( fbase . path_join ( item_list - > get_item_text ( i ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
}
if ( files . size ( ) ) {
2015-06-06 14:44:38 +02:00
_save_to_recent ( ) ;
2015-05-31 06:59:42 +02:00
hide ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " files_selected " ) , files ) ;
2015-05-31 06:59:42 +02:00
}
return ;
}
2022-03-01 20:29:19 +01:00
String file_text = file - > get_text ( ) ;
2022-08-30 02:34:01 +02:00
String f = file_text . is_absolute_path ( ) ? file_text : dir_access - > get_current_dir ( ) . path_join ( file_text ) ;
2015-05-31 06:59:42 +02:00
2020-03-06 18:00:16 +01:00
if ( ( mode = = FILE_MODE_OPEN_ANY | | mode = = FILE_MODE_OPEN_FILE ) & & dir_access - > file_exists ( f ) ) {
2015-06-06 14:44:38 +02:00
_save_to_recent ( ) ;
2015-05-31 06:59:42 +02:00
hide ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " file_selected " ) , f ) ;
2020-03-06 18:00:16 +01:00
} else if ( mode = = FILE_MODE_OPEN_ANY | | mode = = FILE_MODE_OPEN_DIR ) {
2015-05-31 06:59:42 +02:00
String path = dir_access - > get_current_dir ( ) ;
2016-09-26 09:43:10 +02:00
2015-05-31 06:59:42 +02:00
path = path . replace ( " \\ " , " / " ) ;
2016-09-26 09:43:10 +02:00
for ( int i = 0 ; i < item_list - > get_item_count ( ) ; i + + ) {
if ( item_list - > is_selected ( i ) ) {
Dictionary d = item_list - > get_item_metadata ( i ) ;
if ( d [ " dir " ] ) {
2022-08-30 02:34:01 +02:00
path = path . path_join ( d [ " name " ] ) ;
2016-09-26 09:43:10 +02:00
break ;
}
}
}
2015-06-06 14:44:38 +02:00
_save_to_recent ( ) ;
2015-05-31 06:59:42 +02:00
hide ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " dir_selected " ) , path ) ;
2015-05-31 06:59:42 +02:00
}
2020-03-06 18:00:16 +01:00
if ( mode = = FILE_MODE_SAVE_FILE ) {
2015-05-31 06:59:42 +02:00
bool valid = false ;
if ( filter - > get_selected ( ) = = filter - > get_item_count ( ) - 1 ) {
2017-12-25 05:29:00 +01:00
valid = true ; // match none
2015-05-31 06:59:42 +02:00
} else if ( filters . size ( ) > 1 & & filter - > get_selected ( ) = = 0 ) {
// match all filters
for ( int i = 0 ; i < filters . size ( ) ; i + + ) {
String flt = filters [ i ] . get_slice ( " ; " , 0 ) ;
for ( int j = 0 ; j < flt . get_slice_count ( " , " ) ; j + + ) {
String str = flt . get_slice ( " , " , j ) . strip_edges ( ) ;
if ( f . match ( str ) ) {
valid = true ;
break ;
}
}
2020-05-14 16:41:43 +02:00
if ( valid ) {
2015-05-31 06:59:42 +02:00
break ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
}
} else {
int idx = filter - > get_selected ( ) ;
2020-05-14 16:41:43 +02:00
if ( filters . size ( ) > 1 ) {
2015-05-31 06:59:42 +02:00
idx - - ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
if ( idx > = 0 & & idx < filters . size ( ) ) {
String flt = filters [ idx ] . get_slice ( " ; " , 0 ) ;
int filterSliceCount = flt . get_slice_count ( " , " ) ;
for ( int j = 0 ; j < filterSliceCount ; j + + ) {
String str = ( flt . get_slice ( " , " , j ) . strip_edges ( ) ) ;
if ( f . match ( str ) ) {
valid = true ;
break ;
}
}
if ( ! valid & & filterSliceCount > 0 ) {
String str = ( flt . get_slice ( " , " , 0 ) . strip_edges ( ) ) ;
f + = str . substr ( 1 , str . length ( ) - 1 ) ;
2022-08-30 02:34:01 +02:00
_request_single_thumbnail ( get_current_dir ( ) . path_join ( f . get_file ( ) ) ) ;
2015-05-31 06:59:42 +02:00
file - > set_text ( f . get_file ( ) ) ;
valid = true ;
}
} else {
valid = true ;
}
}
2022-12-09 09:32:14 +01:00
// First check we're not having an empty name.
String file_name = file_text . strip_edges ( ) . get_file ( ) ;
if ( file_name . is_empty ( ) ) {
error_dialog - > set_text ( TTR ( " Cannot save file with an empty filename. " ) ) ;
error_dialog - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
return ;
}
2020-10-13 20:28:45 +02:00
// Add first extension of filter if no valid extension is found.
2015-05-31 06:59:42 +02:00
if ( ! valid ) {
2020-10-13 20:28:45 +02:00
int idx = filter - > get_selected ( ) ;
String flt = filters [ idx ] . get_slice ( " ; " , 0 ) ;
String ext = flt . get_slice ( " , " , 0 ) . strip_edges ( ) . get_extension ( ) ;
f + = " . " + ext ;
2015-05-31 06:59:42 +02:00
}
2022-12-09 09:32:14 +01:00
if ( file_name . begins_with ( " . " ) ) { // Could still happen if typed manually.
error_dialog - > set_text ( TTR ( " Cannot save file with a name starting with a dot. " ) ) ;
error_dialog - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
return ;
}
2016-06-20 05:38:13 +02:00
if ( dir_access - > file_exists ( f ) & & ! disable_overwrite_warning ) {
2022-12-09 09:32:14 +01:00
confirm_save - > set_text ( vformat ( TTR ( " File \" %s \" already exists. \n Do you want to overwrite it? " ) , f ) ) ;
confirm_save - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
2015-05-31 06:59:42 +02:00
} else {
2015-06-06 14:44:38 +02:00
_save_to_recent ( ) ;
2015-05-31 06:59:42 +02:00
hide ( ) ;
2021-07-17 23:22:52 +02:00
emit_signal ( SNAME ( " file_selected " ) , f ) ;
2015-05-31 06:59:42 +02:00
}
}
}
void EditorFileDialog : : _cancel_pressed ( ) {
file - > set_text ( " " ) ;
invalidate ( ) ;
hide ( ) ;
}
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _item_selected ( int p_item ) {
int current = p_item ;
2020-05-14 16:41:43 +02:00
if ( current < 0 | | current > = item_list - > get_item_count ( ) ) {
2015-05-31 06:59:42 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
Dictionary d = item_list - > get_item_metadata ( current ) ;
2015-05-31 06:59:42 +02:00
if ( ! d [ " dir " ] ) {
file - > set_text ( d [ " name " ] ) ;
2022-08-30 02:34:01 +02:00
_request_single_thumbnail ( get_current_dir ( ) . path_join ( get_current_file ( ) ) ) ;
2023-07-30 12:09:54 +02:00
// FILE_MODE_OPEN_ANY can alternate this text depending on what's selected.
set_ok_button_text ( TTR ( " Open " ) ) ;
} else if ( mode = = FILE_MODE_OPEN_DIR | | mode = = FILE_MODE_OPEN_ANY ) {
file - > set_text ( " " ) ;
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Select This Folder " ) ) ;
2015-05-31 06:59:42 +02:00
}
2017-11-24 19:12:18 +01:00
2020-12-14 19:37:30 +01:00
get_ok_button ( ) - > set_disabled ( _is_open_should_be_disabled ( ) ) ;
2017-11-24 19:12:18 +01:00
}
2018-01-31 19:25:42 +01:00
void EditorFileDialog : : _multi_selected ( int p_item , bool p_selected ) {
int current = p_item ;
2020-05-14 16:41:43 +02:00
if ( current < 0 | | current > = item_list - > get_item_count ( ) ) {
2018-01-31 19:25:42 +01:00
return ;
2020-05-14 16:41:43 +02:00
}
2018-01-31 19:25:42 +01:00
Dictionary d = item_list - > get_item_metadata ( current ) ;
if ( ! d [ " dir " ] & & p_selected ) {
file - > set_text ( d [ " name " ] ) ;
2022-08-30 02:34:01 +02:00
_request_single_thumbnail ( get_current_dir ( ) . path_join ( get_current_file ( ) ) ) ;
2018-01-31 19:25:42 +01:00
}
2020-12-14 19:37:30 +01:00
get_ok_button ( ) - > set_disabled ( _is_open_should_be_disabled ( ) ) ;
2018-01-31 19:25:42 +01:00
}
2022-05-09 20:17:04 +02:00
void EditorFileDialog : : _items_clear_selection ( const Vector2 & p_pos , MouseButton p_mouse_button_index ) {
2021-11-26 00:53:27 +01:00
if ( p_mouse_button_index ! = MouseButton : : LEFT ) {
return ;
}
2020-12-21 11:26:41 +01:00
item_list - > deselect_all ( ) ;
2017-11-24 19:12:18 +01:00
// If nothing is selected, then block Open button.
switch ( mode ) {
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_FILE :
case FILE_MODE_OPEN_FILES :
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Open " ) ) ;
2020-12-14 19:37:30 +01:00
get_ok_button ( ) - > set_disabled ( ! item_list - > is_anything_selected ( ) ) ;
2017-11-24 19:12:18 +01:00
break ;
2023-07-30 12:09:54 +02:00
case FILE_MODE_OPEN_ANY :
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_DIR :
2023-07-30 12:09:54 +02:00
file - > set_text ( " " ) ;
2020-12-14 19:37:30 +01:00
get_ok_button ( ) - > set_disabled ( false ) ;
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Select Current Folder " ) ) ;
2017-11-24 19:12:18 +01:00
break ;
2018-09-26 13:13:56 +02:00
2020-03-06 18:00:16 +01:00
case FILE_MODE_SAVE_FILE :
2018-09-26 13:13:56 +02:00
// FIXME: Implement, or refactor to avoid duplication with set_mode
break ;
2017-11-24 19:12:18 +01:00
}
2015-05-31 06:59:42 +02:00
}
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _push_history ( ) {
local_history . resize ( local_history_pos + 1 ) ;
String new_path = dir_access - > get_current_dir ( ) ;
if ( local_history . size ( ) = = 0 | | new_path ! = local_history [ local_history_pos ] ) {
local_history . push_back ( new_path ) ;
local_history_pos + + ;
dir_prev - > set_disabled ( local_history_pos = = 0 ) ;
dir_next - > set_disabled ( true ) ;
}
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _item_dc_selected ( int p_item ) {
int current = p_item ;
2020-05-14 16:41:43 +02:00
if ( current < 0 | | current > = item_list - > get_item_count ( ) ) {
2015-05-31 06:59:42 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
2015-06-06 14:44:38 +02:00
Dictionary d = item_list - > get_item_metadata ( current ) ;
2015-05-31 06:59:42 +02:00
if ( d [ " dir " ] ) {
dir_access - > change_dir ( d [ " name " ] ) ;
2023-01-22 18:26:32 +01:00
callable_mp ( this , & EditorFileDialog : : update_file_list ) . call_deferred ( ) ;
callable_mp ( this , & EditorFileDialog : : update_dir ) . call_deferred ( ) ;
2015-06-06 14:44:38 +02:00
_push_history ( ) ;
2015-05-31 06:59:42 +02:00
} else {
_action_pressed ( ) ;
}
}
2021-11-26 00:53:27 +01:00
void EditorFileDialog : : _item_list_item_rmb_clicked ( int p_item , const Vector2 & p_pos , MouseButton p_mouse_button_index ) {
if ( p_mouse_button_index ! = MouseButton : : RIGHT ) {
return ;
}
2017-12-02 01:37:32 +01:00
// Right click on specific file(s) or folder(s).
item_menu - > clear ( ) ;
2021-11-20 09:04:57 +01:00
item_menu - > reset_size ( ) ;
2017-12-02 01:37:32 +01:00
// 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 ) ;
2021-09-10 17:32:29 +02:00
if ( String ( item_meta [ " path " ] ) . begins_with ( ProjectSettings : : get_singleton ( ) - > get_project_data_path ( ) ) ) {
2017-12-02 01:37:32 +01:00
allow_delete = false ;
break ;
}
}
if ( single_item_selected ) {
2022-09-01 17:52:49 +02:00
item_menu - > add_icon_item ( theme_cache . action_copy , TTR ( " Copy Path " ) , ITEM_MENU_COPY_PATH ) ;
2017-12-02 01:37:32 +01:00
}
if ( allow_delete ) {
2022-09-01 17:52:49 +02:00
item_menu - > add_icon_item ( theme_cache . action_delete , TTR ( " Delete " ) , ITEM_MENU_DELETE , Key : : KEY_DELETE ) ;
2017-12-02 01:37:32 +01:00
}
2023-01-15 22:50:40 +01:00
# if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
// Opening the system file manager is not supported on the Android and web editors.
2017-12-02 01:37:32 +01:00
if ( single_item_selected ) {
item_menu - > add_separator ( ) ;
2018-08-11 14:43:00 +02:00
Dictionary item_meta = item_list - > get_item_metadata ( p_item ) ;
2018-10-26 21:11:36 +02:00
String item_text = item_meta [ " dir " ] ? TTR ( " Open in File Manager " ) : TTR ( " Show in File Manager " ) ;
2022-09-01 17:52:49 +02:00
item_menu - > add_icon_item ( theme_cache . filesystem , item_text , ITEM_MENU_SHOW_IN_EXPLORER ) ;
2017-12-02 01:37:32 +01:00
}
2023-01-15 22:50:40 +01:00
# endif
2017-12-02 01:37:32 +01:00
if ( item_menu - > get_item_count ( ) > 0 ) {
2021-08-31 17:43:35 +02:00
item_menu - > set_position ( item_list - > get_screen_position ( ) + p_pos ) ;
item_menu - > reset_size ( ) ;
2017-12-02 01:37:32 +01:00
item_menu - > popup ( ) ;
}
}
2021-11-26 00:53:27 +01:00
void EditorFileDialog : : _item_list_empty_clicked ( const Vector2 & p_pos , MouseButton p_mouse_button_index ) {
if ( p_mouse_button_index ! = MouseButton : : RIGHT & & p_mouse_button_index ! = MouseButton : : LEFT ) {
return ;
}
// Left or right click on folder background. Deselect all files so that actions are applied on the current folder.
2017-12-02 01:37:32 +01:00
for ( int i = 0 ; i < item_list - > get_item_count ( ) ; i + + ) {
2020-12-21 11:26:41 +01:00
item_list - > deselect ( i ) ;
2017-12-02 01:37:32 +01:00
}
2021-11-26 00:53:27 +01:00
if ( p_mouse_button_index ! = MouseButton : : RIGHT ) {
return ;
}
2017-12-02 01:37:32 +01:00
item_menu - > clear ( ) ;
2021-11-20 09:04:57 +01:00
item_menu - > reset_size ( ) ;
2017-12-02 01:37:32 +01:00
if ( can_create_dir ) {
2022-09-02 11:37:48 +02:00
item_menu - > add_icon_item ( theme_cache . folder , TTR ( " New Folder... " ) , ITEM_MENU_NEW_FOLDER , KeyModifierMask : : CMD_OR_CTRL | Key : : N ) ;
2017-12-02 01:37:32 +01:00
}
2022-09-01 17:52:49 +02:00
item_menu - > add_icon_item ( theme_cache . reload , TTR ( " Refresh " ) , ITEM_MENU_REFRESH , Key : : F5 ) ;
2023-01-15 22:50:40 +01:00
# if !defined(ANDROID_ENABLED) && !defined(WEB_ENABLED)
// Opening the system file manager is not supported on the Android and web editors.
2017-12-02 01:37:32 +01:00
item_menu - > add_separator ( ) ;
2022-09-01 17:52:49 +02:00
item_menu - > add_icon_item ( theme_cache . filesystem , TTR ( " Open in File Manager " ) , ITEM_MENU_SHOW_IN_EXPLORER ) ;
2023-01-15 22:50:40 +01:00
# endif
2017-12-02 01:37:32 +01:00
2021-08-31 17:43:35 +02:00
item_menu - > set_position ( item_list - > get_screen_position ( ) + p_pos ) ;
item_menu - > reset_size ( ) ;
2017-12-02 01:37:32 +01:00
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 ( ) ) ;
2020-03-03 14:36:29 +01:00
DisplayServer : : get_singleton ( ) - > clipboard_set ( item_meta [ " path " ] ) ;
2017-12-02 01:37:32 +01:00
} 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 " ] ) ;
}
2022-12-07 04:33:35 +01:00
OS : : get_singleton ( ) - > shell_show_in_file_manager ( path , true ) ;
2017-12-02 01:37:32 +01:00
} break ;
}
}
2017-11-24 19:12:18 +01:00
bool EditorFileDialog : : _is_open_should_be_disabled ( ) {
2020-05-14 16:41:43 +02:00
if ( mode = = FILE_MODE_OPEN_ANY | | mode = = FILE_MODE_SAVE_FILE ) {
2017-11-24 19:12:18 +01:00
return false ;
2020-05-14 16:41:43 +02:00
}
2017-11-24 19:12:18 +01:00
Vector < int > items = item_list - > get_selected_items ( ) ;
2020-05-14 16:41:43 +02:00
if ( items . size ( ) = = 0 ) {
2020-03-06 18:00:16 +01:00
return mode ! = FILE_MODE_OPEN_DIR ; // In "Open folder" mode, having nothing selected picks the current folder.
2020-05-14 16:41:43 +02:00
}
2017-11-24 19:12:18 +01:00
for ( int i = 0 ; i < items . size ( ) ; i + + ) {
Dictionary d = item_list - > get_item_metadata ( items . get ( i ) ) ;
2020-05-14 16:41:43 +02:00
if ( ( ( mode = = FILE_MODE_OPEN_FILE | | mode = = FILE_MODE_OPEN_FILES ) & & d [ " dir " ] ) | | ( mode = = FILE_MODE_OPEN_DIR & & ! d [ " dir " ] ) ) {
2017-11-24 19:12:18 +01:00
return true ;
2020-05-14 16:41:43 +02:00
}
2017-11-24 19:12:18 +01:00
}
return false ;
}
2019-06-28 09:29:50 +02:00
void EditorFileDialog : : update_file_name ( ) {
int idx = filter - > get_selected ( ) - 1 ;
if ( ( idx = = - 1 & & filter - > get_item_count ( ) = = 2 ) | | ( filter - > get_item_count ( ) > 2 & & idx > = 0 & & idx < filter - > get_item_count ( ) - 2 ) ) {
2020-05-14 16:41:43 +02:00
if ( idx = = - 1 ) {
2019-06-28 09:29:50 +02:00
idx + = 1 ;
2020-05-14 16:41:43 +02:00
}
2019-06-28 09:29:50 +02:00
String filter_str = filters [ idx ] ;
String file_str = file - > get_text ( ) ;
String base_name = file_str . get_basename ( ) ;
2019-07-29 12:43:08 +02:00
Vector < String > filter_substr = filter_str . split ( " ; " ) ;
if ( filter_substr . size ( ) > = 2 ) {
2020-04-28 16:03:46 +02:00
file_str = base_name + " . " + filter_substr [ 0 ] . strip_edges ( ) . get_extension ( ) . to_lower ( ) ;
2019-07-29 12:43:08 +02:00
} else {
2020-04-28 16:03:46 +02:00
file_str = base_name + " . " + filter_str . strip_edges ( ) . get_extension ( ) . to_lower ( ) ;
2019-07-29 12:43:08 +02:00
}
2019-06-28 09:29:50 +02:00
file - > set_text ( file_str ) ;
}
}
2023-11-13 11:15:25 +01:00
// TODO: Could use a unit test.
Color EditorFileDialog : : get_dir_icon_color ( const String & p_dir_path ) {
2023-12-14 20:43:46 +01:00
if ( ! FileSystemDock : : get_singleton ( ) ) { // This dialog can be called from the project manager.
return theme_cache . folder_icon_color ;
}
2023-11-13 11:15:25 +01:00
const HashMap < String , Color > & folder_colors = FileSystemDock : : get_singleton ( ) - > get_folder_colors ( ) ;
Dictionary assigned_folder_colors = FileSystemDock : : get_singleton ( ) - > get_assigned_folder_colors ( ) ;
Color folder_icon_color = theme_cache . folder_icon_color ;
// Check for a folder color to inherit (if one is assigned).
2023-12-14 20:43:46 +01:00
String parent_dir = ProjectSettings : : get_singleton ( ) - > localize_path ( p_dir_path ) ;
while ( ! parent_dir . is_empty ( ) & & parent_dir ! = " res:// " ) {
2023-11-13 11:15:25 +01:00
if ( ! parent_dir . ends_with ( " / " ) ) {
parent_dir + = " / " ;
}
if ( assigned_folder_colors . has ( parent_dir ) ) {
folder_icon_color = folder_colors [ assigned_folder_colors [ parent_dir ] ] ;
2023-12-14 20:43:46 +01:00
if ( folder_icon_color ! = theme_cache . folder_icon_color ) {
break ;
}
2023-11-13 11:15:25 +01:00
}
parent_dir = parent_dir . trim_suffix ( " / " ) . get_base_dir ( ) ;
}
return folder_icon_color ;
}
2017-12-19 16:57:46 +01:00
// DO NOT USE THIS FUNCTION UNLESS NEEDED, CALL INVALIDATE() INSTEAD.
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : update_file_list ( ) {
2022-10-18 16:43:37 +02:00
int thumbnail_size = EDITOR_GET ( " filesystem/file_dialog/thumbnail_size " ) ;
2016-05-30 05:28:29 +02:00
thumbnail_size * = EDSCALE ;
2019-06-11 20:43:37 +02:00
Ref < Texture2D > folder_thumbnail ;
Ref < Texture2D > file_thumbnail ;
2015-06-06 14:44:38 +02:00
item_list - > clear ( ) ;
2019-10-24 15:31:31 +02:00
// Scroll back to the top after opening a directory
2021-11-30 17:46:36 +01:00
item_list - > get_v_scroll_bar ( ) - > set_value ( 0 ) ;
2019-10-24 15:31:31 +02:00
2015-06-06 14:44:38 +02:00
if ( display_mode = = DISPLAY_THUMBNAILS ) {
item_list - > set_max_columns ( 0 ) ;
item_list - > set_icon_mode ( ItemList : : ICON_MODE_TOP ) ;
item_list - > set_fixed_column_width ( thumbnail_size * 3 / 2 ) ;
item_list - > set_max_text_lines ( 2 ) ;
2022-06-15 10:01:45 +02:00
item_list - > set_text_overrun_behavior ( TextServer : : OVERRUN_TRIM_ELLIPSIS ) ;
2016-06-12 21:51:27 +02:00
item_list - > set_fixed_icon_size ( Size2 ( thumbnail_size , thumbnail_size ) ) ;
2015-06-06 14:44:38 +02:00
2017-09-12 21:32:04 +02:00
if ( thumbnail_size < 64 ) {
2022-09-01 17:52:49 +02:00
folder_thumbnail = theme_cache . folder_medium_thumbnail ;
file_thumbnail = theme_cache . file_medium_thumbnail ;
2017-09-12 21:32:04 +02:00
} else {
2022-09-01 17:52:49 +02:00
folder_thumbnail = theme_cache . folder_big_thumbnail ;
file_thumbnail = theme_cache . file_big_thumbnail ;
2015-06-06 14:44:38 +02:00
}
preview_vb - > hide ( ) ;
} else {
item_list - > set_icon_mode ( ItemList : : ICON_MODE_LEFT ) ;
item_list - > set_max_columns ( 1 ) ;
item_list - > set_max_text_lines ( 1 ) ;
item_list - > set_fixed_column_width ( 0 ) ;
2016-06-12 21:51:27 +02:00
item_list - > set_fixed_icon_size ( Size2 ( ) ) ;
2020-05-14 16:41:43 +02:00
if ( preview - > get_texture ( ) . is_valid ( ) ) {
2015-06-06 14:44:38 +02:00
preview_vb - > show ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
}
2015-12-11 13:37:34 +01:00
String cdir = dir_access - > get_current_dir ( ) ;
2015-06-06 14:44:38 +02:00
2015-05-31 06:59:42 +02:00
dir_access - > list_dir_begin ( ) ;
List < String > files ;
List < String > dirs ;
2021-11-30 15:19:26 +01:00
String item = dir_access - > get_next ( ) ;
2015-05-31 06:59:42 +02:00
2021-11-30 15:19:26 +01:00
while ( ! item . is_empty ( ) ) {
2020-05-14 16:41:43 +02:00
if ( item = = " . " | | item = = " .. " ) {
2021-11-30 15:19:26 +01:00
item = dir_access - > get_next ( ) ;
2017-11-21 00:58:07 +01:00
continue ;
2020-05-14 16:41:43 +02:00
}
2017-11-21 00:58:07 +01:00
2021-03-03 15:33:34 +01:00
if ( show_hidden_files ) {
2020-05-14 16:41:43 +02:00
if ( ! dir_access - > current_is_dir ( ) ) {
2015-05-31 06:59:42 +02:00
files . push_back ( item ) ;
2020-05-14 16:41:43 +02:00
} else {
2015-05-31 06:59:42 +02:00
dirs . push_back ( item ) ;
2020-05-14 16:41:43 +02:00
}
2021-03-03 15:33:34 +01:00
} else if ( ! dir_access - > current_is_hidden ( ) ) {
String full_path = cdir = = " res:// " ? item : dir_access - > get_current_dir ( ) + " / " + item ;
2024-04-15 05:13:46 +02:00
if ( dir_access - > current_is_dir ( ) ) {
if ( Engine : : get_singleton ( ) - > is_project_manager_hint ( ) | | ! EditorFileSystem : : _should_skip_directory ( full_path ) ) {
dirs . push_back ( item ) ;
}
2021-03-03 15:33:34 +01:00
} else {
files . push_back ( item ) ;
}
2015-05-31 06:59:42 +02:00
}
2021-11-30 15:19:26 +01:00
item = dir_access - > get_next ( ) ;
2015-05-31 06:59:42 +02:00
}
2024-02-02 16:50:23 +01:00
dirs . sort_custom < FileNoCaseComparator > ( ) ;
files . sort_custom < FileNoCaseComparator > ( ) ;
2015-05-31 06:59:42 +02:00
2020-12-15 13:04:21 +01:00
while ( ! dirs . is_empty ( ) ) {
2016-09-26 09:38:15 +02:00
const String & dir_name = dirs . front ( ) - > get ( ) ;
2015-05-31 06:59:42 +02:00
2017-11-21 00:58:07 +01:00
item_list - > add_item ( dir_name ) ;
2015-06-06 14:44:38 +02:00
2016-09-26 09:38:15 +02:00
if ( display_mode = = DISPLAY_THUMBNAILS ) {
2022-03-12 01:06:45 +01:00
item_list - > set_item_icon ( - 1 , folder_thumbnail ) ;
2016-09-26 09:38:15 +02:00
} else {
2022-09-01 17:52:49 +02:00
item_list - > set_item_icon ( - 1 , theme_cache . folder ) ;
2015-05-31 06:59:42 +02:00
}
2016-09-26 09:38:15 +02:00
Dictionary d ;
d [ " name " ] = dir_name ;
2022-08-30 02:34:01 +02:00
d [ " path " ] = cdir . path_join ( dir_name ) ;
2016-09-26 09:38:15 +02:00
d [ " dir " ] = true ;
2022-03-12 01:06:45 +01:00
item_list - > set_item_metadata ( - 1 , d ) ;
2023-11-13 11:15:25 +01:00
item_list - > set_item_icon_modulate ( - 1 , get_dir_icon_color ( String ( d [ " path " ] ) ) ) ;
2016-09-26 09:38:15 +02:00
dirs . pop_front ( ) ;
2015-05-31 06:59:42 +02:00
}
List < String > patterns ;
// build filter
if ( filter - > get_selected ( ) = = filter - > get_item_count ( ) - 1 ) {
// match all
} else if ( filters . size ( ) > 1 & & filter - > get_selected ( ) = = 0 ) {
// match all filters
for ( int i = 0 ; i < filters . size ( ) ; i + + ) {
String f = filters [ i ] . get_slice ( " ; " , 0 ) ;
for ( int j = 0 ; j < f . get_slice_count ( " , " ) ; j + + ) {
patterns . push_back ( f . get_slice ( " , " , j ) . strip_edges ( ) ) ;
}
}
} else {
int idx = filter - > get_selected ( ) ;
2020-05-14 16:41:43 +02:00
if ( filters . size ( ) > 1 ) {
2015-05-31 06:59:42 +02:00
idx - - ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
if ( idx > = 0 & & idx < filters . size ( ) ) {
String f = filters [ idx ] . get_slice ( " ; " , 0 ) ;
for ( int j = 0 ; j < f . get_slice_count ( " , " ) ; j + + ) {
patterns . push_back ( f . get_slice ( " , " , j ) . strip_edges ( ) ) ;
}
}
}
2020-12-15 13:04:21 +01:00
while ( ! files . is_empty ( ) ) {
bool match = patterns . is_empty ( ) ;
2015-05-31 06:59:42 +02:00
2021-07-24 15:46:25 +02:00
for ( const String & E : patterns ) {
2021-07-16 05:45:57 +02:00
if ( files . front ( ) - > get ( ) . matchn ( E ) ) {
2015-05-31 06:59:42 +02:00
match = true ;
break ;
}
}
if ( match ) {
2015-06-06 14:44:38 +02:00
item_list - > add_item ( files . front ( ) - > get ( ) ) ;
2015-05-31 06:59:42 +02:00
if ( get_icon_func ) {
2022-08-30 02:34:01 +02:00
Ref < Texture2D > icon = get_icon_func ( cdir . path_join ( files . front ( ) - > get ( ) ) ) ;
2015-06-06 14:44:38 +02:00
if ( display_mode = = DISPLAY_THUMBNAILS ) {
2023-02-17 22:37:38 +01:00
Ref < Texture2D > thumbnail ;
if ( get_thumbnail_func ) {
thumbnail = get_thumbnail_func ( cdir . path_join ( files . front ( ) - > get ( ) ) ) ;
}
if ( thumbnail . is_null ( ) ) {
thumbnail = file_thumbnail ;
}
item_list - > set_item_icon ( - 1 , thumbnail ) ;
2022-03-12 01:06:45 +01:00
item_list - > set_item_tag_icon ( - 1 , icon ) ;
2015-06-06 14:44:38 +02:00
} else {
2022-03-12 01:06:45 +01:00
item_list - > set_item_icon ( - 1 , icon ) ;
2015-06-06 14:44:38 +02:00
}
2015-05-31 06:59:42 +02:00
}
Dictionary d ;
d [ " name " ] = files . front ( ) - > get ( ) ;
d [ " dir " ] = false ;
2022-08-30 02:34:01 +02:00
String fullpath = cdir . path_join ( files . front ( ) - > get ( ) ) ;
2018-12-06 16:02:40 +01:00
d [ " path " ] = fullpath ;
2022-03-12 01:06:45 +01:00
item_list - > set_item_metadata ( - 1 , d ) ;
2018-12-06 16:02:40 +01:00
2022-02-03 01:21:52 +01:00
if ( display_mode = = DISPLAY_THUMBNAILS & & previews_enabled ) {
2015-06-06 14:44:38 +02:00
EditorResourcePreview : : get_singleton ( ) - > queue_resource_preview ( fullpath , this , " _thumbnail_result " , fullpath ) ;
}
2015-05-31 06:59:42 +02:00
2020-05-14 16:41:43 +02:00
if ( file - > get_text ( ) = = files . front ( ) - > get ( ) ) {
2015-06-06 14:44:38 +02:00
item_list - > set_current ( item_list - > get_item_count ( ) - 1 ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
}
files . pop_front ( ) ;
}
2015-06-06 14:44:38 +02:00
if ( favorites - > get_current ( ) > = 0 ) {
2020-12-21 11:26:41 +01:00
favorites - > deselect ( favorites - > get_current ( ) ) ;
2015-06-06 14:44:38 +02:00
}
favorite - > set_pressed ( false ) ;
fav_up - > set_disabled ( true ) ;
fav_down - > set_disabled ( true ) ;
2020-12-14 19:37:30 +01:00
get_ok_button ( ) - > set_disabled ( _is_open_should_be_disabled ( ) ) ;
2015-06-06 14:44:38 +02:00
for ( int i = 0 ; i < favorites - > get_item_count ( ) ; i + + ) {
2019-03-08 01:48:12 +01:00
if ( favorites - > get_item_metadata ( i ) = = cdir | | favorites - > get_item_metadata ( i ) = = cdir + " / " ) {
2015-06-06 14:44:38 +02:00
favorites - > select ( i ) ;
favorite - > set_pressed ( true ) ;
if ( i > 0 ) {
fav_up - > set_disabled ( false ) ;
}
if ( i < favorites - > get_item_count ( ) - 1 ) {
fav_down - > set_disabled ( false ) ;
}
break ;
}
}
2015-05-31 06:59:42 +02:00
}
void EditorFileDialog : : _filter_selected ( int ) {
2019-06-28 09:29:50 +02:00
update_file_name ( ) ;
2015-05-31 06:59:42 +02:00
update_file_list ( ) ;
}
void EditorFileDialog : : update_filters ( ) {
filter - > clear ( ) ;
if ( filters . size ( ) > 1 ) {
String all_filters ;
const int max_filters = 5 ;
for ( int i = 0 ; i < MIN ( max_filters , filters . size ( ) ) ; i + + ) {
2019-12-07 02:40:59 +01:00
String flt = filters [ i ] . get_slice ( " ; " , 0 ) . strip_edges ( ) ;
2020-05-14 16:41:43 +02:00
if ( i > 0 ) {
2019-12-07 02:40:59 +01:00
all_filters + = " , " ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
all_filters + = flt ;
}
2020-05-14 16:41:43 +02:00
if ( max_filters < filters . size ( ) ) {
2015-05-31 06:59:42 +02:00
all_filters + = " , ... " ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
2019-12-06 11:31:42 +01:00
filter - > add_item ( TTR ( " All Recognized " ) + " ( " + all_filters + " ) " ) ;
2015-05-31 06:59:42 +02:00
}
for ( int i = 0 ; i < filters . size ( ) ; i + + ) {
String flt = filters [ i ] . get_slice ( " ; " , 0 ) . strip_edges ( ) ;
String desc = filters [ i ] . get_slice ( " ; " , 1 ) . strip_edges ( ) ;
2020-05-14 16:41:43 +02:00
if ( desc . length ( ) ) {
2019-12-06 11:31:42 +01:00
filter - > add_item ( desc + " ( " + flt + " ) " ) ;
2020-05-14 16:41:43 +02:00
} else {
2019-12-06 11:31:42 +01:00
filter - > add_item ( " ( " + flt + " ) " ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
}
2016-05-04 03:25:37 +02:00
filter - > add_item ( TTR ( " All Files (*) " ) ) ;
2015-05-31 06:59:42 +02:00
}
void EditorFileDialog : : clear_filters ( ) {
filters . clear ( ) ;
update_filters ( ) ;
invalidate ( ) ;
}
2020-05-14 14:29:06 +02:00
2022-07-04 23:26:26 +02:00
void EditorFileDialog : : add_filter ( const String & p_filter , const String & p_description ) {
if ( p_description . is_empty ( ) ) {
filters . push_back ( p_filter ) ;
} else {
filters . push_back ( vformat ( " %s ; %s " , p_filter , p_description ) ) ;
}
2015-05-31 06:59:42 +02:00
update_filters ( ) ;
invalidate ( ) ;
}
2023-02-22 10:55:08 +01:00
void EditorFileDialog : : set_filters ( const Vector < String > & p_filters ) {
if ( filters = = p_filters ) {
return ;
}
filters = p_filters ;
update_filters ( ) ;
invalidate ( ) ;
}
Vector < String > EditorFileDialog : : get_filters ( ) const {
return filters ;
}
2015-05-31 06:59:42 +02:00
String EditorFileDialog : : get_current_dir ( ) const {
2020-02-10 09:19:29 +01:00
return dir_access - > get_current_dir ( ) ;
2015-05-31 06:59:42 +02:00
}
2020-05-14 14:29:06 +02:00
2015-05-31 06:59:42 +02:00
String EditorFileDialog : : get_current_file ( ) const {
return file - > get_text ( ) ;
}
2020-05-14 14:29:06 +02:00
2015-05-31 06:59:42 +02:00
String EditorFileDialog : : get_current_path ( ) const {
2022-08-30 02:34:01 +02:00
return dir_access - > get_current_dir ( ) . path_join ( file - > get_text ( ) ) ;
2015-05-31 06:59:42 +02:00
}
2020-05-14 14:29:06 +02:00
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : set_current_dir ( const String & p_dir ) {
2021-08-30 01:43:47 +02:00
if ( p_dir . is_relative_path ( ) ) {
2019-12-14 11:06:29 +01:00
dir_access - > change_dir ( OS : : get_singleton ( ) - > get_resource_dir ( ) ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
dir_access - > change_dir ( p_dir ) ;
update_dir ( ) ;
invalidate ( ) ;
}
2020-05-14 14:29:06 +02:00
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : set_current_file ( const String & p_file ) {
file - > set_text ( p_file ) ;
update_dir ( ) ;
invalidate ( ) ;
2022-01-03 10:08:03 +01:00
_focus_file_text ( ) ;
2015-05-31 06:59:42 +02:00
2020-05-14 16:41:43 +02:00
if ( is_visible ( ) ) {
2022-08-30 02:34:01 +02:00
_request_single_thumbnail ( get_current_dir ( ) . path_join ( get_current_file ( ) ) ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
}
2020-05-14 14:29:06 +02:00
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : set_current_path ( const String & p_path ) {
2020-05-14 16:41:43 +02:00
if ( ! p_path . size ( ) ) {
2015-05-31 06:59:42 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2020-07-03 15:26:22 +02:00
int pos = MAX ( p_path . rfind ( " / " ) , p_path . rfind ( " \\ " ) ) ;
2015-05-31 06:59:42 +02:00
if ( pos = = - 1 ) {
set_current_file ( p_path ) ;
} else {
2022-09-29 11:53:28 +02:00
String path_dir = p_path . substr ( 0 , pos ) ;
String path_file = p_path . substr ( pos + 1 , p_path . length ( ) ) ;
set_current_dir ( path_dir ) ;
set_current_file ( path_file ) ;
2015-05-31 06:59:42 +02:00
}
}
2020-03-06 18:00:16 +01:00
void EditorFileDialog : : set_file_mode ( FileMode p_mode ) {
2015-05-31 06:59:42 +02:00
mode = p_mode ;
switch ( mode ) {
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_FILE :
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Open " ) ) ;
2017-08-23 22:25:14 +02:00
set_title ( TTR ( " Open a File " ) ) ;
2017-12-02 01:37:32 +01:00
can_create_dir = false ;
2016-05-04 03:25:37 +02:00
break ;
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_FILES :
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Open " ) ) ;
2017-08-23 22:25:14 +02:00
set_title ( TTR ( " Open File(s) " ) ) ;
2017-12-02 01:37:32 +01:00
can_create_dir = false ;
2016-05-04 03:25:37 +02:00
break ;
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_DIR :
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Open " ) ) ;
2017-08-23 22:25:14 +02:00
set_title ( TTR ( " Open a Directory " ) ) ;
2017-12-02 01:37:32 +01:00
can_create_dir = true ;
2016-05-04 03:25:37 +02:00
break ;
2020-03-06 18:00:16 +01:00
case FILE_MODE_OPEN_ANY :
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Open " ) ) ;
2017-08-23 22:25:14 +02:00
set_title ( TTR ( " Open a File or Directory " ) ) ;
2017-12-02 01:37:32 +01:00
can_create_dir = true ;
2016-05-04 03:25:37 +02:00
break ;
2020-03-06 18:00:16 +01:00
case FILE_MODE_SAVE_FILE :
2022-07-08 02:31:19 +02:00
set_ok_button_text ( TTR ( " Save " ) ) ;
2017-08-23 22:25:14 +02:00
set_title ( TTR ( " Save a File " ) ) ;
2017-12-02 01:37:32 +01:00
can_create_dir = true ;
2016-05-04 03:25:37 +02:00
break ;
2015-05-31 06:59:42 +02:00
}
2020-03-06 18:00:16 +01:00
if ( mode = = FILE_MODE_OPEN_FILES ) {
2015-06-06 14:44:38 +02:00
item_list - > set_select_mode ( ItemList : : SELECT_MULTI ) ;
2015-05-31 06:59:42 +02:00
} else {
2015-06-06 14:44:38 +02:00
item_list - > set_select_mode ( ItemList : : SELECT_SINGLE ) ;
2015-05-31 06:59:42 +02:00
}
2017-12-02 01:37:32 +01:00
if ( can_create_dir ) {
makedir - > show ( ) ;
} else {
makedir - > hide ( ) ;
}
2015-05-31 06:59:42 +02:00
}
2020-03-06 18:00:16 +01:00
EditorFileDialog : : FileMode EditorFileDialog : : get_file_mode ( ) const {
2015-05-31 06:59:42 +02:00
return mode ;
}
void EditorFileDialog : : set_access ( Access p_access ) {
ERR_FAIL_INDEX ( p_access , 3 ) ;
2020-05-14 16:41:43 +02:00
if ( access = = p_access ) {
2015-05-31 06:59:42 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
switch ( p_access ) {
case ACCESS_FILESYSTEM : {
dir_access = DirAccess : : create ( DirAccess : : ACCESS_FILESYSTEM ) ;
} break ;
case ACCESS_RESOURCES : {
dir_access = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
} break ;
case ACCESS_USERDATA : {
dir_access = DirAccess : : create ( DirAccess : : ACCESS_USERDATA ) ;
} break ;
}
access = p_access ;
_update_drives ( ) ;
invalidate ( ) ;
update_filters ( ) ;
update_dir ( ) ;
}
void EditorFileDialog : : invalidate ( ) {
2023-01-22 18:26:32 +01:00
if ( ! is_visible ( ) | | is_invalidating ) {
return ;
}
is_invalidating = true ;
callable_mp ( this , & EditorFileDialog : : _invalidate ) . call_deferred ( ) ;
}
void EditorFileDialog : : _invalidate ( ) {
if ( ! is_invalidating ) {
return ;
2015-05-31 06:59:42 +02:00
}
2023-01-22 18:26:32 +01:00
update_file_list ( ) ;
_update_favorites ( ) ;
_update_recent ( ) ;
is_invalidating = false ;
2015-05-31 06:59:42 +02:00
}
EditorFileDialog : : Access EditorFileDialog : : get_access ( ) const {
return access ;
}
void EditorFileDialog : : _make_dir_confirm ( ) {
2022-04-05 19:09:52 +02:00
const String stripped_dirname = makedirname - > get_text ( ) . strip_edges ( ) ;
if ( dir_access - > dir_exists ( stripped_dirname ) ) {
2022-03-24 23:27:33 +01:00
error_dialog - > set_text ( TTR ( " Could not create folder. File with that name already exists. " ) ) ;
error_dialog - > popup_centered ( Size2 ( 250 , 50 ) * EDSCALE ) ;
makedirname - > set_text ( " " ) ; // Reset label.
return ;
}
2022-04-05 19:09:52 +02:00
Error err = dir_access - > make_dir ( stripped_dirname ) ;
2015-05-31 06:59:42 +02:00
if ( err = = OK ) {
2022-04-05 19:09:52 +02:00
dir_access - > change_dir ( stripped_dirname ) ;
2015-05-31 06:59:42 +02:00
invalidate ( ) ;
update_filters ( ) ;
update_dir ( ) ;
2015-06-06 14:44:38 +02:00
_push_history ( ) ;
2022-02-03 01:21:52 +01:00
if ( access ! = ACCESS_FILESYSTEM ) {
EditorFileSystem : : get_singleton ( ) - > scan_changes ( ) ; //we created a dir, so rescan changes
}
2015-05-31 06:59:42 +02:00
} else {
2022-02-03 01:21:52 +01:00
error_dialog - > set_text ( TTR ( " Could not create folder. " ) ) ;
error_dialog - > popup_centered ( Size2 ( 250 , 50 ) * EDSCALE ) ;
2015-05-31 06:59:42 +02:00
}
2016-05-01 11:38:24 +02:00
makedirname - > set_text ( " " ) ; // reset label
2015-05-31 06:59:42 +02:00
}
void EditorFileDialog : : _make_dir ( ) {
2020-03-06 18:00:16 +01:00
makedialog - > popup_centered ( Size2 ( 250 , 80 ) * EDSCALE ) ;
2015-05-31 06:59:42 +02:00
makedirname - > grab_focus ( ) ;
}
2017-12-02 01:37:32 +01:00
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 ) {
2022-02-03 01:21:52 +01:00
if ( access = = ACCESS_FILESYSTEM ) {
global_remove_dialog - > popup_centered ( ) ;
} else {
dep_remove_dialog - > reset_size ( ) ;
dep_remove_dialog - > show ( folders , files ) ;
}
2017-12-02 01:37:32 +01:00
}
}
2022-02-03 01:21:52 +01:00
void EditorFileDialog : : _delete_files_global ( ) {
// Delete files outside of the project directory without dependency checks.
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 ) ;
// Only delete empty directories for safety.
dir_access - > remove ( item_meta [ " path " ] ) ;
}
update_file_list ( ) ;
}
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : _select_drive ( int p_idx ) {
String d = drives - > get_item_text ( p_idx ) ;
dir_access - > change_dir ( d ) ;
file - > set_text ( " " ) ;
invalidate ( ) ;
update_dir ( ) ;
2015-06-06 14:44:38 +02:00
_push_history ( ) ;
2015-05-31 06:59:42 +02:00
}
2022-01-24 12:12:46 +01:00
void EditorFileDialog : : _update_drives ( bool p_select ) {
2015-05-31 06:59:42 +02:00
int dc = dir_access - > get_drive_count ( ) ;
if ( dc = = 0 | | access ! = ACCESS_FILESYSTEM ) {
drives - > hide ( ) ;
} else {
drives - > clear ( ) ;
2020-02-10 09:19:29 +01:00
Node * dp = drives - > get_parent ( ) ;
if ( dp ) {
dp - > remove_child ( drives ) ;
}
dp = dir_access - > drives_are_shortcuts ( ) ? shortcuts_container : drives_container ;
dp - > add_child ( drives ) ;
2015-05-31 06:59:42 +02:00
drives - > show ( ) ;
for ( int i = 0 ; i < dir_access - > get_drive_count ( ) ; i + + ) {
String d = dir_access - > get_drive ( i ) ;
drives - > add_item ( dir_access - > get_drive ( i ) ) ;
}
2022-01-24 12:12:46 +01:00
if ( p_select ) {
drives - > select ( dir_access - > get_current_drive ( ) ) ;
}
2015-05-31 06:59:42 +02:00
}
}
2022-02-03 01:21:52 +01:00
void EditorFileDialog : : _update_icons ( ) {
// Update icons.
2022-09-01 17:52:49 +02:00
mode_thumbnails - > set_icon ( theme_cache . mode_thumbnails ) ;
mode_list - > set_icon ( theme_cache . mode_list ) ;
2022-02-03 01:21:52 +01:00
if ( is_layout_rtl ( ) ) {
2022-09-01 17:52:49 +02:00
dir_prev - > set_icon ( theme_cache . forward_folder ) ;
dir_next - > set_icon ( theme_cache . back_folder ) ;
2022-02-03 01:21:52 +01:00
} else {
2022-09-01 17:52:49 +02:00
dir_prev - > set_icon ( theme_cache . back_folder ) ;
dir_next - > set_icon ( theme_cache . forward_folder ) ;
2022-02-03 01:21:52 +01:00
}
2022-09-01 17:52:49 +02:00
dir_up - > set_icon ( theme_cache . parent_folder ) ;
2022-02-03 01:21:52 +01:00
2022-09-01 17:52:49 +02:00
refresh - > set_icon ( theme_cache . reload ) ;
favorite - > set_icon ( theme_cache . favorite ) ;
show_hidden - > set_icon ( theme_cache . toggle_hidden ) ;
2024-02-25 17:51:50 +01:00
makedir - > set_icon ( theme_cache . create_folder ) ;
2022-09-01 17:52:49 +02:00
fav_up - > set_icon ( theme_cache . favorites_up ) ;
fav_down - > set_icon ( theme_cache . favorites_down ) ;
2022-02-03 01:21:52 +01:00
}
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _favorite_selected ( int p_idx ) {
2022-02-03 01:21:52 +01:00
Error change_dir_result = dir_access - > change_dir ( favorites - > get_item_metadata ( p_idx ) ) ;
if ( change_dir_result ! = OK ) {
error_dialog - > set_text ( TTR ( " Favorited folder does not exist anymore and will be removed. " ) ) ;
error_dialog - > popup_centered ( Size2 ( 250 , 50 ) * EDSCALE ) ;
bool res = ( access = = ACCESS_RESOURCES ) ;
Vector < String > favorited = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
String dir_to_remove = favorites - > get_item_metadata ( p_idx ) ;
bool found = false ;
for ( int i = 0 ; i < favorited . size ( ) ; i + + ) {
bool cres = favorited [ i ] . begins_with ( " res:// " ) ;
if ( cres ! = res ) {
continue ;
}
if ( favorited [ i ] = = dir_to_remove ) {
found = true ;
break ;
}
}
if ( found ) {
favorited . erase ( favorites - > get_item_metadata ( p_idx ) ) ;
favorites - > remove_item ( p_idx ) ;
EditorSettings : : get_singleton ( ) - > set_favorites ( favorited ) ;
}
} else {
update_dir ( ) ;
invalidate ( ) ;
_push_history ( ) ;
}
2015-06-06 14:44:38 +02:00
}
void EditorFileDialog : : _favorite_move_up ( ) {
int current = favorites - > get_current ( ) ;
if ( current > 0 & & current < favorites - > get_item_count ( ) ) {
2018-09-18 14:02:59 +02:00
Vector < String > favorited = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2015-06-06 14:44:38 +02:00
2015-06-07 03:06:58 +02:00
int a_idx = favorited . find ( String ( favorites - > get_item_metadata ( current - 1 ) ) ) ;
int b_idx = favorited . find ( String ( favorites - > get_item_metadata ( current ) ) ) ;
2015-06-06 14:44:38 +02:00
2020-05-14 16:41:43 +02:00
if ( a_idx = = - 1 | | b_idx = = - 1 ) {
2015-06-06 14:44:38 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 03:11:03 +02:00
SWAP ( favorited . write [ a_idx ] , favorited . write [ b_idx ] ) ;
2015-06-06 14:44:38 +02:00
2018-09-18 14:02:59 +02:00
EditorSettings : : get_singleton ( ) - > set_favorites ( favorited ) ;
2015-06-06 14:44:38 +02:00
_update_favorites ( ) ;
update_file_list ( ) ;
}
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _favorite_move_down ( ) {
int current = favorites - > get_current ( ) ;
if ( current > = 0 & & current < favorites - > get_item_count ( ) - 1 ) {
2018-09-18 14:02:59 +02:00
Vector < String > favorited = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2015-06-06 14:44:38 +02:00
2015-06-07 03:06:58 +02:00
int a_idx = favorited . find ( String ( favorites - > get_item_metadata ( current + 1 ) ) ) ;
int b_idx = favorited . find ( String ( favorites - > get_item_metadata ( current ) ) ) ;
2015-06-06 14:44:38 +02:00
2020-05-14 16:41:43 +02:00
if ( a_idx = = - 1 | | b_idx = = - 1 ) {
2015-06-06 14:44:38 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2018-07-25 03:11:03 +02:00
SWAP ( favorited . write [ a_idx ] , favorited . write [ b_idx ] ) ;
2015-06-06 14:44:38 +02:00
2018-09-18 14:02:59 +02:00
EditorSettings : : get_singleton ( ) - > set_favorites ( favorited ) ;
2015-06-06 14:44:38 +02:00
_update_favorites ( ) ;
update_file_list ( ) ;
}
}
void EditorFileDialog : : _update_favorites ( ) {
2022-02-03 01:21:52 +01:00
bool res = ( access = = ACCESS_RESOURCES ) ;
2015-06-06 14:44:38 +02:00
String current = get_current_dir ( ) ;
favorites - > clear ( ) ;
favorite - > set_pressed ( false ) ;
2018-09-18 14:02:59 +02:00
Vector < String > favorited = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2022-07-27 20:51:03 +02:00
Vector < String > favorited_paths ;
Vector < String > favorited_names ;
2022-03-23 23:28:51 +01:00
bool fav_changed = false ;
2022-07-27 20:51:03 +02:00
int current_favorite = - 1 ;
2015-06-06 14:44:38 +02:00
for ( int i = 0 ; i < favorited . size ( ) ; i + + ) {
2023-09-29 19:31:20 +02:00
String name = favorited [ i ] ;
bool cres = name . begins_with ( " res:// " ) ;
if ( cres ! = res | | ! name . ends_with ( " / " ) ) {
2015-06-06 14:44:38 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
2023-09-29 19:31:20 +02:00
if ( ! dir_access - > dir_exists ( name ) ) {
2022-07-27 20:51:03 +02:00
// Remove invalid directory from the list of Favorited directories.
favorited . remove_at ( i - - ) ;
fav_changed = true ;
continue ;
}
// Compute favorite display text.
2015-06-06 14:44:38 +02:00
if ( res & & name = = " res:// " ) {
2020-05-14 16:41:43 +02:00
if ( name = = current ) {
2022-07-27 20:51:03 +02:00
current_favorite = favorited_paths . size ( ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
name = " / " ;
2022-07-27 20:51:03 +02:00
favorited_paths . append ( favorited [ i ] ) ;
favorited_names . append ( name ) ;
2023-09-29 19:31:20 +02:00
} else {
2020-05-14 16:41:43 +02:00
if ( name = = current | | name = = current + " / " ) {
2022-07-27 20:51:03 +02:00
current_favorite = favorited_paths . size ( ) ;
2020-05-14 16:41:43 +02:00
}
2018-10-20 00:23:09 +02:00
name = name . substr ( 0 , name . length ( ) - 1 ) ;
name = name . get_file ( ) ;
2022-07-27 20:51:03 +02:00
favorited_paths . append ( favorited [ i ] ) ;
favorited_names . append ( name ) ;
2015-06-06 14:44:38 +02:00
}
2022-07-27 20:51:03 +02:00
}
if ( fav_changed ) {
EditorSettings : : get_singleton ( ) - > set_favorites ( favorited ) ;
}
EditorNode : : disambiguate_filenames ( favorited_paths , favorited_names ) ;
2015-06-06 14:44:38 +02:00
2022-07-27 20:51:03 +02:00
for ( int i = 0 ; i < favorited_paths . size ( ) ; i + + ) {
2022-09-01 17:52:49 +02:00
favorites - > add_item ( favorited_names [ i ] , theme_cache . folder ) ;
2022-07-27 20:51:03 +02:00
favorites - > set_item_metadata ( - 1 , favorited_paths [ i ] ) ;
2023-11-13 11:15:25 +01:00
favorites - > set_item_icon_modulate ( - 1 , get_dir_icon_color ( favorited_paths [ i ] ) ) ;
2015-06-06 14:44:38 +02:00
2022-07-27 20:51:03 +02:00
if ( i = = current_favorite ) {
2015-06-06 14:44:38 +02:00
favorite - > set_pressed ( true ) ;
favorites - > set_current ( favorites - > get_item_count ( ) - 1 ) ;
2020-12-21 11:26:41 +01:00
recent - > deselect_all ( ) ;
2015-06-06 14:44:38 +02:00
}
}
}
2019-06-09 22:41:45 +02:00
void EditorFileDialog : : _favorite_pressed ( ) {
2022-02-03 01:21:52 +01:00
bool res = ( access = = ACCESS_RESOURCES ) ;
2015-06-06 14:44:38 +02:00
String cd = get_current_dir ( ) ;
2020-05-14 16:41:43 +02:00
if ( ! cd . ends_with ( " / " ) ) {
2019-03-05 07:55:08 +01:00
cd + = " / " ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
2018-09-18 14:02:59 +02:00
Vector < String > favorited = EditorSettings : : get_singleton ( ) - > get_favorites ( ) ;
2015-06-06 14:44:38 +02:00
bool found = false ;
for ( int i = 0 ; i < favorited . size ( ) ; i + + ) {
bool cres = favorited [ i ] . begins_with ( " res:// " ) ;
2020-05-14 16:41:43 +02:00
if ( cres ! = res ) {
2015-06-06 14:44:38 +02:00
continue ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
if ( favorited [ i ] = = cd ) {
found = true ;
break ;
}
}
2020-05-14 16:41:43 +02:00
if ( found ) {
2015-06-06 14:44:38 +02:00
favorited . erase ( cd ) ;
2020-05-14 16:41:43 +02:00
} else {
2015-06-06 14:44:38 +02:00
favorited . push_back ( cd ) ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
2018-09-18 14:02:59 +02:00
EditorSettings : : get_singleton ( ) - > set_favorites ( favorited ) ;
2015-06-06 14:44:38 +02:00
_update_favorites ( ) ;
}
2022-09-01 17:52:49 +02:00
void EditorFileDialog : : _update_recent ( ) {
recent - > clear ( ) ;
bool res = ( access = = ACCESS_RESOURCES ) ;
Vector < String > recentd = EditorSettings : : get_singleton ( ) - > get_recent_dirs ( ) ;
Vector < String > recentd_paths ;
Vector < String > recentd_names ;
for ( int i = 0 ; i < recentd . size ( ) ; i + + ) {
bool cres = recentd [ i ] . begins_with ( " res:// " ) ;
if ( cres ! = res ) {
continue ;
}
if ( ! dir_access - > dir_exists ( recentd [ i ] ) ) {
// Remove invalid directory from the list of Recent directories.
recentd . remove_at ( i - - ) ;
continue ;
}
// Compute recent directory display text.
String name = recentd [ i ] ;
if ( res & & name = = " res:// " ) {
name = " / " ;
} else {
if ( name . ends_with ( " / " ) ) {
name = name . substr ( 0 , name . length ( ) - 1 ) ;
}
name = name . get_file ( ) ;
}
recentd_paths . append ( recentd [ i ] ) ;
recentd_names . append ( name ) ;
}
EditorNode : : disambiguate_filenames ( recentd_paths , recentd_names ) ;
for ( int i = 0 ; i < recentd_paths . size ( ) ; i + + ) {
recent - > add_item ( recentd_names [ i ] , theme_cache . folder ) ;
recent - > set_item_metadata ( - 1 , recentd_paths [ i ] ) ;
2023-11-13 11:15:25 +01:00
recent - > set_item_icon_modulate ( - 1 , get_dir_icon_color ( recentd_paths [ i ] ) ) ;
2022-09-01 17:52:49 +02:00
}
EditorSettings : : get_singleton ( ) - > set_recent_dirs ( recentd ) ;
}
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _recent_selected ( int p_idx ) {
Vector < String > recentd = EditorSettings : : get_singleton ( ) - > get_recent_dirs ( ) ;
ERR_FAIL_INDEX ( p_idx , recentd . size ( ) ) ;
dir_access - > change_dir ( recent - > get_item_metadata ( p_idx ) ) ;
update_file_list ( ) ;
update_dir ( ) ;
_push_history ( ) ;
}
void EditorFileDialog : : _go_up ( ) {
2023-08-20 17:06:35 +02:00
dir_access - > change_dir ( get_current_dir ( ) . trim_suffix ( " / " ) . get_base_dir ( ) ) ;
2015-06-06 14:44:38 +02:00
update_file_list ( ) ;
update_dir ( ) ;
_push_history ( ) ;
}
void EditorFileDialog : : _go_back ( ) {
if ( local_history_pos < = 0 ) {
return ;
}
local_history_pos - - ;
dir_access - > change_dir ( local_history [ local_history_pos ] ) ;
update_file_list ( ) ;
update_dir ( ) ;
dir_prev - > set_disabled ( local_history_pos = = 0 ) ;
dir_next - > set_disabled ( local_history_pos = = local_history . size ( ) - 1 ) ;
}
2020-05-14 14:29:06 +02:00
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _go_forward ( ) {
2023-01-03 09:23:49 +01:00
if ( local_history_pos > = local_history . size ( ) - 1 ) {
2015-06-06 14:44:38 +02:00
return ;
}
local_history_pos + + ;
dir_access - > change_dir ( local_history [ local_history_pos ] ) ;
update_file_list ( ) ;
update_dir ( ) ;
dir_prev - > set_disabled ( local_history_pos = = 0 ) ;
dir_next - > set_disabled ( local_history_pos = = local_history . size ( ) - 1 ) ;
}
2015-12-06 23:35:31 +01:00
bool EditorFileDialog : : default_show_hidden_files = false ;
2015-05-31 06:59:42 +02:00
2015-12-15 17:39:13 +01:00
EditorFileDialog : : DisplayMode EditorFileDialog : : default_display_mode = DISPLAY_THUMBNAILS ;
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : set_display_mode ( DisplayMode p_mode ) {
2020-05-14 16:41:43 +02:00
if ( display_mode = = p_mode ) {
2015-06-06 14:44:38 +02:00
return ;
2020-05-14 16:41:43 +02:00
}
2015-06-06 14:44:38 +02:00
if ( p_mode = = DISPLAY_THUMBNAILS ) {
mode_list - > set_pressed ( false ) ;
mode_thumbnails - > set_pressed ( true ) ;
} else {
mode_thumbnails - > set_pressed ( false ) ;
mode_list - > set_pressed ( true ) ;
}
display_mode = p_mode ;
2017-01-14 18:03:38 +01:00
invalidate ( ) ;
2015-06-06 14:44:38 +02:00
}
EditorFileDialog : : DisplayMode EditorFileDialog : : get_display_mode ( ) const {
return display_mode ;
}
2024-03-21 09:42:38 +01:00
TypedArray < Dictionary > EditorFileDialog : : _get_options ( ) const {
TypedArray < Dictionary > out ;
for ( const EditorFileDialog : : Option & opt : options ) {
Dictionary dict ;
dict [ " name " ] = opt . name ;
dict [ " values " ] = opt . values ;
dict [ " default " ] = ( int ) selected_options . get ( opt . name , opt . default_idx ) ;
out . push_back ( dict ) ;
}
return out ;
}
void EditorFileDialog : : _option_changed_checkbox_toggled ( bool p_pressed , const String & p_name ) {
if ( selected_options . has ( p_name ) ) {
selected_options [ p_name ] = p_pressed ;
}
}
void EditorFileDialog : : _option_changed_item_selected ( int p_idx , const String & p_name ) {
if ( selected_options . has ( p_name ) ) {
selected_options [ p_name ] = p_idx ;
}
}
void EditorFileDialog : : _update_option_controls ( ) {
if ( ! options_dirty ) {
return ;
}
options_dirty = false ;
while ( grid_options - > get_child_count ( ) > 0 ) {
Node * child = grid_options - > get_child ( 0 ) ;
grid_options - > remove_child ( child ) ;
child - > queue_free ( ) ;
}
selected_options . clear ( ) ;
for ( const EditorFileDialog : : Option & opt : options ) {
Label * lbl = memnew ( Label ) ;
lbl - > set_text ( opt . name ) ;
grid_options - > add_child ( lbl ) ;
if ( opt . values . is_empty ( ) ) {
CheckBox * cb = memnew ( CheckBox ) ;
cb - > set_pressed ( opt . default_idx ) ;
grid_options - > add_child ( cb ) ;
cb - > connect ( " toggled " , callable_mp ( this , & EditorFileDialog : : _option_changed_checkbox_toggled ) . bind ( opt . name ) ) ;
selected_options [ opt . name ] = ( bool ) opt . default_idx ;
} else {
OptionButton * ob = memnew ( OptionButton ) ;
for ( const String & val : opt . values ) {
ob - > add_item ( val ) ;
}
ob - > select ( opt . default_idx ) ;
grid_options - > add_child ( ob ) ;
ob - > connect ( " item_selected " , callable_mp ( this , & EditorFileDialog : : _option_changed_item_selected ) . bind ( opt . name ) ) ;
selected_options [ opt . name ] = opt . default_idx ;
}
}
}
Dictionary EditorFileDialog : : get_selected_options ( ) const {
return selected_options ;
}
String EditorFileDialog : : get_option_name ( int p_option ) const {
ERR_FAIL_INDEX_V ( p_option , options . size ( ) , String ( ) ) ;
return options [ p_option ] . name ;
}
Vector < String > EditorFileDialog : : get_option_values ( int p_option ) const {
ERR_FAIL_INDEX_V ( p_option , options . size ( ) , Vector < String > ( ) ) ;
return options [ p_option ] . values ;
}
int EditorFileDialog : : get_option_default ( int p_option ) const {
ERR_FAIL_INDEX_V ( p_option , options . size ( ) , - 1 ) ;
return options [ p_option ] . default_idx ;
}
void EditorFileDialog : : set_option_name ( int p_option , const String & p_name ) {
if ( p_option < 0 ) {
p_option + = get_option_count ( ) ;
}
ERR_FAIL_INDEX ( p_option , options . size ( ) ) ;
options . write [ p_option ] . name = p_name ;
options_dirty = true ;
if ( is_visible ( ) ) {
_update_option_controls ( ) ;
}
}
void EditorFileDialog : : set_option_values ( int p_option , const Vector < String > & p_values ) {
if ( p_option < 0 ) {
p_option + = get_option_count ( ) ;
}
ERR_FAIL_INDEX ( p_option , options . size ( ) ) ;
options . write [ p_option ] . values = p_values ;
if ( p_values . is_empty ( ) ) {
options . write [ p_option ] . default_idx = CLAMP ( options [ p_option ] . default_idx , 0 , 1 ) ;
} else {
options . write [ p_option ] . default_idx = CLAMP ( options [ p_option ] . default_idx , 0 , options [ p_option ] . values . size ( ) - 1 ) ;
}
options_dirty = true ;
if ( is_visible ( ) ) {
_update_option_controls ( ) ;
}
}
void EditorFileDialog : : set_option_default ( int p_option , int p_index ) {
if ( p_option < 0 ) {
p_option + = get_option_count ( ) ;
}
ERR_FAIL_INDEX ( p_option , options . size ( ) ) ;
if ( options [ p_option ] . values . is_empty ( ) ) {
options . write [ p_option ] . default_idx = CLAMP ( p_index , 0 , 1 ) ;
} else {
options . write [ p_option ] . default_idx = CLAMP ( p_index , 0 , options [ p_option ] . values . size ( ) - 1 ) ;
}
options_dirty = true ;
if ( is_visible ( ) ) {
_update_option_controls ( ) ;
}
}
void EditorFileDialog : : add_option ( const String & p_name , const Vector < String > & p_values , int p_index ) {
Option opt ;
opt . name = p_name ;
opt . values = p_values ;
if ( opt . values . is_empty ( ) ) {
opt . default_idx = CLAMP ( p_index , 0 , 1 ) ;
} else {
opt . default_idx = CLAMP ( p_index , 0 , opt . values . size ( ) - 1 ) ;
}
options . push_back ( opt ) ;
options_dirty = true ;
if ( is_visible ( ) ) {
_update_option_controls ( ) ;
}
}
void EditorFileDialog : : set_option_count ( int p_count ) {
ERR_FAIL_COND ( p_count < 0 ) ;
if ( options . size ( ) = = p_count ) {
return ;
}
options . resize ( p_count ) ;
options_dirty = true ;
notify_property_list_changed ( ) ;
if ( is_visible ( ) ) {
_update_option_controls ( ) ;
}
}
int EditorFileDialog : : get_option_count ( ) const {
return options . size ( ) ;
}
2015-05-31 06:59:42 +02:00
void EditorFileDialog : : _bind_methods ( ) {
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " _cancel_pressed " ) , & EditorFileDialog : : _cancel_pressed ) ;
2017-03-05 16:44:50 +01:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " clear_filters " ) , & EditorFileDialog : : clear_filters ) ;
2022-07-04 23:26:26 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_filter " , " filter " , " description " ) , & EditorFileDialog : : add_filter , DEFVAL ( " " ) ) ;
2023-02-22 10:55:08 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_filters " , " filters " ) , & EditorFileDialog : : set_filters ) ;
ClassDB : : bind_method ( D_METHOD ( " get_filters " ) , & EditorFileDialog : : get_filters ) ;
2024-03-21 09:42:38 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_option_name " , " option " ) , & EditorFileDialog : : get_option_name ) ;
ClassDB : : bind_method ( D_METHOD ( " get_option_values " , " option " ) , & EditorFileDialog : : get_option_values ) ;
ClassDB : : bind_method ( D_METHOD ( " get_option_default " , " option " ) , & EditorFileDialog : : get_option_default ) ;
ClassDB : : bind_method ( D_METHOD ( " set_option_name " , " option " , " name " ) , & EditorFileDialog : : set_option_name ) ;
ClassDB : : bind_method ( D_METHOD ( " set_option_values " , " option " , " values " ) , & EditorFileDialog : : set_option_values ) ;
ClassDB : : bind_method ( D_METHOD ( " set_option_default " , " option " , " default_value_index " ) , & EditorFileDialog : : set_option_default ) ;
ClassDB : : bind_method ( D_METHOD ( " set_option_count " , " count " ) , & EditorFileDialog : : set_option_count ) ;
ClassDB : : bind_method ( D_METHOD ( " get_option_count " ) , & EditorFileDialog : : get_option_count ) ;
ClassDB : : bind_method ( D_METHOD ( " add_option " , " name " , " values " , " default_value_index " ) , & EditorFileDialog : : add_option ) ;
ClassDB : : bind_method ( D_METHOD ( " get_selected_options " ) , & EditorFileDialog : : get_selected_options ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_current_dir " ) , & EditorFileDialog : : get_current_dir ) ;
ClassDB : : bind_method ( D_METHOD ( " get_current_file " ) , & EditorFileDialog : : get_current_file ) ;
ClassDB : : bind_method ( D_METHOD ( " get_current_path " ) , & EditorFileDialog : : get_current_path ) ;
ClassDB : : bind_method ( D_METHOD ( " set_current_dir " , " dir " ) , & EditorFileDialog : : set_current_dir ) ;
ClassDB : : bind_method ( D_METHOD ( " set_current_file " , " file " ) , & EditorFileDialog : : set_current_file ) ;
ClassDB : : bind_method ( D_METHOD ( " set_current_path " , " path " ) , & EditorFileDialog : : set_current_path ) ;
2020-03-06 18:00:16 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_file_mode " , " mode " ) , & EditorFileDialog : : set_file_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_file_mode " ) , & EditorFileDialog : : get_file_mode ) ;
2017-08-09 13:19:41 +02:00
ClassDB : : bind_method ( D_METHOD ( " get_vbox " ) , & EditorFileDialog : : get_vbox ) ;
2023-02-22 10:55:08 +01:00
ClassDB : : bind_method ( D_METHOD ( " get_line_edit " ) , & EditorFileDialog : : get_line_edit ) ;
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " set_access " , " access " ) , & EditorFileDialog : : set_access ) ;
ClassDB : : bind_method ( D_METHOD ( " get_access " ) , & EditorFileDialog : : get_access ) ;
ClassDB : : bind_method ( D_METHOD ( " set_show_hidden_files " , " show " ) , & EditorFileDialog : : set_show_hidden_files ) ;
ClassDB : : bind_method ( D_METHOD ( " is_showing_hidden_files " ) , & EditorFileDialog : : is_showing_hidden_files ) ;
ClassDB : : bind_method ( D_METHOD ( " _thumbnail_done " ) , & EditorFileDialog : : _thumbnail_done ) ;
ClassDB : : bind_method ( D_METHOD ( " set_display_mode " , " mode " ) , & EditorFileDialog : : set_display_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " get_display_mode " ) , & EditorFileDialog : : get_display_mode ) ;
ClassDB : : bind_method ( D_METHOD ( " _thumbnail_result " ) , & EditorFileDialog : : _thumbnail_result ) ;
ClassDB : : bind_method ( D_METHOD ( " set_disable_overwrite_warning " , " disable " ) , & EditorFileDialog : : set_disable_overwrite_warning ) ;
ClassDB : : bind_method ( D_METHOD ( " is_overwrite_warning_disabled " ) , & EditorFileDialog : : is_overwrite_warning_disabled ) ;
2023-09-12 01:05:18 +02:00
ClassDB : : bind_method ( D_METHOD ( " add_side_menu " , " menu " , " title " ) , & EditorFileDialog : : add_side_menu , DEFVAL ( " " ) ) ;
2024-04-29 21:49:32 +02:00
ClassDB : : bind_method ( D_METHOD ( " popup_file_dialog " ) , & EditorFileDialog : : popup_file_dialog ) ;
2017-03-05 16:44:50 +01:00
2017-02-13 12:47:24 +01:00
ClassDB : : bind_method ( D_METHOD ( " invalidate " ) , & EditorFileDialog : : invalidate ) ;
2017-03-05 16:44:50 +01:00
2015-05-31 06:59:42 +02:00
ADD_SIGNAL ( MethodInfo ( " file_selected " , PropertyInfo ( Variant : : STRING , " path " ) ) ) ;
2020-02-17 22:06:54 +01:00
ADD_SIGNAL ( MethodInfo ( " files_selected " , PropertyInfo ( Variant : : PACKED_STRING_ARRAY , " paths " ) ) ) ;
2015-05-31 06:59:42 +02:00
ADD_SIGNAL ( MethodInfo ( " dir_selected " , PropertyInfo ( Variant : : STRING , " dir " ) ) ) ;
2017-03-05 16:44:50 +01:00
2017-12-04 23:11:31 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " access " , PROPERTY_HINT_ENUM , " Resources,User data,File system " ) , " set_access " , " get_access " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " display_mode " , PROPERTY_HINT_ENUM , " Thumbnails,List " ) , " set_display_mode " , " get_display_mode " ) ;
2020-03-06 18:00:16 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : INT , " file_mode " , PROPERTY_HINT_ENUM , " Open one,Open many,Open folder,Open any,Save " ) , " set_file_mode " , " get_file_mode " ) ;
2021-10-29 20:15:33 +02:00
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " current_dir " , PROPERTY_HINT_DIR , " " , PROPERTY_USAGE_NONE ) , " set_current_dir " , " get_current_dir " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " current_file " , PROPERTY_HINT_FILE , " * " , PROPERTY_USAGE_NONE ) , " set_current_file " , " get_current_file " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : STRING , " current_path " , PROPERTY_HINT_NONE , " " , PROPERTY_USAGE_NONE ) , " set_current_path " , " get_current_path " ) ;
2023-02-22 10:55:08 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : PACKED_STRING_ARRAY , " filters " ) , " set_filters " , " get_filters " ) ;
2024-03-21 09:42:38 +01:00
ADD_ARRAY_COUNT ( " Options " , " option_count " , " set_option_count " , " get_option_count " , " option_ " ) ;
2017-12-04 23:11:31 +01:00
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " show_hidden_files " ) , " set_show_hidden_files " , " is_showing_hidden_files " ) ;
ADD_PROPERTY ( PropertyInfo ( Variant : : BOOL , " disable_overwrite_warning " ) , " set_disable_overwrite_warning " , " is_overwrite_warning_disabled " ) ;
2020-03-06 18:00:16 +01:00
BIND_ENUM_CONSTANT ( FILE_MODE_OPEN_FILE ) ;
BIND_ENUM_CONSTANT ( FILE_MODE_OPEN_FILES ) ;
BIND_ENUM_CONSTANT ( FILE_MODE_OPEN_DIR ) ;
BIND_ENUM_CONSTANT ( FILE_MODE_OPEN_ANY ) ;
BIND_ENUM_CONSTANT ( FILE_MODE_SAVE_FILE ) ;
2017-08-20 17:45:01 +02:00
BIND_ENUM_CONSTANT ( ACCESS_RESOURCES ) ;
BIND_ENUM_CONSTANT ( ACCESS_USERDATA ) ;
BIND_ENUM_CONSTANT ( ACCESS_FILESYSTEM ) ;
2017-09-12 21:09:06 +02:00
BIND_ENUM_CONSTANT ( DISPLAY_THUMBNAILS ) ;
BIND_ENUM_CONSTANT ( DISPLAY_LIST ) ;
2024-03-21 09:42:38 +01:00
Option defaults ;
base_property_helper . set_prefix ( " option_ " ) ;
2024-05-09 14:19:16 +02:00
base_property_helper . set_array_length_getter ( & EditorFileDialog : : get_option_count ) ;
2024-03-21 09:42:38 +01:00
base_property_helper . register_property ( PropertyInfo ( Variant : : STRING , " name " ) , defaults . name , & EditorFileDialog : : set_option_name , & EditorFileDialog : : get_option_name ) ;
base_property_helper . register_property ( PropertyInfo ( Variant : : PACKED_STRING_ARRAY , " values " ) , defaults . values , & EditorFileDialog : : set_option_values , & EditorFileDialog : : get_option_values ) ;
base_property_helper . register_property ( PropertyInfo ( Variant : : INT , " default " ) , defaults . default_idx , & EditorFileDialog : : set_option_default , & EditorFileDialog : : get_option_default ) ;
2015-05-31 06:59:42 +02:00
}
void EditorFileDialog : : set_show_hidden_files ( bool p_show ) {
2020-10-06 15:42:25 +02:00
if ( p_show = = show_hidden_files ) {
return ;
}
EditorSettings : : get_singleton ( ) - > set ( " filesystem/file_dialog/show_hidden_files " , p_show ) ;
2015-05-31 06:59:42 +02:00
show_hidden_files = p_show ;
2019-06-09 20:00:30 +02:00
show_hidden - > set_pressed ( p_show ) ;
2015-05-31 06:59:42 +02:00
invalidate ( ) ;
}
bool EditorFileDialog : : is_showing_hidden_files ( ) const {
return show_hidden_files ;
}
void EditorFileDialog : : set_default_show_hidden_files ( bool p_show ) {
default_show_hidden_files = p_show ;
}
2015-12-15 17:39:13 +01:00
void EditorFileDialog : : set_default_display_mode ( DisplayMode p_mode ) {
default_display_mode = p_mode ;
}
2015-06-06 14:44:38 +02:00
void EditorFileDialog : : _save_to_recent ( ) {
2022-09-29 11:53:28 +02:00
String cur_dir = get_current_dir ( ) ;
Vector < String > recent_new = EditorSettings : : get_singleton ( ) - > get_recent_dirs ( ) ;
2015-06-06 14:44:38 +02:00
const int max = 20 ;
int count = 0 ;
2022-09-29 11:53:28 +02:00
bool res = cur_dir . begins_with ( " res:// " ) ;
2015-06-06 14:44:38 +02:00
2022-09-29 11:53:28 +02:00
for ( int i = 0 ; i < recent_new . size ( ) ; i + + ) {
bool cres = recent_new [ i ] . begins_with ( " res:// " ) ;
if ( recent_new [ i ] = = cur_dir | | ( res = = cres & & count > max ) ) {
recent_new . remove_at ( i ) ;
2015-06-06 14:44:38 +02:00
i - - ;
} else {
count + + ;
}
}
2022-09-29 11:53:28 +02:00
recent_new . insert ( 0 , cur_dir ) ;
2015-06-06 14:44:38 +02:00
2022-09-29 11:53:28 +02:00
EditorSettings : : get_singleton ( ) - > set_recent_dirs ( recent_new ) ;
2015-06-06 14:44:38 +02:00
}
2016-06-20 05:38:13 +02:00
void EditorFileDialog : : set_disable_overwrite_warning ( bool p_disable ) {
disable_overwrite_warning = p_disable ;
}
bool EditorFileDialog : : is_overwrite_warning_disabled ( ) const {
return disable_overwrite_warning ;
}
2022-02-03 01:21:52 +01:00
void EditorFileDialog : : set_previews_enabled ( bool p_enabled ) {
previews_enabled = p_enabled ;
}
bool EditorFileDialog : : are_previews_enabled ( ) {
return previews_enabled ;
}
2023-09-12 01:05:18 +02:00
void EditorFileDialog : : add_side_menu ( Control * p_menu , const String & p_title ) {
// HSplitContainer has 3 children at maximum capacity, 1 of them is the SplitContainerDragger.
ERR_FAIL_COND_MSG ( body_hsplit - > get_child_count ( ) > 2 , " EditorFileDialog: Only one side menu can be added. " ) ;
// Everything for the side menu goes inside of a VBoxContainer.
2024-03-21 09:42:38 +01:00
side_vbox = memnew ( VBoxContainer ) ;
2023-09-12 01:05:18 +02:00
side_vbox - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
side_vbox - > set_stretch_ratio ( 0.5 ) ;
body_hsplit - > add_child ( side_vbox ) ;
// Add a Label to the VBoxContainer.
if ( ! p_title . is_empty ( ) ) {
Label * title_label = memnew ( Label ( p_title ) ) ;
title_label - > set_theme_type_variation ( " HeaderSmall " ) ;
side_vbox - > add_child ( title_label ) ;
}
// Add the given menu to the VBoxContainer.
p_menu - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
side_vbox - > add_child ( p_menu ) ;
}
2024-03-21 09:42:38 +01:00
void EditorFileDialog : : _update_side_menu_visibility ( bool p_native_dlg ) {
if ( p_native_dlg ) {
pathhb - > set_visible ( false ) ;
grid_options - > set_visible ( false ) ;
list_hb - > set_visible ( false ) ;
} else {
pathhb - > set_visible ( true ) ;
grid_options - > set_visible ( true ) ;
list_hb - > set_visible ( true ) ;
}
}
2015-05-31 06:59:42 +02:00
EditorFileDialog : : EditorFileDialog ( ) {
2015-12-06 23:35:31 +01:00
show_hidden_files = default_show_hidden_files ;
2015-12-15 17:39:13 +01:00
display_mode = default_display_mode ;
2024-03-21 09:42:38 +01:00
vbc = memnew ( VBoxContainer ) ;
2015-05-31 06:59:42 +02:00
add_child ( vbc ) ;
2016-05-04 03:25:37 +02:00
set_title ( TTR ( " Save a File " ) ) ;
2015-05-31 06:59:42 +02:00
2021-08-13 23:31:57 +02:00
ED_SHORTCUT ( " file_dialog/go_back " , TTR ( " Go Back " ) , KeyModifierMask : : ALT | Key : : LEFT ) ;
ED_SHORTCUT ( " file_dialog/go_forward " , TTR ( " Go Forward " ) , KeyModifierMask : : ALT | Key : : RIGHT ) ;
ED_SHORTCUT ( " file_dialog/go_up " , TTR ( " Go Up " ) , KeyModifierMask : : ALT | Key : : UP ) ;
ED_SHORTCUT ( " file_dialog/refresh " , TTR ( " Refresh " ) , Key : : F5 ) ;
2024-02-16 05:49:01 +01:00
ED_SHORTCUT ( " file_dialog/toggle_hidden_files " , TTR ( " Toggle Hidden Files " ) , KeyModifierMask : : CTRL | Key : : H ) ;
2021-08-13 23:31:57 +02:00
ED_SHORTCUT ( " file_dialog/toggle_favorite " , TTR ( " Toggle Favorite " ) , KeyModifierMask : : ALT | Key : : F ) ;
ED_SHORTCUT ( " file_dialog/toggle_mode " , TTR ( " Toggle Mode " ) , KeyModifierMask : : ALT | Key : : V ) ;
2022-09-02 11:37:48 +02:00
ED_SHORTCUT ( " file_dialog/create_folder " , TTR ( " Create Folder " ) , KeyModifierMask : : CMD_OR_CTRL | Key : : N ) ;
2021-08-13 23:31:57 +02:00
ED_SHORTCUT ( " file_dialog/delete " , TTR ( " Delete " ) , Key : : KEY_DELETE ) ;
2023-08-30 20:11:21 +02:00
ED_SHORTCUT ( " file_dialog/focus_path " , TTR ( " Focus Path " ) , KeyModifierMask : : CMD_OR_CTRL | Key : : L ) ;
// Allow both Cmd + L and Cmd + Shift + G to match Safari's and Finder's shortcuts respectively.
ED_SHORTCUT_OVERRIDE_ARRAY ( " file_dialog/focus_path " , " macos " ,
{ int32_t ( KeyModifierMask : : META | Key : : L ) , int32_t ( KeyModifierMask : : META | KeyModifierMask : : SHIFT | Key : : G ) } ) ;
2022-09-02 11:37:48 +02:00
ED_SHORTCUT ( " file_dialog/move_favorite_up " , TTR ( " Move Favorite Up " ) , KeyModifierMask : : CMD_OR_CTRL | Key : : UP ) ;
ED_SHORTCUT ( " file_dialog/move_favorite_down " , TTR ( " Move Favorite Down " ) , KeyModifierMask : : CMD_OR_CTRL | Key : : DOWN ) ;
2016-06-18 19:32:04 +02:00
2024-05-03 16:34:53 +02:00
ED_SHORTCUT_OVERRIDE ( " file_dialog/toggle_hidden_files " , " macos " , KeyModifierMask : : META | KeyModifierMask : : SHIFT | Key : : PERIOD ) ;
ED_SHORTCUT_OVERRIDE ( " file_dialog/toggle_favorite " , " macos " , KeyModifierMask : : META | KeyModifierMask : : CTRL | Key : : F ) ;
ED_SHORTCUT_OVERRIDE ( " file_dialog/toggle_mode " , " macos " , KeyModifierMask : : META | KeyModifierMask : : CTRL | Key : : V ) ;
2023-02-16 10:28:04 +01:00
2024-03-21 09:42:38 +01:00
pathhb = memnew ( HBoxContainer ) ;
2023-09-12 01:05:18 +02:00
vbc - > add_child ( pathhb ) ;
2015-06-06 14:44:38 +02:00
2020-06-19 20:49:04 +02:00
dir_prev = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
dir_prev - > set_theme_type_variation ( " FlatButton " ) ;
2022-08-25 12:42:17 +02:00
dir_prev - > set_tooltip_text ( TTR ( " Go to previous folder. " ) ) ;
2020-06-19 20:49:04 +02:00
dir_next = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
dir_next - > set_theme_type_variation ( " FlatButton " ) ;
2022-08-25 12:42:17 +02:00
dir_next - > set_tooltip_text ( TTR ( " Go to next folder. " ) ) ;
2020-06-19 20:49:04 +02:00
dir_up = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
dir_up - > set_theme_type_variation ( " FlatButton " ) ;
2022-08-25 12:42:17 +02:00
dir_up - > set_tooltip_text ( TTR ( " Go to parent folder. " ) ) ;
2015-06-06 14:44:38 +02:00
pathhb - > add_child ( dir_prev ) ;
pathhb - > add_child ( dir_next ) ;
pathhb - > add_child ( dir_up ) ;
2024-05-14 09:40:21 +02:00
dir_prev - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : _go_back ) ) ;
dir_next - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : _go_forward ) ) ;
dir_up - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : _go_up ) ) ;
2015-06-06 14:44:38 +02:00
2021-07-08 15:29:15 +02:00
Label * l = memnew ( Label ( TTR ( " Path: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
pathhb - > add_child ( l ) ;
2017-09-27 21:44:48 +02:00
2020-02-10 09:19:29 +01:00
drives_container = memnew ( HBoxContainer ) ;
pathhb - > add_child ( drives_container ) ;
2015-06-06 14:44:38 +02:00
dir = memnew ( LineEdit ) ;
2022-04-19 12:27:18 +02:00
dir - > set_structured_text_bidi_override ( TextServer : : STRUCTURED_TEXT_FILE ) ;
2015-05-31 06:59:42 +02:00
pathhb - > add_child ( dir ) ;
2020-03-06 18:00:16 +01:00
dir - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2015-05-31 06:59:42 +02:00
2020-06-19 20:49:04 +02:00
refresh = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
refresh - > set_theme_type_variation ( " FlatButton " ) ;
2022-08-25 12:42:17 +02:00
refresh - > set_tooltip_text ( TTR ( " Refresh files. " ) ) ;
2024-05-14 09:40:21 +02:00
refresh - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : update_file_list ) ) ;
2015-12-04 19:33:30 +01:00
pathhb - > add_child ( refresh ) ;
2020-06-19 20:49:04 +02:00
favorite = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
favorite - > set_theme_type_variation ( " FlatButton " ) ;
2015-06-06 14:44:38 +02:00
favorite - > set_toggle_mode ( true ) ;
2022-08-25 12:42:17 +02:00
favorite - > set_tooltip_text ( TTR ( " (Un)favorite current folder. " ) ) ;
2024-05-14 09:40:21 +02:00
favorite - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : _favorite_pressed ) ) ;
2015-06-06 14:44:38 +02:00
pathhb - > add_child ( favorite ) ;
2020-06-19 20:49:04 +02:00
show_hidden = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
show_hidden - > set_theme_type_variation ( " FlatButton " ) ;
2019-06-09 20:00:30 +02:00
show_hidden - > set_toggle_mode ( true ) ;
show_hidden - > set_pressed ( is_showing_hidden_files ( ) ) ;
2022-08-25 12:42:17 +02:00
show_hidden - > set_tooltip_text ( TTR ( " Toggle the visibility of hidden files. " ) ) ;
2020-02-21 18:28:45 +01:00
show_hidden - > connect ( " toggled " , callable_mp ( this , & EditorFileDialog : : set_show_hidden_files ) ) ;
2019-06-09 20:00:30 +02:00
pathhb - > add_child ( show_hidden ) ;
2017-06-14 16:00:39 +02:00
2017-12-25 05:29:00 +01:00
pathhb - > add_child ( memnew ( VSeparator ) ) ;
2019-06-09 20:00:30 +02:00
Ref < ButtonGroup > view_mode_group ;
2021-06-18 00:03:09 +02:00
view_mode_group . instantiate ( ) ;
2019-06-09 20:00:30 +02:00
2020-06-19 20:49:04 +02:00
mode_thumbnails = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
mode_thumbnails - > set_theme_type_variation ( " FlatButton " ) ;
2024-05-14 09:40:21 +02:00
mode_thumbnails - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : set_display_mode ) . bind ( DISPLAY_THUMBNAILS ) ) ;
2015-06-06 14:44:38 +02:00
mode_thumbnails - > set_toggle_mode ( true ) ;
2015-12-15 17:39:13 +01:00
mode_thumbnails - > set_pressed ( display_mode = = DISPLAY_THUMBNAILS ) ;
2017-06-14 16:00:39 +02:00
mode_thumbnails - > set_button_group ( view_mode_group ) ;
2022-08-25 12:42:17 +02:00
mode_thumbnails - > set_tooltip_text ( TTR ( " View items as a grid of thumbnails. " ) ) ;
2015-06-06 14:44:38 +02:00
pathhb - > add_child ( mode_thumbnails ) ;
2015-12-15 17:39:13 +01:00
2020-06-19 20:49:04 +02:00
mode_list = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
mode_list - > set_theme_type_variation ( " FlatButton " ) ;
2024-05-14 09:40:21 +02:00
mode_list - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : set_display_mode ) . bind ( DISPLAY_LIST ) ) ;
2015-06-06 14:44:38 +02:00
mode_list - > set_toggle_mode ( true ) ;
2015-12-15 17:39:13 +01:00
mode_list - > set_pressed ( display_mode = = DISPLAY_LIST ) ;
2017-06-14 16:00:39 +02:00
mode_list - > set_button_group ( view_mode_group ) ;
2022-08-25 12:42:17 +02:00
mode_list - > set_tooltip_text ( TTR ( " View items as a list. " ) ) ;
2015-06-06 14:44:38 +02:00
pathhb - > add_child ( mode_list ) ;
2020-02-10 09:19:29 +01:00
shortcuts_container = memnew ( HBoxContainer ) ;
pathhb - > add_child ( shortcuts_container ) ;
2015-05-31 06:59:42 +02:00
drives = memnew ( OptionButton ) ;
2020-02-21 18:28:45 +01:00
drives - > connect ( " item_selected " , callable_mp ( this , & EditorFileDialog : : _select_drive ) ) ;
2020-04-06 20:07:08 +02:00
pathhb - > add_child ( drives ) ;
2015-05-31 06:59:42 +02:00
2024-02-25 17:51:50 +01:00
pathhb - > add_child ( memnew ( VSeparator ) ) ;
2015-05-31 06:59:42 +02:00
makedir = memnew ( Button ) ;
2024-02-25 17:51:50 +01:00
makedir - > set_theme_type_variation ( " FlatButton " ) ;
makedir - > set_tooltip_text ( TTR ( " Create a new folder. " ) ) ;
2024-05-14 09:40:21 +02:00
makedir - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : _make_dir ) ) ;
2015-05-31 06:59:42 +02:00
pathhb - > add_child ( makedir ) ;
2023-09-12 01:05:18 +02:00
body_hsplit = memnew ( HSplitContainer ) ;
body_hsplit - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
vbc - > add_child ( body_hsplit ) ;
2015-05-31 06:59:42 +02:00
2024-03-21 09:42:38 +01:00
grid_options = memnew ( GridContainer ) ;
grid_options - > set_h_size_flags ( Control : : SIZE_SHRINK_CENTER ) ;
grid_options - > set_columns ( 2 ) ;
vbc - > add_child ( grid_options ) ;
2023-09-12 01:05:18 +02:00
list_hb = memnew ( HSplitContainer ) ;
list_hb - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
body_hsplit - > add_child ( list_hb ) ;
2015-06-06 14:44:38 +02:00
2017-12-25 05:29:00 +01:00
VSplitContainer * vsc = memnew ( VSplitContainer ) ;
list_hb - > add_child ( vsc ) ;
2015-06-06 14:44:38 +02:00
VBoxContainer * fav_vb = memnew ( VBoxContainer ) ;
2017-12-25 05:29:00 +01:00
vsc - > add_child ( fav_vb ) ;
fav_vb - > set_custom_minimum_size ( Size2 ( 150 , 100 ) * EDSCALE ) ;
2020-03-06 18:00:16 +01:00
fav_vb - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2015-06-06 14:44:38 +02:00
HBoxContainer * fav_hb = memnew ( HBoxContainer ) ;
fav_vb - > add_child ( fav_hb ) ;
2021-07-08 15:29:15 +02:00
l = memnew ( Label ( TTR ( " Favorites: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
fav_hb - > add_child ( l ) ;
2015-06-06 14:44:38 +02:00
fav_hb - > add_spacer ( ) ;
2020-06-19 20:49:04 +02:00
fav_up = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
fav_up - > set_theme_type_variation ( " FlatButton " ) ;
2015-06-06 14:44:38 +02:00
fav_hb - > add_child ( fav_up ) ;
2024-05-14 09:40:21 +02:00
fav_up - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : _favorite_move_up ) ) ;
2020-06-19 20:49:04 +02:00
fav_down = memnew ( Button ) ;
2023-09-19 18:03:10 +02:00
fav_down - > set_theme_type_variation ( " FlatButton " ) ;
2015-06-06 14:44:38 +02:00
fav_hb - > add_child ( fav_down ) ;
2024-05-14 09:40:21 +02:00
fav_down - > connect ( SceneStringName ( pressed ) , callable_mp ( this , & EditorFileDialog : : _favorite_move_down ) ) ;
2015-06-06 14:44:38 +02:00
favorites = memnew ( ItemList ) ;
2024-01-23 22:29:45 +01:00
favorites - > set_auto_translate_mode ( AUTO_TRANSLATE_MODE_DISABLED ) ;
2017-12-25 05:29:00 +01:00
fav_vb - > add_child ( favorites ) ;
2020-03-06 18:00:16 +01:00
favorites - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2020-02-21 18:28:45 +01:00
favorites - > connect ( " item_selected " , callable_mp ( this , & EditorFileDialog : : _favorite_selected ) ) ;
2015-06-06 14:44:38 +02:00
2017-12-25 05:29:00 +01:00
VBoxContainer * rec_vb = memnew ( VBoxContainer ) ;
vsc - > add_child ( rec_vb ) ;
rec_vb - > set_custom_minimum_size ( Size2 ( 150 , 100 ) * EDSCALE ) ;
2020-03-06 18:00:16 +01:00
rec_vb - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2015-06-06 14:44:38 +02:00
recent = memnew ( ItemList ) ;
2024-01-23 22:29:45 +01:00
recent - > set_auto_translate_mode ( AUTO_TRANSLATE_MODE_DISABLED ) ;
2019-06-10 03:09:10 +02:00
recent - > set_allow_reselect ( true ) ;
2017-12-25 05:29:00 +01:00
rec_vb - > add_margin_child ( TTR ( " Recent: " ) , recent , true ) ;
2020-02-21 18:28:45 +01:00
recent - > connect ( " item_selected " , callable_mp ( this , & EditorFileDialog : : _recent_selected ) ) ;
2015-06-06 14:44:38 +02:00
VBoxContainer * item_vb = memnew ( VBoxContainer ) ;
list_hb - > add_child ( item_vb ) ;
2017-12-25 05:29:00 +01:00
item_vb - > set_custom_minimum_size ( Size2 ( 320 , 0 ) * EDSCALE ) ;
2015-06-06 14:44:38 +02:00
2017-10-06 16:01:54 +02:00
HBoxContainer * preview_hb = memnew ( HBoxContainer ) ;
2020-03-06 18:00:16 +01:00
preview_hb - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2017-10-06 16:01:54 +02:00
item_vb - > add_child ( preview_hb ) ;
2015-05-31 06:59:42 +02:00
2017-10-06 16:01:54 +02:00
VBoxContainer * list_vb = memnew ( VBoxContainer ) ;
2020-03-06 18:00:16 +01:00
list_vb - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2021-07-08 15:29:15 +02:00
l = memnew ( Label ( TTR ( " Directories & Files: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
list_vb - > add_child ( l ) ;
2017-10-06 16:01:54 +02:00
preview_hb - > add_child ( list_vb ) ;
2015-05-31 06:59:42 +02:00
2019-06-10 03:09:10 +02:00
// Item (files and folders) list with context menu.
2017-12-02 01:37:32 +01:00
2017-10-06 16:01:54 +02:00
item_list = memnew ( ItemList ) ;
2024-01-23 22:29:45 +01:00
item_list - > set_auto_translate_mode ( AUTO_TRANSLATE_MODE_DISABLED ) ;
2020-03-06 18:00:16 +01:00
item_list - > set_v_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2021-11-26 00:53:27 +01:00
item_list - > connect ( " item_clicked " , callable_mp ( this , & EditorFileDialog : : _item_list_item_rmb_clicked ) ) ;
item_list - > connect ( " empty_clicked " , callable_mp ( this , & EditorFileDialog : : _item_list_empty_clicked ) ) ;
2017-12-02 01:37:32 +01:00
item_list - > set_allow_rmb_select ( true ) ;
2021-08-21 00:22:09 +02:00
2017-10-06 16:01:54 +02:00
list_vb - > add_child ( item_list ) ;
2015-05-31 06:59:42 +02:00
2017-12-02 01:37:32 +01:00
item_menu = memnew ( PopupMenu ) ;
2020-02-21 18:28:45 +01:00
item_menu - > connect ( " id_pressed " , callable_mp ( this , & EditorFileDialog : : _item_menu_id_pressed ) ) ;
2017-12-02 01:37:32 +01:00
add_child ( item_menu ) ;
2019-06-10 03:09:10 +02:00
// Other stuff.
2017-12-02 01:37:32 +01:00
2015-05-31 06:59:42 +02:00
preview_vb = memnew ( VBoxContainer ) ;
2017-10-06 16:01:54 +02:00
preview_hb - > add_child ( preview_vb ) ;
2015-05-31 06:59:42 +02:00
CenterContainer * prev_cc = memnew ( CenterContainer ) ;
2016-05-04 03:25:37 +02:00
preview_vb - > add_margin_child ( TTR ( " Preview: " ) , prev_cc ) ;
2017-01-12 22:27:27 +01:00
preview = memnew ( TextureRect ) ;
2015-05-31 06:59:42 +02:00
prev_cc - > add_child ( preview ) ;
preview_vb - > hide ( ) ;
2019-10-26 17:29:22 +02:00
file_box = memnew ( HBoxContainer ) ;
2021-07-08 15:29:15 +02:00
l = memnew ( Label ( TTR ( " File: " ) ) ) ;
l - > set_theme_type_variation ( " HeaderSmall " ) ;
file_box - > add_child ( l ) ;
2015-05-31 06:59:42 +02:00
file = memnew ( LineEdit ) ;
2022-04-19 12:27:18 +02:00
file - > set_structured_text_bidi_override ( TextServer : : STRUCTURED_TEXT_FILE ) ;
2017-10-06 16:01:54 +02:00
file - > set_stretch_ratio ( 4 ) ;
2020-03-06 18:00:16 +01:00
file - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2019-10-26 17:29:22 +02:00
file_box - > add_child ( file ) ;
2015-05-31 06:59:42 +02:00
filter = memnew ( OptionButton ) ;
2017-10-06 16:01:54 +02:00
filter - > set_stretch_ratio ( 3 ) ;
2020-03-06 18:00:16 +01:00
filter - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2019-06-10 03:09:10 +02:00
filter - > set_clip_text ( true ) ; // Too many extensions overflow it.
2019-10-26 17:29:22 +02:00
file_box - > add_child ( filter ) ;
2020-03-06 18:00:16 +01:00
file_box - > set_h_size_flags ( Control : : SIZE_EXPAND_FILL ) ;
2019-10-26 17:29:22 +02:00
item_vb - > add_child ( file_box ) ;
2015-05-31 06:59:42 +02:00
dir_access = DirAccess : : create ( DirAccess : : ACCESS_RESOURCES ) ;
_update_drives ( ) ;
2020-02-21 18:28:45 +01:00
connect ( " confirmed " , callable_mp ( this , & EditorFileDialog : : _action_pressed ) ) ;
2022-07-28 22:56:41 +02:00
item_list - > connect ( " item_selected " , callable_mp ( this , & EditorFileDialog : : _item_selected ) , CONNECT_DEFERRED ) ;
item_list - > connect ( " multi_selected " , callable_mp ( this , & EditorFileDialog : : _multi_selected ) , CONNECT_DEFERRED ) ;
item_list - > connect ( " item_activated " , callable_mp ( this , & EditorFileDialog : : _item_dc_selected ) . bind ( ) ) ;
2021-11-26 00:53:27 +01:00
item_list - > connect ( " empty_clicked " , callable_mp ( this , & EditorFileDialog : : _items_clear_selection ) ) ;
2021-06-16 18:43:34 +02:00
dir - > connect ( " text_submitted " , callable_mp ( this , & EditorFileDialog : : _dir_submitted ) ) ;
file - > connect ( " text_submitted " , callable_mp ( this , & EditorFileDialog : : _file_submitted ) ) ;
2020-02-21 18:28:45 +01:00
filter - > connect ( " item_selected " , callable_mp ( this , & EditorFileDialog : : _filter_selected ) ) ;
2015-05-31 06:59:42 +02:00
confirm_save = memnew ( ConfirmationDialog ) ;
add_child ( confirm_save ) ;
2020-02-21 18:28:45 +01:00
confirm_save - > connect ( " confirmed " , callable_mp ( this , & EditorFileDialog : : _save_confirm_pressed ) ) ;
2015-05-31 06:59:42 +02:00
2022-02-03 01:21:52 +01:00
dep_remove_dialog = memnew ( DependencyRemoveDialog ) ;
add_child ( dep_remove_dialog ) ;
global_remove_dialog = memnew ( ConfirmationDialog ) ;
global_remove_dialog - > set_text ( TTR ( " Remove the selected files? For safety only files and empty directories can be deleted from here. (Cannot be undone.) \n Depending on your filesystem configuration, the files will either be moved to the system trash or deleted permanently. " ) ) ;
global_remove_dialog - > connect ( " confirmed " , callable_mp ( this , & EditorFileDialog : : _delete_files_global ) ) ;
add_child ( global_remove_dialog ) ;
2017-12-02 01:37:32 +01:00
2015-05-31 06:59:42 +02:00
makedialog = memnew ( ConfirmationDialog ) ;
2016-05-04 03:25:37 +02:00
makedialog - > set_title ( TTR ( " Create Folder " ) ) ;
2015-05-31 06:59:42 +02:00
VBoxContainer * makevb = memnew ( VBoxContainer ) ;
makedialog - > add_child ( makevb ) ;
2017-01-10 05:49:55 +01:00
2015-05-31 06:59:42 +02:00
makedirname = memnew ( LineEdit ) ;
2022-04-19 12:27:18 +02:00
makedirname - > set_structured_text_bidi_override ( TextServer : : STRUCTURED_TEXT_FILE ) ;
2016-05-04 03:25:37 +02:00
makevb - > add_margin_child ( TTR ( " Name: " ) , makedirname ) ;
2015-05-31 06:59:42 +02:00
add_child ( makedialog ) ;
makedialog - > register_text_enter ( makedirname ) ;
2020-02-21 18:28:45 +01:00
makedialog - > connect ( " confirmed " , callable_mp ( this , & EditorFileDialog : : _make_dir_confirm ) ) ;
2022-02-03 01:21:52 +01:00
error_dialog = memnew ( AcceptDialog ) ;
add_child ( error_dialog ) ;
2015-05-31 06:59:42 +02:00
update_filters ( ) ;
update_dir ( ) ;
set_hide_on_ok ( false ) ;
vbox = vbc ;
2020-05-14 16:41:43 +02:00
if ( register_func ) {
2015-05-31 06:59:42 +02:00
register_func ( this ) ;
2020-05-14 16:41:43 +02:00
}
2024-03-21 09:42:38 +01:00
property_helper . setup_for_instance ( base_property_helper , this ) ;
2015-05-31 06:59:42 +02:00
}
EditorFileDialog : : ~ EditorFileDialog ( ) {
2020-05-14 16:41:43 +02:00
if ( unregister_func ) {
2015-05-31 06:59:42 +02:00
unregister_func ( this ) ;
2020-05-14 16:41:43 +02:00
}
2015-05-31 06:59:42 +02:00
}