Skip to content

Commit

Permalink
Implements save/load/UI for debug server address (#1271)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon authored Feb 1, 2025
1 parent 401f3da commit 9cb1d58
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 19 deletions.
66 changes: 51 additions & 15 deletions gui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ use self::log::LogWriter;
use self::profile::{DisplayResolution, Profile};
use self::setup::{run_setup, SetupError};
use self::ui::{
DesktopExt, MainWindow, ProfileModel, ResolutionModel, RuntimeExt, SlintBackend,
WaitForDebugger,
error, spawn_handler, DesktopExt, MainWindow, ProfileModel, ResolutionModel, RuntimeExt,
SlintBackend, WaitForDebugger,
};
use self::vmm::{CpuError, Vmm, VmmError, VmmEvent};
use async_net::{TcpListener, TcpStream};
Expand All @@ -18,7 +18,9 @@ use erdp::ErrorDisplay;
use futures::{
select_biased, AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, FutureExt, TryStreamExt,
};
use slint::{ComponentHandle, ModelRc, SharedString, ToSharedString, VecModel};
use slint::{
CloseRequestResponse, ComponentHandle, ModelRc, SharedString, ToSharedString, VecModel,
};
use std::cell::Cell;
use std::net::SocketAddrV4;
use std::path::PathBuf;
Expand Down Expand Up @@ -320,15 +322,7 @@ async fn run_launcher(
let win = win.as_weak();
let profiles = profiles.clone();

move || {
let win = win.unwrap();
let row = win.get_selected_profile();
let pro = profiles.update(row, &win);
let loc = data.profiles().data(pro.id());

// TODO: Display error instead of panic.
pro.save(loc).unwrap();
}
move || spawn_handler(&win, |w| save_profile(w, data.clone(), profiles.clone()))
});

