mirror of
https://gitlab.com/gabmus/envision.git
synced 2025-04-22 04:24:50 +00:00
feat: runner status communicates exit code; build window shows color coded build status
This commit is contained in:
parent
47d7a7a629
commit
234f499d2f
4 changed files with 116 additions and 27 deletions
|
@ -30,7 +30,7 @@ pub struct Runner {
|
|||
#[derive(PartialEq, Eq, Debug)]
|
||||
pub enum RunnerStatus {
|
||||
Running,
|
||||
Stopped,
|
||||
Stopped(Option<i32>),
|
||||
}
|
||||
|
||||
macro_rules! logger_thread {
|
||||
|
@ -154,10 +154,10 @@ impl Runner {
|
|||
|
||||
pub fn status(&mut self) -> RunnerStatus {
|
||||
match &mut self.process {
|
||||
None => RunnerStatus::Stopped,
|
||||
None => RunnerStatus::Stopped(None),
|
||||
Some(proc) => match proc.try_wait() {
|
||||
Err(_) => RunnerStatus::Running,
|
||||
Ok(Some(_)) => RunnerStatus::Stopped,
|
||||
Ok(Some(code)) => RunnerStatus::Stopped(code.code()),
|
||||
Ok(None) => RunnerStatus::Running,
|
||||
},
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ mod tests {
|
|||
runner.start();
|
||||
sleep(time::Duration::from_millis(10));
|
||||
runner.terminate();
|
||||
assert_eq!(runner.status(), RunnerStatus::Stopped);
|
||||
assert_eq!(runner.status(), RunnerStatus::Stopped(Some(0)));
|
||||
let out = runner.consume_output();
|
||||
assert_eq!(out, "REX2TEST: Lorem ipsum dolor\n");
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ use crate::runner::{Runner, RunnerStatus};
|
|||
pub struct RunnerPipeline {
|
||||
runners: Vec<RefCell<Runner>>,
|
||||
current_index: usize,
|
||||
last_exit_status: Option<i32>,
|
||||
has_started: bool,
|
||||
pub log: Vec<String>,
|
||||
}
|
||||
|
@ -19,6 +20,7 @@ impl RunnerPipeline {
|
|||
runners: c_runners,
|
||||
current_index: 0,
|
||||
has_started: false,
|
||||
last_exit_status: None,
|
||||
log: vec![],
|
||||
}
|
||||
}
|
||||
|
@ -55,12 +57,23 @@ impl RunnerPipeline {
|
|||
self.log.extend(log);
|
||||
match status {
|
||||
RunnerStatus::Running => {},
|
||||
RunnerStatus::Stopped => {
|
||||
self.current_index += 1;
|
||||
match self.get_current_runner() {
|
||||
None => {},
|
||||
Some(c_runner) => {
|
||||
c_runner.borrow_mut().start();
|
||||
RunnerStatus::Stopped(ecode) => {
|
||||
match ecode {
|
||||
None => {} // should never get here
|
||||
Some(0) => {
|
||||
self.last_exit_status = Some(0);
|
||||
self.current_index += 1;
|
||||
match self.get_current_runner() {
|
||||
None => {},
|
||||
Some(c_runner) => {
|
||||
c_runner.borrow_mut().start();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(nonzero) => {
|
||||
self.last_exit_status = Some(nonzero);
|
||||
// interrupting pipeline by going past last runner
|
||||
self.current_index = self.runners.len();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,7 +86,10 @@ impl RunnerPipeline {
|
|||
self.log.concat()
|
||||
}
|
||||
|
||||
pub fn is_running(&self) -> bool {
|
||||
self.get_current_runner().is_some()
|
||||
pub fn status(&self) -> RunnerStatus {
|
||||
match self.get_current_runner() {
|
||||
None => RunnerStatus::Stopped(self.last_exit_status),
|
||||
Some(_) => RunnerStatus::Running
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::about_dialog::AboutDialog;
|
||||
use super::build_window::BuildWindow;
|
||||
use super::build_window::{BuildStatus, BuildWindow};
|
||||
use super::debug_view::{DebugView, DebugViewMsg};
|
||||
use super::libsurvive_setup_window::LibsurviveSetupWindow;
|
||||
use super::main_view::MainViewMsg;
|
||||
|
@ -161,7 +161,7 @@ impl SimpleComponent for App {
|
|||
}
|
||||
match runner.status() {
|
||||
RunnerStatus::Running => {}
|
||||
RunnerStatus::Stopped => {
|
||||
RunnerStatus::Stopped(_) => {
|
||||
self.main_view
|
||||
.sender()
|
||||
.emit(MainViewMsg::MonadoActiveChanged(false));
|
||||
|
@ -176,12 +176,30 @@ impl SimpleComponent for App {
|
|||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateContent(pipeline.get_log()));
|
||||
if !pipeline.is_running() {
|
||||
self.setcap_confirm_dialog.present();
|
||||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateCanClose(true));
|
||||
self.build_pipeline.take();
|
||||
match pipeline.status() {
|
||||
RunnerStatus::Running | RunnerStatus::Stopped(None) => {}
|
||||
RunnerStatus::Stopped(Some(code)) => {
|
||||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateCanClose(true));
|
||||
self.build_pipeline.take();
|
||||
match code {
|
||||
0 => {
|
||||
self.build_window.sender().emit(
|
||||
BuildWindowMsg::UpdateBuildStatus(BuildStatus::Done)
|
||||
);
|
||||
self.setcap_confirm_dialog.present();
|
||||
self.build_window
|
||||
.sender()
|
||||
.emit(BuildWindowMsg::UpdateCanClose(true));
|
||||
}
|
||||
errcode => self.build_window.sender().emit(
|
||||
BuildWindowMsg::UpdateBuildStatus(BuildStatus::Error(
|
||||
format!("Exit status {}", errcode),
|
||||
)),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -219,7 +237,7 @@ impl SimpleComponent for App {
|
|||
.sender()
|
||||
.emit(MainViewMsg::MonadoActiveChanged(false));
|
||||
}
|
||||
RunnerStatus::Stopped => {
|
||||
RunnerStatus::Stopped(_) => {
|
||||
self.debug_view
|
||||
.sender()
|
||||
.emit(DebugViewMsg::LogUpdated(vec![]));
|
||||
|
@ -301,7 +319,8 @@ impl SimpleComponent for App {
|
|||
.sender()
|
||||
.send(LibsurviveSetupMsg::Present(
|
||||
self.get_selected_profile().clone(),
|
||||
));
|
||||
))
|
||||
.expect_dialog("Failed to present Libsurvive Setup Window");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,27 @@
|
|||
use gtk::prelude::*;
|
||||
use relm4::prelude::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
pub enum BuildStatus {
|
||||
Building,
|
||||
Done,
|
||||
Error(String),
|
||||
}
|
||||
|
||||
#[tracker::track]
|
||||
pub struct BuildWindow {
|
||||
title: String,
|
||||
content: String,
|
||||
can_close: bool,
|
||||
build_status: BuildStatus,
|
||||
|
||||
#[tracker::do_not_track]
|
||||
pub textbuf: gtk::TextBuffer,
|
||||
#[tracker::do_not_track]
|
||||
pub win: Option<adw::Window>,
|
||||
#[tracker::do_not_track]
|
||||
build_status_label: Option<gtk::Label>,
|
||||
#[tracker::do_not_track]
|
||||
pub scrolled_win: Option<gtk::ScrolledWindow>,
|
||||
}
|
||||
|
||||
|
@ -19,6 +29,7 @@ pub struct BuildWindow {
|
|||
pub enum BuildWindowMsg {
|
||||
Present,
|
||||
UpdateTitle(String),
|
||||
UpdateBuildStatus(BuildStatus),
|
||||
UpdateContent(String),
|
||||
UpdateCanClose(bool),
|
||||
}
|
||||
|
@ -34,10 +45,12 @@ impl SimpleComponent for BuildWindow {
|
|||
adw::Window {
|
||||
set_modal: true,
|
||||
set_default_size: (520, 400),
|
||||
set_hide_on_close: true,
|
||||
gtk::Box {
|
||||
set_vexpand: true,
|
||||
set_hexpand: true,
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_spacing: 12,
|
||||
gtk::WindowHandle {
|
||||
set_vexpand: false,
|
||||
set_hexpand: true,
|
||||
|
@ -48,11 +61,32 @@ impl SimpleComponent for BuildWindow {
|
|||
#[wrap(Some)]
|
||||
set_title_widget: title_label = >k::Label {
|
||||
#[track = "model.changed(BuildWindow::title())"]
|
||||
set_label: &model.title,
|
||||
set_markup: &model.title,
|
||||
add_css_class: "title",
|
||||
},
|
||||
}
|
||||
},
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_hexpand: true,
|
||||
set_halign: gtk::Align::Center,
|
||||
set_spacing: 12,
|
||||
#[name(build_status_label)]
|
||||
gtk::Label {
|
||||
#[track = "model.changed(BuildWindow::build_status())"]
|
||||
set_markup: match &model.build_status {
|
||||
BuildStatus::Building => "Build in progress...".to_string(),
|
||||
BuildStatus::Done => "Build done, you can close this window".to_string(),
|
||||
BuildStatus::Error(code) => {
|
||||
format!("Build failed: \"{c}\"", c = code)
|
||||
}
|
||||
}.as_str(),
|
||||
add_css_class: "title-2",
|
||||
set_wrap: true,
|
||||
set_wrap_mode: gtk::pango::WrapMode::Word,
|
||||
set_justify: gtk::Justification::Center,
|
||||
}
|
||||
},
|
||||
#[name(scrolled_win)]
|
||||
gtk::ScrolledWindow {
|
||||
set_hexpand: true,
|
||||
|
@ -65,6 +99,10 @@ impl SimpleComponent for BuildWindow {
|
|||
set_vexpand: true,
|
||||
set_editable: false,
|
||||
set_monospace: true,
|
||||
set_left_margin: 6,
|
||||
set_right_margin: 6,
|
||||
set_top_margin: 6,
|
||||
set_bottom_margin: 6,
|
||||
set_buffer: Some(&model.textbuf),
|
||||
},
|
||||
},
|
||||
|
@ -76,7 +114,8 @@ impl SimpleComponent for BuildWindow {
|
|||
#[track = "model.changed(BuildWindow::can_close())"]
|
||||
set_sensitive: model.can_close,
|
||||
connect_clicked[win] => move |_| {
|
||||
win.hide();
|
||||
|
||||
win.close();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -89,10 +128,11 @@ impl SimpleComponent for BuildWindow {
|
|||
match message {
|
||||
BuildWindowMsg::Present => {
|
||||
self.win.as_ref().unwrap().present();
|
||||
},
|
||||
sender.input(BuildWindowMsg::UpdateBuildStatus(BuildStatus::Building));
|
||||
}
|
||||
BuildWindowMsg::UpdateTitle(t) => {
|
||||
self.set_title(t);
|
||||
},
|
||||
}
|
||||
BuildWindowMsg::UpdateContent(c) => {
|
||||
if self.content != c {
|
||||
self.set_content(c);
|
||||
|
@ -103,7 +143,18 @@ impl SimpleComponent for BuildWindow {
|
|||
adj.set_value(adj.upper());
|
||||
sw.set_vadjustment(Some(&adj));
|
||||
}
|
||||
},
|
||||
}
|
||||
BuildWindowMsg::UpdateBuildStatus(status) => {
|
||||
let label = self.build_status_label.as_ref().unwrap();
|
||||
label.remove_css_class("success");
|
||||
label.remove_css_class("error");
|
||||
match status {
|
||||
BuildStatus::Done => label.add_css_class("success"),
|
||||
BuildStatus::Error(_) => label.add_css_class("error"),
|
||||
_ => {}
|
||||
}
|
||||
self.set_build_status(status);
|
||||
}
|
||||
BuildWindowMsg::UpdateCanClose(val) => {
|
||||
self.set_can_close(val);
|
||||
}
|
||||
|
@ -121,12 +172,15 @@ impl SimpleComponent for BuildWindow {
|
|||
content: "".into(),
|
||||
can_close: false,
|
||||
textbuf: gtk::TextBuffer::builder().build(),
|
||||
build_status: BuildStatus::Building,
|
||||
win: None,
|
||||
build_status_label: None,
|
||||
scrolled_win: None,
|
||||
};
|
||||
let widgets = view_output!();
|
||||
model.scrolled_win = Some(widgets.scrolled_win.clone());
|
||||
model.win = Some(widgets.win.clone());
|
||||
model.build_status_label = Some(widgets.build_status_label.clone());
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue