Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[macOS] Handle bundles as files in the embedded file dialogs. #98812

Merged
merged 1 commit into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/io/dir_access.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,8 @@ void DirAccess::_bind_methods() {
ClassDB::bind_method(D_METHOD("read_link", "path"), &DirAccess::read_link);
ClassDB::bind_method(D_METHOD("create_link", "source", "target"), &DirAccess::create_link);

ClassDB::bind_method(D_METHOD("is_bundle", "path"), &DirAccess::is_bundle);

ClassDB::bind_method(D_METHOD("set_include_navigational", "enable"), &DirAccess::set_include_navigational);
ClassDB::bind_method(D_METHOD("get_include_navigational"), &DirAccess::get_include_navigational);
ClassDB::bind_method(D_METHOD("set_include_hidden", "enable"), &DirAccess::set_include_hidden);
Expand Down
1 change: 1 addition & 0 deletions core/io/dir_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ class DirAccess : public RefCounted {
bool get_include_hidden() const;

virtual bool is_case_sensitive(const String &p_path) const;
virtual bool is_bundle(const String &p_file) const { return false; }

DirAccess() {}
virtual ~DirAccess() {}
Expand Down
8 changes: 8 additions & 0 deletions doc/classes/DirAccess.xml
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,14 @@
Returns the available space on the current directory's disk, in bytes. Returns [code]0[/code] if the platform-specific method to query the available space fails.
</description>
</method>
<method name="is_bundle" qualifiers="const">
<return type="bool" />
<param index="0" name="path" type="String" />
<description>
Returns [code]true[/code] if the directory is a macOS bundle.
[b]Note:[/b] This method is implemented on macOS.
</description>
</method>
<method name="is_case_sensitive" qualifiers="const">
<return type="bool" />
<param index="0" name="path" type="String" />
Expand Down
86 changes: 62 additions & 24 deletions editor/gui/editor_file_dialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ void EditorFileDialog::_update_theme_item_cache() {
theme_cache.favorites_up = get_editor_theme_icon(SNAME("MoveUp"));
theme_cache.favorites_down = get_editor_theme_icon(SNAME("MoveDown"));
theme_cache.create_folder = get_editor_theme_icon(SNAME("FolderCreate"));
theme_cache.open_folder = get_editor_theme_icon(SNAME("FolderBrowse"));

theme_cache.filter_box = get_editor_theme_icon(SNAME("Search"));
theme_cache.file_sort_button = get_editor_theme_icon(SNAME("Sort"));
Expand Down Expand Up @@ -535,7 +536,7 @@ void EditorFileDialog::_action_pressed() {
String file_text = file->get_text();
String f = file_text.is_absolute_path() ? file_text : dir_access->get_current_dir().path_join(file_text);

if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && (dir_access->file_exists(f) || dir_access->is_bundle(f))) {
_save_to_recent();
hide();
emit_signal(SNAME("file_selected"), f);
Expand Down Expand Up @@ -787,6 +788,12 @@ void EditorFileDialog::_item_list_item_rmb_clicked(int p_item, const Vector2 &p_
item_menu->add_icon_item(theme_cache.filesystem, item_text, ITEM_MENU_SHOW_IN_EXPLORER);
}
#endif
if (single_item_selected) {
Dictionary item_meta = item_list->get_item_metadata(p_item);
if (item_meta["bundle"]) {
item_menu->add_icon_item(theme_cache.open_folder, TTR("Show Package Contents"), ITEM_MENU_SHOW_BUNDLE_CONTENT);
}
}

if (item_menu->get_item_count() > 0) {
item_menu->set_position(item_list->get_screen_position() + p_pos);
Expand Down Expand Up @@ -849,7 +856,7 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
case ITEM_MENU_SHOW_IN_EXPLORER: {
String path;
int idx = item_list->get_current();
if (idx == -1 || item_list->get_selected_items().size() == 0) {
if (idx == -1 || !item_list->is_anything_selected()) {
// Folder background was clicked. Open this folder.
path = ProjectSettings::get_singleton()->globalize_path(dir_access->get_current_dir());
} else {
Expand All @@ -859,6 +866,20 @@ void EditorFileDialog::_item_menu_id_pressed(int p_option) {
}
OS::get_singleton()->shell_show_in_file_manager(path, true);
} break;

case ITEM_MENU_SHOW_BUNDLE_CONTENT: {
String path;
int idx = item_list->get_current();
if (idx == -1 || !item_list->is_anything_selected()) {
return;
}
Dictionary item_meta = item_list->get_item_metadata(idx);
dir_access->change_dir(item_meta["path"]);
callable_mp(this, &EditorFileDialog::update_file_list).call_deferred();
callable_mp(this, &EditorFileDialog::update_dir).call_deferred();

_push_history();
} break;
}
}

Expand Down Expand Up @@ -1026,28 +1047,6 @@ void EditorFileDialog::update_file_list() {
}
sort_file_info_list(file_infos, file_sort);

while (!dirs.is_empty()) {
const String &dir_name = dirs.front()->get();

item_list->add_item(dir_name);

if (display_mode == DISPLAY_THUMBNAILS) {
item_list->set_item_icon(-1, folder_thumbnail);
} else {
item_list->set_item_icon(-1, theme_cache.folder);
}

Dictionary d;
d["name"] = dir_name;
d["path"] = cdir.path_join(dir_name);
d["dir"] = true;

item_list->set_item_metadata(-1, d);
item_list->set_item_icon_modulate(-1, get_dir_icon_color(String(d["path"])));

dirs.pop_front();
}

List<String> patterns;
// build filter
if (filter->get_selected() == filter->get_item_count() - 1) {
Expand All @@ -1074,6 +1073,44 @@ void EditorFileDialog::update_file_list() {
}
}

while (!dirs.is_empty()) {
const String &dir_name = dirs.front()->get();

bool bundle = dir_access->is_bundle(dir_name);
bool found = true;
if (bundle) {
bool match = patterns.is_empty();
for (const String &E : patterns) {
if (dir_name.matchn(E)) {
match = true;
break;
}
}
found = match;
}

if (found) {
item_list->add_item(dir_name);

if (display_mode == DISPLAY_THUMBNAILS) {
item_list->set_item_icon(-1, folder_thumbnail);
} else {
item_list->set_item_icon(-1, theme_cache.folder);
}

Dictionary d;
d["name"] = dir_name;
d["path"] = cdir.path_join(dir_name);
d["dir"] = !bundle;
d["bundle"] = bundle;

item_list->set_item_metadata(-1, d);
item_list->set_item_icon_modulate(-1, get_dir_icon_color(String(d["path"])));
}

dirs.pop_front();
}

while (!file_infos.is_empty()) {
bool match = patterns.is_empty();

Expand Down Expand Up @@ -1109,6 +1146,7 @@ void EditorFileDialog::update_file_list() {
Dictionary d;
d["name"] = file_info.name;
d["dir"] = false;
d["bundle"] = false;
d["path"] = file_info.path;
item_list->set_item_metadata(-1, d);

Expand Down
4 changes: 3 additions & 1 deletion editor/gui/editor_file_dialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ class EditorFileDialog : public ConfirmationDialog {
ITEM_MENU_DELETE,
ITEM_MENU_REFRESH,
ITEM_MENU_NEW_FOLDER,
ITEM_MENU_SHOW_IN_EXPLORER
ITEM_MENU_SHOW_IN_EXPLORER,
ITEM_MENU_SHOW_BUNDLE_CONTENT,
};

ConfirmationDialog *makedialog = nullptr;
Expand Down Expand Up @@ -167,6 +168,7 @@ class EditorFileDialog : public ConfirmationDialog {
Ref<Texture2D> parent_folder;
Ref<Texture2D> forward_folder;
Ref<Texture2D> back_folder;
Ref<Texture2D> open_folder;
Ref<Texture2D> reload;
Ref<Texture2D> toggle_hidden;
Ref<Texture2D> toggle_filename_filter;
Expand Down
2 changes: 2 additions & 0 deletions platform/macos/dir_access_macos.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class DirAccessMacOS : public DirAccessUnix {

virtual bool is_hidden(const String &p_name) override;
virtual bool is_case_sensitive(const String &p_path) const override;

virtual bool is_bundle(const String &p_file) const override;
};

#endif // UNIX ENABLED
Expand Down
10 changes: 10 additions & 0 deletions platform/macos/dir_access_macos.mm
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,14 @@
return [cs boolValue];
}

bool DirAccessMacOS::is_bundle(const String &p_file) const {
String f = p_file;
if (!f.is_absolute_path()) {
f = get_current_dir().path_join(f);
}
f = fix_path(f);

return [[NSWorkspace sharedWorkspace] isFilePackageAtPath:[NSString stringWithUTF8String:f.utf8().get_data()]];
}

#endif // UNIX_ENABLED
Loading
Loading