feat: Add gesture click to wifi -> dbus connection

This commit is contained in:
Fabio Lenherr / DashieTM 2023-11-10 19:30:21 +01:00
parent 919f39ce7a
commit 05b75da3fb
13 changed files with 347 additions and 82 deletions

View file

@ -5,9 +5,11 @@ edition = "2021"
description = "A wip universal Linux settings application."
[dependencies]
ReSet-Lib = "0.2.3"
adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"]}
dbus = "0.9.7"
gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"]}
glib = "0.18.3"
[build-dependencies]
glib-build-tools = "0.18.0"

View file

@ -10,10 +10,13 @@ glib::wrapper! {
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Actionable;
}
unsafe impl Send for ListEntry {}
unsafe impl Sync for ListEntry {}
impl ListEntry {
pub fn new(child: &impl IsA<Widget>) -> Self {
let entry: ListEntry = Object::builder().build();
entry.set_child(Some(child));
entry
}
}
}

View file

@ -1,18 +1,25 @@
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::{atomic::AtomicBool, Arc, Weak};
use std::thread;
use std::time::Duration;
use crate::components::base::listEntry::ListEntry;
use adw::glib;
use adw::glib::Object;
use adw::subclass::prelude::ObjectSubclassIsExt;
use dbus::blocking::Connection;
use dbus::Error;
use gtk::glib::Variant;
use dbus::Path;
use gtk::glib::{clone, Variant};
use gtk::prelude::ActionableExt;
use crate::components::base::listEntry::ListEntry;
use ReSet_Lib::network::network::{AccessPoint, WifiStrength};
use ReSet_Lib::signals::{
AccessPointAdded, AccessPointRemoved, BluetoothDeviceAdded, BluetoothDeviceRemoved,
};
use ReSet_Lib::utils::Events;
use crate::components::wifi::wifiBoxImpl;
use crate::components::wifi::wifiEntry::WifiEntry;
use crate::components::wifi::wifiEntryImpl::WifiStrength;
glib::wrapper! {
pub struct WifiBox(ObjectSubclass<wifiBoxImpl::WifiBox>)
@ -20,6 +27,9 @@ glib::wrapper! {
@implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::Orientable;
}
unsafe impl Send for WifiBox {}
unsafe impl Sync for WifiBox {}
impl WifiBox {
pub fn new() -> Self {
Object::builder().build()
@ -28,21 +38,12 @@ impl WifiBox {
pub fn setupCallbacks(&self) {
let selfImp = self.imp();
selfImp.resetSavedNetworks.set_action_name(Some("navigation.push"));
selfImp.resetSavedNetworks.set_action_target_value(Some(&Variant::from("saved")));
}
pub fn scanForWifi(&self) {
let selfImp = self.imp();
let mut wifiEntries = selfImp.wifiEntries.borrow_mut();
wifiEntries.push(ListEntry::new(&WifiEntry::new(WifiStrength::Excellent, "ina internet", true)));
wifiEntries.push(ListEntry::new(&WifiEntry::new(WifiStrength::Excellent, "watch ina", true)));
wifiEntries.push(ListEntry::new(&WifiEntry::new(WifiStrength::Ok, "INANET", true)));
wifiEntries.push(ListEntry::new(&WifiEntry::new(WifiStrength::Weak, "ina best waifu", false)));
for wifiEntry in wifiEntries.iter() {
selfImp.resetWifiList.append(wifiEntry);
}
selfImp
.resetSavedNetworks
.set_action_name(Some("navigation.push"));
selfImp
.resetSavedNetworks
.set_action_target_value(Some(&Variant::from("saved")));
}
pub fn donotdisturb() {
@ -53,7 +54,73 @@ impl WifiBox {
"/org/freedesktop/Notifications",
Duration::from_millis(1000),
);
let _: Result<(), Error> = proxy.method_call("org.freedesktop.Notifications", "DoNotDisturb", ());
let _: Result<(), Error> =
proxy.method_call("org.freedesktop.Notifications", "DoNotDisturb", ());
});
}
}
pub fn scanForWifi(wifiBox: Arc<WifiBox>) {
let wifibox_ref = wifiBox.clone();
let wifiEntries = wifiBox.imp().wifiEntries.clone();
glib::spawn_future_local(async move {
let accessPoints = wat().await;
let wifiEntries = wifiEntries.clone();
{
let mut wifiEntries = wifiEntries.lock().unwrap();
for accessPoint in accessPoints {
wifiEntries.push(ListEntry::new(&*WifiEntry::new(accessPoint)));
}
}
glib::MainContext::default().spawn_local(async move {
glib::idle_add_once(move || {
let wifiEntries = wifiEntries.lock().unwrap();
let selfImp = wifibox_ref.imp();
for wifiEntry in wifiEntries.iter() {
selfImp.resetWifiList.append(wifiEntry);
}
});
});
let (sender, receiver): (
Sender<Events<(AccessPoint,), (Path<'static>,)>>,
Receiver<Events<(AccessPoint,), (Path<'static>,)>>,
) = channel();
let sender_ref = Arc::new(sender);
let listener_active = Arc::new(AtomicBool::new(false));
ReSet_Lib::utils::start_event_listener::<
(AccessPoint,),
(Path<'static>,),
AccessPointAdded,
AccessPointRemoved,
>(listener_active, sender_ref);
// handle receiver...
let res = receiver.try_recv();
if res.is_ok() {
let access_point = res.unwrap();
match access_point {
Events::AddedEvent(access_point) => {
dbg!(access_point);
}
_ => (),
};
} else {
println!("no message there :)");
}
});
}
pub async fn wat() -> Vec<AccessPoint> {
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
"/org/xetibo/ReSet",
Duration::from_millis(1000),
);
let res: Result<(Vec<AccessPoint>,), Error> =
proxy.method_call("org.xetibo.ReSet", "ListAccessPoints", ());
if res.is_err() {
return Vec::new();
}
let (accessPoints,) = res.unwrap();
accessPoints
}

View file

@ -1,4 +1,5 @@
use std::cell::RefCell;
use std::sync::{Arc, Mutex};
use gtk::{Button, CompositeTemplate, glib, ListBox, Switch};
use gtk::prelude::*;
use gtk::subclass::prelude::*;
@ -7,6 +8,8 @@ use crate::components::wifi::wifiBox;
use crate::components::wifi::wifiEntry::WifiEntry;
use crate::components::base::listEntry::ListEntry;
use super::wifiBox::scanForWifi;
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
#[template(resource = "/org/Xetibo/ReSet/resetWiFi.ui")]
@ -23,9 +26,12 @@ pub struct WifiBox {
pub resetWifiList: TemplateChild<ListBox>,
#[template_child]
pub resetWifiAdvanced: TemplateChild<Button>,
pub wifiEntries: RefCell<Vec<ListEntry>>,
pub wifiEntries: Arc<Mutex<Vec<ListEntry>>>,
}
unsafe impl Send for WifiBox {}
unsafe impl Sync for WifiBox {}
#[glib::object_subclass]
impl ObjectSubclass for WifiBox {
const NAME: &'static str = "resetWifi";
@ -49,7 +55,6 @@ impl ObjectImpl for WifiBox {
let obj = self.obj();
obj.setupCallbacks();
obj.scanForWifi();
}
}

View file

@ -2,8 +2,14 @@ use crate::components::wifi::wifiEntryImpl;
use adw::glib;
use adw::glib::{Object, PropertySet};
use adw::subclass::prelude::ObjectSubclassIsExt;
use dbus::blocking::Connection;
use dbus::Error;
use glib::clone;
use gtk::prelude::WidgetExt;
use crate::components::wifi::wifiEntryImpl::WifiStrength;
use gtk::GestureClick;
use std::sync::Arc;
use std::time::Duration;
use ReSet_Lib::network::network::{AccessPoint, WifiStrength};
glib::wrapper! {
pub struct WifiEntry(ObjectSubclass<wifiEntryImpl::WifiEntry>)
@ -11,23 +17,115 @@ glib::wrapper! {
@implements gtk::Accessible, gtk::Buildable, gtk::Actionable, gtk::ConstraintTarget;
}
unsafe impl Send for WifiEntry {}
unsafe impl Sync for WifiEntry {}
impl WifiEntry {
pub fn new(strength: WifiStrength, name: &str, isEncrypted: bool) -> Self {
let entry: WifiEntry = Object::builder().build();
pub fn new(access_point: AccessPoint) -> Arc<Self> {
let entry: Arc<WifiEntry> = Arc::new(Object::builder().build());
let stored_entry = entry.clone();
let new_entry = entry.clone();
let entryImp = entry.imp();
let strength = WifiStrength::from_u8(access_point.strength);
let ssid = access_point.ssid.clone();
let name_opt = String::from_utf8(ssid).unwrap_or_else(|_| String::from(""));
let name = name_opt.as_str();
let stored = access_point.stored;
entryImp.wifiStrength.set(strength);
entryImp.resetWifiLabel.get().set_text(name);
entryImp.resetWifiEncrypted.set_visible(isEncrypted);
entryImp.resetWifiStrength.get().set_from_icon_name(match strength {
WifiStrength::Excellent => Some("network-wireless-signal-excellent-symbolic"),
WifiStrength::Ok => Some("network-wireless-signal-ok-symbolic"),
WifiStrength::Weak => Some("network-wireless-signal-weak-symbolic"),
WifiStrength::None => Some("network-wireless-signal-none-symbolic"),
});
entryImp.resetWifiEncrypted.set_visible(false);
// TODO handle encryption thing
entryImp
.resetWifiStrength
.get()
.set_from_icon_name(match strength {
WifiStrength::Excellent => Some("network-wireless-signal-excellent-symbolic"),
WifiStrength::Ok => Some("network-wireless-signal-ok-symbolic"),
WifiStrength::Weak => Some("network-wireless-signal-weak-symbolic"),
WifiStrength::None => Some("network-wireless-signal-none-symbolic"),
});
if access_point.connected == true {
entryImp
.resetWifiConnected
.get()
.set_from_icon_name(Some("network-wireless-connected-symbolic"));
}
{
let mut wifiName = entryImp.wifiName.borrow_mut();
*wifiName = String::from(name);
}
entryImp.accessPoint.set(access_point);
let gesture = GestureClick::new();
if stored {
entryImp
.resetWifiStored
.get()
.set_from_icon_name(Some("document-save-symbolic"));
gesture.connect_released(move |_, _, _, _| {
click_stored_network(stored_entry.clone());
});
} else {
gesture.connect_released(move |_, _, _, _| {
click_new_network(new_entry.clone());
});
}
entry.add_controller(gesture);
entry
}
}
}
pub fn click_stored_network(entry: Arc<WifiEntry>) {
// TODO handle unknown access point -> should be done by having 2 different categories
let entryImp = entry.imp();
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
"org.xetibo.ReSet",
"/org/xetibo/ReSet",
Duration::from_millis(1000),
);
let access_point = entryImp.accessPoint.clone().into_inner();
if access_point.connected == true {
let res: Result<(bool,), Error> =
proxy.method_call("org.xetibo.ReSet", "DisconnectFromCurrentAccessPoint", ());
if res.is_err() {
// TODO handle error
println!("no worky");
return;
}
let (res,) = res.unwrap();
if res == false {
} else {
entryImp.resetWifiConnected.get().set_from_icon_name(None);
let mut access_point = entryImp.accessPoint.borrow_mut();
(*access_point).connected = false;
}
return;
}
dbg!(access_point.clone());
let res: Result<(bool,), Error> = proxy.method_call(
"org.xetibo.ReSet",
"ConnectToKnownAccessPoint",
(access_point,),
);
if res.is_err() {
// TODO handle error
println!("no worky");
} else {
let (res,) = res.unwrap();
if res == false {
println!("no worky but it connected");
} else {
println!("worky");
entryImp
.resetWifiConnected
.get()
.set_from_icon_name(Some("network-wireless-connected-symbolic"));
let mut access_point = entryImp.accessPoint.borrow_mut();
(*access_point).connected = true;
}
}
}
pub fn click_new_network(entry: Arc<WifiEntry>) {
println!("Not implemented yet :)");
}

View file

@ -1,17 +1,9 @@
use std::cell::RefCell;
use gtk::{Button, CompositeTemplate, glib, Image, Label};
use ReSet_Lib::network::network::{WifiStrength, AccessPoint};
use gtk::{Button, CompositeTemplate, glib, Image, Label, Gesture, GestureClick};
use gtk::subclass::prelude::*;
use crate::components::wifi::wifiEntry;
#[derive(Default, Copy, Clone)]
pub enum WifiStrength {
Excellent,
Ok,
Weak,
#[default]
None,
}
#[allow(non_snake_case)]
#[derive(Default, CompositeTemplate)]
#[template(resource = "/org/Xetibo/ReSet/resetWifiEntry.ui")]
@ -24,10 +16,18 @@ pub struct WifiEntry {
pub resetWifiLabel: TemplateChild<Label>,
#[template_child]
pub resetWifiButton: TemplateChild<Button>,
#[template_child]
pub resetWifiConnected: TemplateChild<Image>,
#[template_child]
pub resetWifiStored: TemplateChild<Image>,
pub wifiName: RefCell<String>,
pub wifiStrength: RefCell<WifiStrength>,
pub accessPoint: RefCell<AccessPoint>,
}
unsafe impl Send for WifiEntry {}
unsafe impl Sync for WifiEntry {}
#[glib::object_subclass]
impl ObjectSubclass for WifiEntry {
const NAME: &'static str = "resetWifiEntry";

View file

@ -1,11 +1,15 @@
use std::sync::Arc;
use gtk::{FlowBox, Label};
use crate::components::audio::audioBox::AudioBox;
use crate::components::bluetooth::bluetoothBox::BluetoothBox;
use crate::components::base::settingBox::SettingBox;
use crate::components::wifi::wifiBox::WifiBox;
use crate::components::wifi::wifiBox::{WifiBox, scanForWifi};
pub const HANDLE_CONNECTIVITY_CLICK: fn(FlowBox) = |resetMain: FlowBox| {
let wifiBox = SettingBox::new(&WifiBox::new());
let wifiBox = Arc::new(WifiBox::new());
scanForWifi(wifiBox.clone());
let wifiBox = SettingBox::new(&*wifiBox);
let bluetoothBox = SettingBox::new(&BluetoothBox::new());
resetMain.remove_all();
resetMain.insert(&wifiBox, -1);

View file

@ -1,9 +1,9 @@
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::sidebarEntry::SidebarEntry;
@ -17,6 +17,9 @@ glib::wrapper! {
gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
}
unsafe impl Send for Window {}
unsafe impl Sync for Window {}
#[allow(non_snake_case)]
impl Window {
pub fn new(app: &Application) -> Self {
@ -26,13 +29,17 @@ impl Window {
pub fn setupCallback(&self) {
let selfImp = self.imp();
selfImp.resetSearchEntry.connect_search_changed(clone!(@ weak self as window => move |_| {
window.filterList();
}));
selfImp
.resetSearchEntry
.connect_search_changed(clone!(@ weak self as window => move |_| {
window.filterList();
}));
selfImp.resetSideBarToggle.connect_clicked(clone!(@ weak self as window => move |_| {
window.toggleSidebar();
}));
selfImp
.resetSideBarToggle
.connect_clicked(clone!(@ weak self as window => move |_| {
window.toggleSidebar();
}));
selfImp.resetSidebarList.connect_row_activated(
clone!(@ weak selfImp as flowbox => move |_, y| {
@ -42,7 +49,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();
}));
@ -54,7 +63,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",
@ -77,13 +88,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 {
@ -218,24 +241,26 @@ impl Window {
pub fn setupPopoverButtons(&self) {
let selfImp = self.imp();
selfImp.resetAboutButton.connect_clicked(clone!(@ weak self as window => move |_| {
let dialog = adw::AboutWindow::builder()
.application_name("ReSet")
.application_icon("ReSet")
.developer_name("Xetibo")
.license("GPL-3.0")
.license_type(gtk::License::Gpl30)
.website("https://github.com/Xetibo/ReSet")
.issue_url("https://github.com/Xetibo/ReSet/issues")
.version("0.0.1")
.transient_for(&window)
.modal(true)
.copyright("© 2022-2023 Xetibo")
.developers(vec!["DashieTM".to_string(), "Takotori".to_string()])
.designers(vec!["DashieTM".to_string(), "Takotori".to_string()])
.build();
selfImp
.resetAboutButton
.connect_clicked(clone!(@ weak self as window => move |_| {
let dialog = adw::AboutWindow::builder()
.application_name("ReSet")
.application_icon("ReSet")
.developer_name("Xetibo")
.license("GPL-3.0")
.license_type(gtk::License::Gpl30)
.website("https://github.com/Xetibo/ReSet")
.issue_url("https://github.com/Xetibo/ReSet/issues")
.version("0.0.1")
.transient_for(&window)
.modal(true)
.copyright("© 2022-2023 Xetibo")
.developers(vec!["DashieTM".to_string(), "Takotori".to_string()])
.designers(vec!["DashieTM".to_string(), "Takotori".to_string()])
.build();
dialog.present();
}));
dialog.present();
}));
}
}

View file

@ -38,6 +38,9 @@ pub struct Window {
pub sidebarEntries: RefCell<Vec<(SidebarEntry, Vec<SidebarEntry>)>>,
}
unsafe impl Send for Window {}
unsafe impl Sync for Window {}
#[glib::object_subclass]
impl ObjectSubclass for Window {
const NAME: &'static str = "resetUI";
@ -72,4 +75,4 @@ impl WindowImpl for Window {}
impl ApplicationWindowImpl for Window {}
impl AdwApplicationWindowImpl for Window {}
impl AdwApplicationWindowImpl for Window {}

View file

@ -89,7 +89,7 @@
<object class="GtkBox">
<property name="orientation">vertical</property>
<child>
<object class="GtkButton">
<object class="GtkButton" id="resetPreferenceButton">
<property name="has-frame">False</property>
<property name="label">Preferences</property>
</object>
@ -100,6 +100,12 @@
<property name="label">About</property>
</object>
</child>
<child>
<object class="GtkButton" id="resetShortcutsButton">
<property name="has-frame">False</property>
<property name="label">Shortcuts</property>
</object>
</child>
</object>
</property>
</object>

View file

@ -0,0 +1,23 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.17.0 -->
<interface>
<requires lib="gtk" version="4.12"/>
<requires lib="libadwaita" version="1.0"/>
<template class="resetPasswordPopup" parent="AdwWindow">
<child>
<object class="GtkBox">
<child>
<object class="GtkEntry" id="resetWifiPasswordEntry">
<property name="activates-default">True</property>
<property name="invisible-char-set">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="resetWifiPasswordButton">
<property name="label">connect</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -13,7 +13,8 @@
(12,1,None,"resetMicrophone.ui",None,None,None,None,None,None,None),
(13,1,None,"resetMicSourceEntry.ui",None,None,None,None,None,None,None),
(14,1,None,"resetSettingBox.ui",None,None,None,None,None,None,None),
(15,1,None,"resetListBoxRow.ui",None,None,None,None,None,None,None)
(15,1,None,"resetListBoxRow.ui",None,None,None,None,None,None,None),
(16,1,None,"resetPasswordPopup.ui",None,None,None,None,None,None,None)
</ui>
<object>
(3,1,"AdwApplicationWindow","resetUI",None,None,None,None,-1," &lt;child&gt;\n &lt;object id=\"resetSidebarBreakpoint\" class=\"AdwBreakpoint\"&gt;\n &lt;/object&gt;\n &lt;/child&gt;"),
@ -33,7 +34,7 @@
(3,34,"GtkBox","resetPath",25,None,None,None,3,None),
(3,35,"GtkPopoverMenu","resetPopoverMenu",33,None,None,None,-1,None),
(3,36,"GtkBox",None,35,None,None,None,-1,None),
(3,38,"GtkButton",None,36,None,None,None,1,None),
(3,38,"GtkButton","resetPreferenceButton",36,None,None,None,1,None),
(3,39,"GtkButton","resetAboutButton",36,None,None,None,2,None),
(3,40,"GtkScrolledWindow",None,18,None,None,None,1,None),
(3,41,"GtkViewport",None,40,None,None,None,None,None),
@ -46,6 +47,7 @@
(3,48,"GtkButton",None,34,None,None,None,4,None),
(3,49,"GtkLabel",None,34,None,None,None,1,None),
(3,50,"GtkLabel",None,34,None,None,None,3,None),
(3,51,"GtkButton","resetShortcutsButton",36,None,None,None,2,None),
(4,7,"GtkBox","resetWifi",None,None,None,None,None,None),
(4,70,"AdwNavigationView",None,7,None,None,None,-1,None),
(4,71,"AdwNavigationPage",None,70,None,None,None,-1,None),
@ -78,7 +80,9 @@
(5,4,"GtkImage","resetWifiStrength",3,None,None,None,None,None),
(5,5,"GtkImage","resetWifiEncrypted",3,None,None,None,1,None),
(5,6,"GtkLabel","resetWifiLabel",2,None,None,None,1,None),
(5,7,"GtkButton","resetWifiButton",2,None,None,None,2,None),
(5,7,"GtkButton","resetWifiButton",2,None,None,None,4,None),
(5,8,"GtkImage","resetWifiConnected",2,None,None,None,3,None),
(5,10,"GtkImage","resetWifiStored",2,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),
@ -151,7 +155,11 @@
(13,9,"GtkLabel","resetMicPercentage",5,None,None,None,2,None),
(13,10,"GtkProgressBar","resetMicMeter",1,None,None,None,2,None),
(14,1,"GtkBox","resetSetting",None,None,None,None,-1,None),
(15,1,"GtkListBoxRow","resetListBoxRow",None,None,None,None,None,None)
(15,1,"GtkListBoxRow","resetListBoxRow",None,None,None,None,None,None),
(16,1,"AdwWindow","resetPasswordPopup",None,None,None,None,-1,None),
(16,2,"GtkBox",None,1,None,None,None,-1,None),
(16,3,"GtkEntry","resetWifiPasswordEntry",2,None,None,None,-1,None),
(16,4,"GtkButton","resetWifiPasswordButton",2,None,None,None,-1,None)
</object>
<object_property>
(3,1,"GtkWindow","default-height","500",None,None,None,None,None,None,None,None,None),
@ -222,6 +230,8 @@
(3,48,"GtkButton","label","Advanced",None,None,None,None,None,None,None,None,None),
(3,49,"GtkLabel","label","&gt;",None,None,None,None,None,None,None,None,None),
(3,50,"GtkLabel","label","&gt;",None,None,None,None,None,None,None,None,None),
(3,51,"GtkButton","has-frame","False",None,None,None,None,None,None,None,None,None),
(3,51,"GtkButton","label","Shortcuts",None,None,None,None,None,None,None,None,None),
(4,7,"GtkOrientable","orientation","vertical",None,None,None,None,None,None,None,None,None),
(4,7,"GtkWidget","hexpand","True",None,None,None,None,None,None,None,None,None),
(4,7,"GtkWidget","hexpand-set","True",None,None,None,None,None,None,None,None,None),
@ -304,6 +314,10 @@
(5,7,"GtkButton","icon-name","info-symbolic",None,None,None,None,None,None,None,None,None),
(5,7,"GtkWidget","halign","start",None,None,None,None,None,None,None,None,None),
(5,7,"GtkWidget","valign","center",None,None,None,None,None,None,None,None,None),
(5,8,"GtkWidget","halign","end",None,None,None,None,None,None,None,None,None),
(5,8,"GtkWidget","valign","center",None,None,None,None,None,None,None,None,None),
(5,10,"GtkWidget","halign","end",None,None,None,None,None,None,None,None,None),
(5,10,"GtkWidget","valign","center",None,None,None,None,None,None,None,None,None),
(6,1,"GtkListBoxRow","child",None,None,None,None,None,2,None,None,None,None),
(6,2,"GtkWidget","margin-bottom","10",None,None,None,None,None,None,None,None,None),
(6,2,"GtkWidget","margin-start","10",None,None,None,None,None,None,None,None,None),
@ -462,7 +476,10 @@
(14,1,"GtkWidget","valign","start",None,None,None,None,None,None,None,None,None),
(14,1,"GtkWidget","width-request","500",None,None,None,None,None,None,None,None,None),
(15,1,"GtkListBoxRow","selectable","False",None,None,None,None,None,None,None,None,None),
(15,1,"GtkWidget","height-request","40",None,None,None,None,None,None,None,None,None)
(15,1,"GtkWidget","height-request","40",None,None,None,None,None,None,None,None,None),
(16,3,"GtkEntry","activates-default","True",None,None,None,None,None,None,None,None,None),
(16,3,"GtkEntry","invisible-char-set","True",None,None,None,None,None,None,None,None,None),
(16,4,"GtkButton","label","connect",None,None,None,None,None,None,None,None,None)
</object_property>
<object_data>
(3,42,"GtkWidget",1,1,None,None,None,None,None,None),

View file

@ -34,6 +34,18 @@
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkImage" id="resetWifiStored">
<property name="halign">end</property>
<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="GtkButton" id="resetWifiButton">
<property name="halign">start</property>