HackStudio: Add a 'Recent Projects' submenu in 'File'

This commit is contained in:
Marco Cutecchia 2022-02-14 14:08:24 +01:00 committed by Andreas Kling
parent dbfe385879
commit 7e7bfdac50
Notes: sideshowbarker 2024-07-17 18:27:01 +09:00
2 changed files with 63 additions and 0 deletions

View File

@ -23,6 +23,7 @@
#include "ProjectDeclarations.h"
#include "TerminalWrapper.h"
#include "ToDoEntries.h"
#include <AK/JsonParser.h>
#include <AK/LexicalPath.h>
#include <AK/StringBuilder.h>
#include <Kernel/API/InodeWatcherEvent.h>
@ -192,6 +193,28 @@ void HackStudioWidget::on_action_tab_change()
}
}
Vector<String> HackStudioWidget::read_recent_projects()
{
auto json = Config::read_string("HackStudio", "Global", "RecentProjects");
AK::JsonParser parser(json);
auto value_or_error = parser.parse();
if (value_or_error.is_error())
return {};
auto value = value_or_error.release_value();
if (!value.is_array())
return {};
Vector<String> paths;
for (auto& json_value : value.as_array().values()) {
if (!json_value.is_string())
return {};
paths.append(json_value.as_string());
}
return paths;
}
void HackStudioWidget::open_project(const String& root_path)
{
if (warn_unsaved_changes("There are unsaved changes, do you want to save before closing current project?") == ContinueDecision::No)
@ -229,6 +252,15 @@ void HackStudioWidget::open_project(const String& root_path)
LexicalPath::relative_path(absolute_old_path, m_project->root_path()),
LexicalPath::relative_path(absolute_new_path, m_project->root_path()));
};
auto recent_projects = read_recent_projects();
recent_projects.remove_all_matching([&](auto& p) { return p == root_path; });
recent_projects.insert(0, root_path);
if (recent_projects.size() > recent_projects_history_size)
recent_projects.shrink(recent_projects_history_size);
Config::write_string("HackStudio", "Global", "RecentProjects", JsonArray(recent_projects).to_string());
update_recent_projects_submenu();
}
Vector<String> HackStudioWidget::selected_file_paths() const
@ -1142,11 +1174,36 @@ void HackStudioWidget::create_project_tab(GUI::Widget& parent)
};
}
void HackStudioWidget::update_recent_projects_submenu()
{
if (!m_recent_projects_submenu)
return;
m_recent_projects_submenu->remove_all_actions();
auto recent_projects = read_recent_projects();
if (recent_projects.size() <= 1) {
auto empty_action = GUI::Action::create("Empty...", [](auto&) {});
empty_action->set_enabled(false);
m_recent_projects_submenu->add_action(empty_action);
return;
}
for (size_t i = 1; i < recent_projects.size(); i++) {
auto project_path = recent_projects[i];
m_recent_projects_submenu->add_action(GUI::Action::create(recent_projects[i], [this, project_path](auto&) {
open_project(project_path);
}));
}
}
void HackStudioWidget::create_file_menu(GUI::Window& window)
{
auto& file_menu = window.add_menu("&File");
file_menu.add_action(*m_new_project_action);
file_menu.add_action(*m_open_action);
m_recent_projects_submenu = &file_menu.add_submenu("Open Recent");
update_recent_projects_submenu();
file_menu.add_action(*m_save_action);
file_menu.add_action(*m_save_as_action);
file_menu.add_separator();

View File

@ -73,7 +73,11 @@ public:
void for_each_open_file(Function<void(ProjectFile const&)>);
bool semantic_syntax_highlighting_is_enabled() const;
static Vector<String> read_recent_projects();
private:
static constexpr size_t recent_projects_history_size = 15;
static String get_full_path_of_serenity_source(const String& file);
String get_absolute_path(String const&) const;
Vector<String> selected_file_paths() const;
@ -128,6 +132,7 @@ private:
void create_toolbar(GUI::Widget& parent);
void create_action_tab(GUI::Widget& parent);
void create_file_menu(GUI::Window&);
void update_recent_projects_submenu();
void create_project_menu(GUI::Window&);
void create_edit_menu(GUI::Window&);
void create_build_menu(GUI::Window&);
@ -193,6 +198,7 @@ private:
RefPtr<DisassemblyWidget> m_disassembly_widget;
RefPtr<Threading::Thread> m_debugger_thread;
RefPtr<EditorWrapper> m_current_editor_in_execution;
RefPtr<GUI::Menu> m_recent_projects_submenu { nullptr };
NonnullRefPtrVector<GUI::Action> m_new_file_actions;
RefPtr<GUI::Action> m_new_plain_file_action;