formatting

This commit is contained in:
Ferdinand Schober
2023-12-09 00:43:54 +01:00
parent 56e5f7a30d
commit 5a7e0cf89c
26 changed files with 881 additions and 497 deletions

View File

@@ -1,12 +1,16 @@
use anyhow::{anyhow, Result, Context};
use std::{thread, io::{Write, Read, ErrorKind}, str::SplitWhitespace};
use anyhow::{anyhow, Context, Result};
#[cfg(windows)]
use std::net::SocketAddrV4;
use std::{
io::{ErrorKind, Read, Write},
str::SplitWhitespace,
thread,
};
#[cfg(unix)]
use std::os::unix::net::UnixStream;
#[cfg(windows)]
use std::net::TcpStream;
#[cfg(unix)]
use std::os::unix::net::UnixStream;
use crate::{client::Position, config::DEFAULT_PORT};
@@ -31,40 +35,40 @@ pub fn run() -> Result<()> {
let reader = thread::Builder::new()
.name("cli-frontend".to_string())
.spawn(move || {
// all further prompts
prompt();
loop {
let mut buf = String::new();
match std::io::stdin().read_line(&mut buf) {
Ok(0) => break,
Ok(len) => {
if let Some(events) = parse_cmd(buf, len) {
for event in events.iter() {
let json = serde_json::to_string(&event).unwrap();
let bytes = json.as_bytes();
let len = bytes.len().to_be_bytes();
if let Err(e) = tx.write(&len) {
log::error!("error sending message: {e}");
};
if let Err(e) = tx.write(bytes) {
log::error!("error sending message: {e}");
};
if *event == FrontendEvent::Shutdown() {
return;
// all further prompts
prompt();
loop {
let mut buf = String::new();
match std::io::stdin().read_line(&mut buf) {
Ok(0) => break,
Ok(len) => {
if let Some(events) = parse_cmd(buf, len) {
for event in events.iter() {
let json = serde_json::to_string(&event).unwrap();
let bytes = json.as_bytes();
let len = bytes.len().to_be_bytes();
if let Err(e) = tx.write(&len) {
log::error!("error sending message: {e}");
};
if let Err(e) = tx.write(bytes) {
log::error!("error sending message: {e}");
};
if *event == FrontendEvent::Shutdown() {
return;
}
}
// prompt is printed after the server response is received
} else {
prompt();
}
// prompt is printed after the server response is received
} else {
prompt();
}
Err(e) => {
log::error!("error reading from stdin: {e}");
break;
}
}
Err(e) => {
log::error!("error reading from stdin: {e}");
break
}
}
}
})?;
})?;
let writer = thread::Builder::new()
.name("cli-frontend-notify".to_string())
@@ -93,35 +97,43 @@ pub fn run() -> Result<()> {
};
match notify {
FrontendNotify::NotifyClientCreate(client, host, port, pos) => {
log::info!("new client ({client}): {}:{port} - {pos}", host.as_deref().unwrap_or(""));
},
log::info!(
"new client ({client}): {}:{port} - {pos}",
host.as_deref().unwrap_or("")
);
}
FrontendNotify::NotifyClientUpdate(client, host, port, pos) => {
log::info!("client ({client}) updated: {}:{port} - {pos}", host.as_deref().unwrap_or(""));
},
log::info!(
"client ({client}) updated: {}:{port} - {pos}",
host.as_deref().unwrap_or("")
);
}
FrontendNotify::NotifyClientDelete(client) => {
log::info!("client ({client}) deleted.");
},
}
FrontendNotify::NotifyError(e) => {
log::warn!("{e}");
},
}
FrontendNotify::Enumerate(clients) => {
for (client, active) in clients.into_iter() {
log::info!("client ({}) [{}]: active: {}, associated addresses: [{}]",
log::info!(
"client ({}) [{}]: active: {}, associated addresses: [{}]",
client.handle,
client.hostname.as_deref().unwrap_or(""),
if active { "yes" } else { "no" },
client.addrs.into_iter().map(|a| a.to_string())
.collect::<Vec<String>>()
.join(", ")
client
.addrs
.into_iter()
.map(|a| a.to_string())
.collect::<Vec<String>>()
.join(", ")
);
}
},
FrontendNotify::NotifyPortChange(port, msg) => {
match msg {
Some(msg) => log::info!("could not change port: {msg}"),
None => log::info!("port changed: {port}"),
}
}
FrontendNotify::NotifyPortChange(port, msg) => match msg {
Some(msg) => log::info!("could not change port: {msg}"),
None => log::info!("port changed: {port}"),
},
}
prompt();
}
@@ -132,10 +144,10 @@ pub fn run() -> Result<()> {
let msg = match (e.downcast_ref::<&str>(), e.downcast_ref::<String>()) {
(Some(&s), _) => s,
(_, Some(s)) => s,
_ => "no panic info"
_ => "no panic info",
};
log::error!("reader thread paniced: {msg}");
},
}
}
match writer.join() {
Ok(_) => (),
@@ -143,10 +155,10 @@ pub fn run() -> Result<()> {
let msg = match (e.downcast_ref::<&str>(), e.downcast_ref::<String>()) {
(Some(&s), _) => s,
(_, Some(s)) => s,
_ => "no panic info"
_ => "no panic info",
};
log::error!("writer thread paniced: {msg}");
},
}
}
Ok(())
}
@@ -158,7 +170,7 @@ fn prompt() {
fn parse_cmd(s: String, len: usize) -> Option<Vec<FrontendEvent>> {
if len == 0 {
return Some(vec![FrontendEvent::Shutdown()])
return Some(vec![FrontendEvent::Shutdown()]);
}
let mut l = s.split_whitespace();
let cmd = l.next()?;
@@ -191,7 +203,7 @@ fn parse_cmd(s: String, len: usize) -> Option<Vec<FrontendEvent>> {
log::warn!("{e}");
None
}
_ => None
_ => None,
}
}
@@ -209,22 +221,34 @@ fn parse_connect(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
} else {
DEFAULT_PORT
};
Ok(vec![FrontendEvent::AddClient(Some(host), port, pos), FrontendEvent::Enumerate()])
Ok(vec![
FrontendEvent::AddClient(Some(host), port, pos),
FrontendEvent::Enumerate(),
])
}
fn parse_disconnect(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
let client = l.next().context("usage: disconnect <client_id>")?.parse()?;
Ok(vec![FrontendEvent::DelClient(client), FrontendEvent::Enumerate()])
Ok(vec![
FrontendEvent::DelClient(client),
FrontendEvent::Enumerate(),
])
}
fn parse_activate(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
let client = l.next().context("usage: activate <client_id>")?.parse()?;
Ok(vec![FrontendEvent::ActivateClient(client, true), FrontendEvent::Enumerate()])
Ok(vec![
FrontendEvent::ActivateClient(client, true),
FrontendEvent::Enumerate(),
])
}
fn parse_deactivate(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {
let client = l.next().context("usage: deactivate <client_id>")?.parse()?;
Ok(vec![FrontendEvent::ActivateClient(client, false), FrontendEvent::Enumerate()])
Ok(vec![
FrontendEvent::ActivateClient(client, false),
FrontendEvent::Enumerate(),
])
}
fn parse_port(mut l: SplitWhitespace) -> Result<Vec<FrontendEvent>> {

View File

@@ -1,13 +1,24 @@
mod window;
mod client_object;
mod client_row;
mod window;
use std::{io::{Read, ErrorKind}, env, process, str};
use std::{
env,
io::{ErrorKind, Read},
process, str,
};
use crate::{frontend::gtk::window::Window, config::DEFAULT_PORT};
use crate::{config::DEFAULT_PORT, frontend::gtk::window::Window};
use gtk::{prelude::*, IconTheme, gdk::Display, gio::{SimpleAction, SimpleActionGroup}, glib::{clone, MainContext, Priority}, CssProvider, subclass::prelude::ObjectSubclassIsExt};
use adw::Application;
use gtk::{
gdk::Display,
gio::{SimpleAction, SimpleActionGroup},
glib::{clone, MainContext, Priority},
prelude::*,
subclass::prelude::ObjectSubclassIsExt,
CssProvider, IconTheme,
};
use gtk::{gio, glib, prelude::ApplicationExt};
use self::client_object::ClientObject;
@@ -22,8 +33,7 @@ pub fn run() -> glib::ExitCode {
}
fn gtk_main() -> glib::ExitCode {
gio::resources_register_include!("lan-mouse.gresource")
.expect("Failed to register resources.");
gio::resources_register_include!("lan-mouse.gresource").expect("Failed to register resources.");
let app = Application::builder()
.application_id("de.feschber.lan-mouse")
@@ -41,14 +51,15 @@ fn load_css() {
let provider = CssProvider::new();
provider.load_from_resource("de/feschber/LanMouse/style.css");
gtk::style_context_add_provider_for_display(
&Display::default().expect("Could not connect to a display."),
&Display::default().expect("Could not connect to a display."),
&provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
}
fn load_icons() {
let icon_theme = IconTheme::for_display(&Display::default().expect("Could not connect to a display."));
let icon_theme =
IconTheme::for_display(&Display::default().expect("Could not connect to a display."));
icon_theme.add_resource_path("/de/feschber/LanMouse/icons");
}
@@ -69,7 +80,7 @@ fn build_ui(app: &Application) {
}
};
log::debug!("connected to lan-mouse-socket");
let (sender, receiver) = MainContext::channel::<FrontendNotify>(Priority::default());
gio::spawn_blocking(move || {
@@ -92,14 +103,13 @@ fn build_ui(app: &Application) {
};
// parse json
let json = str::from_utf8(&buf)
.unwrap();
let json = str::from_utf8(&buf).unwrap();
match serde_json::from_str(json) {
Ok(notify) => sender.send(notify).unwrap(),
Err(e) => log::error!("{e}"),
}
} {
Ok(()) => {},
Ok(()) => {}
Err(e) => log::error!("{e}"),
}
});
@@ -152,16 +162,12 @@ fn build_ui(app: &Application) {
}
));
let action_request_client_update = SimpleAction::new(
"request-client-update",
Some(&u32::static_variant_type()),
);
let action_request_client_update =
SimpleAction::new("request-client-update", Some(&u32::static_variant_type()));
// remove client
let action_client_delete = SimpleAction::new(
"request-client-delete",
Some(&u32::static_variant_type()),
);
let action_client_delete =
SimpleAction::new("request-client-delete", Some(&u32::static_variant_type()));
// update client state
action_request_client_update.connect_activate(clone!(@weak window => move |_action, param| {

View File

@@ -1,7 +1,7 @@
mod imp;
use gtk::glib::{self, Object};
use adw::subclass::prelude::*;
use gtk::glib::{self, Object};
use crate::client::ClientHandle;
@@ -10,7 +10,13 @@ glib::wrapper! {
}
impl ClientObject {
pub fn new(handle: ClientHandle, hostname: Option<String>, port: u32, position: String, active: bool) -> Self {
pub fn new(
handle: ClientHandle,
hostname: Option<String>,
port: u32,
position: String,
active: bool,
) -> Self {
Object::builder()
.property("handle", handle)
.property("hostname", hostname)

View File

@@ -16,8 +16,7 @@ glib::wrapper! {
impl ClientRow {
pub fn new(_client_object: &ClientObject) -> Self {
Object::builder()
.build()
Object::builder().build()
}
pub fn bind(&self, client_object: &ClientObject) {
@@ -86,24 +85,19 @@ impl ClientRow {
.sync_create()
.build();
let position_binding = client_object
.bind_property("position", &self.imp().position.get(), "selected")
.transform_from(|_, v: u32| {
match v {
1 => Some("right"),
2 => Some("top"),
3 => Some("bottom"),
_ => Some("left"),
}
.transform_from(|_, v: u32| match v {
1 => Some("right"),
2 => Some("top"),
3 => Some("bottom"),
_ => Some("left"),
})
.transform_to(|_, v: String| {
match v.as_str() {
"right" => Some(1),
"top" => Some(2u32),
"bottom" => Some(3u32),
_ => Some(0u32),
}
.transform_to(|_, v: String| match v.as_str() {
"right" => Some(1),
"top" => Some(2u32),
"bottom" => Some(3u32),
_ => Some(0u32),
})
.bidirectional()
.sync_create()

View File

@@ -1,10 +1,10 @@
use std::cell::RefCell;
use glib::{Binding, subclass::InitializingObject};
use adw::{prelude::*, ComboRow, ActionRow};
use adw::subclass::prelude::*;
use adw::{prelude::*, ActionRow, ComboRow};
use glib::{subclass::InitializingObject, Binding};
use gtk::glib::clone;
use gtk::{glib, CompositeTemplate, Switch, Button};
use gtk::{glib, Button, CompositeTemplate, Switch};
#[derive(CompositeTemplate, Default)]
#[template(resource = "/de/feschber/LanMouse/client_row.ui")]
@@ -44,9 +44,10 @@ impl ObjectSubclass for ClientRow {
impl ObjectImpl for ClientRow {
fn constructed(&self) {
self.parent_constructed();
self.delete_button.connect_clicked(clone!(@weak self as row => move |button| {
row.handle_client_delete(button);
}));
self.delete_button
.connect_clicked(clone!(@weak self as row => move |button| {
row.handle_client_delete(button);
}));
}
}
@@ -55,7 +56,9 @@ impl ClientRow {
#[template_callback]
fn handle_client_set_state(&self, state: bool, switch: &Switch) -> bool {
let idx = self.obj().index() as u32;
switch.activate_action("win.request-client-update", Some(&idx.to_variant())).unwrap();
switch
.activate_action("win.request-client-update", Some(&idx.to_variant()))
.unwrap();
switch.set_state(state);
true // dont run default handler

View File

@@ -4,10 +4,14 @@ use std::io::Write;
use adw::prelude::*;
use adw::subclass::prelude::*;
use gtk::{glib, gio, NoSelection};
use glib::{clone, Object};
use gtk::{gio, glib, NoSelection};
use crate::{frontend::{gtk::client_object::ClientObject, FrontendEvent}, client::{Position, ClientHandle}, config::DEFAULT_PORT};
use crate::{
client::{ClientHandle, Position},
config::DEFAULT_PORT,
frontend::{gtk::client_object::ClientObject, FrontendEvent},
};
use super::client_row::ClientRow;
@@ -67,7 +71,14 @@ impl Window {
row
}
pub fn new_client(&self, handle: ClientHandle, hostname: Option<String>, port: u16, position: Position, active: bool) {
pub fn new_client(
&self,
handle: ClientHandle,
hostname: Option<String>,
port: u16,
position: Position,
active: bool,
) {
let client = ClientObject::new(handle, hostname, port as u32, position.to_string(), active);
self.clients().append(&client);
self.set_placeholder_visible(false);
@@ -122,7 +133,7 @@ impl Window {
"bottom" => Position::Bottom,
_ => {
log::error!("invalid position: {}", data.position);
return
return;
}
};
let hostname = data.hostname;
@@ -133,7 +144,7 @@ impl Window {
let event = FrontendEvent::ActivateClient(client.handle(), !client.active());
self.request(event);
}
pub fn request_client_delete(&self, idx: u32) {
if let Some(obj) = self.clients().item(idx) {
let client_object: &ClientObject = obj
@@ -145,7 +156,7 @@ impl Window {
}
}
fn request(&self, event: FrontendEvent) {
fn request(&self, event: FrontendEvent) {
let json = serde_json::to_string(&event).unwrap();
log::debug!("requesting {json}");
let mut stream = self.imp().stream.borrow_mut();

View File

@@ -1,9 +1,15 @@
use std::{cell::{Cell, RefCell}, os::unix::net::UnixStream};
use std::{
cell::{Cell, RefCell},
os::unix::net::UnixStream,
};
use glib::subclass::InitializingObject;
use adw::{ActionRow, ToastOverlay, prelude::{WidgetExt, EditableExt}};
use adw::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate, ListBox, gio, Entry};
use adw::{
prelude::{EditableExt, WidgetExt},
ActionRow, ToastOverlay,
};
use glib::subclass::InitializingObject;
use gtk::{gio, glib, Button, CompositeTemplate, Entry, ListBox};
use crate::config::DEFAULT_PORT;
@@ -65,7 +71,8 @@ impl Window {
#[template_callback]
fn handle_port_edit_cancel(&self) {
log::debug!("cancel port edit");
self.port_entry.set_text(self.port.get().to_string().as_str());
self.port_entry
.set_text(self.port.get().to_string().as_str());
self.port_edit_apply.set_visible(false);
self.port_edit_cancel.set_visible(false);
}
@@ -82,7 +89,6 @@ impl Window {
}
}
impl ObjectImpl for Window {
fn constructed(&self) {
self.parent_constructed();