diff --git a/Userland/Applications/FileManager/main.cpp b/Userland/Applications/FileManager/main.cpp index 40a453025d..b496b8ab90 100644 --- a/Userland/Applications/FileManager/main.cpp +++ b/Userland/Applications/FileManager/main.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include using namespace FileManager; @@ -58,6 +59,7 @@ static int run_in_windowed_mode(RefPtr, String initial_locatio static void do_copy(const Vector& selected_file_paths, FileUtils::FileOperation file_operation); static void do_paste(const String& target_directory, GUI::Window* window); static void do_create_link(const Vector& selected_file_paths, GUI::Window* window); +static void do_unzip_archive(const Vector& selected_file_paths, GUI::Window* window); static void show_properties(const String& container_dir_path, const String& path, const Vector& selected, GUI::Window* window); static bool add_launch_handler_actions_to_menu(RefPtr& menu, const DirectoryView& directory_view, const String& full_path, RefPtr& default_action, NonnullRefPtrVector& current_file_launch_handlers); @@ -192,6 +194,32 @@ void do_create_link(const Vector& selected_file_paths, GUI::Window* wind } } +void do_unzip_archive(const Vector& selected_file_paths, GUI::Window* window) +{ + String archive_file_path = selected_file_paths.first(); + String output_directory_path = archive_file_path.substring(0, archive_file_path.length() - 4); + + pid_t unzip_pid = fork(); + if (unzip_pid < 0) { + perror("fork"); + VERIFY_NOT_REACHED(); + } + + if (!unzip_pid) { + int rc = execlp("/bin/unzip", "/bin/unzip", "-o", output_directory_path.characters(), archive_file_path.characters(), nullptr); + if (rc < 0) { + perror("execlp"); + _exit(1); + } + } else { + // FIXME: this could probably be tied in with the new file operation progress tracking + int status; + int rc = waitpid(unzip_pid, &status, 0); + if (rc < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) + GUI::MessageBox::show(window, "Could not extract archive", "Extract Archive Error", GUI::MessageBox::Type::Error); + } +} + void show_properties(const String& container_dir_path, const String& path, const Vector& selected, GUI::Window* window) { RefPtr properties; @@ -285,6 +313,18 @@ int run_in_desktop_mode([[maybe_unused]] RefPtr config) window); cut_action->set_enabled(false); + auto unzip_archive_action + = GUI::Action::create( + "E&xtract Here", + [&](const GUI::Action&) { + auto paths = directory_view.selected_file_paths(); + if (paths.is_empty()) + return; + + do_unzip_archive(paths, directory_view.window()); + }, + window); + directory_view.on_selection_change = [&](const GUI::AbstractView& view) { copy_action->set_enabled(!view.selection().is_empty()); cut_action->set_enabled(!view.selection().is_empty()); @@ -354,6 +394,11 @@ int run_in_desktop_mode([[maybe_unused]] RefPtr config) file_context_menu->add_action(directory_view.delete_action()); file_context_menu->add_separator(); + if (node.full_path().ends_with(".zip", AK::CaseSensitivity::CaseInsensitive)) { + file_context_menu->add_action(unzip_archive_action); + file_context_menu->add_separator(); + } + bool added_open_menu_items = add_launch_handler_actions_to_menu(file_context_menu, directory_view, node.full_path(), file_context_menu_action_default_action, current_file_handlers); if (added_open_menu_items) file_context_menu->add_separator(); @@ -648,6 +693,19 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio }, window); + auto unzip_archive_action + = GUI::Action::create( + "E&xtract Here", + [&](const GUI::Action&) { + auto paths = directory_view.selected_file_paths(); + if (paths.is_empty()) + return; + + do_unzip_archive(paths, directory_view.window()); + refresh_tree_view(); + }, + window); + auto properties_action = GUI::CommonActions::make_properties_action( [&](auto& action) { String container_dir_path; @@ -965,6 +1023,11 @@ int run_in_windowed_mode(RefPtr config, String initial_locatio file_context_menu->add_action(shortcut_action); file_context_menu->add_separator(); + if (node.full_path().ends_with(".zip", AK::CaseSensitivity::CaseInsensitive)) { + file_context_menu->add_action(unzip_archive_action); + file_context_menu->add_separator(); + } + bool added_launch_file_handlers = add_launch_handler_actions_to_menu(file_context_menu, directory_view, node.full_path(), file_context_menu_action_default_action, current_file_handlers); if (added_launch_file_handlers) file_context_menu->add_separator();