Add "Copy config" option to "Add camera" dialog

This commit is contained in:
Skye 2023-07-01 13:47:37 -04:00 committed by Scott Lamb
parent 1fde947f36
commit 81ea7d8a87

View File

@ -5,7 +5,7 @@
use crate::stream::{self, Opener};
use base::strutil::{decode_size, encode_size};
use cursive::traits::{Finder, Nameable, Resizable, Scrollable};
use cursive::views::{self, ViewRef};
use cursive::views::{self, Dialog, ViewRef};
use cursive::Cursive;
use db::writer;
use failure::{bail, format_err, Error, ResultExt};
@ -434,32 +434,12 @@ fn edit_stream_url(type_: db::StreamType, content: &str, mut test_button: ViewRe
test_button.set_enabled(enable_test);
}
/// Adds or updates a camera.
/// (The former if `item` is None; the latter otherwise.)
fn edit_camera_dialog(db: &Arc<db::Database>, siv: &mut Cursive, item: &Option<i32>) {
let camera_list = views::ListView::new()
.child(
"id",
views::TextView::new(item.map_or_else(|| "<new>".to_string(), |id| id.to_string())),
)
.child("uuid", views::TextView::new("<new>").with_name("uuid"))
.child("short name", views::EditView::new().with_name("short_name"))
.child(
"onvif_base_url",
views::EditView::new().with_name("onvif_base_url"),
)
.child("username", views::EditView::new().with_name("username"))
.child("password", views::EditView::new().with_name("password"))
.min_height(6);
let mut layout = views::LinearLayout::vertical()
.child(camera_list)
.child(views::TextView::new("description"))
.child(
views::TextArea::new()
.with_name("description")
.min_height(3),
);
fn load_camera_values(
db: &Arc<db::Database>,
camera_id: i32,
dialog: &mut Dialog,
overwrite_uuid: bool,
) -> (String, i64) {
let dirs: Vec<_> = ::std::iter::once(("<none>".into(), None))
.chain(
db.lock()
@ -468,70 +448,15 @@ fn edit_camera_dialog(db: &Arc<db::Database>, siv: &mut Cursive, item: &Option<i
.map(|(&id, d)| (d.path.to_owned(), Some(id))),
)
.collect();
for &type_ in &db::ALL_STREAM_TYPES {
let list = views::ListView::new()
.child(
"rtsp url",
views::LinearLayout::horizontal()
.child(
views::EditView::new()
.on_edit(move |siv, content, _pos| {
let test_button = siv
.find_name::<views::Button>(&format!("{}_test", type_))
.unwrap();
edit_stream_url(type_, content, test_button);
})
.with_name(format!("{}_url", type_))
.full_width(),
)
.child(views::DummyView)
.child(
views::Button::new("Test", move |siv| press_test(siv, type_))
.disabled()
.with_name(format!("{}_test", type_)),
),
)
.child(
"sample file dir",
views::SelectView::<Option<i32>>::new()
.with_all(dirs.iter().map(|(p, id)| (p.display().to_string(), *id)))
.popup()
.with_name(format!("{}_sample_file_dir", type_)),
)
.child(
"record",
views::Checkbox::new().with_name(format!("{}_record", type_)),
)
.child(
"rtsp_transport",
views::SelectView::<&str>::new()
.with_all([("(default)", ""), ("tcp", "tcp"), ("udp", "udp")])
.popup()
.with_name(format!("{}_rtsp_transport", type_)),
)
.child(
"flush_if_sec",
views::EditView::new().with_name(format!("{}_flush_if_sec", type_)),
)
.child(
"usage/capacity",
views::TextView::new("").with_name(format!("{}_usage_cap", type_)),
)
.min_height(5);
layout.add_child(views::DummyView);
layout.add_child(views::TextView::new(format!("{} stream", type_)));
layout.add_child(list);
}
let mut dialog = views::Dialog::around(layout.scrollable());
let dialog = if let Some(camera_id) = *item {
let l = db.lock();
let camera = l.cameras_by_id().get(&camera_id).expect("missing camera");
if overwrite_uuid {
dialog
.call_on_name("uuid", |v: &mut views::TextView| {
v.set_content(camera.uuid.to_string())
})
.expect("missing TextView");
}
let mut bytes = 0;
for (i, sid) in camera.streams.iter().enumerate() {
@ -627,6 +552,101 @@ fn edit_camera_dialog(db: &Arc<db::Database>, siv: &mut Cursive, item: &Option<i
v.set_content(camera.config.description.clone())
})
.expect("missing TextArea");
(name, bytes)
}
/// Adds or updates a camera.
/// (The former if `item` is None; the latter otherwise.)
fn edit_camera_dialog(db: &Arc<db::Database>, siv: &mut Cursive, item: &Option<i32>) {
let camera_list = views::ListView::new()
.child(
"id",
views::TextView::new(item.map_or_else(|| "<new>".to_string(), |id| id.to_string())),
)
.child("uuid", views::TextView::new("<new>").with_name("uuid"))
.child("short name", views::EditView::new().with_name("short_name"))
.child(
"onvif_base_url",
views::EditView::new().with_name("onvif_base_url"),
)
.child("username", views::EditView::new().with_name("username"))
.child("password", views::EditView::new().with_name("password"))
.min_height(6);
let mut layout = views::LinearLayout::vertical()
.child(camera_list)
.child(views::TextView::new("description"))
.child(
views::TextArea::new()
.with_name("description")
.min_height(3),
);
let dirs: Vec<_> = ::std::iter::once(("<none>".into(), None))
.chain(
db.lock()
.sample_file_dirs_by_id()
.iter()
.map(|(&id, d)| (d.path.to_owned(), Some(id))),
)
.collect();
for &type_ in &db::ALL_STREAM_TYPES {
let list = views::ListView::new()
.child(
"rtsp url",
views::LinearLayout::horizontal()
.child(
views::EditView::new()
.on_edit(move |siv, content, _pos| {
let test_button = siv
.find_name::<views::Button>(&format!("{}_test", type_))
.unwrap();
edit_stream_url(type_, content, test_button);
})
.with_name(format!("{}_url", type_))
.full_width(),
)
.child(views::DummyView)
.child(
views::Button::new("Test", move |siv| press_test(siv, type_))
.disabled()
.with_name(format!("{}_test", type_)),
),
)
.child(
"sample file dir",
views::SelectView::<Option<i32>>::new()
.with_all(dirs.iter().map(|(p, id)| (p.display().to_string(), *id)))
.popup()
.with_name(format!("{}_sample_file_dir", type_)),
)
.child(
"record",
views::Checkbox::new().with_name(format!("{}_record", type_)),
)
.child(
"rtsp_transport",
views::SelectView::<&str>::new()
.with_all([("(default)", ""), ("tcp", "tcp"), ("udp", "udp")])
.popup()
.with_name(format!("{}_rtsp_transport", type_)),
)
.child(
"flush_if_sec",
views::EditView::new().with_name(format!("{}_flush_if_sec", type_)),
)
.child(
"usage/capacity",
views::TextView::new("").with_name(format!("{}_usage_cap", type_)),
)
.min_height(5);
layout.add_child(views::DummyView);
layout.add_child(views::TextView::new(format!("{} stream", type_)));
layout.add_child(list);
}
let mut dialog = views::Dialog::around(layout.scrollable());
let dialog = if let Some(camera_id) = *item {
let (name, bytes) = load_camera_values(db, camera_id, &mut dialog, true);
dialog
.title("Edit camera")
.button("Edit", {
@ -644,14 +664,47 @@ fn edit_camera_dialog(db: &Arc<db::Database>, siv: &mut Cursive, item: &Option<i
|v: &mut views::TextView| v.set_content("<new>"),
);
}
dialog.title("Add camera").button("Add", {
dialog
.title("Add camera")
.button("Add", {
let db = db.clone();
move |s| press_edit(s, &db, None)
})
.button("Copy config", {
let db = db.clone();
move |s| copy_camera_dialog(s, &db)
})
};
siv.add_layer(dialog.dismiss_button("Cancel"));
}
fn copy_camera_dialog(siv: &mut Cursive, db: &Arc<db::Database>) {
siv.add_layer(
views::Dialog::around(
views::SelectView::new()
.with_all(
db.lock()
.cameras_by_id()
.iter()
.map(|(&id, camera)| (format!("{}: {}", id, camera.short_name), id)),
)
.on_submit({
let db = db.clone();
move |siv, &camera_id| {
siv.pop_layer();
let screen = siv.screen_mut();
let dialog = screen.get_mut(views::LayerPosition::FromFront(0)).unwrap();
let dialog = dialog.downcast_mut::<Dialog>().unwrap();
load_camera_values(&db, camera_id, dialog, false);
}
})
.full_width(),
)
.dismiss_button("Cancel")
.title("Select camera to copy"),
);
}
pub fn top_dialog(db: &Arc<db::Database>, siv: &mut Cursive) {
siv.add_layer(
views::Dialog::around(