diff --git a/Cargo.lock b/Cargo.lock index 1e36dee..bdef7aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -272,6 +272,7 @@ dependencies = [ "cxx-qt-lib", "diesel", "dirs", + "libsqlite3-sys", "serde", "serde_derive", ] @@ -282,6 +283,7 @@ version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14" dependencies = [ + "cc", "pkg-config", "vcpkg", ] diff --git a/Cargo.toml b/Cargo.toml index 5930934..da3dcf2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ cxx-qt-lib = "0.5.1" # home = "0.5.4" dirs = "5.0.0" diesel = { version = "2.0.3", features = ["sqlite"] } +libsqlite3-sys = { version = ">=0.17.2, <0.26.0", features = ["bundled"] } # ffmpeg-next = "6.0.0" # cxx-qt-build generates C++ code from the `#[cxx_qt::bridge]` module diff --git a/src/cpp/imagesqlmodel.cpp b/src/cpp/imagesqlmodel.cpp index b10de33..ccfab76 100644 --- a/src/cpp/imagesqlmodel.cpp +++ b/src/cpp/imagesqlmodel.cpp @@ -208,14 +208,15 @@ QVariantMap ImageSqlModel::getImage(const int &row) { ImageProxyModel::ImageProxyModel(QObject *parent) :QSortFilterProxyModel(parent) { - m_imageModel = new ImageSqlModel; + m_imageModel = new ImageModel; + m_imageModel->testDatabase(); setSourceModel(m_imageModel); setDynamicSortFilter(true); - setFilterRole(Qt::UserRole + 1); + setFilterRole(1); setFilterCaseSensitivity(Qt::CaseInsensitive); } -ImageSqlModel *ImageProxyModel::imageModel() { +ImageModel *ImageProxyModel::imageModel() { return m_imageModel; } @@ -226,21 +227,21 @@ QModelIndex ImageProxyModel::idx(int row) { } QVariantMap ImageProxyModel::getImage(const int &row) { - auto model = qobject_cast(sourceModel()); - QVariantMap image = model->getImage(mapToSource(index(row, 0)).row()); + auto model = qobject_cast(sourceModel()); + QVariantMap image = model->getItem(mapToSource(index(row, 0)).row()); return image; } void ImageProxyModel::deleteImage(const int &row) { - auto model = qobject_cast(sourceModel()); - model->deleteImage(row); + auto model = qobject_cast(sourceModel()); + model->removeItem(row); } void ImageProxyModel::deleteImages(const QVector &rows) { - auto model = qobject_cast(sourceModel()); + auto model = qobject_cast(sourceModel()); qDebug() << "DELETING!!!!!!!!!!!!!!!!!!!!!!!" << rows; for (int i = rows.size() - 1; i >= 0; i--) { qDebug() << "deleting" << rows.at(i); - model->deleteImage(rows.at(i)); + model->removeItem(rows.at(i)); } } diff --git a/src/cpp/imagesqlmodel.h b/src/cpp/imagesqlmodel.h index 57d467b..ff31953 100644 --- a/src/cpp/imagesqlmodel.h +++ b/src/cpp/imagesqlmodel.h @@ -8,6 +8,7 @@ #include #include #include +#include "cxx-qt-gen/image_model.cxxqt.h" class ImageSqlModel : public QSqlTableModel { @@ -50,13 +51,13 @@ private: class ImageProxyModel : public QSortFilterProxyModel { Q_OBJECT - Q_PROPERTY(ImageSqlModel *imageModel READ imageModel) + Q_PROPERTY(ImageModel *imageModel READ imageModel) public: explicit ImageProxyModel(QObject *parent = nullptr); ~ImageProxyModel() = default; - ImageSqlModel *imageModel(); + ImageModel *imageModel(); Q_INVOKABLE QModelIndex idx(int row); public slots: @@ -65,7 +66,7 @@ public slots: Q_INVOKABLE void deleteImages(const QVector &rows); private: - ImageSqlModel *m_imageModel; + ImageModel *m_imageModel; }; diff --git a/src/main.cpp b/src/main.cpp index 9bd50ff..fc88ebb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -142,8 +142,6 @@ int main(int argc, char *argv[]) // QScopedPointer preswin(new QQuickView); QScopedPointer serviceItemModel(new ServiceItemModel); QScopedPointer slideobject(new SlideObj); - QScopedPointer imageModel(new ImageModel); - imageModel.get()->testDatabase(); Settings *settings = new Settings; settings->setup(); diff --git a/src/qml/presenter/Library.qml b/src/qml/presenter/Library.qml index 652ee67..b7f3aaf 100644 --- a/src/qml/presenter/Library.qml +++ b/src/qml/presenter/Library.qml @@ -90,7 +90,7 @@ Item { itemIcon: "folder-pictures-symbolic" itemSubtitle: { if (fileValidation) - model.filePath; + model.path; else "file is missing" } @@ -299,11 +299,11 @@ Item { } function addImg(url) { - imageProxyModel.imageModel.newImage(url); + imageProxyModel.imageModel.newItem(url); selectedLibrary = "image"; - imageLibraryList.currentIndex = imageProxyModel.imageModel.rowCount(); - console.log(imageProxyModel.imageModel.getImage(imageLibraryList.currentIndex)); - const image = imageProxyModel.imageModel.getImage(imageLibraryList.currentIndex); + imageLibrary.libraryList.currentIndex = imageProxyModel.imageModel.count(); + console.log(imageProxyModel.getImage(imageLibrary.libraryList.currentIndex)); + const image = imageProxyModel.getImage(imageLibrary.libraryList.currentIndex); showPassiveNotification("newest image: " + image.title); if (!editMode) editMode = true; diff --git a/src/qml/presenter/MainWindow.qml b/src/qml/presenter/MainWindow.qml index aa91011..6136e88 100644 --- a/src/qml/presenter/MainWindow.qml +++ b/src/qml/presenter/MainWindow.qml @@ -52,6 +52,10 @@ Controls.Page { Component.onCompleted: { changeServiceItem(0); presentation.forceActiveFocus(); + imageProxyModel.setSourceModel(ImageModel); + console.log("^^^^^"); + console.log(imageProxyModel.model); + console.log("^^^^^"); /* const loaded = ServiceItemModel.loadLastSaved(); */ /* if (!loaded) */ /* showPassiveNotification("Failed loading last file"); */ diff --git a/src/rust/image_model.rs b/src/rust/image_model.rs index 35c59d2..88519a7 100644 --- a/src/rust/image_model.rs +++ b/src/rust/image_model.rs @@ -1,5 +1,12 @@ #[cxx_qt::bridge] mod image_model { + use crate::image_model::image_model::Image; + use crate::models::*; + use crate::schema::images::dsl::*; + use diesel::sqlite::SqliteConnection; + use diesel::{delete, insert_into, prelude::*}; + use std::path::{Path, PathBuf}; + unsafe extern "C++" { include!(< QAbstractListModel >); include!("cxx-qt-lib/qhash.h"); @@ -10,6 +17,8 @@ mod image_model { type QVariant = cxx_qt_lib::QVariant; include!("cxx-qt-lib/qstring.h"); type QString = cxx_qt_lib::QString; + include!("cxx-qt-lib/qurl.h"); + type QUrl = cxx_qt_lib::QUrl; include!("cxx-qt-lib/qmodelindex.h"); type QModelIndex = cxx_qt_lib::QModelIndex; include!("cxx-qt-lib/qvector.h"); @@ -30,6 +39,7 @@ mod image_model { #[cxx_qt::qobject(base = "QAbstractListModel")] #[derive(Default, Debug)] pub struct ImageModel { + highest_id: i32, images: Vec, } @@ -51,12 +61,6 @@ mod image_model { // use crate::entities::{images, prelude::Images}; // use sea_orm::{ConnectionTrait, Database, DbBackend, DbErr, Statement, ActiveValue}; - use crate::models::*; - use diesel::prelude::*; - use diesel::sqlite::SqliteConnection; - use std::path::PathBuf; - - use crate::image_model::image_model::Image; impl qobject::ImageModel { #[qinvokable] pub fn clear(mut self: Pin<&mut Self>) { @@ -68,61 +72,128 @@ mod image_model { } #[qinvokable] - pub fn test_database(&self) { - use crate::schema::images::dsl::*; - const DATABASE_URL: &str = "sqlite:///home/chris/.local/share/librepresenter/Libre Presenter/library-db.sqlite3"; - const DB_NAME: &str = "library_db"; - - let db = &mut SqliteConnection::establish(DATABASE_URL) - .unwrap_or_else(|_| panic!("error connecting to {}", DATABASE_URL)); - + pub fn test_database(mut self: Pin<&mut Self>) { + let db = &mut self.as_mut().get_db(); let results = images .load::(db) .expect("Error loading images"); + self.as_mut().set_highest_id(0); println!("SHOWING IMAGES"); + println!("--------------"); for image in results { println!("{}", image.title); println!("{}", image.id); - println!("--------------\n"); println!("{}", image.path); + println!("--------------"); + if self.as_mut().highest_id() < &image.id { + self.as_mut().set_highest_id(image.id); + } + + let img = self::Image { + id: image.id, + title: QString::from(&image.title), + path: QString::from(&image.path), + }; + + self.as_mut().add_image(img); } + println!("--------------------------------------"); + println!("{:?}", self.as_mut().images()); + println!("--------------------------------------"); } #[qinvokable] - pub fn remove_item(mut self: Pin<&mut Self>, index: i32) { + pub fn remove_item(mut self: Pin<&mut Self>, index: i32) -> bool { if index < 0 || (index as usize) >= self.images().len() { - return; + return false; } + let db = &mut self.as_mut().get_db(); - unsafe { - self.as_mut() - .begin_remove_rows(&QModelIndex::default(), index, index); - self.as_mut().images_mut().remove(index as usize); - self.as_mut().end_remove_rows(); + let image_id = self.images().get(index as usize).unwrap().id; + + let result = delete(images.filter(id.eq(image_id))).execute(db); + + match result { + Ok(_i) => { + unsafe { + self.as_mut() + .begin_remove_rows(&QModelIndex::default(), index, index); + self.as_mut().images_mut().remove(index as usize); + self.as_mut().end_remove_rows(); + } + println!("removed-item-at-index: {:?}", image_id); + println!("new-Vec: {:?}", self.as_mut().images()); + true + } + Err(_e) => { + println!("Cannot connect to database"); + false + } + } + } + + fn get_db(self: Pin<&mut Self>) -> SqliteConnection { + const DATABASE_URL: &str = "sqlite:///home/chris/.local/share/librepresenter/Libre Presenter/library-db.sqlite3"; + + SqliteConnection::establish(DATABASE_URL) + .unwrap_or_else(|_| panic!("error connecting to {}", DATABASE_URL)) + // self.rust().db = db; + } + + #[qinvokable] + pub fn new_item(mut self: Pin<&mut Self>, url: QUrl) { + println!("LETS INSERT THIS SUCKER!"); + let file_path = PathBuf::from(url.path().to_string()); + let name = file_path.file_stem().unwrap().to_str().unwrap(); + let image_id = self.rust().highest_id + 1; + let image_title = QString::from(name); + let image_path = url.to_qstring(); + + if self.as_mut().add_item(image_id, image_title, image_path) { + println!("filename: {:?}", name); + self.as_mut().set_highest_id(image_id); + } else { + println!("Error in inserting item"); } } #[qinvokable] - pub fn add_item(mut self: Pin<&mut Self>, id: i32, title: QString, path: QString) { - const DATABASE_URL: &str = "sqlite://library-db.sqlite3"; - const DB_NAME: &str = "library_db"; + pub fn add_item( + mut self: Pin<&mut Self>, + image_id: i32, + image_title: QString, + image_path: QString, + ) -> bool { + let db = &mut self.as_mut().get_db(); + // println!("{:?}", db); + let image = self::Image { + id: image_id, + title: image_title.clone(), + path: image_path.clone(), + }; + println!("{:?}", image); - let db = SqliteConnection::establish(DATABASE_URL) - .unwrap_or_else(|_| panic!("error connecting to {}", DATABASE_URL)); + let result = insert_into(images) + .values(( + id.eq(&image_id), + title.eq(&image_title.to_string()), + path.eq(&image_path.to_string()), + )) + .execute(db); + println!("{:?}", result); - let image = self::Image { id, title, path }; - // let model = images::ActiveModel { - // id: ActiveValue::set(id), - // title: ActiveValue::set(title.to_string()), - // path: ActiveValue::set(path.to_string()), - // ..Default::default() - // }; - // let res = Images::insert(model).exec(db).await?; - - self.as_mut().add_image(image); - - // Ok(()) + match result { + Ok(_i) => { + self.as_mut().add_image(image); + println!("{:?}", self.as_mut().images()); + true + } + Err(_e) => { + println!("Cannot connect to database"); + false + } + } } fn add_image(mut self: Pin<&mut Self>, image: self::Image) { @@ -136,27 +207,41 @@ mod image_model { } } - #[qinvokable] - pub fn insert_item( - mut self: Pin<&mut Self>, - id: i32, - title: QString, - path: QString, - index: i32, - ) { - let image = Image { id, title, path }; + // #[qinvokable] + // pub fn insert_item( + // mut self: Pin<&mut Self>, + // image_id: i32, + // image_title: QString, + // image_path: QString, + // index: i32, + // ) { + // let image = Image { + // id: image_id, + // title: image_title, + // path: image_path, + // }; + // let db = self.db(); - self.as_mut().insert_image(image, index); - } + // let i = image_id; + // let t = image_title.to_string(); + // let p = image_path.to_string(); - fn insert_image(mut self: Pin<&mut Self>, image: self::Image, id: i32) { - unsafe { - self.as_mut() - .begin_insert_rows(&QModelIndex::default(), id, id); - self.as_mut().images_mut().insert(id as usize, image); - self.as_mut().end_insert_rows(); - } - } + // use crate::schema::images::dsl::*; + // let result = insert_into(images) + // .values((id.eq(&i), title.eq(&t), path.eq(&p))) + // .execute(db); + + // self.as_mut().insert_image(image, index); + // } + + // fn insert_image(mut self: Pin<&mut Self>, image: self::Image, id: i32) { + // unsafe { + // self.as_mut() + // .begin_insert_rows(&QModelIndex::default(), id, id); + // self.as_mut().images_mut().insert(id as usize, image); + // self.as_mut().end_insert_rows(); + // } + // } #[qinvokable] pub fn get_item(self: Pin<&mut Self>, index: i32) -> QMap_QString_QVariant { @@ -252,7 +337,7 @@ mod image_model { let mut roles = QHash_i32_QByteArray::default(); roles.insert(0, cxx_qt_lib::QByteArray::from("id")); roles.insert(1, cxx_qt_lib::QByteArray::from("title")); - roles.insert(2, cxx_qt_lib::QByteArray::from("path")); + roles.insert(2, cxx_qt_lib::QByteArray::from("filePath")); roles } diff --git a/src/rust/models.rs b/src/rust/models.rs index f3ce7c1..45e0ce7 100644 --- a/src/rust/models.rs +++ b/src/rust/models.rs @@ -4,6 +4,5 @@ use diesel::prelude::*; pub struct Image { pub id: i32, pub title: String, - #[diesel(column_name = "filePath")] pub path: String, }