From c860fcddee01636b616531aa86e605bf99b3241c Mon Sep 17 00:00:00 2001 From: Fabio Lenherr / DashieTM Date: Sat, 16 Dec 2023 12:18:13 +0100 Subject: [PATCH] fix: Use ssid over path for events --- Cargo.toml | 4 +- src/components/bluetooth/bluetooth_box.rs | 25 +- src/components/input/source_box.rs | 17 +- src/components/output/sink_box.rs | 6 +- src/components/wifi/wifi_box.rs | 9 +- src/components/wifi/wifi_entry.rs | 49 +-- wifi_box.rs | 468 ++++++++++++++++++++++ 7 files changed, 532 insertions(+), 46 deletions(-) create mode 100644 wifi_box.rs diff --git a/Cargo.toml b/Cargo.toml index 7f1bae4..5fd3e0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,8 +7,8 @@ repository = "https://github.com/Xetibo/ReSet" license = "GPL-3.0-only" [dependencies] -reset_daemon = "0.6.3" -re_set-lib = "0.8.5" +reset_daemon = "0.6.4" +re_set-lib = "0.8.6" adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] } dbus = "0.9.7" gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] } diff --git a/src/components/bluetooth/bluetooth_box.rs b/src/components/bluetooth/bluetooth_box.rs index c820b7d..a78e556 100644 --- a/src/components/bluetooth/bluetooth_box.rs +++ b/src/components/bluetooth/bluetooth_box.rs @@ -221,9 +221,18 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc = proxy.method_call(BLUETOOTH, "StartBluetoothListener", ()); + loop_box + .imp() + .reset_bluetooth_available_devices + .set_description(Some("Scanning...")); let device_added = BluetoothDeviceAdded::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))) .static_clone(); @@ -233,10 +242,6 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc, bluetooth_box: Arc = proxy.method_call(BLUETOOTH, "StopBluetoothListener", ()); + loop_box + .imp() + .reset_bluetooth_available_devices + .set_description(None); break; } if listener_active && time.elapsed().unwrap() > Duration::from_millis(10000) { @@ -352,6 +361,10 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc = proxy.method_call(BLUETOOTH, "StopBluetoothScan", ()); + loop_box + .imp() + .reset_bluetooth_available_devices + .set_description(None); } if !listener_active && listeners.bluetooth_scan_requested.load(Ordering::SeqCst) { listeners @@ -360,6 +373,10 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc = proxy.method_call(BLUETOOTH, "StartBluetoothListener", ()); + loop_box + .imp() + .reset_bluetooth_available_devices + .set_description(Some("Scanning...")); time = SystemTime::now(); } thread::sleep(Duration::from_millis(100)); diff --git a/src/components/input/source_box.rs b/src/components/input/source_box.rs index 1c839a3..beae0e6 100644 --- a/src/components/input/source_box.rs +++ b/src/components/input/source_box.rs @@ -166,7 +166,8 @@ pub fn populate_sources(input_box: Arc) { for entry in 0..*index { if model_list.string(entry) == Some(name.alias.clone().into()) { input_box_imp.reset_source_dropdown.set_selected(entry); - } + return; + } } input_box_imp.reset_source_dropdown.connect_selected_notify( clone!(@weak input_box_imp => move |dropdown| { @@ -260,6 +261,7 @@ pub fn refresh_default_source(new_source: Source, input_box: Arc, ent for entry in 0..*imp.reset_model_index.read().unwrap() { if model_list.string(entry) == Some(new_source.alias.clone().into()) { imp.reset_source_dropdown.set_selected(entry); + return; } } } @@ -419,15 +421,16 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc) -> let mut index = input_box_imp.reset_model_index.write().unwrap(); let model_list = input_box_imp.reset_model_list.write().unwrap(); if model_list.string(*index - 1) == Some("Monitor of Dummy Output".into()) { - if alias == "Monitor of Dummy Output" { - return; - } model_list.append(&alias); model_list.remove(*index - 1); map.insert(alias, (source_index, name)); + input_box_imp.reset_source_dropdown.set_selected(0); } else { model_list.append(&alias); - map.insert(alias, (source_index, name)); + map.insert(alias.clone(), (source_index, name)); + if alias == "Monitor of Dummy Output" { + input_box_imp.reset_source_dropdown.set_selected(0); + } *index += 1; } }); @@ -464,11 +467,11 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc) -> if *index == 1 { model_list.append("Monitor of Dummy Output"); - map.insert(String::from("Monitor of Dummy Output"), (0, String::from("Monitor of Dummy Output"))); } for entry in 0..*index { if model_list.string(entry) == Some(alias.clone().into()) { model_list.remove(entry); + return; } } if *index > 1 { @@ -609,7 +612,7 @@ pub fn start_input_box_listener(conn: Connection, source_box: Arc) -> for entry in 0..*index { if model_list.string(entry) == Some(alias.clone().into()) { imp.reset_source_selection.set_selected(entry); - } + } } }); }); diff --git a/src/components/output/sink_box.rs b/src/components/output/sink_box.rs index c3f11be..a3838e0 100644 --- a/src/components/output/sink_box.rs +++ b/src/components/output/sink_box.rs @@ -169,6 +169,7 @@ pub fn populate_sinks(output_box: Arc) { for entry in 0..*index { if model_list.string(entry) == Some(name.alias.clone().into()) { output_box_imp.reset_sink_dropdown.set_selected(entry); + return; } } output_box_imp.reset_sink_dropdown.connect_selected_notify( @@ -264,6 +265,7 @@ pub fn refresh_default_sink(new_sink: Sink, output_box: Arc, entry: boo for entry in 0..*index { if model_list.string(entry) == Some(new_sink.alias.clone().into()) { imp.reset_sink_dropdown.set_selected(entry); + return; } } } @@ -423,7 +425,7 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc) -> Co if model_list.string(*index - 1) == Some("Dummy Output".into()) { model_list.append(&alias); model_list.remove(*index - 1); - map.insert(alias.clone(), (sink_index, name)); + map.insert(alias, (sink_index, name)); output_box_imp.reset_sink_dropdown.set_selected(0); } else { model_list.append(&alias); @@ -472,6 +474,7 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc) -> Co for entry in 0..*index { if model_list.string(entry) == Some(alias.clone().into()) { model_list.remove(entry); + return; } } if *index > 1 { @@ -608,6 +611,7 @@ pub fn start_output_box_listener(conn: Connection, sink_box: Arc) -> Co for entry in 0..*index { if model_list.string(entry) == Some(alias.clone().into()) { imp.reset_sink_selection.set_selected(entry); + return; } } }); diff --git a/src/components/wifi/wifi_box.rs b/src/components/wifi/wifi_box.rs index b03a54c..cbb8c68 100644 --- a/src/components/wifi/wifi_box.rs +++ b/src/components/wifi/wifi_box.rs @@ -158,7 +158,7 @@ pub fn scan_for_wifi(wifi_box: Arc) { let ssid = access_point.ssid.clone(); let path = access_point.dbus_path.clone(); let connected = - imp.reset_current_wifi_device.borrow().active_access_point == path; + imp.reset_current_wifi_device.borrow().active_access_point == ssid; let entry = WifiEntry::new(connected, access_point, imp); wifi_entries.insert(ssid, entry.clone()); wifi_entries_path.insert(path, entry.clone()); @@ -294,7 +294,7 @@ pub fn start_event_listener(listeners: Arc, wifi_box: Arc) { return; } let connected = imp.reset_current_wifi_device.borrow().active_access_point - == ir.access_point.dbus_path; + == ir.access_point.ssid; let entry = WifiEntry::new(connected, ir.access_point, imp); wifi_entries.insert(ssid, entry.clone()); wifi_entries_path.insert(path, entry.clone()); @@ -366,7 +366,7 @@ pub fn start_event_listener(listeners: Arc, wifi_box: Arc) { .borrow() .set_sensitive(false); } - if ir.access_point.dbus_path + if ir.access_point.ssid == imp.reset_current_wifi_device.borrow().active_access_point { entry_imp @@ -403,7 +403,8 @@ pub fn start_event_listener(listeners: Arc, wifi_box: Arc) { for entry in wifi_entries.iter_mut() { let imp = entry.1.imp(); let mut connected = imp.connected.borrow_mut(); - *connected = imp.access_point.borrow().dbus_path == current_device.path; + *connected = + imp.access_point.borrow().ssid == current_device.active_access_point; if *connected { imp.reset_wifi_connected.borrow().set_text("Connected"); } else { diff --git a/src/components/wifi/wifi_entry.rs b/src/components/wifi/wifi_entry.rs index 44d468f..aa4746a 100644 --- a/src/components/wifi/wifi_entry.rs +++ b/src/components/wifi/wifi_entry.rs @@ -2,7 +2,7 @@ use std::ops::Deref; use std::sync::Arc; use std::time::Duration; -use crate::components::utils::{WIRELESS, DBUS_PATH, BASE}; +use crate::components::utils::{BASE, DBUS_PATH, WIRELESS}; use crate::components::wifi::utils::get_connection_settings; use adw::glib; use adw::glib::{Object, PropertySet}; @@ -119,20 +119,18 @@ impl WifiEntry { pub fn click_disconnect(entry: Arc) { let entry_ref = entry.clone(); + entry_ref + .imp() + .reset_wifi_connected + .borrow() + .set_text("Disconnecting..."); entry.set_activatable(false); gio::spawn_blocking(move || { let imp = entry_ref.imp(); let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy( - BASE, - DBUS_PATH, - Duration::from_millis(10000), - ); - let res: Result<(bool,), Error> = proxy.method_call( - WIRELESS, - "DisconnectFromCurrentAccessPoint", - (), - ); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(10000)); + let res: Result<(bool,), Error> = + proxy.method_call(WIRELESS, "DisconnectFromCurrentAccessPoint", ()); if res.is_err() { imp.connected.replace(false); return; @@ -151,22 +149,19 @@ pub fn click_stored_network(entry: Arc) { let entry_imp = entry.imp(); let access_point = entry_imp.access_point.borrow().clone(); let entry_ref = entry.clone(); - entry.set_activatable(false); + entry.set_sensitive(false); + entry_imp + .reset_wifi_connected + .borrow() + .set_text("Connecting..."); gio::spawn_blocking(move || { let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy( - BASE, - DBUS_PATH, - Duration::from_millis(10000), - ); - let res: Result<(bool,), Error> = proxy.method_call( - WIRELESS, - "ConnectToKnownAccessPoint", - (access_point,), - ); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(10000)); + let res: Result<(bool,), Error> = + proxy.method_call(WIRELESS, "ConnectToKnownAccessPoint", (access_point,)); glib::spawn_future(async move { glib::idle_add_once(move || { - entry.set_activatable(true); + entry.set_sensitive(true); let imp = entry_ref.imp(); if res.is_err() { imp.connected.replace(false); @@ -194,14 +189,11 @@ pub fn click_new_network(entry: Arc) { popup.reset_popup_label.set_visible(true); popup.reset_popup_entry.set_sensitive(false); popup.reset_popup_button.set_sensitive(false); + entry.set_sensitive(false); gio::spawn_blocking(move || { let conn = Connection::new_session().unwrap(); - let proxy = conn.with_proxy( - BASE, - DBUS_PATH, - Duration::from_millis(10000), - ); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(10000)); let res: Result<(bool,), Error> = proxy.method_call( WIRELESS, "ConnectToNewAccessPoint", @@ -209,6 +201,7 @@ pub fn click_new_network(entry: Arc) { ); glib::spawn_future(async move { glib::idle_add_once(move || { + entry.set_sensitive(false); if res.is_err() { let imp = entry_ref.imp(); imp.reset_wifi_popup diff --git a/wifi_box.rs b/wifi_box.rs new file mode 100644 index 0000000..52ccc79 --- /dev/null +++ b/wifi_box.rs @@ -0,0 +1,468 @@ +use std::sync::atomic::Ordering; + +use std::sync::Arc; + +use std::time::Duration; + +use crate::components::base::utils::Listeners; +use crate::components::utils::{set_combo_row_ellipsis, BASE, DBUS_PATH, WIRELESS}; +use adw::glib; +use adw::glib::Object; +use adw::prelude::{ComboRowExt, ListBoxRowExt, PreferencesGroupExt, PreferencesRowExt}; +use adw::subclass::prelude::ObjectSubclassIsExt; +use dbus::blocking::Connection; +use dbus::message::SignalArgs; +use dbus::Error; +use dbus::Path; +use glib::{clone, Cast, PropertySet}; +use gtk::glib::Variant; +use gtk::prelude::{ActionableExt, WidgetExt}; +use gtk::{gio, StringList, StringObject}; +use re_set_lib::network::network_structures::{AccessPoint, WifiDevice, WifiStrength}; +use re_set_lib::signals::{AccessPointAdded, WifiDeviceChanged, WifiDeviceReset}; +use re_set_lib::signals::{AccessPointChanged, AccessPointRemoved}; + +use crate::components::wifi::wifi_box_impl; +use crate::components::wifi::wifi_entry::WifiEntry; + +use super::saved_wifi_entry::SavedWifiEntry; + +glib::wrapper! { + pub struct WifiBox(ObjectSubclass) + @extends gtk::Box, gtk::Widget, + @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable; +} + +type ResultMap = Result<(Vec<(Path<'static>, Vec)>,), Error>; + +unsafe impl Send for WifiBox {} +unsafe impl Sync for WifiBox {} + +impl WifiBox { + pub fn new(listeners: Arc) -> Arc { + let obj: Arc = Arc::new(Object::builder().build()); + setup_callbacks(listeners, obj) + } + + pub fn setup_callbacks(&self) {} +} + +fn setup_callbacks(listeners: Arc, wifi_box: Arc) -> Arc { + let wifi_status = get_wifi_status(); + let imp = wifi_box.imp(); + let wifibox_ref = wifi_box.clone(); + imp.reset_saved_networks.set_activatable(true); + imp.reset_saved_networks + .set_action_name(Some("navigation.push")); + imp.reset_saved_networks + .set_action_target_value(Some(&Variant::from("saved"))); + + imp.reset_wifi_switch.set_active(wifi_status); + imp.reset_wifi_switch.set_state(wifi_status); + + imp.reset_available_networks.set_activatable(true); + imp.reset_available_networks + .set_action_name(Some("navigation.pop")); + set_combo_row_ellipsis(imp.reset_wifi_device.get()); + imp.reset_wifi_switch.connect_state_set( + clone!(@weak imp => @default-return glib::Propagation::Proceed, move |_, value| { + set_wifi_enabled(value); + if !value { + imp.reset_wifi_devices.write().unwrap().clear(); + *imp.reset_model_list.write().unwrap() = StringList::new(&[]); + *imp.reset_model_index.write().unwrap() = 0; + let mut map = imp.wifi_entries.write().unwrap(); + for entry in map.iter() { + imp.reset_wifi_list.remove(&*(*entry.1)); + } + map.clear(); + imp.wifi_entries_path.write().unwrap().clear(); + listeners.wifi_listener.store(false, Ordering::SeqCst); + } else { + start_event_listener(listeners.clone(), wifibox_ref.clone()); + show_stored_connections(wifibox_ref.clone()); + scan_for_wifi(wifibox_ref.clone()); + } + glib::Propagation::Proceed + }), + ); + wifi_box +} + +pub fn scan_for_wifi(wifi_box: Arc) { + let wifibox_ref = wifi_box.clone(); + let _wifibox_ref_listener = wifi_box.clone(); + let wifi_entries = wifi_box.imp().wifi_entries.clone(); + let wifi_entries_path = wifi_box.imp().wifi_entries_path.clone(); + + gio::spawn_blocking(move || { + let devices = get_wifi_devices(); + let access_points = get_access_points(); + { + let imp = wifibox_ref.imp(); + let list = imp.reset_model_list.write().unwrap(); + let mut model_index = imp.reset_model_index.write().unwrap(); + let mut map = imp.reset_wifi_devices.write().unwrap(); + if devices.is_empty() { + return; + } + imp.reset_current_wifi_device + .replace(devices.last().unwrap().clone()); + for (index, device) in devices.into_iter().enumerate() { + list.append(&device.name); + map.insert(device.name.clone(), (device, index as u32)); + *model_index += 1; + } + } + let wifi_entries = wifi_entries.clone(); + let wifi_entries_path = wifi_entries_path.clone(); + dbus_start_network_events(); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let mut wifi_entries = wifi_entries.write().unwrap(); + let mut wifi_entries_path = wifi_entries_path.write().unwrap(); + let imp = wifibox_ref.imp(); + + let list = imp.reset_model_list.read().unwrap(); + imp.reset_wifi_device.set_model(Some(&*list)); + let map = imp.reset_wifi_devices.read().unwrap(); + { + let device = imp.reset_current_wifi_device.borrow(); + if let Some(index) = map.get(&device.name) { + imp.reset_wifi_device.set_selected(index.1); + } + } + + imp.reset_wifi_device.connect_selected_notify( + clone!(@weak imp => move |dropdown| { + let selected = dropdown.selected_item(); + if selected.is_none() { + return; + } + let selected = selected.unwrap(); + let selected = selected.downcast_ref::().unwrap(); + let selected = selected.string().to_string(); + + let device = imp.reset_wifi_devices.read().unwrap(); + let device = device.get(&selected); + if device.is_none() { + return; + } + set_wifi_device(device.unwrap().0.path.clone()); + }), + ); + for access_point in access_points { + if access_point.ssid.is_empty() { + continue; + } + let ssid = access_point.ssid.clone(); + let path = access_point.dbus_path.clone(); + let connected = + imp.reset_current_wifi_device.borrow().active_access_point == path; + let entry = WifiEntry::new(connected, access_point, imp); + wifi_entries.insert(ssid, entry.clone()); + wifi_entries_path.insert(path, entry.clone()); + imp.reset_wifi_list.add(&*entry); + } + }); + }); + }); +} + +pub fn show_stored_connections(wifi_box: Arc) { + let wifibox_ref = wifi_box.clone(); + gio::spawn_blocking(move || { + let connections = get_stored_connections(); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let self_imp = wifibox_ref.imp(); + for connection in connections { + // TODO include button for settings + let name = + &String::from_utf8(connection.1).unwrap_or_else(|_| String::from("")); + let entry = SavedWifiEntry::new(name, connection.0, self_imp); + self_imp.reset_stored_wifi_list.add(&*entry); + } + }); + }); + }); +} + +pub fn dbus_start_network_events() { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let _: Result<(), Error> = proxy.method_call(WIRELESS, "StartNetworkListener", ()); +} + +pub fn get_access_points() -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = + proxy.method_call(WIRELESS, "ListAccessPoints", ()); + if res.is_err() { + return Vec::new(); + } + let (access_points,) = res.unwrap(); + access_points +} + +pub fn set_wifi_device(path: Path<'static>) { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let _: Result<(bool,), Error> = proxy.method_call(WIRELESS, "SetWifiDevice", (path,)); +} + +pub fn get_wifi_devices() -> Vec { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(Vec,), Error> = + proxy.method_call(WIRELESS, "GetAllWifiDevices", ()); + if res.is_err() { + return Vec::new(); + } + let (devices,) = res.unwrap(); + devices +} + +pub fn get_wifi_status() -> bool { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: Result<(bool,), Error> = proxy.method_call(WIRELESS, "GetWifiStatus", ()); + if res.is_err() { + return false; + } + res.unwrap().0 +} + +pub fn get_stored_connections() -> Vec<(Path<'static>, Vec)> { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let res: ResultMap = proxy.method_call(WIRELESS, "ListStoredConnections", ()); + if res.is_err() { + return Vec::new(); + } + let (connections,) = res.unwrap(); + connections +} + +pub fn set_wifi_enabled(enabled: bool) { + let conn = Connection::new_session().unwrap(); + let proxy = conn.with_proxy(BASE, DBUS_PATH, Duration::from_millis(1000)); + let _: Result<(bool,), Error> = proxy.method_call(WIRELESS, "SetWifiEnabled", (enabled,)); +} + +pub fn start_event_listener(listeners: Arc, wifi_box: Arc) { + gio::spawn_blocking(move || { + if listeners.wifi_disabled.load(Ordering::SeqCst) + || listeners.wifi_listener.load(Ordering::SeqCst) + { + return; + } + listeners.wifi_listener.store(true, Ordering::SeqCst); + + let conn = Connection::new_session().unwrap(); + let added_ref = wifi_box.clone(); + let removed_ref = wifi_box.clone(); + let changed_ref = wifi_box.clone(); + let wifi_changed_ref = wifi_box.clone(); + let wifi_reset_ref = wifi_box.clone(); + let access_point_added = + AccessPointAdded::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))) + .static_clone(); + let access_point_removed = + AccessPointRemoved::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))) + .static_clone(); + let access_point_changed = + AccessPointChanged::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))) + .static_clone(); + let device_changed = + WifiDeviceChanged::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))) + .static_clone(); + let devices_reset = + WifiDeviceReset::match_rule(Some(&BASE.into()), Some(&Path::from(DBUS_PATH))) + .static_clone(); + let res = conn.add_match(access_point_added, move |ir: AccessPointAdded, _, _| { + let wifi_box = added_ref.clone(); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = wifi_box.imp(); + let mut wifi_entries = imp.wifi_entries.write().unwrap(); + let mut wifi_entries_path = imp.wifi_entries_path.write().unwrap(); + let ssid = ir.access_point.ssid.clone(); + let path = ir.access_point.dbus_path.clone(); + if wifi_entries.get(&ssid).is_some() || ssid.is_empty() { + return; + } + let connected = imp.reset_current_wifi_device.borrow().active_access_point + == ir.access_point.ssid; + let entry = WifiEntry::new(connected, ir.access_point, imp); + wifi_entries.insert(ssid, entry.clone()); + wifi_entries_path.insert(path, entry.clone()); + imp.reset_wifi_list.add(&*entry); + }); + }); + true + }); + if res.is_err() { + println!("fail on access point add event"); + return; + } + let res = conn.add_match(access_point_removed, move |ir: AccessPointRemoved, _, _| { + let wifi_box = removed_ref.clone(); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = wifi_box.imp(); + let mut wifi_entries = imp.wifi_entries.write().unwrap(); + let mut wifi_entries_path = imp.wifi_entries_path.write().unwrap(); + let entry = wifi_entries_path.remove(&ir.access_point); + if entry.is_none() { + return; + } + let entry = entry.unwrap(); + let ssid = entry.imp().access_point.borrow().ssid.clone(); + wifi_entries.remove(&ssid); + imp.reset_wifi_list.remove(&*entry); + }); + }); + true + }); + if res.is_err() { + println!("fail on access point remove event"); + return; + } + let res = conn.add_match(access_point_changed, move |ir: AccessPointChanged, _, _| { + let wifi_box = changed_ref.clone(); + glib::spawn_future(async move { + glib::idle_add_local_once(move || { + let imp = wifi_box.imp(); + let wifi_entries = imp.wifi_entries.read().unwrap(); + let entry = wifi_entries.get(&ir.access_point.ssid); + if entry.is_none() { + return; + } + let entry = entry.unwrap(); + let entry_imp = entry.imp(); + let strength = WifiStrength::from_u8(ir.access_point.strength); + let ssid = ir.access_point.ssid.clone(); + let name_opt = String::from_utf8(ssid).unwrap_or_else(|_| String::from("")); + let name = name_opt.as_str(); + entry_imp.wifi_strength.set(strength); + entry.set_title(name); + // TODO handle encryption thing + entry_imp + .reset_wifi_strength + .borrow() + .set_from_icon_name(match strength { + WifiStrength::Excellent => { + Some("network-wireless-signal-excellent-symbolic") + } + WifiStrength::Ok => Some("network-wireless-signal-ok-symbolic"), + WifiStrength::Weak => Some("network-wireless-signal-weak-symbolic"), + WifiStrength::None => Some("network-wireless-signal-none-symbolic"), + }); + if !ir.access_point.stored { + entry_imp + .reset_wifi_edit_button + .borrow() + .set_sensitive(false); + } + if ir.access_point.ssid + == imp.reset_current_wifi_device.borrow().active_access_point + { + entry_imp + .reset_wifi_connected + .borrow() + .set_text("Connected"); + } else { + entry_imp.reset_wifi_connected.borrow().set_text(""); + } + { + let mut wifi_name = entry_imp.wifi_name.borrow_mut(); + *wifi_name = String::from(name); + } + }); + }); + true + }); + if res.is_err() { + println!("fail on access point change event"); + return; + } + let res = conn.add_match(device_changed, move |ir: WifiDeviceChanged, _, _| { + let wifi_box = wifi_changed_ref.clone(); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = wifi_box.imp(); + let mut current_device = imp.reset_current_wifi_device.borrow_mut(); + if current_device.path == ir.wifi_device.path { + current_device.active_access_point = ir.wifi_device.active_access_point; + } else { + *current_device = ir.wifi_device; + } + let mut wifi_entries = imp.wifi_entries.write().unwrap(); + for entry in wifi_entries.iter_mut() { + let imp = entry.1.imp(); + let mut connected = imp.connected.borrow_mut(); + *connected = + imp.access_point.borrow().ssid == current_device.active_access_point; + if *connected { + imp.reset_wifi_connected.borrow().set_text("Connected"); + } else { + imp.reset_wifi_connected.borrow().set_text(""); + } + } + }); + }); + true + }); + if res.is_err() { + println!("fail on wifi device change event"); + return; + } + let res = conn.add_match(devices_reset, move |ir: WifiDeviceReset, _, _| { + if ir.devices.is_empty() { + return true; + } + { + let imp = wifi_reset_ref.imp(); + let list = imp.reset_model_list.write().unwrap(); + let mut model_index = imp.reset_model_index.write().unwrap(); + let mut map = imp.reset_wifi_devices.write().unwrap(); + imp.reset_current_wifi_device + .replace(ir.devices.last().unwrap().clone()); + for (index, device) in ir.devices.into_iter().enumerate() { + list.append(&device.name); + map.insert(device.name.clone(), (device, index as u32)); + *model_index += 1; + } + } + let wifi_box = wifi_reset_ref.clone(); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = wifi_box.imp(); + let list = imp.reset_model_list.read().unwrap(); + imp.reset_wifi_device.set_model(Some(&*list)); + let map = imp.reset_wifi_devices.read().unwrap(); + { + let device = imp.reset_current_wifi_device.borrow(); + if let Some(index) = map.get(&device.name) { + imp.reset_wifi_device.set_selected(index.1); + } + } + }); + }); + true + }); + if res.is_err() { + println!("fail on wifi device change event"); + return; + } + + loop { + let _ = conn.process(Duration::from_millis(1000)); + if !listeners.wifi_listener.load(Ordering::SeqCst) { + break; + } + } + }); +}