mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 12:17:35 +00:00
FileManager: Add file properties tab for PDF documents
This commit is contained in:
parent
a333d9959c
commit
7c8772ad86
4 changed files with 247 additions and 1 deletions
|
@ -12,6 +12,7 @@ compile_gml(PropertiesWindowAudioTab.gml PropertiesWindowAudioTabGML.h propertie
|
||||||
compile_gml(PropertiesWindowFontTab.gml PropertiesWindowFontTabGML.h properties_window_font_tab_gml)
|
compile_gml(PropertiesWindowFontTab.gml PropertiesWindowFontTabGML.h properties_window_font_tab_gml)
|
||||||
compile_gml(PropertiesWindowGeneralTab.gml PropertiesWindowGeneralTabGML.h properties_window_general_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(PropertiesWindowImageTab.gml PropertiesWindowImageTabGML.h properties_window_image_tab_gml)
|
||||||
|
compile_gml(PropertiesWindowPDFTab.gml PropertiesWindowPDFTabGML.h properties_window_pdf_tab_gml)
|
||||||
|
|
||||||
set(SOURCES
|
set(SOURCES
|
||||||
DesktopWidget.cpp
|
DesktopWidget.cpp
|
||||||
|
@ -30,7 +31,8 @@ set(GENERATED_SOURCES
|
||||||
PropertiesWindowFontTabGML.h
|
PropertiesWindowFontTabGML.h
|
||||||
PropertiesWindowGeneralTabGML.h
|
PropertiesWindowGeneralTabGML.h
|
||||||
PropertiesWindowImageTabGML.h
|
PropertiesWindowImageTabGML.h
|
||||||
|
PropertiesWindowPDFTabGML.h
|
||||||
)
|
)
|
||||||
|
|
||||||
serenity_app(FileManager ICON app-file-manager)
|
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/PropertiesWindowFontTabGML.h>
|
||||||
#include <Applications/FileManager/PropertiesWindowGeneralTabGML.h>
|
#include <Applications/FileManager/PropertiesWindowGeneralTabGML.h>
|
||||||
#include <Applications/FileManager/PropertiesWindowImageTabGML.h>
|
#include <Applications/FileManager/PropertiesWindowImageTabGML.h>
|
||||||
|
#include <Applications/FileManager/PropertiesWindowPDFTabGML.h>
|
||||||
#include <LibArchive/Zip.h>
|
#include <LibArchive/Zip.h>
|
||||||
#include <LibAudio/Loader.h>
|
#include <LibAudio/Loader.h>
|
||||||
#include <LibCore/Directory.h>
|
#include <LibCore/Directory.h>
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
#include <LibGfx/Font/WOFF/Font.h>
|
#include <LibGfx/Font/WOFF/Font.h>
|
||||||
#include <LibGfx/ICC/Profile.h>
|
#include <LibGfx/ICC/Profile.h>
|
||||||
#include <LibGfx/ICC/Tags.h>
|
#include <LibGfx/ICC/Tags.h>
|
||||||
|
#include <LibPDF/Document.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.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))
|
if (mime_type.starts_with("image/"sv))
|
||||||
return create_image_tab(tab_widget, move(mapped_file), mime_type);
|
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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,6 +456,59 @@ ErrorOr<void> PropertiesWindow::create_image_tab(GUI::TabWidget& tab_widget, Non
|
||||||
return {};
|
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()
|
void PropertiesWindow::update()
|
||||||
{
|
{
|
||||||
m_icon->set_bitmap(GUI::FileIconProvider::icon_for_path(make_full_path(m_name), m_mode).bitmap_for_size(32));
|
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_audio_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>);
|
||||||
ErrorOr<void> create_font_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>, StringView mime_type);
|
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_image_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>, StringView mime_type);
|
||||||
|
ErrorOr<void> create_pdf_tab(GUI::TabWidget&, NonnullRefPtr<Core::MappedFile>);
|
||||||
|
|
||||||
struct PermissionMasks {
|
struct PermissionMasks {
|
||||||
mode_t read;
|
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…
Add table
Add a link
Reference in a new issue