From 62d26c6f8ffa83c8eefd825cce3cbdd0e666af75 Mon Sep 17 00:00:00 2001 From: Jonatan Pettersson Date: Tue, 26 Nov 2024 12:54:29 +0100 Subject: [PATCH 1/2] Support latest libcosmic --- src/app.rs | 16 +++++++++++++--- src/menu.rs | 55 ++++++++++++++++++++++++++++++++++------------------- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/src/app.rs b/src/app.rs index 0d60f3c4..e859bb55 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1547,37 +1547,44 @@ impl Application for App { { items.push(cosmic::widget::menu::Item::Button( fl!("open"), + None, NavMenuAction::Open(entity), )); items.push(cosmic::widget::menu::Item::Button( fl!("open-with"), + None, NavMenuAction::OpenWith(entity), )); } else { items.push(cosmic::widget::menu::Item::Button( fl!("open-in-new-tab"), + None, NavMenuAction::OpenInNewTab(entity), )); items.push(cosmic::widget::menu::Item::Button( fl!("open-in-new-window"), + None, NavMenuAction::OpenInNewWindow(entity), )); } items.push(cosmic::widget::menu::Item::Divider); items.push(cosmic::widget::menu::Item::Button( fl!("show-details"), + None, NavMenuAction::Preview(entity), )); items.push(cosmic::widget::menu::Item::Divider); if favorite_index_opt.is_some() { items.push(cosmic::widget::menu::Item::Button( fl!("remove-from-sidebar"), + None, NavMenuAction::RemoveFromSidebar(entity), )); } if matches!(location_opt, Some(Location::Trash)) { items.push(cosmic::widget::menu::Item::Button( fl!("empty-trash"), + None, NavMenuAction::EmptyTrash, )); } @@ -2858,7 +2865,7 @@ impl Application for App { let mut paths = Vec::with_capacity(recently_trashed.len()); let icon_sizes = self.config.tab.icon_sizes; - return cosmic::command::future(async move { + return cosmic::task::future(async move { match tokio::task::spawn_blocking(move || Location::Trash.scan(icon_sizes)) .await { @@ -3713,8 +3720,11 @@ impl Application for App { widget::row::with_children(vec![ widget::icon(app.icon.clone()).size(32).into(), if app.is_default { - widget::text::body(fl!("default-app", name = app.name.as_str())) - .into() + widget::text::body(fl!( + "default-app", + name = Some(app.name.as_str()) + )) + .into() } else { widget::text::body(app.name.to_string()).into() }, diff --git a/src/menu.rs b/src/menu.rs index d3d9f8a5..3d079f7f 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -42,9 +42,9 @@ fn menu_button_optional( enabled: bool, ) -> menu::Item { if enabled { - menu::Item::Button(label, action) + menu::Item::Button(label, None, action) } else { - menu::Item::ButtonDisabled(label, action) + menu::Item::ButtonDisabled(label, None, action) } } @@ -351,6 +351,7 @@ pub fn dialog_menu<'a>( let sort_item = |label, sort, dir| { menu::Item::CheckBox( label, + None, sort_name == sort && sort_direction == dir, Action::SetSort(sort, dir), ) @@ -382,11 +383,13 @@ pub fn dialog_menu<'a>( vec![ menu::Item::CheckBox( fl!("grid-view"), + None, matches!(tab.config.view, tab::View::Grid), Action::TabViewGrid, ), menu::Item::CheckBox( fl!("list-view"), + None, matches!(tab.config.view, tab::View::List), Action::TabViewList, ), @@ -447,21 +450,23 @@ pub fn dialog_menu<'a>( menu::items( key_binds, vec![ - menu::Item::Button(fl!("zoom-in"), Action::ZoomIn), - menu::Item::Button(fl!("default-size"), Action::ZoomDefault), - menu::Item::Button(fl!("zoom-out"), Action::ZoomOut), + menu::Item::Button(fl!("zoom-in"), None, Action::ZoomIn), + menu::Item::Button(fl!("default-size"), None, Action::ZoomDefault), + menu::Item::Button(fl!("zoom-out"), None, Action::ZoomOut), menu::Item::Divider, menu::Item::CheckBox( fl!("show-hidden-files"), + None, tab.config.show_hidden, Action::ToggleShowHidden, ), menu::Item::CheckBox( fl!("list-directories-first"), + None, tab.config.folders_first, Action::ToggleFoldersFirst, ), - menu::Item::CheckBox(fl!("show-details"), show_details, Action::Preview), + menu::Item::CheckBox(fl!("show-details"), None, show_details, Action::Preview), menu::Item::Divider, menu_button_optional( fl!("gallery-preview"), @@ -487,6 +492,7 @@ pub fn menu_bar<'a>( let sort_item = |label, sort, dir| { menu::Item::CheckBox( label, + None, sort_options.map_or(false, |(sort_name, sort_direction, _)| { sort_name == sort && sort_direction == dir }), @@ -518,10 +524,10 @@ pub fn menu_bar<'a>( menu::items( key_binds, vec![ - menu::Item::Button(fl!("new-tab"), Action::TabNew), - menu::Item::Button(fl!("new-window"), Action::WindowNew), - menu::Item::Button(fl!("new-folder"), Action::NewFolder), - menu::Item::Button(fl!("new-file"), Action::NewFile), + menu::Item::Button(fl!("new-tab"), None, Action::TabNew), + menu::Item::Button(fl!("new-window"), None, Action::WindowNew), + menu::Item::Button(fl!("new-folder"), None, Action::NewFolder), + menu::Item::Button(fl!("new-file"), None, Action::NewFile), menu_button_optional( fl!("open"), Action::Open, @@ -535,8 +541,8 @@ pub fn menu_bar<'a>( menu::Item::Divider, menu_button_optional(fl!("move-to-trash"), Action::MoveToTrash, selected > 0), menu::Item::Divider, - menu::Item::Button(fl!("close-tab"), Action::TabClose), - menu::Item::Button(fl!("quit"), Action::WindowClose), + menu::Item::Button(fl!("close-tab"), None, Action::TabClose), + menu::Item::Button(fl!("quit"), None, Action::WindowClose), ], ), ), @@ -548,9 +554,9 @@ pub fn menu_bar<'a>( menu_button_optional(fl!("cut"), Action::Cut, selected > 0), menu_button_optional(fl!("copy"), Action::Copy, selected > 0), menu_button_optional(fl!("paste"), Action::Paste, selected > 0), - menu::Item::Button(fl!("select-all"), Action::SelectAll), + menu::Item::Button(fl!("select-all"), None, Action::SelectAll), menu::Item::Divider, - menu::Item::Button(fl!("history"), Action::EditHistory), + menu::Item::Button(fl!("history"), None, Action::EditHistory), ], ), ), @@ -559,32 +565,41 @@ pub fn menu_bar<'a>( menu::items( key_binds, vec![ - menu::Item::Button(fl!("zoom-in"), Action::ZoomIn), - menu::Item::Button(fl!("default-size"), Action::ZoomDefault), - menu::Item::Button(fl!("zoom-out"), Action::ZoomOut), + menu::Item::Button(fl!("zoom-in"), None, Action::ZoomIn), + menu::Item::Button(fl!("default-size"), None, Action::ZoomDefault), + menu::Item::Button(fl!("zoom-out"), None, Action::ZoomOut), menu::Item::Divider, menu::Item::CheckBox( fl!("grid-view"), + None, tab_opt.map_or(false, |tab| matches!(tab.config.view, tab::View::Grid)), Action::TabViewGrid, ), menu::Item::CheckBox( fl!("list-view"), + None, tab_opt.map_or(false, |tab| matches!(tab.config.view, tab::View::List)), Action::TabViewList, ), menu::Item::Divider, menu::Item::CheckBox( fl!("show-hidden-files"), + None, tab_opt.map_or(false, |tab| tab.config.show_hidden), Action::ToggleShowHidden, ), menu::Item::CheckBox( fl!("list-directories-first"), + None, tab_opt.map_or(false, |tab| tab.config.folders_first), Action::ToggleFoldersFirst, ), - menu::Item::CheckBox(fl!("show-details"), config.show_details, Action::Preview), + menu::Item::CheckBox( + fl!("show-details"), + None, + config.show_details, + Action::Preview, + ), menu::Item::Divider, menu_button_optional( fl!("gallery-preview"), @@ -592,9 +607,9 @@ pub fn menu_bar<'a>( selected_gallery > 0, ), menu::Item::Divider, - menu::Item::Button(fl!("menu-settings"), Action::Settings), + menu::Item::Button(fl!("menu-settings"), None, Action::Settings), menu::Item::Divider, - menu::Item::Button(fl!("menu-about"), Action::About), + menu::Item::Button(fl!("menu-about"), None, Action::About), ], ), ), From 2725707f4f813a40ee0c591cd3eff2fca6e4dcc5 Mon Sep 17 00:00:00 2001 From: Jonatan Pettersson Date: Tue, 26 Nov 2024 11:13:30 +0100 Subject: [PATCH 2/2] Use mime_app from libcosmic --- Cargo.lock | 80 ++++--------- Cargo.toml | 3 +- src/app.rs | 6 +- src/lib.rs | 1 - src/mime_app.rs | 296 ------------------------------------------------ src/tab.rs | 5 +- 6 files changed, 28 insertions(+), 363 deletions(-) delete mode 100644 src/mime_app.rs diff --git a/Cargo.lock b/Cargo.lock index 19209e5b..39a23b27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1222,7 +1222,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1241,7 +1241,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "quote", "syn 1.0.109", @@ -1348,7 +1348,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "almost", "cosmic-config", @@ -2138,16 +2138,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fraction" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f158e3ff0a1b334408dc9fb811cd99b446986f4d8b741bb08f9df1604085ae7" -dependencies = [ - "lazy_static", - "num", -] - [[package]] name = "freedesktop-desktop-entry" version = "0.5.2" @@ -2776,7 +2766,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "dnd", "iced_accessibility", @@ -2794,7 +2784,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "accesskit", "accesskit_winit", @@ -2803,7 +2793,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "bitflags 2.6.0", "bytes", @@ -2827,7 +2817,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "futures", "iced_core", @@ -2853,7 +2843,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "bitflags 2.6.0", "bytemuck", @@ -2875,7 +2865,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2887,7 +2877,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "bytes", "dnd", @@ -2902,7 +2892,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "bytemuck", "cosmic-text", @@ -2918,7 +2908,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "as-raw-xcb-connection", "bitflags 2.6.0", @@ -2949,7 +2939,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "dnd", "iced_renderer", @@ -2967,7 +2957,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "dnd", "iced_futures", @@ -3551,7 +3541,7 @@ checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic.git#a355a049d917823dafcd6669cad6afa6983bc6c6" +source = "git+https://github.com/jpttrssn/libcosmic?branch=launch-app-in-term#b450653f65da05c29fbd4fafada9690d5fc313b5" dependencies = [ "apply", "ashpd 0.9.2", @@ -3561,9 +3551,9 @@ dependencies = [ "cosmic-theme", "css-color", "derive_setters", - "fraction", "freedesktop-desktop-entry", "freedesktop-icons", + "freedesktop_entry_parser", "iced", "iced_core", "iced_futures", @@ -3573,9 +3563,12 @@ dependencies = [ "iced_wgpu", "iced_widget", "iced_winit", + "icu_collator", "lazy_static", "libc", "mime 0.3.17", + "mime_guess", + "once_cell", "palette", "rfd", "rustix 0.38.40", @@ -3589,6 +3582,7 @@ dependencies = [ "unicode-segmentation", "url", "ustr", + "xdg", "zbus 4.4.0", ] @@ -4133,20 +4127,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - [[package]] name = "num-bigint" version = "0.4.6" @@ -4157,15 +4137,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - [[package]] name = "num-conv" version = "0.1.0" @@ -4192,17 +4163,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index 52b6721e..12cf19b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -98,8 +98,9 @@ filetime = { git = "https://github.com/jackpot51/filetime" } # [patch.'https://github.com/pop-os/cosmic-text'] # cosmic-text = { path = "../cosmic-text" } -# [patch.'https://github.com/pop-os/libcosmic'] +[patch.'https://github.com/pop-os/libcosmic'] # libcosmic = { path = "../libcosmic" } +libcosmic = { git = "https://github.com/jpttrssn/libcosmic", branch = "launch-app-in-term"} # cosmic-config = { path = "../libcosmic/cosmic-config" } # cosmic-theme = { path = "../libcosmic/cosmic-theme" } diff --git a/src/app.rs b/src/app.rs index e859bb55..3991acf4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -25,7 +25,7 @@ use cosmic::{ Alignment, Event, Length, Size, Subscription, }, iced_runtime::clipboard, - style, theme, + mime_app, style, theme, widget::{ self, dnd_destination::DragId, @@ -61,7 +61,7 @@ use crate::{ fl, home_dir, key_bind::key_binds, localize::LANGUAGE_SORTER, - menu, mime_app, mime_icon, + menu, mime_icon, mounter::{MounterAuth, MounterItem, MounterItems, MounterKey, MounterMessage, MOUNTERS}, operation::{Controller, Operation, OperationSelection, ReplaceResult}, spawn_detached::spawn_detached, @@ -1476,6 +1476,8 @@ impl Application for App { tab_drag_id: DragId::new(), }; + mime_app::reload(Some(&LANGUAGE_SORTER)); + let mut commands = vec![app.update_config()]; for location in flags.locations { diff --git a/src/lib.rs b/src/lib.rs index c6ca3456..2570c028 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,7 +13,6 @@ pub mod dialog; mod key_bind; mod localize; mod menu; -mod mime_app; pub mod mime_icon; mod mounter; mod mouse_area; diff --git a/src/mime_app.rs b/src/mime_app.rs deleted file mode 100644 index 9e110113..00000000 --- a/src/mime_app.rs +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright 2023 System76 -// SPDX-License-Identifier: GPL-3.0-only - -#[cfg(feature = "desktop")] -use cosmic::desktop; -use cosmic::widget; -pub use mime_guess::Mime; -use once_cell::sync::Lazy; -use std::{ - cmp::Ordering, collections::HashMap, env, ffi::OsString, path::PathBuf, process, sync::Mutex, - time::Instant, -}; - -pub fn exec_to_command(exec: &str, path_opt: Option) -> Option { - let args_vec: Vec = shlex::split(exec)?; - let mut args = args_vec.iter(); - let mut command = process::Command::new(args.next()?); - for arg in args { - if arg.starts_with('%') { - match arg.as_str() { - "%f" | "%F" | "%u" | "%U" => { - if let Some(path) = &path_opt { - command.arg(path); - } - } - _ => { - log::warn!("unsupported Exec code {:?} in {:?}", arg, exec); - return None; - } - } - } else { - command.arg(arg); - } - } - Some(command) -} - -#[derive(Clone, Debug)] -pub struct MimeApp { - pub id: String, - pub path: Option, - pub name: String, - pub exec: Option, - pub icon: widget::icon::Handle, - pub is_default: bool, -} - -impl MimeApp { - //TODO: move to libcosmic, support multiple files - pub fn command(&self, path_opt: Option) -> Option { - exec_to_command(self.exec.as_deref()?, path_opt) - } -} - -#[cfg(feature = "desktop")] -impl From<&desktop::DesktopEntryData> for MimeApp { - fn from(app: &desktop::DesktopEntryData) -> Self { - Self { - id: app.id.clone(), - path: app.path.clone(), - name: app.name.clone(), - exec: app.exec.clone(), - icon: match &app.icon { - desktop::IconSource::Name(name) => { - widget::icon::from_name(name.as_str()).size(32).handle() - } - desktop::IconSource::Path(path) => widget::icon::from_path(path.clone()), - }, - is_default: false, - } - } -} - -#[cfg(feature = "desktop")] -fn filename_eq(path_opt: &Option, filename: &str) -> bool { - path_opt - .as_ref() - .and_then(|path| path.file_name()) - .map(|x| x == filename) - .unwrap_or(false) -} - -pub struct MimeAppCache { - cache: HashMap>, - terminals: Vec, -} - -impl MimeAppCache { - pub fn new() -> Self { - let mut mime_app_cache = Self { - cache: HashMap::new(), - terminals: Vec::new(), - }; - mime_app_cache.reload(); - mime_app_cache - } - - #[cfg(not(feature = "desktop"))] - pub fn reload(&mut self) {} - - // Only available when using desktop feature of libcosmic, which only works on Unix-likes - #[cfg(feature = "desktop")] - pub fn reload(&mut self) { - use crate::localize::LANGUAGE_SORTER; - - let start = Instant::now(); - - self.cache.clear(); - self.terminals.clear(); - - //TODO: get proper locale? - let locale = None; - - // Load desktop applications by supported mime types - //TODO: hashmap for all apps by id? - let all_apps = desktop::load_applications(locale, false); - for app in all_apps.iter() { - for mime in app.mime_types.iter() { - let apps = self - .cache - .entry(mime.clone()) - .or_insert_with(|| Vec::with_capacity(1)); - if apps.iter().find(|x| x.id == app.id).is_none() { - apps.push(MimeApp::from(app)); - } - } - for category in app.categories.iter() { - if category == "TerminalEmulator" { - self.terminals.push(MimeApp::from(app)); - break; - } - } - } - - let desktops: Vec = env::var("XDG_CURRENT_DESKTOP") - .unwrap_or_default() - .split(':') - .map(|x| x.to_ascii_lowercase()) - .collect(); - - // Load mimeapps.list files - // https://specifications.freedesktop.org/mime-apps-spec/mime-apps-spec-latest.html - //TODO: ensure correct lookup order - let mut mimeapps_paths = Vec::new(); - match xdg::BaseDirectories::new() { - Ok(xdg_dirs) => { - for path in xdg_dirs.find_data_files("applications/mimeapps.list") { - mimeapps_paths.push(path); - } - for desktop in desktops.iter().rev() { - for path in - xdg_dirs.find_data_files(format!("applications/{desktop}-mimeapps.list")) - { - mimeapps_paths.push(path); - } - } - for path in xdg_dirs.find_config_files("mimeapps.list") { - mimeapps_paths.push(path); - } - for desktop in desktops.iter().rev() { - for path in xdg_dirs.find_config_files(format!("{desktop}-mimeapps.list")) { - mimeapps_paths.push(path); - } - } - } - Err(err) => { - log::warn!("failed to get xdg base directories: {}", err); - } - } - - //TODO: handle directory specific behavior - for path in mimeapps_paths { - let entry = match freedesktop_entry_parser::parse_entry(&path) { - Ok(ok) => ok, - Err(err) => { - log::warn!("failed to parse {:?}: {}", path, err); - continue; - } - }; - - for attr in entry - .section("Added Associations") - .attrs() - .chain(entry.section("Default Applications").attrs()) - { - if let Ok(mime) = attr.name.parse::() { - if let Some(filenames) = attr.value { - for filename in filenames.split_terminator(';') { - log::trace!("add {}={}", mime, filename); - let apps = self - .cache - .entry(mime.clone()) - .or_insert_with(|| Vec::with_capacity(1)); - if apps - .iter() - .find(|x| filename_eq(&x.path, filename)) - .is_none() - { - if let Some(app) = - all_apps.iter().find(|x| filename_eq(&x.path, filename)) - { - apps.push(MimeApp::from(app)); - } else { - log::debug!("failed to add association for {:?}: application {:?} not found", mime, filename); - } - } - } - } - } - } - - for attr in entry.section("Removed Associations").attrs() { - if let Ok(mime) = attr.name.parse::() { - if let Some(filenames) = attr.value { - for filename in filenames.split_terminator(';') { - log::trace!("remove {}={}", mime, filename); - if let Some(apps) = self.cache.get_mut(&mime) { - apps.retain(|x| !filename_eq(&x.path, filename)); - } - } - } - } - } - - for attr in entry.section("Default Applications").attrs() { - if let Ok(mime) = attr.name.parse::() { - if let Some(filenames) = attr.value { - for filename in filenames.split_terminator(';') { - log::trace!("default {}={}", mime, filename); - if let Some(apps) = self.cache.get_mut(&mime) { - let mut found = false; - for app in apps.iter_mut() { - if filename_eq(&app.path, filename) { - app.is_default = true; - found = true; - } else { - app.is_default = false; - } - } - if found { - break; - } else { - log::debug!("failed to set default for {:?}: application {:?} not found", mime, filename); - } - } - } - } - } - } - } - - // Sort apps by name - for apps in self.cache.values_mut() { - apps.sort_by(|a, b| match (a.is_default, b.is_default) { - (true, false) => Ordering::Less, - (false, true) => Ordering::Greater, - _ => LANGUAGE_SORTER.compare(&a.name, &b.name), - }); - } - - let elapsed = start.elapsed(); - log::info!("loaded mime app cache in {:?}", elapsed); - } - - pub fn get(&self, key: &Mime) -> Vec { - self.cache - .get(&key) - .map_or_else(|| Vec::new(), |x| x.clone()) - } -} - -static MIME_APP_CACHE: Lazy> = Lazy::new(|| Mutex::new(MimeAppCache::new())); - -pub fn mime_apps(mime: &Mime) -> Vec { - let mime_app_cache = MIME_APP_CACHE.lock().unwrap(); - mime_app_cache.get(mime) -} - -pub fn terminal() -> Option { - let mime_app_cache = MIME_APP_CACHE.lock().unwrap(); - - //TODO: consider rules in https://github.com/Vladimir-csp/xdg-terminal-exec - - // Look for and return preferred terminals - //TODO: fallback order beyond cosmic-term? - for id in &["com.system76.CosmicTerm"] { - for terminal in mime_app_cache.terminals.iter() { - if &terminal.id == id { - return Some(terminal.clone()); - } - } - } - - // Return whatever was the first terminal found - mime_app_cache.terminals.first().map(|x| x.clone()) -} diff --git a/src/tab.rs b/src/tab.rs index 284d0365..1b17e461 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -8,8 +8,7 @@ use cosmic::{ alignment::{Horizontal, Vertical}, clipboard::dnd::DndAction, event, - futures, - futures::SinkExt, + futures::{self, SinkExt}, keyboard::Modifiers, stream, //TODO: export in cosmic::widget @@ -28,6 +27,7 @@ use cosmic::{ Subscription, }, iced_core::{mouse::ScrollDelta, widget::tree}, + mime_app::{mime_apps, MimeApp}, theme, widget::{ self, @@ -65,7 +65,6 @@ use crate::{ fl, localize::{LANGUAGE_CHRONO, LANGUAGE_SORTER}, menu, - mime_app::{mime_apps, MimeApp}, mime_icon::{mime_for_path, mime_icon}, mounter::MOUNTERS, mouse_area,