From fa9f5c97997d609a52cebd2958966b404a67d1c9 Mon Sep 17 00:00:00 2001 From: Algot Axelzon Date: Wed, 31 Mar 2021 02:54:39 +0200 Subject: [PATCH] HackStudio: Make actions with project tree selections work as expected Creating a file while having a file or directory selected will now create the file under the selected directory, or in same directory as a selected file. Creating directories works the same way. Right click -> Open on selected files will now open the selected files. Deleting selected files will now delete the selected files. As suggested by sagefarrenholz this was accomplished by adding a private function HackStudioWidget::selected_file_paths() that returns a Vector of the current project tree selection. Function HackStudioWidget::selected_file_names() is removed due to not being used. --- .../DevTools/HackStudio/HackStudioWidget.cpp | 65 ++++++++++++++++--- .../DevTools/HackStudio/HackStudioWidget.h | 3 +- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.cpp b/Userland/DevTools/HackStudio/HackStudioWidget.cpp index 1fd0a673399..ff6d9e26b66 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.cpp +++ b/Userland/DevTools/HackStudio/HackStudioWidget.cpp @@ -202,11 +202,21 @@ void HackStudioWidget::open_project(const String& root_path) } } -Vector HackStudioWidget::selected_file_names() const +Vector HackStudioWidget::selected_file_paths() const { Vector files; m_project_tree_view->selection().for_each_index([&](const GUI::ModelIndex& index) { - files.append(index.data().as_string()); + String sub_path = index.data().as_string(); + + GUI::ModelIndex parent_or_invalid = index.parent(); + + while (parent_or_invalid.is_valid()) { + sub_path = String::formatted("{}/{}", parent_or_invalid.data().as_string(), sub_path); + + parent_or_invalid = parent_or_invalid.parent(); + } + + files.append(sub_path); }); return files; } @@ -319,12 +329,34 @@ NonnullRefPtr HackStudioWidget::create_new_file_action() String filename; if (GUI::InputBox::show(window(), filename, "Enter name of new file:", "Add new file to project") != GUI::InputBox::ExecOK) return; - auto file = Core::File::construct(filename); + + auto path_to_selected = selected_file_paths(); + + String filepath; + + if (!path_to_selected.is_empty()) { + VERIFY(Core::File::exists(path_to_selected.first())); + + LexicalPath selected(path_to_selected.first()); + + String dir_path; + + if (Core::File::is_directory(selected.string())) + dir_path = selected.string(); + else + dir_path = selected.dirname(); + + filepath = String::formatted("{}/", dir_path); + } + + filepath = String::formatted("{}{}", filepath, filename); + + auto file = Core::File::construct(filepath); if (!file->open((Core::IODevice::OpenMode)(Core::IODevice::WriteOnly | Core::IODevice::MustBeNew))) { - GUI::MessageBox::show(window(), String::formatted("Failed to create '{}'", filename), "Error", GUI::MessageBox::Type::Error); + GUI::MessageBox::show(window(), String::formatted("Failed to create '{}'", filepath), "Error", GUI::MessageBox::Type::Error); return; } - open_file(filename); + open_file(filepath); }); } @@ -334,6 +366,22 @@ NonnullRefPtr HackStudioWidget::create_new_directory_action() String directory_name; if (GUI::InputBox::show(window(), directory_name, "Enter name of new directory:", "Add new folder to project") != GUI::InputBox::ExecOK) return; + + auto path_to_selected = selected_file_paths(); + + if (!path_to_selected.is_empty()) { + LexicalPath selected(path_to_selected.first()); + + String dir_path; + + if (Core::File::is_directory(selected.string())) + dir_path = selected.string(); + else + dir_path = selected.dirname(); + + directory_name = String::formatted("{}/{}", dir_path, directory_name); + } + auto formatted_dir_name = LexicalPath::canonicalized_path(String::formatted("{}/{}", m_project->model().root_path(), directory_name)); int rc = mkdir(formatted_dir_name.characters(), 0755); if (rc < 0) { @@ -347,7 +395,7 @@ NonnullRefPtr HackStudioWidget::create_open_selected_action() { auto open_selected_action = GUI::Action::create("Open", [this](const GUI::Action&) { - auto files = selected_file_names(); + auto files = selected_file_paths(); for (auto& file : files) open_file(file); }); @@ -358,13 +406,14 @@ NonnullRefPtr HackStudioWidget::create_open_selected_action() NonnullRefPtr HackStudioWidget::create_delete_action() { auto delete_action = GUI::CommonActions::make_delete_action([this](const GUI::Action&) { - auto files = selected_file_names(); + auto files = selected_file_paths(); if (files.is_empty()) return; String message; if (files.size() == 1) { - message = String::formatted("Really remove {} from disk?", LexicalPath(files[0]).basename()); + LexicalPath file(files[0]); + message = String::formatted("Really remove {} from disk?", file.basename()); } else { message = String::formatted("Really remove {} files from disk?", files.size()); } diff --git a/Userland/DevTools/HackStudio/HackStudioWidget.h b/Userland/DevTools/HackStudio/HackStudioWidget.h index d7ce22f3319..1b363ca1998 100644 --- a/Userland/DevTools/HackStudio/HackStudioWidget.h +++ b/Userland/DevTools/HackStudio/HackStudioWidget.h @@ -54,8 +54,6 @@ public: virtual ~HackStudioWidget() override; void open_file(const String& filename); - Vector selected_file_names() const; - void update_actions(); Project& project(); GUI::TextEditor& current_editor(); @@ -73,6 +71,7 @@ public: private: static String get_full_path_of_serenity_source(const String& file); + Vector selected_file_paths() const; HackStudioWidget(const String& path_to_project); void open_project(const String& root_path);