azalea_shell/window/taskbar/widget/shortcut/
mod.rs1use gtk::{gio, prelude::*};
2use relm4::{Component, ComponentParts, ComponentSender, component};
3
4use crate::{icon, service::search::AppInfo};
5
6crate::init! {
7 Model {
8 icon: Option<gio::Icon>,
9 name: Option<String>,
10 app_info: Option<gio::AppInfo>,
11 }
12
13 Config {
14 desktop_entry: String,
15 }
16}
17
18#[derive(Debug)]
19pub enum Input {
20 Click,
21}
22
23#[derive(Debug)]
24pub enum CommandOutput {
25 FindApplication(Vec<AppInfo>),
26}
27
28#[component(pub)]
29impl Component for Model {
30 type Init = Init;
31 type Input = Input;
32 type Output = ();
33 type CommandOutput = CommandOutput;
34
35 view! {
36 gtk::Button {
37 gtk::Box {
38 set_spacing: 8,
39
40
41 gtk::Image {
42 set_from_gicon: model.icon
43 .as_ref()
44 .unwrap_or(&gio::ThemedIcon::from_names(&[icon::APPS]).upcast::<gio::Icon>())
45 },
46
47 gtk::Label {
48 set_label: &model.name.as_deref().unwrap_or(""),
49 }
50 },
51
52 connect_clicked => Input::Click,
53 }
54 }
55
56 fn init(
57 init: Self::Init,
58 _root: Self::Root,
59 sender: ComponentSender<Self>,
60 ) -> ComponentParts<Self> {
61 let app = gio::AppInfo::all().into_iter().find(|app| {
62 app.id().map(|id| id.to_string()).unwrap_or_default() == init.config.desktop_entry
63 });
64
65 let model = Model {
66 icon: app.as_ref().and_then(|app| app.icon()),
67 name: app.as_ref().map(|app| app.name().to_string()),
68 app_info: app,
69 };
70
71 if model.app_info.is_none() {
72 azalea_log::warning!(Self, "Failed to find desktop entry");
73 }
74
75 let widgets = view_output!();
76
77 ComponentParts { model, widgets }
78 }
79
80 fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>, _root: &Self::Root) {
81 match message {
82 Input::Click => {
83 if let Some(app_info) = &self.app_info {
84 let executable = app_info.executable();
85 match std::process::Command::new(&executable)
86 .stdin(std::process::Stdio::null())
87 .stdout(std::process::Stdio::null())
88 .stderr(std::process::Stdio::null())
89 .spawn()
90 {
91 Ok(_) => azalea_log::debug!("Launched application: {:?}", executable),
92 Err(e) => azalea_log::warning!(
93 Self,
94 "Failed to launch application {:?}: {e}",
95 executable
96 ),
97 }
98 }
99 }
100 }
101 }
102
103 fn update_cmd(
104 &mut self,
105 message: Self::CommandOutput,
106 _sender: ComponentSender<Self>,
107 _root: &Self::Root,
108 ) {
109 match message {
110 CommandOutput::FindApplication(app_infos) => {
111 for app_info in app_infos {
112 println!("{app_info:#?}");
113 }
114 }
115 }
116 }
117}