2021-05-10 15:50:15 -03:00
/*
2022-03-05 21:30:55 -03:00
* Copyright ( c ) 2021 - 2022 , Matthew Olsson < mattco @ serenityos . org >
2021-09-13 17:48:22 -03:00
* Copyright ( c ) 2021 , Mustafa Quraish < mustafa @ serenityos . org >
2021-05-10 15:50:15 -03:00
*
* SPDX - License - Identifier : BSD - 2 - Clause
*/
# include "PDFViewerWidget.h"
# include <LibCore/File.h>
2021-09-02 09:22:13 -03:00
# include <LibFileSystemAccessClient/Client.h>
2021-05-10 15:50:15 -03:00
# include <LibGUI/Application.h>
# include <LibGUI/BoxLayout.h>
# include <LibGUI/FilePicker.h>
2021-05-24 02:34:44 -03:00
# include <LibGUI/Label.h>
2021-05-10 15:50:15 -03:00
# include <LibGUI/Menu.h>
# include <LibGUI/Menubar.h>
2021-05-24 18:23:08 -03:00
# include <LibGUI/MessageBox.h>
2021-05-24 01:34:06 -03:00
# include <LibGUI/Splitter.h>
2021-05-24 02:34:44 -03:00
# include <LibGUI/Toolbar.h>
# include <LibGUI/ToolbarContainer.h>
2021-05-10 15:50:15 -03:00
PDFViewerWidget : : PDFViewerWidget ( )
{
set_fill_with_background_color ( true ) ;
set_layout < GUI : : VerticalBoxLayout > ( ) ;
2021-05-24 02:34:44 -03:00
create_toolbar ( ) ;
2021-05-24 01:34:06 -03:00
auto & splitter = add < GUI : : HorizontalSplitter > ( ) ;
2021-05-10 15:50:15 -03:00
2021-05-24 01:34:06 -03:00
m_sidebar = splitter . add < SidebarWidget > ( ) ;
m_sidebar - > set_fixed_width ( 0 ) ;
m_viewer = splitter . add < PDFViewer > ( ) ;
2021-06-20 16:07:44 -03:00
m_viewer - > on_page_change = [ & ] ( auto new_page ) {
m_page_text_box - > set_current_number ( new_page + 1 ) ;
} ;
2021-05-10 15:50:15 -03:00
}
2021-07-21 16:21:03 -03:00
void PDFViewerWidget : : initialize_menubar ( GUI : : Window & window )
2021-05-10 15:50:15 -03:00
{
2021-07-21 16:21:03 -03:00
auto & file_menu = window . add_menu ( " &File " ) ;
2021-05-10 15:50:15 -03:00
file_menu . add_action ( GUI : : CommonActions : : make_open_action ( [ & ] ( auto & ) {
2022-01-16 22:47:11 -03:00
auto response = FileSystemAccessClient : : Client : : the ( ) . try_open_file ( & window ) ;
if ( response . is_error ( ) )
2021-09-02 09:22:13 -03:00
return ;
2022-01-16 22:47:11 -03:00
open_file ( * response . value ( ) ) ;
2021-05-10 15:50:15 -03:00
} ) ) ;
2021-05-27 14:09:37 -03:00
file_menu . add_separator ( ) ;
2021-05-10 15:50:15 -03:00
file_menu . add_action ( GUI : : CommonActions : : make_quit_action ( [ ] ( auto & ) {
GUI : : Application : : the ( ) - > quit ( ) ;
} ) ) ;
2021-05-27 14:10:34 -03:00
2021-12-27 09:41:01 -03:00
auto & view_menu = window . add_menu ( " &View " ) ;
view_menu . add_action ( * m_toggle_sidebar_action ) ;
2022-01-02 17:58:51 -03:00
view_menu . add_separator ( ) ;
view_menu . add_action ( * m_zoom_in_action ) ;
view_menu . add_action ( * m_zoom_out_action ) ;
view_menu . add_action ( * m_reset_zoom_action ) ;
2021-12-27 09:41:01 -03:00
2021-07-21 16:21:03 -03:00
auto & help_menu = window . add_menu ( " &Help " ) ;
help_menu . add_action ( GUI : : CommonActions : : make_about_action ( " PDF Viewer " , GUI : : Icon : : default_icon ( " app-pdf-viewer " ) , & window ) ) ;
2021-05-24 02:34:44 -03:00
}
2021-05-24 01:34:06 -03:00
2021-05-24 02:34:44 -03:00
void PDFViewerWidget : : create_toolbar ( )
{
auto & toolbar_container = add < GUI : : ToolbarContainer > ( ) ;
auto & toolbar = toolbar_container . add < GUI : : Toolbar > ( ) ;
2021-05-24 01:34:06 -03:00
2021-05-24 02:34:44 -03:00
auto open_outline_action = GUI : : Action : : create (
2021-12-27 09:41:01 -03:00
" Toggle &Sidebar " , { Mod_Ctrl , Key_S } , Gfx : : Bitmap : : try_load_from_file ( " /res/icons/16x16/sidebar.png " ) . release_value_but_fixme_should_propagate_errors ( ) , [ & ] ( auto & ) {
2021-05-24 01:34:06 -03:00
m_sidebar_open = ! m_sidebar_open ;
2021-12-27 09:41:01 -03:00
m_sidebar - > set_fixed_width ( m_sidebar_open ? 200 : 0 ) ;
2021-05-24 01:34:06 -03:00
} ,
nullptr ) ;
2021-05-24 02:34:44 -03:00
open_outline_action - > set_enabled ( false ) ;
m_toggle_sidebar_action = open_outline_action ;
toolbar . add_action ( * open_outline_action ) ;
toolbar . add_separator ( ) ;
2021-11-06 12:25:29 -03:00
m_go_to_prev_page_action = GUI : : Action : : create ( " Go to &Previous Page " , Gfx : : Bitmap : : try_load_from_file ( " /res/icons/16x16/go-up.png " ) . release_value_but_fixme_should_propagate_errors ( ) , [ & ] ( auto & ) {
2021-05-27 14:47:44 -03:00
VERIFY ( m_viewer - > current_page ( ) > 0 ) ;
m_page_text_box - > set_current_number ( m_viewer - > current_page ( ) ) ;
2021-05-24 02:34:44 -03:00
} ) ;
m_go_to_prev_page_action - > set_enabled ( false ) ;
2021-05-24 01:34:06 -03:00
2021-11-06 12:25:29 -03:00
m_go_to_next_page_action = GUI : : Action : : create ( " Go to &Next Page " , Gfx : : Bitmap : : try_load_from_file ( " /res/icons/16x16/go-down.png " ) . release_value_but_fixme_should_propagate_errors ( ) , [ & ] ( auto & ) {
2021-05-27 14:47:44 -03:00
VERIFY ( m_viewer - > current_page ( ) < m_viewer - > document ( ) - > get_page_count ( ) - 1 ) ;
m_page_text_box - > set_current_number ( m_viewer - > current_page ( ) + 2 ) ;
2021-05-24 02:34:44 -03:00
} ) ;
m_go_to_next_page_action - > set_enabled ( false ) ;
2021-05-24 01:34:06 -03:00
2021-05-24 02:34:44 -03:00
toolbar . add_action ( * m_go_to_prev_page_action ) ;
toolbar . add_action ( * m_go_to_next_page_action ) ;
m_page_text_box = toolbar . add < NumericInput > ( ) ;
m_page_text_box - > set_enabled ( false ) ;
m_page_text_box - > set_fixed_width ( 30 ) ;
m_page_text_box - > set_min_number ( 1 ) ;
m_page_text_box - > on_number_changed = [ & ] ( i32 number ) {
2021-05-27 14:47:44 -03:00
auto page_count = m_viewer - > document ( ) - > get_page_count ( ) ;
auto new_page_number = static_cast < u32 > ( number ) ;
VERIFY ( new_page_number > = 1 & & new_page_number < = page_count ) ;
m_viewer - > set_current_page ( new_page_number - 1 ) ;
2021-05-24 02:34:44 -03:00
m_viewer - > update ( ) ;
2021-05-27 14:47:44 -03:00
m_go_to_prev_page_action - > set_enabled ( new_page_number > 1 ) ;
m_go_to_next_page_action - > set_enabled ( new_page_number < page_count ) ;
2021-05-24 02:34:44 -03:00
} ;
m_total_page_label = toolbar . add < GUI : : Label > ( ) ;
2022-01-02 17:58:51 -03:00
m_total_page_label - > set_fixed_width ( 30 ) ;
toolbar . add_separator ( ) ;
m_zoom_in_action = GUI : : CommonActions : : make_zoom_in_action ( [ & ] ( auto & ) {
m_viewer - > zoom_in ( ) ;
} ) ;
m_zoom_out_action = GUI : : CommonActions : : make_zoom_out_action ( [ & ] ( auto & ) {
m_viewer - > zoom_out ( ) ;
} ) ;
m_reset_zoom_action = GUI : : CommonActions : : make_reset_zoom_action ( [ & ] ( auto & ) {
m_viewer - > reset_zoom ( ) ;
} ) ;
2022-01-02 20:24:11 -03:00
m_rotate_counterclockwise_action = GUI : : CommonActions : : make_rotate_counterclockwise_action ( [ & ] ( auto & ) {
m_viewer - > rotate ( - 90 ) ;
} ) ;
m_rotate_clockwise_action = GUI : : CommonActions : : make_rotate_clockwise_action ( [ & ] ( auto & ) {
m_viewer - > rotate ( 90 ) ;
} ) ;
2022-01-02 17:58:51 -03:00
m_zoom_in_action - > set_enabled ( false ) ;
m_zoom_out_action - > set_enabled ( false ) ;
m_reset_zoom_action - > set_enabled ( false ) ;
2022-01-02 20:24:11 -03:00
m_rotate_counterclockwise_action - > set_enabled ( false ) ;
m_rotate_clockwise_action - > set_enabled ( false ) ;
2022-01-02 17:58:51 -03:00
toolbar . add_action ( * m_zoom_in_action ) ;
toolbar . add_action ( * m_zoom_out_action ) ;
toolbar . add_action ( * m_reset_zoom_action ) ;
2022-01-02 20:24:11 -03:00
toolbar . add_action ( * m_rotate_counterclockwise_action ) ;
toolbar . add_action ( * m_rotate_clockwise_action ) ;
2021-05-10 15:50:15 -03:00
}
2022-01-16 22:47:11 -03:00
void PDFViewerWidget : : open_file ( Core : : File & file )
2021-05-10 15:50:15 -03:00
{
2022-01-16 22:47:11 -03:00
window ( ) - > set_title ( String : : formatted ( " {} - PDF Viewer " , file . filename ( ) ) ) ;
2021-05-24 18:23:08 -03:00
2022-01-16 22:47:11 -03:00
m_buffer = file . read_all ( ) ;
2022-03-05 21:30:55 -03:00
auto maybe_document = PDF : : Document : : create ( m_buffer ) ;
if ( maybe_document . is_error ( ) ) {
auto error = maybe_document . release_error ( ) ;
GUI : : MessageBox : : show_error ( nullptr , String : : formatted ( " Couldn't load PDF {}: \n {} " , file . filename ( ) , error . message ( ) ) ) ;
2021-05-24 18:23:08 -03:00
return ;
}
2022-03-05 21:30:55 -03:00
auto document = maybe_document . release_value ( ) ;
2022-03-30 22:08:02 -03:00
if ( auto sh = document - > security_handler ( ) ; sh & & ! sh - > has_user_password ( ) ) {
2022-03-20 18:24:23 -03:00
// FIXME: Prompt the user for a password
VERIFY_NOT_REACHED ( ) ;
}
auto result = document - > initialize ( ) ;
if ( result . is_error ( ) ) {
auto error = result . release_error ( ) ;
GUI : : MessageBox : : show_error ( nullptr , String : : formatted ( " Couldn't load PDF {}: \n {} " , file . filename ( ) , error . message ( ) ) ) ;
return ;
}
2021-05-24 01:34:06 -03:00
m_viewer - > set_document ( document ) ;
2021-05-24 02:34:44 -03:00
m_total_page_label - > set_text ( String : : formatted ( " of {} " , document - > get_page_count ( ) ) ) ;
m_page_text_box - > set_enabled ( true ) ;
2021-05-27 14:49:49 -03:00
m_page_text_box - > set_current_number ( 1 , false ) ;
2021-05-24 02:34:44 -03:00
m_page_text_box - > set_max_number ( document - > get_page_count ( ) ) ;
2021-05-27 14:47:44 -03:00
m_go_to_prev_page_action - > set_enabled ( false ) ;
m_go_to_next_page_action - > set_enabled ( document - > get_page_count ( ) > 1 ) ;
2021-05-24 02:34:44 -03:00
m_toggle_sidebar_action - > set_enabled ( true ) ;
2022-01-02 17:58:51 -03:00
m_zoom_in_action - > set_enabled ( true ) ;
m_zoom_out_action - > set_enabled ( true ) ;
m_reset_zoom_action - > set_enabled ( true ) ;
2022-01-02 20:24:11 -03:00
m_rotate_counterclockwise_action - > set_enabled ( true ) ;
m_rotate_clockwise_action - > set_enabled ( true ) ;
2021-05-24 01:34:06 -03:00
if ( document - > outline ( ) ) {
auto outline = document - > outline ( ) ;
m_sidebar - > set_outline ( outline . release_nonnull ( ) ) ;
m_sidebar - > set_fixed_width ( 200 ) ;
m_sidebar_open = true ;
} else {
m_sidebar - > set_outline ( { } ) ;
m_sidebar - > set_fixed_width ( 0 ) ;
m_sidebar_open = false ;
}
2021-05-10 15:50:15 -03:00
}