mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
FileManager: Add file properties tab for PDF documents
This commit is contained in:
parent
a333d9959c
commit
7c8772ad86
|
@ -12,6 +12,7 @@ compile_gml(PropertiesWindowAudioTab.gml PropertiesWindowAudioTabGML.h propertie
|
|||
compile_gml(PropertiesWindowFontTab.gml PropertiesWindowFontTabGML.h properties_window_font_tab_gml)
|
||||
compile_gml(PropertiesWindowGeneralTab.gml PropertiesWindowGeneralTabGML.h properties_window_general_tab_gml)
|
||||
compile_gml(PropertiesWindowImageTab.gml PropertiesWindowImageTabGML.h properties_window_image_tab_gml)
|
||||
compile_gml(PropertiesWindowPDFTab.gml PropertiesWindowPDFTabGML.h properties_window_pdf_tab_gml)
|
||||
|
||||
set(SOURCES
|
||||
DesktopWidget.cpp
|
||||
|
@ -30,7 +31,8 @@ set(GENERATED_SOURCES
|
|||
PropertiesWindowFontTabGML.h
|
||||
PropertiesWindowGeneralTabGML.h
|
||||
PropertiesWindowImageTabGML.h
|
||||
PropertiesWindowPDFTabGML.h
|
||||
)
|
||||
|
||||
serenity_app(FileManager ICON app-file-manager)
|
||||
target_link_libraries(FileManager PRIVATE LibArchive LibAudio LibCore LibFileSystem LibGfx LibGUI LibDesktop LibConfig LibMain LibThreading)
|
||||
target_link_libraries(FileManager PRIVATE LibArchive LibAudio LibConfig LibCore LibDesktop LibFileSystem LibGfx LibGUI LibMain LibPDF LibThreading)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <Applications/FileManager/PropertiesWindowFontTabGML.h>
|
||||
#include <Applications/FileManager/PropertiesWindowGeneralTabGML.h>
|
||||
#include <Applications/FileManager/PropertiesWindowImageTabGML.h>
|
||||
#include <Applications/FileManager/PropertiesWindowPDFTabGML.h>
|
||||
#include <LibArchive/Zip.h>
|
||||
#include <LibAudio/Loader.h>
|
||||
#include <LibCore/Directory.h>
|
||||
|
@ -39,6 +40,7 @@
|
|||
#include <LibGfx/Font/WOFF/Font.h>
|
||||
#include <LibGfx/ICC/Profile.h>
|
||||
#include <LibGfx/ICC/Tags.h>
|
||||
#include <LibPDF/Document.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
|
@ -238,6 +240,9 @@ ErrorOr<void> PropertiesWindow::create_file_type_specific_tabs(GUI::TabWidget& t
|
|||
if (mime_type.starts_with("image/"sv))
|
||||
return create_image_tab(tab_widget, move(mapped_file), mime_type);
|
||||
|
||||
if (mime_type == "application/pdf"sv)
|
||||
return create_pdf_tab(tab_widget, move(mapped_file));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -451,6 +456,59 @@ ErrorOr<void> PropertiesWindow::create_image_tab(GUI::TabWidget& tab_widget, Non
|
|||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> PropertiesWindow::create_pdf_tab(GUI::TabWidget& tab_widget, NonnullRefPtr<Core::MappedFile> mapped_file)
|
||||
{
|
||||
auto maybe_document = PDF::Document::create(mapped_file->bytes());
|
||||
if (maybe_document.is_error()) {
|
||||
warnln("Failed to open '{}': {}", m_path, maybe_document.error().message());
|
||||
return {};
|
||||
}
|
||||
auto document = maybe_document.release_value();
|
||||
|
||||
if (auto handler = document->security_handler(); handler && !handler->has_user_password()) {
|
||||
// FIXME: Show a password dialog, once we've switched to lazy-loading
|
||||
auto tab = TRY(tab_widget.try_add_tab<GUI::Label>("PDF"_short_string));
|
||||
tab->set_text(TRY("PDF is password-protected."_string));
|
||||
return {};
|
||||
}
|
||||
|
||||
if (auto maybe_error = document->initialize(); maybe_error.is_error()) {
|
||||
warnln("PDF '{}' seems to be invalid: {}", m_path, maybe_error.error().message());
|
||||
return {};
|
||||
}
|
||||
|
||||
auto tab = TRY(tab_widget.try_add_tab<GUI::Widget>("PDF"_short_string));
|
||||
TRY(tab->load_from_gml(properties_window_pdf_tab_gml));
|
||||
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_version")->set_text(TRY(String::formatted("{}.{}", document->version().major, document->version().minor)));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_page_count")->set_text(TRY(String::number(document->get_page_count())));
|
||||
|
||||
auto maybe_info_dict = document->info_dict();
|
||||
if (maybe_info_dict.is_error()) {
|
||||
warnln("Failed to read InfoDict from '{}': {}", m_path, maybe_info_dict.error().message());
|
||||
} else if (maybe_info_dict.value().has_value()) {
|
||||
auto get_info_string = [](PDF::PDFErrorOr<Optional<DeprecatedString>> input) -> ErrorOr<String> {
|
||||
if (input.is_error())
|
||||
return String {};
|
||||
if (!input.value().has_value())
|
||||
return String {};
|
||||
return String::from_deprecated_string(input.value().value());
|
||||
};
|
||||
|
||||
auto info_dict = maybe_info_dict.release_value().release_value();
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_title")->set_text(TRY(get_info_string(info_dict.title())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_author")->set_text(TRY(get_info_string(info_dict.author())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_subject")->set_text(TRY(get_info_string(info_dict.subject())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_keywords")->set_text(TRY(get_info_string(info_dict.keywords())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_creator")->set_text(TRY(get_info_string(info_dict.creator())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_producer")->set_text(TRY(get_info_string(info_dict.producer())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_creation_date")->set_text(TRY(get_info_string(info_dict.creation_date())));
|
||||
tab->find_descendant_of_type_named<GUI::Label>("pdf_modification_date")->set_text(TRY(get_info_string(info_dict.modification_date())));
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void PropertiesWindow::update()
|
||||
{
|
||||
m_icon->set_bitmap(GUI::FileIconProvider::icon_for_path(make_full_path(m_name), m_mode).bitmap_for_size(32));
|
||||
|
|
|
@ -34,6 +34,7 @@ private:
|
|||
ErrorOr<void> create_audio_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>);
|
||||
ErrorOr<void> create_font_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>, StringView mime_type);
|
||||
ErrorOr<void> create_image_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>, StringView mime_type);
|
||||
ErrorOr<void> create_pdf_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>);
|
||||
|
||||
struct PermissionMasks {
|
||||
mode_t read;
|
||||
|
|
185
Userland/Applications/FileManager/PropertiesWindowPDFTab.gml
Normal file
185
Userland/Applications/FileManager/PropertiesWindowPDFTab.gml
Normal file
|
@ -0,0 +1,185 @@
|
|||
@GUI::Widget {
|
||||
layout: @GUI::VerticalBoxLayout {
|
||||
margins: [8]
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::GroupBox {
|
||||
title: "PDF"
|
||||
preferred_height: "shrink"
|
||||
layout: @GUI::VerticalBoxLayout {
|
||||
margins: [12, 8, 0]
|
||||
spacing: 2
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Version:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_version"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Page count:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_page_count"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Title:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_title"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Author:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_author"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Subject:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_subject"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Keywords:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_keywords"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Creator:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_creator"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Producer:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_producer"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Created:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_creation_date"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
layout: @GUI::HorizontalBoxLayout {
|
||||
spacing: 12
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
text: "Modified:"
|
||||
text_alignment: "TopLeft"
|
||||
fixed_width: 80
|
||||
}
|
||||
|
||||
@GUI::Label {
|
||||
name: "pdf_modification_date"
|
||||
text_alignment: "TopLeft"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue