summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorJulian Offenhäuser <metalvoidzz@gmail.com>2021-12-27 18:16:37 +0100
committerLinus Groh <mail@linusgroh.de>2021-12-28 01:14:52 +0100
commit5bc7a18a046c86a17d4dc33d24c01be43875ac0f (patch)
treea2996b4872a7f351682ec253ebe49dd63fb6bb8e /Userland
parent5d55a42ded2a0376a8a2d90869e4d9e920fe40e2 (diff)
downloadserenity-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.
Diffstat (limited to 'Userland')
-rw-r--r--Userland/Applications/FileManager/main.cpp84
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)) {