Merge pull request #69698 from Daylily-Zeleen/daylily-zeleen/show_in_explorer
Implement and expose OS::shell_show_in_file_manager()
This commit is contained in:
commit
76d33d187f
|
@ -257,6 +257,15 @@ Error OS::shell_open(String p_uri) {
|
||||||
return ::OS::get_singleton()->shell_open(p_uri);
|
return ::OS::get_singleton()->shell_open(p_uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error OS::shell_show_in_file_manager(String p_path, bool p_open_folder) {
|
||||||
|
if (p_path.begins_with("res://")) {
|
||||||
|
WARN_PRINT("Attempting to explore file path with the \"res://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_show_in_file_manager()`.");
|
||||||
|
} else if (p_path.begins_with("user://")) {
|
||||||
|
WARN_PRINT("Attempting to explore file path with the \"user://\" protocol. Use `ProjectSettings.globalize_path()` to convert a Godot-specific path to a system path before opening it with `OS.shell_show_in_file_manager()`.");
|
||||||
|
}
|
||||||
|
return ::OS::get_singleton()->shell_show_in_file_manager(p_path, p_open_folder);
|
||||||
|
}
|
||||||
|
|
||||||
String OS::read_string_from_stdin() {
|
String OS::read_string_from_stdin() {
|
||||||
return ::OS::get_singleton()->get_stdin_string();
|
return ::OS::get_singleton()->get_stdin_string();
|
||||||
}
|
}
|
||||||
|
@ -553,6 +562,7 @@ void OS::_bind_methods() {
|
||||||
ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
|
ClassDB::bind_method(D_METHOD("create_instance", "arguments"), &OS::create_instance);
|
||||||
ClassDB::bind_method(D_METHOD("kill", "pid"), &OS::kill);
|
ClassDB::bind_method(D_METHOD("kill", "pid"), &OS::kill);
|
||||||
ClassDB::bind_method(D_METHOD("shell_open", "uri"), &OS::shell_open);
|
ClassDB::bind_method(D_METHOD("shell_open", "uri"), &OS::shell_open);
|
||||||
|
ClassDB::bind_method(D_METHOD("shell_show_in_file_manager", "file_or_dir_path", "open_folder"), &OS::shell_show_in_file_manager, DEFVAL(true));
|
||||||
ClassDB::bind_method(D_METHOD("is_process_running", "pid"), &OS::is_process_running);
|
ClassDB::bind_method(D_METHOD("is_process_running", "pid"), &OS::is_process_running);
|
||||||
ClassDB::bind_method(D_METHOD("get_process_id"), &OS::get_process_id);
|
ClassDB::bind_method(D_METHOD("get_process_id"), &OS::get_process_id);
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,7 @@ public:
|
||||||
int create_instance(const Vector<String> &p_arguments);
|
int create_instance(const Vector<String> &p_arguments);
|
||||||
Error kill(int p_pid);
|
Error kill(int p_pid);
|
||||||
Error shell_open(String p_uri);
|
Error shell_open(String p_uri);
|
||||||
|
Error shell_show_in_file_manager(String p_path, bool p_open_folder = true);
|
||||||
|
|
||||||
bool is_process_running(int p_pid) const;
|
bool is_process_running(int p_pid) const;
|
||||||
int get_process_id() const;
|
int get_process_id() const;
|
||||||
|
|
|
@ -281,6 +281,15 @@ Error OS::shell_open(String p_uri) {
|
||||||
return ERR_UNAVAILABLE;
|
return ERR_UNAVAILABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error OS::shell_show_in_file_manager(String p_path, bool p_open_folder) {
|
||||||
|
if (!p_path.begins_with("file://")) {
|
||||||
|
p_path = String("file://") + p_path;
|
||||||
|
}
|
||||||
|
if (!p_path.ends_with("/")) {
|
||||||
|
p_path = p_path.get_base_dir();
|
||||||
|
}
|
||||||
|
return shell_open(p_path);
|
||||||
|
}
|
||||||
// implement these with the canvas?
|
// implement these with the canvas?
|
||||||
|
|
||||||
uint64_t OS::get_static_memory_usage() const {
|
uint64_t OS::get_static_memory_usage() const {
|
||||||
|
|
|
@ -163,6 +163,7 @@ public:
|
||||||
virtual void vibrate_handheld(int p_duration_ms = 500) {}
|
virtual void vibrate_handheld(int p_duration_ms = 500) {}
|
||||||
|
|
||||||
virtual Error shell_open(String p_uri);
|
virtual Error shell_open(String p_uri);
|
||||||
|
virtual Error shell_show_in_file_manager(String p_path, bool p_open_folder = true);
|
||||||
virtual Error set_cwd(const String &p_cwd);
|
virtual Error set_cwd(const String &p_cwd);
|
||||||
|
|
||||||
virtual bool has_environment(const String &p_var) const = 0;
|
virtual bool has_environment(const String &p_var) const = 0;
|
||||||
|
|
|
@ -649,6 +649,17 @@
|
||||||
[b]Note:[/b] This method is implemented on Android, iOS, Web, Linux, macOS and Windows.
|
[b]Note:[/b] This method is implemented on Android, iOS, Web, Linux, macOS and Windows.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
|
<method name="shell_show_in_file_manager">
|
||||||
|
<return type="int" enum="Error" />
|
||||||
|
<param index="0" name="file_or_dir_path" type="String" />
|
||||||
|
<param index="1" name="open_folder" type="bool" default="true" />
|
||||||
|
<description>
|
||||||
|
Requests the OS to open file manager, then navigate to the given [param file_or_dir_path] and select the target file or folder.
|
||||||
|
If [param file_or_dir_path] is a valid directory path, and [param open_folder] is [code]true[/code], the method will open explorer and enter the target folder without selecting anything.
|
||||||
|
Use [method ProjectSettings.globalize_path] to convert a [code]res://[/code] or [code]user://[/code] path into a system path for use with this method.
|
||||||
|
[b]Note:[/b] Currently this method is only implemented on Windows. On other platforms, it will fallback to [method shell_open] with a directory path for [param file_or_dir_path].
|
||||||
|
</description>
|
||||||
|
</method>
|
||||||
<method name="unset_environment" qualifiers="const">
|
<method name="unset_environment" qualifiers="const">
|
||||||
<return type="void" />
|
<return type="void" />
|
||||||
<param index="0" name="variable" type="String" />
|
<param index="0" name="variable" type="String" />
|
||||||
|
|
|
@ -2995,10 +2995,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
|
||||||
case RUN_USER_DATA_FOLDER: {
|
case RUN_USER_DATA_FOLDER: {
|
||||||
// Ensure_user_data_dir() to prevent the edge case: "Open User Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved.
|
// Ensure_user_data_dir() to prevent the edge case: "Open User Data Folder" won't work after the project was renamed in ProjectSettingsEditor unless the project is saved.
|
||||||
OS::get_singleton()->ensure_user_data_dir();
|
OS::get_singleton()->ensure_user_data_dir();
|
||||||
OS::get_singleton()->shell_open(String("file://") + OS::get_singleton()->get_user_data_dir());
|
OS::get_singleton()->shell_show_in_file_manager(OS::get_singleton()->get_user_data_dir(), true);
|
||||||
} break;
|
} break;
|
||||||
case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: {
|
case FILE_EXPLORE_ANDROID_BUILD_TEMPLATES: {
|
||||||
OS::get_singleton()->shell_open("file://" + ProjectSettings::get_singleton()->get_resource_path().path_join("android"));
|
OS::get_singleton()->shell_show_in_file_manager(ProjectSettings::get_singleton()->get_resource_path().path_join("android"), true);
|
||||||
} break;
|
} break;
|
||||||
case FILE_QUIT:
|
case FILE_QUIT:
|
||||||
case RUN_PROJECT_MANAGER:
|
case RUN_PROJECT_MANAGER:
|
||||||
|
@ -3070,10 +3070,10 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
|
||||||
editor_settings_dialog->popup_edit_settings();
|
editor_settings_dialog->popup_edit_settings();
|
||||||
} break;
|
} break;
|
||||||
case SETTINGS_EDITOR_DATA_FOLDER: {
|
case SETTINGS_EDITOR_DATA_FOLDER: {
|
||||||
OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_data_dir());
|
OS::get_singleton()->shell_show_in_file_manager(EditorPaths::get_singleton()->get_data_dir(), true);
|
||||||
} break;
|
} break;
|
||||||
case SETTINGS_EDITOR_CONFIG_FOLDER: {
|
case SETTINGS_EDITOR_CONFIG_FOLDER: {
|
||||||
OS::get_singleton()->shell_open(String("file://") + EditorPaths::get_singleton()->get_config_dir());
|
OS::get_singleton()->shell_show_in_file_manager(EditorPaths::get_singleton()->get_config_dir(), true);
|
||||||
} break;
|
} break;
|
||||||
case SETTINGS_MANAGE_EXPORT_TEMPLATES: {
|
case SETTINGS_MANAGE_EXPORT_TEMPLATES: {
|
||||||
export_template_manager->popup_manager();
|
export_template_manager->popup_manager();
|
||||||
|
@ -3176,7 +3176,7 @@ void EditorNode::_screenshot(bool p_use_utc) {
|
||||||
NodePath path = String("user://") + name;
|
NodePath path = String("user://") + name;
|
||||||
_save_screenshot(path);
|
_save_screenshot(path);
|
||||||
if (EDITOR_GET("interface/editor/automatically_open_screenshots")) {
|
if (EDITOR_GET("interface/editor/automatically_open_screenshots")) {
|
||||||
OS::get_singleton()->shell_open(String("file://") + ProjectSettings::get_singleton()->globalize_path(path));
|
OS::get_singleton()->shell_show_in_file_manager(ProjectSettings::get_singleton()->globalize_path(path), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -620,7 +620,7 @@ void ExportTemplateManager::_installed_table_button_cbk(Object *p_item, int p_co
|
||||||
|
|
||||||
void ExportTemplateManager::_open_template_folder(const String &p_version) {
|
void ExportTemplateManager::_open_template_folder(const String &p_version) {
|
||||||
const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir();
|
const String &templates_dir = EditorPaths::get_singleton()->get_export_templates_dir();
|
||||||
OS::get_singleton()->shell_open("file://" + templates_dir.path_join(p_version));
|
OS::get_singleton()->shell_show_in_file_manager(templates_dir.path_join(p_version), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExportTemplateManager::popup_manager() {
|
void ExportTemplateManager::popup_manager() {
|
||||||
|
|
|
@ -1881,11 +1881,8 @@ void FileSystemDock::_file_option(int p_option, const Vector<String> &p_selected
|
||||||
fpath = p_selected[0];
|
fpath = p_selected[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fpath.ends_with("/")) {
|
|
||||||
fpath = fpath.get_base_dir();
|
|
||||||
}
|
|
||||||
String dir = ProjectSettings::get_singleton()->globalize_path(fpath);
|
String dir = ProjectSettings::get_singleton()->globalize_path(fpath);
|
||||||
OS::get_singleton()->shell_open(String("file://") + dir);
|
OS::get_singleton()->shell_show_in_file_manager(dir, true);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case FILE_OPEN_EXTERNAL: {
|
case FILE_OPEN_EXTERNAL: {
|
||||||
|
|
|
@ -713,11 +713,8 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
|
||||||
// Specific item was clicked. Open folders directly, or the folder containing a selected file.
|
// Specific item was clicked. Open folders directly, or the folder containing a selected file.
|
||||||
Dictionary item_meta = item_list->get_item_metadata(idx);
|
Dictionary item_meta = item_list->get_item_metadata(idx);
|
||||||
path = ProjectSettings::get_singleton()->globalize_path(item_meta["path"]);
|
path = ProjectSettings::get_singleton()->globalize_path(item_meta["path"]);
|
||||||
if (!item_meta["dir"]) {
|
|
||||||
path = path.get_base_dir();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
OS::get_singleton()->shell_open(String("file://") + path);
|
OS::get_singleton()->shell_show_in_file_manager(path, true);
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1829,7 +1829,7 @@ void ProjectList::_favorite_pressed(Node *p_hb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectList::_show_project(const String &p_path) {
|
void ProjectList::_show_project(const String &p_path) {
|
||||||
OS::get_singleton()->shell_open(String("file://") + p_path);
|
OS::get_singleton()->shell_show_in_file_manager(p_path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProjectList::_bind_methods() {
|
void ProjectList::_bind_methods() {
|
||||||
|
|
|
@ -1351,6 +1351,51 @@ Error OS_Windows::shell_open(String p_uri) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Error OS_Windows::shell_show_in_file_manager(String p_path, bool p_open_folder) {
|
||||||
|
p_path = p_path.trim_suffix("file://");
|
||||||
|
|
||||||
|
bool open_folder = false;
|
||||||
|
if (DirAccess::dir_exists_absolute(p_path) && p_open_folder) {
|
||||||
|
open_folder = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_path.begins_with("\"")) {
|
||||||
|
p_path = String("\"") + p_path;
|
||||||
|
}
|
||||||
|
if (p_path.ends_with("\"")) {
|
||||||
|
p_path = p_path + String("\"");
|
||||||
|
}
|
||||||
|
p_path = p_path.replace("/", "\\");
|
||||||
|
|
||||||
|
INT_PTR ret = OK;
|
||||||
|
if (open_folder) {
|
||||||
|
ret = (INT_PTR)ShellExecuteW(nullptr, nullptr, L"explorer.exe", LPCWSTR(p_path.utf16().get_data()), nullptr, SW_SHOWNORMAL);
|
||||||
|
} else {
|
||||||
|
ret = (INT_PTR)ShellExecuteW(nullptr, nullptr, L"explorer.exe", LPCWSTR((String("/select,") + p_path).utf16().get_data()), nullptr, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret > 32) {
|
||||||
|
return OK;
|
||||||
|
} else {
|
||||||
|
switch (ret) {
|
||||||
|
case ERROR_FILE_NOT_FOUND:
|
||||||
|
case SE_ERR_DLLNOTFOUND:
|
||||||
|
return ERR_FILE_NOT_FOUND;
|
||||||
|
case ERROR_PATH_NOT_FOUND:
|
||||||
|
return ERR_FILE_BAD_PATH;
|
||||||
|
case ERROR_BAD_FORMAT:
|
||||||
|
return ERR_FILE_CORRUPT;
|
||||||
|
case SE_ERR_ACCESSDENIED:
|
||||||
|
return ERR_UNAUTHORIZED;
|
||||||
|
case 0:
|
||||||
|
case SE_ERR_OOM:
|
||||||
|
return ERR_OUT_OF_MEMORY;
|
||||||
|
default:
|
||||||
|
return FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String OS_Windows::get_locale() const {
|
String OS_Windows::get_locale() const {
|
||||||
const _WinLocale *wl = &_win_locales[0];
|
const _WinLocale *wl = &_win_locales[0];
|
||||||
|
|
||||||
|
|
|
@ -214,6 +214,7 @@ public:
|
||||||
virtual String get_unique_id() const override;
|
virtual String get_unique_id() const override;
|
||||||
|
|
||||||
virtual Error shell_open(String p_uri) override;
|
virtual Error shell_open(String p_uri) override;
|
||||||
|
virtual Error shell_show_in_file_manager(String p_path, bool p_open_folder) override;
|
||||||
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue