Path: blob/master/editor/project_manager/project_list.h
21423 views
/**************************************************************************/1/* project_list.h */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#pragma once3132#include "core/io/config_file.h"33#include "core/os/time.h"34#include "scene/gui/box_container.h"35#include "scene/gui/scroll_container.h"3637class AcceptDialog;38class Button;39class Label;40class PopupMenu;41class ProjectList;42class TextureButton;43class TextureRect;4445class ProjectListItemControl : public HBoxContainer {46GDCLASS(ProjectListItemControl, HBoxContainer)4748VBoxContainer *main_vbox = nullptr;49TextureButton *favorite_button = nullptr;50Button *explore_button = nullptr;5152TextureRect *project_icon = nullptr;53Label *project_title = nullptr;54Label *project_path = nullptr;55Label *last_edited_info = nullptr;56Label *project_version = nullptr;57TextureRect *project_unsupported_features = nullptr;58HBoxContainer *tag_container = nullptr;59Button *touch_menu_button = nullptr;6061Color favorite_focus_color;6263bool project_is_missing = false;64bool icon_needs_reload = true;65bool is_selected = false;66bool is_focus_hidden = false;67bool is_hovering = false;68bool is_favorite = false;6970void _update_favorite_button_focus_color();71void _favorite_button_pressed();72void _explore_button_pressed();73void _request_menu();7475ProjectList *get_list() const;7677void _accessibility_action_open(const Variant &p_data);78void _accessibility_action_scroll_into_view(const Variant &p_data);79void _accessibility_action_focus(const Variant &p_data);80void _accessibility_action_blur(const Variant &p_data);8182protected:83void _notification(int p_what);84static void _bind_methods();8586public:87void set_project_title(const String &p_title);88void set_project_path(const String &p_path);89void set_tags(const PackedStringArray &p_tags, ProjectList *p_parent_list);90void set_project_icon(const Ref<Texture2D> &p_icon);91void set_last_edited_info(const String &p_info);92void set_project_version(const String &p_version);93void set_unsupported_features(PackedStringArray p_features);9495bool should_load_project_icon() const;96void set_selected(bool p_selected, bool p_hide_focus = false);9798void set_is_favorite(bool p_favorite);99void set_is_missing(bool p_missing);100void set_is_grayed(bool p_grayed);101102ProjectListItemControl();103};104105class ProjectList : public ScrollContainer {106GDCLASS(ProjectList, ScrollContainer)107108friend class ProjectManager;109friend class ProjectListItemControl;110111public:112enum FilterOption {113EDIT_DATE,114NAME,115PATH,116TAGS,117};118119enum MenuOption {120MENU_EDIT,121MENU_EDIT_VERBOSE,122MENU_EDIT_RECOVERY,123MENU_RUN,124MENU_SHOW_IN_FILE_MANAGER,125MENU_COPY_PATH,126MENU_RENAME,127MENU_MANAGE_TAGS,128MENU_DUPLICATE,129MENU_REMOVE,130};131132// Can often be passed by copy.133struct Item {134String project_name;135String description;136String project_version;137PackedStringArray tags;138String tag_sort_string;139String path;140String icon;141String main_scene;142PackedStringArray unsupported_features;143uint64_t last_edited = 0;144bool favorite = false;145bool grayed = false;146bool missing = false;147bool recovery_mode = false;148int version = 0;149150ProjectListItemControl *control = nullptr;151152Item() {}153154Item(const String &p_name,155const String &p_description,156const String &p_project_version,157const PackedStringArray &p_tags,158const String &p_path,159const String &p_icon,160const String &p_main_scene,161const PackedStringArray &p_unsupported_features,162uint64_t p_last_edited,163bool p_favorite,164bool p_grayed,165bool p_missing,166bool p_recovery_mode,167int p_version) {168project_name = p_name;169description = p_description;170project_version = p_project_version;171tags = p_tags;172path = p_path;173icon = p_icon;174main_scene = p_main_scene;175unsupported_features = p_unsupported_features;176last_edited = p_last_edited;177favorite = p_favorite;178grayed = p_grayed;179missing = p_missing;180recovery_mode = p_recovery_mode;181version = p_version;182183control = nullptr;184185PackedStringArray sorted_tags = tags;186sorted_tags.sort();187tag_sort_string = String().join(sorted_tags);188}189190_FORCE_INLINE_ bool operator==(const Item &l) const {191return path == l.path;192}193194String get_last_edited_string() const {195if (missing) {196return TTR("Missing Date");197}198199OS::TimeZoneInfo tz = OS::get_singleton()->get_time_zone_info();200return Time::get_singleton()->get_datetime_string_from_unix_time(last_edited + tz.bias * 60, true);201}202};203204private:205String _config_path;206ConfigFile _config;207208Vector<Item> _projects;209210int _icon_load_index = 0;211bool project_opening_initiated = false;212213String _search_term;214FilterOption _order_option = FilterOption::EDIT_DATE;215HashSet<String> _selected_project_paths;216String _last_clicked; // Project key217218VBoxContainer *project_list_vbox = nullptr;219PopupMenu *project_context_menu = nullptr;220221// Projects scan.222223struct ScanData {224Thread *thread = nullptr;225PackedStringArray paths_to_scan;226List<String> found_projects;227SafeFlag scan_in_progress;228};229ScanData *scan_data = nullptr;230AcceptDialog *scan_progress = nullptr;231232static void _scan_thread(void *p_scan_data);233void _scan_finished();234235// Initialization & loading.236237void _migrate_config();238239static Item load_project_data(const String &p_property_key, bool p_favorite);240void _update_icons_async();241void _load_project_icon(int p_index);242243// Project list updates.244245static void _scan_folder_recursive(const String &p_path, List<String> *r_projects, const SafeFlag &p_scan_active);246247// Project list items.248249void _create_project_item_control(int p_index);250void _toggle_project(int p_index);251void _remove_project(int p_index, bool p_update_settings);252253void _list_item_input(const Ref<InputEvent> &p_ev, Control *p_hb);254void _on_favorite_pressed(Node *p_hb);255void _on_explore_pressed(const String &p_path);256257void _open_menu(const Vector2 &p_at, Control *p_hb);258void _menu_option(int p_option);259void _update_menu_icons();260261// Project list selection.262263void _clear_project_selection();264void _select_project_nocheck(int p_index, bool p_hide_focus = false);265void _deselect_project_nocheck(int p_index);266void _select_project_range(int p_begin, int p_end);267268// Global menu integration.269270void _global_menu_new_window(const Variant &p_tag);271void _global_menu_open_project(const Variant &p_tag);272273protected:274void _notification(int p_what);275static void _bind_methods();276277public:278static inline const char *SIGNAL_LIST_CHANGED = "list_changed";279static inline const char *SIGNAL_SELECTION_CHANGED = "selection_changed";280static inline const char *SIGNAL_PROJECT_ASK_OPEN = "project_ask_open";281static inline const char *SIGNAL_MENU_OPTION_SELECTED = "menu_option_selected";282283static bool project_feature_looks_like_version(const String &p_feature);284285// Initialization & loading.286287void save_config();288289// Project list updates.290291void load_project_list();292void update_project_list();293void sort_projects();294int get_project_count() const;295296void find_projects(const String &p_path);297void find_projects_multiple(const PackedStringArray &p_paths);298299// Project list items.300301void add_project(const String &dir_path, bool favorite);302void set_project_version(const String &p_project_path, int version);303int refresh_project(const String &dir_path);304void ensure_project_visible(int p_index);305int get_index(const ProjectListItemControl *p_control) const;306307// Project list selection.308309void select_project(int p_index, bool p_hide_focus = false);310void deselect_project(int p_index);311void select_first_visible_project();312void select_all_visible_projects();313void deselect_all_visible_projects();314Vector<Item> get_selected_projects() const;315const HashSet<String> &get_selected_project_keys() const;316int get_single_selected_index() const;317void erase_selected_projects(bool p_delete_project_contents);318319// Missing projects.320321bool is_any_project_missing() const;322void erase_missing_projects();323324// Project list sorting and filtering.325326void set_search_term(String p_search_term);327void add_search_tag(const String &p_tag);328void set_order_option(int p_option, bool p_save);329330// Global menu integration.331332void update_dock_menu();333334ProjectList();335};336337338