librsvg2-bin,
librust-anyhow-1-dev,
librust-clap-4+derive-dev,
- librust-cursive+crossterm-backend-dev (>= 0.20.0),
+ librust-cursive-0.21+crossterm-backend-dev,
librust-glob-0.3-dev,
librust-hex-0.4-dev,
librust-native-tls-dev,
homepage = "https://www.proxmox.com"
[dependencies]
-cursive = { version = "0.20.0", default-features = false, features = ["crossterm-backend"] }
+cursive = { version = "0.21", default-features = false, features = ["crossterm-backend"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
regex = "1.7"
use cursive::{
event::Event,
- theme::{ColorStyle, Effect, PaletteColor, Style},
+ theme::{ColorStyle, Effect, Effects, PaletteColor, Style},
view::{Nameable, Offset, Resizable, ViewWrapper},
views::{
Button, Checkbox, Dialog, DummyView, EditView, Layer, LinearLayout, PaddedView, Panel,
pub fn new<T: View>(
state: &InstallerState,
view: T,
- next_cb: Box<dyn Fn(&mut Cursive)>,
+ next_cb: Box<dyn Fn(&mut Cursive) + Send + Sync>,
focus_next: bool,
) -> Self {
let mut bbar = LinearLayout::horizontal()
title: &str,
text: &str,
yes_text: &str,
- callback_yes: Box<dyn Fn(&mut Cursive)>,
+ callback_yes: Box<dyn Fn(&mut Cursive) + Send + Sync>,
no_text: &str,
- callback_no: Box<dyn Fn(&mut Cursive)>,
+ callback_no: Box<dyn Fn(&mut Cursive) + Send + Sync>,
) {
siv.add_layer(
Dialog::around(TextView::new(text))
-use std::{cell::RefCell, marker::PhantomData, rc::Rc};
+use std::{
+ marker::PhantomData,
+ sync::{Arc, Mutex},
+};
use cursive::{
view::{Nameable, Resizable, ViewWrapper},
const ZFS_ARC_MIN_SIZE_MIB: usize = 64; // MiB
/// Convenience wrapper when needing to take a (interior-mutable) reference to `BootdiskOptions`.
-/// Interior mutability is safe for this case, as it is completely single-threaded.
-pub type BootdiskOptionsRef = Rc<RefCell<BootdiskOptions>>;
+pub type BootdiskOptionsRef = Arc<Mutex<BootdiskOptions>>;
pub struct BootdiskOptionsView {
view: LinearLayout,
impl BootdiskOptionsView {
pub fn new(siv: &mut Cursive, runinfo: &RuntimeInfo, options: &BootdiskOptions) -> Self {
- let advanced_options = Rc::new(RefCell::new(options.clone()));
+ let advanced_options = Arc::new(Mutex::new(options.clone()));
let bootdisk_form = FormView::new()
.child(
// The simple disk selector, as well as the advanced bootdisk dialog save their
// info on submit directly to the shared `BootdiskOptionsRef` - so just clone() + return
// it.
- let options = (*self.advanced_options).clone().into_inner();
+ let options = self.advanced_options.lock().unwrap().clone();
check_disks_4kn_legacy_boot(self.boot_type, &options.disks)?;
Ok(options)
}
) -> Self {
let filter_btrfs =
|fstype: &&FsType| -> bool { product_conf.enable_btrfs || !fstype.is_btrfs() };
- let options = (*options_ref).borrow();
+ let options = options_ref.lock().unwrap();
let fstype_select = SelectView::new()
.popup()
}
siv.pop_layer();
- *(*options_ref).borrow_mut() = options;
+ *options_ref.lock().unwrap() = options;
}
})
.with_name("advanced-bootdisk-options-dialog")
.with_all(avail_disks.iter().map(|d| (d.to_string(), d.clone())))
.selected(selected_disk_pos)
.on_submit(move |_, disk| {
- options_ref.borrow_mut().disks = vec![disk.clone()];
- options_ref.borrow_mut().advanced =
+ let mut options = options_ref.lock().unwrap();
+ options.disks = vec![disk.clone()];
+ options.advanced =
AdvancedBootdiskOptions::Lvm(LvmBootdiskOptions::defaults_from(disk));
})
}
}
}
- fn show_prompt<W: Write + 'static>(siv: &mut Cursive, text: &str, writer: Arc<Mutex<W>>) {
+ fn show_prompt<W: Write + 'static + Send>(
+ siv: &mut Cursive,
+ text: &str,
+ writer: Arc<Mutex<W>>,
+ ) {
let send_answer = |writer: Arc<Mutex<W>>, answer| {
if let Ok(mut writer) = writer.lock() {
let _ = writeln!(
-use std::{net::IpAddr, rc::Rc, str::FromStr};
+use std::{net::IpAddr, str::FromStr, sync::Arc};
use cursive::{
event::{Event, EventResult},
self.max_value = Some(max);
}
- fn check_bounds(&mut self, original: Rc<String>, result: EventResult) -> EventResult {
+ fn check_bounds(&mut self, original: Arc<String>, result: EventResult) -> EventResult {
// Check if the new value is actually valid according to the max value, if set
if let Some(max) = self.max_value {
if let Ok(val) = self.get_content() {
}
}
-impl<T: 'static + Clone> FormViewGetValue<T> for SelectView<T> {
+impl<T: 'static + Clone + Send + Sync> FormViewGetValue<T> for SelectView<T> {
fn get_value(&self) -> Option<T> {
self.selection().map(|v| (*v).clone())
}
}
}
-impl<T: TableViewItem + 'static> View for TableView<T> {
+impl<T: TableViewItem + 'static + Send + Sync> View for TableView<T> {
fn draw(&self, p: &Printer) {
// Equally split up the columns width, taking into account the scrollbar size and column
// separator.