nmrs_gui/ui/
wired_devices.rs1use gtk::Align;
2use gtk::GestureClick;
3use gtk::prelude::*;
4use gtk::{Box, Image, Label, ListBox, ListBoxRow, Orientation};
5use nmrs::models;
6use std::rc::Rc;
7
8use crate::ui::networks::NetworksContext;
9use crate::ui::wired_page::WiredPage;
10
11pub struct WiredDeviceRowController {
12 pub row: gtk::ListBoxRow,
13 pub arrow: gtk::Image,
14 pub ctx: Rc<NetworksContext>,
15 pub device: models::Device,
16 pub details_page: Rc<WiredPage>,
17}
18
19impl WiredDeviceRowController {
20 pub fn new(
21 row: gtk::ListBoxRow,
22 arrow: gtk::Image,
23 ctx: Rc<NetworksContext>,
24 device: models::Device,
25 details_page: Rc<WiredPage>,
26 ) -> Self {
27 Self {
28 row,
29 arrow,
30 ctx,
31 device,
32 details_page,
33 }
34 }
35
36 pub fn attach(&self) {
37 self.attach_arrow();
38 self.attach_row_double();
39 }
40
41 fn attach_arrow(&self) {
42 let click = GestureClick::new();
43
44 let device = self.device.clone();
45 let stack = self.ctx.stack.clone();
46 let page = self.details_page.clone();
47
48 click.connect_pressed(move |_, _, _, _| {
49 let device_c = device.clone();
50 let stack_c = stack.clone();
51 let page_c = page.clone();
52
53 glib::MainContext::default().spawn_local(async move {
54 page_c.update(&device_c);
55 stack_c.set_visible_child_name("wired-details");
56 });
57 });
58
59 self.arrow.add_controller(click);
60 }
61
62 fn attach_row_double(&self) {
63 let click = GestureClick::new();
64
65 let ctx = self.ctx.clone();
66 let device = self.device.clone();
67 let interface = device.interface.clone();
68
69 let status = ctx.status.clone();
70 let window = ctx.parent_window.clone();
71 let on_success = ctx.on_success.clone();
72
73 click.connect_pressed(move |_, n, _, _| {
74 if n != 2 {
75 return;
76 }
77
78 status.set_text(&format!("Connecting to {interface}..."));
79
80 let nm_c = ctx.nm.clone();
81 let status_c = status.clone();
82 let window_c = window.clone();
83 let on_success_c = on_success.clone();
84
85 glib::MainContext::default().spawn_local(async move {
86 window_c.set_sensitive(false);
87 match nm_c.connect_wired().await {
88 Ok(_) => {
89 status_c.set_text("");
90 on_success_c();
91 }
92 Err(e) => status_c.set_text(&format!("Failed to connect: {e}")),
93 }
94 window_c.set_sensitive(true);
95 status_c.set_text("");
96 });
97 });
98
99 self.row.add_controller(click);
100 }
101}
102
103pub fn wired_devices_view(
104 ctx: Rc<NetworksContext>,
105 devices: &[models::Device],
106 details_page: Rc<WiredPage>,
107) -> ListBox {
108 let list = ListBox::new();
109
110 for device in devices {
111 let row = ListBoxRow::new();
112 let hbox = Box::new(Orientation::Horizontal, 6);
113
114 row.add_css_class("network-selection");
115
116 if device.state == models::DeviceState::Activated {
117 row.add_css_class("connected");
118 }
119
120 let display_name = format!("{} ({})", device.interface, device.device_type);
121 hbox.append(&Label::new(Some(&display_name)));
122
123 if device.state == models::DeviceState::Activated {
124 let connected_label = Label::new(Some("Connected"));
125 connected_label.add_css_class("connected-label");
126 hbox.append(&connected_label);
127 }
128
129 let spacer = Box::new(Orientation::Horizontal, 0);
130 spacer.set_hexpand(true);
131 hbox.append(&spacer);
132
133 let state_text = match device.state {
135 models::DeviceState::Activated => Some("Connected"),
136 models::DeviceState::Disconnected => Some("Disconnected"),
137 models::DeviceState::Unavailable => Some("Unavailable"),
138 models::DeviceState::Failed => Some("Failed"),
139 _ => None,
141 };
142
143 if let Some(text) = state_text {
144 let state_label = Label::new(Some(text));
145 state_label.add_css_class(match device.state {
146 models::DeviceState::Activated => "network-good",
147 models::DeviceState::Unavailable
148 | models::DeviceState::Disconnected
149 | models::DeviceState::Failed => "network-poor",
150 _ => "network-okay",
151 });
152 hbox.append(&state_label);
153 }
154
155 let icon = Image::from_icon_name("network-wired-symbolic");
156 icon.add_css_class("wired-icon");
157 hbox.append(&icon);
158
159 let arrow = Image::from_icon_name("go-next-symbolic");
160 arrow.set_halign(Align::End);
161 arrow.add_css_class("network-arrow");
162 arrow.set_cursor_from_name(Some("pointer"));
163 hbox.append(&arrow);
164
165 row.set_child(Some(&hbox));
166
167 let controller = WiredDeviceRowController::new(
168 row.clone(),
169 arrow.clone(),
170 ctx.clone(),
171 device.clone(),
172 details_page.clone(),
173 );
174
175 controller.attach();
176
177 list.append(&row);
178 }
179 list
180}