diff --git a/src/app/browser.rs b/src/app/browser.rs index eed91c2e..58df588f 100644 --- a/src/app/browser.rs +++ b/src/app/browser.rs @@ -1,30 +1,27 @@ mod database; mod header; mod main; +mod widget; use database::Database; use header::Header; use main::Main; +use widget::Widget; use gtk::{ gio::{AppInfo, AppLaunchContext, SimpleAction}, - prelude::{ActionMapExt, GtkWindowExt, WidgetExt}, + prelude::{ActionMapExt, GtkWindowExt}, ApplicationWindow, }; use std::{path::PathBuf, sync::Arc}; -const DEFAULT_HEIGHT: i32 = 480; -const DEFAULT_WIDTH: i32 = 640; -const MAXIMIZED: bool = false; - pub struct Browser { // Extras database: Arc, // Components // header: Arc
, // main: Arc
, - // GTK - widget: ApplicationWindow, + widget: Arc, } impl Browser { @@ -48,7 +45,7 @@ impl Browser { action_tab_pin: Arc, ) -> Browser { // Init database - let database = match Database::init(profile_database_connection) { + let database = match Database::init(profile_database_connection.clone()) { Ok(database) => Arc::new(database), Err(error) => panic!("{error}"), // @TODO }; @@ -77,33 +74,64 @@ impl Browser { )); // Init widget - let widget = ApplicationWindow::builder() - .titlebar(header.widget()) - .child(main.widget()) - .default_height(DEFAULT_HEIGHT) - .default_width(DEFAULT_WIDTH) - .maximized(MAXIMIZED) - .build(); + let widget = Arc::new(Widget::new( + profile_database_connection.clone(), + header.widget(), + main.widget(), + )); // Assign actions - widget.add_action(action_tool_debug.as_ref()); - widget.add_action(action_tool_profile_directory.as_ref()); - widget.add_action(action_quit.as_ref()); - widget.add_action(action_update.as_ref()); - widget.add_action(action_tab_append.as_ref()); - widget.add_action(action_tab_close.as_ref()); - widget.add_action(action_tab_close_all.as_ref()); - widget.add_action(action_tab_page_navigation_base.as_ref()); - widget.add_action(action_tab_page_navigation_history_back.as_ref()); - widget.add_action(action_tab_page_navigation_history_forward.as_ref()); - widget.add_action(action_tab_page_navigation_reload.as_ref()); - widget.add_action(action_tab_pin.as_ref()); + widget + .application_window() + .add_action(action_tool_debug.as_ref()); + + widget + .application_window() + .add_action(action_tool_profile_directory.as_ref()); + + widget.application_window().add_action(action_quit.as_ref()); + + widget + .application_window() + .add_action(action_update.as_ref()); + + widget + .application_window() + .add_action(action_tab_append.as_ref()); + + widget + .application_window() + .add_action(action_tab_close.as_ref()); + + widget + .application_window() + .add_action(action_tab_close_all.as_ref()); + + widget + .application_window() + .add_action(action_tab_page_navigation_base.as_ref()); + + widget + .application_window() + .add_action(action_tab_page_navigation_history_back.as_ref()); + + widget + .application_window() + .add_action(action_tab_page_navigation_history_forward.as_ref()); + + widget + .application_window() + .add_action(action_tab_page_navigation_reload.as_ref()); + + widget + .application_window() + .add_action(action_tab_pin.as_ref()); // Init events action_tool_debug.connect_activate({ let widget = widget.clone(); move |_, _| { - widget.emit_enable_debugging(true); + widget.application_window().emit_enable_debugging(true); } }); @@ -120,7 +148,7 @@ impl Browser { action_quit.connect_activate({ let widget = widget.clone(); move |_, _| { - widget.close(); + widget.application_window().close(); } }); @@ -206,8 +234,10 @@ impl Browser { match self.database.delete(record.id) { Ok(_) => { // Delegate clean action to childs + // @TODO // self.header.clean(record.id); // self.main.clean(record.id); + self.widget.clean(record.id); } Err(error) => panic!("{error}"), // @TODO } @@ -222,17 +252,14 @@ impl Browser { } pub fn save(&self, app_id: i64) { - match self.database.add( - app_id, - self.widget.default_width(), - self.widget.default_height(), - self.widget.is_maximized(), - ) { + match self.database.add(app_id) { Ok(_) => { // Delegate save action to childs - // let id = self.database.last_insert_id(); + let id = self.database.last_insert_id(); + // @TODO // self.header.save(id); // self.main.save(id); + self.widget.save(id); } Err(error) => panic!("{error}"), // @TODO } @@ -240,6 +267,6 @@ impl Browser { // Getters pub fn widget(&self) -> &ApplicationWindow { - &self.widget + &self.widget.application_window() } } diff --git a/src/app/browser/database.rs b/src/app/browser/database.rs index d91a1c2f..65f7e8a2 100644 --- a/src/app/browser/database.rs +++ b/src/app/browser/database.rs @@ -5,9 +5,6 @@ pub struct Table { pub id: i64, pub app_id: i64, // pub time: i64, - pub default_width: i32, - pub default_height: i32, - pub is_maximized: bool, } pub struct Database { @@ -21,10 +18,7 @@ impl Database { ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `time` INTEGER NOT NULL DEFAULT (UNIXEPOCH('NOW')), - `app_id` INTEGER NOT NULL, - `default_width` INTEGER NOT NULL, - `default_height` INTEGER NOT NULL, - `is_maximized` INTEGER NOT NULL + `app_id` INTEGER NOT NULL )", [], )?; @@ -32,48 +26,20 @@ impl Database { Ok(Self { connection }) } - pub fn add( - &self, - app_id: i64, - default_width: i32, - default_height: i32, - is_maximized: bool, - ) -> Result { - self.connection.execute( - "INSERT INTO `app_browser` ( - `app_id`, - `default_width`, - `default_height`, - `is_maximized` - ) VALUES (?, ?, ?, ?)", - [ - app_id, - default_width as i64, - default_height as i64, - match is_maximized { - true => 1, - false => 0, - }, - ], - ) + pub fn add(&self, app_id: i64) -> Result { + self.connection + .execute("INSERT INTO `app_browser` (`app_id`) VALUES (?)", [app_id]) } pub fn records(&self, app_id: i64) -> Result, Error> { - let mut statement = self.connection.prepare( - "SELECT `id`, - `app_id`, - `default_width`, - `default_height`, - `is_maximized` FROM `app_browser` WHERE `app_id` = ?", - )?; + let mut statement = self + .connection + .prepare("SELECT `id`, `app_id` WHERE `app_id` = ?")?; let result = statement.query_map([app_id], |row| { Ok(Table { id: row.get(0)?, app_id: row.get(1)?, - default_width: row.get(2)?, - default_height: row.get(3)?, - is_maximized: row.get(4)?, }) })?; diff --git a/src/app/browser/widget.rs b/src/app/browser/widget.rs new file mode 100644 index 00000000..39d821ec --- /dev/null +++ b/src/app/browser/widget.rs @@ -0,0 +1,89 @@ +mod database; + +use database::Database; + +use gtk::{prelude::GtkWindowExt, ApplicationWindow, Box, HeaderBar}; +use std::sync::Arc; + +// Default options +const DEFAULT_HEIGHT: i32 = 480; +const DEFAULT_WIDTH: i32 = 640; +const MAXIMIZED: bool = false; + +pub struct Widget { + database: Arc, + application_window: ApplicationWindow, +} + +impl Widget { + // Construct + pub fn new( + profile_database_connection: Arc, + titlebar: &HeaderBar, + child: &Box, + ) -> Self { + // Init database + let database = match Database::init(profile_database_connection) { + Ok(database) => Arc::new(database), + Err(error) => panic!("{error}"), // @TODO + }; + + // Init GTK + let application_window = ApplicationWindow::builder() + .titlebar(titlebar) + .child(child) + .default_height(DEFAULT_HEIGHT) + .default_width(DEFAULT_WIDTH) + .maximized(MAXIMIZED) + .build(); + + // Return new struct + Self { + database, + application_window, + } + } + + // Actions + pub fn clean(&self, app_browser_id: i64) { + match self.database.records(app_browser_id) { + Ok(records) => { + for record in records { + match self.database.delete(record.id) { + Ok(_) => { + // Delegate clean action to childs + // nothing yet.. + } + Err(error) => panic!("{error}"), // @TODO + } + } + } + Err(error) => panic!("{error}"), // @TODO + } + } + + pub fn restore(&self) { + // @TODO + } + + pub fn save(&self, app_browser_id: i64) { + match self.database.add( + app_browser_id, + self.application_window.default_width(), + self.application_window.default_height(), + self.application_window.is_maximized(), + ) { + Ok(_) => { + // Delegate save action to childs + // let id = self.database.last_insert_id(); + // nothing yet.. + } + Err(error) => panic!("{error}"), // @TODO + } + } + + // Getters + pub fn application_window(&self) -> &ApplicationWindow { + &self.application_window + } +} diff --git a/src/app/browser/widget/database.rs b/src/app/browser/widget/database.rs new file mode 100644 index 00000000..10bfc670 --- /dev/null +++ b/src/app/browser/widget/database.rs @@ -0,0 +1,98 @@ +use sqlite::{Connection, Error}; +use std::sync::Arc; + +pub struct Table { + pub id: i64, + pub app_browser_id: i64, + // pub time: i64, + pub default_width: i32, + pub default_height: i32, + pub is_maximized: bool, +} + +pub struct Database { + connection: Arc, +} + +impl Database { + pub fn init(connection: Arc) -> Result { + connection.execute( + "CREATE TABLE IF NOT EXISTS `app_browser_widget` + ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + `time` INTEGER NOT NULL DEFAULT (UNIXEPOCH('NOW')), + `app_browser_id` INTEGER NOT NULL, + `default_width` INTEGER NOT NULL, + `default_height` INTEGER NOT NULL, + `is_maximized` INTEGER NOT NULL + )", + [], + )?; + + Ok(Self { connection }) + } + + pub fn add( + &self, + app_browser_id: i64, + default_width: i32, + default_height: i32, + is_maximized: bool, + ) -> Result { + self.connection.execute( + "INSERT INTO `app_browser_widget` ( + `app_browser_id`, + `default_width`, + `default_height`, + `is_maximized` + ) VALUES (?, ?, ?, ?)", + [ + app_browser_id, + default_width as i64, + default_height as i64, + match is_maximized { + true => 1, + false => 0, + }, + ], + ) + } + + pub fn records(&self, app_browser_id: i64) -> Result, Error> { + let mut statement = self.connection.prepare( + "SELECT `id`, + `app_browser_id`, + `default_width`, + `default_height`, + `is_maximized` FROM `app_browser_widget` WHERE `app_browser_id` = ?", + )?; + + let result = statement.query_map([app_browser_id], |row| { + Ok(Table { + id: row.get(0)?, + app_browser_id: row.get(1)?, + default_width: row.get(2)?, + default_height: row.get(3)?, + is_maximized: row.get(4)?, + }) + })?; + + let mut records = Vec::new(); + + for record in result { + let table = record?; + records.push(table); + } + + Ok(records) + } + + pub fn delete(&self, id: i64) -> Result { + self.connection + .execute("DELETE FROM `app_browser_widget` WHERE `id` = ?", [id]) + } + + pub fn last_insert_id(&self) -> i64 { + self.connection.last_insert_rowid() + } +}