Adding in new functionality to open / open-with based off of MIME subclasses where needed
This commit is contained in:
parent
3e5b14dd23
commit
e3226d8dc2
2 changed files with 118 additions and 2 deletions
114
src/app.rs
114
src/app.rs
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright 2023 System76 <info@system76.com>
|
// Copyright 2023 System76 <info@system76.com>
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use cosmic::iced::mouse::Event::CursorMoved;
|
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
use cosmic::iced::{
|
use cosmic::iced::{
|
||||||
event::wayland::{Event as WaylandEvent, OutputEvent, OverlapNotifyEvent},
|
event::wayland::{Event as WaylandEvent, OutputEvent, OverlapNotifyEvent},
|
||||||
|
|
@ -57,6 +56,8 @@ use std::{
|
||||||
sync::{Arc, Mutex},
|
sync::{Arc, Mutex},
|
||||||
time::{self, Instant},
|
time::{self, Instant},
|
||||||
};
|
};
|
||||||
|
use cosmic::iced::mouse::Event::CursorMoved;
|
||||||
|
use cosmic::widget::{Button, ListColumn};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use trash::TrashItem;
|
use trash::TrashItem;
|
||||||
#[cfg(feature = "wayland")]
|
#[cfg(feature = "wayland")]
|
||||||
|
|
@ -75,6 +76,7 @@ use crate::{
|
||||||
spawn_detached::spawn_detached,
|
spawn_detached::spawn_detached,
|
||||||
tab::{self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION},
|
tab::{self, HeadingOptions, ItemMetadata, Location, Tab, HOVER_DURATION},
|
||||||
};
|
};
|
||||||
|
use crate::mime_app::MimeApp;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
|
|
@ -560,6 +562,7 @@ pub struct App {
|
||||||
impl App {
|
impl App {
|
||||||
fn open_file(&mut self, path: &PathBuf) {
|
fn open_file(&mut self, path: &PathBuf) {
|
||||||
let mime = mime_icon::mime_for_path(path);
|
let mime = mime_icon::mime_for_path(path);
|
||||||
|
|
||||||
if mime == "application/x-desktop" {
|
if mime == "application/x-desktop" {
|
||||||
// Try opening desktop application
|
// Try opening desktop application
|
||||||
match freedesktop_entry_parser::parse_entry(path) {
|
match freedesktop_entry_parser::parse_entry(path) {
|
||||||
|
|
@ -627,6 +630,31 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// loop through subclasses if available
|
||||||
|
if let Some(mime_sub_classes) = mime_icon::parent_mime_types(&mime) {
|
||||||
|
for sub_class in mime_sub_classes {
|
||||||
|
for app in self.mime_app_cache.get(&sub_class) {
|
||||||
|
let Some(mut command) = app.command(Some(path.clone().into())) else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
match spawn_detached(&mut command) {
|
||||||
|
Ok(()) => {
|
||||||
|
let _ = recently_used_xbel::update_recently_used(
|
||||||
|
path,
|
||||||
|
App::APP_ID.to_string(),
|
||||||
|
"cosmic-files".to_string(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::warn!("failed to open {:?} with {:?}: {}", path, app.id, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fall back to using open crate
|
// Fall back to using open crate
|
||||||
match open::that_detached(path) {
|
match open::that_detached(path) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
|
@ -2187,7 +2215,8 @@ impl Application for App {
|
||||||
selected,
|
selected,
|
||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Some(app) = self.mime_app_cache.get(&mime).get(selected) {
|
let direct_apps = self.mime_app_cache.get(&mime);
|
||||||
|
if let Some(app) = direct_apps.get(selected) {
|
||||||
if let Some(mut command) = app.command(Some(path.clone().into())) {
|
if let Some(mut command) = app.command(Some(path.clone().into())) {
|
||||||
match spawn_detached(&mut command) {
|
match spawn_detached(&mut command) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
|
|
@ -2215,6 +2244,46 @@ impl Application for App {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut sub_class_index = selected - direct_apps.len();
|
||||||
|
if let Some(sub_classes) = mime_icon::parent_mime_types(&mime) {
|
||||||
|
for sub_class in sub_classes {
|
||||||
|
let sub_class_apps = self.mime_app_cache.get(&sub_class);
|
||||||
|
if let Some(app) = sub_class_apps.get(sub_class_index) {
|
||||||
|
if let Some(mut command) = app.command(Some(path.clone().into())) {
|
||||||
|
match spawn_detached(&mut command) {
|
||||||
|
Ok(()) => {
|
||||||
|
let _ = recently_used_xbel::update_recently_used(
|
||||||
|
&path,
|
||||||
|
App::APP_ID.to_string(),
|
||||||
|
"cosmic-files".to_string(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::warn!(
|
||||||
|
"failed to open {:?} with {:?}: {}",
|
||||||
|
path,
|
||||||
|
app.id,
|
||||||
|
err
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::warn!(
|
||||||
|
"failed to open {:?} with {:?}: failed to get command",
|
||||||
|
path,
|
||||||
|
app.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sub_class_index -= sub_class_apps.len();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
DialogPage::RenameItem {
|
DialogPage::RenameItem {
|
||||||
from, parent, name, ..
|
from, parent, name, ..
|
||||||
|
|
@ -4229,6 +4298,7 @@ impl Application for App {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut column = widget::list_column();
|
let mut column = widget::list_column();
|
||||||
|
let mut open_index = 0;
|
||||||
for (i, app) in self.mime_app_cache.get(mime).iter().enumerate() {
|
for (i, app) in self.mime_app_cache.get(mime).iter().enumerate() {
|
||||||
column = column.add(
|
column = column.add(
|
||||||
widget::button::custom(
|
widget::button::custom(
|
||||||
|
|
@ -4260,8 +4330,48 @@ impl Application for App {
|
||||||
.class(theme::Button::MenuItem)
|
.class(theme::Button::MenuItem)
|
||||||
.on_press(Message::OpenWithSelection(i)),
|
.on_press(Message::OpenWithSelection(i)),
|
||||||
);
|
);
|
||||||
|
open_index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(sub_classes) = mime_icon::parent_mime_types(&mime) {
|
||||||
|
for sub_class in sub_classes {
|
||||||
|
for (i, app) in self.mime_app_cache.get(&sub_class).iter().enumerate() {
|
||||||
|
column = column.add(
|
||||||
|
widget::button::custom(
|
||||||
|
widget::row::with_children(vec![
|
||||||
|
widget::icon(app.icon.clone()).size(32).into(),
|
||||||
|
if app.is_default {
|
||||||
|
widget::text::body(fl!(
|
||||||
|
"default-app",
|
||||||
|
name = Some(app.name.as_str())
|
||||||
|
))
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
widget::text::body(app.name.to_string()).into()
|
||||||
|
},
|
||||||
|
widget::horizontal_space().into(),
|
||||||
|
if *selected == open_index {
|
||||||
|
widget::icon::from_name("checkbox-checked-symbolic")
|
||||||
|
.size(16)
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
widget::Space::with_width(Length::Fixed(16.0)).into()
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.spacing(space_s)
|
||||||
|
.height(Length::Fixed(32.0))
|
||||||
|
.align_y(Alignment::Center),
|
||||||
|
)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.class(theme::Button::MenuItem)
|
||||||
|
.on_press(Message::OpenWithSelection(open_index)),
|
||||||
|
);
|
||||||
|
open_index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let mut dialog = widget::dialog()
|
let mut dialog = widget::dialog()
|
||||||
.title(fl!("open-with-title", name = name))
|
.title(fl!("open-with-title", name = name))
|
||||||
.primary_action(
|
.primary_action(
|
||||||
|
|
|
||||||
|
|
@ -73,3 +73,9 @@ pub fn mime_icon(mime: Mime, size: u16) -> icon::Handle {
|
||||||
None => icon::from_name(FALLBACK_MIME_ICON).size(size).handle(),
|
None => icon::from_name(FALLBACK_MIME_ICON).size(size).handle(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parent_mime_types(mime: &Mime) -> Option<Vec<Mime>> {
|
||||||
|
let mut mime_icon_cache = MIME_ICON_CACHE.lock().unwrap();
|
||||||
|
|
||||||
|
mime_icon_cache.shared_mime_info.get_parents_aliased(mime)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue