diff options
author | Julian Offenhäuser <metalvoidzz@gmail.com> | 2021-12-27 18:16:37 +0100 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2021-12-28 01:14:52 +0100 |
commit | 5bc7a18a046c86a17d4dc33d24c01be43875ac0f (patch) | |
tree | a2996b4872a7f351682ec253ebe49dd63fb6bb8e | |
parent | 5d55a42ded2a0376a8a2d90869e4d9e920fe40e2 (diff) | |
download | serenity-5bc7a18a046c86a17d4dc33d24c01be43875ac0f.zip |
FileManager: Add "Create Archive" action
This option will appear when you select one or more files or
directories. It will then ask the user to enter a name for the new
archive (or use the current directories' name if left empty) and
create it under that name in the currently opened directory.
Note that only .zip files are currently supported.
-rw-r--r-- | Userland/Applications/FileManager/main.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/Userland/Applications/FileManager/main.cpp b/Userland/Applications/FileManager/main.cpp index 27326c9c5a..d560112b19 100644 --- a/Userland/Applications/FileManager/main.cpp +++ b/Userland/Applications/FileManager/main.cpp @@ -30,6 +30,7 @@ #include <LibGUI/Desktop.h> #include <LibGUI/FileIconProvider.h> #include <LibGUI/FileSystemModel.h> +#include <LibGUI/InputBox.h> #include <LibGUI/Menu.h> #include <LibGUI/Menubar.h> #include <LibGUI/MessageBox.h> @@ -58,6 +59,7 @@ static ErrorOr<int> run_in_windowed_mode(String initial_location, String entry_f static void do_copy(Vector<String> const& selected_file_paths, FileOperation file_operation); static void do_paste(String const& target_directory, GUI::Window* window); static void do_create_link(Vector<String> const& selected_file_paths, GUI::Window* window); +static void do_create_archive(Vector<String> const& selected_file_paths, GUI::Window* window); static void do_unzip_archive(Vector<String> const& selected_file_paths, GUI::Window* window); static void show_properties(String const& container_dir_path, String const& path, Vector<String> const& selected, GUI::Window* window); static bool add_launch_handler_actions_to_menu(RefPtr<GUI::Menu>& menu, DirectoryView const& directory_view, String const& full_path, RefPtr<GUI::Action>& default_action, NonnullRefPtrVector<LauncherHandler>& current_file_launch_handlers); @@ -187,6 +189,58 @@ void do_create_link(Vector<String> const& selected_file_paths, GUI::Window* wind } } +void do_create_archive(Vector<String> const& selected_file_paths, GUI::Window* window) +{ + String archive_name; + if (GUI::InputBox::show(window, archive_name, "Enter name:", "Create Archive") != GUI::InputBox::ExecOK) + return; + + auto output_directory_path = LexicalPath(selected_file_paths.first()); + + StringBuilder path_builder; + path_builder.append(output_directory_path.dirname()); + path_builder.append("/"); + if (archive_name.is_empty()) { + path_builder.append(output_directory_path.parent().basename()); + path_builder.append(".zip"); + } else { + path_builder.append(archive_name); + if (!archive_name.ends_with(".zip")) + path_builder.append(".zip"); + } + auto output_path = path_builder.build(); + + pid_t zip_pid = fork(); + if (zip_pid < 0) { + perror("fork"); + VERIFY_NOT_REACHED(); + } + + if (!zip_pid) { + Vector<String> relative_paths; + Vector<char const*> arg_list; + arg_list.append("/bin/zip"); + arg_list.append("-r"); + arg_list.append("-f"); + arg_list.append(output_path.characters()); + for (auto const& path : selected_file_paths) { + relative_paths.append(LexicalPath::relative_path(path, output_directory_path.dirname())); + arg_list.append(relative_paths.last().characters()); + } + arg_list.append(nullptr); + int rc = execvp("/bin/zip", const_cast<char* const*>(arg_list.data())); + if (rc < 0) { + perror("execvp"); + _exit(1); + } + } else { + int status; + int rc = waitpid(zip_pid, &status, 0); + if (rc < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) + GUI::MessageBox::show(window, "Could not create archive", "Archive Error", GUI::MessageBox::Type::Error); + } +} + void do_unzip_archive(Vector<String> const& selected_file_paths, GUI::Window* window) { String archive_file_path = selected_file_paths.first(); @@ -307,6 +361,19 @@ ErrorOr<int> run_in_desktop_mode() window); copy_action->set_enabled(false); + auto create_archive_action + = GUI::Action::create( + "Create &Archive", + Gfx::Bitmap::try_load_from_file("/res/icons/16x16/filetype-archive.png").release_value_but_fixme_should_propagate_errors(), + [&](GUI::Action const&) { + auto paths = directory_view->selected_file_paths(); + if (paths.is_empty()) + return; + + do_create_archive(paths, directory_view->window()); + }, + window); + auto unzip_archive_action = GUI::Action::create( "E&xtract Here", @@ -420,6 +487,7 @@ ErrorOr<int> run_in_desktop_mode() file_context_menu->add_action(paste_action); file_context_menu->add_action(directory_view->delete_action()); file_context_menu->add_action(directory_view->rename_action()); + file_context_menu->add_action(create_archive_action); file_context_menu->add_separator(); if (node.full_path().ends_with(".zip", AK::CaseSensitivity::CaseInsensitive)) { @@ -732,6 +800,20 @@ ErrorOr<int> run_in_windowed_mode(String initial_location, String entry_focused_ }, window); + auto create_archive_action + = GUI::Action::create( + "Create &Archive", + Gfx::Bitmap::try_load_from_file("/res/icons/16x16/filetype-archive.png").release_value_but_fixme_should_propagate_errors(), + [&](GUI::Action const&) { + auto paths = directory_view->selected_file_paths(); + if (paths.is_empty()) + return; + + do_create_archive(paths, directory_view->window()); + refresh_tree_view(); + }, + window); + auto unzip_archive_action = GUI::Action::create( "E&xtract Here", @@ -1049,6 +1131,7 @@ ErrorOr<int> run_in_windowed_mode(String initial_location, String entry_focused_ TRY(directory_context_menu->try_add_action(directory_view->delete_action())); TRY(directory_context_menu->try_add_action(directory_view->rename_action())); TRY(directory_context_menu->try_add_action(shortcut_action)); + TRY(directory_context_menu->try_add_action(create_archive_action)); TRY(directory_context_menu->try_add_separator()); TRY(directory_context_menu->try_add_action(properties_action)); @@ -1098,6 +1181,7 @@ ErrorOr<int> run_in_windowed_mode(String initial_location, String entry_focused_ file_context_menu->add_action(directory_view->delete_action()); file_context_menu->add_action(directory_view->rename_action()); file_context_menu->add_action(shortcut_action); + file_context_menu->add_action(create_archive_action); file_context_menu->add_separator(); if (node.full_path().ends_with(".zip", AK::CaseSensitivity::CaseInsensitive)) { |