From 3db4c2c6be562e09ceca66635e2af6d726d75fc6 Mon Sep 17 00:00:00 2001 From: yggverse Date: Tue, 12 Nov 2024 18:02:35 +0200 Subject: [PATCH] integrate bookmark action --- src/app.rs | 8 +++ src/app/browser/action.rs | 10 +-- src/app/browser/window.rs | 5 ++ src/app/browser/window/action.rs | 27 +++++--- src/app/browser/window/action/bookmark.rs | 81 +++++++++++++++++++++++ src/app/browser/window/header/bar/menu.rs | 23 +++++-- src/app/browser/window/tab.rs | 10 +++ src/app/browser/window/tab/item/page.rs | 4 ++ src/app/browser/window/tab/menu.rs | 15 ++++- 9 files changed, 163 insertions(+), 20 deletions(-) create mode 100644 src/app/browser/window/action/bookmark.rs diff --git a/src/app.rs b/src/app.rs index 18cc033d..fa5a26d4 100644 --- a/src/app.rs +++ b/src/app.rs @@ -174,6 +174,14 @@ impl App { ), &["t"], ), + ( + format!( + "{}.{}", + browser.window().action().id(), + browser.window().action().bookmark().id() + ), + &["b"], + ), ( format!( "{}.{}", diff --git a/src/app/browser/action.rs b/src/app/browser/action.rs index 54ef8b58..bf9860de 100644 --- a/src/app/browser/action.rs +++ b/src/app/browser/action.rs @@ -69,27 +69,27 @@ impl Action { // Getters - /// Get reference `About` action + /// Get reference to `About` action pub fn about(&self) -> &Rc { &self.about } - /// Get reference `Close` action + /// Get reference to `Close` action pub fn close(&self) -> &Rc { &self.close } - /// Get reference `Debug` action + /// Get reference to `Debug` action pub fn debug(&self) -> &Rc { &self.debug } - /// Get reference `Profile` action + /// Get reference to `Profile` action pub fn profile(&self) -> &Rc { &self.profile } - /// Get reference `Update` action + /// Get reference to `Update` action pub fn update(&self) -> &Rc { &self.update } diff --git a/src/app/browser/window.rs b/src/app/browser/window.rs index f73212b4..b8fe8f19 100644 --- a/src/app/browser/window.rs +++ b/src/app/browser/window.rs @@ -49,6 +49,11 @@ impl Window { } }); + action.bookmark().connect_activate({ + let tab = tab.clone(); + move |position| tab.bookmark(position) + }); + action.pin().connect_activate({ let tab = tab.clone(); move |position| tab.pin(position) diff --git a/src/app/browser/window/action.rs b/src/app/browser/window/action.rs index 8c52fff4..07afe663 100644 --- a/src/app/browser/window/action.rs +++ b/src/app/browser/window/action.rs @@ -1,4 +1,5 @@ mod append; +mod bookmark; mod close; mod close_all; mod history_back; @@ -8,6 +9,7 @@ mod pin; mod reload; use append::Append; +use bookmark::Bookmark; use close::Close; use close_all::CloseAll; use history_back::HistoryBack; @@ -29,6 +31,7 @@ pub use append::Position; // public enum pub struct Action { // Actions append: Rc, + bookmark: Rc, close_all: Rc, close: Rc, history_back: Rc, @@ -48,6 +51,7 @@ impl Action { pub fn new() -> Self { // Init actions let append = Rc::new(Append::new()); + let bookmark = Rc::new(Bookmark::new()); let close = Rc::new(Close::new()); let close_all = Rc::new(CloseAll::new()); let history_back = Rc::new(HistoryBack::new()); @@ -64,6 +68,7 @@ impl Action { // Add action to given group gobject.add_action(append.gobject()); + gobject.add_action(bookmark.gobject()); gobject.add_action(close_all.gobject()); gobject.add_action(close.gobject()); gobject.add_action(history_back.gobject()); @@ -75,6 +80,7 @@ impl Action { // Done Self { append, + bookmark, close_all, close, history_back, @@ -89,42 +95,47 @@ impl Action { // Getters - /// Get reference `Append` action + /// Get reference to `Append` action pub fn append(&self) -> &Rc { &self.append } - /// Get reference `CloseAll` action + /// Get reference to `Bookmark` action + pub fn bookmark(&self) -> &Rc { + &self.bookmark + } + + /// Get reference to `CloseAll` action pub fn close_all(&self) -> &Rc { &self.close_all } - /// Get reference `Close` action + /// Get reference to `Close` action pub fn close(&self) -> &Rc { &self.close } - /// Get reference `HistoryBack` action + /// Get reference to `HistoryBack` action pub fn history_back(&self) -> &Rc { &self.history_back } - /// Get reference `HistoryForward` action + /// Get reference to `HistoryForward` action pub fn history_forward(&self) -> &Rc { &self.history_forward } - /// Get reference `Home` action + /// Get reference to `Home` action pub fn home(&self) -> &Rc { &self.home } - /// Get reference `Pin` action + /// Get reference to `Pin` action pub fn pin(&self) -> &Rc { &self.pin } - /// Get reference `Reload` action + /// Get reference to `Reload` action pub fn reload(&self) -> &Rc { &self.reload } diff --git a/src/app/browser/window/action/bookmark.rs b/src/app/browser/window/action/bookmark.rs new file mode 100644 index 00000000..4524e60d --- /dev/null +++ b/src/app/browser/window/action/bookmark.rs @@ -0,0 +1,81 @@ +use gtk::{ + gio::SimpleAction, + glib::{uuid_string_random, GString}, + prelude::{ActionExt, ToVariant}, +}; + +// Defaults + +/// C-compatible variant type +const DEFAULT_STATE: i32 = -1; + +/// [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) wrapper for `Home` action of `Window` group +pub struct Bookmark { + gobject: SimpleAction, +} + +impl Bookmark { + // Constructors + + /// Create new `Self` + pub fn new() -> Self { + Self { + gobject: SimpleAction::new_stateful( + &uuid_string_random(), + None, + &DEFAULT_STATE.to_variant(), + ), + } + } + + // Actions + + /// Emit [activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal + pub fn activate(&self) { + self.gobject.activate(None); + } + + /// Change action [state](https://docs.gtk.org/gio/method.SimpleAction.set_state.html) + /// * set `DEFAULT_STATE` on `None` + pub fn change_state(&self, state: Option) { + self.gobject.change_state( + &match state { + Some(value) => value, + None => DEFAULT_STATE, + } + .to_variant(), + ) + } + + // Events + + /// Define callback function for + /// [SimpleAction::activate](https://docs.gtk.org/gio/signal.SimpleAction.activate.html) signal + pub fn connect_activate(&self, callback: impl Fn(Option) + 'static) { + self.gobject.connect_activate(move |this, _| { + let state = this + .state() + .expect("State value required") + .get::() + .expect("Parameter type does not match `i32`"); + + callback(if state == DEFAULT_STATE { + None + } else { + Some(state) + }) + }); + } + + // Getters + + /// Get reference to [SimpleAction](https://docs.gtk.org/gio/class.SimpleAction.html) GObject + pub fn gobject(&self) -> &SimpleAction { + &self.gobject + } + + /// Get auto-generated [action name](https://docs.gtk.org/gio/property.SimpleAction.name.html) + pub fn id(&self) -> GString { + self.gobject.name() + } +} diff --git a/src/app/browser/window/header/bar/menu.rs b/src/app/browser/window/header/bar/menu.rs index 6ba6c58b..15ee9578 100644 --- a/src/app/browser/window/header/bar/menu.rs +++ b/src/app/browser/window/header/bar/menu.rs @@ -36,16 +36,27 @@ impl Menu { window_action.reload().id() ))); - main_page.append(Some("Pin"), Some(&format!( - "{}.{}", - window_action.id(), - window_action.pin().id() - ))); + // Main > Page > Mark + let main_page_mark = gio::Menu::new(); + + main_page_mark.append(Some("Bookmark"), Some(&format!( + "{}.{}", + window_action.id(), + window_action.bookmark().id() + ))); + + main_page_mark.append(Some("Pin"), Some(&format!( + "{}.{}", + window_action.id(), + window_action.pin().id() + ))); + + main_page.append_section(None, &main_page_mark); // Main > Page > Navigation let main_page_navigation = gio::Menu::new(); - main_page.append(Some("Home"), Some(&format!( + main_page_navigation.append(Some("Home"), Some(&format!( "{}.{}", window_action.id(), window_action.home().id() diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index c177ba15..f27850fe 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -152,6 +152,16 @@ impl Tab { self.widget.close_all(); } + pub fn bookmark(&self, page_position: Option) { + if let Some(page) = self.widget.page(page_position) { + if let Some(id) = page.keyword() { + if let Some(item) = self.index.borrow().get(&id) { + item.page().bookmark(); + } + } + } + } + // Toggle pin status for active tab pub fn pin(&self, page_position: Option) { self.widget.pin(page_position); diff --git a/src/app/browser/window/tab/item/page.rs b/src/app/browser/window/tab/item/page.rs index 6f725562..fee6ae5a 100644 --- a/src/app/browser/window/tab/item/page.rs +++ b/src/app/browser/window/tab/item/page.rs @@ -88,6 +88,10 @@ impl Page { // Actions + pub fn bookmark(&self) { + // @TODO self.navigation.request().widget().gobject().text() + } + /// Navigate home URL (parsed from current navigation entry) /// * this method create new history record in memory as defined in `action_page_open` action pub fn home(&self) { diff --git a/src/app/browser/window/tab/menu.rs b/src/app/browser/window/tab/menu.rs index de6eb1c7..9a084975 100644 --- a/src/app/browser/window/tab/menu.rs +++ b/src/app/browser/window/tab/menu.rs @@ -24,7 +24,18 @@ impl Menu { )), ); - main.append( + let main_mark = gtk::gio::Menu::new(); + + main_mark.append( + Some("Bookmark"), + Some(&format!( + "{}.{}", + window_action.id(), + window_action.bookmark().id() + )), + ); + + main_mark.append( Some("Pin"), Some(&format!( "{}.{}", @@ -33,6 +44,8 @@ impl Menu { )), ); + main.append_section(None, &main_mark); + let navigation = gtk::gio::Menu::new(); navigation.append(