Browse Source

implement tab restore feature

master
yggverse 2 months ago
parent
commit
09c08b2b6f
  1. 2
      src/app/browser/window.rs
  2. 20
      src/app/browser/window/tab.rs
  3. 31
      src/app/browser/window/tab/item.rs
  4. 25
      src/app/browser/window/tab/item/database.rs
  5. 19
      src/app/browser/window/tab/item/page.rs
  6. 13
      src/app/browser/window/tab/item/widget.rs
  7. 4
      src/app/browser/window/tab/widget.rs

2
src/app/browser/window.rs

@ -11,7 +11,7 @@ use widget::Widget;
use std::sync::Arc; use std::sync::Arc;
use gtk::{gio::SimpleAction, glib::GString, Box}; use gtk::{gio::SimpleAction, Box};
pub struct Window { pub struct Window {
//header: Arc<Header>, //header: Arc<Header>,

20
src/app/browser/window/tab.rs

@ -10,7 +10,6 @@ use adw::TabView;
use gtk::{ use gtk::{
gio::SimpleAction, gio::SimpleAction,
glib::{GString, Propagation}, glib::{GString, Propagation},
prelude::{ActionExt, WidgetExt},
}; };
use sqlite::Transaction; use sqlite::Transaction;
use std::{cell::RefCell, collections::HashMap, sync::Arc}; use std::{cell::RefCell, collections::HashMap, sync::Arc};
@ -46,7 +45,7 @@ impl Tab {
let widget = Arc::new(Widget::new()); let widget = Arc::new(Widget::new());
// Init events // Init events
widget.gobject().connect_close_page(move |_, tab_page| { widget.gobject().connect_close_page(move |_, _| {
/* @TODO /* @TODO
// Cleanup HashMap index // Cleanup HashMap index
let id = tab_page.widget_name(); let id = tab_page.widget_name();
@ -203,9 +202,6 @@ impl Tab {
for item in items { for item in items {
// Register dynamically created tab item in the HashMap index // Register dynamically created tab item in the HashMap index
self.index.borrow_mut().insert(item.id(), item.clone()); self.index.borrow_mut().insert(item.id(), item.clone());
// Append new page
self.append();
} }
// Append just one blank page if nothing to restore // Append just one blank page if nothing to restore
@ -233,25 +229,15 @@ impl Tab {
// Delegate save action to childs // Delegate save action to childs
let id = Database::last_insert_id(transaction); let id = Database::last_insert_id(transaction);
// At least one active page wanted to continue
/* @TODO
if let Some(current_page) = self.widget.gobject().current_page() {
// Read collected HashMap index // Read collected HashMap index
for (_, item) in self.index.borrow().iter() { for (_, item) in self.index.borrow().iter() {
// Get page number as HashMap does not keep order, no page_reorder listener also
match self.widget.gobject().page_num(item.page()) {
Some(page_number) => {
item.save( item.save(
transaction, transaction,
&id, &id,
&page_number, &self.widget.gobject().page_position(item.gobject()),
&(current_page == page_number), &item.gobject().is_selected(),
)?; )?;
} }
None => panic!(), // page number expected at this point @TODO Err?
}
}
}; */
} }
Err(e) => return Err(e.to_string()), Err(e) => return Err(e.to_string()),
} }

31
src/app/browser/window/tab/item.rs

@ -6,11 +6,10 @@ use database::Database;
use page::Page; use page::Page;
use widget::Widget; use widget::Widget;
use adw::TabView; use adw::{TabPage, TabView};
use gtk::{ use gtk::{
gio::SimpleAction, gio::SimpleAction,
glib::{uuid_string_random, GString}, glib::{uuid_string_random, GString},
Box,
}; };
use sqlite::Transaction; use sqlite::Transaction;
use std::sync::Arc; use std::sync::Arc;
@ -35,7 +34,7 @@ impl Item {
action_tab_page_navigation_reload: Arc<SimpleAction>, action_tab_page_navigation_reload: Arc<SimpleAction>,
action_update: Arc<SimpleAction>, action_update: Arc<SimpleAction>,
// Options // Options
is_selected_page: bool, is_selected: bool,
) -> Arc<Self> { ) -> Arc<Self> {
// Generate unique ID for new page components // Generate unique ID for new page components
let id = uuid_string_random(); let id = uuid_string_random();
@ -50,7 +49,7 @@ impl Item {
action_update.clone(), action_update.clone(),
); );
let widget = Widget::new_arc(tab_view, page.gobject(), Some("New page"), is_selected_page); // @TODO let widget = Widget::new_arc(tab_view, page.gobject(), None, is_selected); // @TODO
// Return struct // Return struct
Arc::new(Self { id, page, widget }) Arc::new(Self { id, page, widget })
@ -138,7 +137,7 @@ impl Item {
action_tab_page_navigation_reload.clone(), action_tab_page_navigation_reload.clone(),
action_update.clone(), action_update.clone(),
// Options // Options
true, record.is_selected,
); );
// Delegate restore action to the item childs // Delegate restore action to the item childs
@ -160,9 +159,15 @@ impl Item {
&self, &self,
transaction: &Transaction, transaction: &Transaction,
app_browser_window_tab_id: &i64, app_browser_window_tab_id: &i64,
page_number: &u32, page_position: &i32,
is_selected: &bool,
) -> Result<(), String> { ) -> Result<(), String> {
match Database::add(transaction, app_browser_window_tab_id, page_number) { match Database::add(
transaction,
app_browser_window_tab_id,
page_position,
is_selected,
) {
Ok(_) => { Ok(_) => {
let id = Database::last_insert_id(transaction); let id = Database::last_insert_id(transaction);
@ -182,16 +187,8 @@ impl Item {
self.id.clone() self.id.clone()
} }
pub fn gobject(&self) -> &Box { pub fn gobject(&self) -> &TabPage {
&self.page.gobject() &self.widget.gobject()
}
pub fn page_title(&self) -> Option<GString> {
self.page.title()
}
pub fn page_description(&self) -> Option<GString> {
self.page.description()
} }
// Tools // Tools

25
src/app/browser/window/tab/item/database.rs

@ -3,6 +3,7 @@ use sqlite::{Error, Transaction};
pub struct Table { pub struct Table {
pub id: i64, pub id: i64,
// pub app_browser_window_tab_id: i64, not in use // pub app_browser_window_tab_id: i64, not in use
pub is_selected: bool,
} }
pub struct Database { pub struct Database {
@ -16,7 +17,8 @@ impl Database {
( (
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
`app_browser_window_tab_id` INTEGER NOT NULL, `app_browser_window_tab_id` INTEGER NOT NULL,
`page_number` INTEGER NOT NULL `page_position` INTEGER NOT NULL,
`is_selected` INTEGER NOT NULL
)", )",
[], [],
) )
@ -25,29 +27,38 @@ impl Database {
pub fn add( pub fn add(
tx: &Transaction, tx: &Transaction,
app_browser_window_tab_id: &i64, app_browser_window_tab_id: &i64,
page_number: &u32, page_position: &i32,
is_selected: &bool,
) -> Result<usize, Error> { ) -> Result<usize, Error> {
tx.execute( tx.execute(
"INSERT INTO `app_browser_window_tab_item` ( "INSERT INTO `app_browser_window_tab_item` (
`app_browser_window_tab_id`, `app_browser_window_tab_id`,
`page_number` `page_position`,
) VALUES (?, ?)", `is_selected`
[app_browser_window_tab_id, &(*page_number as i64)], ) VALUES (?, ?, ?)",
[
app_browser_window_tab_id,
&(*page_position as i64),
&(*is_selected as i64),
],
) )
} }
pub fn records(tx: &Transaction, app_browser_window_tab_id: &i64) -> Result<Vec<Table>, Error> { pub fn records(tx: &Transaction, app_browser_window_tab_id: &i64) -> Result<Vec<Table>, Error> {
let mut stmt = tx.prepare( let mut stmt = tx.prepare(
"SELECT `id`, "SELECT `id`,
`app_browser_window_tab_id` FROM `app_browser_window_tab_item` `app_browser_window_tab_id`,
`is_selected`
FROM `app_browser_window_tab_item`
WHERE `app_browser_window_tab_id` = ? WHERE `app_browser_window_tab_id` = ?
ORDER BY `page_number` ASC", // just order by, no store in struct wanted ORDER BY `page_position` ASC", // just order by, no store in struct wanted
)?; )?;
let result = stmt.query_map([app_browser_window_tab_id], |row| { let result = stmt.query_map([app_browser_window_tab_id], |row| {
Ok(Table { Ok(Table {
id: row.get(0)?, id: row.get(0)?,
// app_browser_window_tab_id: row.get(1)?, not in use // app_browser_window_tab_id: row.get(1)?, not in use
is_selected: row.get(2)?,
}) })
})?; })?;

19
src/app/browser/window/tab/item/page.rs

@ -9,16 +9,13 @@ use navigation::Navigation;
use widget::Widget; use widget::Widget;
use gtk::{ use gtk::{
gio::{ gio::{Cancellable, SimpleAction, SocketClient, SocketProtocol, TlsCertificateFlags},
Cancellable, SimpleAction, SimpleActionGroup, SocketClient, SocketProtocol,
TlsCertificateFlags,
},
glib::{gformat, GString, Priority, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags}, glib::{gformat, GString, Priority, Regex, RegexCompileFlags, RegexMatchFlags, Uri, UriFlags},
prelude::{ prelude::{
ActionExt, ActionMapExt, BoxExt, IOStreamExt, InputStreamExtManual, OutputStreamExtManual, ActionExt, IOStreamExt, InputStreamExtManual, OutputStreamExtManual, SocketClientExt,
SocketClientExt, StaticVariantType, ToVariant, WidgetExt, StaticVariantType, ToVariant,
}, },
Box, Orientation, Box,
}; };
use std::{cell::RefCell, path::Path, sync::Arc}; use std::{cell::RefCell, path::Path, sync::Arc};
@ -466,14 +463,6 @@ impl Page {
} }
// Getters // Getters
pub fn title(&self) -> Option<GString> {
self.meta.borrow().title.clone()
}
pub fn description(&self) -> Option<GString> {
self.meta.borrow().description.clone()
}
pub fn gobject(&self) -> &Box { pub fn gobject(&self) -> &Box {
&self.widget.gobject() &self.widget.gobject()
} }

13
src/app/browser/window/tab/item/widget.rs

@ -2,6 +2,8 @@ use adw::{TabPage, TabView};
use gtk::Box; use gtk::Box;
use std::sync::Arc; use std::sync::Arc;
const DEFAULT_TITLE: &str = "New page";
pub struct Widget { pub struct Widget {
gobject: TabPage, gobject: TabPage,
} }
@ -12,15 +14,16 @@ impl Widget {
tab_view: &TabView, tab_view: &TabView,
page: &Box, page: &Box,
title: Option<&str>, title: Option<&str>,
is_selected_page: bool, is_selected: bool,
) -> Arc<Self> { ) -> Arc<Self> {
let gobject = tab_view.append(page); let gobject = tab_view.append(page);
if let Some(value) = title { gobject.set_title(match title {
gobject.set_title(value); Some(value) => value,
} None => DEFAULT_TITLE,
});
if is_selected_page { if is_selected {
tab_view.set_selected_page(&gobject); tab_view.set_selected_page(&gobject);
} }

4
src/app/browser/window/tab/widget.rs

@ -1,5 +1,5 @@
use adw::{TabPage, TabView}; use adw::TabView;
use gtk::{glib::GString, Box}; use gtk::glib::GString;
pub struct Widget { pub struct Widget {
gobject: TabView, gobject: TabView,

Loading…
Cancel
Save