update `cursive`
`cursive` now requires `Send + Sync` bounds, so I had to switch from `Rc<RefCell<...>>` to `Arc<Mutex<...>>`. I also coalesced some lock calls together, hopefully without introducing any deadlocks. I don't see any calls into the UI that would need the model while these are held, and it seemed fine in a quick test.
This commit is contained in:
parent
f9e3fb56b3
commit
06f942582c
|
@ -200,6 +200,15 @@ version = "1.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
|
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "castaway"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
|
||||||
|
dependencies = [
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.1.14"
|
version = "1.1.14"
|
||||||
|
@ -244,6 +253,20 @@ name = "coded"
|
||||||
version = "0.2.0-pre"
|
version = "0.2.0-pre"
|
||||||
source = "git+https://github.com/scottlamb/coded?rev=2c97994974a73243d5dd12134831814f42cdb0e8#2c97994974a73243d5dd12134831814f42cdb0e8"
|
source = "git+https://github.com/scottlamb/coded?rev=2c97994974a73243d5dd12134831814f42cdb0e8#2c97994974a73243d5dd12134831814f42cdb0e8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "compact_str"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644"
|
||||||
|
dependencies = [
|
||||||
|
"castaway",
|
||||||
|
"cfg-if",
|
||||||
|
"itoa",
|
||||||
|
"rustversion",
|
||||||
|
"ryu",
|
||||||
|
"static_assertions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "constant_time_eq"
|
name = "constant_time_eq"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -330,9 +353,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cursive"
|
name = "cursive"
|
||||||
version = "0.20.0"
|
version = "0.21.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5438eb16bdd8af51b31e74764fef5d0a9260227a5ec82ba75c9d11ce46595839"
|
checksum = "386d5a36020bb856e9a34ecb8a4e6c9bd6b0262d1857bae4db7bc7e2fdaa532e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -348,19 +371,31 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cursive_core"
|
name = "cursive-macros"
|
||||||
version = "0.3.7"
|
version = "0.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4db3b58161228d0dcb45c7968c5e74c3f03ad39e8983e58ad7d57061aa2cd94d"
|
checksum = "ac7ac0eb0cede3dfdfebf4d5f22354e05a730b79c25fd03481fc69fcfba0a73e"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cursive_core"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "321ec774d27fafc66e812034d0025f8858bd7d9095304ff8fc200e0b9f9cc257"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
|
"compact_str",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
|
"cursive-macros",
|
||||||
"enum-map",
|
"enum-map",
|
||||||
"enumset",
|
"enumset",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"num",
|
"num",
|
||||||
"owning_ref",
|
"parking_lot",
|
||||||
|
"serde_json",
|
||||||
"time 0.3.36",
|
"time 0.3.36",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
|
@ -980,6 +1015,17 @@ version = "0.2.158"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.4.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libsqlite3-sys"
|
name = "libsqlite3-sys"
|
||||||
version = "0.30.1"
|
version = "0.30.1"
|
||||||
|
@ -1015,6 +1061,16 @@ version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.22"
|
version = "0.4.22"
|
||||||
|
@ -1399,21 +1455,35 @@ version = "0.1.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "owning_ref"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
|
|
||||||
dependencies = [
|
|
||||||
"stable_deref_trait",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owo-colors"
|
name = "owo-colors"
|
||||||
version = "4.0.0"
|
version = "4.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
|
checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
"parking_lot_core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking_lot_core"
|
||||||
|
version = "0.9.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.5.3",
|
||||||
|
"smallvec",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "password-hash"
|
name = "password-hash"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
@ -1616,13 +1686,22 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.2.16"
|
version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
|
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_syscall"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_termios"
|
name = "redox_termios"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
@ -1802,6 +1881,12 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustversion"
|
||||||
|
version = "1.0.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.18"
|
||||||
|
@ -1826,6 +1911,12 @@ dependencies = [
|
||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scrypt"
|
name = "scrypt"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
@ -1994,6 +2085,12 @@ version = "1.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "static_assertions"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
|
@ -2062,13 +2159,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "termion"
|
name = "termion"
|
||||||
version = "1.5.6"
|
version = "4.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
|
checksum = "1ccce68e518d1173e80876edd54760b60b792750d0cab6444a79101c6ea03848"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
|
"libredox",
|
||||||
"numtoa",
|
"numtoa",
|
||||||
"redox_syscall",
|
|
||||||
"redox_termios",
|
"redox_termios",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ blake3 = "1.0.0"
|
||||||
bpaf = { version = "0.9.1", features = ["autocomplete", "bright-color", "derive"]}
|
bpaf = { version = "0.9.1", features = ["autocomplete", "bright-color", "derive"]}
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
cursive = { version = "0.20.0", default-features = false, features = ["termion-backend"] }
|
cursive = { version = "0.21.1", default-features = false, features = ["termion-backend"] }
|
||||||
db = { package = "moonfire-db", path = "db" }
|
db = { package = "moonfire-db", path = "db" }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
h264-reader = { workspace = true }
|
h264-reader = { workspace = true }
|
||||||
|
|
|
@ -9,11 +9,9 @@ use cursive::view::Scrollable;
|
||||||
use cursive::Cursive;
|
use cursive::Cursive;
|
||||||
use cursive::{views, With};
|
use cursive::{views, With};
|
||||||
use db::writer;
|
use db::writer;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::sync::Arc;
|
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
use super::tab_complete::TabCompleteEditView;
|
use super::tab_complete::TabCompleteEditView;
|
||||||
|
@ -58,10 +56,8 @@ fn update_limits(model: &Model, siv: &mut Cursive) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edit_limit(model: &RefCell<Model>, siv: &mut Cursive, id: i32, content: &str) {
|
fn edit_limit(model: &mut Model, siv: &mut Cursive, id: i32, content: &str) {
|
||||||
debug!("on_edit called for id {}", id);
|
debug!("on_edit called for id {}", id);
|
||||||
let mut model = model.borrow_mut();
|
|
||||||
let model: &mut Model = &mut model;
|
|
||||||
let stream = model.streams.get_mut(&id).unwrap();
|
let stream = model.streams.get_mut(&id).unwrap();
|
||||||
let new_value = decode_size(content).ok();
|
let new_value = decode_size(content).ok();
|
||||||
let delta = new_value.unwrap_or(0) - stream.retain.unwrap_or(0);
|
let delta = new_value.unwrap_or(0) - stream.retain.unwrap_or(0);
|
||||||
|
@ -96,14 +92,12 @@ fn edit_limit(model: &RefCell<Model>, siv: &mut Cursive, id: i32, content: &str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edit_record(model: &RefCell<Model>, id: i32, record: bool) {
|
fn edit_record(model: &mut Model, id: i32, record: bool) {
|
||||||
let mut model = model.borrow_mut();
|
|
||||||
let model: &mut Model = &mut model;
|
|
||||||
let stream = model.streams.get_mut(&id).unwrap();
|
let stream = model.streams.get_mut(&id).unwrap();
|
||||||
stream.record = record;
|
stream.record = record;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_deletion(model: &RefCell<Model>, siv: &mut Cursive, to_delete: i64) {
|
fn confirm_deletion(model: &Mutex<Model>, siv: &mut Cursive, to_delete: i64) {
|
||||||
let typed = siv
|
let typed = siv
|
||||||
.find_name::<views::EditView>("confirm")
|
.find_name::<views::EditView>("confirm")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -124,8 +118,8 @@ fn confirm_deletion(model: &RefCell<Model>, siv: &mut Cursive, to_delete: i64) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn actually_delete(model: &RefCell<Model>, siv: &mut Cursive) {
|
fn actually_delete(model: &Mutex<Model>, siv: &mut Cursive) {
|
||||||
let model = &*model.borrow();
|
let model = model.lock().unwrap();
|
||||||
let new_limits: Vec<_> = model
|
let new_limits: Vec<_> = model
|
||||||
.streams
|
.streams
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -147,20 +141,21 @@ fn actually_delete(model: &RefCell<Model>, siv: &mut Cursive) {
|
||||||
.dismiss_button("Abort"),
|
.dismiss_button("Abort"),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
update_limits(model, siv);
|
update_limits(&model, siv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn press_change(model: &Rc<RefCell<Model>>, siv: &mut Cursive) {
|
fn press_change(model: &Arc<Mutex<Model>>, siv: &mut Cursive) {
|
||||||
if model.borrow().errors > 0 {
|
let to_delete = {
|
||||||
return;
|
let l = model.lock().unwrap();
|
||||||
}
|
if l.errors > 0 {
|
||||||
let to_delete = model
|
return;
|
||||||
.borrow()
|
}
|
||||||
.streams
|
l.streams
|
||||||
.values()
|
.values()
|
||||||
.map(|s| ::std::cmp::max(s.used - s.retain.unwrap(), 0))
|
.map(|s| ::std::cmp::max(s.used - s.retain.unwrap(), 0))
|
||||||
.sum();
|
.sum()
|
||||||
|
};
|
||||||
debug!("change press, to_delete={}", to_delete);
|
debug!("change press, to_delete={}", to_delete);
|
||||||
if to_delete > 0 {
|
if to_delete > 0 {
|
||||||
let prompt = format!(
|
let prompt = format!(
|
||||||
|
@ -190,7 +185,7 @@ fn press_change(model: &Rc<RefCell<Model>>, siv: &mut Cursive) {
|
||||||
siv.add_layer(dialog);
|
siv.add_layer(dialog);
|
||||||
} else {
|
} else {
|
||||||
siv.pop_layer();
|
siv.pop_layer();
|
||||||
update_limits(&model.borrow(), siv);
|
update_limits(&model.lock().unwrap(), siv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +362,7 @@ fn edit_dir_dialog(db: &Arc<db::Database>, siv: &mut Cursive, dir_id: i32) {
|
||||||
fs_capacity = stat.block_size() as i64 * stat.blocks_available() as i64 + total_used;
|
fs_capacity = stat.block_size() as i64 * stat.blocks_available() as i64 + total_used;
|
||||||
path = dir.path.clone();
|
path = dir.path.clone();
|
||||||
}
|
}
|
||||||
Rc::new(RefCell::new(Model {
|
Arc::new(Mutex::new(Model {
|
||||||
dir_id,
|
dir_id,
|
||||||
db: db.clone(),
|
db: db.clone(),
|
||||||
fs_capacity,
|
fs_capacity,
|
||||||
|
@ -389,12 +384,13 @@ fn edit_dir_dialog(db: &Arc<db::Database>, siv: &mut Cursive, dir_id: i32) {
|
||||||
.child(views::TextView::new("usage").fixed_width(BYTES_WIDTH))
|
.child(views::TextView::new("usage").fixed_width(BYTES_WIDTH))
|
||||||
.child(views::TextView::new("limit").fixed_width(BYTES_WIDTH)),
|
.child(views::TextView::new("limit").fixed_width(BYTES_WIDTH)),
|
||||||
);
|
);
|
||||||
for (&id, stream) in &model.borrow().streams {
|
let l = model.lock().unwrap();
|
||||||
|
for (&id, stream) in &l.streams {
|
||||||
let mut record_cb = views::Checkbox::new();
|
let mut record_cb = views::Checkbox::new();
|
||||||
record_cb.set_checked(stream.record);
|
record_cb.set_checked(stream.record);
|
||||||
record_cb.set_on_change({
|
record_cb.set_on_change({
|
||||||
let model = model.clone();
|
let model = model.clone();
|
||||||
move |_siv, record| edit_record(&model, id, record)
|
move |_siv, record| edit_record(&mut model.lock().unwrap(), id, record)
|
||||||
});
|
});
|
||||||
list.add_child(
|
list.add_child(
|
||||||
&stream.label,
|
&stream.label,
|
||||||
|
@ -406,7 +402,9 @@ fn edit_dir_dialog(db: &Arc<db::Database>, siv: &mut Cursive, dir_id: i32) {
|
||||||
.content(encode_size(stream.retain.unwrap()))
|
.content(encode_size(stream.retain.unwrap()))
|
||||||
.on_edit({
|
.on_edit({
|
||||||
let model = model.clone();
|
let model = model.clone();
|
||||||
move |siv, content, _pos| edit_limit(&model, siv, id, content)
|
move |siv, content, _pos| {
|
||||||
|
edit_limit(&mut model.lock().unwrap(), siv, id, content)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.on_submit({
|
.on_submit({
|
||||||
let model = model.clone();
|
let model = model.clone();
|
||||||
|
@ -421,17 +419,14 @@ fn edit_dir_dialog(db: &Arc<db::Database>, siv: &mut Cursive, dir_id: i32) {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let over = model.borrow().total_retain > model.borrow().fs_capacity;
|
let over = l.total_retain > l.fs_capacity;
|
||||||
list.add_child(
|
list.add_child(
|
||||||
"total",
|
"total",
|
||||||
views::LinearLayout::horizontal()
|
views::LinearLayout::horizontal()
|
||||||
.child(views::DummyView {}.fixed_width(RECORD_WIDTH))
|
.child(views::DummyView {}.fixed_width(RECORD_WIDTH))
|
||||||
|
.child(views::TextView::new(encode_size(l.total_used)).fixed_width(BYTES_WIDTH))
|
||||||
.child(
|
.child(
|
||||||
views::TextView::new(encode_size(model.borrow().total_used))
|
views::TextView::new(encode_size(l.total_retain))
|
||||||
.fixed_width(BYTES_WIDTH),
|
|
||||||
)
|
|
||||||
.child(
|
|
||||||
views::TextView::new(encode_size(model.borrow().total_retain))
|
|
||||||
.with_name("total_retain")
|
.with_name("total_retain")
|
||||||
.fixed_width(BYTES_WIDTH),
|
.fixed_width(BYTES_WIDTH),
|
||||||
)
|
)
|
||||||
|
@ -442,11 +437,9 @@ fn edit_dir_dialog(db: &Arc<db::Database>, siv: &mut Cursive, dir_id: i32) {
|
||||||
views::LinearLayout::horizontal()
|
views::LinearLayout::horizontal()
|
||||||
.child(views::DummyView {}.fixed_width(RECORD_WIDTH))
|
.child(views::DummyView {}.fixed_width(RECORD_WIDTH))
|
||||||
.child(views::DummyView {}.fixed_width(BYTES_WIDTH))
|
.child(views::DummyView {}.fixed_width(BYTES_WIDTH))
|
||||||
.child(
|
.child(views::TextView::new(encode_size(l.fs_capacity)).fixed_width(BYTES_WIDTH)),
|
||||||
views::TextView::new(encode_size(model.borrow().fs_capacity))
|
|
||||||
.fixed_width(BYTES_WIDTH),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
drop(l);
|
||||||
let mut change_button = views::Button::new("Change", move |siv| press_change(&model, siv));
|
let mut change_button = views::Button::new("Change", move |siv| press_change(&model, siv));
|
||||||
change_button.set_enabled(!over);
|
change_button.set_enabled(!over);
|
||||||
let mut buttons = views::LinearLayout::horizontal().child(views::DummyView.full_width());
|
let mut buttons = views::LinearLayout::horizontal().child(views::DummyView.full_width());
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
// Copyright (C) 2020 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
// Copyright (C) 2020 The Moonfire NVR Authors; see AUTHORS and LICENSE.txt.
|
||||||
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
// SPDX-License-Identifier: GPL-v3.0-or-later WITH GPL-3.0-linking-exception.
|
||||||
|
|
||||||
use std::{cell::RefCell, rc::Rc};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use cursive::{
|
use cursive::{
|
||||||
direction::Direction,
|
direction::Direction,
|
||||||
|
@ -13,46 +13,49 @@ use cursive::{
|
||||||
Printer, Rect, Vec2, View, With,
|
Printer, Rect, Vec2, View, With,
|
||||||
};
|
};
|
||||||
|
|
||||||
type TabCompleteFn = Rc<dyn Fn(&str) -> Vec<String>>;
|
type TabCompleteFn = Arc<dyn Fn(&str) -> Vec<String> + Send + Sync>;
|
||||||
|
|
||||||
pub struct TabCompleteEditView {
|
pub struct TabCompleteEditView {
|
||||||
edit_view: Rc<RefCell<EditView>>,
|
edit_view: Arc<Mutex<EditView>>,
|
||||||
tab_completer: Option<TabCompleteFn>,
|
tab_completer: Option<TabCompleteFn>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TabCompleteEditView {
|
impl TabCompleteEditView {
|
||||||
pub fn new(edit_view: EditView) -> Self {
|
pub fn new(edit_view: EditView) -> Self {
|
||||||
Self {
|
Self {
|
||||||
edit_view: Rc::new(RefCell::new(edit_view)),
|
edit_view: Arc::new(Mutex::new(edit_view)),
|
||||||
tab_completer: None,
|
tab_completer: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_tab_complete(mut self, handler: impl Fn(&str) -> Vec<String> + 'static) -> Self {
|
pub fn on_tab_complete(
|
||||||
self.tab_completer = Some(Rc::new(handler));
|
mut self,
|
||||||
|
handler: impl Fn(&str) -> Vec<String> + Send + Sync + 'static,
|
||||||
|
) -> Self {
|
||||||
|
self.tab_completer = Some(Arc::new(handler));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_content(&self) -> Rc<String> {
|
pub fn get_content(&self) -> Arc<String> {
|
||||||
self.edit_view.borrow_mut().get_content()
|
self.edit_view.lock().unwrap().get_content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl View for TabCompleteEditView {
|
impl View for TabCompleteEditView {
|
||||||
fn draw(&self, printer: &Printer) {
|
fn draw(&self, printer: &Printer) {
|
||||||
self.edit_view.borrow().draw(printer)
|
self.edit_view.lock().unwrap().draw(printer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout(&mut self, size: Vec2) {
|
fn layout(&mut self, size: Vec2) {
|
||||||
self.edit_view.borrow_mut().layout(size)
|
self.edit_view.lock().unwrap().layout(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_focus(&mut self, source: Direction) -> Result<EventResult, CannotFocus> {
|
fn take_focus(&mut self, source: Direction) -> Result<EventResult, CannotFocus> {
|
||||||
self.edit_view.borrow_mut().take_focus(source)
|
self.edit_view.lock().unwrap().take_focus(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_event(&mut self, event: Event) -> EventResult {
|
fn on_event(&mut self, event: Event) -> EventResult {
|
||||||
if !self.edit_view.borrow().is_enabled() {
|
if !self.edit_view.lock().unwrap().is_enabled() {
|
||||||
return EventResult::Ignored;
|
return EventResult::Ignored;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,32 +66,32 @@ impl View for TabCompleteEditView {
|
||||||
EventResult::consumed()
|
EventResult::consumed()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.edit_view.borrow_mut().on_event(event)
|
self.edit_view.lock().unwrap().on_event(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn important_area(&self, view_size: Vec2) -> Rect {
|
fn important_area(&self, view_size: Vec2) -> Rect {
|
||||||
self.edit_view.borrow().important_area(view_size)
|
self.edit_view.lock().unwrap().important_area(view_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tab_complete(
|
fn tab_complete(
|
||||||
edit_view: Rc<RefCell<EditView>>,
|
edit_view: Arc<Mutex<EditView>>,
|
||||||
tab_completer: TabCompleteFn,
|
tab_completer: TabCompleteFn,
|
||||||
autofill_one: bool,
|
autofill_one: bool,
|
||||||
) -> EventResult {
|
) -> EventResult {
|
||||||
let completions = tab_completer(edit_view.borrow().get_content().as_str());
|
let completions = tab_completer(edit_view.lock().unwrap().get_content().as_str());
|
||||||
EventResult::with_cb_once(move |siv| match *completions {
|
EventResult::with_cb_once(move |siv| match *completions {
|
||||||
[] => {}
|
[] => {}
|
||||||
[ref completion] if autofill_one => edit_view.borrow_mut().set_content(completion)(siv),
|
[ref completion] if autofill_one => edit_view.lock().unwrap().set_content(completion)(siv),
|
||||||
[..] => {
|
[..] => {
|
||||||
siv.add_layer(TabCompletePopup {
|
siv.add_layer(TabCompletePopup {
|
||||||
popup: views::MenuPopup::new(Rc::new({
|
popup: views::MenuPopup::new(Arc::new({
|
||||||
menu::Tree::new().with(|tree| {
|
menu::Tree::new().with(|tree| {
|
||||||
for completion in completions {
|
for completion in completions {
|
||||||
let edit_view = edit_view.clone();
|
let edit_view = edit_view.clone();
|
||||||
tree.add_leaf(completion.clone(), move |siv| {
|
tree.add_leaf(completion.clone(), move |siv| {
|
||||||
edit_view.borrow_mut().set_content(&completion)(siv)
|
edit_view.lock().unwrap().set_content(&completion)(siv)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -101,7 +104,7 @@ fn tab_complete(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TabCompletePopup {
|
struct TabCompletePopup {
|
||||||
edit_view: Rc<RefCell<EditView>>,
|
edit_view: Arc<Mutex<EditView>>,
|
||||||
popup: MenuPopup,
|
popup: MenuPopup,
|
||||||
tab_completer: TabCompleteFn,
|
tab_completer: TabCompleteFn,
|
||||||
}
|
}
|
||||||
|
@ -111,7 +114,7 @@ impl TabCompletePopup {
|
||||||
let tab_completer = self.tab_completer.clone();
|
let tab_completer = self.tab_completer.clone();
|
||||||
EventResult::with_cb_once(move |s| {
|
EventResult::with_cb_once(move |s| {
|
||||||
s.pop_layer();
|
s.pop_layer();
|
||||||
edit_view.borrow_mut().on_event(event).process(s);
|
edit_view.lock().unwrap().on_event(event).process(s);
|
||||||
tab_complete(edit_view, tab_completer, false).process(s);
|
tab_complete(edit_view, tab_completer, false).process(s);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,7 +189,7 @@ fn edit_user_dialog(db: &Arc<db::Database>, siv: &mut Cursive, item: Option<i32>
|
||||||
] {
|
] {
|
||||||
let mut checkbox = views::Checkbox::new();
|
let mut checkbox = views::Checkbox::new();
|
||||||
checkbox.set_checked(*b);
|
checkbox.set_checked(*b);
|
||||||
perms.add_child(name, checkbox.with_name(format!("perm_{name}")));
|
perms.add_child(*name, checkbox.with_name(format!("perm_{name}")));
|
||||||
}
|
}
|
||||||
layout.add_child(perms);
|
layout.add_child(perms);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue