draft profile database implementation, make members public, run initial dialog, rename field from active to is_active

This commit is contained in:
yggverse 2024-11-13 08:03:48 +02:00
parent b0ee52c3f4
commit 4d7b61ef59
4 changed files with 81 additions and 54 deletions

View File

@ -7,7 +7,7 @@ use crate::profile::Profile;
use adw::Application;
use gtk::{
glib::ExitCode,
prelude::{ApplicationExt, ApplicationExtManual, GtkApplicationExt, GtkWindowExt},
prelude::{ApplicationExt, ApplicationExtManual, GtkApplicationExt},
};
use sqlite::Transaction;
use std::rc::Rc;
@ -41,7 +41,7 @@ impl App {
let profile = profile.clone();
move |this| {
// Init readable connection
match profile.database().read() {
match profile.database.connection.read() {
Ok(connection) => {
// Create transaction
match connection.unchecked_transaction() {
@ -57,9 +57,6 @@ impl App {
todo!("{e}")
}
}
// Run initial features
browser.init();
}
Err(e) => todo!("{e}"),
}
@ -70,11 +67,8 @@ impl App {
Err(e) => todo!("{e}"),
}
// Assign browser window to this application
browser.gobject().set_application(Some(this));
// Show main widget
browser.gobject().present();
// Run initial features, show widget
browser.init(Some(this)).present();
}
});
@ -83,7 +77,7 @@ impl App {
let profile = profile.clone();
move |_| {
// Init writable connection
match profile.database().write() {
match profile.database.connection.write() {
Ok(mut connection) => {
// Create transaction
match connection.transaction() {
@ -240,7 +234,7 @@ impl App {
// Begin database migration @TODO
{
// Init writable connection
let mut connection = match self.profile.database().try_write() {
let mut connection = match self.profile.database.connection.write() {
Ok(connection) => connection,
Err(e) => todo!("{e}"),
};

View File

@ -12,11 +12,10 @@ use widget::Widget;
use window::Window;
use crate::profile::Profile;
use adw::ApplicationWindow;
use gtk::{
gio::{Cancellable, File},
prelude::GtkWindowExt,
FileLauncher,
prelude::{GtkWindowExt, IsA},
Application, FileLauncher,
};
use sqlite::Transaction;
use std::rc::Rc;
@ -76,7 +75,7 @@ impl Browser {
action.profile().connect_activate({
let profile = profile.clone();
move || {
FileLauncher::new(Some(&File::for_path(profile.config_path()))).launch(
FileLauncher::new(Some(&File::for_path(profile.config_path.as_path()))).launch(
None::<&gtk::Window>,
None::<&Cancellable>,
|result| {
@ -163,12 +162,25 @@ impl Browser {
Ok(())
}
pub fn init(&self) {
// Show welcome dialog on profile not selected yet (e.g. first launch) @TODO
// Welcome::new(self.profile.clone()).present(Some(self.widget.gobject()));
pub fn init(&self, application: Option<&impl IsA<Application>>) -> &Self {
// Assign browser window to this application
self.widget.gobject().set_application(application); // @TODO
// Init main window
self.window.init();
self
}
pub fn present(&self) -> &Self {
// Show main window
self.widget.gobject().present();
// Show welcome dialog on profile not selected yet (e.g. first launch)
if self.profile.database.selected().is_none() {
Welcome::new(self.profile.clone()).present(Some(self.widget.gobject()));
}
self
}
pub fn update(&self) {
@ -181,10 +193,6 @@ impl Browser {
&self.action
}
pub fn gobject(&self) -> &ApplicationWindow {
self.widget.gobject()
}
pub fn window(&self) -> &Rc<Window> {
&self.window
}

View File

@ -3,24 +3,21 @@ mod database;
mod history;
mod identity;
use database::Database;
use gtk::glib::user_config_dir;
use sqlite::{Connection, Transaction};
use std::{
fs::create_dir_all,
path::{Path, PathBuf},
rc::Rc,
sync::RwLock,
};
use std::{fs::create_dir_all, path::PathBuf, rc::Rc, sync::RwLock};
const VENDOR: &str = "YGGverse";
const APP_ID: &str = "Yoda";
const BRANCH: &str = "master";
const DB_NAME: &str = "profile.sqlite3";
const DB_NAME: &str = "database.sqlite3";
pub struct Profile {
database: Rc<RwLock<Connection>>,
config_path: PathBuf,
pub database: Rc<Database>,
pub config_path: PathBuf,
}
impl Profile {
@ -82,20 +79,10 @@ impl Profile {
// Result
Self {
database: connection,
database: Rc::new(Database::new(connection)),
config_path,
}
}
// Getters
pub fn database(&self) -> &Rc<RwLock<Connection>> {
&self.database
}
pub fn config_path(&self) -> &Path {
self.config_path.as_path()
}
}
pub fn migrate(tx: &Transaction) -> Result<(), String> {

View File

@ -1,22 +1,60 @@
use sqlite::{Error, Transaction};
use gtk::glib::DateTime;
use sqlite::{Connection, Error, Transaction};
use std::{rc::Rc, sync::RwLock};
#[derive(Debug)]
pub struct Table {
pub id: i64,
pub active: bool,
pub is_active: bool,
pub time: DateTime,
pub name: Option<String>,
}
pub struct Database {
pub connection: Rc<RwLock<Connection>>,
}
impl Database {
// Constructors
/// Create new `Self`
pub fn new(connection: Rc<RwLock<Connection>>) -> Self {
Self { connection }
}
// Getters
/// Get all records
pub fn records(&self) -> Vec<Table> {
let binding = self.connection.read().unwrap();
let tx = binding.unchecked_transaction().unwrap();
records(&tx).unwrap()
}
/// Get selected profile record if exist
pub fn selected(&self) -> Option<Table> {
let binding = self.connection.read().unwrap();
let tx = binding.unchecked_transaction().unwrap();
for record in records(&tx).unwrap() {
if record.is_active {
return Some(record);
}
}
None
}
}
pub fn init(tx: &Transaction) -> Result<usize, Error> {
tx.execute(
"CREATE TABLE IF NOT EXISTS `profile`
(
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`active` INTEGER NOT NULL,
`time` INTEGER NOT NULL,
`name` VARCHAR(255)
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`is_active` INTEGER NOT NULL,
`time` INTEGER NOT NULL,
`name` VARCHAR(255)
)",
[],
)
@ -24,19 +62,19 @@ pub fn init(tx: &Transaction) -> Result<usize, Error> {
pub fn add(
tx: &Transaction,
active: bool,
is_active: bool,
time: &DateTime,
name: Option<&str>,
) -> Result<usize, Error> {
tx.execute("INSERT INTO `profile`", (active, time.to_unix(), name))
tx.execute("INSERT INTO `profile`", (is_active, time.to_unix(), name))
}
pub fn records(tx: &Transaction) -> Result<Vec<Table>, Error> {
let mut stmt = tx.prepare("SELECT `id`, `active`, `time`, `name` FROM `profile`")?;
let mut stmt = tx.prepare("SELECT `id`, `is_active`, `time`, `name` FROM `profile`")?;
let result = stmt.query_map([], |row| {
Ok(Table {
id: row.get(0)?,
active: row.get(1)?,
is_active: row.get(1)?,
time: DateTime::from_unix_local(row.get(2)?).unwrap(),
name: row.get(3)?,
})