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.
This commit is contained in:
parent
5d55a42ded
commit
5bc7a18a04
Notes:
sideshowbarker
2024-07-17 22:05:30 +09:00
Author: https://github.com/janso3 Commit: https://github.com/SerenityOS/serenity/commit/5bc7a18a046 Pull-request: https://github.com/SerenityOS/serenity/pull/11448 Reviewed-by: https://github.com/linusg
1 changed files with 84 additions and 0 deletions
|
@ -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)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue