Merge pull request #70 from Xetibo/ina2

Ina2
This commit is contained in:
Dashie 2023-12-04 12:23:21 +01:00 committed by GitHub
commit 9f3e2146fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1158 additions and 595 deletions

View file

@ -5,8 +5,8 @@ edition = "2021"
description = "A wip universal Linux settings application."
[dependencies]
reset_daemon = "0.3.3"
ReSet-Lib = "0.5.5"
reset_daemon = "0.3.7"
ReSet-Lib = "0.6.1"
adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] }
dbus = "0.9.7"
gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] }

View file

@ -5,14 +5,16 @@ use std::time::{Duration, SystemTime};
use adw::glib;
use adw::glib::Object;
use adw::prelude::{ComboRowExt, ListModelExtManual};
use adw::subclass::prelude::ObjectSubclassIsExt;
use dbus::blocking::Connection;
use dbus::message::SignalArgs;
use dbus::{Error, Path};
use gtk::gio;
use glib::{clone, Cast};
use gtk::glib::Variant;
use gtk::prelude::{ActionableExt, ListBoxRowExt, WidgetExt};
use ReSet_Lib::bluetooth::bluetooth::BluetoothDevice;
use gtk::prelude::{ActionableExt, BoxExt, ListBoxRowExt, WidgetExt};
use gtk::{gio, StringObject, Widget};
use ReSet_Lib::bluetooth::bluetooth::{BluetoothAdapter, BluetoothDevice};
use ReSet_Lib::signals::{BluetoothDeviceAdded, BluetoothDeviceChanged, BluetoothDeviceRemoved};
use crate::components::base::listEntry::ListEntry;
@ -30,40 +32,102 @@ unsafe impl Send for BluetoothBox {}
unsafe impl Sync for BluetoothBox {}
impl BluetoothBox {
pub fn new() -> Self {
Object::builder().build()
pub fn new(listeners: Arc<Listeners>) -> Arc<Self> {
let obj: Arc<Self> = Arc::new(Object::builder().build());
setupCallbacks(listeners, obj)
}
pub fn setupCallbacks(&self) {
let selfImp = self.imp();
selfImp.resetVisibility.set_activatable(true);
selfImp
.resetVisibility
.set_action_name(Some("navigation.push"));
selfImp
.resetVisibility
.set_action_target_value(Some(&Variant::from("visibility")));
selfImp
.resetBluetoothMainTab
.set_action_name(Some("navigation.pop"));
}
pub fn setupCallbacks(&self) {}
}
impl Default for BluetoothBox {
fn default() -> Self {
Self::new()
}
fn setupCallbacks(
listeners: Arc<Listeners>,
bluetooth_box: Arc<BluetoothBox>,
) -> Arc<BluetoothBox> {
let bluetooth_box_ref = bluetooth_box.clone();
let imp = bluetooth_box.imp();
// let bluetooth_box_ref = bluetooth_box.clone();
imp.resetVisibility.set_activatable(true);
imp.resetVisibility.set_action_name(Some("navigation.push"));
imp.resetVisibility
.set_action_target_value(Some(&Variant::from("visibility")));
imp.resetBluetoothMainTab
.set_action_name(Some("navigation.pop"));
// TODO add a manual search button here
imp.resetBluetoothSwitch.connect_state_set(move |_, state| {
if !state {
let imp = bluetooth_box_ref.imp();
for x in imp.resetBluetoothConnectedDevices.observe_children().iter::<Object>() {
if let Ok(entry) = x { // todo test this
if let Some(item) = entry.downcast_ref::<Widget>() {
imp.resetBluetoothAvailableDevices.remove(item);
}
}
};
listeners.bluetooth_listener.store(false, Ordering::SeqCst);
set_adapter_enabled(
imp.resetCurrentBluetoothAdapter.borrow().path.clone(),
false,
);
} else {
let imp = bluetooth_box_ref.imp();
set_adapter_enabled(imp.resetCurrentBluetoothAdapter.borrow().path.clone(), true);
start_bluetooth_listener(listeners.clone(), bluetooth_box_ref.clone());
}
glib::Propagation::Proceed
});
bluetooth_box
}
pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc<BluetoothBox>) {
gio::spawn_blocking(move || {
let ref_box = bluetooth_box.clone();
let devices = get_connected_devices();
let adapters = get_bluetooth_adapters();
{
let imp = bluetooth_box.imp();
let list = imp.resetModelList.write().unwrap();
let mut model_index = imp.resetModelIndex.write().unwrap();
let mut map = imp.resetBluetoothAdapters.write().unwrap();
imp.resetCurrentBluetoothAdapter
.replace(adapters.last().unwrap().clone());
for (index, adapter) in adapters.into_iter().enumerate() {
list.append(&adapter.alias);
map.insert(adapter.alias.clone(), (adapter, index as u32));
*model_index += 1;
}
}
glib::spawn_future(async move {
glib::idle_add_once(move || {
let imp = ref_box.imp();
let list = imp.resetModelList.read().unwrap();
imp.resetBluetoothAdapter.set_model(Some(&*list));
let map = imp.resetBluetoothAdapters.read().unwrap();
let device = imp.resetCurrentBluetoothAdapter.borrow();
if let Some(index) = map.get(&device.alias) {
imp.resetBluetoothAdapter.set_selected(index.1);
}
imp.resetBluetoothAdapter.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::<StringObject>().unwrap();
let selected = selected.string().to_string();
let device = imp.resetBluetoothAdapters.read().unwrap();
let device = device.get(&selected);
if device.is_none() {
return;
}
set_bluetooth_adapter(device.unwrap().0.path.clone());
}),
);
for device in devices {
let path = device.path.clone();
let connected = device.connected;
@ -159,7 +223,6 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
let imp = bluetooth_box.imp();
let map = imp.availableDevices.borrow_mut();
if let Some(list_entry) = map.get(&ir.bluetooth_device) {
imp.resetBluetoothAvailableDevices.remove(&*list_entry.1);
imp.resetBluetoothConnectedDevices.remove(&*list_entry.1);
}
});
@ -216,7 +279,13 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
glib::spawn_future(async move {
glib::idle_add_once(move || {
let imp = loop_box.imp();
imp.resetBluetoothAvailableDevices.remove_all();
for x in imp.resetBluetoothAvailableDevices.observe_children().iter::<Object>() {
if let Ok(entry) = x { // todo test this
if let Some(item) = entry.downcast_ref::<Widget>() {
imp.resetBluetoothAvailableDevices.remove(item);
}
}
};
});
});
println!("stopping bluetooth listener");
@ -244,3 +313,43 @@ fn get_connected_devices() -> Vec<BluetoothDevice> {
}
res.unwrap().0
}
fn get_bluetooth_adapters() -> Vec<BluetoothAdapter> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let res: Result<(Vec<BluetoothAdapter>,), Error> =
proxy.method_call("org.Xetibo.ReSetBluetooth", "GetBluetoothAdapters", ());
if res.is_err() {
return Vec::new();
}
res.unwrap().0
}
fn set_bluetooth_adapter(path: Path<'static>) {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let _: Result<(Vec<BluetoothAdapter>,), Error> =
proxy.method_call("org.Xetibo.ReSetBluetooth", "SetBluetoothAdapter", (path,));
}
fn set_adapter_enabled(path: Path<'static>, enabled: bool) {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let _: Result<(Vec<BluetoothAdapter>,), Error> = proxy.method_call(
"org.Xetibo.ReSetBluetooth",
"SetBluetoothAdapterEnabled",
(path, enabled),
);
}

View file

@ -1,12 +1,12 @@
use adw::ActionRow;
use adw::{ActionRow, ComboRow};
use dbus::Path;
use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, ListBox, Switch};
use gtk::{glib, CompositeTemplate, ListBox, Switch, Button};
use gtk::{prelude::*, StringList};
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::Arc;
use ReSet_Lib::bluetooth::bluetooth::BluetoothDevice;
use std::sync::{Arc, RwLock};
use ReSet_Lib::bluetooth::bluetooth::{BluetoothAdapter, BluetoothDevice};
use crate::components::base::listEntry::ListEntry;
use crate::components::bluetooth::bluetoothBox;
@ -22,15 +22,23 @@ pub struct BluetoothBox {
#[template_child]
pub resetBluetoothSwitch: TemplateChild<Switch>,
#[template_child]
pub resetBluetoothAvailableDevices: TemplateChild<ListBox>,
pub resetBluetoothAvailableDevices: TemplateChild<gtk::Box>,
#[template_child]
pub resetBluetoothConnectedDevices: TemplateChild<ListBox>,
pub resetBluetoothRefreshButton: TemplateChild<Button>,
#[template_child]
pub resetBluetoothAdapter: TemplateChild<ComboRow>,
#[template_child]
pub resetBluetoothConnectedDevices: TemplateChild<gtk::Box>,
#[template_child]
pub resetVisibility: TemplateChild<ActionRow>,
#[template_child]
pub resetBluetoothMainTab: TemplateChild<ListEntry>,
pub availableDevices: BluetoothMap,
pub connectedDevices: BluetoothMap,
pub resetBluetoothAdapters: Arc<RwLock<HashMap<String, (BluetoothAdapter, u32)>>>,
pub resetCurrentBluetoothAdapter: Arc<RefCell<BluetoothAdapter>>,
pub resetModelList: Arc<RwLock<StringList>>,
pub resetModelIndex: Arc<RwLock<u32>>,
}
#[glib::object_subclass]

View file

@ -49,15 +49,16 @@ impl BluetoothEntry {
});
let gesture = GestureClick::new();
let connected = device.connected;
let paired = device.paired;
// let paired = device.paired;
// paired is not what we think
// TODO implement paired
let path = device.path.clone();
gesture.connect_released(move |_, _, _, _| {
connect_to_device(path.clone());
if connected {
disconnect_from_device(path.clone());
} else if paired {
connect_to_device(path.clone());
} else {
pair_with_device(path.clone());
connect_to_device(path.clone());
}
});
entry.add_controller(gesture);
@ -81,21 +82,21 @@ fn connect_to_device(path: Path<'static>) {
});
}
fn pair_with_device(path: Path<'static>) {
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let _: Result<(bool,), Error> = proxy.method_call(
"org.Xetibo.ReSetBluetooth",
"PairWithBluetoothDevice",
(path,),
);
});
}
// fn pair_with_device(path: Path<'static>) {
// gio::spawn_blocking(move || {
// let conn = Connection::new_session().unwrap();
// let proxy = conn.with_proxy(
// "org.Xetibo.ReSetDaemon",
// "/org/Xetibo/ReSetDaemon",
// Duration::from_millis(1000),
// );
// let _: Result<(bool,), Error> = proxy.method_call(
// "org.Xetibo.ReSetBluetooth",
// "PairWithBluetoothDevice",
// (path,),
// );
// });
// }
fn disconnect_from_device(path: Path<'static>) {
gio::spawn_blocking(move || {

View file

@ -12,4 +12,3 @@ pub mod wifiOptions;
pub mod wifiOptionsImpl;
pub mod wifiRouteEntry;
pub mod wifiRouteEntryImpl;

View file

@ -14,7 +14,7 @@ pub enum IpProtocol {
}
type ResultType =
Result<(HashMap<String, HashMap<String, dbus::arg::Variant<Box<dyn RefArg>>>>,), Error>;
Result<(HashMap<String, HashMap<String, dbus::arg::Variant<Box<dyn RefArg>>>>,), Error>;
pub fn getConnectionSettings(path: Path<'static>) -> ResetConnection {
let conn = Connection::new_session().unwrap();

View file

@ -22,7 +22,11 @@ glib::wrapper! {
}
impl WifiAddressEntry {
pub fn new(address: Option<usize>, conn: Rc<RefCell<Connection>>, protocol: IpProtocol) -> Self {
pub fn new(
address: Option<usize>,
conn: Rc<RefCell<Connection>>,
protocol: IpProtocol,
) -> Self {
let entry: WifiAddressEntry = Object::builder().build();
let entryImp = entry.imp();
@ -30,9 +34,13 @@ impl WifiAddressEntry {
let conn = conn.borrow();
let address = unsafe { conn.ipv4.address_data.get_unchecked(address) };
entryImp.resetAddressAddress.set_text(&*address.address);
entryImp.resetAddressPrefix.set_text(&*address.prefix_length.to_string());
entryImp.resetAddressRow.set_title(&format!("{}, {}", &*address.address, address.prefix_length));
entryImp.resetAddressAddress.set_text(&address.address);
entryImp
.resetAddressPrefix
.set_text(&address.prefix_length.to_string());
entryImp
.resetAddressRow
.set_title(&format!("{}/{}", &*address.address, address.prefix_length));
}
entryImp.protocol.set(protocol);
entry.setupCallbacks(conn);
@ -43,7 +51,7 @@ impl WifiAddressEntry {
let selfImp = self.imp();
let conn = connection.clone();
selfImp.resetAddressAddress.connect_changed(clone!(@weak selfImp, @weak self as what => move |entry| {
selfImp.resetAddressAddress.connect_changed(clone!(@weak selfImp => move |entry| {
let addressInput = entry.text();
let mut conn = conn.borrow_mut();
@ -53,18 +61,18 @@ impl WifiAddressEntry {
return;
}
let result = match selfImp.protocol.get() {
IpProtocol::IPv4 => Ipv4Addr::from_str(addressInput.as_str()).map(|a| IpAddr::V4(a)),
IpProtocol::IPv6 => Ipv6Addr::from_str(addressInput.as_str()).map(|a| IpAddr::V6(a)),
IpProtocol::IPv4 => Ipv4Addr::from_str(addressInput.as_str()).map(IpAddr::V4),
IpProtocol::IPv6 => Ipv6Addr::from_str(addressInput.as_str()).map(IpAddr::V6),
};
match result {
Ok(ip_addr) => {
Ok(ipAddr) => {
selfImp.resetAddressAddress.remove_css_class("error");
let addressData = match selfImp.protocol.get() {
IpProtocol::IPv4 => &mut conn.ipv4.address_data,
IpProtocol::IPv6 => &mut conn.ipv6.address_data,
};
addressData.push(Address::theBetterNew(ip_addr.to_string(), selfImp.prefix.get().1 as u32));
*selfImp.address.borrow_mut() = (true, ip_addr.to_string());
addressData.push(Address::theBetterNew(ipAddr.to_string(), selfImp.prefix.get().1 as u32));
*selfImp.address.borrow_mut() = (true, ipAddr.to_string());
}
Err(_) => {
selfImp.resetAddressAddress.add_css_class("error");
@ -88,17 +96,16 @@ impl WifiAddressEntry {
}
selfImp.prefix.set((false, 0));
setRowName(&selfImp);
return;
};
if prefixInput.is_empty() || !prefix.is_ok() {
if prefixInput.is_empty() || prefix.is_err() {
handleError();
return;
}
let prefix = prefix.unwrap();
match selfImp.protocol.get() {
IpProtocol::IPv4 if prefix < 32 => {
IpProtocol::IPv4 if prefix <= 32 => {
selfImp.prefix.set((true, prefix as u32));
selfImp.resetAddressPrefix.remove_css_class("error");
if let Ok(address2) = Ipv4Addr::from_str(selfImp.resetAddressAddress.text().as_str()) {
@ -108,7 +115,7 @@ impl WifiAddressEntry {
}
}
}
IpProtocol::IPv6 if prefix < 128 => {
IpProtocol::IPv6 if prefix <= 128 => {
selfImp.prefix.set((true, prefix as u32));
selfImp.resetAddressPrefix.remove_css_class("error");
if let Ok(address2) = Ipv6Addr::from_str(selfImp.resetAddressAddress.text().as_str()) {
@ -124,24 +131,30 @@ impl WifiAddressEntry {
}));
let conn = connection.clone();
selfImp.resetAddressRemove.connect_clicked(clone!(@weak selfImp, @weak self as what => move |_| {
let address = selfImp.resetAddressAddress.text();
let mut conn = conn.borrow_mut();
conn.ipv4.address_data.retain(|addr| addr.address != address.to_string());
what.unparent();
}));
selfImp.resetAddressRemove.connect_clicked(
clone!(@weak selfImp, @weak self as what => move |_| {
let address = selfImp.resetAddressAddress.text();
let mut conn = conn.borrow_mut();
conn.ipv4.address_data.retain(|addr| addr.address != address);
what.unparent();
}),
);
}
}
fn setRowName(selfImp: &WifiAddressEntryImpl) {
if selfImp.resetAddressAddress.text().is_empty() { return; }
if selfImp.resetAddressAddress.text().is_empty() {
return;
}
let address = selfImp.address.borrow();
let prefix = selfImp.prefix.get();
let title = match (address.0, prefix.0) {
(true, true) => { format!("{}/{}", address.1, prefix.1) },
(true, true) => {
format!("{}/{}", address.1, prefix.1)
}
(true, false) => "Prefix wrong".to_string(),
(false, true) => "Address wrong".to_string(),
(false, false) => "Address and Prefix wrong".to_string(),
};
selfImp.resetAddressRow.set_title(&*title);
}
selfImp.resetAddressRow.set_title(&title);
}

View file

@ -1,12 +1,9 @@
use std::cell::{Cell, RefCell};
use adw::{EntryRow, ExpanderRow};
use glib::once_cell::sync::Lazy;
use glib::StaticType;
use glib::subclass::Signal;
use crate::components::wifi::{wifiAddressEntry};
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, Button};
use crate::components::wifi::utils::IpProtocol;
use crate::components::wifi::wifiAddressEntry;
use adw::{EntryRow, ExpanderRow};
use gtk::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate};
use std::cell::{Cell, RefCell};
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]

View file

@ -8,18 +8,18 @@ use crate::components::base::utils::Listeners;
use crate::components::utils::setComboRowEllipsis;
use adw::glib;
use adw::glib::Object;
use adw::prelude::{ListBoxRowExt, PreferencesGroupExt};
use adw::prelude::{ComboRowExt, ListBoxRowExt, PreferencesGroupExt};
use adw::subclass::prelude::ObjectSubclassIsExt;
use dbus::blocking::Connection;
use dbus::message::SignalArgs;
use dbus::Error;
use dbus::Path;
use glib::PropertySet;
use gtk::gio;
use glib::{clone, Cast, PropertySet};
use gtk::glib::Variant;
use gtk::prelude::{ActionableExt, WidgetExt};
use ReSet_Lib::network::network::{AccessPoint, WifiStrength};
use ReSet_Lib::signals::AccessPointAdded;
use gtk::prelude::{ActionableExt, WidgetExt, BoxExt};
use gtk::{gio, StringObject};
use ReSet_Lib::network::network::{AccessPoint, WifiDevice, WifiStrength};
use ReSet_Lib::signals::{AccessPointAdded, WifiDeviceChanged};
use ReSet_Lib::signals::{AccessPointChanged, AccessPointRemoved};
use crate::components::wifi::wifiBoxImpl;
@ -39,35 +39,50 @@ unsafe impl Send for WifiBox {}
unsafe impl Sync for WifiBox {}
impl WifiBox {
pub fn new() -> Self {
Object::builder().build()
pub fn new(listeners: Arc<Listeners>) -> Arc<Self> {
let obj: Arc<WifiBox> = Arc::new(Object::builder().build());
setupCallbacks(listeners, obj)
}
pub fn setupCallbacks(&self) {
let selfImp = self.imp();
selfImp.resetSavedNetworks.set_activatable(true);
selfImp
.resetSavedNetworks
.set_action_name(Some("navigation.push"));
selfImp
.resetSavedNetworks
.set_action_target_value(Some(&Variant::from("saved")));
selfImp.resetAvailableNetworks.set_activatable(true);
selfImp
.resetAvailableNetworks
.set_action_name(Some("navigation.pop"));
setComboRowEllipsis(selfImp.resetWiFiDevice.get());
}
pub fn setupCallbacks(&self) {}
}
impl Default for WifiBox {
fn default() -> Self {
Self::new()
}
fn setupCallbacks(listeners: Arc<Listeners>, wifiBox: Arc<WifiBox>) -> Arc<WifiBox> {
let imp = wifiBox.imp();
let wifibox_ref = wifiBox.clone();
imp.resetSavedNetworks.set_activatable(true);
imp.resetSavedNetworks
.set_action_name(Some("navigation.push"));
imp.resetSavedNetworks
.set_action_target_value(Some(&Variant::from("saved")));
imp.resetAvailableNetworks.set_activatable(true);
imp.resetAvailableNetworks
.set_action_name(Some("navigation.pop"));
setComboRowEllipsis(imp.resetWiFiDevice.get());
imp.resetWifiSwitch.connect_state_set(
clone!(@weak imp => @default-return glib::Propagation::Proceed, move |_, value| {
set_wifi_enabled(value);
if !value {
let mut map = imp.wifiEntries.lock().unwrap();
for entry in map.iter() {
imp.resetWifiList.remove(&*(*entry.1));
}
map.clear();
imp.wifiEntriesPath.lock().unwrap().clear();
listeners.network_listener.store(false, Ordering::SeqCst);
} else {
start_event_listener(listeners.clone(), wifibox_ref.clone());
show_stored_connections(wifibox_ref.clone());
scanForWifi(wifibox_ref.clone());
}
glib::Propagation::Proceed
}),
);
wifiBox
}
pub fn scanForWifi(_listeners: Arc<Listeners>, wifiBox: Arc<WifiBox>) {
pub fn scanForWifi(wifiBox: Arc<WifiBox>) {
let wifibox_ref = wifiBox.clone();
let _wifibox_ref_listener = wifiBox.clone();
let wifiEntries = wifiBox.imp().wifiEntries.clone();
@ -75,6 +90,20 @@ pub fn scanForWifi(_listeners: Arc<Listeners>, wifiBox: Arc<WifiBox>) {
gio::spawn_blocking(move || {
let accessPoints = get_access_points();
let devices = get_wifi_devices();
{
let imp = wifibox_ref.imp();
let list = imp.resetModelList.write().unwrap();
let mut model_index = imp.resetModelIndex.write().unwrap();
let mut map = imp.resetWifiDevices.write().unwrap();
imp.resetCurrentWifiDevice
.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 wifiEntries = wifiEntries.clone();
let wifiEntriesPath = wifiEntriesPath.clone();
dbus_start_network_events();
@ -82,14 +111,40 @@ pub fn scanForWifi(_listeners: Arc<Listeners>, wifiBox: Arc<WifiBox>) {
glib::idle_add_once(move || {
let mut wifiEntries = wifiEntries.lock().unwrap();
let mut wifiEntriesPath = wifiEntriesPath.lock().unwrap();
let selfImp = wifibox_ref.imp();
let imp = wifibox_ref.imp();
let list = imp.resetModelList.read().unwrap();
imp.resetWiFiDevice.set_model(Some(&*list));
let map = imp.resetWifiDevices.read().unwrap();
let device = imp.resetCurrentWifiDevice.borrow();
if let Some(index) = map.get(&device.name) {
imp.resetWiFiDevice.set_selected(index.1);
}
imp.resetWiFiDevice
.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::<StringObject>().unwrap();
let selected = selected.string().to_string();
let device = imp.resetWifiDevices.read().unwrap();
let device = device.get(&selected);
if device.is_none() {
return;
}
set_wifi_device(device.unwrap().0.path.clone());
}));
for accessPoint in accessPoints {
let ssid = accessPoint.ssid.clone();
let path = accessPoint.dbus_path.clone();
let entry = WifiEntry::new(accessPoint, selfImp);
let connected = imp.resetCurrentWifiDevice.borrow().active_access_point == path;
let entry = WifiEntry::new(connected, accessPoint, imp);
wifiEntries.insert(ssid, entry.clone());
wifiEntriesPath.insert(path, entry.clone());
selfImp.resetWifiList.add(&*entry);
imp.resetWifiList.add(&*entry);
}
});
});
@ -142,6 +197,33 @@ pub fn get_access_points() -> Vec<AccessPoint> {
accessPoints
}
pub fn set_wifi_device(path: Path<'static>) {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let _: Result<(bool,), Error> =
proxy.method_call("org.Xetibo.ReSetWireless", "SetWifiDevice", (path,));
}
pub fn get_wifi_devices() -> Vec<WifiDevice> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let res: Result<(Vec<WifiDevice>,), Error> =
proxy.method_call("org.Xetibo.ReSetWireless", "GetAllWifiDevices", ());
if res.is_err() {
return Vec::new();
}
let (devices,) = res.unwrap();
devices
}
pub fn get_stored_connections() -> Vec<(Path<'static>, Vec<u8>)> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
@ -158,6 +240,17 @@ pub fn get_stored_connections() -> Vec<(Path<'static>, Vec<u8>)> {
connections
}
pub fn set_wifi_enabled(enabled: bool) {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let _: Result<(bool,), Error> =
proxy.method_call("org.Xetibo.ReSetWireless", "SetWifiEnabled", (enabled,));
}
pub fn start_event_listener(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) {
gio::spawn_blocking(move || {
if listeners.network_listener.load(Ordering::SeqCst) {
@ -169,6 +262,7 @@ pub fn start_event_listener(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) {
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 access_point_added = AccessPointAdded::match_rule(
Some(&"org.Xetibo.ReSetDaemon".into()),
Some(&Path::from("/org/Xetibo/ReSetDaemon")),
@ -184,6 +278,11 @@ pub fn start_event_listener(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) {
Some(&Path::from("/org/Xetibo/ReSetDaemon")),
)
.static_clone();
let device_changed = WifiDeviceChanged::match_rule(
Some(&"org.Xetibo.ReSetDaemon".into()),
Some(&Path::from("/org/Xetibo/ReSetDaemon")),
)
.static_clone();
let res = conn.add_match(access_point_added, move |ir: AccessPointAdded, _, _| {
println!("received added event");
let wifi_box = added_ref.clone();
@ -197,7 +296,9 @@ pub fn start_event_listener(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) {
if wifiEntries.get(&ssid).is_some() {
return;
}
let entry = WifiEntry::new(ir.access_point, imp);
let connected = imp.resetCurrentWifiDevice.borrow().active_access_point
== ir.access_point.dbus_path;
let entry = WifiEntry::new(connected, ir.access_point, imp);
wifiEntries.insert(ssid, entry.clone());
wifiEntriesPath.insert(path, entry.clone());
imp.resetWifiList.add(&*entry);
@ -269,13 +370,12 @@ pub fn start_event_listener(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) {
if !ir.access_point.stored {
entryImp.resetWifiEditButton.set_sensitive(false);
}
if ir.access_point.connected {
entryImp
.resetWifiConnected
.get()
.set_from_icon_name(Some("network-wireless-connected-symbolic"));
if ir.access_point.dbus_path
== imp.resetCurrentWifiDevice.borrow().active_access_point
{
entryImp.resetWifiConnected.set_text("Connected");
} else {
entryImp.resetWifiConnected.get().set_from_icon_name(None);
entryImp.resetWifiConnected.set_text("");
}
{
let mut wifiName = entryImp.wifiName.borrow_mut();
@ -289,6 +389,32 @@ pub fn start_event_listener(listeners: Arc<Listeners>, wifi_box: Arc<WifiBox>) {
println!("fail on change");
return;
}
let res = conn.add_match(device_changed, move |ir: WifiDeviceChanged, _, _| {
println!("received wifidevice changed event");
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.resetCurrentWifiDevice.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 wifiEntries = imp.wifiEntries.lock().unwrap();
for entry in wifiEntries.iter_mut() {
let imp = entry.1.imp();
let mut connected = imp.connected.borrow_mut();
*connected = imp.accessPoint.borrow().dbus_path == current_device.path;
}
});
});
true
});
if res.is_err() {
println!("fail on add");
return;
}
println!("starting thread listener");
loop {
let _ = conn.process(Duration::from_millis(1000));

View file

@ -1,11 +1,13 @@
use crate::components::wifi::wifiBox;
use adw::{ActionRow, ComboRow, NavigationView, PreferencesGroup};
use dbus::Path;
use gtk::prelude::*;
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, Switch};
use gtk::{prelude::*, StringList};
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::sync::{Arc, Mutex, RwLock};
use ReSet_Lib::network::network::WifiDevice;
use crate::components::base::listEntry::ListEntry;
use crate::components::wifi::wifiEntry::WifiEntry;
@ -33,6 +35,10 @@ pub struct WifiBox {
pub wifiEntries: Arc<Mutex<HashMap<Vec<u8>, Arc<WifiEntry>>>>,
pub wifiEntriesPath: Arc<Mutex<HashMap<Path<'static>, Arc<WifiEntry>>>>,
pub savedWifiEntries: Arc<Mutex<Vec<ListEntry>>>,
pub resetWifiDevices: Arc<RwLock<HashMap<String, (WifiDevice, u32)>>>,
pub resetCurrentWifiDevice: Arc<RefCell<WifiDevice>>,
pub resetModelList: Arc<RwLock<StringList>>,
pub resetModelIndex: Arc<RwLock<u32>>,
}
unsafe impl Send for WifiBox {}

View file

@ -1,4 +1,3 @@
use std::sync::atomic::AtomicBool;
use std::sync::Arc;
use std::time::Duration;
@ -28,7 +27,7 @@ unsafe impl Send for WifiEntry {}
unsafe impl Sync for WifiEntry {}
impl WifiEntry {
pub fn new(access_point: AccessPoint, wifiBox: &WifiBox) -> Arc<Self> {
pub fn new(connected: bool, access_point: AccessPoint, wifiBox: &WifiBox) -> Arc<Self> {
let entry: Arc<WifiEntry> = Arc::new(Object::builder().build());
let stored_entry = entry.clone();
let new_entry = entry.clone();
@ -40,6 +39,7 @@ impl WifiEntry {
entryImp.wifiStrength.set(strength);
entryImp.resetWifiLabel.get().set_text(name);
entryImp.resetWifiEncrypted.set_visible(false);
entryImp.connected.set(connected);
// TODO handle encryption thing
entryImp
.resetWifiStrength
@ -53,11 +53,9 @@ impl WifiEntry {
if !access_point.stored {
entryImp.resetWifiEditButton.set_sensitive(false);
}
if access_point.connected {
if connected {
entryImp
.resetWifiConnected
.get()
.set_from_icon_name(Some("network-wireless-connected-symbolic"));
.resetWifiConnected.set_text("Connected");
}
{
let mut wifiName = entryImp.wifiName.borrow_mut();
@ -68,7 +66,7 @@ impl WifiEntry {
entry.set_activatable(true);
entry.connect_activated(clone!(@weak entryImp => move |_| {
let access_point = entryImp.accessPoint.borrow();
if access_point.connected {
if *entryImp.connected.borrow() {
click_disconnect(stored_entry.clone());
} else if access_point.stored {
click_stored_network(stored_entry.clone());
@ -84,7 +82,7 @@ impl WifiEntry {
let selfImp = self.imp();
selfImp.resetWifiEditButton.connect_clicked(clone!(@ weak selfImp, @ weak wifiBox => move |_| {
let _option = getConnectionSettings(selfImp.accessPoint.borrow().associated_connection.clone());
wifiBox.resetWifiNavigation.push(&*WifiOptions::new(_option));
wifiBox.resetWifiNavigation.push(&*WifiOptions::new(_option, selfImp.accessPoint.borrow().dbus_path.clone()));
}));
}
}
@ -92,7 +90,9 @@ impl WifiEntry {
pub fn click_disconnect(entry: Arc<WifiEntry>) {
println!("called disconnect");
let entry_ref = entry.clone();
entry.set_activatable(false);
gio::spawn_blocking(move || {
let imp = entry_ref.imp();
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
@ -105,21 +105,24 @@ pub fn click_disconnect(entry: Arc<WifiEntry>) {
(),
);
if res.is_err() {
println!("res of disconnect was error bro");
imp.connected.replace(false);
return;
}
let imp = entry_ref.imp();
imp.resetWifiConnected.get().set_from_icon_name(None);
imp.accessPoint.borrow_mut().connected = false;
println!("disconnect worked");
imp.resetWifiConnected.set_text("");
imp.connected.replace(false);
glib::spawn_future(async move {
glib::idle_add_once(move || {
entry.set_activatable(true);
});
});
});
}
pub fn click_stored_network(entry: Arc<WifiEntry>) {
let result = Arc::new(AtomicBool::new(false));
let entryImp = entry.imp();
let access_point = entryImp.accessPoint.borrow().clone();
let entry_ref = entry.clone();
entry.set_activatable(false);
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
@ -134,24 +137,21 @@ pub fn click_stored_network(entry: Arc<WifiEntry>) {
);
glib::spawn_future(async move {
glib::idle_add_once(move || {
let _imp = entry_ref.imp();
entry.set_activatable(true);
let imp = entry_ref.imp();
if res.is_err() {
println!("wat bro?");
result.store(false, std::sync::atomic::Ordering::SeqCst);
println!("wtf?");
imp.connected.replace(false);
return;
}
if res.unwrap() == (false,) {
println!("error bro?");
result.store(false, std::sync::atomic::Ordering::SeqCst);
println!("false on connecting");
imp.connected.replace(false);
return;
}
let imp = entry_ref.imp();
println!("wateroni");
imp.resetWifiConnected
.get()
.set_from_icon_name(Some("network-wireless-connected-symbolic"));
imp.accessPoint.borrow_mut().connected = true;
result.store(true, std::sync::atomic::Ordering::SeqCst);
imp.resetWifiConnected.set_text("Connected");
imp.connected.replace(true);
});
});
});
@ -159,81 +159,70 @@ pub fn click_stored_network(entry: Arc<WifiEntry>) {
}
pub fn click_new_network(entry: Arc<WifiEntry>) {
let connect_new_network = |result: Arc<AtomicBool>,
entry: Arc<WifiEntry>,
access_point: AccessPoint,
password: String| {
let entry_ref = entry.clone();
let popup = entry.imp().resetWifiPopup.imp();
popup.resetPopupLabel.set_text("Connecting...");
popup.resetPopupLabel.set_visible(true);
popup.resetPopupEntry.set_sensitive(false);
popup.resetPopupButton.set_sensitive(false);
let connect_new_network =
|entry: Arc<WifiEntry>, access_point: AccessPoint, password: String| {
let entry_ref = entry.clone();
let popup = entry.imp().resetWifiPopup.imp();
popup.resetPopupLabel.set_text("Connecting...");
popup.resetPopupLabel.set_visible(true);
popup.resetPopupEntry.set_sensitive(false);
popup.resetPopupButton.set_sensitive(false);
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(10000),
);
let res: Result<(bool,), Error> = proxy.method_call(
"org.Xetibo.ReSetWireless",
"ConnectToNewAccessPoint",
(access_point, password),
);
glib::spawn_future(async move {
glib::idle_add_once(move || {
if res.is_err() {
println!("error bro");
entry_ref
.imp()
.resetWifiPopup
.imp()
.resetPopupLabel
.set_text("Could not connect to dbus.");
result.store(false, std::sync::atomic::Ordering::SeqCst);
return;
}
if res.unwrap() == (false,) {
println!("wrong pw");
entry_ref
.imp()
.resetWifiPopup
.imp()
.resetPopupLabel
.set_text("Could not connect to access point.");
result.store(false, std::sync::atomic::Ordering::SeqCst);
return;
}
println!("worked?");
let imp = entry_ref.imp();
imp.resetWifiPopup.popdown();
imp.resetWifiEditButton.set_sensitive(true);
imp.resetWifiConnected
.get()
.set_from_icon_name(Some("network-wireless-connected-symbolic"));
result.store(true, std::sync::atomic::Ordering::SeqCst);
gio::spawn_blocking(move || {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(10000),
);
let res: Result<(bool,), Error> = proxy.method_call(
"org.Xetibo.ReSetWireless",
"ConnectToNewAccessPoint",
(access_point, password),
);
glib::spawn_future(async move {
glib::idle_add_once(move || {
if res.is_err() {
let imp = entry_ref.imp();
imp.resetWifiPopup
.imp()
.resetPopupLabel
.set_text("Could not connect to dbus.");
imp.connected.replace(false);
return;
}
if res.unwrap() == (false,) {
let imp = entry_ref.imp();
imp.resetWifiPopup
.imp()
.resetPopupLabel
.set_text("Could not connect to access point.");
imp.connected.replace(false);
return;
}
println!("worked?");
let imp = entry_ref.imp();
imp.resetWifiPopup.popdown();
imp.resetWifiEditButton.set_sensitive(true);
imp.resetWifiConnected.set_text("Connected");
imp.connected.replace(true);
});
});
});
});
// TODO crate spinner animation and block UI
};
// TODO crate spinner animation and block UI
};
let result = Arc::new(AtomicBool::new(false));
let result_ref = result.clone();
let result_ref_button = result.clone();
let entryImp = entry.imp();
let popupImp = entryImp.resetWifiPopup.imp();
popupImp
.resetPopupEntry
.connect_activate(clone!(@weak entry as origEntry, @weak entryImp => move |entry| {
connect_new_network(result_ref.clone(), origEntry, entryImp.accessPoint.clone().take(), entry.text().to_string());
connect_new_network(origEntry, entryImp.accessPoint.clone().take(), entry.text().to_string());
}));
popupImp.resetPopupButton.connect_clicked(
clone!(@weak entry as origEntry,@weak entryImp, @weak popupImp => move |_| {
let entry = entryImp.resetWifiPopup.imp().resetPopupEntry.text().to_string();
connect_new_network(result_ref_button.clone(), origEntry, entryImp.accessPoint.clone().take(), entry);
connect_new_network(origEntry, entryImp.accessPoint.clone().take(), entry);
}),
);
entryImp.resetWifiPopup.popup();

View file

@ -21,12 +21,13 @@ pub struct WifiEntry {
#[template_child]
pub resetWifiEditButton: TemplateChild<Button>,
#[template_child]
pub resetWifiConnected: TemplateChild<Image>,
pub resetWifiConnected: TemplateChild<Label>,
#[template_child]
pub resetWifiPopup: TemplateChild<Popup>,
pub wifiName: RefCell<String>,
pub wifiStrength: RefCell<WifiStrength>,
pub accessPoint: RefCell<AccessPoint>,
pub connected: RefCell<bool>,
}
unsafe impl Send for WifiEntry {}

View file

@ -1,16 +1,18 @@
use std::net::{Ipv4Addr, Ipv6Addr};
use std::str::FromStr;
use std::sync::Arc;
use std::time::Duration;
use adw::glib;
use adw::{gio, glib};
use adw::glib::Object;
use adw::prelude::{ActionRowExt, ComboRowExt, PreferencesGroupExt};
use adw::subclass::prelude::ObjectSubclassIsExt;
use dbus::{Error, Path};
use dbus::arg::PropMap;
use glib::{clone, closure_local, ObjectExt, PropertySet};
use glib::{clone, PropertySet};
use gtk::prelude::{ButtonExt, EditableExt, WidgetExt};
use gtk::Widget;
use ReSet_Lib::network::connection::{Connection, DNSMethod4, DNSMethod6, Enum, TypeSettings};
use IpProtocol::{IPv4, IPv6};
use crate::components::wifi::utils::IpProtocol;
use crate::components::wifi::wifiAddressEntry::WifiAddressEntry;
@ -23,21 +25,24 @@ glib::wrapper! {
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
}
unsafe impl Send for WifiOptions {}
unsafe impl Sync for WifiOptions {}
impl WifiOptions {
pub fn new(connection: Connection) -> Arc<Self> {
pub fn new(connection: Connection, accessPoint: Path<'static>) -> Arc<Self> {
let wifiOption: Arc<WifiOptions> = Arc::new(Object::builder().build());
wifiOption.imp().connection.set(connection);
wifiOption.initializeUI();
setupCallbacks(&wifiOption);
setupCallbacks(&wifiOption, accessPoint);
wifiOption
}
pub fn initializeUI(&self) {
let selfImp = self.imp();
let mut ip4AddressLength = 0;
let mut ip4RouteLength = 0;
let mut ip6AddressLength = 0;
let mut ip6RouteLength = 0;
let ip4AddressLength;
let ip4RouteLength;
let ip6AddressLength;
let ip6RouteLength;
{
let conn = selfImp.connection.borrow();
ip4AddressLength = conn.ipv4.address_data.len();
@ -46,7 +51,6 @@ impl WifiOptions {
ip6RouteLength = conn.ipv4.route_data.len();
// General
selfImp.resetWifiAutoConnect.set_active(conn.settings.autoconnect);
selfImp.resetWifiMetered.set_active(conn.settings.metered != -1);
match &conn.device {
@ -92,38 +96,53 @@ impl WifiOptions {
}).collect();
selfImp.resetIP6DNS.set_text(&ipv6Dns.join(", "));
selfImp.resetIP6Gateway.set_text(&conn.ipv6.gateway);
dbg!(conn);
// Security
if let TypeSettings::WIFI(wifi) = &conn.device {
match wifi.security_settings.key_management.as_str() {
"none" => {
selfImp.resetWifiSecurityDropdown.set_selected(0);
selfImp.resetWifiPassword.set_visible(false);
selfImp.resetWifiPassword.set_text("");
}
"wpa-psk" => {
selfImp.resetWifiSecurityDropdown.set_selected(1);
selfImp.resetWifiPassword.set_visible(true);
selfImp.resetWifiPassword.set_text(&wifi.security_settings.psk);
}
_ => {}
}
}
}
// IPv4
for i in 0..ip4AddressLength {
let address = &WifiAddressEntry::new(Some(i), selfImp.connection.clone(), IpProtocol::IPv4);
let address = &WifiAddressEntry::new(Some(i), selfImp.connection.clone(), IPv4);
selfImp.resetIP4AddressGroup.add(address);
}
let address = &WifiAddressEntry::new(None, selfImp.connection.clone(), IpProtocol::IPv4);
let address = &WifiAddressEntry::new(None, selfImp.connection.clone(), IPv4);
selfImp.resetIP4AddressGroup.add(address);
if ip4RouteLength == 0 {
selfImp.resetIP4RoutesGroup.add(&WifiRouteEntry::new(None, selfImp.connection.clone(), IpProtocol::IPv4))
} else {
for address in 0..ip4RouteLength {
selfImp.resetIP4RoutesGroup.add(&WifiRouteEntry::new(Some(address), selfImp.connection.clone(), IpProtocol::IPv4))
}
for i in 0..ip4RouteLength {
let route = &WifiRouteEntry::new(Some(i), selfImp.connection.clone(), IPv4);
selfImp.resetIP4RoutesGroup.add(route)
}
let route = &WifiRouteEntry::new(None, selfImp.connection.clone(), IPv4);
selfImp.resetIP4RoutesGroup.add(route);
// IPv6
for address in 0..ip6AddressLength {
let address = &WifiAddressEntry::new(Some(address), selfImp.connection.clone(), IpProtocol::IPv6);
for i in 0..ip6AddressLength {
let address = &WifiAddressEntry::new(Some(i), selfImp.connection.clone(), IPv6);
selfImp.resetIP6AddressGroup.add(address);
}
let address = &WifiAddressEntry::new(None, selfImp.connection.clone(), IpProtocol::IPv6);
let address = &WifiAddressEntry::new(None, selfImp.connection.clone(), IPv6);
selfImp.resetIP6AddressGroup.add(address);
if ip6RouteLength == 0 {
selfImp.resetIP6RoutesGroup.add(&WifiRouteEntry::new(None, selfImp.connection.clone(), IpProtocol::IPv6))
} else {
for address in 0..ip6RouteLength {
selfImp.resetIP6RoutesGroup.add(&WifiRouteEntry::new(Some(address), selfImp.connection.clone(), IpProtocol::IPv6))
}
for i in 0..ip6RouteLength {
let route = &WifiRouteEntry::new(Some(i), selfImp.connection.clone(), IPv6);
selfImp.resetIP6RoutesGroup.add(route);
}
let route = &WifiRouteEntry::new(None, selfImp.connection.clone(), IPv6);
selfImp.resetIP6RoutesGroup.add(route);
// Security
}
@ -170,7 +189,7 @@ impl WifiOptions {
}
}
fn setupCallbacks(wifiOptions: &Arc<WifiOptions>) {
fn setupCallbacks(wifiOptions: &Arc<WifiOptions>, path: Path<'static>) {
let imp = wifiOptions.imp();
// General
@ -182,6 +201,7 @@ fn setupCallbacks(wifiOptions: &Arc<WifiOptions>) {
}));
imp.wifiOptionsApplyButton.connect_clicked(clone!(@weak imp => move |_| {
let prop = imp.connection.borrow().convert_to_propmap();
setConnectionSettings(path.clone(), prop);
}));
// IPv4
let wifiOptionsIP4 = wifiOptions.clone();
@ -255,6 +275,11 @@ fn setupCallbacks(wifiOptions: &Arc<WifiOptions>) {
}
}
}));
imp.resetIP6AddressAddButton.connect_clicked(clone!(@weak imp => move |_| {
let address = &WifiAddressEntry::new(None, imp.connection.clone(), IpProtocol::IPv4);
imp.resetIP6AddressGroup.add(address);
}));
imp.resetIP6Gateway.connect_changed(clone!(@weak imp => move |entry| {
let gatewayInput = entry.text();
let mut conn = imp.connection.borrow_mut();
@ -270,5 +295,48 @@ fn setupCallbacks(wifiOptions: &Arc<WifiOptions>) {
imp.resetIP6Gateway.add_css_class("error");
}
}));
// Security
imp.resetWifiSecurityDropdown.connect_selected_notify(clone!(@weak imp => move |dropdown| {
let selected = dropdown.selected();
let mut conn = imp.connection.borrow_mut();
match (selected, &mut conn.device) {
(0 , TypeSettings::WIFI(wifi)) => { // None
imp.resetWifiPassword.set_visible(false);
wifi.security_settings.key_management = String::from("none");
wifi.security_settings.authentication_algorithm = String::from("open");
},
(1 , TypeSettings::WIFI(wifi)) => { // WPA/WPA2 Personal
imp.resetWifiPassword.set_visible(true);
wifi.security_settings.key_management = String::from("wpa-psk");
wifi.security_settings.authentication_algorithm = String::from("");
},
(_, _) => {}
}
}));
imp.resetWifiPassword.connect_changed(clone!(@weak imp => move |entry| {
let passwordInput = entry.text();
let mut conn = imp.connection.borrow_mut();
if let TypeSettings::WIFI(wifi) = &mut conn.device {
wifi.security_settings.psk = passwordInput.to_string();
}
}));
}
fn setConnectionSettings(path: Path<'static>, prop: PropMap) {
gio::spawn_blocking(move || {
let conn = dbus::blocking::Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.Xetibo.ReSetDaemon",
"/org/Xetibo/ReSetDaemon",
Duration::from_millis(1000),
);
let _: Result<(bool,), Error> = proxy.method_call(
"org.Xetibo.ReSetWireless",
"SetConnectionSettings",
(path, prop),
);
});
}

View file

@ -1,11 +1,12 @@
use crate::components::wifi::wifiOptions;
use adw::subclass::prelude::NavigationPageImpl;
use adw::{ActionRow, ComboRow, EntryRow, NavigationPage, PreferencesGroup, SwitchRow};
use adw::{ActionRow, ComboRow, EntryRow, NavigationPage, PasswordEntryRow, PreferencesGroup, SwitchRow};
use gtk::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate};
use std::cell::RefCell;
use std::rc::Rc;
use ReSet_Lib::network::connection::Connection;
use ReSet_Lib::network::network::AccessPoint;
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
@ -45,6 +46,8 @@ pub struct WifiOptions {
pub resetIP4AddressAddButton: TemplateChild<Button>,
#[template_child]
pub resetIP4RoutesGroup: TemplateChild<PreferencesGroup>,
#[template_child]
pub resetIP4RouteAddButton: TemplateChild<Button>,
// IPv6
#[template_child]
pub resetIP6Method: TemplateChild<ComboRow>,
@ -55,8 +58,16 @@ pub struct WifiOptions {
#[template_child]
pub resetIP6AddressGroup: TemplateChild<PreferencesGroup>,
#[template_child]
pub resetIP6AddressAddButton: TemplateChild<Button>,
#[template_child]
pub resetIP6RoutesGroup: TemplateChild<PreferencesGroup>,
#[template_child]
pub resetIP6RouteAddButton: TemplateChild<Button>,
// Security
#[template_child]
pub resetWifiSecurityDropdown: TemplateChild<ComboRow>,
#[template_child]
pub resetWifiPassword: TemplateChild<PasswordEntryRow>,
// Misc
#[template_child]
pub wifiOptionsApplyButton: TemplateChild<Button>,

View file

@ -1,11 +1,18 @@
use std::cell::RefCell;
use std::rc::Rc;
use crate::components::wifi::utils::IpProtocol;
use adw::glib;
use adw::glib::Object;
use ReSet_Lib::network::connection::{Connection};
use crate::components::wifi::utils::IpProtocol;
use adw::prelude::{ExpanderRowExt, PreferencesRowExt};
use glib::clone;
use glib::subclass::prelude::ObjectSubclassIsExt;
use gtk::prelude::{EditableExt, WidgetExt};
use std::cell::RefCell;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::rc::Rc;
use std::str::FromStr;
use ReSet_Lib::network::connection::{Address, Connection};
use crate::components::wifi::wifiRouteEntryImpl;
use crate::components::wifi::wifiRouteEntryImpl::WifiRouteEntryImpl;
glib::wrapper! {
pub struct WifiRouteEntry(ObjectSubclass<wifiRouteEntryImpl::WifiRouteEntryImpl>)
@ -14,24 +21,222 @@ glib::wrapper! {
}
impl WifiRouteEntry {
pub fn new(address: Option<usize>, rc: Rc<RefCell<Connection>>, protocol: IpProtocol) -> Self {
pub fn new(
address: Option<usize>,
conn: Rc<RefCell<Connection>>,
protocol: IpProtocol,
) -> Self {
let entry: WifiRouteEntry = Object::builder().build();
// if let Some(address) = address {
// let entryImp = entry.imp();
// let map = address.to_map();
//
// let addr = getValueFromKey(&map, "address");
// let prefix = getValueFromKey(&map, "prefix-length");
// let gateway = getValueFromKey(&map, "gateway");
// let metric = getValueFromKey(&map, "metric");
//
// entryImp.resetRouteAddress.set_text(&addr);
// entryImp.resetRouteNetmask.set_text(&prefix);
// entryImp.resetRouteGateway.set_text(&gateway);
// entryImp.resetRouteMetric.set_text(&metric);
// entryImp.resetRouteRow.set_title(&format!("{}, {}, {}, {}", addr, prefix, gateway, metric));
// }
let entryImp = entry.imp();
if let Some(address) = address {
let conn = conn.borrow();
let address = unsafe { conn.ipv4.route_data.get_unchecked(address) };
entryImp.resetRouteAddress.set_text(&address.address);
entryImp
.resetRoutePrefix
.set_text(&address.prefix_length.to_string());
if let Some(gateway) = &address.gateway {
entryImp.resetRouteGateway.set_text(gateway);
}
if let Some(metric) = address.metric {
entryImp.resetRouteMetric.set_text(&metric.to_string());
}
entryImp
.resetRouteRow
.set_title(&format!("{}/{}", &*address.address, address.prefix_length));
}
entryImp.protocol.set(protocol);
entry.setupCallbacks(conn);
entry
}
fn setupCallbacks(&self, connection: Rc<RefCell<Connection>>) {
let selfImp = self.imp();
let conn = connection.clone();
selfImp.resetRouteAddress.connect_changed(clone!(@weak selfImp => move |entry| {
let addressInput = entry.text();
let mut conn = conn.borrow_mut();
if addressInput.is_empty() {
selfImp.resetRouteAddress.remove_css_class("error");
selfImp.resetRouteRow.set_title("Add new address");
return;
}
let result = match selfImp.protocol.get() {
IpProtocol::IPv4 => Ipv4Addr::from_str(addressInput.as_str()).map(IpAddr::V4),
IpProtocol::IPv6 => Ipv6Addr::from_str(addressInput.as_str()).map(IpAddr::V6),
};
match result {
Ok(ipAddr) => {
selfImp.resetRouteAddress.remove_css_class("error");
let addressData = match selfImp.protocol.get() {
IpProtocol::IPv4 => &mut conn.ipv4.route_data,
IpProtocol::IPv6 => &mut conn.ipv6.route_data,
};
addressData.push(Address::new(ipAddr.to_string(), selfImp.prefix.get().1 as u32, selfImp.gateway.borrow().clone(), selfImp.metric.get()));
*selfImp.address.borrow_mut() = (true, ipAddr.to_string());
}
Err(_) => {
selfImp.resetRouteAddress.add_css_class("error");
*selfImp.address.borrow_mut() = (false, String::default());
}
}
setRowTitle(&selfImp);
}));
let conn = connection.clone();
selfImp.resetRoutePrefix.connect_changed(clone!(@weak selfImp => move |entry| {
let prefixInput = entry.text();
let prefix = prefixInput.parse::<u8>();
let mut conn = conn.borrow_mut();
let handleError = || {
if selfImp.resetRoutePrefix.text().is_empty() {
selfImp.resetRoutePrefix.remove_css_class("error");
} else {
selfImp.resetRoutePrefix.add_css_class("error");
}
selfImp.prefix.set((false, 0));
setRowTitle(&selfImp);
};
if prefixInput.is_empty() || prefix.is_err() {
handleError();
return;
}
let prefix = prefix.unwrap();
match selfImp.protocol.get() {
IpProtocol::IPv4 if prefix <= 32 => {
selfImp.prefix.set((true, prefix as u32));
selfImp.resetRoutePrefix.remove_css_class("error");
if let Ok(address2) = Ipv4Addr::from_str(selfImp.resetRouteAddress.text().as_str()) {
if let Some(addr) = conn.ipv4.route_data.iter_mut()
.find(|connAddr| *connAddr.address == address2.to_string()) {
addr.prefix_length = prefix as u32;
}
}
}
IpProtocol::IPv6 if prefix <= 128 => {
selfImp.prefix.set((true, prefix as u32));
selfImp.resetRoutePrefix.remove_css_class("error");
if let Ok(address2) = Ipv6Addr::from_str(selfImp.resetRouteAddress.text().as_str()) {
if let Some(addr) = conn.ipv6.route_data.iter_mut()
.find(|connAddr| *connAddr.address == address2.to_string()) {
addr.prefix_length = prefix as u32;
}
}
}
_ => handleError()
}
setRowTitle(&selfImp);
}));
let conn = connection.clone();
selfImp
.resetRouteGateway
.connect_changed(clone!(@weak selfImp => move |entry| {
let gatewayInput = entry.text();
let mut conn = conn.borrow_mut();
if gatewayInput.is_empty() {
selfImp.resetRouteGateway.remove_css_class("error");
*selfImp.gateway.borrow_mut() = None;
setRowSubtitle(&selfImp);
return;
}
let result = match selfImp.protocol.get() {
IpProtocol::IPv4 => Ipv4Addr::from_str(gatewayInput.as_str()).map(IpAddr::V4),
IpProtocol::IPv6 => Ipv6Addr::from_str(gatewayInput.as_str()).map(IpAddr::V6),
};
match result {
Ok(ipAddr) => {
selfImp.resetRouteGateway.remove_css_class("error");
let addressData = match selfImp.protocol.get() {
IpProtocol::IPv4 => &mut conn.ipv4.route_data,
IpProtocol::IPv6 => &mut conn.ipv6.route_data,
};
if let Some(address) = addressData.iter_mut()
.find(|connAddr| *connAddr.address == selfImp.resetRouteAddress.text()) {
address.gateway = Some(ipAddr.to_string());
}
*selfImp.gateway.borrow_mut() = Some(ipAddr.to_string());
}
Err(_) => {
selfImp.resetRouteGateway.add_css_class("error");
*selfImp.gateway.borrow_mut() = None;
}
}
setRowSubtitle(&selfImp);
}));
let conn = connection.clone();
selfImp
.resetRouteMetric
.connect_changed(clone!(@weak selfImp => move |entry| {
let metricInput = entry.text();
let mut conn = conn.borrow_mut();
if metricInput.is_empty() {
selfImp.resetRouteMetric.remove_css_class("error");
selfImp.metric.set(None);
setRowSubtitle(&selfImp);
return;
}
let result = metricInput.parse::<u32>();
match result {
Ok(metric) => {
selfImp.resetRouteMetric.remove_css_class("error");
let addressData = match selfImp.protocol.get() {
IpProtocol::IPv4 => &mut conn.ipv4.route_data,
IpProtocol::IPv6 => &mut conn.ipv6.route_data,
};
if let Some(address) = addressData.iter_mut()
.find(|connAddr| *connAddr.address == selfImp.resetRouteAddress.text()) {
address.metric = Some(metric);
}
selfImp.metric.set(Some(metric));
}
Err(_) => {
selfImp.resetRouteMetric.add_css_class("error");
selfImp.metric.set(None);
}
}
setRowSubtitle(&selfImp);
}));
}
}
fn setRowTitle(selfImp: &WifiRouteEntryImpl) {
if selfImp.resetRouteAddress.text().is_empty() {
return;
}
let address = selfImp.address.borrow();
let prefix = selfImp.prefix.get();
let title = match (address.0, prefix.0) {
(true, true) => {
format!("{}/{}", address.1, prefix.1)
}
(true, false) => "Prefix wrong".to_string(),
(false, true) => "Address wrong".to_string(),
(false, false) => "Address and Prefix wrong".to_string(),
};
selfImp.resetRouteRow.set_title(&title);
}
fn setRowSubtitle(selfImp: &WifiRouteEntryImpl) {
let gateway = selfImp.gateway.borrow().clone();
let metric = selfImp.metric.get();
let title = match (gateway, metric) {
(Some(gateway), Some(metric)) => {
format!("{}, {}", gateway, metric)
}
(Some(gateway), None) => gateway,
(None, Some(metric)) => metric.to_string(),
(None, None) => String::default(),
};
selfImp.resetRouteRow.set_subtitle(&title);
}

View file

@ -1,7 +1,9 @@
use crate::components::wifi::utils::IpProtocol;
use crate::components::wifi::wifiRouteEntry;
use adw::{EntryRow, ExpanderRow};
use gtk::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate};
use std::cell::{Cell, RefCell};
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
@ -12,13 +14,18 @@ pub struct WifiRouteEntryImpl {
#[template_child]
pub resetRouteAddress: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteNetmask: TemplateChild<EntryRow>,
pub resetRoutePrefix: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteGateway: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteMetric: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteRemove: TemplateChild<Button>,
pub address: RefCell<(bool, String)>,
pub prefix: Cell<(bool, u32)>,
pub gateway: RefCell<Option<String>>,
pub metric: Cell<Option<u32>>,
pub protocol: Cell<IpProtocol>,
}
#[glib::object_subclass]

View file

@ -4,24 +4,26 @@ use std::sync::Arc;
use crate::components::base::settingBox::SettingBox;
use crate::components::base::utils::{start_audio_listener, Listeners};
use crate::components::bluetooth::bluetoothBox::{start_bluetooth_listener, BluetoothBox, populate_conntected_bluetooth_devices};
use crate::components::bluetooth::bluetoothBox::{
populate_conntected_bluetooth_devices, start_bluetooth_listener, BluetoothBox,
};
use crate::components::input::sourceBox::{populate_sources, SourceBox};
use crate::components::output::sinkBox::{populate_sinks, SinkBox};
use crate::components::wifi::wifiBox::{
scanForWifi, show_stored_connections, start_event_listener, WifiBox,
};
use gtk::prelude::WidgetExt;
use gtk::{FlowBox, Frame, Label};
use gtk::{FlowBox, Frame};
pub const HANDLE_CONNECTIVITY_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_audio_listener();
let wifiBox = Arc::new(WifiBox::new());
let wifiBox = WifiBox::new(listeners.clone());
start_event_listener(listeners.clone(), wifiBox.clone());
show_stored_connections(wifiBox.clone());
scanForWifi(listeners.clone(), wifiBox.clone());
scanForWifi(wifiBox.clone());
let wifiFrame = wrapInFrame(SettingBox::new(&*wifiBox));
let bluetooth_box = Arc::new(BluetoothBox::new());
let bluetooth_box = BluetoothBox::new(listeners.clone());
populate_conntected_bluetooth_devices(bluetooth_box.clone());
start_bluetooth_listener(listeners.clone(), bluetooth_box.clone());
let bluetoothFrame = wrapInFrame(SettingBox::new(&*bluetooth_box));
@ -35,10 +37,10 @@ pub const HANDLE_WIFI_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_audio_listener();
listeners.stop_bluetooth_listener();
let wifiBox = Arc::new(WifiBox::new());
let wifiBox = WifiBox::new(listeners.clone());
start_event_listener(listeners.clone(), wifiBox.clone());
show_stored_connections(wifiBox.clone());
scanForWifi(listeners.clone(), wifiBox.clone());
scanForWifi(wifiBox.clone());
let wifiFrame = wrapInFrame(SettingBox::new(&*wifiBox));
resetMain.remove_all();
resetMain.insert(&wifiFrame, -1);
@ -49,7 +51,7 @@ pub const HANDLE_BLUETOOTH_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
listeners.stop_audio_listener();
let bluetooth_box = Arc::new(BluetoothBox::new());
let bluetooth_box = BluetoothBox::new(listeners.clone());
start_bluetooth_listener(listeners.clone(), bluetooth_box.clone());
populate_conntected_bluetooth_devices(bluetooth_box.clone());
let bluetoothFrame = wrapInFrame(SettingBox::new(&*bluetooth_box));
@ -58,17 +60,6 @@ pub const HANDLE_BLUETOOTH_CLICK: fn(Arc<Listeners>, FlowBox) =
resetMain.set_max_children_per_line(1);
};
pub const HANDLE_VPN_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
listeners.stop_bluetooth_listener();
listeners.stop_audio_listener();
let label = Label::new(Some("not implemented yet"));
resetMain.remove_all();
resetMain.insert(&label, -1);
resetMain.set_max_children_per_line(1);
};
pub const HANDLE_AUDIO_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
@ -96,7 +87,9 @@ pub const HANDLE_VOLUME_CLICK: fn(Arc<Listeners>, FlowBox) =
listeners.stop_bluetooth_listener();
let audioOutput = Arc::new(SinkBox::new());
start_audio_listener(listeners.clone(), Some(audioOutput.clone()), None);
while !listeners.pulse_listener.load(Ordering::SeqCst) { std::hint::spin_loop() }
while !listeners.pulse_listener.load(Ordering::SeqCst) {
std::hint::spin_loop()
}
populate_sinks(audioOutput.clone());
let audioFrame = wrapInFrame(SettingBox::new(&*audioOutput));
resetMain.remove_all();
@ -117,50 +110,6 @@ pub const HANDLE_MICROPHONE_CLICK: fn(Arc<Listeners>, FlowBox) =
resetMain.set_max_children_per_line(1);
};
pub const HANDLE_PERIPHERALS_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
listeners.stop_audio_listener();
listeners.stop_bluetooth_listener();
let label = Label::new(Some("not implemented yet"));
resetMain.remove_all();
resetMain.insert(&label, -1);
resetMain.set_max_children_per_line(1);
};
pub const HANDLE_MONITOR_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
listeners.stop_audio_listener();
listeners.stop_bluetooth_listener();
let label = Label::new(Some("not implemented yet"));
resetMain.remove_all();
resetMain.insert(&label, -1);
resetMain.set_max_children_per_line(1);
};
pub const HANDLE_MOUSE_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
listeners.stop_audio_listener();
listeners.stop_bluetooth_listener();
let label = Label::new(Some("not implemented yet"));
resetMain.remove_all();
resetMain.insert(&label, -1);
resetMain.set_max_children_per_line(1);
};
pub const HANDLE_KEYBOARD_CLICK: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
listeners.stop_audio_listener();
listeners.stop_bluetooth_listener();
let label = Label::new(Some("not implemented yet"));
resetMain.remove_all();
resetMain.insert(&label, -1);
resetMain.set_max_children_per_line(1);
};
pub const HANDLE_HOME: fn(Arc<Listeners>, FlowBox) =
|listeners: Arc<Listeners>, resetMain: FlowBox| {
listeners.stop_network_listener();
@ -175,3 +124,60 @@ fn wrapInFrame(widget: SettingBox) -> Frame {
frame.add_css_class("resetSettingFrame");
frame
}
// for future implementations
// pub const HANDLE_VPN_CLICK: fn(Arc<Listeners>, FlowBox) =
// |listeners: Arc<Listeners>, resetMain: FlowBox| {
// listeners.stop_network_listener();
// listeners.stop_bluetooth_listener();
// listeners.stop_audio_listener();
// let label = Label::new(Some("not implemented yet"));
// resetMain.remove_all();
// resetMain.insert(&label, -1);
// resetMain.set_max_children_per_line(1);
// };
//
// pub const HANDLE_PERIPHERALS_CLICK: fn(Arc<Listeners>, FlowBox) =
// |listeners: Arc<Listeners>, resetMain: FlowBox| {
// listeners.stop_network_listener();
// listeners.stop_audio_listener();
// listeners.stop_bluetooth_listener();
// let label = Label::new(Some("not implemented yet"));
// resetMain.remove_all();
// resetMain.insert(&label, -1);
// resetMain.set_max_children_per_line(1);
// };
//
// pub const HANDLE_MONITOR_CLICK: fn(Arc<Listeners>, FlowBox) =
// |listeners: Arc<Listeners>, resetMain: FlowBox| {
// listeners.stop_network_listener();
// listeners.stop_audio_listener();
// listeners.stop_bluetooth_listener();
// let label = Label::new(Some("not implemented yet"));
// resetMain.remove_all();
// resetMain.insert(&label, -1);
// resetMain.set_max_children_per_line(1);
// };
//
// pub const HANDLE_MOUSE_CLICK: fn(Arc<Listeners>, FlowBox) =
// |listeners: Arc<Listeners>, resetMain: FlowBox| {
// listeners.stop_network_listener();
// listeners.stop_audio_listener();
// listeners.stop_bluetooth_listener();
// let label = Label::new(Some("not implemented yet"));
// resetMain.remove_all();
// resetMain.insert(&label, -1);
// resetMain.set_max_children_per_line(1);
// };
//
// pub const HANDLE_KEYBOARD_CLICK: fn(Arc<Listeners>, FlowBox) =
// |listeners: Arc<Listeners>, resetMain: FlowBox| {
// listeners.stop_network_listener();
// listeners.stop_audio_listener();
// listeners.stop_bluetooth_listener();
// let label = Label::new(Some("not implemented yet"));
// resetMain.remove_all();
// resetMain.insert(&label, -1);
// resetMain.set_max_children_per_line(1);
// };
//

View file

@ -1,6 +1,6 @@
#![allow(non_snake_case)]
pub mod handleSidebarClick;
pub mod resetWindow;
pub mod resetWindowImpl;
pub mod sidebarEntry;
pub mod sidebarEntryImpl;
pub mod window;
pub mod windowImpl;

View file

@ -1,28 +1,28 @@
use adw::BreakpointCondition;
use adw::glib::clone;
use adw::subclass::prelude::ObjectSubclassIsExt;
use adw::BreakpointCondition;
use glib::Object;
use gtk::{Application, gio, glib, ListBoxRow, Orientation};
use gtk::prelude::*;
use gtk::{gio, glib, Application, ListBoxRow, Orientation};
use crate::components::window::handleSidebarClick::*;
use crate::components::window::resetWindowImpl;
use crate::components::window::sidebarEntry::SidebarEntry;
use crate::components::window::sidebarEntryImpl::Categories;
use crate::components::window::windowImpl;
glib::wrapper! {
pub struct Window(ObjectSubclass<windowImpl::Window>)
pub struct ReSetWindow(ObjectSubclass<resetWindowImpl::ReSetWindow>)
@extends gtk::ApplicationWindow, gtk::Window, gtk::Widget,
@implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
}
unsafe impl Send for Window {}
unsafe impl Send for ReSetWindow {}
unsafe impl Sync for Window {}
unsafe impl Sync for ReSetWindow {}
#[allow(non_snake_case)]
impl Window {
impl ReSetWindow {
pub fn new(app: &Application) -> Self {
Object::builder().property("application", app).build()
}
@ -30,11 +30,15 @@ impl Window {
pub fn setupCallback(&self) {
let selfImp = self.imp();
selfImp.resetSearchEntry.connect_search_changed(clone!(@ weak self as window => move |_| {
selfImp
.resetSearchEntry
.connect_search_changed(clone!(@ weak self as window => move |_| {
window.filterList();
}));
selfImp.resetSideBarToggle.connect_clicked(clone!(@ weak self as window => move |_| {
selfImp
.resetSideBarToggle
.connect_clicked(clone!(@ weak self as window => move |_| {
window.toggleSidebar();
}));
@ -46,7 +50,9 @@ impl Window {
}),
);
selfImp.resetClose.connect_clicked(clone!(@ weak self as window => move |_| {
selfImp
.resetClose
.connect_clicked(clone!(@ weak self as window => move |_| {
window.close();
}));
@ -58,7 +64,9 @@ impl Window {
pub fn handleDynamicSidebar(&self) {
let selfImp = self.imp();
selfImp.resetSidebarBreakpoint.set_condition(BreakpointCondition::parse("max-width: 700sp").as_ref().ok());
selfImp
.resetSidebarBreakpoint
.set_condition(BreakpointCondition::parse("max-width: 700sp").as_ref().ok());
selfImp.resetSidebarBreakpoint.add_setter(
&Object::from(selfImp.resetOverlaySplitView.get()),
"collapsed",
@ -81,13 +89,25 @@ impl Window {
}
continue;
}
if mainEntry.imp().name.borrow().to_lowercase().contains(&text.to_lowercase()) {
if mainEntry
.imp()
.name
.borrow()
.to_lowercase()
.contains(&text.to_lowercase())
{
mainEntry.set_visible(true);
} else {
mainEntry.set_visible(false);
}
for subEntry in subEntries {
if subEntry.imp().name.borrow().to_lowercase().contains(&text.to_lowercase()) {
if subEntry
.imp()
.name
.borrow()
.to_lowercase()
.contains(&text.to_lowercase())
{
subEntry.set_visible(true);
mainEntry.set_visible(true);
} else {
@ -124,13 +144,13 @@ impl Window {
true,
HANDLE_BLUETOOTH_CLICK,
),
SidebarEntry::new(
"VPN",
"network-vpn-symbolic",
Categories::Connectivity,
true,
HANDLE_VPN_CLICK,
),
// SidebarEntry::new(
// "VPN",
// "network-vpn-symbolic",
// Categories::Connectivity,
// true,
// HANDLE_VPN_CLICK,
// ),
];
sidebarEntries.push((
@ -172,44 +192,46 @@ impl Window {
audioList,
));
let peripheralsList = vec![
SidebarEntry::new(
"Displays",
"video-display-symbolic",
Categories::Peripherals,
true,
HANDLE_MONITOR_CLICK,
),
SidebarEntry::new(
"Mouse",
"input-mouse-symbolic",
Categories::Peripherals,
true,
HANDLE_MOUSE_CLICK,
),
SidebarEntry::new(
"Keyboard",
"input-keyboard-symbolic",
Categories::Peripherals,
true,
HANDLE_KEYBOARD_CLICK,
),
];
// let peripheralsList = vec![
// SidebarEntry::new(
// "Displays",
// "video-display-symbolic",
// Categories::Peripherals,
// true,
// HANDLE_MONITOR_CLICK,
// ),
// SidebarEntry::new(
// "Mouse",
// "input-mouse-symbolic",
// Categories::Peripherals,
// true,
// HANDLE_MOUSE_CLICK,
// ),
// SidebarEntry::new(
// "Keyboard",
// "input-keyboard-symbolic",
// Categories::Peripherals,
// true,
// HANDLE_KEYBOARD_CLICK,
// ),
// ];
sidebarEntries.push((
SidebarEntry::new(
"Peripherals",
"preferences-system-devices-symbolic",
Categories::Peripherals,
false,
HANDLE_PERIPHERALS_CLICK,
),
peripheralsList,
));
// sidebarEntries.push((
// SidebarEntry::new(
// "Peripherals",
// "preferences-system-devices-symbolic",
// Categories::Peripherals,
// false,
// HANDLE_PERIPHERALS_CLICK,
// ),
// peripheralsList,
// ));
selfImp.resetSidebarList.connect_row_activated(clone!(@ weak selfImp => move |_, _| {
selfImp.resetSearchEntry.set_text("");
}));
selfImp
.resetSidebarList
.connect_row_activated(clone!(@ weak selfImp => move |_, _| {
selfImp.resetSearchEntry.set_text("");
}));
for (mainEntry, subEntries) in sidebarEntries.iter() {
selfImp.resetSidebarList.append(mainEntry);
@ -226,7 +248,9 @@ impl Window {
pub fn setupPopoverButtons(&self) {
let selfImp = self.imp();
selfImp.resetAboutButton.connect_clicked(clone!(@ weak self as window => move |_| {
selfImp
.resetAboutButton
.connect_clicked(clone!(@ weak self as window => move |_| {
let dialog = adw::AboutWindow::builder()
.application_name("ReSet")
.application_icon("ReSet")
@ -245,12 +269,16 @@ impl Window {
window.imp().resetPopoverMenu.popdown();
dialog.present();
}));
selfImp.resetPreferenceButton.connect_clicked(clone!(@weak self as window => move |_| {
selfImp
.resetPreferenceButton
.connect_clicked(clone!(@weak self as window => move |_| {
let preferences = adw::PreferencesWindow::builder().build();
window.imp().resetPopoverMenu.popdown();
preferences.present();
}));
selfImp.resetShortcutsButton.connect_clicked(clone!(@weak self as window => move |_| {
selfImp
.resetShortcutsButton
.connect_clicked(clone!(@weak self as window => move |_| {
let shortcuts = gtk::ShortcutsWindow::builder().build();
window.imp().resetPopoverMenu.popdown();
shortcuts.present();

View file

@ -10,13 +10,13 @@ use gtk::{glib, Button, CompositeTemplate, FlowBox, ListBox, PopoverMenu, Search
use crate::components::base::utils::Listeners;
use crate::components::wifi::wifiBox::WifiBox;
use crate::components::window::resetWindow;
use crate::components::window::sidebarEntry::SidebarEntry;
use crate::components::window::window;
#[allow(non_snake_case)]
#[derive(CompositeTemplate, Default)]
#[template(resource = "/org/Xetibo/ReSet/resetMainWindow.ui")]
pub struct Window {
pub struct ReSetWindow {
#[template_child]
pub resetMain: TemplateChild<FlowBox>,
#[template_child]
@ -43,14 +43,14 @@ pub struct Window {
pub listeners: Arc<Listeners>,
}
unsafe impl Send for Window {}
unsafe impl Sync for Window {}
unsafe impl Send for ReSetWindow {}
unsafe impl Sync for ReSetWindow {}
#[glib::object_subclass]
impl ObjectSubclass for Window {
impl ObjectSubclass for ReSetWindow {
const ABSTRACT: bool = false;
const NAME: &'static str = "resetUI";
type Type = window::Window;
type Type = resetWindow::ReSetWindow;
type ParentType = adw::ApplicationWindow;
fn class_init(klass: &mut Self::Class) {
@ -63,7 +63,7 @@ impl ObjectSubclass for Window {
}
}
impl ObjectImpl for Window {
impl ObjectImpl for ReSetWindow {
fn constructed(&self) {
self.parent_constructed();
@ -75,10 +75,10 @@ impl ObjectImpl for Window {
}
}
impl WidgetImpl for Window {}
impl WidgetImpl for ReSetWindow {}
impl WindowImpl for Window {}
impl WindowImpl for ReSetWindow {}
impl ApplicationWindowImpl for Window {}
impl ApplicationWindowImpl for ReSetWindow {}
impl AdwApplicationWindowImpl for Window {}
impl AdwApplicationWindowImpl for ReSetWindow {}

View file

@ -3,6 +3,7 @@
use std::thread;
use std::time::Duration;
use components::window::resetWindow::ReSetWindow;
use dbus::blocking::Connection;
use dbus::Error;
use gtk::gdk::Display;
@ -10,8 +11,6 @@ use gtk::prelude::*;
use gtk::{gio, Application, CssProvider};
use reset_daemon::run_daemon;
use crate::components::window::window::Window;
mod components;
const APP_ID: &str = "org.Xetibo.ReSet";
@ -49,7 +48,7 @@ fn loadCss() {
#[allow(non_snake_case)]
fn buildUI(app: &Application) {
let window = Window::new(app);
let window = ReSetWindow::new(app);
window.present();
}

View file

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.17.0 -->
<interface>
<requires lib="gtk" version="4.6"/>
<requires lib="gtk" version="4.12"/>
<requires lib="libadwaita" version="1.4"/>
<template class="resetBluetooth" parent="GtkBox">
<property name="orientation">vertical</property>
@ -39,8 +39,8 @@
<child>
<object class="AdwPreferencesGroup" id="resetBluetoothDetails">
<child>
<object class="AdwComboRow" id="resetBluetoothDevice">
<property name="title">Bluetooth Device</property>
<object class="AdwComboRow" id="resetBluetoothAdapter">
<property name="title">Bluetooth Adapter</property>
</object>
</child>
<child>
@ -59,17 +59,14 @@
</object>
</child>
<child>
<object class="GtkBox">
<property name="margin-top">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="justify">right</property>
<property name="label">Available devices</property>
<property name="margin-start">5</property>
<object class="AdwPreferencesGroup">
<property name="header-suffix">
<object class="GtkButton" id="resetBluetoothRefreshButton">
<property name="icon-name">view-refresh-symbolic</property>
</object>
</child>
</property>
<property name="margin-top">10</property>
<property name="title">Available Devices</property>
<child>
<object class="GtkScrolledWindow">
<property name="min-content-height">100</property>
@ -77,14 +74,8 @@
<child>
<object class="GtkViewport">
<child>
<object class="GtkListBox" id="resetBluetoothAvailableDevices">
<property name="css-classes">boxed-list
</property>
<property name="margin-end">5</property>
<property name="margin-start">5</property>
<property name="margin-top">5</property>
<property name="show-separators">True</property>
<property name="valign">start</property>
<object class="GtkBox" id="resetBluetoothAvailableDevices">
<property name="orientation">vertical</property>
</object>
</child>
</object>
@ -94,17 +85,8 @@
</object>
</child>
<child>
<object class="GtkBox">
<property name="margin-top">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="justify">right</property>
<property name="label">Connected devices</property>
<property name="margin-start">5</property>
</object>
</child>
<object class="AdwPreferencesGroup">
<property name="title">Connected Devices</property>
<child>
<object class="GtkScrolledWindow">
<property name="min-content-height">100</property>
@ -112,14 +94,8 @@
<child>
<object class="GtkViewport">
<child>
<object class="GtkListBox" id="resetBluetoothConnectedDevices">
<property name="css-classes">boxed-list
</property>
<property name="margin-end">5</property>
<property name="margin-start">5</property>
<property name="margin-top">5</property>
<property name="show-separators">True</property>
<property name="valign">start</property>
<object class="GtkBox" id="resetBluetoothConnectedDevices">
<property name="orientation">vertical</property>
</object>
</child>
</object>

View file

@ -44,7 +44,7 @@
<child>
<object class="GtkButton" id="resetBluetoothButton">
<property name="has-frame">False</property>
<property name="icon-name">user-trash-symbolic</property>
<property name="icon-name">emblem-system-symbolic</property>
</object>
</child>
</template>

View file

@ -21,7 +21,8 @@
(20,None,None,"resetCardEntry.ui",None,None,None,None,None,None,None),
(21,1,None,"resetWifiOptions.ui",None,None,None,None,None,None,None),
(22,1,None,"resetWifiAddressEntry.ui",None,None,None,None,None,None,None),
(23,1,None,"resetWifiRouteEntry.ui",None,None,None,None,None,None,None)
(23,1,None,"resetWifiRouteEntry.ui",None,None,None,None,None,None,None),
(24,None,None,None,None,None,None,None,None,None,None)
</ui>
<ui_library>
(21,"gtk","4.12",None),
@ -54,11 +55,7 @@
(4,7,"GtkBox","resetWifi",None,None,None,None,None,None),
(4,152,"AdwNavigationView","resetWifiNavigation",7,None,None,None,1,None),
(4,153,"AdwNavigationPage",None,152,None,None,None,None,None),
(4,154,"GtkBox",None,153,None,None,None,None,None),
(4,164,"GtkBox",None,154,None,None,None,1,None),
(4,165,"GtkLabel",None,164,None,None,None,None,None),
(4,166,"GtkScrolledWindow",None,164,None,None,None,1,None),
(4,167,"GtkViewport",None,166,None,None,None,None,None),
(4,154,"GtkBox",None,153,None,None,None,1,None),
(4,174,"AdwNavigationPage",None,152,None,None,None,2,None),
(4,175,"GtkBox",None,174,None,None,None,None,None),
(4,182,"GtkBox",None,7,None,None,None,None,None),
@ -68,20 +65,20 @@
(4,200,"AdwComboRow","resetWiFiDevice",199,None,None,None,-1,None),
(4,201,"AdwActionRow","resetSavedNetworks",199,None,None,None,-1,None),
(4,202,"GtkImage",None,201,None,None,None,None,None),
(4,203,"AdwPreferencesGroup","resetWifiList",167,None,None,None,-1,None),
(4,204,"AdwPreferencesGroup","resetStoredWifiList",175,None,None,None,2,None),
(4,205,"AdwPreferencesGroup",None,175,None,None,None,None,None),
(4,206,"AdwActionRow","resetAvailableNetworks",205,None,None,None,-1,None),
(4,207,"GtkImage",None,206,None,None,None,None,None),
(4,208,"AdwPreferencesGroup","resetWifiList",154,None,None,None,1,None),
(5,12,"AdwActionRow","resetWifiEntry",None,None,None,None,-1,None),
(5,13,"GtkBox",None,12,None,None,None,None,None),
(5,14,"GtkBox",None,13,None,None,None,None,None),
(5,15,"GtkImage","resetWifiStrength",14,None,None,None,None,None),
(5,16,"GtkImage","resetWifiEncrypted",14,None,None,None,1,None),
(5,18,"GtkLabel","resetWifiLabel",13,None,None,None,1,None),
(5,19,"GtkImage","resetWifiConnected",13,None,None,None,3,None),
(5,20,"GtkButton","resetWifiEditButton",13,None,None,None,2,None),
(5,20,"GtkButton","resetWifiEditButton",13,None,None,None,3,None),
(5,21,"resetPopup","resetWifiPopup",13,None,None,None,4,None),
(5,22,"GtkLabel","resetWifiConnected",13,None,None,None,2,None),
(6,1,"GtkListBoxRow","resetSidebarEntry",None,None,None,None,None,None),
(6,2,"GtkBox",None,1,None,None,None,-1,None),
(6,6,"GtkImage","resetSidebarImage",2,None,None,None,None,None),
@ -137,16 +134,6 @@
(10,119,"AdwNavigationView",None,1,None,None,None,1,None),
(10,120,"AdwNavigationPage",None,119,None,None,None,None,None),
(10,121,"GtkBox",None,120,None,None,None,None,None),
(10,127,"GtkBox",None,121,None,None,None,1,None),
(10,128,"GtkLabel",None,127,None,None,None,None,None),
(10,129,"GtkScrolledWindow",None,127,None,None,None,1,None),
(10,130,"GtkViewport",None,129,None,None,None,None,None),
(10,131,"GtkListBox","resetBluetoothAvailableDevices",130,None,None,None,None,None),
(10,132,"GtkBox",None,121,None,None,None,2,None),
(10,133,"GtkLabel",None,132,None,None,None,None,None),
(10,134,"GtkScrolledWindow",None,132,None,None,None,1,None),
(10,135,"GtkViewport",None,134,None,None,None,None,None),
(10,136,"GtkListBox","resetBluetoothConnectedDevices",135,None,None,None,None,None),
(10,138,"AdwNavigationPage",None,119,None,None,None,1,None),
(10,142,"GtkBox",None,1,None,None,None,None,None),
(10,143,"GtkLabel",None,142,None,None,None,None,None),
@ -159,15 +146,24 @@
(10,158,"GtkImage",None,156,None,None,None,1,None),
(10,159,"GtkLabel",None,153,None,None,None,1,None),
(10,172,"AdwPreferencesGroup","resetBluetoothDetails",121,None,None,None,None,None),
(10,173,"AdwComboRow","resetBluetoothDevice",172,None,None,None,None,None),
(10,173,"AdwComboRow","resetBluetoothAdapter",172,None,None,None,None,None),
(10,174,"AdwActionRow","resetVisibility",172,None,None,None,1,None),
(10,175,"GtkImage",None,174,None,None,None,None,None),
(10,176,"AdwPreferencesGroup",None,121,None,None,None,1,None),
(10,177,"GtkButton","resetBluetoothRefreshButton",176,None,None,None,None,None),
(10,178,"GtkScrolledWindow",None,176,None,None,None,None,None),
(10,179,"GtkViewport",None,178,None,None,None,None,None),
(10,180,"GtkBox","resetBluetoothAvailableDevices",179,None,None,None,None,None),
(10,181,"AdwPreferencesGroup",None,121,None,None,None,2,None),
(10,183,"GtkScrolledWindow",None,181,None,None,None,None,None),
(10,184,"GtkViewport",None,183,None,None,None,None,None),
(10,185,"GtkBox","resetBluetoothConnectedDevices",184,None,None,None,None,None),
(11,2,"GtkBox","resetBluetoothEntry",None,None,None,None,None,None),
(11,3,"GtkImage","resetBluetoothDeviceType",2,None,None,None,None,None),
(11,5,"GtkButton","resetBluetoothButton",2,None,None,None,3,None),
(11,6,"GtkBox",None,2,None,None,None,1,None),
(11,6,"GtkBox",None,2,None,None,None,2,None),
(11,7,"GtkLabel","resetBluetoothLabel",6,None,None,None,None,None),
(11,8,"GtkLabel","resetBluetoothAddress",6,None,None,None,2,None),
(11,8,"GtkLabel","resetBluetoothAddress",6,None,None,None,1,None),
(12,11,"GtkBox","resetAudioInput",None,None,None,None,None,None),
(12,12,"GtkLabel",None,11,None,None,None,None,None),
(12,13,"AdwNavigationView",None,11,None,None,None,1,None),
@ -294,26 +290,40 @@
(21,90,"GtkLabel",None,53,None,"tab",None,5,None),
(21,91,"GtkBox",None,53,None,None,None,6,None),
(21,92,"AdwPreferencesGroup",None,91,None,None,None,None,None),
(21,93,"AdwComboRow",None,92,None,None,None,None,None),
(21,94,"GtkStringList",None,93,None,None,None,None,None),
(21,95,"AdwEntryRow",None,92,None,None,None,1,None),
(21,96,"AdwPasswordEntryRow",None,92,None,None,None,2,None),
(21,93,"AdwComboRow","resetWifiSecurityDropdown",92,None,None,None,None,None),
(21,96,"AdwPasswordEntryRow","resetWifiPassword",92,None,None,None,1,None),
(21,97,"GtkLabel",None,53,None,"tab",None,7,None),
(21,98,"GtkButton","wifiOptionsApplyButton",52,None,None,None,1,None),
(21,99,"GtkButton","resetIP4AddressAddButton",73,None,None,None,-1,None),
(21,100,"GtkButton","resetIP4RouteAddButton",75,None,None,None,2,None),
(21,101,"GtkButton","resetIP6AddressAddButton",85,None,None,None,-1,None),
(21,102,"GtkButton","resetIP6RouteAddButton",87,None,None,None,2,None),
(21,103,"GtkStringList",None,93,None,None,None,-1,None),
(22,1,"GtkBox","resetWifiAddressEntry",None,None,None,None,-1,None),
(22,2,"AdwExpanderRow","resetAddressRow",1,None,None,None,-1,None),
(22,3,"AdwEntryRow","resetAddressAddress",2,None,None,None,-1,None),
(22,4,"AdwEntryRow","resetAddressPrefix",2,None,None,None,1,None),
(22,5,"GtkButton","resetAddressRemove",1,None,None,None,-1,None),
(22,6,"GtkBox",None,2,None,None,None,None,None),
(22,7,"AdwEntryRow","resetAddressAddress",6,None,None,None,None,None),
(22,8,"AdwEntryRow","resetAddressPrefix",6,None,None,None,1,None),
(23,1,"GtkBox","resetWifiRouteEntry",None,None,None,None,None,None),
(23,2,"AdwExpanderRow","resetRouteRow",1,None,None,None,None,None),
(23,3,"AdwEntryRow","resetRouteAddress",2,None,None,None,None,None),
(23,4,"AdwEntryRow","resetRouteNetmask",2,None,None,None,1,None),
(23,5,"GtkButton","resetRouteRemove",1,None,None,None,1,None),
(23,6,"GtkBox",None,2,None,None,None,2,None),
(23,6,"GtkBox",None,2,None,None,None,1,None),
(23,7,"AdwEntryRow","resetRouteGateway",6,None,None,None,None,None),
(23,8,"AdwEntryRow","resetRouteMetric",6,None,None,None,1,None)
(23,8,"AdwEntryRow","resetRouteMetric",6,None,None,None,1,None),
(23,9,"GtkBox",None,2,None,None,None,None,None),
(23,10,"AdwEntryRow","resetRouteAddress",9,None,None,None,None,None),
(23,11,"AdwEntryRow","resetRoutePrefix",9,None,None,None,1,None),
(24,1,"AdwPreferencesGroup",None,None,None,None,None,-1,None),
(24,4,"GtkButton",None,1,None,None,None,-1,None),
(24,5,"GtkScrolledWindow",None,1,None,None,None,None,None),
(24,6,"GtkViewport",None,5,None,None,None,None,None),
(24,9,"GtkBox",None,6,None,None,None,None,None),
(24,10,"AdwActionRow",None,9,None,None,None,None,None),
(24,11,"AdwActionRow",None,9,None,None,None,1,None),
(24,12,"AdwActionRow",None,9,None,None,None,2,None),
(24,13,"AdwActionRow",None,9,None,None,None,3,None),
(24,14,"AdwActionRow",None,9,None,None,None,4,None)
</object>
<object_property>
(3,1,"GtkWidget","height-request","200",None,None,None,None,None,None,None,None,None),
@ -380,14 +390,6 @@
(4,153,"AdwNavigationPage","tag","main",None,None,None,None,None,None,None,None,None),
(4,153,"AdwNavigationPage","title","main",None,None,None,None,None,None,None,None,None),
(4,154,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(4,164,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(4,164,"GtkWidget","margin-top","10",None,None,None,None,None,None,None,None,None),
(4,165,"GtkLabel","justify","right",None,None,None,None,None,None,None,None,None),
(4,165,"GtkLabel","label","Available networks",None,None,None,None,None,None,None,None,None),
(4,165,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None),
(4,165,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(4,166,"GtkScrolledWindow","min-content-height","100",None,None,None,None,None,None,None,None,None),
(4,166,"GtkScrolledWindow","propagate-natural-height","True",None,None,None,None,None,None,None,None,None),
(4,174,"AdwNavigationPage","tag","saved",None,None,None,None,None,None,None,None,None),
(4,174,"AdwNavigationPage","title","saved",None,None,None,None,None,None,None,None,None),
(4,175,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
@ -412,6 +414,8 @@
(4,207,"GtkWidget","halign","end",None,None,None,None,None,None,None,None,None),
(4,207,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(4,207,"GtkWidget","margin-end","5",None,None,None,None,None,None,None,None,None),
(4,208,"AdwPreferencesGroup","title","Available networks",None,None,None,None,None,None,None,None,None),
(4,208,"GtkWidget","margin-top","10",None,None,None,None,None,None,None,None,None),
(5,12,"GtkListBoxRow","child",None,None,None,None,None,13,None,None,None,None),
(5,13,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(5,14,"GtkWidget","width-request","35",None,None,None,None,None,None,None,None,None),
@ -428,12 +432,17 @@
(5,18,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(5,18,"GtkWidget","margin-end","10",None,None,None,None,None,None,None,None,None),
(5,18,"GtkWidget","width-request","200",None,None,None,None,None,None,None,None,None),
(5,19,"GtkWidget","halign","end",None,None,None,None,None,None,None,None,None),
(5,19,"GtkWidget","valign","center",None,None,None,None,None,None,None,None,None),
(5,20,"GtkButton","has-frame","False",None,None,None,None,None,None,None,None,None),
(5,20,"GtkButton","icon-name","document-edit-symbolic",None,None,None,None,None,None,None,None,None),
(5,20,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None),
(5,20,"GtkWidget","valign","center",None,None,None,None,None,None,None,None,None),
(5,22,"GtkLabel","justify","right",None,None,None,None,None,None,None,None,None),
(5,22,"GtkLabel","label","Connected",None,None,None,None,None,None,None,None,None),
(5,22,"GtkLabel","single-line-mode","True",None,None,None,None,None,None,None,None,None),
(5,22,"GtkLabel","xalign","0.0",None,None,None,None,None,None,None,None,None),
(5,22,"GtkWidget","halign","end",None,None,None,None,None,None,None,None,None),
(5,22,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(5,22,"GtkWidget","margin-end","10",None,None,None,None,None,None,None,None,None),
(6,1,"GtkListBoxRow","child",None,None,None,None,None,2,None,None,None,None),
(6,1,"GtkWidget","css-classes","resetSidebarEntry",None,None,None,None,None,None,None,None,None),
(6,2,"GtkWidget","margin-bottom","10",None,None,None,None,None,None,None,None,None),
@ -532,34 +541,6 @@
(10,120,"AdwNavigationPage","tag","main",None,None,None,None,None,None,None,None,None),
(10,120,"AdwNavigationPage","title","main",None,None,None,None,None,None,None,None,None),
(10,121,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(10,127,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(10,127,"GtkWidget","margin-top","10",None,None,None,None,None,None,None,None,None),
(10,128,"GtkLabel","justify","right",None,None,None,None,None,None,None,None,None),
(10,128,"GtkLabel","label","Available devices",None,None,None,None,None,None,None,None,None),
(10,128,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None),
(10,128,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(10,129,"GtkScrolledWindow","min-content-height","100",None,None,None,None,None,None,None,None,None),
(10,129,"GtkScrolledWindow","propagate-natural-height","True",None,None,None,None,None,None,None,None,None),
(10,131,"GtkListBox","show-separators","True",None,None,None,None,None,None,None,None,None),
(10,131,"GtkWidget","css-classes","boxed-list\n",None,None,None,None,None,None,None,None,None),
(10,131,"GtkWidget","margin-end","5",None,None,None,None,None,None,None,None,None),
(10,131,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(10,131,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None),
(10,131,"GtkWidget","valign","start",None,None,None,None,None,None,None,None,None),
(10,132,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(10,132,"GtkWidget","margin-top","10",None,None,None,None,None,None,None,None,None),
(10,133,"GtkLabel","justify","right",None,None,None,None,None,None,None,None,None),
(10,133,"GtkLabel","label","Connected devices",None,None,None,None,None,None,None,None,None),
(10,133,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None),
(10,133,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(10,134,"GtkScrolledWindow","min-content-height","100",None,None,None,None,None,None,None,None,None),
(10,134,"GtkScrolledWindow","propagate-natural-height","True",None,None,None,None,None,None,None,None,None),
(10,136,"GtkListBox","show-separators","True",None,None,None,None,None,None,None,None,None),
(10,136,"GtkWidget","css-classes","boxed-list\n",None,None,None,None,None,None,None,None,None),
(10,136,"GtkWidget","margin-end","5",None,None,None,None,None,None,None,None,None),
(10,136,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(10,136,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None),
(10,136,"GtkWidget","valign","start",None,None,None,None,None,None,None,None,None),
(10,138,"AdwNavigationPage","tag","visibility",None,None,None,None,None,None,None,None,None),
(10,138,"AdwNavigationPage","title","visibility",None,None,None,None,None,None,None,None,None),
(10,142,"GtkWidget","height-request","40",None,None,None,None,None,None,None,None,None),
@ -589,17 +570,28 @@
(10,159,"GtkLabel","label","Visibility Settings",None,None,None,None,None,None,None,None,None),
(10,159,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None),
(10,159,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(10,173,"AdwPreferencesRow","title","Bluetooth Device",None,None,None,None,None,None,None,None,None),
(10,173,"AdwPreferencesRow","title","Bluetooth Adapter",None,None,None,None,None,None,None,None,None),
(10,174,"AdwPreferencesRow","title","Visibility Settings",None,None,None,None,None,None,None,None,None),
(10,175,"GtkImage","icon-name","go-previous-symbolic-rtl",None,None,None,None,None,None,None,None,None),
(10,175,"GtkWidget","halign","end",None,None,None,None,None,None,None,None,None),
(10,175,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(10,175,"GtkWidget","margin-end","5",None,None,None,None,None,None,None,None,None),
(10,176,"AdwPreferencesGroup","header-suffix",None,None,None,None,None,177,None,None,None,None),
(10,176,"AdwPreferencesGroup","title","Available Devices",None,None,None,None,None,None,None,None,None),
(10,176,"GtkWidget","margin-top","10",None,None,None,None,None,None,None,None,None),
(10,177,"GtkButton","icon-name","view-refresh-symbolic",None,None,None,None,None,None,None,None,None),
(10,178,"GtkScrolledWindow","min-content-height","100",None,None,None,None,None,None,None,None,None),
(10,178,"GtkScrolledWindow","propagate-natural-height","True",None,None,None,None,None,None,None,None,None),
(10,180,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(10,181,"AdwPreferencesGroup","title","Connected Devices",None,None,None,None,None,None,None,None,None),
(10,183,"GtkScrolledWindow","min-content-height","100",None,None,None,None,None,None,None,None,None),
(10,183,"GtkScrolledWindow","propagate-natural-height","True",None,None,None,None,None,None,None,None,None),
(10,185,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(11,2,"GtkWidget","margin-start","5",None,None,None,None,None,None,None,None,None),
(11,3,"GtkImage","icon-name","input-mouse-symbolic",None,None,None,None,None,None,None,None,None),
(11,3,"GtkWidget","margin-end","15",None,None,None,None,None,None,None,None,None),
(11,5,"GtkButton","has-frame","False",None,None,None,None,None,None,None,None,None),
(11,5,"GtkButton","icon-name","user-trash-symbolic",None,None,None,None,None,None,None,None,None),
(11,5,"GtkButton","icon-name","emblem-system-symbolic",None,None,None,None,None,None,None,None,None),
(11,6,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(11,7,"GtkLabel","ellipsize","end",None,None,None,None,None,None,None,None,None),
(11,7,"GtkLabel","label","LoremIpsum Wireless Mouse",None,None,None,None,None,None,None,None,None),
@ -801,6 +793,7 @@
(21,53,"GtkNotebook","scrollable","True",None,None,None,None,None,None,None,None,None),
(21,53,"GtkNotebook","show-border","False",None,None,None,None,None,None,None,None,None),
(21,54,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(21,54,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None),
(21,56,"AdwPreferencesRow","title","WiFi Name",None,None,None,None,None,None,None,None,None),
(21,56,"GtkWidget","css-classes","property",None,None,None,None,None,None,None,None,None),
(21,57,"AdwPreferencesRow","title","MAC-Address",None,None,None,None,None,None,None,None,None),
@ -821,6 +814,7 @@
(21,65,"AdwPreferencesRow","title","Metered Connection",None,None,None,None,None,None,None,None,None),
(21,66,"GtkLabel","label","General",None,None,None,None,None,None,None,None,None),
(21,67,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(21,67,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None),
(21,69,"AdwComboRow","model",None,None,None,None,None,70,None,None,None,None),
(21,69,"AdwPreferencesRow","title","IPv4 Method",None,None,None,None,None,None,None,None,None),
(21,71,"AdwPreferencesRow","title","DNS (separate IP by comma, empty for automatic)",None,None,None,None,None,None,None,None,None),
@ -836,10 +830,12 @@
(21,77,"GtkWidget","valign","center",None,None,None,None,None,None,None,None,None),
(21,78,"GtkLabel","label","IPv4",None,None,None,None,None,None,None,None,None),
(21,79,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(21,79,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None),
(21,81,"AdwComboRow","model",None,None,None,None,None,82,None,None,None,None),
(21,81,"AdwPreferencesRow","title","IPv6 Method",None,None,None,None,None,None,None,None,None),
(21,83,"AdwPreferencesRow","title","DNS (separate IP by comma, empty for automatic)",None,None,None,None,None,None,None,None,None),
(21,84,"AdwPreferencesRow","title","Gateway",None,None,None,None,None,None,None,None,None),
(21,85,"AdwPreferencesGroup","header-suffix",None,None,None,None,None,101,None,None,None,None),
(21,85,"AdwPreferencesGroup","title","Addresses",None,None,None,None,None,None,None,None,None),
(21,85,"GtkWidget","margin-top","10",None,None,None,None,None,None,None,None,None),
(21,86,"AdwPreferencesGroup","header-suffix",None,None,None,None,None,87,None,None,None,None),
@ -850,35 +846,55 @@
(21,89,"GtkWidget","valign","center",None,None,None,None,None,None,None,None,None),
(21,90,"GtkLabel","label","IPv6",None,None,None,None,None,None,None,None,None),
(21,91,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(21,93,"AdwComboRow","model",None,None,None,None,None,94,None,None,None,None),
(21,91,"GtkWidget","margin-top","5",None,None,None,None,None,None,None,None,None),
(21,93,"AdwComboRow","model",None,None,None,None,None,103,None,None,None,None),
(21,93,"AdwPreferencesRow","title","Security",None,None,None,None,None,None,None,None,None),
(21,95,"AdwPreferencesRow","title","Username",None,None,None,None,None,None,None,None,None),
(21,96,"AdwPreferencesRow","title","Password",None,None,None,None,None,None,None,None,None),
(21,97,"GtkLabel","label","Security",None,None,None,None,None,None,None,None,None),
(21,98,"GtkButton","label","Apply",None,None,None,None,None,None,None,None,None),
(21,98,"GtkWidget","halign","end",None,None,None,None,None,None,None,None,None),
(21,98,"GtkWidget","margin-top","10",None,None,None,None,None,None,None,None,None),
(21,99,"GtkButton","icon-name","list-add-symbolic",None,None,None,None,None,None,None,None,None),
(21,100,"GtkButton","icon-name","list-add-symbolic",None,None,None,None,None,None,None,None,None),
(21,100,"GtkWidget","margin-start","10",None,None,None,None,None,None,None,None,None),
(21,101,"GtkButton","icon-name","list-add-symbolic",None,None,None,None,None,None,None,None,None),
(21,102,"GtkButton","icon-name","list-add-symbolic",None,None,None,None,None,None,None,None,None),
(21,102,"GtkWidget","margin-start","10",None,None,None,None,None,None,None,None,None),
(22,1,"GtkWidget","margin-bottom","2",None,None,None,None,None,None,None,None,None),
(22,1,"GtkWidget","margin-top","2",None,None,None,None,None,None,None,None,None),
(22,2,"AdwPreferencesRow","title","Add new Address",None,None,None,None,None,None,None,None,None),
(22,2,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(22,3,"AdwPreferencesRow","title","Address",None,None,None,None,None,None,None,None,None),
(22,4,"AdwPreferencesRow","title","Prefix",None,None,None,None,None,None,None,None,None),
(22,5,"GtkButton","icon-name","edit-delete-symbolic",None,None,None,None,None,None,None,None,None),
(22,5,"GtkWidget","height-request","55",None,None,None,None,None,None,None,None,None),
(22,5,"GtkWidget","valign","start",None,None,None,None,None,None,None,None,None),
(22,7,"AdwPreferencesRow","title","Address",None,None,None,None,None,None,None,None,None),
(22,7,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(22,8,"AdwPreferencesRow","title","Prefix",None,None,None,None,None,None,None,None,None),
(22,8,"GtkEditable","max-width-chars","5",None,None,None,None,None,None,None,None,None),
(23,2,"AdwPreferencesRow","title","Add new Route",None,None,None,None,None,None,None,None,None),
(23,2,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(23,3,"AdwPreferencesRow","title","Address",None,None,None,None,None,None,None,None,None),
(23,4,"AdwPreferencesRow","title","Netmask",None,None,None,None,None,None,None,None,None),
(23,5,"GtkButton","icon-name","edit-delete-symbolic",None,None,None,None,None,None,None,None,None),
(23,5,"GtkWidget","height-request","55",None,None,None,None,None,None,None,None,None),
(23,5,"GtkWidget","valign","start",None,None,None,None,None,None,None,None,None),
(23,7,"AdwPreferencesRow","title","Gateway",None,None,None,None,None,None,None,None,None),
(23,7,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(23,8,"AdwPreferencesRow","title","Metric",None,None,None,None,None,None,None,None,None),
(23,8,"GtkEditable","max-width-chars","5",None,None,None,None,None,None,None,None,None)
(23,8,"GtkEditable","max-width-chars","5",None,None,None,None,None,None,None,None,None),
(23,10,"AdwPreferencesRow","title","Address",None,None,None,None,None,None,None,None,None),
(23,10,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(23,11,"AdwPreferencesRow","title","Prefix",None,None,None,None,None,None,None,None,None),
(23,11,"GtkEditable","max-width-chars","5",None,None,None,None,None,None,None,None,None),
(24,1,"AdwPreferencesGroup","header-suffix",None,None,None,None,None,4,None,None,None,None),
(24,1,"AdwPreferencesGroup","title","Available Devices",None,None,None,None,None,None,None,None,None),
(24,4,"GtkButton","icon-name","view-refresh-symbolic",None,None,None,None,None,None,None,None,None),
(24,5,"GtkScrolledWindow","min-content-height","100",None,None,None,None,None,None,None,None,None),
(24,5,"GtkScrolledWindow","propagate-natural-height","True",None,None,None,None,None,None,None,None,None),
(24,9,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(24,10,"AdwPreferencesRow","title","device 2",None,None,None,None,None,None,None,None,None),
(24,11,"AdwPreferencesRow","title","device 1",None,None,None,None,None,None,None,None,None),
(24,12,"AdwPreferencesRow","title","device 2",None,None,None,None,None,None,None,None,None),
(24,13,"AdwPreferencesRow","title","device 2",None,None,None,None,None,None,None,None,None),
(24,14,"AdwPreferencesRow","title","device 2",None,None,None,None,None,None,None,None,None)
</object_property>
<object_data>
(3,42,"GtkWidget",1,1,None,None,None,None,None,None),
@ -908,16 +924,9 @@
(21,82,"GtkStringList",2,5,"Link-Local Only",1,None,None,None,None),
(21,82,"GtkStringList",2,6,"Shared to other computers",1,None,None,None,None),
(21,82,"GtkStringList",2,7,"Disabled",1,None,None,None,None),
(21,94,"GtkStringList",1,1,None,None,None,None,None,None),
(21,94,"GtkStringList",2,2,"None",1,None,None,None,None),
(21,94,"GtkStringList",2,3,"Enhanced Open",1,None,None,None,None),
(21,94,"GtkStringList",2,4,"WEP 40/128-bit Key (Hex or ASCII)",1,None,None,None,None),
(21,94,"GtkStringList",2,5,"WEP 128-bit Passphrase",1,None,None,None,None),
(21,94,"GtkStringList",2,6,"LEAP",1,None,None,None,None),
(21,94,"GtkStringList",2,7,"Dynamic WEP (802.1X)",1,None,None,None,None),
(21,94,"GtkStringList",2,8,"WPA &amp; WPA2 Personal",1,None,None,None,None),
(21,94,"GtkStringList",2,9,"WPA &amp; WPA2 Enterprise",1,None,None,None,None),
(21,94,"GtkStringList",2,10,"WPA3 Personal",1,None,None,None,None)
(21,103,"GtkStringList",1,1,None,None,None,None,None,None),
(21,103,"GtkStringList",2,2,"None",1,None,None,None,None),
(21,103,"GtkStringList",2,3,"WPA &amp; WPA2 Personal",1,None,None,None,None)
</object_data>
<object_data_arg>
(3,42,"GtkWidget",2,2,"name","b"),

View file

@ -61,30 +61,9 @@
</object>
</child>
<child>
<object class="GtkBox">
<object class="AdwPreferencesGroup" id="resetWifiList">
<property name="margin-top">10</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="justify">right</property>
<property name="label">Available networks</property>
<property name="margin-start">5</property>
</object>
</child>
<child>
<object class="GtkScrolledWindow">
<property name="min-content-height">100</property>
<property name="propagate-natural-height">True</property>
<child>
<object class="GtkViewport">
<child>
<object class="AdwPreferencesGroup" id="resetWifiList"/>
</child>
</object>
</child>
</object>
</child>
<property name="title">Available networks</property>
</object>
</child>
</object>

View file

@ -11,13 +11,19 @@
<property name="hexpand">True</property>
<property name="title">Add new Address</property>
<child>
<object class="AdwEntryRow" id="resetAddressAddress">
<property name="title">Address</property>
</object>
</child>
<child>
<object class="AdwEntryRow" id="resetAddressPrefix">
<property name="title">Prefix</property>
<object class="GtkBox">
<child>
<object class="AdwEntryRow" id="resetAddressAddress">
<property name="hexpand">True</property>
<property name="title">Address</property>
</object>
</child>
<child>
<object class="AdwEntryRow" id="resetAddressPrefix">
<property name="max-width-chars">5</property>
<property name="title">Prefix</property>
</object>
</child>
</object>
</child>
</object>

View file

@ -37,6 +37,17 @@
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkLabel" id="resetWifiConnected">
<property name="halign">end</property>
<property name="hexpand">True</property>
<property name="justify">right</property>
<property name="label">Connected</property>
<property name="margin-end">10</property>
<property name="single-line-mode">True</property>
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkButton" id="resetWifiEditButton">
<property name="halign">start</property>
@ -45,12 +56,6 @@
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkImage" id="resetWifiConnected">
<property name="halign">end</property>
<property name="valign">center</property>
</object>
</child>
<child>
<object class="resetPopup" id="resetWifiPopup"/>
</child>

View file

@ -13,6 +13,7 @@
<property name="show-border">False</property>
<child>
<object class="GtkBox">
<property name="margin-top">5</property>
<property name="orientation">vertical</property>
<child>
<object class="AdwPreferencesGroup">
@ -85,6 +86,7 @@
</child>
<child>
<object class="GtkBox">
<property name="margin-top">5</property>
<property name="orientation">vertical</property>
<child>
<object class="AdwPreferencesGroup">
@ -142,6 +144,12 @@
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="resetIP4RouteAddButton">
<property name="icon-name">list-add-symbolic</property>
<property name="margin-start">10</property>
</object>
</child>
</object>
</property>
<property name="margin-top">10</property>
@ -157,6 +165,7 @@
</child>
<child>
<object class="GtkBox">
<property name="margin-top">5</property>
<property name="orientation">vertical</property>
<child>
<object class="AdwPreferencesGroup">
@ -191,6 +200,11 @@
</child>
<child>
<object class="AdwPreferencesGroup" id="resetIP6AddressGroup">
<property name="header-suffix">
<object class="GtkButton" id="resetIP6AddressAddButton">
<property name="icon-name">list-add-symbolic</property>
</object>
</property>
<property name="margin-top">10</property>
<property name="title">Addresses</property>
</object>
@ -210,6 +224,12 @@
<property name="valign">center</property>
</object>
</child>
<child>
<object class="GtkButton" id="resetIP6RouteAddButton">
<property name="icon-name">list-add-symbolic</property>
<property name="margin-start">10</property>
</object>
</child>
</object>
</property>
<property name="margin-top">10</property>
@ -225,23 +245,17 @@
</child>
<child>
<object class="GtkBox">
<property name="margin-top">5</property>
<property name="orientation">vertical</property>
<child>
<object class="AdwPreferencesGroup">
<child>
<object class="AdwComboRow">
<object class="AdwComboRow" id="resetWifiSecurityDropdown">
<property name="model">
<object class="GtkStringList">
<items>
<item>None</item>
<item>Enhanced Open</item>
<item>WEP 40/128-bit Key (Hex or ASCII)</item>
<item>WEP 128-bit Passphrase</item>
<item>LEAP</item>
<item>Dynamic WEP (802.1X)</item>
<item>WPA &amp; WPA2 Personal</item>
<item>WPA &amp; WPA2 Enterprise</item>
<item>WPA3 Personal</item>
</items>
</object>
</property>
@ -249,12 +263,7 @@
</object>
</child>
<child>
<object class="AdwEntryRow">
<property name="title">Username</property>
</object>
</child>
<child>
<object class="AdwPasswordEntryRow">
<object class="AdwPasswordEntryRow" id="resetWifiPassword">
<property name="title">Password</property>
</object>
</child>

View file

@ -9,13 +9,19 @@
<property name="hexpand">True</property>
<property name="title">Add new Route</property>
<child>
<object class="AdwEntryRow" id="resetRouteAddress">
<property name="title">Address</property>
</object>
</child>
<child>
<object class="AdwEntryRow" id="resetRouteNetmask">
<property name="title">Netmask</property>
<object class="GtkBox">
<child>
<object class="AdwEntryRow" id="resetRouteAddress">
<property name="hexpand">True</property>
<property name="title">Address</property>
</object>
</child>
<child>
<object class="AdwEntryRow" id="resetRoutePrefix">
<property name="max-width-chars">5</property>
<property name="title">Prefix</property>
</object>
</child>
</object>
</child>
<child>