2020-01-18 11:38:21 +03:00
/*
* Copyright ( c ) 2018 - 2020 , Andreas Kling < kling @ serenityos . org >
2021-09-03 21:36:13 +03:00
* Copyright ( c ) 2021 , Mohsan Ali < mohsan0073 @ gmail . com >
2023-03-23 23:51:42 +03:00
* Copyright ( c ) 2023 , Caoimhe Byrne < caoimhebyrne06 @ gmail . com >
2020-01-18 11:38:21 +03:00
*
2021-04-22 11:24:48 +03:00
* SPDX - License - Identifier : BSD - 2 - Clause
2020-01-18 11:38:21 +03:00
*/
2023-01-29 00:18:33 +03:00
# include "MainWidget.h"
2021-05-14 19:37:08 +03:00
# include "ViewWidget.h"
2023-02-06 20:51:02 +03:00
# include <LibConfig/Client.h>
2020-04-12 16:24:13 +03:00
# include <LibCore/ArgsParser.h>
2021-11-24 02:06:40 +03:00
# include <LibCore/System.h>
2021-03-12 15:25:38 +03:00
# include <LibDesktop/Launcher.h>
2023-03-23 23:51:42 +03:00
# include <LibFileSystemAccessClient/Client.h>
2020-02-06 22:33:02 +03:00
# include <LibGUI/Action.h>
2021-12-29 18:37:04 +03:00
# include <LibGUI/ActionGroup.h>
2020-02-06 22:33:02 +03:00
# include <LibGUI/Application.h>
# include <LibGUI/BoxLayout.h>
2020-09-05 17:53:30 +03:00
# include <LibGUI/Clipboard.h>
2020-06-18 00:25:57 +03:00
# include <LibGUI/Desktop.h>
2020-04-05 21:25:14 +03:00
# include <LibGUI/FilePicker.h>
2020-02-06 22:33:02 +03:00
# include <LibGUI/Label.h>
# include <LibGUI/Menu.h>
2021-04-13 17:18:20 +03:00
# include <LibGUI/Menubar.h>
2020-04-12 16:40:05 +03:00
# include <LibGUI/MessageBox.h>
2021-04-13 17:18:20 +03:00
# include <LibGUI/Toolbar.h>
# include <LibGUI/ToolbarContainer.h>
2020-02-06 22:33:02 +03:00
# include <LibGUI/Window.h>
2020-02-15 01:02:47 +03:00
# include <LibGfx/Bitmap.h>
2020-04-23 19:21:23 +03:00
# include <LibGfx/Palette.h>
2020-06-18 16:00:19 +03:00
# include <LibGfx/Rect.h>
2021-11-24 02:06:40 +03:00
# include <LibMain/Main.h>
2024-03-18 06:22:27 +03:00
# include <LibURL/URL.h>
2020-08-04 15:23:06 +03:00
# include <serenity.h>
2020-04-12 16:40:05 +03:00
# include <string.h>
2019-03-21 05:57:42 +03:00
2021-05-14 19:37:08 +03:00
using namespace ImageViewer ;
2021-11-24 02:06:40 +03:00
ErrorOr < int > serenity_main ( Main : : Arguments arguments )
2019-03-21 05:57:42 +03:00
{
2021-11-28 01:26:34 +03:00
TRY ( Core : : System : : pledge ( " stdio recvfd sendfd rpath wpath cpath unix thread " ) ) ;
2020-01-12 04:02:44 +03:00
2023-05-05 07:24:53 +03:00
auto app = TRY ( GUI : : Application : : create ( arguments ) ) ;
2019-03-21 05:57:42 +03:00
2023-04-03 00:29:32 +03:00
Config : : pledge_domains ( { " ImageViewer " , " WindowManager " } ) ;
2023-02-06 20:51:02 +03:00
2023-08-07 12:12:38 +03:00
app - > set_config_domain ( " ImageViewer " _string ) ;
2023-02-06 20:51:02 +03:00
2021-11-24 02:23:00 +03:00
TRY ( Desktop : : Launcher : : add_allowed_handler_with_any_url ( " /bin/ImageViewer " ) ) ;
2023-04-08 12:48:22 +03:00
TRY ( Desktop : : Launcher : : add_allowed_handler_with_only_specific_urls ( " /bin/Help " , { URL : : create_with_file_scheme ( " /usr/share/man/man1/Applications/ImageViewer.md " ) } ) ) ;
2021-11-24 02:23:00 +03:00
TRY ( Desktop : : Launcher : : seal_allowlist ( ) ) ;
2021-03-12 15:25:38 +03:00
2023-03-23 23:51:42 +03:00
// FIXME: Use unveil when we solve the issue with ViewWidget::load_files_from_directory, an explanation is given in ViewWidget.cpp
// TRY(Core::System::unveil("/tmp/session/%sid/portal/filesystemaccess", "rw"));
// TRY(Core::System::unveil("/tmp/session/%sid/portal/image", "rw"));
// TRY(Core::System::unveil("/res", "r"));
// TRY(Core::System::unveil(nullptr, nullptr));
2024-03-06 19:44:11 +03:00
auto app_icon = GUI : : Icon : : default_icon ( " app-image-viewer " sv ) ;
2020-11-02 22:30:17 +03:00
2023-02-28 23:41:43 +03:00
StringView path ;
2020-04-12 16:24:13 +03:00
Core : : ArgsParser args_parser ;
args_parser . add_positional_argument ( path , " The image file to be displayed. " , " file " , Core : : ArgsParser : : Required : : No ) ;
2021-11-24 02:06:40 +03:00
args_parser . parse ( arguments ) ;
2019-03-21 05:57:42 +03:00
2023-09-16 14:51:33 +03:00
auto window = GUI : : Window : : construct ( ) ;
2020-04-05 21:25:14 +03:00
window - > set_double_buffering_enabled ( true ) ;
2020-08-01 01:12:11 +03:00
window - > resize ( 300 , 200 ) ;
2020-11-02 22:30:17 +03:00
window - > set_icon ( app_icon . bitmap_for_size ( 16 ) ) ;
2021-05-14 19:34:44 +03:00
window - > set_title ( " Image Viewer " ) ;
2020-04-05 21:25:14 +03:00
2023-09-19 03:13:48 +03:00
auto root_widget = window - > set_main_widget < MainWidget > ( ) ;
2019-03-21 15:31:47 +03:00
2023-09-23 00:28:59 +03:00
auto & toolbar_container = root_widget - > add < GUI : : ToolbarContainer > ( ) ;
auto & main_toolbar = toolbar_container . add < GUI : : Toolbar > ( ) ;
2020-04-12 17:40:34 +03:00
2023-09-23 00:28:59 +03:00
auto & widget = root_widget - > add < ViewWidget > ( ) ;
widget . on_scale_change = [ & ] ( float scale ) {
if ( ! widget . image ( ) ) {
2021-05-14 19:34:44 +03:00
window - > set_title ( " Image Viewer " ) ;
2020-06-18 16:00:19 +03:00
return ;
}
2023-12-16 17:19:34 +03:00
window - > set_title ( ByteString : : formatted ( " {} {} {}% - Image Viewer " , widget . path ( ) , widget . image ( ) - > size ( ) . to_byte_string ( ) , ( int ) ( scale * 100 ) ) ) ;
2020-06-18 16:00:19 +03:00
2023-09-23 00:28:59 +03:00
if ( ! widget . scaled_for_first_image ( ) ) {
widget . set_scaled_for_first_image ( true ) ;
widget . resize_window ( ) ;
2021-07-08 01:04:50 +03:00
}
2019-06-23 17:35:43 +03:00
} ;
2023-09-23 00:28:59 +03:00
widget . on_drop = [ & ] ( auto & event ) {
2021-03-12 15:25:38 +03:00
if ( ! event . mime_data ( ) . has_urls ( ) )
return ;
2020-04-05 21:25:14 +03:00
2021-03-12 15:25:38 +03:00
auto urls = event . mime_data ( ) . urls ( ) ;
2020-04-05 21:25:14 +03:00
2021-03-12 15:25:38 +03:00
if ( urls . is_empty ( ) )
return ;
2021-07-12 18:58:33 +03:00
window - > move_to_front ( ) ;
2021-09-03 21:36:13 +03:00
2023-04-14 22:12:03 +03:00
auto path = urls . first ( ) . serialize_path ( ) ;
2023-03-23 23:51:42 +03:00
auto result = FileSystemAccessClient : : Client : : the ( ) . request_file_read_only_approved ( window , path ) ;
if ( result . is_error ( ) )
return ;
auto value = result . release_value ( ) ;
2024-01-23 19:05:59 +03:00
widget . open_file ( MUST ( String : : from_byte_string ( value . filename ( ) ) ) , value . stream ( ) ) ;
2021-03-12 15:25:38 +03:00
for ( size_t i = 1 ; i < urls . size ( ) ; + + i ) {
2023-04-14 22:12:03 +03:00
Desktop : : Launcher : : open ( URL : : create_with_file_scheme ( urls [ i ] . serialize_path ( ) . characters ( ) ) , " /bin/ImageViewer " ) ;
2020-04-05 21:25:14 +03:00
}
} ;
2023-09-23 00:28:59 +03:00
widget . on_doubleclick = [ & ] {
2020-06-16 10:47:47 +03:00
window - > set_fullscreen ( ! window - > is_fullscreen ( ) ) ;
2023-09-23 00:28:59 +03:00
toolbar_container . set_visible ( ! window - > is_fullscreen ( ) ) ;
widget . set_frame_style ( window - > is_fullscreen ( ) ? Gfx : : FrameStyle : : NoFrame : Gfx : : FrameStyle : : SunkenContainer ) ;
2020-06-16 10:47:47 +03:00
} ;
2020-04-05 21:25:14 +03:00
2020-04-12 14:35:15 +03:00
// Actions
2020-04-12 16:40:05 +03:00
auto open_action = GUI : : CommonActions : : make_open_action (
[ & ] ( auto & ) {
2023-05-28 18:57:02 +03:00
FileSystemAccessClient : : OpenFileOptions options {
. window_title = " Open Image " sv ,
. allowed_file_types = Vector { GUI : : FileTypeFilter : : image_files ( ) , GUI : : FileTypeFilter : : all_files ( ) } ,
} ;
auto result = FileSystemAccessClient : : Client : : the ( ) . open_file ( window , options ) ;
2023-03-23 23:51:42 +03:00
if ( result . is_error ( ) )
return ;
auto value = result . release_value ( ) ;
2024-01-23 19:05:59 +03:00
widget . open_file ( MUST ( String : : from_byte_string ( value . filename ( ) ) ) , value . stream ( ) ) ;
2020-04-12 16:40:05 +03:00
} ) ;
auto delete_action = GUI : : CommonActions : : make_delete_action (
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
auto path = widget . path ( ) ;
2020-04-12 17:40:34 +03:00
if ( path . is_empty ( ) )
2020-04-12 16:40:05 +03:00
return ;
2020-07-16 05:45:11 +03:00
auto msgbox_result = GUI : : MessageBox : : show ( window ,
2023-12-16 17:19:34 +03:00
ByteString : : formatted ( " Are you sure you want to delete {}? " , path ) ,
2023-05-22 20:07:09 +03:00
" Confirm Deletion " sv ,
2020-04-12 16:40:05 +03:00
GUI : : MessageBox : : Type : : Warning ,
2020-07-16 05:45:11 +03:00
GUI : : MessageBox : : InputType : : OKCancel ) ;
2020-04-12 16:40:05 +03:00
2022-05-13 15:10:27 +03:00
if ( msgbox_result = = GUI : : MessageBox : : ExecResult : : Cancel )
2020-04-12 16:40:05 +03:00
return ;
2023-09-23 00:28:59 +03:00
auto unlinked_or_error = Core : : System : : unlink ( widget . path ( ) ) ;
2021-12-29 23:47:38 +03:00
if ( unlinked_or_error . is_error ( ) ) {
2020-07-16 05:45:11 +03:00
GUI : : MessageBox : : show ( window ,
2023-12-16 17:19:34 +03:00
ByteString : : formatted ( " unlink({}) failed: {} " , path , unlinked_or_error . error ( ) ) ,
2023-05-22 20:07:09 +03:00
" Delete Failed " sv ,
2020-07-16 05:45:11 +03:00
GUI : : MessageBox : : Type : : Error ) ;
2020-04-12 16:40:05 +03:00
return ;
}
2023-09-23 00:28:59 +03:00
widget . clear ( ) ;
2020-04-12 16:40:05 +03:00
} ) ;
auto quit_action = GUI : : CommonActions : : make_quit_action (
[ & ] ( auto & ) {
2020-07-04 15:05:19 +03:00
app - > quit ( ) ;
2020-04-12 16:40:05 +03:00
} ) ;
2022-01-03 13:19:05 +03:00
auto rotate_counterclockwise_action = GUI : : CommonActions : : make_rotate_counterclockwise_action ( [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . rotate ( Gfx : : RotationDirection : : CounterClockwise ) ;
2022-01-03 13:19:05 +03:00
} ) ;
2020-04-12 16:03:31 +03:00
2022-01-03 13:19:05 +03:00
auto rotate_clockwise_action = GUI : : CommonActions : : make_rotate_clockwise_action ( [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . rotate ( Gfx : : RotationDirection : : Clockwise ) ;
2022-01-03 13:19:05 +03:00
} ) ;
2020-04-12 16:03:31 +03:00
2023-01-20 22:06:05 +03:00
auto vertical_flip_action = GUI : : Action : : create ( " Flip &Vertically " , { Mod_None , Key_V } , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/edit-flip-vertical.png " sv ) ) ,
2020-04-12 16:03:31 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . flip ( Gfx : : Orientation : : Vertical ) ;
2020-04-12 16:03:31 +03:00
} ) ;
2023-01-20 22:06:05 +03:00
auto horizontal_flip_action = GUI : : Action : : create ( " Flip &Horizontally " , { Mod_None , Key_H } , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/edit-flip-horizontal.png " sv ) ) ,
2020-04-12 16:03:31 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . flip ( Gfx : : Orientation : : Horizontal ) ;
2020-04-12 16:03:31 +03:00
} ) ;
2023-01-20 22:06:05 +03:00
auto desktop_wallpaper_action = GUI : : Action : : create ( " Set as Desktop &Wallpaper " , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/app-display-settings.png " sv ) ) ,
2020-06-18 00:25:57 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
if ( ! GUI : : Desktop : : the ( ) . set_wallpaper ( widget . image ( ) - > bitmap ( GUI : : Desktop : : the ( ) . rect ( ) . size ( ) ) . release_value_but_fixme_should_propagate_errors ( ) , widget . path ( ) ) ) {
2021-12-30 00:07:30 +03:00
GUI : : MessageBox : : show ( window ,
2023-12-16 17:19:34 +03:00
ByteString : : formatted ( " set_wallpaper({}) failed " , widget . path ( ) ) ,
2022-07-11 20:32:29 +03:00
" Could not set wallpaper " sv ,
2021-12-30 00:07:30 +03:00
GUI : : MessageBox : : Type : : Error ) ;
}
2020-06-18 00:25:57 +03:00
} ) ;
2023-01-20 22:06:05 +03:00
auto go_first_action = GUI : : Action : : create ( " &Go to First " , { Mod_None , Key_Home } , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/go-first.png " sv ) ) ,
2020-04-12 14:35:15 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . navigate ( ViewWidget : : Directions : : First ) ;
2020-04-12 14:35:15 +03:00
} ) ;
2023-01-29 00:30:52 +03:00
auto go_back_action = GUI : : Action : : create ( " Go to &Previous " , { Mod_None , Key_Left } , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/go-back.png " sv ) ) ,
2020-04-12 14:35:15 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . navigate ( ViewWidget : : Directions : : Back ) ;
2020-04-12 14:35:15 +03:00
} ) ;
2023-01-29 00:30:52 +03:00
auto go_forward_action = GUI : : Action : : create ( " Go to &Next " , { Mod_None , Key_Right } , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/go-forward.png " sv ) ) ,
2020-04-12 14:35:15 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . navigate ( ViewWidget : : Directions : : Forward ) ;
2020-04-12 14:35:15 +03:00
} ) ;
2023-01-20 22:06:05 +03:00
auto go_last_action = GUI : : Action : : create ( " Go to &Last " , { Mod_None , Key_End } , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/go-last.png " sv ) ) ,
2020-04-12 14:35:15 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . navigate ( ViewWidget : : Directions : : Last ) ;
2020-04-12 14:35:15 +03:00
} ) ;
2021-05-16 11:01:29 +03:00
auto full_screen_action = GUI : : CommonActions : : make_fullscreen_action (
2020-04-12 16:24:31 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . on_doubleclick ( ) ;
2020-04-12 16:24:31 +03:00
} ) ;
2021-05-15 21:35:52 +03:00
auto zoom_in_action = GUI : : CommonActions : : make_zoom_in_action (
2020-04-12 16:24:31 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . set_scale ( widget . scale ( ) * 1.44f ) ;
2021-05-15 21:35:52 +03:00
} ,
window ) ;
2020-04-12 16:24:31 +03:00
2021-05-15 21:35:52 +03:00
auto reset_zoom_action = GUI : : CommonActions : : make_reset_zoom_action (
2020-04-12 16:24:31 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . set_scale ( 1.f ) ;
2021-05-15 21:35:52 +03:00
} ,
window ) ;
2020-04-12 16:24:31 +03:00
2022-01-21 11:56:32 +03:00
auto fit_image_to_view_action = GUI : : Action : : create (
2023-01-20 22:06:05 +03:00
" Fit Image To &View " , TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/fit-image-to-view.png " sv ) ) , [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . fit_content_to_view ( ) ;
2022-01-21 11:56:32 +03:00
} ) ;
2021-05-15 21:35:52 +03:00
auto zoom_out_action = GUI : : CommonActions : : make_zoom_out_action (
2020-04-12 16:24:31 +03:00
[ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . set_scale ( widget . scale ( ) / 1.44f ) ;
2021-05-15 21:35:52 +03:00
} ,
window ) ;
2020-04-12 17:59:24 +03:00
2023-05-22 20:07:09 +03:00
auto hide_show_toolbar_action = GUI : : Action : : create_checkable ( " &Toolbar " , { Mod_Ctrl , Key_T } ,
[ & ] ( auto & action ) {
2023-09-23 00:28:59 +03:00
toolbar_container . set_visible ( action . is_checked ( ) ) ;
2020-04-12 17:40:34 +03:00
} ) ;
2023-05-22 20:07:09 +03:00
hide_show_toolbar_action - > set_checked ( true ) ;
2020-04-12 17:40:34 +03:00
2020-09-05 17:53:30 +03:00
auto copy_action = GUI : : CommonActions : : make_copy_action ( [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
if ( widget . image ( ) )
GUI : : Clipboard : : the ( ) . set_bitmap ( * widget . image ( ) - > bitmap ( { } ) . release_value_but_fixme_should_propagate_errors ( ) ) ;
2020-09-05 17:53:30 +03:00
} ) ;
2021-12-29 18:37:04 +03:00
auto nearest_neighbor_action = GUI : : Action : : create_checkable ( " &Nearest Neighbor " , [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . set_scaling_mode ( Gfx : : Painter : : ScalingMode : : NearestNeighbor ) ;
2021-12-29 18:37:04 +03:00
} ) ;
nearest_neighbor_action - > set_checked ( true ) ;
2022-06-03 21:12:25 +03:00
auto smooth_pixels_action = GUI : : Action : : create_checkable ( " &Smooth Pixels " , [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . set_scaling_mode ( Gfx : : Painter : : ScalingMode : : SmoothPixels ) ;
2022-06-03 21:12:25 +03:00
} ) ;
2021-12-29 18:37:04 +03:00
auto bilinear_action = GUI : : Action : : create_checkable ( " &Bilinear " , [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . set_scaling_mode ( Gfx : : Painter : : ScalingMode : : BilinearBlend ) ;
2021-12-29 18:37:04 +03:00
} ) ;
2023-05-19 01:28:51 +03:00
auto box_sampling_action = GUI : : Action : : create_checkable ( " B&ox Sampling " , [ & ] ( auto & ) {
2023-09-23 00:28:59 +03:00
widget . set_scaling_mode ( Gfx : : Painter : : ScalingMode : : BoxSampling ) ;
2023-05-19 01:28:51 +03:00
} ) ;
2023-09-23 00:28:59 +03:00
widget . on_image_change = [ & ] ( Image const * image ) {
2023-07-08 03:34:25 +03:00
bool should_enable_image_actions = ( image ! = nullptr ) ;
2023-09-23 00:28:59 +03:00
bool should_enable_forward_actions = ( widget . is_next_available ( ) & & should_enable_image_actions ) ;
bool should_enable_backward_actions = ( widget . is_previous_available ( ) & & should_enable_image_actions ) ;
2021-05-16 11:01:29 +03:00
delete_action - > set_enabled ( should_enable_image_actions ) ;
2022-01-03 13:19:05 +03:00
rotate_counterclockwise_action - > set_enabled ( should_enable_image_actions ) ;
rotate_clockwise_action - > set_enabled ( should_enable_image_actions ) ;
2021-05-16 11:01:29 +03:00
vertical_flip_action - > set_enabled ( should_enable_image_actions ) ;
horizontal_flip_action - > set_enabled ( should_enable_image_actions ) ;
desktop_wallpaper_action - > set_enabled ( should_enable_image_actions ) ;
2021-09-03 21:36:13 +03:00
go_first_action - > set_enabled ( should_enable_backward_actions ) ;
go_back_action - > set_enabled ( should_enable_backward_actions ) ;
go_forward_action - > set_enabled ( should_enable_forward_actions ) ;
go_last_action - > set_enabled ( should_enable_forward_actions ) ;
2021-05-16 11:01:29 +03:00
zoom_in_action - > set_enabled ( should_enable_image_actions ) ;
reset_zoom_action - > set_enabled ( should_enable_image_actions ) ;
zoom_out_action - > set_enabled ( should_enable_image_actions ) ;
if ( ! should_enable_image_actions ) {
window - > set_title ( " Image Viewer " ) ;
}
} ;
2023-09-23 00:28:59 +03:00
main_toolbar . add_action ( open_action ) ;
main_toolbar . add_action ( delete_action ) ;
main_toolbar . add_separator ( ) ;
main_toolbar . add_action ( go_first_action ) ;
main_toolbar . add_action ( go_back_action ) ;
main_toolbar . add_action ( go_forward_action ) ;
main_toolbar . add_action ( go_last_action ) ;
main_toolbar . add_separator ( ) ;
main_toolbar . add_action ( zoom_in_action ) ;
main_toolbar . add_action ( reset_zoom_action ) ;
main_toolbar . add_action ( zoom_out_action ) ;
2021-12-30 00:19:48 +03:00
2023-08-14 11:44:42 +03:00
auto file_menu = window - > add_menu ( " &File " _string ) ;
2023-08-14 11:14:27 +03:00
file_menu - > add_action ( open_action ) ;
file_menu - > add_action ( delete_action ) ;
2023-08-14 08:19:40 +03:00
file_menu - > add_separator ( ) ;
2023-02-06 20:51:02 +03:00
2023-08-14 11:16:18 +03:00
file_menu - > add_recent_files_list ( [ & ] ( auto & action ) {
2023-02-06 20:51:02 +03:00
auto path = action . text ( ) ;
2023-03-23 23:51:42 +03:00
auto result = FileSystemAccessClient : : Client : : the ( ) . request_file_read_only_approved ( window , path ) ;
if ( result . is_error ( ) )
return ;
auto value = result . release_value ( ) ;
2024-01-23 19:05:59 +03:00
widget . open_file ( MUST ( String : : from_byte_string ( value . filename ( ) ) ) , value . stream ( ) ) ;
2023-08-14 11:16:18 +03:00
} ) ;
2023-02-06 20:51:02 +03:00
2023-08-14 11:14:27 +03:00
file_menu - > add_action ( quit_action ) ;
2021-12-30 00:19:48 +03:00
2023-08-14 11:44:42 +03:00
auto image_menu = window - > add_menu ( " &Image " _string ) ;
2023-08-14 11:14:27 +03:00
image_menu - > add_action ( rotate_counterclockwise_action ) ;
image_menu - > add_action ( rotate_clockwise_action ) ;
image_menu - > add_action ( vertical_flip_action ) ;
image_menu - > add_action ( horizontal_flip_action ) ;
2023-08-14 08:19:40 +03:00
image_menu - > add_separator ( ) ;
2023-08-14 11:14:27 +03:00
image_menu - > add_action ( desktop_wallpaper_action ) ;
2021-12-30 00:19:48 +03:00
2023-08-14 11:44:42 +03:00
auto navigate_menu = window - > add_menu ( " &Navigate " _string ) ;
2023-08-14 11:14:27 +03:00
navigate_menu - > add_action ( go_first_action ) ;
navigate_menu - > add_action ( go_back_action ) ;
navigate_menu - > add_action ( go_forward_action ) ;
navigate_menu - > add_action ( go_last_action ) ;
2021-12-30 00:19:48 +03:00
2023-08-14 11:44:42 +03:00
auto view_menu = window - > add_menu ( " &View " _string ) ;
2023-08-14 11:14:27 +03:00
view_menu - > add_action ( full_screen_action ) ;
2023-08-14 08:19:40 +03:00
view_menu - > add_separator ( ) ;
2023-08-14 11:14:27 +03:00
view_menu - > add_action ( zoom_in_action ) ;
view_menu - > add_action ( reset_zoom_action ) ;
view_menu - > add_action ( fit_image_to_view_action ) ;
view_menu - > add_action ( zoom_out_action ) ;
2023-08-14 08:19:40 +03:00
view_menu - > add_separator ( ) ;
2021-12-30 00:19:48 +03:00
2023-08-14 10:04:41 +03:00
auto scaling_mode_menu = view_menu - > add_submenu ( " &Scaling Mode " _string ) ;
2023-01-20 22:06:05 +03:00
scaling_mode_menu - > set_icon ( TRY ( Gfx : : Bitmap : : load_from_file ( " /res/icons/16x16/scale.png " sv ) ) ) ;
2021-12-29 18:37:04 +03:00
auto scaling_mode_group = make < GUI : : ActionGroup > ( ) ;
scaling_mode_group - > set_exclusive ( true ) ;
scaling_mode_group - > add_action ( * nearest_neighbor_action ) ;
2022-06-03 21:12:25 +03:00
scaling_mode_group - > add_action ( * smooth_pixels_action ) ;
2021-12-29 18:37:04 +03:00
scaling_mode_group - > add_action ( * bilinear_action ) ;
2023-05-19 01:28:51 +03:00
scaling_mode_group - > add_action ( * box_sampling_action ) ;
2021-12-29 18:37:04 +03:00
2023-08-14 11:14:27 +03:00
scaling_mode_menu - > add_action ( nearest_neighbor_action ) ;
scaling_mode_menu - > add_action ( smooth_pixels_action ) ;
scaling_mode_menu - > add_action ( bilinear_action ) ;
scaling_mode_menu - > add_action ( box_sampling_action ) ;
2021-12-29 18:37:04 +03:00
2023-08-14 08:19:40 +03:00
view_menu - > add_separator ( ) ;
2023-08-14 11:14:27 +03:00
view_menu - > add_action ( hide_show_toolbar_action ) ;
2020-04-12 16:24:31 +03:00
2023-08-14 11:44:42 +03:00
auto help_menu = window - > add_menu ( " &Help " _string ) ;
2023-08-14 11:14:27 +03:00
help_menu - > add_action ( GUI : : CommonActions : : make_command_palette_action ( window ) ) ;
help_menu - > add_action ( GUI : : CommonActions : : make_help_action ( [ ] ( auto & ) {
2023-04-08 12:48:22 +03:00
Desktop : : Launcher : : open ( URL : : create_with_file_scheme ( " /usr/share/man/man1/Applications/ImageViewer.md " ) , " /bin/Help " ) ;
2023-08-14 11:14:27 +03:00
} ) ) ;
2023-09-13 22:34:46 +03:00
help_menu - > add_action ( GUI : : CommonActions : : make_about_action ( " Image Viewer " _string , app_icon , window ) ) ;
2020-04-05 21:25:14 +03:00
2023-03-23 23:51:42 +03:00
window - > show ( ) ;
// We must do this here and not any earlier, as we need a visible window to call FileSystemAccessClient::Client::request_file_read_only_approved();
2020-04-12 16:24:13 +03:00
if ( path ! = nullptr ) {
2023-03-23 23:51:42 +03:00
auto result = FileSystemAccessClient : : Client : : the ( ) . request_file_read_only_approved ( window , path ) ;
if ( result . is_error ( ) )
return 1 ;
auto value = result . release_value ( ) ;
2024-01-23 19:05:59 +03:00
widget . open_file ( MUST ( String : : from_byte_string ( value . filename ( ) ) ) , value . stream ( ) ) ;
2021-05-16 11:01:29 +03:00
} else {
2023-09-23 00:28:59 +03:00
widget . clear ( ) ;
2020-04-12 16:24:13 +03:00
}
2020-07-04 15:05:19 +03:00
return app - > exec ( ) ;
2019-03-21 05:57:42 +03:00
}