Add per-VM action buttons in VM list
This commit is contained in:
174
src/gui.rs
174
src/gui.rs
@@ -316,103 +316,93 @@ impl eframe::App for App {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 虚拟机列表(只读)
|
// 虚拟机列表(每行带操作按钮)
|
||||||
ui.label("虚拟机列表:");
|
ui.label("虚拟机列表:");
|
||||||
egui::ScrollArea::vertical().max_height(120.0).stick_to_bottom(true).show(ui, |ui| {
|
let vms_list = st.vms.clone();
|
||||||
let vm_count = st.vms.len();
|
let client_ref = st.client.clone();
|
||||||
ui.label(format!("共 {} 台虚拟机 (点击选择)", vm_count));
|
let node_ref = st.node.clone();
|
||||||
|
egui::ScrollArea::vertical().max_height(180.0).stick_to_bottom(true).show(ui, |ui| {
|
||||||
|
let vm_count = vms_list.len();
|
||||||
|
ui.label(format!("共 {} 台虚拟机", vm_count));
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
for (idx, (id, name)) in st.vms.iter().enumerate() {
|
for (_, (id, name)) in vms_list.iter().enumerate() {
|
||||||
let is_selected = st.vm_id == *id;
|
ui.horizontal(|ui| {
|
||||||
let label = if is_selected {
|
ui.label(format!("{} ({})", name, id));
|
||||||
format!("● {} ({}) - 已选择", name, id)
|
ui.add_space(10.0);
|
||||||
} else {
|
|
||||||
format!("○ {} ({})", name, id)
|
let client = client_ref.clone();
|
||||||
};
|
let node = node_ref.clone();
|
||||||
if is_selected {
|
let vm_id = *id;
|
||||||
ui.colored_label(egui::Color32::LIGHT_BLUE, label);
|
let state_clone = state.clone();
|
||||||
} else {
|
|
||||||
ui.label(label);
|
if ui.button("▶").clicked() {
|
||||||
}
|
state_clone.write().unwrap().add_log(&format!("启动 VM {}...", vm_id));
|
||||||
|
ctx.request_repaint();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
rt.block_on(async {
|
||||||
|
let client = client.lock().unwrap();
|
||||||
|
if let Some(c) = client.as_ref() {
|
||||||
|
match c.start_vm(&node, vm_id).await {
|
||||||
|
Ok(_) => state_clone.write().unwrap().add_log("✓ 启动成功"),
|
||||||
|
Err(e) => state_clone.write().unwrap().add_log(&format!("✗ {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let client2 = client_ref.clone();
|
||||||
|
let node2 = node_ref.clone();
|
||||||
|
let vm_id2 = *id;
|
||||||
|
let state2 = state.clone();
|
||||||
|
if ui.button("■").clicked() {
|
||||||
|
state2.write().unwrap().add_log(&format!("停止 VM {}...", vm_id2));
|
||||||
|
ctx.request_repaint();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
rt.block_on(async {
|
||||||
|
let client = client2.lock().unwrap();
|
||||||
|
if let Some(c) = client.as_ref() {
|
||||||
|
match c.stop_vm(&node2, vm_id2).await {
|
||||||
|
Ok(_) => state2.write().unwrap().add_log("✓ 停止成功"),
|
||||||
|
Err(e) => state2.write().unwrap().add_log(&format!("✗ {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let client3 = client_ref.clone();
|
||||||
|
let node3 = node_ref.clone();
|
||||||
|
let vm_id3 = *id;
|
||||||
|
let state3 = state.clone();
|
||||||
|
if ui.button("↻").clicked() {
|
||||||
|
state3.write().unwrap().add_log(&format!("重启 VM {}...", vm_id3));
|
||||||
|
ctx.request_repaint();
|
||||||
|
thread::spawn(move || {
|
||||||
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
rt.block_on(async {
|
||||||
|
let client = client3.lock().unwrap();
|
||||||
|
if let Some(c) = client.as_ref() {
|
||||||
|
match c.stop_vm(&node3, vm_id3).await {
|
||||||
|
Ok(_) => {
|
||||||
|
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
|
||||||
|
match c.start_vm(&node3, vm_id3).await {
|
||||||
|
Ok(_) => state3.write().unwrap().add_log("✓ 重启成功"),
|
||||||
|
Err(e) => state3.write().unwrap().add_log(&format!("✗ {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => state3.write().unwrap().add_log(&format!("✗ {}", e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 选择VM后显示操作按钮
|
|
||||||
if !st.vms.is_empty() {
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label("选中 VM 操作:");
|
|
||||||
let client = st.client.clone();
|
|
||||||
let node = st.node.clone();
|
|
||||||
let vm_id = st.vm_id;
|
|
||||||
let state_clone = state.clone();
|
|
||||||
|
|
||||||
if ui.button("▶ 启动").clicked() {
|
|
||||||
st.add_log(&format!("启动 VM {}...", vm_id));
|
|
||||||
ctx.request_repaint();
|
|
||||||
thread::spawn(move || {
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
rt.block_on(async {
|
|
||||||
let client = client.lock().unwrap();
|
|
||||||
if let Some(c) = client.as_ref() {
|
|
||||||
match c.start_vm(&node, vm_id).await {
|
|
||||||
Ok(_) => state_clone.write().unwrap().add_log("✓ 启动成功"),
|
|
||||||
Err(e) => state_clone.write().unwrap().add_log(&format!("✗ {}", e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let client2 = st.client.clone();
|
|
||||||
let node2 = st.node.clone();
|
|
||||||
let vm_id2 = st.vm_id;
|
|
||||||
let state2 = state.clone();
|
|
||||||
if ui.button("■ 停止").clicked() {
|
|
||||||
st.add_log(&format!("停止 VM {}...", vm_id2));
|
|
||||||
ctx.request_repaint();
|
|
||||||
thread::spawn(move || {
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
rt.block_on(async {
|
|
||||||
let client = client2.lock().unwrap();
|
|
||||||
if let Some(c) = client.as_ref() {
|
|
||||||
match c.stop_vm(&node2, vm_id2).await {
|
|
||||||
Ok(_) => state2.write().unwrap().add_log("✓ 停止成功"),
|
|
||||||
Err(e) => state2.write().unwrap().add_log(&format!("✗ {}", e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let client3 = st.client.clone();
|
|
||||||
let node3 = st.node.clone();
|
|
||||||
let vm_id3 = st.vm_id;
|
|
||||||
let state3 = state.clone();
|
|
||||||
if ui.button("↻ 重启").clicked() {
|
|
||||||
st.add_log(&format!("重启 VM {}...", vm_id3));
|
|
||||||
ctx.request_repaint();
|
|
||||||
thread::spawn(move || {
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
|
||||||
rt.block_on(async {
|
|
||||||
let client = client3.lock().unwrap();
|
|
||||||
if let Some(c) = client.as_ref() {
|
|
||||||
match c.stop_vm(&node3, vm_id3).await {
|
|
||||||
Ok(_) => {
|
|
||||||
tokio::time::sleep(tokio::time::Duration::from_secs(3)).await;
|
|
||||||
match c.start_vm(&node3, vm_id3).await {
|
|
||||||
Ok(_) => state3.write().unwrap().add_log("✓ 重启成功"),
|
|
||||||
Err(e) => state3.write().unwrap().add_log(&format!("✗ {}", e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => state3.write().unwrap().add_log(&format!("✗ {}", e)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user