yoda: Dolphin-style quick actions toolbar under the headerbar

Adds a full-width row of 6 icon buttons between the tab bar and the
tab view: New folder · Rename · Delete | Cut · Copy · Paste. Paste is
disabled when the clipboard is empty (existing self.clipboard_has_content
check). A vertical divider separates file-ops (3 first) from clipboard
ops (3 last).

Implementation reuses Action::message(entity_opt = None) so keybinding
and toolbar dispatch share exactly the same code path — no duplication.
Icons are freedesktop *-symbolic names so they inherit the COSMIC
theme's symbolic color. Tooltips use the existing fl!() strings
(new-folder / rename / delete / cut / copy / paste, EN + FR).

Customization (pick which buttons show up) is deferred to a follow-up
commit — this first pass is fixed at the minimal-6 set per the user's
spec.
This commit is contained in:
Lionel DARNIS 2026-04-24 07:38:17 +02:00
parent 8fb2b15c68
commit 0595296609

View file

@ -6521,6 +6521,48 @@ impl Application for App {
);
}
// Yoda: Dolphin-style quick actions toolbar under the headerbar.
// Minimal 6-button set: New folder · Rename · Delete · Cut · Copy · Paste.
// Actions dispatch through Action::message so the keybinding path and
// toolbar path share the same code.
{
let clipboard_has = self.clipboard_has_content();
let tb_btn =
|icon_name: &'static str, label: String, msg: Message, enabled: bool| {
let btn = widget::button::icon(
widget::icon::from_name(icon_name).size(16),
);
let btn = if enabled { btn.on_press(msg) } else { btn };
widget::tooltip(
btn,
widget::text::body(label),
widget::tooltip::Position::Bottom,
)
};
let toolbar = widget::row::with_children(vec![
tb_btn("folder-new-symbolic", fl!("new-folder"),
Action::NewFolder.message(None), true).into(),
tb_btn("edit-rename-symbolic", fl!("rename"),
Action::Rename.message(None), true).into(),
tb_btn("edit-delete-symbolic", fl!("delete"),
Action::Delete.message(None), true).into(),
widget::divider::vertical::light().height(16).into(),
tb_btn("edit-cut-symbolic", fl!("cut"),
Action::Cut.message(None), true).into(),
tb_btn("edit-copy-symbolic", fl!("copy"),
Action::Copy.message(None), true).into(),
tb_btn("edit-paste-symbolic", fl!("paste"),
Action::Paste.message(None), clipboard_has).into(),
])
.spacing(space_xxs)
.align_y(Alignment::Center);
tab_column = tab_column.push(
widget::container(toolbar)
.width(Length::Fill)
.padding([space_xxs, space_s]),
);
}
let entity = self.tab_model.active();
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
let tab_view = tab