From a333d9959cf6ed725d54a48b3450190845bc7ac2 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Tue, 25 Jul 2023 11:45:01 +0100 Subject: [PATCH] FileManager: Add file properties tab for ZIP archives --- .../Applications/FileManager/CMakeLists.txt | 4 +- .../FileManager/PropertiesWindow.cpp | 29 +++++++ .../FileManager/PropertiesWindow.h | 1 + .../PropertiesWindowArchiveTab.gml | 87 +++++++++++++++++++ 4 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 Userland/Applications/FileManager/PropertiesWindowArchiveTab.gml diff --git a/Userland/Applications/FileManager/CMakeLists.txt b/Userland/Applications/FileManager/CMakeLists.txt index 6c4dbd7081..d5ef54ae29 100644 --- a/Userland/Applications/FileManager/CMakeLists.txt +++ b/Userland/Applications/FileManager/CMakeLists.txt @@ -7,6 +7,7 @@ serenity_component( compile_gml(FileManagerWindow.gml FileManagerWindowGML.h file_manager_window_gml) compile_gml(FileOperationProgress.gml FileOperationProgressGML.h file_operation_progress_gml) +compile_gml(PropertiesWindowArchiveTab.gml PropertiesWindowArchiveTabGML.h properties_window_archive_tab_gml) compile_gml(PropertiesWindowAudioTab.gml PropertiesWindowAudioTabGML.h properties_window_audio_tab_gml) compile_gml(PropertiesWindowFontTab.gml PropertiesWindowFontTabGML.h properties_window_font_tab_gml) compile_gml(PropertiesWindowGeneralTab.gml PropertiesWindowGeneralTabGML.h properties_window_general_tab_gml) @@ -24,6 +25,7 @@ set(SOURCES set(GENERATED_SOURCES FileManagerWindowGML.h FileOperationProgressGML.h + PropertiesWindowArchiveTabGML.h PropertiesWindowAudioTabGML.h PropertiesWindowFontTabGML.h PropertiesWindowGeneralTabGML.h @@ -31,4 +33,4 @@ set(GENERATED_SOURCES ) serenity_app(FileManager ICON app-file-manager) -target_link_libraries(FileManager PRIVATE LibAudio LibCore LibFileSystem LibGfx LibGUI LibDesktop LibConfig LibMain LibThreading) +target_link_libraries(FileManager PRIVATE LibArchive LibAudio LibCore LibFileSystem LibGfx LibGUI LibDesktop LibConfig LibMain LibThreading) diff --git a/Userland/Applications/FileManager/PropertiesWindow.cpp b/Userland/Applications/FileManager/PropertiesWindow.cpp index 5deacfd584..acf44b3e36 100644 --- a/Userland/Applications/FileManager/PropertiesWindow.cpp +++ b/Userland/Applications/FileManager/PropertiesWindow.cpp @@ -7,13 +7,16 @@ */ #include "PropertiesWindow.h" +#include #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -222,6 +225,10 @@ ErrorOr PropertiesWindow::create_file_type_specific_tabs(GUI::TabWidget& t auto file_name_guess = Core::guess_mime_type_based_on_filename(m_path); auto mime_type = Core::guess_mime_type_based_on_sniffed_bytes(mapped_file->bytes()).value_or(file_name_guess); + // FIXME: Support other archive types + if (mime_type == "application/zip"sv) + return create_archive_tab(tab_widget, move(mapped_file)); + if (mime_type.starts_with("audio/"sv)) return create_audio_tab(tab_widget, move(mapped_file)); @@ -234,6 +241,28 @@ ErrorOr PropertiesWindow::create_file_type_specific_tabs(GUI::TabWidget& t return {}; } +ErrorOr PropertiesWindow::create_archive_tab(GUI::TabWidget& tab_widget, NonnullRefPtr mapped_file) +{ + auto maybe_zip = Archive::Zip::try_create(mapped_file->bytes()); + if (!maybe_zip.has_value()) { + warnln("Failed to read zip file '{}' ", m_path); + return {}; + } + auto zip = maybe_zip.release_value(); + + auto tab = TRY(tab_widget.try_add_tab(TRY("Archive"_string))); + TRY(tab->load_from_gml(properties_window_archive_tab_gml)); + + auto statistics = TRY(zip.calculate_statistics()); + + tab->find_descendant_of_type_named("archive_format")->set_text("ZIP"_short_string); + tab->find_descendant_of_type_named("archive_file_count")->set_text(TRY(String::number(statistics.file_count()))); + tab->find_descendant_of_type_named("archive_directory_count")->set_text(TRY(String::number(statistics.directory_count()))); + tab->find_descendant_of_type_named("archive_uncompressed_size")->set_text(TRY(String::from_deprecated_string(AK::human_readable_size(statistics.total_uncompressed_bytes())))); + + return {}; +} + ErrorOr PropertiesWindow::create_audio_tab(GUI::TabWidget& tab_widget, NonnullRefPtr mapped_file) { auto loader_or_error = Audio::Loader::create(mapped_file->bytes()); diff --git a/Userland/Applications/FileManager/PropertiesWindow.h b/Userland/Applications/FileManager/PropertiesWindow.h index fc429631e9..9b45210f01 100644 --- a/Userland/Applications/FileManager/PropertiesWindow.h +++ b/Userland/Applications/FileManager/PropertiesWindow.h @@ -30,6 +30,7 @@ private: ErrorOr create_widgets(bool disable_rename); ErrorOr create_general_tab(GUI::TabWidget&, bool disable_rename); ErrorOr create_file_type_specific_tabs(GUI::TabWidget&); + ErrorOr create_archive_tab(GUI::TabWidget&, NonnullRefPtr); ErrorOr create_audio_tab(GUI::TabWidget&, NonnullRefPtr); ErrorOr create_font_tab(GUI::TabWidget&, NonnullRefPtr, StringView mime_type); ErrorOr create_image_tab(GUI::TabWidget&, NonnullRefPtr, StringView mime_type); diff --git a/Userland/Applications/FileManager/PropertiesWindowArchiveTab.gml b/Userland/Applications/FileManager/PropertiesWindowArchiveTab.gml new file mode 100644 index 0000000000..654bc6adf2 --- /dev/null +++ b/Userland/Applications/FileManager/PropertiesWindowArchiveTab.gml @@ -0,0 +1,87 @@ +@GUI::Widget { + layout: @GUI::VerticalBoxLayout { + margins: [8] + spacing: 12 + } + + @GUI::GroupBox { + title: "Archive" + preferred_height: "shrink" + layout: @GUI::VerticalBoxLayout { + margins: [12, 8, 0] + spacing: 2 + } + + @GUI::Widget { + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Format:" + text_alignment: "TopLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "archive_format" + text: "ZIP" + text_alignment: "TopLeft" + } + } + + @GUI::Widget { + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Files:" + text_alignment: "TopLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "archive_file_count" + text: "42" + text_alignment: "TopLeft" + } + } + + @GUI::Widget { + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Directories:" + text_alignment: "TopLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "archive_directory_count" + text: "7" + text_alignment: "TopLeft" + } + } + + @GUI::Widget { + layout: @GUI::HorizontalBoxLayout { + spacing: 12 + } + + @GUI::Label { + text: "Uncompressed:" + text_alignment: "TopLeft" + fixed_width: 80 + } + + @GUI::Label { + name: "archive_uncompressed_size" + text: "3.3 MiB" + text_alignment: "TopLeft" + } + } + } +}