mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-03-07 11:59:59 +03:00
properly synchronize frontend
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
<!-- enabled -->
|
||||
<child type="prefix">
|
||||
<object class="GtkSwitch" id="enable_switch">
|
||||
<signal name="state_set" handler="handle_activate_switch" swapped="true"/>
|
||||
<property name="valign">center</property>
|
||||
<property name="halign">end</property>
|
||||
<property name="tooltip-text" translatable="yes">enable</property>
|
||||
@@ -68,7 +67,6 @@
|
||||
</items>
|
||||
</object>
|
||||
</property>
|
||||
<signal name="notify::selected" handler="handle_position_changed" swapped="true"/>
|
||||
</object>
|
||||
</child>
|
||||
<!-- delete button -->
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use std::cell::Cell;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use glib::Properties;
|
||||
@@ -21,7 +20,6 @@ pub struct ClientObject {
|
||||
#[property(name = "resolving", get, set, type = bool, member = resolving)]
|
||||
#[property(name = "ips", get, set, type = Vec<String>, member = ips)]
|
||||
pub data: RefCell<ClientData>,
|
||||
pub ignore_next_update: Cell<bool>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
|
||||
@@ -3,8 +3,8 @@ use std::cell::RefCell;
|
||||
use adw::subclass::prelude::*;
|
||||
use adw::{prelude::*, ActionRow, ComboRow};
|
||||
use glib::{subclass::InitializingObject, Binding};
|
||||
use gtk::glib::clone;
|
||||
use gtk::glib::subclass::Signal;
|
||||
use gtk::glib::{clone, SignalHandlerId};
|
||||
use gtk::{glib, Button, CompositeTemplate, Entry, Switch};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
@@ -28,6 +28,10 @@ pub struct ClientRow {
|
||||
#[template_child]
|
||||
pub dns_loading_indicator: TemplateChild<gtk::Spinner>,
|
||||
pub bindings: RefCell<Vec<Binding>>,
|
||||
pub hostname_change_handler: RefCell<Option<SignalHandlerId>>,
|
||||
pub port_change_handler: RefCell<Option<SignalHandlerId>>,
|
||||
pub position_change_handler: RefCell<Option<SignalHandlerId>>,
|
||||
pub set_state_handler: RefCell<Option<SignalHandlerId>>,
|
||||
}
|
||||
|
||||
#[glib::object_subclass]
|
||||
@@ -59,13 +63,42 @@ impl ObjectImpl for ClientRow {
|
||||
row.handle_client_delete(button);
|
||||
}
|
||||
));
|
||||
self.hostname.connect_changed(clone!(
|
||||
let handler = self.hostname.connect_changed(clone!(
|
||||
#[weak(rename_to = row)]
|
||||
self,
|
||||
move |entry| {
|
||||
row.handle_hostname_changed(entry);
|
||||
}
|
||||
));
|
||||
self.hostname_change_handler.replace(Some(handler));
|
||||
let handler = self.port.connect_changed(clone!(
|
||||
#[weak(rename_to = row)]
|
||||
self,
|
||||
move |entry| {
|
||||
row.handle_port_changed(entry);
|
||||
}
|
||||
));
|
||||
self.port_change_handler.replace(Some(handler));
|
||||
let handler = self.position.connect_selected_notify(clone!(
|
||||
#[weak(rename_to = row)]
|
||||
self,
|
||||
move |position| {
|
||||
row.handle_position_changed(position);
|
||||
}
|
||||
));
|
||||
self.position_change_handler.replace(Some(handler));
|
||||
// <signal name="state_set" handler="handle_activate_switch" swapped="true"/>
|
||||
let handler = self.enable_switch.connect_state_set(clone!(
|
||||
#[weak(rename_to = row)]
|
||||
self,
|
||||
#[upgrade_or]
|
||||
glib::Propagation::Proceed,
|
||||
move |switch, state| {
|
||||
row.handle_activate_switch(state, switch);
|
||||
glib::Propagation::Proceed
|
||||
}
|
||||
));
|
||||
self.set_state_handler.replace(Some(handler));
|
||||
}
|
||||
|
||||
fn signals() -> &'static [glib::subclass::Signal] {
|
||||
@@ -109,24 +142,70 @@ impl ClientRow {
|
||||
self.obj().emit_by_name::<()>("request-delete", &[]);
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn handle_port_changed(&self) {
|
||||
if let Ok(port) = self.port.text().parse::<u16>() {
|
||||
fn handle_port_changed(&self, port_entry: &Entry) {
|
||||
if let Ok(port) = port_entry.text().parse::<u16>() {
|
||||
self.obj()
|
||||
.emit_by_name::<()>("request-port-change", &[&(port as u32)]);
|
||||
}
|
||||
}
|
||||
|
||||
// #[template_callback]
|
||||
fn handle_hostname_changed(&self, entry: &Entry) {
|
||||
fn handle_hostname_changed(&self, hostname_entry: &Entry) {
|
||||
log::error!("hostname changed: {}", hostname_entry.text());
|
||||
self.obj()
|
||||
.emit_by_name::<()>("request-hostname-change", &[&entry.text()]);
|
||||
.emit_by_name::<()>("request-hostname-change", &[&hostname_entry.text()]);
|
||||
}
|
||||
|
||||
#[template_callback]
|
||||
fn handle_position_changed(&self) {
|
||||
fn handle_position_changed(&self, position: &ComboRow) {
|
||||
self.obj()
|
||||
.emit_by_name("request-position-change", &[&self.position.selected()])
|
||||
.emit_by_name("request-position-change", &[&position.selected()])
|
||||
}
|
||||
|
||||
pub fn block_hostname_change(&self) {
|
||||
let handler = self.hostname_change_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.hostname.block_signal(handler);
|
||||
}
|
||||
|
||||
pub fn unblock_hostname_change(&self) {
|
||||
let handler = self.hostname_change_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.hostname.unblock_signal(handler);
|
||||
}
|
||||
|
||||
pub fn block_port_change(&self) {
|
||||
let handler = self.port_change_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.port.block_signal(handler);
|
||||
}
|
||||
|
||||
pub fn unblock_port_change(&self) {
|
||||
let handler = self.port_change_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.port.unblock_signal(handler);
|
||||
}
|
||||
|
||||
pub fn block_position_change(&self) {
|
||||
let handler = self.position_change_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.position.block_signal(handler);
|
||||
}
|
||||
|
||||
pub fn unblock_position_change(&self) {
|
||||
let handler = self.position_change_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.position.unblock_signal(handler);
|
||||
}
|
||||
|
||||
pub fn block_active_switch(&self) {
|
||||
let handler = self.set_state_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.enable_switch.block_signal(handler);
|
||||
}
|
||||
|
||||
pub fn unblock_active_switch(&self) {
|
||||
let handler = self.set_state_handler.borrow();
|
||||
let handler = handler.as_ref().expect("signal handler");
|
||||
self.enable_switch.unblock_signal(handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ use glib::{clone, Object};
|
||||
use gtk::{
|
||||
gio,
|
||||
glib::{self, closure_local},
|
||||
ListBox, NoSelection,
|
||||
NoSelection,
|
||||
};
|
||||
|
||||
use lan_mouse_ipc::{
|
||||
@@ -58,6 +58,14 @@ impl Window {
|
||||
self.clients().item(idx).map(|o| o.downcast().unwrap())
|
||||
}
|
||||
|
||||
fn row_by_idx(&self, idx: i32) -> Option<ClientRow> {
|
||||
self.imp()
|
||||
.client_list
|
||||
.get()
|
||||
.row_at_index(idx)
|
||||
.map(|o| o.downcast().expect("expected ClientRow"))
|
||||
}
|
||||
|
||||
fn authorized_by_idx(&self, idx: u32) -> Option<KeyObject> {
|
||||
self.authorized().item(idx).map(|o| o.downcast().unwrap())
|
||||
}
|
||||
@@ -118,8 +126,11 @@ impl Window {
|
||||
#[strong]
|
||||
window,
|
||||
move |row: ClientRow, hostname: String| {
|
||||
log::info!("request-hostname-change");
|
||||
if let Some(client) = window.client_by_idx(row.index() as u32) {
|
||||
let hostname = Some(hostname).filter(|s| !s.is_empty());
|
||||
/* changed in response to FrontendEvent
|
||||
* -> do not request additional update */
|
||||
window.request(FrontendRequest::UpdateHostname(
|
||||
client.handle(),
|
||||
hostname,
|
||||
@@ -264,14 +275,10 @@ impl Window {
|
||||
self.update_dns_state(handle, !state.ips.is_empty());
|
||||
}
|
||||
|
||||
pub fn client_idx(&self, handle: ClientHandle) -> Option<usize> {
|
||||
self.clients().iter::<ClientObject>().position(|c| {
|
||||
if let Ok(c) = c {
|
||||
c.handle() == handle
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
pub(super) fn client_idx(&self, handle: ClientHandle) -> Option<usize> {
|
||||
self.clients()
|
||||
.iter::<ClientObject>()
|
||||
.position(|c| c.ok().map(|c| c.handle() == handle).unwrap_or_default())
|
||||
}
|
||||
|
||||
pub fn delete_client(&self, handle: ClientHandle) {
|
||||
@@ -287,41 +294,51 @@ impl Window {
|
||||
}
|
||||
|
||||
pub fn update_client_config(&self, handle: ClientHandle, client: ClientConfig) {
|
||||
let Some(idx) = self.client_idx(handle) else {
|
||||
log::warn!("could not find client with handle {}", handle);
|
||||
let Some(row) = self.row_for_handle(handle) else {
|
||||
log::warn!("could not find row for handle {}", handle);
|
||||
return;
|
||||
};
|
||||
let Some(client_object) = self.client_object_for_handle(handle) else {
|
||||
log::warn!("could not find row for handle {}", handle);
|
||||
return;
|
||||
};
|
||||
let client_object = self.clients().item(idx as u32).unwrap();
|
||||
let client_object: &ClientObject = client_object.downcast_ref().unwrap();
|
||||
let data = client_object.get_data();
|
||||
|
||||
/* only change if it actually has changed, otherwise
|
||||
* the update signal is triggered */
|
||||
if data.hostname != client.hostname {
|
||||
client_object.set_hostname(client.hostname.unwrap_or("".into()));
|
||||
}
|
||||
if data.port != client.port as u32 {
|
||||
client_object.set_port(client.port as u32);
|
||||
}
|
||||
if data.position != client.pos.to_string() {
|
||||
client_object.set_position(client.pos.to_string());
|
||||
}
|
||||
row.imp().block_hostname_change();
|
||||
client_object.set_hostname(client.hostname.unwrap_or("".into()));
|
||||
row.imp().unblock_hostname_change();
|
||||
|
||||
row.imp().block_port_change();
|
||||
client_object.set_port(client.port as u32);
|
||||
row.imp().unblock_port_change();
|
||||
|
||||
row.imp().block_position_change();
|
||||
client_object.set_position(client.pos.to_string());
|
||||
row.imp().unblock_position_change();
|
||||
}
|
||||
|
||||
pub fn update_client_state(&self, handle: ClientHandle, state: ClientState) {
|
||||
let Some(idx) = self.client_idx(handle) else {
|
||||
log::warn!("could not find client with handle {}", handle);
|
||||
let Some(row) = self.row_for_handle(handle) else {
|
||||
log::warn!("could not find row for handle {}", handle);
|
||||
return;
|
||||
};
|
||||
let Some(client_object) = self.client_object_for_handle(handle) else {
|
||||
log::warn!("could not find row for handle {}", handle);
|
||||
return;
|
||||
};
|
||||
let client_object = self.clients().item(idx as u32).unwrap();
|
||||
let client_object: &ClientObject = client_object.downcast_ref().unwrap();
|
||||
let data = client_object.get_data();
|
||||
|
||||
/* activation state */
|
||||
row.imp().block_active_switch();
|
||||
client_object.set_active(state.active);
|
||||
row.imp().unblock_active_switch();
|
||||
log::info!("set active to {}", state.active);
|
||||
|
||||
/* dns state */
|
||||
client_object.set_resolving(state.resolving);
|
||||
log::info!("resolving {}: {}", data.handle, state.resolving);
|
||||
log::info!(
|
||||
"resolving {}: {}",
|
||||
client_object.get_data().handle,
|
||||
state.resolving
|
||||
);
|
||||
|
||||
self.update_dns_state(handle, !state.ips.is_empty());
|
||||
let ips = state
|
||||
@@ -332,18 +349,25 @@ impl Window {
|
||||
client_object.set_ips(ips);
|
||||
}
|
||||
|
||||
pub fn update_dns_state(&self, handle: ClientHandle, resolved: bool) {
|
||||
let Some(idx) = self.client_idx(handle) else {
|
||||
log::warn!("could not find client with handle {}", handle);
|
||||
return;
|
||||
};
|
||||
let list_box: ListBox = self.imp().client_list.get();
|
||||
let row = list_box.row_at_index(idx as i32).unwrap();
|
||||
let client_row: ClientRow = row.downcast().expect("expected ClientRow Object");
|
||||
if resolved {
|
||||
client_row.imp().dns_button.set_css_classes(&["success"])
|
||||
} else {
|
||||
client_row.imp().dns_button.set_css_classes(&["warning"])
|
||||
fn client_object_for_handle(&self, handle: ClientHandle) -> Option<ClientObject> {
|
||||
self.client_idx(handle)
|
||||
.map(|i| self.client_by_idx(i as u32))
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn row_for_handle(&self, handle: ClientHandle) -> Option<ClientRow> {
|
||||
self.client_idx(handle)
|
||||
.map(|i| self.row_by_idx(i as i32))
|
||||
.flatten()
|
||||
}
|
||||
|
||||
fn update_dns_state(&self, handle: ClientHandle, resolved: bool) {
|
||||
if let Some(client_row) = self.row_for_handle(handle) {
|
||||
if resolved {
|
||||
client_row.imp().dns_button.set_css_classes(&["success"])
|
||||
} else {
|
||||
client_row.imp().dns_button.set_css_classes(&["warning"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -455,6 +455,7 @@ impl Service {
|
||||
}
|
||||
|
||||
fn update_hostname(&mut self, handle: ClientHandle, hostname: Option<String>) {
|
||||
log::info!("hostname changed: {hostname:?}");
|
||||
if self.client_manager.set_hostname(handle, hostname.clone()) {
|
||||
self.resolve(handle);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user