Support browsing for application in open with dialog
This commit is contained in:
parent
fef57ee031
commit
7f60a0c710
3 changed files with 61 additions and 12 deletions
|
|
@ -53,6 +53,7 @@ save-file = Save file
|
||||||
|
|
||||||
## Open With Dialog
|
## Open With Dialog
|
||||||
open-with-title = How do you want to open "{$name}"?
|
open-with-title = How do you want to open "{$name}"?
|
||||||
|
browse-store = Browse {$store}
|
||||||
|
|
||||||
## Rename Dialog
|
## Rename Dialog
|
||||||
rename-file = Rename file
|
rename-file = Rename file
|
||||||
|
|
|
||||||
65
src/app.rs
65
src/app.rs
|
|
@ -282,6 +282,7 @@ pub enum Message {
|
||||||
OpenInNewTab(Option<Entity>),
|
OpenInNewTab(Option<Entity>),
|
||||||
OpenInNewWindow(Option<Entity>),
|
OpenInNewWindow(Option<Entity>),
|
||||||
OpenItemLocation(Option<Entity>),
|
OpenItemLocation(Option<Entity>),
|
||||||
|
OpenWithBrowse,
|
||||||
OpenWithDialog(Option<Entity>),
|
OpenWithDialog(Option<Entity>),
|
||||||
OpenWithSelection(usize),
|
OpenWithSelection(usize),
|
||||||
Paste(Option<Entity>),
|
Paste(Option<Entity>),
|
||||||
|
|
@ -408,8 +409,10 @@ pub enum DialogPage {
|
||||||
},
|
},
|
||||||
OpenWith {
|
OpenWith {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
|
mime: mime_guess::Mime,
|
||||||
apps: Vec<mime_app::MimeApp>,
|
apps: Vec<mime_app::MimeApp>,
|
||||||
selected: usize,
|
selected: usize,
|
||||||
|
store_opt: Option<mime_app::MimeApp>,
|
||||||
},
|
},
|
||||||
RenameItem {
|
RenameItem {
|
||||||
from: PathBuf,
|
from: PathBuf,
|
||||||
|
|
@ -1451,9 +1454,10 @@ impl Application for App {
|
||||||
path,
|
path,
|
||||||
apps,
|
apps,
|
||||||
selected,
|
selected,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Some(app) = apps.get(selected) {
|
if let Some(app) = apps.get(selected) {
|
||||||
if let Some(mut command) = app.command(Some(path.clone())) {
|
if let Some(mut command) = app.command(Some(path.clone().into())) {
|
||||||
match spawn_detached(&mut command) {
|
match spawn_detached(&mut command) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
let _ = recently_used_xbel::update_recently_used(
|
let _ = recently_used_xbel::update_recently_used(
|
||||||
|
|
@ -1837,6 +1841,38 @@ impl Application for App {
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
Message::OpenWithBrowse => match self.dialog_pages.pop_front() {
|
||||||
|
Some(DialogPage::OpenWith {
|
||||||
|
mime, store_opt, ..
|
||||||
|
}) => {
|
||||||
|
if let Some(app) = store_opt {
|
||||||
|
let url = format!("mime:///{mime}");
|
||||||
|
if let Some(mut command) = app.command(Some(url.clone().into())) {
|
||||||
|
match spawn_detached(&mut command) {
|
||||||
|
Ok(()) => {}
|
||||||
|
Err(err) => {
|
||||||
|
log::warn!(
|
||||||
|
"failed to open {:?} with {:?}: {}",
|
||||||
|
url,
|
||||||
|
app.id,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::warn!(
|
||||||
|
"failed to open {:?} with {:?}: failed to get command",
|
||||||
|
url,
|
||||||
|
app.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(dialog_page) => {
|
||||||
|
self.dialog_pages.push_front(dialog_page);
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
},
|
||||||
Message::OpenWithDialog(entity_opt) => {
|
Message::OpenWithDialog(entity_opt) => {
|
||||||
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||||
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
||||||
|
|
@ -1850,8 +1886,13 @@ impl Application for App {
|
||||||
};
|
};
|
||||||
return self.update(Message::DialogPush(DialogPage::OpenWith {
|
return self.update(Message::DialogPush(DialogPage::OpenWith {
|
||||||
path: path.to_path_buf(),
|
path: path.to_path_buf(),
|
||||||
|
mime: item.mime.clone(),
|
||||||
apps: item.open_with.clone(),
|
apps: item.open_with.clone(),
|
||||||
selected: 0,
|
selected: 0,
|
||||||
|
store_opt: "x-scheme-handler/mime"
|
||||||
|
.parse::<mime_guess::Mime>()
|
||||||
|
.ok()
|
||||||
|
.and_then(|mime| mime_app::mime_apps(&mime).first().cloned()),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2801,10 +2842,7 @@ impl Application for App {
|
||||||
};
|
};
|
||||||
|
|
||||||
let cosmic_theme::Spacing {
|
let cosmic_theme::Spacing {
|
||||||
space_xxs,
|
space_xxs, space_s, ..
|
||||||
space_s,
|
|
||||||
space_m,
|
|
||||||
..
|
|
||||||
} = theme::active().cosmic().spacing;
|
} = theme::active().cosmic().spacing;
|
||||||
|
|
||||||
let dialog = match dialog_page {
|
let dialog = match dialog_page {
|
||||||
|
|
@ -3098,6 +3136,8 @@ impl Application for App {
|
||||||
path,
|
path,
|
||||||
apps,
|
apps,
|
||||||
selected,
|
selected,
|
||||||
|
store_opt,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
let name = match path.file_name() {
|
let name = match path.file_name() {
|
||||||
Some(file_name) => file_name.to_str(),
|
Some(file_name) => file_name.to_str(),
|
||||||
|
|
@ -3135,16 +3175,23 @@ impl Application for App {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Browse COSMIC Store link, does that imply auto updating the app list?
|
let mut dialog = widget::dialog(fl!("open-with-title", name = name))
|
||||||
|
|
||||||
widget::dialog(fl!("open-with-title", name = name))
|
|
||||||
.primary_action(
|
.primary_action(
|
||||||
widget::button::suggested(fl!("open")).on_press(Message::DialogComplete),
|
widget::button::suggested(fl!("open")).on_press(Message::DialogComplete),
|
||||||
)
|
)
|
||||||
.secondary_action(
|
.secondary_action(
|
||||||
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
widget::button::standard(fl!("cancel")).on_press(Message::DialogCancel),
|
||||||
)
|
)
|
||||||
.control(column)
|
.control(column);
|
||||||
|
|
||||||
|
if let Some(app) = store_opt {
|
||||||
|
dialog = dialog.control(
|
||||||
|
widget::button::link(fl!("browse-store", store = app.name.as_str()))
|
||||||
|
.on_press(Message::OpenWithBrowse),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog
|
||||||
}
|
}
|
||||||
DialogPage::RenameItem {
|
DialogPage::RenameItem {
|
||||||
from,
|
from,
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@ use cosmic::widget;
|
||||||
pub use mime_guess::Mime;
|
pub use mime_guess::Mime;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use std::{
|
use std::{
|
||||||
cmp::Ordering, collections::HashMap, env, path::PathBuf, process, sync::Mutex, time::Instant,
|
cmp::Ordering, collections::HashMap, env, ffi::OsString, path::PathBuf, process, sync::Mutex,
|
||||||
|
time::Instant,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn exec_to_command(exec: &str, path_opt: Option<PathBuf>) -> Option<process::Command> {
|
pub fn exec_to_command(exec: &str, path_opt: Option<OsString>) -> Option<process::Command> {
|
||||||
let args_vec: Vec<String> = shlex::split(exec)?;
|
let args_vec: Vec<String> = shlex::split(exec)?;
|
||||||
let mut args = args_vec.iter();
|
let mut args = args_vec.iter();
|
||||||
let mut command = process::Command::new(args.next()?);
|
let mut command = process::Command::new(args.next()?);
|
||||||
|
|
@ -46,7 +47,7 @@ pub struct MimeApp {
|
||||||
|
|
||||||
impl MimeApp {
|
impl MimeApp {
|
||||||
//TODO: move to libcosmic, support multiple files
|
//TODO: move to libcosmic, support multiple files
|
||||||
pub fn command(&self, path_opt: Option<PathBuf>) -> Option<process::Command> {
|
pub fn command(&self, path_opt: Option<OsString>) -> Option<process::Command> {
|
||||||
exec_to_command(self.exec.as_deref()?, path_opt)
|
exec_to_command(self.exec.as_deref()?, path_opt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue