Skip to content

Commit

Permalink
Improve Remove Missing of project manager
Browse files Browse the repository at this point in the history
  • Loading branch information
timothyqiu committed May 19, 2024
1 parent daa81bb commit 23e5cfb
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 32 deletions.
35 changes: 14 additions & 21 deletions editor/project_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,8 @@
#include "project_manager.h"

#include "core/config/project_settings.h"
#include "core/io/config_file.h"
#include "core/io/dir_access.h"
#include "core/io/file_access.h"
#include "core/io/resource_saver.h"
#include "core/io/stream_peer_tls.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/os/time.h"
Expand All @@ -51,20 +48,17 @@
#include "editor/project_manager/project_list.h"
#include "editor/project_manager/project_tag.h"
#include "editor/project_manager/quick_settings_dialog.h"
#include "editor/themes/editor_icons.h"
#include "editor/project_manager/remove_missing_dialog.h"
#include "editor/themes/editor_scale.h"
#include "editor/themes/editor_theme_manager.h"
#include "main/main.h"
#include "scene/gui/check_box.h"
#include "scene/gui/color_rect.h"
#include "scene/gui/flow_container.h"
#include "scene/gui/line_edit.h"
#include "scene/gui/margin_container.h"
#include "scene/gui/option_button.h"
#include "scene/gui/panel_container.h"
#include "scene/gui/rich_text_label.h"
#include "scene/gui/separator.h"
#include "scene/gui/texture_rect.h"
#include "scene/main/window.h"
#include "scene/theme/theme_db.h"
#include "servers/display_server.h"
Expand Down Expand Up @@ -661,8 +655,7 @@ void ProjectManager::_erase_project() {
}

void ProjectManager::_erase_missing_projects() {
erase_missing_ask->set_text(TTR("Remove all missing projects from the list?\nThe project folders' contents won't be modified."));
erase_missing_ask->popup_centered();
remove_missing_dialog->show_dialog(project_list->get_missing_project_paths());
}

void ProjectManager::_erase_project_confirm() {
Expand All @@ -671,8 +664,8 @@ void ProjectManager::_erase_project_confirm() {
_update_list_placeholder();
}

void ProjectManager::_erase_missing_projects_confirm() {
project_list->erase_missing_projects();
void ProjectManager::_erase_missing_projects_confirm(const Vector<String> &p_paths) {
project_list->erase_missing_projects(p_paths);
_update_project_buttons();
_update_list_placeholder();
}
Expand All @@ -695,7 +688,7 @@ void ProjectManager::_update_project_buttons() {
manage_tags_btn->set_disabled(empty_selection || is_missing_project_selected || selected_projects.size() > 1);
run_btn->set_disabled(empty_selection || is_missing_project_selected);

erase_missing_btn->set_disabled(!project_list->is_any_project_missing());
erase_missing_btn->set_visible(project_list->is_any_project_missing());
}

void ProjectManager::_on_projects_updated() {
Expand Down Expand Up @@ -1231,6 +1224,12 @@ ProjectManager::ProjectManager() {
scan_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_scan_projects));
hb->add_child(scan_btn);

erase_missing_btn = memnew(Button);
erase_missing_btn->set_text(TTR("Clean"));
erase_missing_btn->set_tooltip_text(TTR("Remove missing projects."));
erase_missing_btn->connect("pressed", callable_mp(this, &ProjectManager::_erase_missing_projects));
hb->add_child(erase_missing_btn);

loading_label = memnew(Label(TTR("Loading, please wait...")));
loading_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
loading_label->hide();
Expand Down Expand Up @@ -1374,11 +1373,6 @@ ProjectManager::ProjectManager() {
Control *filler = memnew(Control);
filler->set_v_size_flags(Control::SIZE_EXPAND_FILL);
project_list_sidebar->add_child(filler);

erase_missing_btn = memnew(Button);
erase_missing_btn->set_text(TTR("Remove Missing"));
erase_missing_btn->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_erase_missing_projects));
project_list_sidebar->add_child(erase_missing_btn);
}
}

Expand Down Expand Up @@ -1444,10 +1438,9 @@ ProjectManager::ProjectManager() {
add_child(scan_dir);
scan_dir->connect("dir_selected", callable_mp(project_list, &ProjectList::find_projects));

erase_missing_ask = memnew(ConfirmationDialog);
erase_missing_ask->set_ok_button_text(TTR("Remove All"));
erase_missing_ask->get_ok_button()->connect(SceneStringName(pressed), callable_mp(this, &ProjectManager::_erase_missing_projects_confirm));
add_child(erase_missing_ask);
remove_missing_dialog = memnew(RemoveMissingDialog);
remove_missing_dialog->connect("remove_missing_projects", callable_mp(this, &ProjectManager::_erase_missing_projects_confirm));
add_child(remove_missing_dialog);

erase_ask = memnew(ConfirmationDialog);
erase_ask->set_ok_button_text(TTR("Remove"));
Expand Down
6 changes: 3 additions & 3 deletions editor/project_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#define PROJECT_MANAGER_H

#include "scene/gui/dialogs.h"
#include "scene/gui/scroll_container.h"

class CheckBox;
class EditorAbout;
Expand All @@ -48,6 +47,7 @@ class PanelContainer;
class ProjectDialog;
class ProjectList;
class QuickSettingsDialog;
class RemoveMissingDialog;
class RichTextLabel;
class TabContainer;
class VBoxContainer;
Expand Down Expand Up @@ -165,7 +165,7 @@ class ProjectManager : public Control {
// Comment out for now until we have a better warning system to
// ensure users delete their project only.
//CheckBox *delete_project_contents = nullptr;
ConfirmationDialog *erase_missing_ask = nullptr;
RemoveMissingDialog *remove_missing_dialog = nullptr;
ConfirmationDialog *multi_open_ask = nullptr;
ConfirmationDialog *multi_run_ask = nullptr;

Expand All @@ -184,7 +184,7 @@ class ProjectManager : public Control {
void _erase_project();
void _erase_missing_projects();
void _erase_project_confirm();
void _erase_missing_projects_confirm();
void _erase_missing_projects_confirm(const Vector<String> &p_paths);
void _update_project_buttons();

void _on_project_created(const String &dir);
Expand Down
19 changes: 12 additions & 7 deletions editor/project_manager/project_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,16 @@ Vector<ProjectList::Item> ProjectList::get_selected_projects() const {
return items;
}

Vector<String> ProjectList::get_missing_project_paths() const {
Vector<String> paths;
for (const Item &project : _projects) {
if (project.missing) {
paths.push_back(project.path);
}
}
return paths;
}

const HashSet<String> &ProjectList::get_selected_project_keys() const {
// Faster if that's all you need
return _selected_project_paths;
Expand Down Expand Up @@ -963,22 +973,17 @@ bool ProjectList::is_any_project_missing() const {
return false;
}

void ProjectList::erase_missing_projects() {
if (_projects.is_empty()) {
return;
}

void ProjectList::erase_missing_projects(const Vector<String> &p_paths) {
int deleted_count = 0;
int remaining_count = 0;

for (int i = 0; i < _projects.size(); ++i) {
const Item &item = _projects[i];

if (item.missing) {
if (item.missing && p_paths.has(item.path)) {
_remove_project(i, true);
--i;
++deleted_count;

} else {
++remaining_count;
}
Expand Down
3 changes: 2 additions & 1 deletion editor/project_manager/project_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,15 @@ class ProjectList : public ScrollContainer {
void select_project(int p_index);
void select_first_visible_project();
Vector<Item> get_selected_projects() const;
Vector<String> get_missing_project_paths() const;
const HashSet<String> &get_selected_project_keys() const;
int get_single_selected_index() const;
void erase_selected_projects(bool p_delete_project_contents);

// Missing projects.

bool is_any_project_missing() const;
void erase_missing_projects();
void erase_missing_projects(const Vector<String> &p_paths);

// Project list sorting and filtering.

Expand Down
98 changes: 98 additions & 0 deletions editor/project_manager/remove_missing_dialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/**************************************************************************/
/* remove_missing_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. */
/**************************************************************************/

#include "remove_missing_dialog.h"

#include "editor/themes/editor_scale.h"
#include "scene/gui/box_container.h"
#include "scene/gui/label.h"
#include "scene/gui/tree.h"

void RemoveMissingDialog::_on_item_edited() {
bool has_checked = false;
for (TreeItem *item = tree->get_root()->get_next_visible(); item != nullptr; item = item->get_next_visible()) {
if (item->is_checked(0)) {
has_checked = true;
break;
}
}
get_ok_button()->set_disabled(!has_checked);
}

void RemoveMissingDialog::_bind_methods() {
ADD_SIGNAL(MethodInfo("remove_missing_projects", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths")));
}

void RemoveMissingDialog::ok_pressed() {
Vector<String> paths;
for (TreeItem *item = tree->get_root()->get_next_visible(); item != nullptr; item = item->get_next_visible()) {
if (item->is_checked(0)) {
paths.push_back(item->get_text(0));
}
}
hide();
emit_signal("remove_missing_projects", paths);
}

void RemoveMissingDialog::show_dialog(const Vector<String> &p_paths) {
tree->clear();

TreeItem *root = tree->create_item();

for (const String &path : p_paths) {
TreeItem *item = tree->create_item(root);
item->set_cell_mode(0, TreeItem::CELL_MODE_CHECK);
item->set_editable(0, true);
item->set_checked(0, true);
item->set_text(0, path);
}

popup_centered_clamped(Size2(480, 260) * EDSCALE);
}

RemoveMissingDialog::RemoveMissingDialog() {
set_title(TTR("Remove Missing"));
set_hide_on_ok(false);

VBoxContainer *vb = memnew(VBoxContainer);
add_child(vb);

vb->add_child(memnew(Label(TTR("The following paths will be removed from the project list."))));

tree = memnew(Tree);
tree->set_custom_minimum_size(Size2(0, 100) * EDSCALE);
tree->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
tree->set_h_scroll_enabled(false);
tree->set_v_size_flags(Control::SIZE_EXPAND_FILL);
tree->set_hide_root(true);
tree->set_select_mode(Tree::SELECT_ROW);
tree->connect("item_edited", callable_mp(this, &RemoveMissingDialog::_on_item_edited));
vb->add_child(tree);
}
56 changes: 56 additions & 0 deletions editor/project_manager/remove_missing_dialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**************************************************************************/
/* remove_missing_dialog.h */
/**************************************************************************/
/* 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. */
/**************************************************************************/

#ifndef REMOVE_MISSING_DIALOG_H
#define REMOVE_MISSING_DIALOG_H

#include "scene/gui/dialogs.h"

class Tree;

class RemoveMissingDialog : public ConfirmationDialog {
GDCLASS(RemoveMissingDialog, ConfirmationDialog);

Tree *tree;

void _on_item_edited();

protected:
static void _bind_methods();

virtual void ok_pressed() override;

public:
void show_dialog(const Vector<String> &p_paths);

RemoveMissingDialog();
};

#endif // REMOVE_MISSING_DIALOG_H

0 comments on commit 23e5cfb

Please sign in to comment.