Show all applications that handle any mime types in open with dialog, fixes #568, fixes #226, fixes #721
This commit is contained in:
parent
d9ffb5d599
commit
8ced8b0551
3 changed files with 58 additions and 11 deletions
|
|
@ -80,6 +80,8 @@ save-file = Save file
|
|||
## Open With Dialog
|
||||
open-with-title = How do you want to open "{$name}"?
|
||||
browse-store = Browse {$store}
|
||||
other-apps = Other applications
|
||||
related-apps = Related applications
|
||||
|
||||
## Rename Dialog
|
||||
rename-file = Rename file
|
||||
|
|
|
|||
50
src/app.rs
50
src/app.rs
|
|
@ -505,6 +505,13 @@ pub enum DialogPage {
|
|||
|
||||
pub struct FavoriteIndex(usize);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
enum MimeAppMatch {
|
||||
Exact,
|
||||
Related,
|
||||
Other,
|
||||
}
|
||||
|
||||
pub struct MounterData(MounterKey, MounterItem);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -1710,7 +1717,7 @@ impl App {
|
|||
.into()
|
||||
}
|
||||
|
||||
fn get_programs_for_mime(&self, mime_type: &Mime) -> Vec<&MimeApp> {
|
||||
fn get_apps_for_mime(&self, mime_type: &Mime) -> Vec<(&MimeApp, MimeAppMatch)> {
|
||||
let mut results = Vec::new();
|
||||
|
||||
let mut dedupe = HashSet::new();
|
||||
|
|
@ -1719,7 +1726,7 @@ impl App {
|
|||
for mime_app in self.mime_app_cache.get(mime_type) {
|
||||
let app_id = &mime_app.id;
|
||||
if !dedupe.contains(app_id) {
|
||||
results.push(mime_app);
|
||||
results.push((mime_app, MimeAppMatch::Exact));
|
||||
dedupe.insert(app_id);
|
||||
}
|
||||
}
|
||||
|
|
@ -1730,13 +1737,22 @@ impl App {
|
|||
for mime_app in self.mime_app_cache.get(&parent_type) {
|
||||
let app_id = &mime_app.id;
|
||||
if !dedupe.contains(app_id) {
|
||||
results.push(mime_app);
|
||||
results.push((mime_app, MimeAppMatch::Related));
|
||||
dedupe.insert(app_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add other apps
|
||||
for mime_app in self.mime_app_cache.apps() {
|
||||
let app_id = &mime_app.id;
|
||||
if !dedupe.contains(app_id) {
|
||||
results.push((mime_app, MimeAppMatch::Other));
|
||||
dedupe.insert(app_id);
|
||||
}
|
||||
}
|
||||
|
||||
results
|
||||
}
|
||||
|
||||
|
|
@ -2412,9 +2428,9 @@ impl Application for App {
|
|||
selected,
|
||||
..
|
||||
} => {
|
||||
let all_apps = self.get_programs_for_mime(&mime);
|
||||
let available_apps = self.get_apps_for_mime(&mime);
|
||||
|
||||
if let Some(app) = all_apps.get(selected) {
|
||||
if let Some((app, _)) = available_apps.get(selected) {
|
||||
if let Some(mut command) =
|
||||
app.command(&[&path]).and_then(|v| v.into_iter().next())
|
||||
{
|
||||
|
|
@ -4555,11 +4571,23 @@ impl Application for App {
|
|||
};
|
||||
|
||||
let mut column = widget::list_column();
|
||||
let available_programs = self.get_programs_for_mime(mime);
|
||||
let available_apps = self.get_apps_for_mime(mime);
|
||||
let item_height = 32.0;
|
||||
let mut displayed_default = false;
|
||||
|
||||
for (i, app) in available_programs.iter().enumerate() {
|
||||
let mut last_kind = MimeAppMatch::Exact;
|
||||
for (i, (app, kind)) in available_apps.iter().enumerate() {
|
||||
if *kind != last_kind {
|
||||
match kind {
|
||||
MimeAppMatch::Related => {
|
||||
column = column.add(widget::text::heading(fl!("related-apps")));
|
||||
}
|
||||
MimeAppMatch::Other => {
|
||||
column = column.add(widget::text::heading(fl!("other-apps")));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
last_kind = *kind;
|
||||
}
|
||||
column = column.add(
|
||||
widget::button::custom(
|
||||
widget::row::with_children(vec![
|
||||
|
|
@ -4603,13 +4631,13 @@ impl Application for App {
|
|||
)
|
||||
.control(
|
||||
widget::scrollable(column).height(if let Some(size) = self.size {
|
||||
let max_size = size.height - 256.0;
|
||||
let max_size = (size.height - 256.0).min(480.0);
|
||||
// (32 (item_height) + 5.0 (custom button padding)) + (space_xxs (list item spacing) * 2)
|
||||
let scrollable_height = available_programs.len() as f32
|
||||
let scrollable_height = available_apps.len() as f32
|
||||
* (item_height + 5.0 + (2.0 * space_xxs as f32));
|
||||
|
||||
if scrollable_height > max_size {
|
||||
Length::Fill
|
||||
Length::Fixed(max_size)
|
||||
} else {
|
||||
Length::Shrink
|
||||
}
|
||||
|
|
|
|||
|
|
@ -220,6 +220,7 @@ fn filename_eq(path_opt: &Option<PathBuf>, filename: &str) -> bool {
|
|||
}
|
||||
|
||||
pub struct MimeAppCache {
|
||||
apps: Vec<MimeApp>,
|
||||
cache: HashMap<Mime, Vec<MimeApp>>,
|
||||
icons: HashMap<Mime, Vec<widget::icon::Handle>>,
|
||||
terminals: Vec<MimeApp>,
|
||||
|
|
@ -228,6 +229,7 @@ pub struct MimeAppCache {
|
|||
impl MimeAppCache {
|
||||
pub fn new() -> Self {
|
||||
let mut mime_app_cache = Self {
|
||||
apps: Vec::new(),
|
||||
cache: HashMap::new(),
|
||||
icons: HashMap::new(),
|
||||
terminals: Vec::new(),
|
||||
|
|
@ -246,6 +248,7 @@ impl MimeAppCache {
|
|||
|
||||
let start = Instant::now();
|
||||
|
||||
self.apps.clear();
|
||||
self.cache.clear();
|
||||
self.icons.clear();
|
||||
self.terminals.clear();
|
||||
|
|
@ -257,6 +260,10 @@ impl MimeAppCache {
|
|||
//TODO: hashmap for all apps by id?
|
||||
let mut all_apps = desktop::load_applications(locale, false);
|
||||
for app in &mut all_apps {
|
||||
//TODO: just collect apps that can be executed with a file argument?
|
||||
if !app.mime_types.is_empty() {
|
||||
self.apps.push(MimeApp::from(&app));
|
||||
}
|
||||
for mime in app.mime_types.iter() {
|
||||
let apps = self
|
||||
.cache
|
||||
|
|
@ -387,6 +394,12 @@ impl MimeAppCache {
|
|||
}
|
||||
|
||||
// Sort apps by name
|
||||
self.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),
|
||||
});
|
||||
for apps in self.cache.values_mut() {
|
||||
apps.sort_by(|a, b| match (a.is_default, b.is_default) {
|
||||
(true, false) => Ordering::Less,
|
||||
|
|
@ -408,6 +421,10 @@ impl MimeAppCache {
|
|||
log::info!("loaded mime app cache in {:?}", elapsed);
|
||||
}
|
||||
|
||||
pub fn apps(&self) -> &[MimeApp] {
|
||||
&self.apps
|
||||
}
|
||||
|
||||
pub fn get(&self, key: &Mime) -> &[MimeApp] {
|
||||
static EMPTY: Vec<MimeApp> = Vec::new();
|
||||
self.cache.get(key).unwrap_or(&EMPTY)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue