Add Wifi Options (UI only)

This commit is contained in:
takotori 2023-11-20 17:52:07 +01:00
parent 5311bb8c4c
commit ed7b814e62
15 changed files with 702 additions and 447 deletions

View file

@ -7,3 +7,7 @@ pub mod wifiEntry;
pub mod wifiEntryImpl;
pub mod wifiOptions;
pub mod wifiOptionsImpl;
pub mod wifiAddressEntry;
pub mod wifiAddressEntryImpl;
pub mod wifiRouteEntry;
pub mod wifiRouteEntryImpl;

View file

@ -0,0 +1,34 @@
use adw::glib;
use adw::glib::Object;
use adw::prelude::PreferencesRowExt;
use glib::subclass::prelude::ObjectSubclassIsExt;
use gtk::prelude::EditableExt;
use ReSet_Lib::network::connection::Address;
use crate::components::wifi::wifiAddressEntryImpl;
use crate::components::wifi::wifiOptions::getValueFromKey;
glib::wrapper! {
pub struct WifiAddressEntry(ObjectSubclass<wifiAddressEntryImpl::WifiAddressEntryImpl>)
@extends gtk::Box, gtk::Widget,
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable;
}
impl WifiAddressEntry {
pub fn new(address: Option<&Address>) -> Self {
let entry: WifiAddressEntry = 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");
entryImp.resetAddressAddress.set_text(&*addr);
entryImp.resetAddressNetmask.set_text(&*prefix);
entryImp.resetAddressRow.set_title(&*format!("{}, {}", addr, prefix));
}
entry
}
}

View file

@ -0,0 +1,47 @@
use adw::{EntryRow, ExpanderRow};
use crate::components::wifi::{wifiAddressEntry};
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, Button};
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
#[template(resource = "/org/Xetibo/ReSet/resetWifiAddressEntry.ui")]
pub struct WifiAddressEntryImpl {
#[template_child]
pub resetAddressRow: TemplateChild<ExpanderRow>,
#[template_child]
pub resetAddressAddress: TemplateChild<EntryRow>,
#[template_child]
pub resetAddressNetmask: TemplateChild<EntryRow>,
#[template_child]
pub resetAddressRemove: TemplateChild<Button>,
}
#[glib::object_subclass]
impl ObjectSubclass for WifiAddressEntryImpl {
const NAME: &'static str = "resetWifiAddressEntry";
type Type = wifiAddressEntry::WifiAddressEntry;
type ParentType = gtk::Box;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for WifiAddressEntryImpl {
fn constructed(&self) {
self.parent_constructed();
}
}
impl BoxImpl for WifiAddressEntryImpl {}
impl WidgetImpl for WifiAddressEntryImpl {}
impl WindowImpl for WifiAddressEntryImpl {}
impl ApplicationWindowImpl for WifiAddressEntryImpl {}

View file

@ -1,4 +1,5 @@
use std::collections::HashMap;
use std::net::Shutdown::Read;
use std::sync::atomic::Ordering;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Arc;
@ -214,7 +215,7 @@ pub fn get_stored_connections() -> Vec<(Path<'static>, Vec<u8>)> {
connections
}
pub fn getConnectionSettings(path: Path<'static>) -> Option<ResetConnection> {
pub fn getConnectionSettings(path: Path<'static>) -> ResetConnection {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
@ -226,14 +227,14 @@ pub fn getConnectionSettings(path: Path<'static>) -> Option<ResetConnection> {
Error,
> = proxy.method_call("org.xetibo.ReSet", "GetConnectionSettings", (path,));
if res.is_err() {
return None;
ResetConnection::default();
}
let (res,) = res.unwrap();
let res = ResetConnection::convert_from_propmap(res);
if res.is_err() {
return None;
ResetConnection::default();
}
Some(res.unwrap())
res.unwrap()
}
// temporary, testing this with lib is pain

View file

@ -86,7 +86,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));
}));
}
}

View file

@ -1,9 +1,17 @@
use std::sync::Arc;
use adw::glib;
use adw::glib::Object;
use adw::prelude::{ActionRowExt, ComboRowExt, PreferencesGroupExt};
use adw::subclass::prelude::ObjectSubclassIsExt;
use glib::PropertySet;
use ReSet_Lib::network::connection::Connection;
use crate::components::wifi::{wifiOptionsImpl};
use dbus::arg::PropMap;
use glib::{PropertySet, Cast, ObjectExt, clone};
use gtk::prelude::{EditableExt, WidgetExt};
use ReSet_Lib::network::connection::{Connection, Enum};
use crate::components::wifi::wifiAddressEntry::WifiAddressEntry;
use crate::components::wifi::wifiOptionsImpl;
use crate::components::wifi::wifiRouteEntry::WifiRouteEntry;
glib::wrapper! {
pub struct WifiOptions(ObjectSubclass<wifiOptionsImpl::WifiOptions>)
@ -12,10 +20,151 @@ glib::wrapper! {
}
impl WifiOptions {
pub fn new(option: Option<Connection>) -> Self {
let wifiOption: WifiOptions = Object::builder().build();
wifiOption.imp().options.set(option);
wifiOption
pub fn new(connection: Connection) -> Arc<Self> {
let wifiOption: Arc<WifiOptions> = Arc::new(Object::builder().build());
wifiOption.imp().connection.set(connection);
wifiOption.initializeUI();
setupCallbacks(wifiOption)
}
pub fn initializeUI(&self) {
let selfImp = self.imp();
let conn = selfImp.connection.borrow();
// General
selfImp.resetWifiName.set_subtitle(&*conn.settings.name);
selfImp.resetWifiAutoConnect.set_active(conn.settings.autoconnect);
selfImp.resetWifiMetered.set_active(if conn.settings.metered != -1 { true } else { false });
// IPv4
selfImp.resetIP4Method.set_selected(conn.ipv4.dns_method.to_i32() as u32);
self.setIP4Visibility(conn.ipv4.dns_method.to_i32() as u32);
let ipv4Dns: Vec<String> = conn.ipv4.dns.iter()
.map(|addr| {
addr.iter()
.map(|octet| octet.to_string())
.collect::<Vec<String>>()
.join(".")
})
.collect();
selfImp.resetIP4DNS.set_text(&*ipv4Dns.join(", "));
selfImp.resetIP4Gateway.set_text(&*conn.ipv4.gateway);
if conn.ipv4.address_data.is_empty() {
selfImp.resetIP4AddressGroup.add(&WifiAddressEntry::new(None))
} else {
for address in conn.ipv4.address_data.iter() {
selfImp.resetIP4AddressGroup.add(&WifiAddressEntry::new(Some(address)))
}
}
if conn.ipv4.route_data.is_empty() {
selfImp.resetIP4RoutesGroup.add(&WifiRouteEntry::new(None))
} else {
for address in conn.ipv4.route_data.iter() {
selfImp.resetIP4RoutesGroup.add(&WifiRouteEntry::new(Some(address)))
}
}
// IPv6
selfImp.resetIP6Method.set_selected(conn.ipv6.dns_method.to_i32() as u32);
self.setIP6Visibility(conn.ipv6.dns_method.to_i32() as u32);
let ipv6Dns: Vec<String> = conn.ipv6.dns.iter()
.map(|addr| {
addr.iter()
.map(|octet| octet.to_string())
.collect::<Vec<String>>()
.join(":")
})
.collect();
selfImp.resetIP6DNS.set_text(&*ipv6Dns.join(", "));
selfImp.resetIP6Gateway.set_text(&*conn.ipv6.gateway);
if conn.ipv6.address_data.is_empty() {
selfImp.resetIP6AddressGroup.add(&WifiAddressEntry::new(None))
} else {
for address in conn.ipv6.address_data.iter() {
selfImp.resetIP6AddressGroup.add(&WifiAddressEntry::new(Some(address)))
}
}
if conn.ipv6.route_data.is_empty() {
selfImp.resetIP6RoutesGroup.add(&WifiRouteEntry::new(None))
} else {
for address in conn.ipv6.route_data.iter() {
selfImp.resetIP6RoutesGroup.add(&WifiRouteEntry::new(Some(address)))
}
}
// Security
dbg!(conn);
}
pub fn setIP4Visibility(&self, method: u32) {
let selfImp = self.imp();
match method {
0 => { // auto
selfImp.resetIP4AddressGroup.set_visible(false);
selfImp.resetIP4RoutesGroup.set_visible(true);
selfImp.resetIP4Gateway.set_visible(false);
}
1 => { // manual
selfImp.resetIP4AddressGroup.set_visible(true);
selfImp.resetIP4RoutesGroup.set_visible(true);
selfImp.resetIP4Gateway.set_visible(true);
}
_ => {
selfImp.resetIP4AddressGroup.set_visible(false);
selfImp.resetIP4RoutesGroup.set_visible(false);
selfImp.resetIP4Gateway.set_visible(false);
}
}
}
pub fn setIP6Visibility(&self, method: u32) {
let selfImp = self.imp();
match method {
0 | 1 => { // auto, dhcp
selfImp.resetIP6AddressGroup.set_visible(false);
selfImp.resetIP6RoutesGroup.set_visible(true);
selfImp.resetIP6Gateway.set_visible(false);
}
2 => { // manual
selfImp.resetIP6AddressGroup.set_visible(true);
selfImp.resetIP6RoutesGroup.set_visible(true);
selfImp.resetIP6Gateway.set_visible(true);
}
_ => {
selfImp.resetIP6AddressGroup.set_visible(false);
selfImp.resetIP6RoutesGroup.set_visible(false);
selfImp.resetIP6Gateway.set_visible(false);
}
}
}
}
fn setupCallbacks(wifiOptions: Arc<WifiOptions>) -> Arc<WifiOptions> {
let imp = wifiOptions.imp();
let wifiOptionsRef = wifiOptions.clone();
let wifiOptionsRef2 = wifiOptions.clone();
imp.resetIP4Method.connect_selected_notify(move |dropdown| {
let selected = dropdown.selected();
wifiOptionsRef.setIP4Visibility(selected);
});
imp.resetIP6Method.connect_selected_notify(move |dropdown| {
let selected = dropdown.selected();
wifiOptionsRef2.setIP6Visibility(selected);
});
wifiOptions
}
pub fn getValueFromKey(map: &PropMap, key: &str) -> String {
map.get(key)
.map_or_else(|| "".to_string(),
|value| value.0
.as_str()
.unwrap_or_default()
.trim()
.to_string())
}

View file

@ -1,5 +1,6 @@
use std::cell::RefCell;
use adw::NavigationPage;
use std::rc::Rc;
use adw::{ActionRow, ComboRow, EntryRow, NavigationPage, PreferencesGroup, SwitchRow};
use adw::subclass::prelude::NavigationPageImpl;
use crate::components::wifi::{wifiOptions};
use gtk::subclass::prelude::*;
@ -10,7 +11,40 @@ use ReSet_Lib::network::connection::Connection;
#[derive(Default, CompositeTemplate)]
#[template(resource = "/org/Xetibo/ReSet/resetWifiOptions.ui")]
pub struct WifiOptions {
pub options: RefCell<Option<Connection>> // Option<Rc<RefCell<Connection>>>
// General
#[template_child]
pub resetWifiName: TemplateChild<ActionRow>,
#[template_child]
pub resetWifiMac: TemplateChild<ActionRow>,
#[template_child]
pub resetWifiAutoConnect: TemplateChild<SwitchRow>,
#[template_child]
pub resetWifiMetered: TemplateChild<SwitchRow>,
// IPv4
#[template_child]
pub resetIP4Method: TemplateChild<ComboRow>,
#[template_child]
pub resetIP4DNS: TemplateChild<EntryRow>,
#[template_child]
pub resetIP4Gateway: TemplateChild<EntryRow>,
#[template_child]
pub resetIP4AddressGroup: TemplateChild<PreferencesGroup>,
#[template_child]
pub resetIP4RoutesGroup: TemplateChild<PreferencesGroup>,
// IPv6
#[template_child]
pub resetIP6Method: TemplateChild<ComboRow>,
#[template_child]
pub resetIP6DNS: TemplateChild<EntryRow>,
#[template_child]
pub resetIP6Gateway: TemplateChild<EntryRow>,
#[template_child]
pub resetIP6AddressGroup: TemplateChild<PreferencesGroup>,
#[template_child]
pub resetIP6RoutesGroup: TemplateChild<PreferencesGroup>,
// Security
// Misc
pub connection: Rc<RefCell<Connection>>
}
#[glib::object_subclass]

View file

@ -0,0 +1,38 @@
use adw::glib;
use adw::glib::Object;
use adw::prelude::PreferencesRowExt;
use glib::subclass::prelude::ObjectSubclassIsExt;
use gtk::prelude::EditableExt;
use ReSet_Lib::network::connection::Address;
use crate::components::wifi::wifiOptions::getValueFromKey;
use crate::components::wifi::wifiRouteEntryImpl;
glib::wrapper! {
pub struct WifiRouteEntry(ObjectSubclass<wifiRouteEntryImpl::WifiRouteEntryImpl>)
@extends gtk::Box, gtk::Widget,
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable;
}
impl WifiRouteEntry {
pub fn new(address: Option<&Address>) -> 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));
}
entry
}
}

View file

@ -0,0 +1,51 @@
use adw::{EntryRow, ExpanderRow};
use crate::components::wifi::wifiRouteEntry;
use gtk::subclass::prelude::*;
use gtk::{glib, CompositeTemplate, Button};
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
#[template(resource = "/org/Xetibo/ReSet/resetWifiRouteEntry.ui")]
pub struct WifiRouteEntryImpl {
#[template_child]
pub resetRouteRow: TemplateChild<ExpanderRow>,
#[template_child]
pub resetRouteAddress: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteNetmask: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteGateway: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteMetric: TemplateChild<EntryRow>,
#[template_child]
pub resetRouteRemove: TemplateChild<Button>,
}
#[glib::object_subclass]
impl ObjectSubclass for WifiRouteEntryImpl {
const NAME: &'static str = "resetWifiRouteEntry";
type Type = wifiRouteEntry::WifiRouteEntry;
type ParentType = gtk::Box;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for WifiRouteEntryImpl {
fn constructed(&self) {
self.parent_constructed();
}
}
impl BoxImpl for WifiRouteEntryImpl {}
impl WidgetImpl for WifiRouteEntryImpl {}
impl WindowImpl for WifiRouteEntryImpl {}
impl ApplicationWindowImpl for WifiRouteEntryImpl {}