feat: add "edit desktop entry" to the desktop file context menu
Opening a .desktop file launches the application it describes, so the file manager offered no way to look at or change the file itself: the only way out was a terminal. Reported upstream on 2025-05-11 and still open. Add an "Edit desktop entry" action to the context menu, next to the entry own desktop actions. It opens the file with the default text/plain handler instead of its application/x-desktop one. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9e0c2726ef
commit
d78a22d87c
4 changed files with 37 additions and 0 deletions
|
|
@ -342,6 +342,7 @@ extract-here = Extract
|
||||||
new-file = New file...
|
new-file = New file...
|
||||||
new-folder = New folder...
|
new-folder = New folder...
|
||||||
open-in-terminal = Open in terminal
|
open-in-terminal = Open in terminal
|
||||||
|
edit-desktop-entry = Edit desktop entry
|
||||||
move-to = Move to...
|
move-to = Move to...
|
||||||
move-to-trash = Move to trash
|
move-to-trash = Move to trash
|
||||||
restore-from-trash = Restore from trash
|
restore-from-trash = Restore from trash
|
||||||
|
|
|
||||||
|
|
@ -349,6 +349,7 @@ extract-here = Extraire
|
||||||
new-file = Nouveau fichier...
|
new-file = Nouveau fichier...
|
||||||
new-folder = Nouveau dossier...
|
new-folder = Nouveau dossier...
|
||||||
open-in-terminal = Ouvrir dans le terminal
|
open-in-terminal = Ouvrir dans le terminal
|
||||||
|
edit-desktop-entry = Modifier le fichier .desktop
|
||||||
move-to-trash = Déplacer vers la corbeille
|
move-to-trash = Déplacer vers la corbeille
|
||||||
restore-from-trash = Restaurer depuis la corbeille
|
restore-from-trash = Restaurer depuis la corbeille
|
||||||
remove-from-sidebar = Supprimer de la barre latérale
|
remove-from-sidebar = Supprimer de la barre latérale
|
||||||
|
|
|
||||||
33
src/app.rs
33
src/app.rs
|
|
@ -247,6 +247,7 @@ pub enum Action {
|
||||||
CosmicSettingsWallpaper,
|
CosmicSettingsWallpaper,
|
||||||
DesktopViewOptions,
|
DesktopViewOptions,
|
||||||
Delete,
|
Delete,
|
||||||
|
EditDesktopEntry,
|
||||||
EditHistory,
|
EditHistory,
|
||||||
EditLocation,
|
EditLocation,
|
||||||
Eject,
|
Eject,
|
||||||
|
|
@ -320,6 +321,7 @@ impl Action {
|
||||||
Self::CosmicSettingsWallpaper => Message::CosmicSettings("wallpaper"),
|
Self::CosmicSettingsWallpaper => Message::CosmicSettings("wallpaper"),
|
||||||
Self::Delete => Message::Delete(entity_opt),
|
Self::Delete => Message::Delete(entity_opt),
|
||||||
Self::DesktopViewOptions => Message::DesktopViewOptions,
|
Self::DesktopViewOptions => Message::DesktopViewOptions,
|
||||||
|
Self::EditDesktopEntry => Message::EditDesktopEntry(entity_opt),
|
||||||
Self::EditHistory => Message::ToggleContextPage(ContextPage::EditHistory),
|
Self::EditHistory => Message::ToggleContextPage(ContextPage::EditHistory),
|
||||||
Self::EditLocation => Message::TabMessage(entity_opt, tab::Message::EditLocationEnable),
|
Self::EditLocation => Message::TabMessage(entity_opt, tab::Message::EditLocationEnable),
|
||||||
Self::Eject => Message::Eject,
|
Self::Eject => Message::Eject,
|
||||||
|
|
@ -455,6 +457,7 @@ pub enum Message {
|
||||||
DesktopDialogs(bool),
|
DesktopDialogs(bool),
|
||||||
DialogCancel,
|
DialogCancel,
|
||||||
DialogComplete,
|
DialogComplete,
|
||||||
|
EditDesktopEntry(Option<Entity>),
|
||||||
Eject,
|
Eject,
|
||||||
FileDialogMessage(DialogMessage),
|
FileDialogMessage(DialogMessage),
|
||||||
DialogPush(DialogPage, Option<widget::Id>),
|
DialogPush(DialogPage, Option<widget::Id>),
|
||||||
|
|
@ -1060,6 +1063,21 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Open paths with the default text editor, ignoring their own MIME type.
|
||||||
|
///
|
||||||
|
/// Desktop entries launch the application they describe when opened, so
|
||||||
|
/// `open_file` never shows the file itself. This gives the file manager a
|
||||||
|
/// way to edit one without falling back to a terminal.
|
||||||
|
fn edit_file(&self, paths: &[PathBuf]) -> Task<Message> {
|
||||||
|
let Ok(text_plain) = "text/plain".parse::<Mime>() else {
|
||||||
|
return Task::none();
|
||||||
|
};
|
||||||
|
if !self.launch_from_mime_cache(&text_plain, paths) {
|
||||||
|
log::warn!("no application registered for text/plain, cannot edit {paths:?}");
|
||||||
|
}
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
|
||||||
fn launch_from_mime_cache<P>(&self, mime: &Mime, paths: &[P]) -> bool
|
fn launch_from_mime_cache<P>(&self, mime: &Mime, paths: &[P]) -> bool
|
||||||
where
|
where
|
||||||
P: std::fmt::Debug + AsRef<Path> + AsRef<std::ffi::OsStr>,
|
P: std::fmt::Debug + AsRef<Path> + AsRef<std::ffi::OsStr>,
|
||||||
|
|
@ -4114,6 +4132,21 @@ impl Application for App {
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
},
|
},
|
||||||
|
Message::EditDesktopEntry(entity_opt) => {
|
||||||
|
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||||
|
if let Some(tab) = self.tab_model.data::<Tab>(entity)
|
||||||
|
&& let Some(items) = tab.items_opt()
|
||||||
|
{
|
||||||
|
let paths: Vec<PathBuf> = items
|
||||||
|
.iter()
|
||||||
|
.filter(|item| item.selected)
|
||||||
|
.filter_map(|item| item.path_opt().cloned())
|
||||||
|
.collect();
|
||||||
|
if !paths.is_empty() {
|
||||||
|
return self.edit_file(&paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,8 @@ pub fn context_menu<'a>(
|
||||||
|(i, action)| menu_item(action.name, Action::ExecEntryAction(i)).into(),
|
|(i, action)| menu_item(action.name, Action::ExecEntryAction(i)).into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
children
|
||||||
|
.push(menu_item(fl!("edit-desktop-entry"), Action::EditDesktopEntry).into());
|
||||||
children.push(divider::horizontal::light().into());
|
children.push(divider::horizontal::light().into());
|
||||||
children.push(menu_item(fl!("rename"), Action::Rename).into());
|
children.push(menu_item(fl!("rename"), Action::Rename).into());
|
||||||
children.push(menu_item(fl!("cut"), Action::Cut).into());
|
children.push(menu_item(fl!("cut"), Action::Cut).into());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue