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

Backport filesystem dock sorting to 3.x #50565

Merged
merged 1 commit into from
Jul 20, 2021
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
5 changes: 5 additions & 0 deletions editor/editor_file_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ bool EditorFileSystemDirectory::get_file_import_is_valid(int p_idx) const {
return files[p_idx]->import_valid;
}

uint64_t EditorFileSystemDirectory::get_file_modified_time(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, files.size(), 0);
return files[p_idx]->modified_time;
}

String EditorFileSystemDirectory::get_file_script_class_name(int p_idx) const {
return files[p_idx]->script_class_name;
}
Expand Down
1 change: 1 addition & 0 deletions editor/editor_file_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class EditorFileSystemDirectory : public Object {
StringName get_file_type(int p_idx) const;
Vector<String> get_file_deps(int p_idx) const;
bool get_file_import_is_valid(int p_idx) const;
uint64_t get_file_modified_time(int p_idx) const;
String get_file_script_class_name(int p_idx) const; //used for scripts
String get_file_script_class_extends(int p_idx) const; //used for scripts
String get_file_script_class_icon_path(int p_idx) const; //used for scripts
Expand Down
168 changes: 144 additions & 24 deletions editor/filesystem_dock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,12 @@
#include "scene/main/viewport.h"
#include "scene/resources/packed_scene.h"

Ref<Texture> FileSystemDock::_get_tree_item_icon(EditorFileSystemDirectory *p_dir, int p_idx) {
Ref<Texture> FileSystemDock::_get_tree_item_icon(bool p_is_valid, String p_file_type) {
Ref<Texture> file_icon;
if (!p_dir->get_file_import_is_valid(p_idx)) {
if (!p_is_valid) {
file_icon = get_icon("ImportFail", "EditorIcons");
} else {
String file_type = p_dir->get_file_type(p_idx);
file_icon = (has_icon(file_type, "EditorIcons")) ? get_icon(file_type, "EditorIcons") : get_icon("File", "EditorIcons");
file_icon = (has_icon(p_file_type, "EditorIcons")) ? get_icon(p_file_type, "EditorIcons") : get_icon("File", "EditorIcons");
}
return file_icon;
}
Expand Down Expand Up @@ -90,22 +89,28 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
}

// Create items for all subdirectories.
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
bool reversed = file_sort == FILE_SORT_NAME_REVERSE;
for (int i = reversed ? p_dir->get_subdir_count() - 1 : 0;
reversed ? i >= 0 : i < p_dir->get_subdir_count();
reversed ? i-- : i++) {
parent_should_expand = (_create_tree(subdirectory_item, p_dir->get_subdir(i), uncollapsed_paths, p_select_in_favorites, p_unfold_path) || parent_should_expand);
}

// Create all items for the files in the subdirectory.
if (display_mode == DISPLAY_MODE_TREE_ONLY) {
String main_scene = ProjectSettings::get_singleton()->get("application/run/main_scene");

// Build the list of the files to display.
List<FileInfo> file_list;
for (int i = 0; i < p_dir->get_file_count(); i++) {
String file_type = p_dir->get_file_type(i);

if (_is_file_type_disabled_by_feature_profile(file_type)) {
// If type is disabled, file won't be displayed.
continue;
}
String file_name = p_dir->get_file(i);

String file_name = p_dir->get_file(i);
if (searched_string.length() > 0) {
if (file_name.to_lower().find(searched_string) < 0) {
// The searched string is not in the file name, we skip it.
Expand All @@ -116,10 +121,26 @@ bool FileSystemDock::_create_tree(TreeItem *p_parent, EditorFileSystemDirectory
}
}

FileInfo fi;
fi.name = p_dir->get_file(i);
fi.type = p_dir->get_file_type(i);
fi.import_broken = !p_dir->get_file_import_is_valid(i);
fi.modified_time = p_dir->get_file_modified_time(i);

file_list.push_back(fi);
}

// Sort the file list if needed.
_sort_file_info_list(file_list);

// Build the tree.
for (List<FileInfo>::Element *E = file_list.front(); E; E = E->next()) {
FileInfo fi = E->get();

TreeItem *file_item = tree->create_item(subdirectory_item);
file_item->set_text(0, file_name);
file_item->set_icon(0, _get_tree_item_icon(p_dir, i));
String file_metadata = lpath.plus_file(file_name);
file_item->set_text(0, fi.name);
file_item->set_icon(0, _get_tree_item_icon(!fi.import_broken, fi.type));
String file_metadata = lpath.plus_file(fi.name);
file_item->set_metadata(0, file_metadata);
if (!p_select_in_favorites && path == file_metadata) {
file_item->select(0);
Expand Down Expand Up @@ -223,7 +244,7 @@ void FileSystemDock::_update_tree(const Vector<String> &p_uncollapsed_paths, boo
int index;
EditorFileSystemDirectory *dir = EditorFileSystem::get_singleton()->find_file(fave, &index);
if (dir) {
icon = _get_tree_item_icon(dir, index);
icon = _get_tree_item_icon(dir->get_file_import_is_valid(index), dir->get_file_type(index));
} else {
icon = get_icon("File", "EditorIcons");
}
Expand Down Expand Up @@ -275,11 +296,7 @@ void FileSystemDock::_update_display_mode(bool p_force) {
case DISPLAY_MODE_TREE_ONLY:
tree->show();
tree->set_v_size_flags(SIZE_EXPAND_FILL);
if (display_mode == DISPLAY_MODE_TREE_ONLY) {
tree_search_box->show();
} else {
tree_search_box->hide();
}
toolbar2_hbc->show();

_update_tree(_compute_uncollapsed_paths());
file_list_vb->hide();
Expand All @@ -289,7 +306,7 @@ void FileSystemDock::_update_display_mode(bool p_force) {
tree->show();
tree->set_v_size_flags(SIZE_EXPAND_FILL);
tree->ensure_cursor_is_visible();
tree_search_box->hide();
toolbar2_hbc->hide();
_update_tree(_compute_uncollapsed_paths());

file_list_vb->show();
Expand Down Expand Up @@ -322,8 +339,11 @@ void FileSystemDock::_notification(int p_what) {
button_hist_prev->connect("pressed", this, "_bw_history");
tree_search_box->set_right_icon(get_icon("Search", ei));
tree_search_box->set_clear_button_enabled(true);
tree_button_sort->set_icon(get_icon("Sort", ei));

file_list_search_box->set_right_icon(get_icon("Search", ei));
file_list_search_box->set_clear_button_enabled(true);
file_list_button_sort->set_icon(get_icon("Sort", ei));

button_hist_next->set_icon(get_icon("Forward", ei));
button_hist_prev->set_icon(get_icon("Back", ei));
Expand Down Expand Up @@ -389,8 +409,11 @@ void FileSystemDock::_notification(int p_what) {

tree_search_box->set_right_icon(get_icon("Search", ei));
tree_search_box->set_clear_button_enabled(true);
tree_button_sort->set_icon(get_icon("Sort", ei));

file_list_search_box->set_right_icon(get_icon("Search", ei));
file_list_search_box->set_clear_button_enabled(true);
file_list_button_sort->set_icon(get_icon("Sort", ei));

// Update always show folders.
bool new_always_show_folders = bool(EditorSettings::get_singleton()->get("docks/filesystem/always_show_folders"));
Expand Down Expand Up @@ -605,6 +628,54 @@ void FileSystemDock::_search(EditorFileSystemDirectory *p_path, List<FileInfo> *
}
}

struct FileSystemDock::FileInfoTypeComparator {
bool operator()(const FileInfo &p_a, const FileInfo &p_b) const {
// Uses the extension, then the icon name to distinguish file types.
String icon_path_a = "";
String icon_path_b = "";
Ref<Texture> icon_a = EditorNode::get_singleton()->get_class_icon(p_a.type);
if (icon_a.is_valid()) {
icon_path_a = icon_a->get_name();
}
Ref<Texture> icon_b = EditorNode::get_singleton()->get_class_icon(p_b.type);
if (icon_b.is_valid()) {
icon_path_b = icon_b->get_name();
}
return NaturalNoCaseComparator()(p_a.name.get_extension() + icon_path_a + p_a.name.get_basename(), p_b.name.get_extension() + icon_path_b + p_b.name.get_basename());
}
};

struct FileSystemDock::FileInfoModifiedTimeComparator {
bool operator()(const FileInfo &p_a, const FileInfo &p_b) const {
return p_a.modified_time > p_b.modified_time;
}
};

void FileSystemDock::_sort_file_info_list(List<FileSystemDock::FileInfo> &r_file_list) {
// Sort the file list if needed.
switch (file_sort) {
case FILE_SORT_TYPE:
r_file_list.sort_custom<FileInfoTypeComparator>();
break;
case FILE_SORT_TYPE_REVERSE:
r_file_list.sort_custom<FileInfoTypeComparator>();
r_file_list.invert();
break;
case FILE_SORT_MODIFIED_TIME:
r_file_list.sort_custom<FileInfoModifiedTimeComparator>();
break;
case FILE_SORT_MODIFIED_TIME_REVERSE:
r_file_list.sort_custom<FileInfoModifiedTimeComparator>();
r_file_list.invert();
break;
case FILE_SORT_NAME_REVERSE:
r_file_list.invert();
break;
default: // FILE_SORT_NAME
break;
}
}

void FileSystemDock::_update_file_list(bool p_keep_selection) {
// Register the previously selected items.
Set<String> cselection;
Expand Down Expand Up @@ -662,7 +733,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
const Color folder_color = get_color("folder_icon_modulate", "FileDialog");

// Build the FileInfo list.
List<FileInfo> filelist;
List<FileInfo> file_list;
if (path == "Favorites") {
// Display the favorites.
Vector<String> favorites = EditorSettings::get_singleton()->get_favorites();
Expand Down Expand Up @@ -694,13 +765,15 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
if (efd) {
fi.type = efd->get_file_type(index);
fi.import_broken = !efd->get_file_import_is_valid(index);
fi.modified_time = efd->get_file_modified_time(index);
} else {
fi.type = "";
fi.import_broken = true;
fi.modified_time = 0;
}

if (searched_string.length() == 0 || fi.name.to_lower().find(searched_string) >= 0) {
filelist.push_back(fi);
file_list.push_back(fi);
}
}
}
Expand All @@ -722,7 +795,7 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
if (searched_string.length() > 0) {
// Display the search results.
// Limit the number of results displayed to avoid an infinite loop.
_search(EditorFileSystem::get_singleton()->get_filesystem(), &filelist, 10000);
_search(EditorFileSystem::get_singleton()->get_filesystem(), &file_list, 10000);
} else {
if (display_mode == DISPLAY_MODE_TREE_ONLY || always_show_folders) {
// Display folders in the list.
Expand All @@ -739,7 +812,10 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
files->set_item_icon_modulate(files->get_item_count() - 1, folder_color);
}

for (int i = 0; i < efd->get_subdir_count(); i++) {
bool reversed = file_sort == FILE_SORT_NAME_REVERSE;
for (int i = reversed ? efd->get_subdir_count() - 1 : 0;
reversed ? i >= 0 : i < efd->get_subdir_count();
reversed ? i-- : i++) {
String dname = efd->get_subdir(i)->get_name();

files->add_item(dname, folder_icon, true);
Expand All @@ -759,17 +835,20 @@ void FileSystemDock::_update_file_list(bool p_keep_selection) {
fi.path = directory.plus_file(fi.name);
fi.type = efd->get_file_type(i);
fi.import_broken = !efd->get_file_import_is_valid(i);
fi.modified_time = efd->get_file_modified_time(i);

filelist.push_back(fi);
file_list.push_back(fi);
}
}
filelist.sort();
file_list.sort();
}

_sort_file_info_list(file_list);

// Fills the ItemList control node from the FileInfos.
String main_scene = ProjectSettings::get_singleton()->get("application/run/main_scene");
String oi = "Object";
for (List<FileInfo>::Element *E = filelist.front(); E; E = E->next()) {
for (List<FileInfo>::Element *E = file_list.front(); E; E = E->next()) {
FileInfo *finfo = &(E->get());
String fname = finfo->name;
String fpath = finfo->path;
Expand Down Expand Up @@ -2585,13 +2664,48 @@ void FileSystemDock::_feature_profile_changed() {
_update_display_mode(true);
}

void FileSystemDock::set_file_sort(FileSortOption p_file_sort) {
for (int i = 0; i != FILE_SORT_MAX; i++) {
tree_button_sort->get_popup()->set_item_checked(i, (i == (int)p_file_sort));
file_list_button_sort->get_popup()->set_item_checked(i, (i == (int)p_file_sort));
}
file_sort = p_file_sort;

// Update everything needed.
_update_tree(_compute_uncollapsed_paths());
_update_file_list(true);
}

void FileSystemDock::_file_sort_popup(int p_id) {
set_file_sort((FileSortOption)p_id);
}

MenuButton *FileSystemDock::_create_file_menu_button() {
MenuButton *button = memnew(MenuButton);
button->set_flat(true);
button->set_tooltip(TTR("Sort files"));

PopupMenu *p = button->get_popup();
p->connect("id_pressed", this, "_file_sort_popup");
p->add_radio_check_item(TTR("Sort by Name (Ascending)"), FILE_SORT_NAME);
p->add_radio_check_item(TTR("Sort by Name (Descending)"), FILE_SORT_NAME_REVERSE);
p->add_radio_check_item(TTR("Sort by Type (Ascending)"), FILE_SORT_TYPE);
p->add_radio_check_item(TTR("Sort by Type (Descending)"), FILE_SORT_TYPE_REVERSE);
p->add_radio_check_item(TTR("Sort by Last Modified"), FILE_SORT_MODIFIED_TIME);
p->add_radio_check_item(TTR("Sort by First Modified"), FILE_SORT_MODIFIED_TIME_REVERSE);
p->set_item_checked(file_sort, true);
return button;
}

void FileSystemDock::_bind_methods() {
ClassDB::bind_method(D_METHOD("_file_list_gui_input"), &FileSystemDock::_file_list_gui_input);
ClassDB::bind_method(D_METHOD("_tree_gui_input"), &FileSystemDock::_tree_gui_input);

ClassDB::bind_method(D_METHOD("_update_tree"), &FileSystemDock::_update_tree);
ClassDB::bind_method(D_METHOD("_rescan"), &FileSystemDock::_rescan);

ClassDB::bind_method(D_METHOD("_file_sort_popup"), &FileSystemDock::_file_sort_popup);

ClassDB::bind_method(D_METHOD("_toggle_split_mode"), &FileSystemDock::_toggle_split_mode);

ClassDB::bind_method(D_METHOD("_tree_rmb_option", "option"), &FileSystemDock::_tree_rmb_option);
Expand Down Expand Up @@ -2701,7 +2815,7 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
button_toggle_display_mode->set_tooltip(TTR("Toggle Split Mode"));
toolbar_hbc->add_child(button_toggle_display_mode);

HBoxContainer *toolbar2_hbc = memnew(HBoxContainer);
toolbar2_hbc = memnew(HBoxContainer);
toolbar2_hbc->add_constant_override("separation", 0);
top_vbc->add_child(toolbar2_hbc);

Expand All @@ -2711,6 +2825,9 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
tree_search_box->connect("text_changed", this, "_search_changed", varray(tree_search_box));
toolbar2_hbc->add_child(tree_search_box);

tree_button_sort = _create_file_menu_button();
toolbar2_hbc->add_child(tree_button_sort);

file_list_popup = memnew(PopupMenu);
file_list_popup->set_hide_on_window_lose_focus(true);
add_child(file_list_popup);
Expand Down Expand Up @@ -2752,6 +2869,9 @@ FileSystemDock::FileSystemDock(EditorNode *p_editor) {
file_list_search_box->connect("text_changed", this, "_search_changed", varray(file_list_search_box));
path_hb->add_child(file_list_search_box);

file_list_button_sort = _create_file_menu_button();
path_hb->add_child(file_list_button_sort);

button_file_list_display_mode = memnew(ToolButton);
path_hb->add_child(button_file_list_display_mode);

Expand Down
Loading