fixing lots of bugs

This commit is contained in:
Chris Cochrun 2025-03-10 23:18:30 -05:00
parent da735aa00b
commit 0ba3e7588b
24 changed files with 781 additions and 486 deletions

4
Cargo.lock generated
View file

@ -1464,7 +1464,7 @@ dependencies = [
"cxx-qt-lib",
"dirs",
"fastrand 2.1.1",
"lumina-core",
"lumina_core",
"obws",
"qt-build-utils",
"quote",
@ -1549,7 +1549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "lumina-core"
name = "lumina_core"
version = "0.1.0"
dependencies = [
"color-eyre",

View file

@ -21,7 +21,7 @@ path = "src/rust/lib.rs"
# path = "src/rust/main.rs"
[dependencies]
lumina-core = { path = "src/rust/core" }
lumina_core = { path = "src/rust/core" }
configparser = "3.0.2"
serde = "1.0.152"
serde_derive = "1.0.152"

View file

@ -15,7 +15,7 @@ test:
RUST_LOG=debug cargo test --benches --tests --all-features -- --nocapture
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 r := run

View file

@ -1,5 +1,5 @@
[package]
name = "lumina-core"
name = "lumina_core"
version = "0.1.0"
edition = "2021"
authors = [

View file

@ -1,86 +1,131 @@
use tar::{Archive, Builder};
use tracing::error;
use zstd::Encoder;
use std::{fs::{self, File}, iter, path::{Path, PathBuf}};
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 color_eyre::eyre::{eyre, Context, Result};
use serde_json::Value;
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 save_file = File::create(path)?;
let mut db = get_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(())
}
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 mut tar = Builder::new(encoder);
let mut temp_dir = dirs::data_dir().unwrap();
temp_dir.push("lumina");
let mut s: String =
iter::repeat_with(fastrand::alphanumeric)
.take(5)
.collect();
iter::repeat_with(fastrand::alphanumeric).take(5).collect();
s.insert_str(0, "temp_");
temp_dir.push(s);
fs::create_dir_all(&temp_dir)?;
let service_file = temp_dir.join("serviceitems.json");
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) => {
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 {
let background;
let audio: Option<PathBuf>;
match item.kind {
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;
audio = song.audio;
},
}
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)?);
audio = None;
},
}
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)?);
audio = None;
},
}
ServiceItemKind::Presentation(_) => {
let presentation = get_presentation_from_db(item.database_id, db).await?;
background = Some(Background::try_from(presentation.path)?);
let presentation =
get_presentation_from_db(item.database_id, db)
.await?;
background =
Some(Background::try_from(presentation.path)?);
audio = None;
},
}
ServiceItemKind::Content => {
todo!()
},
}
};
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://") {
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");
} 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");
}
};
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://") {
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");
} 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");
}
}
@ -92,66 +137,96 @@ async fn clear_temp_dir(temp_dir: &Path) -> Result<()> {
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![];
for item in items {
match item.kind {
ServiceItemKind::Song => {
let value = process_song(item.database_id, db).await?;
let value =
process_song(item.database_id, db).await?;
values.push(value);
},
}
ServiceItemKind::Image => {
let value = process_image(item.database_id, db).await?;
let value =
process_image(item.database_id, db).await?;
values.push(value);
},
}
ServiceItemKind::Video => {
let value = process_video(item.database_id, db).await?;
let value =
process_video(item.database_id, db).await?;
values.push(value);
},
}
ServiceItemKind::Presentation(_) => {
let value = process_presentation(item.database_id, db).await?;
let value =
process_presentation(item.database_id, db)
.await?;
values.push(value);
},
}
ServiceItemKind::Content => {
todo!()
},
}
}
}
let json = Value::from(values);
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_json = serde_json::to_value(&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)
}
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_json = serde_json::to_value(&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)
}
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_json = serde_json::to_value(&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)
}
async fn process_presentation(database_id: i32, db: &mut SqliteConnection) -> Result<Value> {
let presentation = get_presentation_from_db(database_id, db).await?;
async fn process_presentation(
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 kind_json = match presentation.kind {
PresKind::Html => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Html))?,
PresKind::Pdf => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Pdf))?,
PresKind::Generic => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Generic))?,
PresKind::Html => serde_json::to_value(
ServiceItemKind::Presentation(PresKind::Html),
)?,
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});
Ok(json)
@ -161,11 +236,11 @@ async fn process_presentation(database_id: i32, db: &mut SqliteConnection) -> Re
mod test {
use std::path::PathBuf;
use fs::canonicalize;
use sqlx::Connection;
use pretty_assertions::assert_eq;
use tracing::debug;
use super::*;
use fs::canonicalize;
use pretty_assertions::assert_eq;
use sqlx::Connection;
use tracing::debug;
async fn get_db() -> SqliteConnection {
let mut data = dirs::data_local_dir().unwrap();
@ -173,9 +248,7 @@ mod test {
data.push("library-db.sqlite3");
let mut db_url = String::from("sqlite://");
db_url.push_str(data.to_str().unwrap());
SqliteConnection::connect(&db_url)
.await
.expect("problems")
SqliteConnection::connect(&db_url).await.expect("problems")
}
#[tokio::test(flavor = "current_thread")]
@ -245,7 +318,8 @@ mod test {
async fn test_process_presentation() {
let mut db = get_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) {
debug!(file = ?&path);
if let Ok(s) = fs::read_to_string(path) {
@ -258,7 +332,9 @@ mod test {
panic!("String wasn't read from file");
}
} 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() {
let mut db = get_db().await;
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;
if let Ok(path) = canonicalize(json_item_file) {
if let Ok(s) = fs::read_to_string(path) {
@ -311,16 +388,23 @@ mod test {
#[tokio::test]
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) {
Ok(f) => f,
Err(e) => panic!("Couldn't create save_file: {e}"),
};
let mut db = get_db().await;
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);
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),
Err(e) => panic!("There was an error: {e}"),
}

View file

@ -5,7 +5,9 @@ use sqlx::{query_as, SqliteConnection};
use std::path::PathBuf;
use tracing::error;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[derive(
Clone, Debug, Default, PartialEq, Serialize, Deserialize,
)]
pub struct Image {
pub id: i32,
pub title: String,
@ -16,7 +18,7 @@ impl Model<Image> {
pub fn load_from_db(&mut self) {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
Ok(v) => {
for image in v.into_iter() {
@ -29,9 +31,11 @@ impl Model<Image> {
}
}
pub async fn get_image_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Image> {
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?)
pub async fn get_image_from_db(
database_id: i32,
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)]
@ -67,7 +71,10 @@ mod test {
let new_image = test_image("A newer image".into());
match result {
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!(
&new_image,
image_model.find(|i| i.id == 0).unwrap()

View file

@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize};
use crate::presentations::PresKind;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
)]
pub enum ServiceItemKind {
#[default]
Song,

View file

@ -1,3 +1,4 @@
pub mod file;
pub mod images;
pub mod kinds;
pub mod model;
@ -6,4 +7,3 @@ pub mod service_items;
pub mod slides;
pub mod songs;
pub mod videos;
pub mod file;

View file

@ -36,8 +36,7 @@ impl<T> Model<T> {
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)
}
@ -60,10 +59,8 @@ impl<T> Default for Model<T> {
items: vec![],
db: {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
get_db().await
})
}
rt.block_on(async { get_db().await })
},
}
}
}
@ -74,9 +71,7 @@ pub async fn get_db() -> SqliteConnection {
data.push("library-db.sqlite3");
let mut db_url = String::from("sqlite://");
db_url.push_str(data.to_str().unwrap());
SqliteConnection::connect(&db_url)
.await
.expect("problems")
SqliteConnection::connect(&db_url).await.expect("problems")
}
pub trait Modeling {

View file

@ -1,12 +1,16 @@
use std::path::PathBuf;
use color_eyre::eyre::Result;
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 crate::model::Model;
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
)]
pub enum PresKind {
Html,
#[default]
@ -14,7 +18,9 @@ pub enum PresKind {
Generic,
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(
Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize,
)]
pub struct Presentation {
pub id: i32,
pub title: String,
@ -57,7 +63,7 @@ impl Model<Presentation> {
pub fn load_from_db(&mut self) {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
Ok(v) => {
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> {
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?;
pub async fn get_presentation_from_db(
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)?)
}
@ -111,7 +120,9 @@ mod test {
let mut presentation_model: Model<Presentation> =
Model::default();
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();
assert_eq!(&test_presentation, presentation);
} else {

View file

@ -52,7 +52,9 @@ impl From<&Image> for ServiceItem {
impl From<&Presentation> for ServiceItem {
fn from(presentation: &Presentation) -> Self {
Self {
kind: ServiceItemKind::Presentation(presentation.kind.clone()),
kind: ServiceItemKind::Presentation(
presentation.kind.clone(),
),
database_id: presentation.id,
..Default::default()
}
@ -60,7 +62,10 @@ impl From<&Presentation> for ServiceItem {
}
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();
self.items.push(service_item);
Ok(())
@ -94,7 +99,6 @@ mod test {
}
}
#[test]
pub fn test_service_item() {
let song = test_song();
@ -104,10 +108,16 @@ mod test {
let mut service_model = ServiceItemModel::default();
match service_model.add_item(&song) {
Ok(_) => {
assert_eq!(ServiceItemKind::Song, service_model.items[0].kind);
assert_eq!(ServiceItemKind::Presentation(PresKind::Html), pres_item.kind);
assert_eq!(
ServiceItemKind::Song,
service_model.items[0].kind
);
assert_eq!(
ServiceItemKind::Presentation(PresKind::Html),
pres_item.kind
);
assert_eq!(service_item, service_model.items[0]);
},
}
Err(e) => panic!("Problem adding item: {:?}", e),
}
}

View file

@ -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 serde::{Deserialize, Serialize};
@ -10,7 +14,9 @@ use crate::{
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 {
TopLeft,
TopCenter,
@ -24,7 +30,9 @@ pub enum TextAlignment {
BottomRight,
}
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(
Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
)]
pub struct Background {
pub path: PathBuf,
pub kind: BackgroundKind,
@ -36,7 +44,7 @@ impl TryFrom<String> for Background {
let value = value.trim_start_matches("file://");
let path = PathBuf::from(value);
if !path.exists() {
return Err(ParseError::DoesNotExist)
return Err(ParseError::DoesNotExist);
}
let extension = value.rsplit_once('.').unwrap_or_default();
match extension.1 {
@ -106,11 +114,15 @@ impl DatabaseError for ParseError {
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!()
}
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!()
}
@ -128,15 +140,15 @@ impl Display for ParseError {
Self::NonBackgroundFile => {
"The file is not a recognized image or video type"
}
Self::DoesNotExist => {
"This file doesn't exist"
}
Self::DoesNotExist => "This file doesn't exist",
};
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 {
#[default]
Image,

View file

@ -2,7 +2,10 @@ use std::{collections::HashMap, path::PathBuf};
use color_eyre::eyre::{eyre, Context, Result};
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 crate::{
@ -10,7 +13,9 @@ use crate::{
slides::{Background, TextAlignment},
};
#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
#[derive(
Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize,
)]
pub struct Song {
pub id: i32,
pub title: String,
@ -56,17 +61,24 @@ impl FromRow<'_, SqliteRow> for Song {
text_alignment: Some({
let horizontal_alignment: String = row.try_get(3)?;
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", "center") => TextAlignment::MiddleLeft,
("left", "bottom") => TextAlignment::BottomLeft,
("center", "top") => TextAlignment::TopCenter,
("center", "center") => TextAlignment::MiddleCenter,
("center", "bottom") => TextAlignment::BottomCenter,
("center", "center") => {
TextAlignment::MiddleCenter
}
("center", "bottom") => {
TextAlignment::BottomCenter
}
("right", "top") => TextAlignment::TopRight,
("right", "center") => TextAlignment::MiddleRight,
("right", "bottom") => TextAlignment::BottomRight,
_ => TextAlignment::MiddleCenter
_ => TextAlignment::MiddleCenter,
}
}),
font: row.try_get(6)?,
@ -75,19 +87,20 @@ impl FromRow<'_, SqliteRow> for Song {
}
}
pub async fn get_song_from_db(index: i32, db: &mut SqliteConnection) -> Result<Song> {
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?;
pub async fn get_song_from_db(
index: i32,
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)?)
}
impl Model<Song> {
pub fn load_from_db(&mut self) {
// static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
Ok(s) => {
for song in s.into_iter() {

View file

@ -5,7 +5,9 @@ use sqlx::{query_as, SqliteConnection};
use std::path::PathBuf;
use tracing::error;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
#[derive(
Clone, Debug, Default, PartialEq, Serialize, Deserialize,
)]
pub struct Video {
pub id: i32,
pub title: String,
@ -19,7 +21,7 @@ impl Model<Video> {
pub fn load_from_db(&mut self) {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
Ok(v) => {
for video in v.into_iter() {
@ -32,12 +34,13 @@ impl Model<Video> {
}
}
pub async fn get_video_from_db(database_id: i32, db: &mut SqliteConnection) -> Result<Video> {
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?)
pub async fn get_video_from_db(
database_id: i32,
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)]
mod test {
use super::*;
@ -71,7 +74,10 @@ mod test {
let new_video = test_video("A newer video".into());
match result {
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!(
&new_video,
video_model.find(|v| v.id == 0).unwrap()

View file

@ -181,7 +181,7 @@ pub struct ImageModelRust {
highest_id: i32,
images: Vec<Image>,
inner_images: Vec<Image>,
db: SqliteConnection
db: SqliteConnection,
}
impl Default for ImageModelRust {
@ -199,9 +199,11 @@ impl Default for ImageModelRust {
let mut db_url = String::from("sqlite://");
db_url.push_str(data.to_str().unwrap());
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://");
db_url.push_str(data.to_str().unwrap());
rt.block_on(async {
SqliteConnection::connect(&db_url).await.expect("problems")
SqliteConnection::connect(&db_url)
.await
.expect("problems")
})
};
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)
})
}
@ -236,7 +240,7 @@ impl image_model::ImageModel {
pub fn setup(mut self: Pin<&mut Self>) {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
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}"),
@ -251,7 +255,10 @@ impl image_model::ImageModel {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
Ok(_i) => {
unsafe {
@ -308,7 +315,7 @@ impl image_model::ImageModel {
rt.block_on(async {
let image_title = image_title.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_title,
image_path)
@ -367,7 +374,11 @@ impl image_model::ImageModel {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
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)
.await;
match result {
@ -380,9 +391,11 @@ impl image_model::ImageModel {
.filter(|x| x.id == index)
{
image.title = title.clone();
debug!(title = image.title,
debug!(
title = image.title,
title = title,
"updated image title");
"updated image title"
);
}
self.as_mut().data_changed(
model_index,
@ -394,7 +407,7 @@ impl image_model::ImageModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true
@ -414,7 +427,11 @@ impl image_model::ImageModel {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
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)
.await;
match result {
@ -427,9 +444,11 @@ impl image_model::ImageModel {
.filter(|x| x.id == index)
{
image.path = updated_path.clone();
debug!(title = image.title,
debug!(
title = image.title,
path = updated_path,
"updated image path");
"updated image path"
);
}
self.as_mut().data_changed(
model_index,
@ -441,7 +460,7 @@ impl image_model::ImageModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true

View file

@ -8,10 +8,9 @@ pub mod service_item_model;
pub mod settings;
pub mod slide_model;
pub mod slide_object;
pub mod slide_types;
pub mod songs;
pub mod utils;
pub mod video_model;
pub mod ytdl;
pub mod slide_types;
// pub mod core;
// mod video_thumbnail;

View file

@ -4,7 +4,6 @@ use cxx_qt_lib::{QString, QStringList};
use obws::responses::scenes::{CurrentProgramScene, Scenes};
use obws::Client;
use std::{error::Error, pin::Pin};
use tracing::{debug, error};
@ -22,7 +21,10 @@ impl fmt::Debug for Obs {
f.debug_struct("Client")
.field("scenes", &self.scenes)
.field("client", &self.client.is_some())
.field("current_program_scene", &self.current_program_scene)
.field(
"current_program_scene",
&self.current_program_scene,
)
.finish()
}
}
@ -37,8 +39,6 @@ impl Clone for Obs {
}
}
impl Obs {
pub async fn new() -> Result<Self, Box<dyn Error>> {
let client =

View file

@ -208,7 +208,7 @@ pub struct PresentationModelRust {
highest_id: i32,
presentations: Vec<Presentation>,
inner_presentations: Vec<Presentation>,
db: SqliteConnection
db: SqliteConnection,
}
impl Default for PresentationModelRust {
@ -226,14 +226,18 @@ impl Default for PresentationModelRust {
let mut db_url = String::from("sqlite://");
db_url.push_str(data.to_str().unwrap());
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 mut db = {
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://");
db_url.push_str(data.to_str().unwrap());
rt.block_on(async {
SqliteConnection::connect(&db_url).await.expect("problems")
SqliteConnection::connect(&db_url)
.await
.expect("problems")
})
};
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)
})
}
@ -263,7 +269,7 @@ impl presentation_model::PresentationModel {
pub fn setup(mut self: Pin<&mut Self>) {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
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}"),
@ -278,7 +284,12 @@ impl presentation_model::PresentationModel {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
Ok(_i) => {
unsafe {
@ -365,7 +376,7 @@ impl presentation_model::PresentationModel {
rt.block_on(async {
let presentation_title = presentation_title.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_title,
presentation_path,
@ -503,7 +514,11 @@ impl presentation_model::PresentationModel {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
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)
.await;
match result {
@ -516,9 +531,11 @@ impl presentation_model::PresentationModel {
.filter(|x| x.id == index)
{
presentation.title = title.clone();
debug!(title = presentation.title,
debug!(
title = presentation.title,
title = title,
"updated presentation title");
"updated presentation title"
);
}
self.as_mut().data_changed(
model_index,
@ -530,7 +547,7 @@ impl presentation_model::PresentationModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true
@ -549,7 +566,11 @@ impl presentation_model::PresentationModel {
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
match result {
@ -561,10 +582,13 @@ impl presentation_model::PresentationModel {
.iter_mut()
.filter(|x| x.id == index)
{
presentation.page_count = updated_page_count.clone();
debug!(title = presentation.title,
presentation.page_count =
updated_page_count.clone();
debug!(
title = presentation.title,
page_count = updated_page_count,
"updated presentation page_count");
"updated presentation page_count"
);
}
self.as_mut().data_changed(
model_index,
@ -576,7 +600,7 @@ impl presentation_model::PresentationModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true

View file

@ -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::slide_types::SlideType;
use crate::songs::song_model::{get_song, Song};
use crate::{image_model, presentation_model, video_model};
use cxx_qt::{CxxQtType, Threading};
@ -279,6 +284,7 @@ use cxx_qt_lib::{
QByteArray, QModelIndex, QString, QStringList, QUrl, QVariant,
};
use dirs;
// use lumina_core::service_items::ServiceItem as SI;
use serde_json::{json, Value};
use std::iter;
use std::path::{Path, PathBuf};
@ -288,12 +294,6 @@ use std::{fs, println};
use tar::{Archive, Builder};
use tracing::{debug, error};
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;
@ -377,7 +377,9 @@ impl service_item_model::ServiceItemModel {
pub fn remove_items(mut self: Pin<&mut Self>) {
let mut indices = vec![];
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;
indices.push(index);
}
@ -436,7 +438,10 @@ impl service_item_model::ServiceItemModel {
self.as_mut().end_insert_rows();
}
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(
@ -475,7 +480,11 @@ impl service_item_model::ServiceItemModel {
self.as_mut().end_insert_rows();
}
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(
@ -876,8 +885,7 @@ impl service_item_model::ServiceItemModel {
Some(name) => {
println!("audio: {:?}", &name);
if name.to_str().unwrap() != "temp" {
flat_audio =
name.to_str().unwrap()
flat_audio = name.to_str().unwrap()
} else {
flat_audio = "";
}
@ -961,12 +969,18 @@ impl service_item_model::ServiceItemModel {
debug!(time = ?now.elapsed(), "file written");
std::thread::spawn(move || {
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() {
if let Ok(file) = file {
let file_name = file.file_name();
let file_name =
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");
thread.queue(move |mut service| {
service
@ -977,10 +991,11 @@ impl service_item_model::ServiceItemModel {
)
}).expect("Problem queuing on cxx thread");
}
}
if let Ok(encoder) = tar.into_inner() {
if let Ok(done) = encoder.finish() {
if let Ok(encoder) = tar.into_inner()
{
if let Ok(done) = encoder.finish()
{
debug!(time = ?now.elapsed(), ?done, "tar finished");
thread.queue(move |mut service| {
service.as_mut().set_save_progress(100.0);
@ -1000,9 +1015,7 @@ impl service_item_model::ServiceItemModel {
}
} else {
fs::remove_dir_all(&temp_dir)
.expect(
"error in removal",
);
.expect("error in removal");
false
}
});
@ -1058,7 +1071,9 @@ impl service_item_model::ServiceItemModel {
if !file_path.exists() {
match file.unpack_in(&datadir) {
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();
vector_roles.append(self.as_ref().get_role(role));
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(
index as i32,
@ -1355,7 +1372,6 @@ impl service_item_model::ServiceItemModel {
}
}
pub fn load_last_saved(self: Pin<&mut Self>) -> bool {
todo!();
// Don't actually need
@ -1394,9 +1410,9 @@ impl service_item_model::ServiceItemModel {
ServiceRoles::Name => {
QVariant::from(&service_item.name)
}
ServiceRoles::Type => {
QVariant::from(&QString::from(&service_item.ty.clone().to_string()))
}
ServiceRoles::Type => QVariant::from(&QString::from(
&service_item.ty.clone().to_string(),
)),
ServiceRoles::Audio => {
QVariant::from(&service_item.audio)
}
@ -1433,9 +1449,9 @@ impl service_item_model::ServiceItemModel {
ServiceRoles::VideoEndTime => {
QVariant::from(&service_item.video_end_time)
}
ServiceRoles::Id => {
QVariant::from(&service_item.database_id.unwrap_or_default())
}
ServiceRoles::Id => QVariant::from(
&service_item.database_id.unwrap_or_default(),
),
_ => QVariant::default(),
};
}
@ -1503,22 +1519,21 @@ impl service_item_model::ServiceItemModel {
ServiceRoles::VideoEndTime.repr,
QByteArray::from("videoEndTime"),
);
roles.insert(
ServiceRoles::Id.repr,
QByteArray::from("id"),
);
roles.insert(ServiceRoles::Id.repr, QByteArray::from("id"));
roles
}
pub fn row_count(&self, _parent: &QModelIndex) -> i32 {
// println!("row count is {cnt}");
self.service_items.len() as i32
}
}
impl ServiceItemModelRust {
pub fn save(_model: Pin<&mut ServiceItemModel>, _file: QUrl) -> bool {
pub fn save(
_model: Pin<&mut ServiceItemModel>,
_file: QUrl,
) -> bool {
todo!()
}
}

View file

@ -19,9 +19,11 @@ pub mod slide_model {
include!("cxx-qt-lib/qlist.h");
type QList_QString = cxx_qt_lib::QList<QString>;
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");
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");
type VideoModel = crate::video_model::video_model::VideoModel;
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::{self, Image, ImageModelRust};
use crate::obs::Obs;
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::{get_song, Song, SongModelRust};
use crate::video_model::video_model::VideoModel;
use crate::video_model::{self, Video, VideoModelRust};
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::Section;
use cxx_qt::{CxxQtType, Threading};
use cxx_qt_lib::{
CaseSensitivity, QByteArray, QList, QModelIndex, QString, QStringList, QVariant
CaseSensitivity, QByteArray, QList, QModelIndex, QString,
QStringList, QVariant,
};
use slide_model::SlideObject;
use std::error::Error;
use std::fmt::{Display};
use std::fmt::Display;
use std::{path::PathBuf, pin::Pin};
use tracing::{debug, error};
use tracing::{debug, error, warn};
use self::slide_model::{
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
@ -336,45 +341,40 @@ impl Slide {
fn slides_from_song(song: Song) -> Result<Vec<Self>> {
let list = song.get_lyric_list();
let total = list.len();
let mut vector: Vec<Slide> = vec![];
list.iter().map(|t| t.to_string()).enumerate()
.for_each(|(i, s)| {
if song.background_type == "image" {
vector.push(
Self {
let vector = list
.iter()
.map(|t| {
let s = t.to_string();
warn!(s);
s
})
.enumerate()
.map(|(i, s)| Self {
text: s,
ty: SlideType::Song,
audio: song.audio.clone(),
image_background: song.background.clone(),
video_background: "".to_owned(),
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()
}
);
image_background: if song.background_type == "image" {
song.background.clone()
} else {
vector.push(
Self {
text: s,
ty: SlideType::Song,
audio: song.audio.clone(),
image_background: "".to_owned(),
video_background: song.background.clone(),
htext_alignment: song.horizontal_text_alignment.clone(),
"".into()
},
video_background: if song.background_type == "video" {
song.background.clone()
} else {
"".to_owned()
},
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()
}
)
}
});
})
.collect();
warn!(?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 mut slides: Vec<Slide> = vec![];
for i in 0..total {
@ -406,7 +408,7 @@ impl Slide {
image_background: presentation.path.clone(),
..Default::default()
})
};
}
Ok(slides)
}
}
@ -456,9 +458,12 @@ impl slide_model::SlideModel {
index: i32,
) -> bool {
let mut vector_roles = QVector_i32::default();
vector_roles.append(self.get_role(SlideRoles::VideoThumbnail));
vector_roles.append(self.get_role(SlideRoles::VideoBackground));
vector_roles.append(self.get_role(SlideRoles::ImageBackground));
vector_roles
.append(self.get_role(SlideRoles::VideoThumbnail));
vector_roles
.append(self.get_role(SlideRoles::VideoBackground));
vector_roles
.append(self.get_role(SlideRoles::ImageBackground));
let rc = self.as_ref().count() - 1;
let tl = self.as_ref().index(0, 0, &QModelIndex::default());
let br = self.as_ref().index(rc, 0, &QModelIndex::default());
@ -470,7 +475,11 @@ impl slide_model::SlideModel {
let path =
PathBuf::from(slide.video_background.to_string());
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://");
slide.video_thumbnail = screenshot_string;
std::thread::spawn(move || {
@ -616,37 +625,56 @@ impl slide_model::SlideModel {
SlideType::Song => {
let song = get_song(item_model_id)?;
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(())
},
}
SlideType::Video => {
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(())
},
}
SlideType::Image => {
let result = image_model::get_image(item_model_id);
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) => {
e.with_note(|| {
format!("This might fail if we are loading the items from a file")
});
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);
},
}
}
Ok(())
},
}
SlideType::Content => {
todo!();
Ok(())
},
}
SlideType::Presentation(_) => {
let presentation = presentation_model::get_presentation(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));
let presentation =
presentation_model::get_presentation(
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(())
}
}
@ -692,7 +720,8 @@ impl slide_model::SlideModel {
if let Some((i, slide)) = slides_iter
.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);
first_slide = i as i32;
@ -705,11 +734,8 @@ impl slide_model::SlideModel {
// lets get the dest_slide and count
if move_down {
if let Some((i, slide)) = slides_iter
.clone()
.enumerate()
.rev()
.find(|slide| {
if let Some((i, slide)) =
slides_iter.clone().enumerate().rev().find(|slide| {
slide.1.service_item_id == destination_index
})
{
@ -724,9 +750,8 @@ impl slide_model::SlideModel {
dest_slide, dest_count
);
}
} else if let Some((i, slide)) = slides_iter
.enumerate()
.find(|slide| {
} else if let Some((i, slide)) =
slides_iter.enumerate().find(|slide| {
slide.1.service_item_id == destination_index
})
{
@ -1001,7 +1026,8 @@ impl slide_model::SlideModel {
debug!(service_item = index, "Getting slide from this item");
let mut id = 0;
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);
id = i as i32;
@ -1105,7 +1131,6 @@ impl slide_model::SlideModel {
(0, QModelIndex::default(), vector_roles)
}
}
}
// QAbstractListModel implementation
@ -1114,22 +1139,30 @@ impl slide_model::SlideModel {
let role = SlideRoles { repr: role };
if let Some(slide) = self.slides.get(index.row() as usize) {
return match role {
SlideRoles::Ty => QVariant::from(&QString::from(&slide.ty.to_string())),
SlideRoles::Text => QVariant::from(&QString::from(&slide.text)),
SlideRoles::Audio => QVariant::from(&QString::from(&slide.audio)),
SlideRoles::ImageBackground => {
QVariant::from(&QString::from(&slide.image_background))
SlideRoles::Ty => QVariant::from(&QString::from(
&slide.ty.to_string(),
)),
SlideRoles::Text => {
QVariant::from(&QString::from(&slide.text))
}
SlideRoles::VideoBackground => {
QVariant::from(&QString::from(&slide.video_background))
SlideRoles::Audio => {
QVariant::from(&QString::from(&slide.audio))
}
SlideRoles::HTextAlignment => {
QVariant::from(&QString::from(&slide.htext_alignment))
SlideRoles::ImageBackground => QVariant::from(
&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 => {
QVariant::from(&slide.font_size)
}
@ -1147,9 +1180,9 @@ impl slide_model::SlideModel {
QVariant::from(&slide.selected)
}
SlideRoles::Looping => QVariant::from(&slide.looping),
SlideRoles::VideoThumbnail => {
QVariant::from(&QString::from(&slide.video_thumbnail))
}
SlideRoles::VideoThumbnail => QVariant::from(
&QString::from(&slide.video_thumbnail),
),
SlideRoles::VideoStartTime => {
QVariant::from(&slide.video_start_time)
}
@ -1256,7 +1289,8 @@ impl slide_model::SlideModel {
fn extract_string(item: &QMap_QString_QVariant, key: &str) -> String {
item.get(&QString::from(key))
.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 {
@ -1277,12 +1311,11 @@ fn extract_bool(item: &QMap_QString_QVariant, key: &str) -> bool {
.value_or_default::<bool>()
}
#[cfg(test)]
mod test {
// #[cfg(test)]
// mod test {
#[test]
pub fn test_obs_setting_scene() {
assert_eq!(true, true)
}
}
// #[test]
// pub fn test_obs_setting_scene() {
// assert_eq!(true, true)
// }
// }

View file

@ -89,7 +89,8 @@ use cxx_qt_lib::{CaseSensitivity, QString, QVariant};
use tracing::{debug, error};
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;
@ -484,10 +485,18 @@ impl slide_object::SlideObject {
self.as_mut().set_text(QString::from(&slide.text));
self.as_mut().set_ty(QString::from(&slide.ty.to_string()));
self.as_mut().set_audio(QString::from(&slide.audio));
self.as_mut().set_image_background(QString::from(&slide.image_background));
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_image_background(QString::from(
&slide.image_background,
));
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_size(slide.font_size);
self.as_mut().set_video_start_time(slide.video_start_time);

View file

@ -241,6 +241,7 @@ pub mod song_model {
}
use crate::songs::song_editor::song_editor::QList_QString;
use color_eyre::Result;
use cxx_qt::{CxxQtType, Threading};
use cxx_qt_lib::{
QByteArray, QModelIndex, QString, QStringList, QVariant,
@ -249,7 +250,6 @@ use sqlx::{query, query_as, Connection, SqliteConnection};
use std::collections::HashMap;
use std::pin::Pin;
use tracing::{debug, error};
use color_eyre::Result;
use self::song_model::{
QHash_i32_QByteArray, QMap_QString_QVariant, QVector_i32,
@ -293,15 +293,13 @@ impl Song {
}
let raw_lyrics = self.lyrics.clone();
println!("raw-lyrics: {:?}", raw_lyrics);
let vorder: Vec<&str> =
self.verse_order.split(' ').collect();
let vorder: Vec<&str> = self.verse_order.split(' ').collect();
let keywords = vec![
"Verse 1", "Verse 2", "Verse 3", "Verse 4",
"Verse 5", "Verse 6", "Verse 7", "Verse 8",
"Chorus 1", "Chorus 2", "Chorus 3", "Chorus 4",
"Bridge 1", "Bridge 2", "Bridge 3", "Bridge 4",
"Intro 1", "Intro 2", "Ending 1", "Ending 2",
"Other 1", "Other 2", "Other 3", "Other 4",
"Verse 1", "Verse 2", "Verse 3", "Verse 4", "Verse 5",
"Verse 6", "Verse 7", "Verse 8", "Chorus 1", "Chorus 2",
"Chorus 3", "Chorus 4", "Bridge 1", "Bridge 2",
"Bridge 3", "Bridge 4", "Intro 1", "Intro 2", "Ending 1",
"Ending 2", "Other 1", "Other 2", "Other 3", "Other 4",
];
let _first_item = true;
@ -335,10 +333,8 @@ impl Song {
let mut verse_name = "";
// debug!(verse = verse);
for word in keywords.clone() {
let end_verse =
verse.get(1..2).unwrap_or_default();
let beg_verse =
verse.get(0..1).unwrap_or_default();
let end_verse = verse.get(1..2).unwrap_or_default();
let beg_verse = verse.get(0..1).unwrap_or_default();
// println!(
// "verse: {:?}, beginning: {:?}, end: {:?}, word: {:?}",
// verse, beg_verse, end_verse, word
@ -400,9 +396,11 @@ impl Default for SongModelRust {
let mut db_url = String::from("sqlite://");
db_url.push_str(data.to_str().unwrap());
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://");
db_url.push_str(data.to_str().unwrap());
rt.block_on(async {
SqliteConnection::connect(&db_url).await.expect("problems")
SqliteConnection::connect(&db_url)
.await
.expect("problems")
})
};
debug!("getting song with id: {id}");
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);
Ok(result)
})
@ -440,7 +440,7 @@ impl song_model::SongModel {
static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3";
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
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}"),
@ -453,7 +453,13 @@ impl song_model::SongModel {
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 db = &mut self.as_mut().rust_mut().db;
@ -504,7 +510,7 @@ impl song_model::SongModel {
};
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.font_size,
song.background_type,
@ -758,7 +764,11 @@ impl song_model::SongModel {
let db_string = updated_ccli.clone().to_string();
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
@ -783,9 +793,11 @@ impl song_model::SongModel {
}
}
Err(e) => {
error!("There was an error updating ccli in db: {e}");
error!(
"There was an error updating ccli in db: {e}"
);
false
},
}
}
});
true
@ -802,7 +814,7 @@ impl song_model::SongModel {
let db_string = updated_verse_order.clone().to_string();
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
@ -891,7 +903,7 @@ impl song_model::SongModel {
let db_string = updated_background_type.clone().to_string();
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
@ -933,10 +945,11 @@ impl song_model::SongModel {
.as_mut()
.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();
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)
.await;
@ -978,10 +991,11 @@ impl song_model::SongModel {
.as_mut()
.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();
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)
.await;
@ -1025,7 +1039,11 @@ impl song_model::SongModel {
let db_string = updated_font.clone().to_string();
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
@ -1050,9 +1068,11 @@ impl song_model::SongModel {
}
}
Err(e) => {
error!("There was an error updating font in db: {e}");
error!(
"There was an error updating font in db: {e}"
);
false
},
}
}
});
true
@ -1069,7 +1089,7 @@ impl song_model::SongModel {
let db_string = updated_font_size.clone().to_string();
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;

View file

@ -178,6 +178,7 @@ pub mod video_model {
}
}
use color_eyre::eyre::Error;
use cxx_qt::{CxxQtType, Threading};
use cxx_qt_lib::{QByteArray, QModelIndex, QString, QUrl, QVariant};
use sqlx::{query, query_as, Connection, SqliteConnection};
@ -224,9 +225,11 @@ impl Default for VideoModelRust {
let mut db_url = String::from("sqlite://");
db_url.push_str(data.to_str().unwrap());
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://");
db_url.push_str(data.to_str().unwrap());
rt.block_on(async {
SqliteConnection::connect(&db_url).await.expect("problems")
SqliteConnection::connect(&db_url)
.await
.expect("problems")
})
};
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?;
Ok(result)
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;
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>) {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
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}"),
@ -277,7 +288,10 @@ impl video_model::VideoModel {
let rt = tokio::runtime::Runtime::new().unwrap();
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 {
Ok(_i) => {
unsafe {
@ -334,7 +348,7 @@ impl video_model::VideoModel {
rt.block_on(async {
let video_title = video_title.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_title,
video_path,
@ -435,7 +449,11 @@ impl video_model::VideoModel {
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
match result {
@ -448,9 +466,11 @@ impl video_model::VideoModel {
.filter(|x| x.id == index)
{
video.looping = loop_value;
debug!(title = video.title,
debug!(
title = video.title,
looping = loop_value,
"updated video loop");
"updated video loop"
);
}
self.as_mut().data_changed(
model_index,
@ -462,7 +482,7 @@ impl video_model::VideoModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true
@ -481,7 +501,11 @@ impl video_model::VideoModel {
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
match result {
@ -494,9 +518,11 @@ impl video_model::VideoModel {
.filter(|x| x.id == index)
{
video.end_time = updated_end_time;
debug!(title = video.title,
debug!(
title = video.title,
end_time = updated_end_time,
"updated video end_time");
"updated video end_time"
);
}
self.as_mut().data_changed(
model_index,
@ -508,7 +534,7 @@ impl video_model::VideoModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true
@ -527,7 +553,11 @@ impl video_model::VideoModel {
let rt = tokio::runtime::Runtime::new().unwrap();
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)
.await;
match result {
@ -540,9 +570,11 @@ impl video_model::VideoModel {
.filter(|x| x.id == index)
{
video.start_time = updated_start_time;
debug!(title = video.title,
debug!(
title = video.title,
start_time = updated_start_time,
"updated video start_time");
"updated video start_time"
);
}
self.as_mut().data_changed(
model_index,
@ -554,7 +586,7 @@ impl video_model::VideoModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true
@ -574,7 +606,11 @@ impl video_model::VideoModel {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
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)
.await;
match result {
@ -587,9 +623,11 @@ impl video_model::VideoModel {
.filter(|x| x.id == index)
{
video.title = title.clone();
debug!(title = video.title,
debug!(
title = video.title,
title = title,
"updated video title");
"updated video title"
);
}
self.as_mut().data_changed(
model_index,
@ -601,7 +639,7 @@ impl video_model::VideoModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true
@ -620,7 +658,11 @@ impl video_model::VideoModel {
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async {
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)
.await;
match result {
@ -633,9 +675,11 @@ impl video_model::VideoModel {
.filter(|x| x.id == index)
{
video.path = updated_path.clone();
debug!(title = video.title,
debug!(
title = video.title,
path = updated_path,
"updated video path");
"updated video path"
);
}
self.as_mut().data_changed(
model_index,
@ -647,7 +691,7 @@ impl video_model::VideoModel {
Err(e) => {
error!("Error connecting to db: {e}");
false
},
}
}
});
true

View file

@ -67,14 +67,10 @@ impl ytdl::Ytdl {
.run()
.unwrap();
let output = ytdl.into_single_video().unwrap();
debug!(
output.title,
output.thumbnail, output.url
);
debug!(output.title, output.thumbnail, output.url);
let title = QString::from(&output.title);
let thumbnail = QUrl::from(
&output.thumbnail.unwrap_or_default(),
);
let thumbnail =
QUrl::from(&output.thumbnail.unwrap_or_default());
let mut file = String::from(output_dirs);
file.push('/');
file.push_str(&output.title);
@ -86,12 +82,8 @@ impl ytdl::Ytdl {
qobject_ytdl.as_mut().set_loaded(true);
qobject_ytdl.as_mut().set_loading(false);
qobject_ytdl.as_mut().set_title(title);
qobject_ytdl
.as_mut()
.set_thumbnail(thumbnail);
qobject_ytdl
.as_mut()
.set_file(QUrl::from(&file));
qobject_ytdl.as_mut().set_thumbnail(thumbnail);
qobject_ytdl.as_mut().set_file(QUrl::from(&file));
})
});
true