fixing lots of bugs
This commit is contained in:
parent
da735aa00b
commit
0ba3e7588b
24 changed files with 781 additions and 486 deletions
4
Cargo.lock
generated
4
Cargo.lock
generated
|
@ -1464,7 +1464,7 @@ dependencies = [
|
||||||
"cxx-qt-lib",
|
"cxx-qt-lib",
|
||||||
"dirs",
|
"dirs",
|
||||||
"fastrand 2.1.1",
|
"fastrand 2.1.1",
|
||||||
"lumina-core",
|
"lumina_core",
|
||||||
"obws",
|
"obws",
|
||||||
"qt-build-utils",
|
"qt-build-utils",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -1549,7 +1549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lumina-core"
|
name = "lumina_core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
|
|
|
@ -21,7 +21,7 @@ path = "src/rust/lib.rs"
|
||||||
# path = "src/rust/main.rs"
|
# path = "src/rust/main.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lumina-core = { path = "src/rust/core" }
|
lumina_core = { path = "src/rust/core" }
|
||||||
configparser = "3.0.2"
|
configparser = "3.0.2"
|
||||||
serde = "1.0.152"
|
serde = "1.0.152"
|
||||||
serde_derive = "1.0.152"
|
serde_derive = "1.0.152"
|
||||||
|
|
2
justfile
2
justfile
|
@ -15,7 +15,7 @@ test:
|
||||||
RUST_LOG=debug cargo test --benches --tests --all-features -- --nocapture
|
RUST_LOG=debug cargo test --benches --tests --all-features -- --nocapture
|
||||||
|
|
||||||
testcore:
|
testcore:
|
||||||
RUST_LOG=debug cargo test -p core --benches --tests --all-features -- --nocapture
|
RUST_LOG=debug cargo test -p lumina_core --benches --tests --all-features -- --nocapture
|
||||||
|
|
||||||
alias b := build
|
alias b := build
|
||||||
alias r := run
|
alias r := run
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[package]
|
[package]
|
||||||
name = "lumina-core"
|
name = "lumina_core"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = [
|
authors = [
|
||||||
|
|
|
@ -1,86 +1,131 @@
|
||||||
use tar::{Archive, Builder};
|
use crate::{
|
||||||
use tracing::error;
|
images::{get_image_from_db, Image},
|
||||||
use zstd::Encoder;
|
kinds::ServiceItemKind,
|
||||||
use std::{fs::{self, File}, iter, path::{Path, PathBuf}};
|
model::get_db,
|
||||||
|
presentations::{
|
||||||
|
get_presentation_from_db, PresKind, Presentation,
|
||||||
|
},
|
||||||
|
service_items::ServiceItem,
|
||||||
|
slides::Background,
|
||||||
|
songs::{get_song_from_db, Song},
|
||||||
|
videos::{get_video_from_db, Video},
|
||||||
|
};
|
||||||
use color_eyre::eyre::{eyre, Context, Result};
|
use color_eyre::eyre::{eyre, Context, Result};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use sqlx::{query, query_as, FromRow, SqliteConnection};
|
use sqlx::{query, query_as, FromRow, SqliteConnection};
|
||||||
use crate::{images::{get_image_from_db, Image}, kinds::ServiceItemKind, model::get_db, presentations::{get_presentation_from_db, PresKind, Presentation}, service_items::ServiceItem, slides::Background, songs::{get_song_from_db, Song}, videos::{get_video_from_db, Video}};
|
use std::{
|
||||||
|
fs::{self, File},
|
||||||
|
iter,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
use tar::{Archive, Builder};
|
||||||
|
use tracing::error;
|
||||||
|
use zstd::Encoder;
|
||||||
|
|
||||||
pub async fn save(list: Vec<ServiceItem>, path: impl AsRef<Path>) -> Result<()> {
|
pub async fn save(
|
||||||
|
list: Vec<ServiceItem>,
|
||||||
|
path: impl AsRef<Path>,
|
||||||
|
) -> Result<()> {
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
let save_file = File::create(path)?;
|
let save_file = File::create(path)?;
|
||||||
let mut db = get_db().await;
|
let mut db = get_db().await;
|
||||||
let json = process_service_items(&list, &mut db).await?;
|
let json = process_service_items(&list, &mut db).await?;
|
||||||
let archive = store_service_items(&list, &mut db, &save_file, &json).await?;
|
let archive =
|
||||||
|
store_service_items(&list, &mut db, &save_file, &json)
|
||||||
|
.await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn store_service_items(items: &Vec<ServiceItem>, db: &mut SqliteConnection, save_file: &File, json: &Value) -> Result<()> {
|
async fn store_service_items(
|
||||||
|
items: &Vec<ServiceItem>,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
save_file: &File,
|
||||||
|
json: &Value,
|
||||||
|
) -> Result<()> {
|
||||||
let encoder = Encoder::new(save_file, 3).unwrap();
|
let encoder = Encoder::new(save_file, 3).unwrap();
|
||||||
let mut tar = Builder::new(encoder);
|
let mut tar = Builder::new(encoder);
|
||||||
let mut temp_dir = dirs::data_dir().unwrap();
|
let mut temp_dir = dirs::data_dir().unwrap();
|
||||||
temp_dir.push("lumina");
|
temp_dir.push("lumina");
|
||||||
let mut s: String =
|
let mut s: String =
|
||||||
iter::repeat_with(fastrand::alphanumeric)
|
iter::repeat_with(fastrand::alphanumeric).take(5).collect();
|
||||||
.take(5)
|
|
||||||
.collect();
|
|
||||||
s.insert_str(0, "temp_");
|
s.insert_str(0, "temp_");
|
||||||
temp_dir.push(s);
|
temp_dir.push(s);
|
||||||
fs::create_dir_all(&temp_dir)?;
|
fs::create_dir_all(&temp_dir)?;
|
||||||
let service_file = temp_dir.join("serviceitems.json");
|
let service_file = temp_dir.join("serviceitems.json");
|
||||||
fs::File::create(&service_file)?;
|
fs::File::create(&service_file)?;
|
||||||
match fs::File::options().read(true).write(true).open(service_file) {
|
match fs::File::options()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.open(service_file)
|
||||||
|
{
|
||||||
Ok(f) => {
|
Ok(f) => {
|
||||||
serde_json::to_writer_pretty(f, json)?;
|
serde_json::to_writer_pretty(f, json)?;
|
||||||
},
|
}
|
||||||
Err(e) => error!("There were problems making a file i guess: {e}"),
|
Err(e) => {
|
||||||
|
error!("There were problems making a file i guess: {e}")
|
||||||
|
}
|
||||||
};
|
};
|
||||||
for item in items {
|
for item in items {
|
||||||
let background;
|
let background;
|
||||||
let audio: Option<PathBuf>;
|
let audio: Option<PathBuf>;
|
||||||
match item.kind {
|
match item.kind {
|
||||||
ServiceItemKind::Song => {
|
ServiceItemKind::Song => {
|
||||||
let song = get_song_from_db(item.database_id, db).await?;
|
let song =
|
||||||
|
get_song_from_db(item.database_id, db).await?;
|
||||||
background = song.background;
|
background = song.background;
|
||||||
audio = song.audio;
|
audio = song.audio;
|
||||||
},
|
}
|
||||||
ServiceItemKind::Image => {
|
ServiceItemKind::Image => {
|
||||||
let image = get_image_from_db(item.database_id, db).await?;
|
let image =
|
||||||
|
get_image_from_db(item.database_id, db).await?;
|
||||||
background = Some(Background::try_from(image.path)?);
|
background = Some(Background::try_from(image.path)?);
|
||||||
audio = None;
|
audio = None;
|
||||||
},
|
}
|
||||||
ServiceItemKind::Video => {
|
ServiceItemKind::Video => {
|
||||||
let video = get_video_from_db(item.database_id, db).await?;
|
let video =
|
||||||
|
get_video_from_db(item.database_id, db).await?;
|
||||||
background = Some(Background::try_from(video.path)?);
|
background = Some(Background::try_from(video.path)?);
|
||||||
audio = None;
|
audio = None;
|
||||||
},
|
}
|
||||||
ServiceItemKind::Presentation(_) => {
|
ServiceItemKind::Presentation(_) => {
|
||||||
let presentation = get_presentation_from_db(item.database_id, db).await?;
|
let presentation =
|
||||||
background = Some(Background::try_from(presentation.path)?);
|
get_presentation_from_db(item.database_id, db)
|
||||||
|
.await?;
|
||||||
|
background =
|
||||||
|
Some(Background::try_from(presentation.path)?);
|
||||||
audio = None;
|
audio = None;
|
||||||
},
|
}
|
||||||
ServiceItemKind::Content => {
|
ServiceItemKind::Content => {
|
||||||
todo!()
|
todo!()
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
if let Some(file) = audio {
|
if let Some(file) = audio {
|
||||||
let audio_file = temp_dir.join(file.file_name().expect("Audio file couldn't be added to temp_dir"));
|
let audio_file =
|
||||||
|
temp_dir.join(file.file_name().expect(
|
||||||
|
"Audio file couldn't be added to temp_dir",
|
||||||
|
));
|
||||||
if let Ok(file) = file.strip_prefix("file://") {
|
if let Ok(file) = file.strip_prefix("file://") {
|
||||||
fs::File::create(&audio_file).wrap_err("Couldn't create audio file")?;
|
fs::File::create(&audio_file)
|
||||||
|
.wrap_err("Couldn't create audio file")?;
|
||||||
fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found");
|
fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found");
|
||||||
} else {
|
} else {
|
||||||
fs::File::create(&audio_file).wrap_err("Couldn't create audio file")?;
|
fs::File::create(&audio_file)
|
||||||
|
.wrap_err("Couldn't create audio file")?;
|
||||||
fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found");
|
fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if let Some(file) = background {
|
if let Some(file) = background {
|
||||||
let background_file = temp_dir.join(file.path.file_name().expect("Background file couldn't be added to temp_dir"));
|
let background_file =
|
||||||
|
temp_dir.join(file.path.file_name().expect(
|
||||||
|
"Background file couldn't be added to temp_dir",
|
||||||
|
));
|
||||||
if let Ok(file) = file.path.strip_prefix("file://") {
|
if let Ok(file) = file.path.strip_prefix("file://") {
|
||||||
fs::File::create(&background_file).wrap_err("Couldn't create background file")?;
|
fs::File::create(&background_file)
|
||||||
|
.wrap_err("Couldn't create background file")?;
|
||||||
fs::copy(file, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found");
|
fs::copy(file, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found");
|
||||||
} else {
|
} else {
|
||||||
fs::File::create(&background_file).wrap_err("Couldn't create background file")?;
|
fs::File::create(&background_file)
|
||||||
|
.wrap_err("Couldn't create background file")?;
|
||||||
fs::copy(file.path, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found");
|
fs::copy(file.path, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,66 +137,96 @@ async fn clear_temp_dir(temp_dir: &Path) -> Result<()> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_service_items(items: &Vec<ServiceItem>, db: &mut SqliteConnection) -> Result<Value> {
|
async fn process_service_items(
|
||||||
|
items: &Vec<ServiceItem>,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Value> {
|
||||||
let mut values: Vec<Value> = vec![];
|
let mut values: Vec<Value> = vec![];
|
||||||
for item in items {
|
for item in items {
|
||||||
match item.kind {
|
match item.kind {
|
||||||
ServiceItemKind::Song => {
|
ServiceItemKind::Song => {
|
||||||
let value = process_song(item.database_id, db).await?;
|
let value =
|
||||||
|
process_song(item.database_id, db).await?;
|
||||||
values.push(value);
|
values.push(value);
|
||||||
},
|
}
|
||||||
ServiceItemKind::Image => {
|
ServiceItemKind::Image => {
|
||||||
let value = process_image(item.database_id, db).await?;
|
let value =
|
||||||
|
process_image(item.database_id, db).await?;
|
||||||
values.push(value);
|
values.push(value);
|
||||||
},
|
}
|
||||||
ServiceItemKind::Video => {
|
ServiceItemKind::Video => {
|
||||||
let value = process_video(item.database_id, db).await?;
|
let value =
|
||||||
|
process_video(item.database_id, db).await?;
|
||||||
values.push(value);
|
values.push(value);
|
||||||
},
|
}
|
||||||
ServiceItemKind::Presentation(_) => {
|
ServiceItemKind::Presentation(_) => {
|
||||||
let value = process_presentation(item.database_id, db).await?;
|
let value =
|
||||||
|
process_presentation(item.database_id, db)
|
||||||
|
.await?;
|
||||||
values.push(value);
|
values.push(value);
|
||||||
},
|
}
|
||||||
ServiceItemKind::Content => {
|
ServiceItemKind::Content => {
|
||||||
todo!()
|
todo!()
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let json = Value::from(values);
|
let json = Value::from(values);
|
||||||
Ok(json)
|
Ok(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_song(database_id: i32, db: &mut SqliteConnection) -> Result<Value> {
|
async fn process_song(
|
||||||
|
database_id: i32,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Value> {
|
||||||
let song = get_song_from_db(database_id, db).await?;
|
let song = get_song_from_db(database_id, db).await?;
|
||||||
let song_json = serde_json::to_value(&song)?;
|
let song_json = serde_json::to_value(&song)?;
|
||||||
let kind_json = serde_json::to_value(ServiceItemKind::Song)?;
|
let kind_json = serde_json::to_value(ServiceItemKind::Song)?;
|
||||||
let json = serde_json::json!({"item": song_json, "kind": kind_json});
|
let json =
|
||||||
|
serde_json::json!({"item": song_json, "kind": kind_json});
|
||||||
Ok(json)
|
Ok(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_image(database_id: i32, db: &mut SqliteConnection) -> Result<Value> {
|
async fn process_image(
|
||||||
|
database_id: i32,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Value> {
|
||||||
let image = get_image_from_db(database_id, db).await?;
|
let image = get_image_from_db(database_id, db).await?;
|
||||||
let image_json = serde_json::to_value(&image)?;
|
let image_json = serde_json::to_value(&image)?;
|
||||||
let kind_json = serde_json::to_value(ServiceItemKind::Image)?;
|
let kind_json = serde_json::to_value(ServiceItemKind::Image)?;
|
||||||
let json = serde_json::json!({"item": image_json, "kind": kind_json});
|
let json =
|
||||||
|
serde_json::json!({"item": image_json, "kind": kind_json});
|
||||||
Ok(json)
|
Ok(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_video(database_id: i32, db: &mut SqliteConnection) -> Result<Value> {
|
async fn process_video(
|
||||||
|
database_id: i32,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Value> {
|
||||||
let video = get_video_from_db(database_id, db).await?;
|
let video = get_video_from_db(database_id, db).await?;
|
||||||
let video_json = serde_json::to_value(&video)?;
|
let video_json = serde_json::to_value(&video)?;
|
||||||
let kind_json = serde_json::to_value(ServiceItemKind::Video)?;
|
let kind_json = serde_json::to_value(ServiceItemKind::Video)?;
|
||||||
let json = serde_json::json!({"item": video_json, "kind": kind_json});
|
let json =
|
||||||
|
serde_json::json!({"item": video_json, "kind": kind_json});
|
||||||
Ok(json)
|
Ok(json)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn process_presentation(database_id: i32, db: &mut SqliteConnection) -> Result<Value> {
|
async fn process_presentation(
|
||||||
let presentation = get_presentation_from_db(database_id, db).await?;
|
database_id: i32,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Value> {
|
||||||
|
let presentation =
|
||||||
|
get_presentation_from_db(database_id, db).await?;
|
||||||
let presentation_json = serde_json::to_value(&presentation)?;
|
let presentation_json = serde_json::to_value(&presentation)?;
|
||||||
let kind_json = match presentation.kind {
|
let kind_json = match presentation.kind {
|
||||||
PresKind::Html => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Html))?,
|
PresKind::Html => serde_json::to_value(
|
||||||
PresKind::Pdf => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Pdf))?,
|
ServiceItemKind::Presentation(PresKind::Html),
|
||||||
PresKind::Generic => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Generic))?,
|
)?,
|
||||||
|
PresKind::Pdf => serde_json::to_value(
|
||||||
|
ServiceItemKind::Presentation(PresKind::Pdf),
|
||||||
|
)?,
|
||||||
|
PresKind::Generic => serde_json::to_value(
|
||||||
|
ServiceItemKind::Presentation(PresKind::Generic),
|
||||||
|
)?,
|
||||||
};
|
};
|
||||||
let json = serde_json::json!({"item": presentation_json, "kind": kind_json});
|
let json = serde_json::json!({"item": presentation_json, "kind": kind_json});
|
||||||
Ok(json)
|
Ok(json)
|
||||||
|
@ -161,11 +236,11 @@ async fn process_presentation(database_id: i32, db: &mut SqliteConnection) -> Re
|
||||||
mod test {
|
mod test {
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use fs::canonicalize;
|
|
||||||
use sqlx::Connection;
|
|
||||||
use pretty_assertions::assert_eq;
|
|
||||||
use tracing::debug;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use fs::canonicalize;
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use sqlx::Connection;
|
||||||
|
use tracing::debug;
|
||||||
|
|
||||||
async fn get_db() -> SqliteConnection {
|
async fn get_db() -> SqliteConnection {
|
||||||
let mut data = dirs::data_local_dir().unwrap();
|
let mut data = dirs::data_local_dir().unwrap();
|
||||||
|
@ -173,9 +248,7 @@ mod test {
|
||||||
data.push("library-db.sqlite3");
|
data.push("library-db.sqlite3");
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
SqliteConnection::connect(&db_url)
|
SqliteConnection::connect(&db_url).await.expect("problems")
|
||||||
.await
|
|
||||||
.expect("problems")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "current_thread")]
|
#[tokio::test(flavor = "current_thread")]
|
||||||
|
@ -245,7 +318,8 @@ mod test {
|
||||||
async fn test_process_presentation() {
|
async fn test_process_presentation() {
|
||||||
let mut db = get_db().await;
|
let mut db = get_db().await;
|
||||||
let result = process_presentation(54, &mut db).await;
|
let result = process_presentation(54, &mut db).await;
|
||||||
let json_presentation_file = PathBuf::from("./test/test_presentation.json");
|
let json_presentation_file =
|
||||||
|
PathBuf::from("./test/test_presentation.json");
|
||||||
if let Ok(path) = canonicalize(json_presentation_file) {
|
if let Ok(path) = canonicalize(json_presentation_file) {
|
||||||
debug!(file = ?&path);
|
debug!(file = ?&path);
|
||||||
if let Ok(s) = fs::read_to_string(path) {
|
if let Ok(s) = fs::read_to_string(path) {
|
||||||
|
@ -258,7 +332,9 @@ mod test {
|
||||||
panic!("String wasn't read from file");
|
panic!("String wasn't read from file");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
panic!("Cannot find absolute path to test_presentation.json");
|
panic!(
|
||||||
|
"Cannot find absolute path to test_presentation.json"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +363,8 @@ mod test {
|
||||||
async fn test_service_items() {
|
async fn test_service_items() {
|
||||||
let mut db = get_db().await;
|
let mut db = get_db().await;
|
||||||
let items = get_items();
|
let items = get_items();
|
||||||
let json_item_file = PathBuf::from("./test/test_service_items.json");
|
let json_item_file =
|
||||||
|
PathBuf::from("./test/test_service_items.json");
|
||||||
let result = process_service_items(&items, &mut db).await;
|
let result = process_service_items(&items, &mut db).await;
|
||||||
if let Ok(path) = canonicalize(json_item_file) {
|
if let Ok(path) = canonicalize(json_item_file) {
|
||||||
if let Ok(s) = fs::read_to_string(path) {
|
if let Ok(s) = fs::read_to_string(path) {
|
||||||
|
@ -311,16 +388,23 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_store() {
|
async fn test_store() {
|
||||||
let path = PathBuf::from("/home/chris/dev/lumina/src/rust/core/test.pres");
|
let path = PathBuf::from(
|
||||||
|
"/home/chris/dev/lumina/src/rust/core/test.pres",
|
||||||
|
);
|
||||||
let save_file = match File::create(path) {
|
let save_file = match File::create(path) {
|
||||||
Ok(f) => f,
|
Ok(f) => f,
|
||||||
Err(e) => panic!("Couldn't create save_file: {e}"),
|
Err(e) => panic!("Couldn't create save_file: {e}"),
|
||||||
};
|
};
|
||||||
let mut db = get_db().await;
|
let mut db = get_db().await;
|
||||||
let list = get_items();
|
let list = get_items();
|
||||||
if let Ok(json) = process_service_items(&list, &mut db).await {
|
if let Ok(json) = process_service_items(&list, &mut db).await
|
||||||
|
{
|
||||||
println!("{:?}", json);
|
println!("{:?}", json);
|
||||||
match store_service_items(&list, &mut db, &save_file, &json).await {
|
match store_service_items(
|
||||||
|
&list, &mut db, &save_file, &json,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
Ok(_) => assert!(true),
|
Ok(_) => assert!(true),
|
||||||
Err(e) => panic!("There was an error: {e}"),
|
Err(e) => panic!("There was an error: {e}"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,9 @@ use sqlx::{query_as, SqliteConnection};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Clone, Debug, Default, PartialEq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub struct Image {
|
pub struct Image {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -16,7 +18,7 @@ impl Model<Image> {
|
||||||
pub fn load_from_db(&mut self) {
|
pub fn load_from_db(&mut self) {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Image, r#"SELECT title as "title!", filePath as "path!", id as "id: i32" from images"#).fetch_all(&mut self.db).await;
|
let result = query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images"#).fetch_all(&mut self.db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
for image in v.into_iter() {
|
for image in v.into_iter() {
|
||||||
|
@ -29,9 +31,11 @@ impl Model<Image> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_image_from_db(
|
||||||
pub async fn get_image_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Image> {
|
database_id: i32,
|
||||||
Ok(query_as!(Image, r#"SELECT title as "title!", filePath as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await?)
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Image> {
|
||||||
|
Ok(query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -67,7 +71,10 @@ mod test {
|
||||||
let new_image = test_image("A newer image".into());
|
let new_image = test_image("A newer image".into());
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
assert_eq!(&image, image_model.find(|i| i.id == 0).unwrap());
|
assert_eq!(
|
||||||
|
&image,
|
||||||
|
image_model.find(|i| i.id == 0).unwrap()
|
||||||
|
);
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
&new_image,
|
&new_image,
|
||||||
image_model.find(|i| i.id == 0).unwrap()
|
image_model.find(|i| i.id == 0).unwrap()
|
||||||
|
|
|
@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::presentations::PresKind;
|
use crate::presentations::PresKind;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub enum ServiceItemKind {
|
pub enum ServiceItemKind {
|
||||||
#[default]
|
#[default]
|
||||||
Song,
|
Song,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
pub mod file;
|
||||||
pub mod images;
|
pub mod images;
|
||||||
pub mod kinds;
|
pub mod kinds;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
|
@ -6,4 +7,3 @@ pub mod service_items;
|
||||||
pub mod slides;
|
pub mod slides;
|
||||||
pub mod songs;
|
pub mod songs;
|
||||||
pub mod videos;
|
pub mod videos;
|
||||||
pub mod file;
|
|
||||||
|
|
|
@ -36,8 +36,7 @@ impl<T> Model<T> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_item(&self, index: i32) -> Option<&T>
|
pub fn get_item(&self, index: i32) -> Option<&T> {
|
||||||
{
|
|
||||||
self.items.get(index as usize)
|
self.items.get(index as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,10 +59,8 @@ impl<T> Default for Model<T> {
|
||||||
items: vec![],
|
items: vec![],
|
||||||
db: {
|
db: {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async { get_db().await })
|
||||||
get_db().await
|
},
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,9 +71,7 @@ pub async fn get_db() -> SqliteConnection {
|
||||||
data.push("library-db.sqlite3");
|
data.push("library-db.sqlite3");
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
SqliteConnection::connect(&db_url)
|
SqliteConnection::connect(&db_url).await.expect("problems")
|
||||||
.await
|
|
||||||
.expect("problems")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Modeling {
|
pub trait Modeling {
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
use std::path::PathBuf;
|
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection};
|
use sqlx::{
|
||||||
|
prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection,
|
||||||
|
};
|
||||||
|
use std::path::PathBuf;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
use crate::model::Model;
|
use crate::model::Model;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub enum PresKind {
|
pub enum PresKind {
|
||||||
Html,
|
Html,
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -14,7 +18,9 @@ pub enum PresKind {
|
||||||
Generic,
|
Generic,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub struct Presentation {
|
pub struct Presentation {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -57,7 +63,7 @@ impl Model<Presentation> {
|
||||||
pub fn load_from_db(&mut self) {
|
pub fn load_from_db(&mut self) {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!(r#"SELECT id as "id: i32", title, filePath as "path", html from presentations"#).fetch_all(&mut self.db).await;
|
let result = query!(r#"SELECT id as "id: i32", title, file_path as "path", html from presentations"#).fetch_all(&mut self.db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
for presentation in v.into_iter() {
|
for presentation in v.into_iter() {
|
||||||
|
@ -79,8 +85,11 @@ impl Model<Presentation> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_presentation_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Presentation> {
|
pub async fn get_presentation_from_db(
|
||||||
let row = query(r#"SELECT id as "id: i32", title, filePath as "path", html from presentations where id = $1"#).bind(database_id).fetch_one(db).await?;
|
database_id: i32,
|
||||||
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Presentation> {
|
||||||
|
let row = query(r#"SELECT id as "id: i32", title, file_path as "path", html from presentations where id = $1"#).bind(database_id).fetch_one(db).await?;
|
||||||
Ok(Presentation::from_row(&row)?)
|
Ok(Presentation::from_row(&row)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +120,9 @@ mod test {
|
||||||
let mut presentation_model: Model<Presentation> =
|
let mut presentation_model: Model<Presentation> =
|
||||||
Model::default();
|
Model::default();
|
||||||
presentation_model.load_from_db();
|
presentation_model.load_from_db();
|
||||||
if let Some(presentation) = presentation_model.find(|p| p.id == 54) {
|
if let Some(presentation) =
|
||||||
|
presentation_model.find(|p| p.id == 54)
|
||||||
|
{
|
||||||
let test_presentation = test_presentation();
|
let test_presentation = test_presentation();
|
||||||
assert_eq!(&test_presentation, presentation);
|
assert_eq!(&test_presentation, presentation);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -52,7 +52,9 @@ impl From<&Image> for ServiceItem {
|
||||||
impl From<&Presentation> for ServiceItem {
|
impl From<&Presentation> for ServiceItem {
|
||||||
fn from(presentation: &Presentation) -> Self {
|
fn from(presentation: &Presentation) -> Self {
|
||||||
Self {
|
Self {
|
||||||
kind: ServiceItemKind::Presentation(presentation.kind.clone()),
|
kind: ServiceItemKind::Presentation(
|
||||||
|
presentation.kind.clone(),
|
||||||
|
),
|
||||||
database_id: presentation.id,
|
database_id: presentation.id,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
|
@ -60,7 +62,10 @@ impl From<&Presentation> for ServiceItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceItemModel {
|
impl ServiceItemModel {
|
||||||
fn add_item(&mut self, item: impl Into<ServiceItem>) -> Result<()> {
|
fn add_item(
|
||||||
|
&mut self,
|
||||||
|
item: impl Into<ServiceItem>,
|
||||||
|
) -> Result<()> {
|
||||||
let service_item: ServiceItem = item.into();
|
let service_item: ServiceItem = item.into();
|
||||||
self.items.push(service_item);
|
self.items.push(service_item);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -94,7 +99,6 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
pub fn test_service_item() {
|
pub fn test_service_item() {
|
||||||
let song = test_song();
|
let song = test_song();
|
||||||
|
@ -104,10 +108,16 @@ mod test {
|
||||||
let mut service_model = ServiceItemModel::default();
|
let mut service_model = ServiceItemModel::default();
|
||||||
match service_model.add_item(&song) {
|
match service_model.add_item(&song) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
assert_eq!(ServiceItemKind::Song, service_model.items[0].kind);
|
assert_eq!(
|
||||||
assert_eq!(ServiceItemKind::Presentation(PresKind::Html), pres_item.kind);
|
ServiceItemKind::Song,
|
||||||
|
service_model.items[0].kind
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
ServiceItemKind::Presentation(PresKind::Html),
|
||||||
|
pres_item.kind
|
||||||
|
);
|
||||||
assert_eq!(service_item, service_model.items[0]);
|
assert_eq!(service_item, service_model.items[0]);
|
||||||
},
|
}
|
||||||
Err(e) => panic!("Problem adding item: {:?}", e),
|
Err(e) => panic!("Problem adding item: {:?}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
use std::{error::Error, fmt::Display, path::{Path, PathBuf}};
|
use std::{
|
||||||
|
error::Error,
|
||||||
|
fmt::Display,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
use color_eyre::eyre::{eyre, Result};
|
use color_eyre::eyre::{eyre, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -10,7 +14,9 @@ use crate::{
|
||||||
presentations::Presentation, songs::Song, videos::Video,
|
presentations::Presentation, songs::Song, videos::Video,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub enum TextAlignment {
|
pub enum TextAlignment {
|
||||||
TopLeft,
|
TopLeft,
|
||||||
TopCenter,
|
TopCenter,
|
||||||
|
@ -24,7 +30,9 @@ pub enum TextAlignment {
|
||||||
BottomRight,
|
BottomRight,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub struct Background {
|
pub struct Background {
|
||||||
pub path: PathBuf,
|
pub path: PathBuf,
|
||||||
pub kind: BackgroundKind,
|
pub kind: BackgroundKind,
|
||||||
|
@ -36,7 +44,7 @@ impl TryFrom<String> for Background {
|
||||||
let value = value.trim_start_matches("file://");
|
let value = value.trim_start_matches("file://");
|
||||||
let path = PathBuf::from(value);
|
let path = PathBuf::from(value);
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
return Err(ParseError::DoesNotExist)
|
return Err(ParseError::DoesNotExist);
|
||||||
}
|
}
|
||||||
let extension = value.rsplit_once('.').unwrap_or_default();
|
let extension = value.rsplit_once('.').unwrap_or_default();
|
||||||
match extension.1 {
|
match extension.1 {
|
||||||
|
@ -106,11 +114,15 @@ impl DatabaseError for ParseError {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_error_mut(&mut self) -> &mut (dyn Error + Send + Sync + 'static) {
|
fn as_error_mut(
|
||||||
|
&mut self,
|
||||||
|
) -> &mut (dyn Error + Send + Sync + 'static) {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn into_error(self: Box<Self>) -> Box<dyn Error + Send + Sync + 'static> {
|
fn into_error(
|
||||||
|
self: Box<Self>,
|
||||||
|
) -> Box<dyn Error + Send + Sync + 'static> {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,15 +140,15 @@ impl Display for ParseError {
|
||||||
Self::NonBackgroundFile => {
|
Self::NonBackgroundFile => {
|
||||||
"The file is not a recognized image or video type"
|
"The file is not a recognized image or video type"
|
||||||
}
|
}
|
||||||
Self::DoesNotExist => {
|
Self::DoesNotExist => "This file doesn't exist",
|
||||||
"This file doesn't exist"
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
write!(f, "Error: {message}")
|
write!(f, "Error: {message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub enum BackgroundKind {
|
pub enum BackgroundKind {
|
||||||
#[default]
|
#[default]
|
||||||
Image,
|
Image,
|
||||||
|
|
|
@ -2,7 +2,10 @@ use std::{collections::HashMap, path::PathBuf};
|
||||||
|
|
||||||
use color_eyre::eyre::{eyre, Context, Result};
|
use color_eyre::eyre::{eyre, Context, Result};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{query, query_as, sqlite::SqliteRow, FromRow, Row, SqliteConnection};
|
use sqlx::{
|
||||||
|
query, query_as, sqlite::SqliteRow, FromRow, Row,
|
||||||
|
SqliteConnection,
|
||||||
|
};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -10,7 +13,9 @@ use crate::{
|
||||||
slides::{Background, TextAlignment},
|
slides::{Background, TextAlignment},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub struct Song {
|
pub struct Song {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -56,17 +61,24 @@ impl FromRow<'_, SqliteRow> for Song {
|
||||||
text_alignment: Some({
|
text_alignment: Some({
|
||||||
let horizontal_alignment: String = row.try_get(3)?;
|
let horizontal_alignment: String = row.try_get(3)?;
|
||||||
let vertical_alignment: String = row.try_get(4)?;
|
let vertical_alignment: String = row.try_get(4)?;
|
||||||
match (horizontal_alignment.to_lowercase().as_str(), vertical_alignment.to_lowercase().as_str()) {
|
match (
|
||||||
|
horizontal_alignment.to_lowercase().as_str(),
|
||||||
|
vertical_alignment.to_lowercase().as_str(),
|
||||||
|
) {
|
||||||
("left", "top") => TextAlignment::TopLeft,
|
("left", "top") => TextAlignment::TopLeft,
|
||||||
("left", "center") => TextAlignment::MiddleLeft,
|
("left", "center") => TextAlignment::MiddleLeft,
|
||||||
("left", "bottom") => TextAlignment::BottomLeft,
|
("left", "bottom") => TextAlignment::BottomLeft,
|
||||||
("center", "top") => TextAlignment::TopCenter,
|
("center", "top") => TextAlignment::TopCenter,
|
||||||
("center", "center") => TextAlignment::MiddleCenter,
|
("center", "center") => {
|
||||||
("center", "bottom") => TextAlignment::BottomCenter,
|
TextAlignment::MiddleCenter
|
||||||
|
}
|
||||||
|
("center", "bottom") => {
|
||||||
|
TextAlignment::BottomCenter
|
||||||
|
}
|
||||||
("right", "top") => TextAlignment::TopRight,
|
("right", "top") => TextAlignment::TopRight,
|
||||||
("right", "center") => TextAlignment::MiddleRight,
|
("right", "center") => TextAlignment::MiddleRight,
|
||||||
("right", "bottom") => TextAlignment::BottomRight,
|
("right", "bottom") => TextAlignment::BottomRight,
|
||||||
_ => TextAlignment::MiddleCenter
|
_ => TextAlignment::MiddleCenter,
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
font: row.try_get(6)?,
|
font: row.try_get(6)?,
|
||||||
|
@ -75,19 +87,20 @@ impl FromRow<'_, SqliteRow> for Song {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_song_from_db(
|
||||||
pub async fn get_song_from_db(index: i32, db: &mut SqliteConnection) -> Result<Song> {
|
index: i32,
|
||||||
let row = query(r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#).bind(index).fetch_one(db).await?;
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Song> {
|
||||||
|
let row = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#).bind(index).fetch_one(db).await?;
|
||||||
Ok(Song::from_row(&row)?)
|
Ok(Song::from_row(&row)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl Model<Song> {
|
impl Model<Song> {
|
||||||
pub fn load_from_db(&mut self) {
|
pub fn load_from_db(&mut self) {
|
||||||
// static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
|
// static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query(r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.db).await;
|
let result = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(s) => {
|
Ok(s) => {
|
||||||
for song in s.into_iter() {
|
for song in s.into_iter() {
|
||||||
|
|
|
@ -5,7 +5,9 @@ use sqlx::{query_as, SqliteConnection};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(
|
||||||
|
Clone, Debug, Default, PartialEq, Serialize, Deserialize,
|
||||||
|
)]
|
||||||
pub struct Video {
|
pub struct Video {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
@ -19,7 +21,7 @@ impl Model<Video> {
|
||||||
pub fn load_from_db(&mut self) {
|
pub fn load_from_db(&mut self) {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Video, r#"SELECT title as "title!", filePath as "path!", startTime as "start_time!: f32", endTime as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(&mut self.db).await;
|
let result = query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos"#).fetch_all(&mut self.db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => {
|
Ok(v) => {
|
||||||
for video in v.into_iter() {
|
for video in v.into_iter() {
|
||||||
|
@ -32,12 +34,13 @@ impl Model<Video> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_video_from_db(
|
||||||
pub async fn get_video_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Video> {
|
database_id: i32,
|
||||||
Ok(query_as!(Video, r#"SELECT title as "title!", filePath as "path!", startTime as "start_time!: f32", endTime as "end_time!: f32", loop as "looping!", id as "id: i32" from videos where id = ?"#, database_id).fetch_one(db).await?)
|
db: &mut SqliteConnection,
|
||||||
|
) -> Result<Video> {
|
||||||
|
Ok(query_as!(Video, r#"SELECT title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!", id as "id: i32" from videos where id = ?"#, database_id).fetch_one(db).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -71,7 +74,10 @@ mod test {
|
||||||
let new_video = test_video("A newer video".into());
|
let new_video = test_video("A newer video".into());
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
assert_eq!(&video, video_model.find(|v| v.id == 0).unwrap());
|
assert_eq!(
|
||||||
|
&video,
|
||||||
|
video_model.find(|v| v.id == 0).unwrap()
|
||||||
|
);
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
&new_video,
|
&new_video,
|
||||||
video_model.find(|v| v.id == 0).unwrap()
|
video_model.find(|v| v.id == 0).unwrap()
|
||||||
|
|
|
@ -181,7 +181,7 @@ pub struct ImageModelRust {
|
||||||
highest_id: i32,
|
highest_id: i32,
|
||||||
images: Vec<Image>,
|
images: Vec<Image>,
|
||||||
inner_images: Vec<Image>,
|
inner_images: Vec<Image>,
|
||||||
db: SqliteConnection
|
db: SqliteConnection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ImageModelRust {
|
impl Default for ImageModelRust {
|
||||||
|
@ -199,9 +199,11 @@ impl Default for ImageModelRust {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,11 +217,13 @@ pub fn get_image(index: i32) -> color_eyre::Result<Image> {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Image, r#"SELECT id as "id: i32", title as "title!", filePath as "path!" from images where id = ?"#, index).fetch_one(&mut db).await?;
|
let result = query_as!(Image, r#"SELECT id as "id: i32", title as "title!", file_path as "path!" from images where id = ?"#, index).fetch_one(&mut db).await?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -236,7 +240,7 @@ impl image_model::ImageModel {
|
||||||
pub fn setup(mut self: Pin<&mut Self>) {
|
pub fn setup(mut self: Pin<&mut Self>) {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Image, r#"SELECT id as "id: i32", title as "title!", filePath as "path!" from images"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
let result = query_as!(Image, r#"SELECT id as "id: i32", title as "title!", file_path as "path!" from images"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(i) => i.into_iter().for_each(|i| self.as_mut().add_image(i)),
|
Ok(i) => i.into_iter().for_each(|i| self.as_mut().add_image(i)),
|
||||||
Err(e) => error!("There was an error in converting songs: {e}"),
|
Err(e) => error!("There was an error in converting songs: {e}"),
|
||||||
|
@ -251,7 +255,10 @@ impl image_model::ImageModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("delete from images where id = ?", index).execute(&mut self.as_mut().rust_mut().db).await;
|
let result =
|
||||||
|
query!("delete from images where id = ?", index)
|
||||||
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
|
.await;
|
||||||
match result {
|
match result {
|
||||||
Ok(_i) => {
|
Ok(_i) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -308,7 +315,7 @@ impl image_model::ImageModel {
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let image_title = image_title.to_string();
|
let image_title = image_title.to_string();
|
||||||
let image_path = image_path.to_string();
|
let image_path = image_path.to_string();
|
||||||
let result = query!(r#"INSERT into images (id, title, filePath) VALUES (?, ?, ?)"#,
|
let result = query!(r#"INSERT into images (id, title, file_path) VALUES (?, ?, ?)"#,
|
||||||
image_id,
|
image_id,
|
||||||
image_title,
|
image_title,
|
||||||
image_path)
|
image_path)
|
||||||
|
@ -367,7 +374,11 @@ impl image_model::ImageModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let title = updated_title.to_string();
|
let title = updated_title.to_string();
|
||||||
let result = query!("UPDATE images SET title = ? where id = ?", title, index)
|
let result = query!(
|
||||||
|
"UPDATE images SET title = ? where id = ?",
|
||||||
|
title,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -380,9 +391,11 @@ impl image_model::ImageModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
image.title = title.clone();
|
image.title = title.clone();
|
||||||
debug!(title = image.title,
|
debug!(
|
||||||
|
title = image.title,
|
||||||
title = title,
|
title = title,
|
||||||
"updated image title");
|
"updated image title"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -394,7 +407,7 @@ impl image_model::ImageModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -414,7 +427,11 @@ impl image_model::ImageModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let updated_path = updated_path.to_string();
|
let updated_path = updated_path.to_string();
|
||||||
let result = query!("UPDATE images SET filePath = ? where id = ?", updated_path, index)
|
let result = query!(
|
||||||
|
"UPDATE images SET file_path = ? where id = ?",
|
||||||
|
updated_path,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -427,9 +444,11 @@ impl image_model::ImageModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
image.path = updated_path.clone();
|
image.path = updated_path.clone();
|
||||||
debug!(title = image.title,
|
debug!(
|
||||||
|
title = image.title,
|
||||||
path = updated_path,
|
path = updated_path,
|
||||||
"updated image path");
|
"updated image path"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -441,7 +460,7 @@ impl image_model::ImageModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
|
|
@ -8,10 +8,9 @@ pub mod service_item_model;
|
||||||
pub mod settings;
|
pub mod settings;
|
||||||
pub mod slide_model;
|
pub mod slide_model;
|
||||||
pub mod slide_object;
|
pub mod slide_object;
|
||||||
|
pub mod slide_types;
|
||||||
pub mod songs;
|
pub mod songs;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod video_model;
|
pub mod video_model;
|
||||||
pub mod ytdl;
|
pub mod ytdl;
|
||||||
pub mod slide_types;
|
|
||||||
// pub mod core;
|
|
||||||
// mod video_thumbnail;
|
// mod video_thumbnail;
|
||||||
|
|
|
@ -4,7 +4,6 @@ use cxx_qt_lib::{QString, QStringList};
|
||||||
use obws::responses::scenes::{CurrentProgramScene, Scenes};
|
use obws::responses::scenes::{CurrentProgramScene, Scenes};
|
||||||
use obws::Client;
|
use obws::Client;
|
||||||
|
|
||||||
|
|
||||||
use std::{error::Error, pin::Pin};
|
use std::{error::Error, pin::Pin};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
|
@ -22,7 +21,10 @@ impl fmt::Debug for Obs {
|
||||||
f.debug_struct("Client")
|
f.debug_struct("Client")
|
||||||
.field("scenes", &self.scenes)
|
.field("scenes", &self.scenes)
|
||||||
.field("client", &self.client.is_some())
|
.field("client", &self.client.is_some())
|
||||||
.field("current_program_scene", &self.current_program_scene)
|
.field(
|
||||||
|
"current_program_scene",
|
||||||
|
&self.current_program_scene,
|
||||||
|
)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,8 +39,6 @@ impl Clone for Obs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
impl Obs {
|
impl Obs {
|
||||||
pub async fn new() -> Result<Self, Box<dyn Error>> {
|
pub async fn new() -> Result<Self, Box<dyn Error>> {
|
||||||
let client =
|
let client =
|
||||||
|
|
|
@ -208,7 +208,7 @@ pub struct PresentationModelRust {
|
||||||
highest_id: i32,
|
highest_id: i32,
|
||||||
presentations: Vec<Presentation>,
|
presentations: Vec<Presentation>,
|
||||||
inner_presentations: Vec<Presentation>,
|
inner_presentations: Vec<Presentation>,
|
||||||
db: SqliteConnection
|
db: SqliteConnection,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PresentationModelRust {
|
impl Default for PresentationModelRust {
|
||||||
|
@ -226,14 +226,18 @@ impl Default for PresentationModelRust {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_presentation(index: i32) -> color_eyre::Result<Presentation> {
|
pub fn get_presentation(
|
||||||
|
index: i32,
|
||||||
|
) -> color_eyre::Result<Presentation> {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
let mut db = {
|
let mut db = {
|
||||||
let mut data = dirs::data_local_dir().unwrap();
|
let mut data = dirs::data_local_dir().unwrap();
|
||||||
|
@ -242,11 +246,13 @@ pub fn get_presentation(index: i32) -> color_eyre::Result<Presentation> {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Presentation, r#"SELECT id as "id: i32", title as "title!", filePath as "path!", html as "html!", pageCount as "page_count!: i32" from presentations where id = ?"#, index).fetch_one(&mut db).await?;
|
let result = query_as!(Presentation, r#"SELECT id as "id: i32", title as "title!", file_path as "path!", html as "html!", pageCount as "page_count!: i32" from presentations where id = ?"#, index).fetch_one(&mut db).await?;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -263,7 +269,7 @@ impl presentation_model::PresentationModel {
|
||||||
pub fn setup(mut self: Pin<&mut Self>) {
|
pub fn setup(mut self: Pin<&mut Self>) {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Presentation, r#"SELECT id as "id: i32", title as "title!", filePath as "path!", html as "html!", pageCount as "page_count!: i32" from presentations"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
let result = query_as!(Presentation, r#"SELECT id as "id: i32", title as "title!", file_path as "path!", html as "html!", pageCount as "page_count!: i32" from presentations"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(p) => p.into_iter().for_each(|p| self.as_mut().add_presentation(p)),
|
Ok(p) => p.into_iter().for_each(|p| self.as_mut().add_presentation(p)),
|
||||||
Err(e) => error!("There was an error in converting songs: {e}"),
|
Err(e) => error!("There was an error in converting songs: {e}"),
|
||||||
|
@ -278,7 +284,12 @@ impl presentation_model::PresentationModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("delete from presentations where id = ?", index).execute(&mut self.as_mut().rust_mut().db).await;
|
let result = query!(
|
||||||
|
"delete from presentations where id = ?",
|
||||||
|
index
|
||||||
|
)
|
||||||
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
|
.await;
|
||||||
match result {
|
match result {
|
||||||
Ok(_i) => {
|
Ok(_i) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -365,7 +376,7 @@ impl presentation_model::PresentationModel {
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let presentation_title = presentation_title.to_string();
|
let presentation_title = presentation_title.to_string();
|
||||||
let presentation_path = presentation_path.to_string();
|
let presentation_path = presentation_path.to_string();
|
||||||
let result = query!(r#"INSERT into presentations (id, title, filePath, html, pageCount) VALUES (?, ?, ?, ?, ?)"#,
|
let result = query!(r#"INSERT into presentations (id, title, file_path, html, pageCount) VALUES (?, ?, ?, ?, ?)"#,
|
||||||
presentation_id,
|
presentation_id,
|
||||||
presentation_title,
|
presentation_title,
|
||||||
presentation_path,
|
presentation_path,
|
||||||
|
@ -503,7 +514,11 @@ impl presentation_model::PresentationModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let title = updated_title.to_string();
|
let title = updated_title.to_string();
|
||||||
let result = query!("UPDATE presentations SET title = ? where id = ?", title, index)
|
let result = query!(
|
||||||
|
"UPDATE presentations SET title = ? where id = ?",
|
||||||
|
title,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -516,9 +531,11 @@ impl presentation_model::PresentationModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
presentation.title = title.clone();
|
presentation.title = title.clone();
|
||||||
debug!(title = presentation.title,
|
debug!(
|
||||||
|
title = presentation.title,
|
||||||
title = title,
|
title = title,
|
||||||
"updated presentation title");
|
"updated presentation title"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -530,7 +547,7 @@ impl presentation_model::PresentationModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -549,7 +566,11 @@ impl presentation_model::PresentationModel {
|
||||||
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE presentations SET pageCount = ? where id = ?", updated_page_count, index)
|
let result = query!(
|
||||||
|
"UPDATE presentations SET pageCount = ? where id = ?",
|
||||||
|
updated_page_count,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -561,10 +582,13 @@ impl presentation_model::PresentationModel {
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
presentation.page_count = updated_page_count.clone();
|
presentation.page_count =
|
||||||
debug!(title = presentation.title,
|
updated_page_count.clone();
|
||||||
|
debug!(
|
||||||
|
title = presentation.title,
|
||||||
page_count = updated_page_count,
|
page_count = updated_page_count,
|
||||||
"updated presentation page_count");
|
"updated presentation page_count"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -576,7 +600,7 @@ impl presentation_model::PresentationModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
|
|
@ -271,7 +271,12 @@ mod service_item_model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use self::service_item_model::{
|
||||||
|
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
|
||||||
|
ServiceRoles,
|
||||||
|
};
|
||||||
use crate::service_item_model::service_item_model::QList_QString;
|
use crate::service_item_model::service_item_model::QList_QString;
|
||||||
|
use crate::slide_types::SlideType;
|
||||||
use crate::songs::song_model::{get_song, Song};
|
use crate::songs::song_model::{get_song, Song};
|
||||||
use crate::{image_model, presentation_model, video_model};
|
use crate::{image_model, presentation_model, video_model};
|
||||||
use cxx_qt::{CxxQtType, Threading};
|
use cxx_qt::{CxxQtType, Threading};
|
||||||
|
@ -279,6 +284,7 @@ use cxx_qt_lib::{
|
||||||
QByteArray, QModelIndex, QString, QStringList, QUrl, QVariant,
|
QByteArray, QModelIndex, QString, QStringList, QUrl, QVariant,
|
||||||
};
|
};
|
||||||
use dirs;
|
use dirs;
|
||||||
|
// use lumina_core::service_items::ServiceItem as SI;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
@ -288,12 +294,6 @@ use std::{fs, println};
|
||||||
use tar::{Archive, Builder};
|
use tar::{Archive, Builder};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
use zstd::{Decoder, Encoder};
|
use zstd::{Decoder, Encoder};
|
||||||
use self::service_item_model::{
|
|
||||||
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
|
|
||||||
ServiceRoles,
|
|
||||||
};
|
|
||||||
use crate::slide_types::SlideType;
|
|
||||||
use lumina_core::service_items::ServiceItem as SI;
|
|
||||||
|
|
||||||
use super::service_item_model::service_item_model::ServiceItemModel;
|
use super::service_item_model::service_item_model::ServiceItemModel;
|
||||||
|
|
||||||
|
@ -377,7 +377,9 @@ impl service_item_model::ServiceItemModel {
|
||||||
pub fn remove_items(mut self: Pin<&mut Self>) {
|
pub fn remove_items(mut self: Pin<&mut Self>) {
|
||||||
let mut indices = vec![];
|
let mut indices = vec![];
|
||||||
let mut items = self.service_items.clone();
|
let mut items = self.service_items.clone();
|
||||||
for (index, _item) in items.iter_mut().enumerate().filter(|(_y, x)| x.selected) {
|
for (index, _item) in
|
||||||
|
items.iter_mut().enumerate().filter(|(_y, x)| x.selected)
|
||||||
|
{
|
||||||
let index = index as i32;
|
let index = index as i32;
|
||||||
indices.push(index);
|
indices.push(index);
|
||||||
}
|
}
|
||||||
|
@ -436,7 +438,10 @@ impl service_item_model::ServiceItemModel {
|
||||||
self.as_mut().end_insert_rows();
|
self.as_mut().end_insert_rows();
|
||||||
}
|
}
|
||||||
debug!("ADDING: {:?}", &service_item);
|
debug!("ADDING: {:?}", &service_item);
|
||||||
self.as_mut().item_added(&service_item.database_id.unwrap_or_default(), &QString::from(&service_item.ty.to_string()));
|
self.as_mut().item_added(
|
||||||
|
&service_item.database_id.unwrap_or_default(),
|
||||||
|
&QString::from(&service_item.ty.to_string()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_item(
|
pub fn insert_item(
|
||||||
|
@ -475,7 +480,11 @@ impl service_item_model::ServiceItemModel {
|
||||||
self.as_mut().end_insert_rows();
|
self.as_mut().end_insert_rows();
|
||||||
}
|
}
|
||||||
debug!("ADDING: {:?}", &service_item);
|
debug!("ADDING: {:?}", &service_item);
|
||||||
self.as_mut().item_inserted(&index, &service_item.database_id.unwrap_or_default(), &QString::from(&service_item.ty.to_string()));
|
self.as_mut().item_inserted(
|
||||||
|
&index,
|
||||||
|
&service_item.database_id.unwrap_or_default(),
|
||||||
|
&QString::from(&service_item.ty.to_string()),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_item(
|
pub fn get_item(
|
||||||
|
@ -876,8 +885,7 @@ impl service_item_model::ServiceItemModel {
|
||||||
Some(name) => {
|
Some(name) => {
|
||||||
println!("audio: {:?}", &name);
|
println!("audio: {:?}", &name);
|
||||||
if name.to_str().unwrap() != "temp" {
|
if name.to_str().unwrap() != "temp" {
|
||||||
flat_audio =
|
flat_audio = name.to_str().unwrap()
|
||||||
name.to_str().unwrap()
|
|
||||||
} else {
|
} else {
|
||||||
flat_audio = "";
|
flat_audio = "";
|
||||||
}
|
}
|
||||||
|
@ -961,12 +969,18 @@ impl service_item_model::ServiceItemModel {
|
||||||
debug!(time = ?now.elapsed(), "file written");
|
debug!(time = ?now.elapsed(), "file written");
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
debug!(time = ?now.elapsed(), "idk");
|
debug!(time = ?now.elapsed(), "idk");
|
||||||
let dir = fs::read_dir(&temp_dir).expect("idk");
|
let dir = fs::read_dir(&temp_dir)
|
||||||
|
.expect("idk");
|
||||||
for (index, file) in dir.enumerate() {
|
for (index, file) in dir.enumerate() {
|
||||||
if let Ok(file) = file {
|
if let Ok(file) = file {
|
||||||
let file_name = file.file_name();
|
let file_name =
|
||||||
|
file.file_name();
|
||||||
debug!(?file, ?file_name);
|
debug!(?file, ?file_name);
|
||||||
let mut file = std::fs::File::open(file.path()).expect("missing file");
|
let mut file =
|
||||||
|
std::fs::File::open(
|
||||||
|
file.path(),
|
||||||
|
)
|
||||||
|
.expect("missing file");
|
||||||
tar.append_file(file_name, &mut file).expect("Error in moving file to tar");
|
tar.append_file(file_name, &mut file).expect("Error in moving file to tar");
|
||||||
thread.queue(move |mut service| {
|
thread.queue(move |mut service| {
|
||||||
service
|
service
|
||||||
|
@ -977,10 +991,11 @@ impl service_item_model::ServiceItemModel {
|
||||||
)
|
)
|
||||||
}).expect("Problem queuing on cxx thread");
|
}).expect("Problem queuing on cxx thread");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if let Ok(encoder) = tar.into_inner() {
|
if let Ok(encoder) = tar.into_inner()
|
||||||
if let Ok(done) = encoder.finish() {
|
{
|
||||||
|
if let Ok(done) = encoder.finish()
|
||||||
|
{
|
||||||
debug!(time = ?now.elapsed(), ?done, "tar finished");
|
debug!(time = ?now.elapsed(), ?done, "tar finished");
|
||||||
thread.queue(move |mut service| {
|
thread.queue(move |mut service| {
|
||||||
service.as_mut().set_save_progress(100.0);
|
service.as_mut().set_save_progress(100.0);
|
||||||
|
@ -1000,9 +1015,7 @@ impl service_item_model::ServiceItemModel {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fs::remove_dir_all(&temp_dir)
|
fs::remove_dir_all(&temp_dir)
|
||||||
.expect(
|
.expect("error in removal");
|
||||||
"error in removal",
|
|
||||||
);
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1058,7 +1071,9 @@ impl service_item_model::ServiceItemModel {
|
||||||
if !file_path.exists() {
|
if !file_path.exists() {
|
||||||
match file.unpack_in(&datadir) {
|
match file.unpack_in(&datadir) {
|
||||||
Ok(_t) => (),
|
Ok(_t) => (),
|
||||||
Err(e) => error!("Error unpacking archive: {}", e),
|
Err(e) => {
|
||||||
|
error!("Error unpacking archive: {}", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1341,7 +1356,9 @@ impl service_item_model::ServiceItemModel {
|
||||||
let mut vector_roles = QVector_i32::default();
|
let mut vector_roles = QVector_i32::default();
|
||||||
vector_roles.append(self.as_ref().get_role(role));
|
vector_roles.append(self.as_ref().get_role(role));
|
||||||
if let Some(index) =
|
if let Some(index) =
|
||||||
self.as_ref().service_items.iter().position(|x| x.database_id.unwrap_or_default() == item_id)
|
self.as_ref().service_items.iter().position(|x| {
|
||||||
|
x.database_id.unwrap_or_default() == item_id
|
||||||
|
})
|
||||||
{
|
{
|
||||||
let model_index = self.as_ref().index(
|
let model_index = self.as_ref().index(
|
||||||
index as i32,
|
index as i32,
|
||||||
|
@ -1355,7 +1372,6 @@ impl service_item_model::ServiceItemModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn load_last_saved(self: Pin<&mut Self>) -> bool {
|
pub fn load_last_saved(self: Pin<&mut Self>) -> bool {
|
||||||
todo!();
|
todo!();
|
||||||
// Don't actually need
|
// Don't actually need
|
||||||
|
@ -1394,9 +1410,9 @@ impl service_item_model::ServiceItemModel {
|
||||||
ServiceRoles::Name => {
|
ServiceRoles::Name => {
|
||||||
QVariant::from(&service_item.name)
|
QVariant::from(&service_item.name)
|
||||||
}
|
}
|
||||||
ServiceRoles::Type => {
|
ServiceRoles::Type => QVariant::from(&QString::from(
|
||||||
QVariant::from(&QString::from(&service_item.ty.clone().to_string()))
|
&service_item.ty.clone().to_string(),
|
||||||
}
|
)),
|
||||||
ServiceRoles::Audio => {
|
ServiceRoles::Audio => {
|
||||||
QVariant::from(&service_item.audio)
|
QVariant::from(&service_item.audio)
|
||||||
}
|
}
|
||||||
|
@ -1433,9 +1449,9 @@ impl service_item_model::ServiceItemModel {
|
||||||
ServiceRoles::VideoEndTime => {
|
ServiceRoles::VideoEndTime => {
|
||||||
QVariant::from(&service_item.video_end_time)
|
QVariant::from(&service_item.video_end_time)
|
||||||
}
|
}
|
||||||
ServiceRoles::Id => {
|
ServiceRoles::Id => QVariant::from(
|
||||||
QVariant::from(&service_item.database_id.unwrap_or_default())
|
&service_item.database_id.unwrap_or_default(),
|
||||||
}
|
),
|
||||||
_ => QVariant::default(),
|
_ => QVariant::default(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1503,22 +1519,21 @@ impl service_item_model::ServiceItemModel {
|
||||||
ServiceRoles::VideoEndTime.repr,
|
ServiceRoles::VideoEndTime.repr,
|
||||||
QByteArray::from("videoEndTime"),
|
QByteArray::from("videoEndTime"),
|
||||||
);
|
);
|
||||||
roles.insert(
|
roles.insert(ServiceRoles::Id.repr, QByteArray::from("id"));
|
||||||
ServiceRoles::Id.repr,
|
|
||||||
QByteArray::from("id"),
|
|
||||||
);
|
|
||||||
roles
|
roles
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn row_count(&self, _parent: &QModelIndex) -> i32 {
|
pub fn row_count(&self, _parent: &QModelIndex) -> i32 {
|
||||||
|
|
||||||
// println!("row count is {cnt}");
|
// println!("row count is {cnt}");
|
||||||
self.service_items.len() as i32
|
self.service_items.len() as i32
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceItemModelRust {
|
impl ServiceItemModelRust {
|
||||||
pub fn save(_model: Pin<&mut ServiceItemModel>, _file: QUrl) -> bool {
|
pub fn save(
|
||||||
|
_model: Pin<&mut ServiceItemModel>,
|
||||||
|
_file: QUrl,
|
||||||
|
) -> bool {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,11 @@ pub mod slide_model {
|
||||||
include!("cxx-qt-lib/qlist.h");
|
include!("cxx-qt-lib/qlist.h");
|
||||||
type QList_QString = cxx_qt_lib::QList<QString>;
|
type QList_QString = cxx_qt_lib::QList<QString>;
|
||||||
include!("cxx-qt-gen/slide_object.cxxqt.h");
|
include!("cxx-qt-gen/slide_object.cxxqt.h");
|
||||||
type SlideObject = crate::slide_object::slide_object::SlideObject;
|
type SlideObject =
|
||||||
|
crate::slide_object::slide_object::SlideObject;
|
||||||
include!("cxx-qt-gen/song_model.cxxqt.h");
|
include!("cxx-qt-gen/song_model.cxxqt.h");
|
||||||
type SongModel = crate::songs::song_model::song_model::SongModel;
|
type SongModel =
|
||||||
|
crate::songs::song_model::song_model::SongModel;
|
||||||
include!("cxx-qt-gen/video_model.cxxqt.h");
|
include!("cxx-qt-gen/video_model.cxxqt.h");
|
||||||
type VideoModel = crate::video_model::video_model::VideoModel;
|
type VideoModel = crate::video_model::video_model::VideoModel;
|
||||||
include!("cxx-qt-gen/image_model.cxxqt.h");
|
include!("cxx-qt-gen/image_model.cxxqt.h");
|
||||||
|
@ -229,26 +231,29 @@ pub mod slide_model {
|
||||||
|
|
||||||
use crate::image_model::image_model::ImageModel;
|
use crate::image_model::image_model::ImageModel;
|
||||||
use crate::image_model::{self, Image, ImageModelRust};
|
use crate::image_model::{self, Image, ImageModelRust};
|
||||||
|
use crate::obs::Obs;
|
||||||
use crate::presentation_model::presentation_model::PresentationModel;
|
use crate::presentation_model::presentation_model::PresentationModel;
|
||||||
use crate::presentation_model::{self, Presentation, PresentationModelRust};
|
use crate::presentation_model::{
|
||||||
|
self, Presentation, PresentationModelRust,
|
||||||
|
};
|
||||||
|
use crate::slide_model::slide_model::QList_QString;
|
||||||
use crate::songs::song_model::song_model::{self, SongModel};
|
use crate::songs::song_model::song_model::{self, SongModel};
|
||||||
use crate::songs::song_model::{get_song, Song, SongModelRust};
|
use crate::songs::song_model::{get_song, Song, SongModelRust};
|
||||||
use crate::video_model::video_model::VideoModel;
|
use crate::video_model::video_model::VideoModel;
|
||||||
use crate::video_model::{self, Video, VideoModelRust};
|
use crate::video_model::{self, Video, VideoModelRust};
|
||||||
use crate::{ffmpeg, slide_types::SlideType};
|
use crate::{ffmpeg, slide_types::SlideType};
|
||||||
use crate::obs::Obs;
|
|
||||||
use crate::slide_model::slide_model::QList_QString;
|
|
||||||
use color_eyre::eyre::Result;
|
use color_eyre::eyre::Result;
|
||||||
use color_eyre::Section;
|
use color_eyre::Section;
|
||||||
use cxx_qt::{CxxQtType, Threading};
|
use cxx_qt::{CxxQtType, Threading};
|
||||||
use cxx_qt_lib::{
|
use cxx_qt_lib::{
|
||||||
CaseSensitivity, QByteArray, QList, QModelIndex, QString, QStringList, QVariant
|
CaseSensitivity, QByteArray, QList, QModelIndex, QString,
|
||||||
|
QStringList, QVariant,
|
||||||
};
|
};
|
||||||
use slide_model::SlideObject;
|
use slide_model::SlideObject;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt::{Display};
|
use std::fmt::Display;
|
||||||
use std::{path::PathBuf, pin::Pin};
|
use std::{path::PathBuf, pin::Pin};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
use self::slide_model::{
|
use self::slide_model::{
|
||||||
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
|
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
|
||||||
|
@ -336,45 +341,40 @@ impl Slide {
|
||||||
fn slides_from_song(song: Song) -> Result<Vec<Self>> {
|
fn slides_from_song(song: Song) -> Result<Vec<Self>> {
|
||||||
let list = song.get_lyric_list();
|
let list = song.get_lyric_list();
|
||||||
let total = list.len();
|
let total = list.len();
|
||||||
let mut vector: Vec<Slide> = vec![];
|
let vector = list
|
||||||
list.iter().map(|t| t.to_string()).enumerate()
|
.iter()
|
||||||
.for_each(|(i, s)| {
|
.map(|t| {
|
||||||
if song.background_type == "image" {
|
let s = t.to_string();
|
||||||
vector.push(
|
warn!(s);
|
||||||
Self {
|
s
|
||||||
|
})
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, s)| Self {
|
||||||
text: s,
|
text: s,
|
||||||
ty: SlideType::Song,
|
ty: SlideType::Song,
|
||||||
audio: song.audio.clone(),
|
audio: song.audio.clone(),
|
||||||
image_background: song.background.clone(),
|
image_background: if song.background_type == "image" {
|
||||||
video_background: "".to_owned(),
|
song.background.clone()
|
||||||
htext_alignment: song.horizontal_text_alignment.clone(),
|
|
||||||
vtext_alignment: song.vertical_text_alignment.clone(),
|
|
||||||
font: song.font.clone(),
|
|
||||||
font_size: song.font_size,
|
|
||||||
slide_count: total as i32,
|
|
||||||
slide_index: i as i32,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
vector.push(
|
"".into()
|
||||||
Self {
|
},
|
||||||
text: s,
|
video_background: if song.background_type == "video" {
|
||||||
ty: SlideType::Song,
|
song.background.clone()
|
||||||
audio: song.audio.clone(),
|
} else {
|
||||||
image_background: "".to_owned(),
|
"".to_owned()
|
||||||
video_background: song.background.clone(),
|
},
|
||||||
htext_alignment: song.horizontal_text_alignment.clone(),
|
htext_alignment: song
|
||||||
|
.horizontal_text_alignment
|
||||||
|
.clone(),
|
||||||
vtext_alignment: song.vertical_text_alignment.clone(),
|
vtext_alignment: song.vertical_text_alignment.clone(),
|
||||||
font: song.font.clone(),
|
font: song.font.clone(),
|
||||||
font_size: song.font_size,
|
font_size: song.font_size,
|
||||||
slide_count: total as i32,
|
slide_count: total as i32,
|
||||||
slide_index: i as i32,
|
slide_index: i as i32,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
})
|
||||||
)
|
.collect();
|
||||||
}
|
warn!(?vector);
|
||||||
});
|
|
||||||
Ok(vector)
|
Ok(vector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -395,7 +395,9 @@ impl Slide {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slides_from_presentation(presentation: Presentation) -> Result<Vec<Self>> {
|
fn slides_from_presentation(
|
||||||
|
presentation: Presentation,
|
||||||
|
) -> Result<Vec<Self>> {
|
||||||
let total = presentation.page_count;
|
let total = presentation.page_count;
|
||||||
let mut slides: Vec<Slide> = vec![];
|
let mut slides: Vec<Slide> = vec![];
|
||||||
for i in 0..total {
|
for i in 0..total {
|
||||||
|
@ -406,7 +408,7 @@ impl Slide {
|
||||||
image_background: presentation.path.clone(),
|
image_background: presentation.path.clone(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
};
|
}
|
||||||
Ok(slides)
|
Ok(slides)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -456,9 +458,12 @@ impl slide_model::SlideModel {
|
||||||
index: i32,
|
index: i32,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let mut vector_roles = QVector_i32::default();
|
let mut vector_roles = QVector_i32::default();
|
||||||
vector_roles.append(self.get_role(SlideRoles::VideoThumbnail));
|
vector_roles
|
||||||
vector_roles.append(self.get_role(SlideRoles::VideoBackground));
|
.append(self.get_role(SlideRoles::VideoThumbnail));
|
||||||
vector_roles.append(self.get_role(SlideRoles::ImageBackground));
|
vector_roles
|
||||||
|
.append(self.get_role(SlideRoles::VideoBackground));
|
||||||
|
vector_roles
|
||||||
|
.append(self.get_role(SlideRoles::ImageBackground));
|
||||||
let rc = self.as_ref().count() - 1;
|
let rc = self.as_ref().count() - 1;
|
||||||
let tl = self.as_ref().index(0, 0, &QModelIndex::default());
|
let tl = self.as_ref().index(0, 0, &QModelIndex::default());
|
||||||
let br = self.as_ref().index(rc, 0, &QModelIndex::default());
|
let br = self.as_ref().index(rc, 0, &QModelIndex::default());
|
||||||
|
@ -470,7 +475,11 @@ impl slide_model::SlideModel {
|
||||||
let path =
|
let path =
|
||||||
PathBuf::from(slide.video_background.to_string());
|
PathBuf::from(slide.video_background.to_string());
|
||||||
let screenshot = ffmpeg::bg_path_from_video(&path);
|
let screenshot = ffmpeg::bg_path_from_video(&path);
|
||||||
let mut screenshot_string = screenshot.clone().into_os_string().into_string().unwrap_or_default();
|
let mut screenshot_string = screenshot
|
||||||
|
.clone()
|
||||||
|
.into_os_string()
|
||||||
|
.into_string()
|
||||||
|
.unwrap_or_default();
|
||||||
screenshot_string.insert_str(0, "file://");
|
screenshot_string.insert_str(0, "file://");
|
||||||
slide.video_thumbnail = screenshot_string;
|
slide.video_thumbnail = screenshot_string;
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
|
@ -616,37 +625,56 @@ impl slide_model::SlideModel {
|
||||||
SlideType::Song => {
|
SlideType::Song => {
|
||||||
let song = get_song(item_model_id)?;
|
let song = get_song(item_model_id)?;
|
||||||
let slides = Slide::slides_from_song(song)?;
|
let slides = Slide::slides_from_song(song)?;
|
||||||
slides.iter().for_each(|slide| self.as_mut().insert_slide(slide, index));
|
slides.iter().enumerate().for_each(|(i, slide)| {
|
||||||
|
self.as_mut()
|
||||||
|
.insert_slide(slide, index + i as i32)
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
SlideType::Video => {
|
SlideType::Video => {
|
||||||
let video = video_model::get_video(item_model_id)?;
|
let video = video_model::get_video(item_model_id)?;
|
||||||
self.insert_slide(&Slide::slide_from_video(video)?, index);
|
self.insert_slide(
|
||||||
|
&Slide::slide_from_video(video)?,
|
||||||
|
index,
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
SlideType::Image => {
|
SlideType::Image => {
|
||||||
let result = image_model::get_image(item_model_id);
|
let result = image_model::get_image(item_model_id);
|
||||||
match result {
|
match result {
|
||||||
Ok(image) => self.insert_slide(&Slide::slide_from_image(image)?, index),
|
Ok(image) => self.insert_slide(
|
||||||
|
&Slide::slide_from_image(image)?,
|
||||||
|
index,
|
||||||
|
),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
e.with_note(|| {
|
e.with_note(|| {
|
||||||
format!("This might fail if we are loading the items from a file")
|
format!("This might fail if we are loading the items from a file")
|
||||||
});
|
});
|
||||||
let mut slide = Slide::default();
|
let mut slide = Slide::default();
|
||||||
slide.image_background = "qrc:/assets/black.jpg".to_owned();
|
slide.image_background =
|
||||||
|
"qrc:/assets/black.jpg".to_owned();
|
||||||
self.insert_slide(&slide, index);
|
self.insert_slide(&slide, index);
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
SlideType::Content => {
|
SlideType::Content => {
|
||||||
todo!();
|
todo!();
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
}
|
||||||
SlideType::Presentation(_) => {
|
SlideType::Presentation(_) => {
|
||||||
let presentation = presentation_model::get_presentation(item_model_id)?;
|
let presentation =
|
||||||
let slides = Slide::slides_from_presentation(presentation)?;
|
presentation_model::get_presentation(
|
||||||
slides.iter().for_each(|slide| self.as_mut().insert_slide(slide, slide.slide_index + index));
|
item_model_id,
|
||||||
|
)?;
|
||||||
|
let slides =
|
||||||
|
Slide::slides_from_presentation(presentation)?;
|
||||||
|
slides.iter().for_each(|slide| {
|
||||||
|
self.as_mut().insert_slide(
|
||||||
|
slide,
|
||||||
|
slide.slide_index + index,
|
||||||
|
)
|
||||||
|
});
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -692,7 +720,8 @@ impl slide_model::SlideModel {
|
||||||
|
|
||||||
if let Some((i, slide)) = slides_iter
|
if let Some((i, slide)) = slides_iter
|
||||||
.clone()
|
.clone()
|
||||||
.enumerate().find(|slide| slide.1.service_item_id == source_index)
|
.enumerate()
|
||||||
|
.find(|slide| slide.1.service_item_id == source_index)
|
||||||
{
|
{
|
||||||
debug!(index = i, ?slide);
|
debug!(index = i, ?slide);
|
||||||
first_slide = i as i32;
|
first_slide = i as i32;
|
||||||
|
@ -705,11 +734,8 @@ impl slide_model::SlideModel {
|
||||||
|
|
||||||
// lets get the dest_slide and count
|
// lets get the dest_slide and count
|
||||||
if move_down {
|
if move_down {
|
||||||
if let Some((i, slide)) = slides_iter
|
if let Some((i, slide)) =
|
||||||
.clone()
|
slides_iter.clone().enumerate().rev().find(|slide| {
|
||||||
.enumerate()
|
|
||||||
.rev()
|
|
||||||
.find(|slide| {
|
|
||||||
slide.1.service_item_id == destination_index
|
slide.1.service_item_id == destination_index
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
@ -724,9 +750,8 @@ impl slide_model::SlideModel {
|
||||||
dest_slide, dest_count
|
dest_slide, dest_count
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if let Some((i, slide)) = slides_iter
|
} else if let Some((i, slide)) =
|
||||||
.enumerate()
|
slides_iter.enumerate().find(|slide| {
|
||||||
.find(|slide| {
|
|
||||||
slide.1.service_item_id == destination_index
|
slide.1.service_item_id == destination_index
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
@ -1001,7 +1026,8 @@ impl slide_model::SlideModel {
|
||||||
debug!(service_item = index, "Getting slide from this item");
|
debug!(service_item = index, "Getting slide from this item");
|
||||||
let mut id = 0;
|
let mut id = 0;
|
||||||
if let Some((i, slide)) = slides_iter
|
if let Some((i, slide)) = slides_iter
|
||||||
.enumerate().find(|(_i, slide)| slide.service_item_id == index)
|
.enumerate()
|
||||||
|
.find(|(_i, slide)| slide.service_item_id == index)
|
||||||
{
|
{
|
||||||
debug!(slide_id = i, ?slide);
|
debug!(slide_id = i, ?slide);
|
||||||
id = i as i32;
|
id = i as i32;
|
||||||
|
@ -1105,7 +1131,6 @@ impl slide_model::SlideModel {
|
||||||
(0, QModelIndex::default(), vector_roles)
|
(0, QModelIndex::default(), vector_roles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QAbstractListModel implementation
|
// QAbstractListModel implementation
|
||||||
|
@ -1114,22 +1139,30 @@ impl slide_model::SlideModel {
|
||||||
let role = SlideRoles { repr: role };
|
let role = SlideRoles { repr: role };
|
||||||
if let Some(slide) = self.slides.get(index.row() as usize) {
|
if let Some(slide) = self.slides.get(index.row() as usize) {
|
||||||
return match role {
|
return match role {
|
||||||
SlideRoles::Ty => QVariant::from(&QString::from(&slide.ty.to_string())),
|
SlideRoles::Ty => QVariant::from(&QString::from(
|
||||||
SlideRoles::Text => QVariant::from(&QString::from(&slide.text)),
|
&slide.ty.to_string(),
|
||||||
SlideRoles::Audio => QVariant::from(&QString::from(&slide.audio)),
|
)),
|
||||||
SlideRoles::ImageBackground => {
|
SlideRoles::Text => {
|
||||||
QVariant::from(&QString::from(&slide.image_background))
|
QVariant::from(&QString::from(&slide.text))
|
||||||
}
|
}
|
||||||
SlideRoles::VideoBackground => {
|
SlideRoles::Audio => {
|
||||||
QVariant::from(&QString::from(&slide.video_background))
|
QVariant::from(&QString::from(&slide.audio))
|
||||||
}
|
}
|
||||||
SlideRoles::HTextAlignment => {
|
SlideRoles::ImageBackground => QVariant::from(
|
||||||
QVariant::from(&QString::from(&slide.htext_alignment))
|
&QString::from(&slide.image_background),
|
||||||
|
),
|
||||||
|
SlideRoles::VideoBackground => QVariant::from(
|
||||||
|
&QString::from(&slide.video_background),
|
||||||
|
),
|
||||||
|
SlideRoles::HTextAlignment => QVariant::from(
|
||||||
|
&QString::from(&slide.htext_alignment),
|
||||||
|
),
|
||||||
|
SlideRoles::VTextAlignment => QVariant::from(
|
||||||
|
&QString::from(&slide.vtext_alignment),
|
||||||
|
),
|
||||||
|
SlideRoles::Font => {
|
||||||
|
QVariant::from(&QString::from(&slide.font))
|
||||||
}
|
}
|
||||||
SlideRoles::VTextAlignment => {
|
|
||||||
QVariant::from(&QString::from(&slide.vtext_alignment))
|
|
||||||
}
|
|
||||||
SlideRoles::Font => QVariant::from(&QString::from(&slide.font)),
|
|
||||||
SlideRoles::FontSize => {
|
SlideRoles::FontSize => {
|
||||||
QVariant::from(&slide.font_size)
|
QVariant::from(&slide.font_size)
|
||||||
}
|
}
|
||||||
|
@ -1147,9 +1180,9 @@ impl slide_model::SlideModel {
|
||||||
QVariant::from(&slide.selected)
|
QVariant::from(&slide.selected)
|
||||||
}
|
}
|
||||||
SlideRoles::Looping => QVariant::from(&slide.looping),
|
SlideRoles::Looping => QVariant::from(&slide.looping),
|
||||||
SlideRoles::VideoThumbnail => {
|
SlideRoles::VideoThumbnail => QVariant::from(
|
||||||
QVariant::from(&QString::from(&slide.video_thumbnail))
|
&QString::from(&slide.video_thumbnail),
|
||||||
}
|
),
|
||||||
SlideRoles::VideoStartTime => {
|
SlideRoles::VideoStartTime => {
|
||||||
QVariant::from(&slide.video_start_time)
|
QVariant::from(&slide.video_start_time)
|
||||||
}
|
}
|
||||||
|
@ -1256,7 +1289,8 @@ impl slide_model::SlideModel {
|
||||||
fn extract_string(item: &QMap_QString_QVariant, key: &str) -> String {
|
fn extract_string(item: &QMap_QString_QVariant, key: &str) -> String {
|
||||||
item.get(&QString::from(key))
|
item.get(&QString::from(key))
|
||||||
.unwrap_or(QVariant::from(&QString::default()))
|
.unwrap_or(QVariant::from(&QString::default()))
|
||||||
.value_or_default::<QString>().to_string()
|
.value_or_default::<QString>()
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_value(item: &QMap_QString_QVariant, key: &str) -> i32 {
|
fn extract_value(item: &QMap_QString_QVariant, key: &str) -> i32 {
|
||||||
|
@ -1277,12 +1311,11 @@ fn extract_bool(item: &QMap_QString_QVariant, key: &str) -> bool {
|
||||||
.value_or_default::<bool>()
|
.value_or_default::<bool>()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
// #[cfg(test)]
|
||||||
mod test {
|
// mod test {
|
||||||
|
|
||||||
|
// #[test]
|
||||||
#[test]
|
// pub fn test_obs_setting_scene() {
|
||||||
pub fn test_obs_setting_scene() {
|
// assert_eq!(true, true)
|
||||||
assert_eq!(true, true)
|
// }
|
||||||
}
|
// }
|
||||||
}
|
|
||||||
|
|
|
@ -89,7 +89,8 @@ use cxx_qt_lib::{CaseSensitivity, QString, QVariant};
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
slide_model::{slide_model, Slide}, slide_types::SlideType
|
slide_model::{slide_model, Slide},
|
||||||
|
slide_types::SlideType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use self::slide_object::QMap_QString_QVariant;
|
use self::slide_object::QMap_QString_QVariant;
|
||||||
|
@ -484,10 +485,18 @@ impl slide_object::SlideObject {
|
||||||
self.as_mut().set_text(QString::from(&slide.text));
|
self.as_mut().set_text(QString::from(&slide.text));
|
||||||
self.as_mut().set_ty(QString::from(&slide.ty.to_string()));
|
self.as_mut().set_ty(QString::from(&slide.ty.to_string()));
|
||||||
self.as_mut().set_audio(QString::from(&slide.audio));
|
self.as_mut().set_audio(QString::from(&slide.audio));
|
||||||
self.as_mut().set_image_background(QString::from(&slide.image_background));
|
self.as_mut().set_image_background(QString::from(
|
||||||
self.as_mut().set_video_background(QString::from(&slide.video_background));
|
&slide.image_background,
|
||||||
self.as_mut().set_vtext_alignment(QString::from(&slide.vtext_alignment));
|
));
|
||||||
self.as_mut().set_htext_alignment(QString::from(&slide.htext_alignment));
|
self.as_mut().set_video_background(QString::from(
|
||||||
|
&slide.video_background,
|
||||||
|
));
|
||||||
|
self.as_mut().set_vtext_alignment(QString::from(
|
||||||
|
&slide.vtext_alignment,
|
||||||
|
));
|
||||||
|
self.as_mut().set_htext_alignment(QString::from(
|
||||||
|
&slide.htext_alignment,
|
||||||
|
));
|
||||||
self.as_mut().set_font(QString::from(&slide.font));
|
self.as_mut().set_font(QString::from(&slide.font));
|
||||||
self.as_mut().set_font_size(slide.font_size);
|
self.as_mut().set_font_size(slide.font_size);
|
||||||
self.as_mut().set_video_start_time(slide.video_start_time);
|
self.as_mut().set_video_start_time(slide.video_start_time);
|
||||||
|
|
|
@ -241,6 +241,7 @@ pub mod song_model {
|
||||||
}
|
}
|
||||||
|
|
||||||
use crate::songs::song_editor::song_editor::QList_QString;
|
use crate::songs::song_editor::song_editor::QList_QString;
|
||||||
|
use color_eyre::Result;
|
||||||
use cxx_qt::{CxxQtType, Threading};
|
use cxx_qt::{CxxQtType, Threading};
|
||||||
use cxx_qt_lib::{
|
use cxx_qt_lib::{
|
||||||
QByteArray, QModelIndex, QString, QStringList, QVariant,
|
QByteArray, QModelIndex, QString, QStringList, QVariant,
|
||||||
|
@ -249,7 +250,6 @@ use sqlx::{query, query_as, Connection, SqliteConnection};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use tracing::{debug, error};
|
use tracing::{debug, error};
|
||||||
use color_eyre::Result;
|
|
||||||
|
|
||||||
use self::song_model::{
|
use self::song_model::{
|
||||||
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
|
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
|
||||||
|
@ -293,15 +293,13 @@ impl Song {
|
||||||
}
|
}
|
||||||
let raw_lyrics = self.lyrics.clone();
|
let raw_lyrics = self.lyrics.clone();
|
||||||
println!("raw-lyrics: {:?}", raw_lyrics);
|
println!("raw-lyrics: {:?}", raw_lyrics);
|
||||||
let vorder: Vec<&str> =
|
let vorder: Vec<&str> = self.verse_order.split(' ').collect();
|
||||||
self.verse_order.split(' ').collect();
|
|
||||||
let keywords = vec![
|
let keywords = vec![
|
||||||
"Verse 1", "Verse 2", "Verse 3", "Verse 4",
|
"Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5",
|
||||||
"Verse 5", "Verse 6", "Verse 7", "Verse 8",
|
"Verse 6", "Verse 7", "Verse 8", "Chorus 1", "Chorus 2",
|
||||||
"Chorus 1", "Chorus 2", "Chorus 3", "Chorus 4",
|
"Chorus 3", "Chorus 4", "Bridge 1", "Bridge 2",
|
||||||
"Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4",
|
"Bridge 3", "Bridge 4", "Intro 1", "Intro 2", "Ending 1",
|
||||||
"Intro 1", "Intro 2", "Ending 1", "Ending 2",
|
"Ending 2", "Other 1", "Other 2", "Other 3", "Other 4",
|
||||||
"Other 1", "Other 2", "Other 3", "Other 4",
|
|
||||||
];
|
];
|
||||||
let _first_item = true;
|
let _first_item = true;
|
||||||
|
|
||||||
|
@ -335,10 +333,8 @@ impl Song {
|
||||||
let mut verse_name = "";
|
let mut verse_name = "";
|
||||||
// debug!(verse = verse);
|
// debug!(verse = verse);
|
||||||
for word in keywords.clone() {
|
for word in keywords.clone() {
|
||||||
let end_verse =
|
let end_verse = verse.get(1..2).unwrap_or_default();
|
||||||
verse.get(1..2).unwrap_or_default();
|
let beg_verse = verse.get(0..1).unwrap_or_default();
|
||||||
let beg_verse =
|
|
||||||
verse.get(0..1).unwrap_or_default();
|
|
||||||
// println!(
|
// println!(
|
||||||
// "verse: {:?}, beginning: {:?}, end: {:?}, word: {:?}",
|
// "verse: {:?}, beginning: {:?}, end: {:?}, word: {:?}",
|
||||||
// verse, beg_verse, end_verse, word
|
// verse, beg_verse, end_verse, word
|
||||||
|
@ -400,9 +396,11 @@ impl Default for SongModelRust {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,12 +414,14 @@ pub fn get_song(id: i32) -> Result<Song> {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
debug!("getting song with id: {id}");
|
debug!("getting song with id: {id}");
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Song, r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = ?"#, id).fetch_one(&mut db).await?;
|
let result = query_as!(Song, r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#, id).fetch_one(&mut db).await?;
|
||||||
debug!(?result);
|
debug!(?result);
|
||||||
Ok(result)
|
Ok(result)
|
||||||
})
|
})
|
||||||
|
@ -440,7 +440,7 @@ impl song_model::SongModel {
|
||||||
static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
|
static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Song, r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
let result = query_as!(Song, r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(s) => s.into_iter().for_each(|s| self.as_mut().add_song(s)),
|
Ok(s) => s.into_iter().for_each(|s| self.as_mut().add_song(s)),
|
||||||
Err(e) => error!("There was an error in converting songs: {e}"),
|
Err(e) => error!("There was an error in converting songs: {e}"),
|
||||||
|
@ -453,7 +453,13 @@ impl song_model::SongModel {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let song_id = self.as_mut().rust_mut().songs.get(index as usize).unwrap().id;
|
let song_id = self
|
||||||
|
.as_mut()
|
||||||
|
.rust_mut()
|
||||||
|
.songs
|
||||||
|
.get(index as usize)
|
||||||
|
.unwrap()
|
||||||
|
.id;
|
||||||
let thread = self.qt_thread();
|
let thread = self.qt_thread();
|
||||||
let db = &mut self.as_mut().rust_mut().db;
|
let db = &mut self.as_mut().rust_mut().db;
|
||||||
|
|
||||||
|
@ -504,7 +510,7 @@ impl song_model::SongModel {
|
||||||
};
|
};
|
||||||
|
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!(r#"INSERT into songs (vorder, fontSize, backgroundType, horizontalTextAlignment, verticalTextAlignment, title, font, background, lyrics, ccli, author, audio, id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"#,
|
let result = query!(r#"INSERT into songs (verse_order, font_size, background_type, horizontal_text_alignment, vertical_text_alignment, title, font, background, lyrics, ccli, author, audio, id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"#,
|
||||||
song.verse_order,
|
song.verse_order,
|
||||||
song.font_size,
|
song.font_size,
|
||||||
song.background_type,
|
song.background_type,
|
||||||
|
@ -758,7 +764,11 @@ impl song_model::SongModel {
|
||||||
let db_string = updated_ccli.clone().to_string();
|
let db_string = updated_ccli.clone().to_string();
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE songs SET ccli = ? where id = ?", db_string, song_id)
|
let result = query!(
|
||||||
|
"UPDATE songs SET ccli = ? where id = ?",
|
||||||
|
db_string,
|
||||||
|
song_id
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -783,9 +793,11 @@ impl song_model::SongModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("There was an error updating ccli in db: {e}");
|
error!(
|
||||||
|
"There was an error updating ccli in db: {e}"
|
||||||
|
);
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -802,7 +814,7 @@ impl song_model::SongModel {
|
||||||
let db_string = updated_verse_order.clone().to_string();
|
let db_string = updated_verse_order.clone().to_string();
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE songs SET vorder = ? where id = ?", db_string, song_id)
|
let result = query!("UPDATE songs SET verse_order = ? where id = ?", db_string, song_id)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -891,7 +903,7 @@ impl song_model::SongModel {
|
||||||
let db_string = updated_background_type.clone().to_string();
|
let db_string = updated_background_type.clone().to_string();
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE songs SET backgroundType = ? where id = ?", db_string, song_id)
|
let result = query!("UPDATE songs SET background_type = ? where id = ?", db_string, song_id)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -933,10 +945,11 @@ impl song_model::SongModel {
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.get_indices(song_id, SongRoles::HorizontalTextAlignment);
|
.get_indices(song_id, SongRoles::HorizontalTextAlignment);
|
||||||
|
|
||||||
let db_string = updated_horizontal_text_alignment.clone().to_string();
|
let db_string =
|
||||||
|
updated_horizontal_text_alignment.clone().to_string();
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE songs SET horizontalTextAlignment = ? where id = ?", db_string, song_id)
|
let result = query!("UPDATE songs SET horizontal_text_alignment = ? where id = ?", db_string, song_id)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -978,10 +991,11 @@ impl song_model::SongModel {
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.get_indices(song_id, SongRoles::VerticalTextAlignment);
|
.get_indices(song_id, SongRoles::VerticalTextAlignment);
|
||||||
|
|
||||||
let db_string = updated_vertical_text_alignment.clone().to_string();
|
let db_string =
|
||||||
|
updated_vertical_text_alignment.clone().to_string();
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE songs SET verticalTextAlignment = ? where id = ?", db_string, song_id)
|
let result = query!("UPDATE songs SET vertical_text_alignment = ? where id = ?", db_string, song_id)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -1025,7 +1039,11 @@ impl song_model::SongModel {
|
||||||
let db_string = updated_font.clone().to_string();
|
let db_string = updated_font.clone().to_string();
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE songs SET font = ? where id = ?", db_string, song_id)
|
let result = query!(
|
||||||
|
"UPDATE songs SET font = ? where id = ?",
|
||||||
|
db_string,
|
||||||
|
song_id
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
@ -1050,9 +1068,11 @@ impl song_model::SongModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("There was an error updating font in db: {e}");
|
error!(
|
||||||
|
"There was an error updating font in db: {e}"
|
||||||
|
);
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -1069,7 +1089,7 @@ impl song_model::SongModel {
|
||||||
let db_string = updated_font_size.clone().to_string();
|
let db_string = updated_font_size.clone().to_string();
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE songs SET fontSize = ? where id = ?", db_string, song_id)
|
let result = query!("UPDATE songs SET font_size = ? where id = ?", db_string, song_id)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|
|
@ -178,6 +178,7 @@ pub mod video_model {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
use color_eyre::eyre::Error;
|
||||||
use cxx_qt::{CxxQtType, Threading};
|
use cxx_qt::{CxxQtType, Threading};
|
||||||
use cxx_qt_lib::{QByteArray, QModelIndex, QString, QUrl, QVariant};
|
use cxx_qt_lib::{QByteArray, QModelIndex, QString, QUrl, QVariant};
|
||||||
use sqlx::{query, query_as, Connection, SqliteConnection};
|
use sqlx::{query, query_as, Connection, SqliteConnection};
|
||||||
|
@ -224,9 +225,11 @@ impl Default for VideoModelRust {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,12 +243,20 @@ pub fn get_video(index: i32) -> color_eyre::Result<Video> {
|
||||||
let mut db_url = String::from("sqlite://");
|
let mut db_url = String::from("sqlite://");
|
||||||
db_url.push_str(data.to_str().unwrap());
|
db_url.push_str(data.to_str().unwrap());
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
SqliteConnection::connect(&db_url).await.expect("problems")
|
SqliteConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("problems")
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Video, r#"SELECT id as "id: i32", title as "title!", filePath as "path!", startTime as "start_time!: f32", endTime as "end_time!: f32", loop as "looping!" from videos where id = ?"#, index).fetch_one(&mut db).await?;
|
let result = query_as!(Video, r#"SELECT id as "id: i32", title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!" from videos where id = ?"#, index).fetch_one(&mut db).await;
|
||||||
Ok(result)
|
match result {
|
||||||
|
Ok(v) => Ok(v),
|
||||||
|
Err(e) => {
|
||||||
|
error!(?e);
|
||||||
|
Err(color_eyre::Report::from(e))
|
||||||
|
},
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +272,7 @@ impl video_model::VideoModel {
|
||||||
pub fn setup(mut self: Pin<&mut Self>) {
|
pub fn setup(mut self: Pin<&mut Self>) {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query_as!(Video, r#"SELECT id as "id: i32", title as "title!", filePath as "path!", startTime as "start_time!: f32", endTime as "end_time!: f32", loop as "looping!" from videos"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
let result = query_as!(Video, r#"SELECT id as "id: i32", title as "title!", file_path as "path!", start_time as "start_time!: f32", end_time as "end_time!: f32", loop as "looping!" from videos"#).fetch_all(&mut self.as_mut().rust_mut().db).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(v) => v.into_iter().for_each(|v| self.as_mut().add_video(v)),
|
Ok(v) => v.into_iter().for_each(|v| self.as_mut().add_video(v)),
|
||||||
Err(e) => error!("There was an error in converting songs: {e}"),
|
Err(e) => error!("There was an error in converting songs: {e}"),
|
||||||
|
@ -277,7 +288,10 @@ impl video_model::VideoModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
|
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("delete from videos where id = ?", video_id).execute(&mut self.as_mut().rust_mut().db).await;
|
let result =
|
||||||
|
query!("delete from videos where id = ?", video_id)
|
||||||
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
|
.await;
|
||||||
match result {
|
match result {
|
||||||
Ok(_i) => {
|
Ok(_i) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -334,7 +348,7 @@ impl video_model::VideoModel {
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let video_title = video_title.to_string();
|
let video_title = video_title.to_string();
|
||||||
let video_path = video_path.to_string();
|
let video_path = video_path.to_string();
|
||||||
let result = query!(r#"INSERT into videos (id, title, filePath, startTime, endTime, loop) VALUES (?, ?, ?, ?, ?, ?)"#,
|
let result = query!(r#"INSERT into videos (id, title, file_path, start_time, end_time, loop) VALUES (?, ?, ?, ?, ?, ?)"#,
|
||||||
video_id,
|
video_id,
|
||||||
video_title,
|
video_title,
|
||||||
video_path,
|
video_path,
|
||||||
|
@ -435,7 +449,11 @@ impl video_model::VideoModel {
|
||||||
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE videos SET loop = ? where id = ?", loop_value, index)
|
let result = query!(
|
||||||
|
"UPDATE videos SET loop = ? where id = ?",
|
||||||
|
loop_value,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -448,9 +466,11 @@ impl video_model::VideoModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
video.looping = loop_value;
|
video.looping = loop_value;
|
||||||
debug!(title = video.title,
|
debug!(
|
||||||
|
title = video.title,
|
||||||
looping = loop_value,
|
looping = loop_value,
|
||||||
"updated video loop");
|
"updated video loop"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -462,7 +482,7 @@ impl video_model::VideoModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -481,7 +501,11 @@ impl video_model::VideoModel {
|
||||||
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE videos SET endTime = ? where id = ?", updated_end_time, index)
|
let result = query!(
|
||||||
|
"UPDATE videos SET end_time = ? where id = ?",
|
||||||
|
updated_end_time,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -494,9 +518,11 @@ impl video_model::VideoModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
video.end_time = updated_end_time;
|
video.end_time = updated_end_time;
|
||||||
debug!(title = video.title,
|
debug!(
|
||||||
|
title = video.title,
|
||||||
end_time = updated_end_time,
|
end_time = updated_end_time,
|
||||||
"updated video end_time");
|
"updated video end_time"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -508,7 +534,7 @@ impl video_model::VideoModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -527,7 +553,11 @@ impl video_model::VideoModel {
|
||||||
|
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let result = query!("UPDATE videos SET startTime = ? where id = ?", updated_start_time, index)
|
let result = query!(
|
||||||
|
"UPDATE videos SET start_time = ? where id = ?",
|
||||||
|
updated_start_time,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -540,9 +570,11 @@ impl video_model::VideoModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
video.start_time = updated_start_time;
|
video.start_time = updated_start_time;
|
||||||
debug!(title = video.title,
|
debug!(
|
||||||
|
title = video.title,
|
||||||
start_time = updated_start_time,
|
start_time = updated_start_time,
|
||||||
"updated video start_time");
|
"updated video start_time"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -554,7 +586,7 @@ impl video_model::VideoModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -574,7 +606,11 @@ impl video_model::VideoModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let title = updated_title.to_string();
|
let title = updated_title.to_string();
|
||||||
let result = query!("UPDATE videos SET title = ? where id = ?", title, index)
|
let result = query!(
|
||||||
|
"UPDATE videos SET title = ? where id = ?",
|
||||||
|
title,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -587,9 +623,11 @@ impl video_model::VideoModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
video.title = title.clone();
|
video.title = title.clone();
|
||||||
debug!(title = video.title,
|
debug!(
|
||||||
|
title = video.title,
|
||||||
title = title,
|
title = title,
|
||||||
"updated video title");
|
"updated video title"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -601,7 +639,7 @@ impl video_model::VideoModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
@ -620,7 +658,11 @@ impl video_model::VideoModel {
|
||||||
let rt = tokio::runtime::Runtime::new().unwrap();
|
let rt = tokio::runtime::Runtime::new().unwrap();
|
||||||
rt.block_on(async {
|
rt.block_on(async {
|
||||||
let updated_path = updated_path.to_string();
|
let updated_path = updated_path.to_string();
|
||||||
let result = query!("UPDATE videos SET filePath = ? where id = ?", updated_path, index)
|
let result = query!(
|
||||||
|
"UPDATE videos SET file_path = ? where id = ?",
|
||||||
|
updated_path,
|
||||||
|
index
|
||||||
|
)
|
||||||
.execute(&mut self.as_mut().rust_mut().db)
|
.execute(&mut self.as_mut().rust_mut().db)
|
||||||
.await;
|
.await;
|
||||||
match result {
|
match result {
|
||||||
|
@ -633,9 +675,11 @@ impl video_model::VideoModel {
|
||||||
.filter(|x| x.id == index)
|
.filter(|x| x.id == index)
|
||||||
{
|
{
|
||||||
video.path = updated_path.clone();
|
video.path = updated_path.clone();
|
||||||
debug!(title = video.title,
|
debug!(
|
||||||
|
title = video.title,
|
||||||
path = updated_path,
|
path = updated_path,
|
||||||
"updated video path");
|
"updated video path"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
self.as_mut().data_changed(
|
self.as_mut().data_changed(
|
||||||
model_index,
|
model_index,
|
||||||
|
@ -647,7 +691,7 @@ impl video_model::VideoModel {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("Error connecting to db: {e}");
|
error!("Error connecting to db: {e}");
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
|
|
@ -67,14 +67,10 @@ impl ytdl::Ytdl {
|
||||||
.run()
|
.run()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let output = ytdl.into_single_video().unwrap();
|
let output = ytdl.into_single_video().unwrap();
|
||||||
debug!(
|
debug!(output.title, output.thumbnail, output.url);
|
||||||
output.title,
|
|
||||||
output.thumbnail, output.url
|
|
||||||
);
|
|
||||||
let title = QString::from(&output.title);
|
let title = QString::from(&output.title);
|
||||||
let thumbnail = QUrl::from(
|
let thumbnail =
|
||||||
&output.thumbnail.unwrap_or_default(),
|
QUrl::from(&output.thumbnail.unwrap_or_default());
|
||||||
);
|
|
||||||
let mut file = String::from(output_dirs);
|
let mut file = String::from(output_dirs);
|
||||||
file.push('/');
|
file.push('/');
|
||||||
file.push_str(&output.title);
|
file.push_str(&output.title);
|
||||||
|
@ -86,12 +82,8 @@ impl ytdl::Ytdl {
|
||||||
qobject_ytdl.as_mut().set_loaded(true);
|
qobject_ytdl.as_mut().set_loaded(true);
|
||||||
qobject_ytdl.as_mut().set_loading(false);
|
qobject_ytdl.as_mut().set_loading(false);
|
||||||
qobject_ytdl.as_mut().set_title(title);
|
qobject_ytdl.as_mut().set_title(title);
|
||||||
qobject_ytdl
|
qobject_ytdl.as_mut().set_thumbnail(thumbnail);
|
||||||
.as_mut()
|
qobject_ytdl.as_mut().set_file(QUrl::from(&file));
|
||||||
.set_thumbnail(thumbnail);
|
|
||||||
qobject_ytdl
|
|
||||||
.as_mut()
|
|
||||||
.set_file(QUrl::from(&file));
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
true
|
true
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue