@@ -234,6 +234,8 @@ pub enum PreviewKind {
234
234
235
235
#[ derive( Copy , Clone , Debug , Eq , PartialEq ) ]
236
236
pub enum NavMenuAction {
237
+ Open ( segmented_button:: Entity ) ,
238
+ OpenWith ( segmented_button:: Entity ) ,
237
239
OpenInNewTab ( segmented_button:: Entity ) ,
238
240
OpenInNewWindow ( segmented_button:: Entity ) ,
239
241
Preview ( segmented_button:: Entity ) ,
@@ -525,6 +527,69 @@ pub struct App {
525
527
}
526
528
527
529
impl App {
530
+ fn open_file ( & mut self , path : & PathBuf ) {
531
+ let mut found_desktop_exec = false ;
532
+ let mime = mime_icon:: mime_for_path ( path) ;
533
+ if mime == "application/x-desktop" {
534
+ match freedesktop_entry_parser:: parse_entry ( path) {
535
+ Ok ( entry) => match entry. section ( "Desktop Entry" ) . attr ( "Exec" ) {
536
+ Some ( exec) => match mime_app:: exec_to_command ( exec, None ) {
537
+ Some ( mut command) => match spawn_detached ( & mut command) {
538
+ Ok ( ( ) ) => {
539
+ found_desktop_exec = true ;
540
+ }
541
+ Err ( err) => {
542
+ log:: warn!( "failed to execute {:?}: {}" , path, err) ;
543
+ }
544
+ } ,
545
+ None => {
546
+ log:: warn!( "failed to parse {:?}: invalid Desktop Entry/Exec" , path) ;
547
+ }
548
+ } ,
549
+ None => {
550
+ log:: warn!( "failed to parse {:?}: missing Desktop Entry/Exec" , path) ;
551
+ }
552
+ } ,
553
+ Err ( err) => {
554
+ log:: warn!( "failed to parse {:?}: {}" , path, err) ;
555
+ }
556
+ }
557
+ } else if mime == "application/x-executable" || mime == "application/vnd.appimage" {
558
+ let mut command = std:: process:: Command :: new ( path) ;
559
+ match spawn_detached ( & mut command) {
560
+ Ok ( ( ) ) => { }
561
+ Err ( err) => match err. kind ( ) {
562
+ io:: ErrorKind :: PermissionDenied => {
563
+ // If permission is denied, try marking as executable, then running
564
+ self . dialog_pages
565
+ . push_back ( DialogPage :: SetExecutableAndLaunch {
566
+ path : path. to_path_buf ( ) ,
567
+ } ) ;
568
+ }
569
+ _ => {
570
+ log:: warn!( "failed to execute {:?}: {}" , path, err) ;
571
+ }
572
+ } ,
573
+ }
574
+ found_desktop_exec = true ;
575
+ }
576
+ if !found_desktop_exec {
577
+ match open:: that_detached ( path) {
578
+ Ok ( ( ) ) => {
579
+ let _ = recently_used_xbel:: update_recently_used (
580
+ path,
581
+ App :: APP_ID . to_string ( ) ,
582
+ "cosmic-files" . to_string ( ) ,
583
+ None ,
584
+ ) ;
585
+ }
586
+ Err ( err) => {
587
+ log:: warn!( "failed to open {:?}: {}" , path, err) ;
588
+ }
589
+ }
590
+ }
591
+ }
592
+
528
593
fn open_tab_entity (
529
594
& mut self ,
530
595
location : Location ,
@@ -1364,14 +1429,28 @@ impl Application for App {
1364
1429
1365
1430
let mut items = Vec :: new ( ) ;
1366
1431
1367
- items. push ( cosmic:: widget:: menu:: Item :: Button (
1368
- fl ! ( "open-in-new-tab" ) ,
1369
- NavMenuAction :: OpenInNewTab ( entity) ,
1370
- ) ) ;
1371
- items. push ( cosmic:: widget:: menu:: Item :: Button (
1372
- fl ! ( "open-in-new-window" ) ,
1373
- NavMenuAction :: OpenInNewWindow ( entity) ,
1374
- ) ) ;
1432
+ if location_opt
1433
+ . and_then ( |x| x. path_opt ( ) )
1434
+ . map_or ( false , |x| x. is_file ( ) )
1435
+ {
1436
+ items. push ( cosmic:: widget:: menu:: Item :: Button (
1437
+ fl ! ( "open" ) ,
1438
+ NavMenuAction :: Open ( entity) ,
1439
+ ) ) ;
1440
+ items. push ( cosmic:: widget:: menu:: Item :: Button (
1441
+ fl ! ( "open-with" ) ,
1442
+ NavMenuAction :: OpenWith ( entity) ,
1443
+ ) ) ;
1444
+ } else {
1445
+ items. push ( cosmic:: widget:: menu:: Item :: Button (
1446
+ fl ! ( "open-in-new-tab" ) ,
1447
+ NavMenuAction :: OpenInNewTab ( entity) ,
1448
+ ) ) ;
1449
+ items. push ( cosmic:: widget:: menu:: Item :: Button (
1450
+ fl ! ( "open-in-new-window" ) ,
1451
+ NavMenuAction :: OpenInNewWindow ( entity) ,
1452
+ ) ) ;
1453
+ }
1375
1454
items. push ( cosmic:: widget:: menu:: Item :: Divider ) ;
1376
1455
items. push ( cosmic:: widget:: menu:: Item :: Button (
1377
1456
fl ! ( "show-details" ) ,
@@ -2538,81 +2617,7 @@ impl Application for App {
2538
2617
tab:: Command :: MoveToTrash ( paths) => {
2539
2618
self . operation ( Operation :: Delete { paths } ) ;
2540
2619
}
2541
- tab:: Command :: OpenFile ( path) => {
2542
- let mut found_desktop_exec = false ;
2543
- let mime = mime_icon:: mime_for_path ( & path) ;
2544
- if mime == "application/x-desktop" {
2545
- match freedesktop_entry_parser:: parse_entry ( & path) {
2546
- Ok ( entry) => {
2547
- match entry. section ( "Desktop Entry" ) . attr ( "Exec" ) {
2548
- Some ( exec) => {
2549
- match mime_app:: exec_to_command ( exec, None ) {
2550
- Some ( mut command) => {
2551
- match spawn_detached ( & mut command) {
2552
- Ok ( ( ) ) => {
2553
- found_desktop_exec = true ;
2554
- }
2555
- Err ( err) => {
2556
- log:: warn!(
2557
- "failed to execute {:?}: {}" ,
2558
- path,
2559
- err
2560
- ) ;
2561
- }
2562
- }
2563
- }
2564
- None => {
2565
- log:: warn!( "failed to parse {:?}: invalid Desktop Entry/Exec" , path) ;
2566
- }
2567
- }
2568
- }
2569
- None => {
2570
- log:: warn!( "failed to parse {:?}: missing Desktop Entry/Exec" , path) ;
2571
- }
2572
- }
2573
- }
2574
- Err ( err) => {
2575
- log:: warn!( "failed to parse {:?}: {}" , path, err) ;
2576
- }
2577
- }
2578
- } else if mime == "application/x-executable"
2579
- || mime == "application/vnd.appimage"
2580
- {
2581
- let mut command = std:: process:: Command :: new ( & path) ;
2582
- match spawn_detached ( & mut command) {
2583
- Ok ( ( ) ) => { }
2584
- Err ( err) => match err. kind ( ) {
2585
- io:: ErrorKind :: PermissionDenied => {
2586
- // If permission is denied, try marking as executable, then running
2587
- self . dialog_pages . push_back (
2588
- DialogPage :: SetExecutableAndLaunch {
2589
- path : path. clone ( ) ,
2590
- } ,
2591
- ) ;
2592
- }
2593
- _ => {
2594
- log:: warn!( "failed to execute {:?}: {}" , path, err) ;
2595
- }
2596
- } ,
2597
- }
2598
- found_desktop_exec = true ;
2599
- }
2600
- if !found_desktop_exec {
2601
- match open:: that_detached ( & path) {
2602
- Ok ( ( ) ) => {
2603
- let _ = recently_used_xbel:: update_recently_used (
2604
- & path,
2605
- App :: APP_ID . to_string ( ) ,
2606
- "cosmic-files" . to_string ( ) ,
2607
- None ,
2608
- ) ;
2609
- }
2610
- Err ( err) => {
2611
- log:: warn!( "failed to open {:?}: {}" , path, err) ;
2612
- }
2613
- }
2614
- }
2615
- }
2620
+ tab:: Command :: OpenFile ( path) => self . open_file ( & path) ,
2616
2621
tab:: Command :: OpenInNewTab ( path) => {
2617
2622
commands. push ( self . open_tab ( Location :: Path ( path. clone ( ) ) , false , None ) ) ;
2618
2623
}
@@ -2937,6 +2942,48 @@ impl Application for App {
2937
2942
2938
2943
// Applies selected nav bar context menu operation.
2939
2944
Message :: NavMenuAction ( action) => match action {
2945
+ NavMenuAction :: Open ( entity) => {
2946
+ match self
2947
+ . nav_model
2948
+ . data :: < Location > ( entity)
2949
+ . and_then ( |x| x. path_opt ( ) )
2950
+ . map ( |x| x. to_path_buf ( ) )
2951
+ {
2952
+ Some ( path) => {
2953
+ self . open_file ( & path) ;
2954
+ }
2955
+ None => { }
2956
+ }
2957
+ }
2958
+ NavMenuAction :: OpenWith ( entity) => {
2959
+ match self
2960
+ . nav_model
2961
+ . data :: < Location > ( entity)
2962
+ . and_then ( |x| x. path_opt ( ) )
2963
+ . map ( |x| x. to_path_buf ( ) )
2964
+ {
2965
+ Some ( path) => match tab:: item_from_path ( & path, IconSizes :: default ( ) ) {
2966
+ Ok ( item) => {
2967
+ return self . update ( Message :: DialogPush ( DialogPage :: OpenWith {
2968
+ path : path. to_path_buf ( ) ,
2969
+ mime : item. mime . clone ( ) ,
2970
+ apps : item. open_with . clone ( ) ,
2971
+ selected : 0 ,
2972
+ store_opt : "x-scheme-handler/mime"
2973
+ . parse :: < mime_guess:: Mime > ( )
2974
+ . ok ( )
2975
+ . and_then ( |mime| {
2976
+ mime_app:: mime_apps ( & mime) . first ( ) . cloned ( )
2977
+ } ) ,
2978
+ } ) ) ;
2979
+ }
2980
+ Err ( err) => {
2981
+ log:: warn!( "failed to get item for path {:?}: {}" , path, err) ;
2982
+ }
2983
+ } ,
2984
+ None => { }
2985
+ }
2986
+ }
2940
2987
NavMenuAction :: OpenInNewTab ( entity) => {
2941
2988
match self . nav_model . data :: < Location > ( entity) {
2942
2989
Some ( Location :: Path ( ref path) ) => {
0 commit comments