win.on_report_issue(|| {
Expand All @@ -353,6 +347,29 @@ async fn run_launcher(
move || todo!()
});

win.window().on_close_requested({
let win = win.as_weak();
let profiles = profiles.clone();

move || {
let win = win.unwrap();
let profile = win.get_selected_profile();

if let Err(e) = profiles.update(profile, &win) {
let m = slint::format!("Failed to update profile: {}.", e.display());

wae::spawn_blocker(
win.clone_strong(),
async move { error(Some(&win), m).await },
);

return CloseRequestResponse::KeepWindowShown;
}

CloseRequestResponse::HideWindow
}
});

// Set window properties.
let physical_devices = ModelRc::new(VecModel::from_iter(
graphics
Expand All @@ -375,11 +392,9 @@ async fn run_launcher(
win.set_center().map_err(ProgramError::CenterMainWindow)?;
win.wait().await;

// Update selected profile.
// Extract window states.
let profile = win.get_selected_profile();

profiles.update(profile, &win);

drop(win);

// Check how we exit.
Expand Down Expand Up @@ -470,6 +485,27 @@ async fn dispatch_vmm(ev: VmmEvent, logs: &mut LogWriter) -> Result<bool, Progra
Ok(true)
}

async fn save_profile(win: MainWindow, data: Arc<DataMgr>, profiles: Rc<ProfileModel>) {
// Update profile.
let row = win.get_selected_profile();
let pro = match profiles.update(row, &win) {
Ok(v) => v,
Err(e) => {
let m = slint::format!("Failed to update profile: {}.", e.display());
error(Some(&win), m).await;
return;
}
};

// Save.
let loc = data.profiles().data(pro.id());

if let Err(e) = pro.save(loc) {
let m = slint::format!("Failed to save profile: {}.", e.display());
error(Some(&win), m).await;
}
}

/// Program arguments parsed from command line.
#[derive(Parser)]
#[command(about = None)]
Expand Down
11 changes: 11 additions & 0 deletions gui/src/profile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use config::Config;
use serde::{Deserialize, Serialize};
use std::fmt::{Display, Formatter};
use std::fs::File;
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::num::NonZero;
use std::path::{Path, PathBuf};
use std::time::SystemTime;
Expand All @@ -15,6 +16,7 @@ pub struct Profile {
id: Uuid,
name: String,
display_resolution: DisplayResolution,
debug_addr: SocketAddr,
kernel_config: Config,
created: SystemTime,
}
Expand Down Expand Up @@ -54,6 +56,14 @@ impl Profile {
self.display_resolution = v;
}

pub fn debug_addr(&self) -> &SocketAddr {
&self.debug_addr
}

pub fn set_debug_addr(&mut self, v: SocketAddr) {
self.debug_addr = v;
}

pub fn kernel_config(&self) -> &Config {
&self.kernel_config
}
Expand Down Expand Up @@ -81,6 +91,7 @@ impl Default for Profile {
id: Uuid::new_v4(),
name: String::from("Default"),
display_resolution: DisplayResolution::Hd,
debug_addr: SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::LOCALHOST, 1234)),
kernel_config: Config {
max_cpu: NonZero::new(8).unwrap(),
},
Expand Down
20 changes: 17 additions & 3 deletions gui/src/ui/profile.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use super::MainWindow;
use crate::profile::{DisplayResolution, Profile};
use slint::{Model, ModelNotify, ModelTracker, SharedString};
use slint::{Model, ModelNotify, ModelTracker, SharedString, ToSharedString};
use std::any::Any;
use std::cell::{RefCell, RefMut};
use std::rc::Rc;
use thiserror::Error;

/// Implementation of [`Model`] for [`DisplayResolution`].
pub struct ResolutionModel([DisplayResolution; 3]);
Expand Down Expand Up @@ -74,18 +75,24 @@ impl ProfileModel {
let p = &profiles[row];

dst.set_selected_resolution(self.resolutions.position(p.display_resolution()).unwrap());
dst.set_debug_address(p.debug_addr().to_shared_string());
}

/// # Panics
/// If `row` is not valid.
pub fn update(&self, row: i32, src: &MainWindow) -> RefMut<Profile> {
pub fn update(&self, row: i32, src: &MainWindow) -> Result<RefMut<Profile>, ProfileError> {
let row = usize::try_from(row).unwrap();
let mut profiles = self.profiles.borrow_mut();
let p = &mut profiles[row];

p.set_display_resolution(self.resolutions.get(src.get_selected_resolution()).unwrap());

RefMut::map(profiles, move |v| &mut v[row])
match src.get_debug_address().parse() {
Ok(v) => p.set_debug_addr(v),
Err(_) => return Err(ProfileError::InvalidDebugAddress),
}

Ok(RefMut::map(profiles, move |v| &mut v[row]))
}

pub fn into_inner(self) -> Vec<Profile> {
Expand All @@ -112,3 +119,10 @@ impl Model for ProfileModel {
self
}
}

/// Represents an error when [`ProfileModel::update()`] fails.
#[derive(Debug, Error)]
pub enum ProfileError {
#[error("invalid debug address")]
InvalidDebugAddress,
}
2 changes: 2 additions & 0 deletions gui/ui/main.slint
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export component MainWindow inherits Window {
in property <[string]> devices;
in property <[string]> resolutions;
in-out property <int> selected-resolution;
in-out property <string> debug-address;
in property <[string]> profiles;
in-out property <int> selected-profile;

Expand Down Expand Up @@ -87,6 +88,7 @@ export component MainWindow inherits Window {
}

if tab == Tab.cpu: CpuTab {
debug-address <=> debug-address;
vertical-stretch: 1;
start-debug => {
start-debug();
Expand Down
2 changes: 1 addition & 1 deletion gui/ui/main/cpu.slint
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ component DebugAddr {

export component CpuTab {
in-out property <float> cpu-count: 8;
in-out property <string> debug-address: "127.0.0.1:1234";
in-out property <string> debug-address;

pure callback start-debug();

Expand Down

0 comments on commit 9cb1d58

Please sign in to comment.