diff --git a/data/gtk/window.blp b/data/gtk/window.blp index e75ffa2..7dcd740 100644 --- a/data/gtk/window.blp +++ b/data/gtk/window.blp @@ -47,323 +47,314 @@ template $CartridgesWindow : Adw.ApplicationWindow { title: _("Cartridges"); Adw.ToastOverlay toast_overlay { - Stack stack { - visible-child: library_view; - transition-type: over_left; + Adw.NavigationView navigation_view { + Adw.NavigationPage library_page { + title: _("Cartridges"); - Overlay details_view { - name: "details_view"; + Adw.ToolbarView library_view { + [top] + Adw.HeaderBar header_bar { + [start] + MenuButton { + tooltip-text: _("Add Game"); + icon-name: "list-add-symbolic"; + menu-model: add_games; + } - [overlay] - Box details_view_box { - orientation: vertical; + [end] + MenuButton primary_menu_button { + tooltip-text: _("Main Menu"); + icon-name: "open-menu-symbolic"; + menu-model: primary_menu; + } - Adw.HeaderBar { - [start] - Button back_button { - tooltip-text: _("Back"); - action-name: "win.go_back"; - icon-name: "go-previous-symbolic"; + [end] + ToggleButton search_button { + tooltip-text: _("Search"); + icon-name: "system-search-symbolic"; + action-name: "win.toggle_search"; + } } - [title] - Adw.WindowTitle details_view_header_bar_title { - title: _("Game Details"); - } - - styles [ - "flat", - ] - } - - Adw.Bin { - hexpand: true; - vexpand: true; - - Box { - halign: center; - valign: center; - margin-start: 24; - margin-end: 24; - margin-top: 24; - margin-bottom: 24; + [top] + SearchBar search_bar { + search-mode-enabled: bind-property search_button.active bidirectional; + key-capture-widget: library_view; Adw.Clamp { - maximum-size: 200; + maximum-size: 500; + tightening-threshold: 500; - Overlay { - [overlay] - Spinner details_view_spinner { - margin-start: 72; - margin-end: 72; - } - - Picture details_view_cover { - halign: end; - valign: start; - width-request: 200; - height-request: 300; - - styles [ - "card", - ] - } + SearchEntry search_entry { + hexpand: true; } } + } + + Overlay library_overlay { + ScrolledWindow scrolledwindow { + FlowBox library { + homogeneous: true; + halign: center; + valign: start; + column-spacing: 12; + row-spacing: 12; + margin-top: 15; + margin-bottom: 15; + margin-start: 15; + margin-end: 15; + selection-mode: none; + } + } + } + } + } + } + } + } + +Adw.NavigationPage hidden_library_page { + title: _("Hidden Games"); + + Adw.ToolbarView hidden_library_view { + [top] + Adw.HeaderBar hidden_header_bar { + [end] + MenuButton hidden_primary_menu_button { + tooltip-text: _("Main Menu"); + icon-name: "open-menu-symbolic"; + menu-model: primary_menu; + } + + [end] + ToggleButton hidden_search_button { + tooltip-text: _("Search"); + icon-name: "system-search-symbolic"; + action-name: "win.toggle_search"; + } + } + + [top] + SearchBar hidden_search_bar { + search-mode-enabled: bind-property hidden_search_button.active bidirectional; + key-capture-widget: hidden_library_view; + + Adw.Clamp { + maximum-size: 500; + tightening-threshold: 500; + + SearchEntry hidden_search_entry { + hexpand: true; + } + } + } + + Overlay hidden_library_overlay { + ScrolledWindow hidden_scrolledwindow { + FlowBox hidden_library { + homogeneous: true; + halign: center; + valign: start; + column-spacing: 12; + row-spacing: 12; + margin-top: 15; + margin-bottom: 15; + margin-start: 15; + margin-end: 15; + selection-mode: none; + } + } + } + + styles [ + "background", + ] + } +} + +Adw.NavigationPage details_page { + title: _("Game Details"); + + Overlay details_view { + name: "details_view"; + + [overlay] + Box details_view_box { + orientation: vertical; + + Adw.HeaderBar { + styles [ + "flat", + ] + } + + Adw.Bin { + hexpand: true; + vexpand: true; + + Box { + halign: center; + valign: center; + margin-start: 24; + margin-end: 24; + margin-top: 24; + margin-bottom: 24; + + Adw.Clamp { + maximum-size: 200; + + Overlay { + [overlay] + Spinner details_view_spinner { + margin-start: 72; + margin-end: 72; + } + + Picture details_view_cover { + halign: end; + valign: start; + width-request: 200; + height-request: 300; + + styles [ + "card", + ] + } + } + } + + Box { + orientation: vertical; + margin-start: 48; + vexpand: true; + valign: center; + + Label details_view_title { + label: _("Game Title"); + hexpand: true; + halign: start; + max-width-chars: 24; + wrap: true; + wrap-mode: word_char; + natural-wrap-mode: word; + + styles [ + "title-1", + ] + } + + Label details_view_developer { + margin-top: 6; + hexpand: true; + halign: start; + max-width-chars: 36; + wrap: true; + wrap-mode: word_char; + natural-wrap-mode: word; + + styles [ + "heading", + ] + } + + Box { + orientation: horizontal; + margin-top: 15; + hexpand: true; + halign: start; + + Label details_view_added { + wrap: true; + wrap-mode: word_char; + natural-wrap-mode: word; + } + + Label details_view_last_played { + margin-start: 12; + wrap: true; + wrap-mode: word_char; + natural-wrap-mode: word; + } + } + + Box { + hexpand: true; + vexpand: true; + valign: center; + + Button details_view_play_button { + name: "details_view_play_button"; + action-name: "app.launch_game"; + label: _("Play"); + halign: start; + margin-top: 24; + + styles [ + "opaque", + "pill", + ] + } Box { - orientation: vertical; - margin-start: 48; - vexpand: true; + halign: start; valign: center; + margin-top: 24; + margin-start: 9; - Label details_view_title { - label: _("Game Title"); - hexpand: true; - halign: start; - max-width-chars: 24; - wrap: true; - wrap-mode: word_char; - natural-wrap-mode: word; + Button { + icon-name: "document-edit-symbolic"; + action-name: "app.edit_game"; + tooltip-text: _("Edit"); styles [ - "title-1", + "raised", + "circular", ] } - Label details_view_developer { - margin-top: 6; - hexpand: true; - halign: start; - max-width-chars: 36; - wrap: true; - wrap-mode: word_char; - natural-wrap-mode: word; + Button details_view_hide_button { + action-name: "app.hide_game"; styles [ - "heading", + "raised", + "circular", ] } - Box { - orientation: horizontal; - margin-top: 15; - hexpand: true; - halign: start; + Button { + icon-name: "user-trash-symbolic"; + action-name: "app.remove_game"; + tooltip-text: _("Remove"); - Label details_view_added { - wrap: true; - wrap-mode: word_char; - natural-wrap-mode: word; - } - - Label details_view_last_played { - margin-start: 12; - wrap: true; - wrap-mode: word_char; - natural-wrap-mode: word; - } + styles [ + "raised", + "circular", + ] } - Box { - hexpand: true; - vexpand: true; - valign: center; + MenuButton { + icon-name: "system-search-symbolic"; + menu-model: search; + tooltip-text: _("Search"); - Button details_view_play_button { - name: "details_view_play_button"; - action-name: "app.launch_game"; - label: _("Play"); - halign: start; - margin-top: 24; - - styles [ - "opaque", - "pill", - ] - } - - Box { - halign: start; - valign: center; - margin-top: 24; - margin-start: 9; - - Button { - icon-name: "document-edit-symbolic"; - action-name: "app.edit_game"; - tooltip-text: _("Edit"); - - styles ["raised", "circular"] - } - - Button details_view_hide_button { - action-name: "app.hide_game"; - - styles ["raised", "circular"] - } - - Button { - icon-name: "user-trash-symbolic"; - action-name: "app.remove_game"; - tooltip-text: _("Remove"); - - styles ["raised", "circular"] - } - - MenuButton { - icon-name: "system-search-symbolic"; - menu-model: search; - tooltip-text: _("Search"); - - styles ["raised", "circular"] - } - - styles [ - "toolbar", - ] - } + styles [ + "raised", + "circular", + ] } + + styles [ + "toolbar", + ] } } } } - - Picture details_view_blurred_cover { - keep-aspect-ratio: false; - } } + } - Box library_view { - orientation: vertical; - - Adw.HeaderBar header_bar { - [start] - MenuButton { - tooltip-text: _("Add Game"); - icon-name: "list-add-symbolic"; - menu-model: add_games; - } - - [end] - MenuButton primary_menu_button { - tooltip-text: _("Main Menu"); - icon-name: "open-menu-symbolic"; - menu-model: primary_menu; - } - - [end] - ToggleButton search_button { - tooltip-text: _("Search"); - icon-name: "system-search-symbolic"; - action-name: "win.toggle_search"; - } - } - - SearchBar search_bar { - search-mode-enabled: bind-property search_button.active bidirectional; - key-capture-widget: library_view; - - Adw.Clamp { - maximum-size: 500; - tightening-threshold: 500; - - SearchEntry search_entry { - hexpand: true; - } - } - } - - Adw.Bin library_bin { - ScrolledWindow scrolledwindow { - hexpand: true; - vexpand: true; - - FlowBox library { - homogeneous: true; - halign: center; - valign: start; - column-spacing: 12; - row-spacing: 12; - margin-top: 15; - margin-bottom: 15; - margin-start: 15; - margin-end: 15; - selection-mode: none; - } - } - } - } - - Box hidden_library_view { - orientation: vertical; - - Adw.HeaderBar hidden_header_bar { - [start] - Button hidden_back_button { - tooltip-text: _("Back"); - action-name: "win.go_back"; - icon-name: "go-previous-symbolic"; - } - - [title] - Adw.WindowTitle { - title: _("Hidden Games"); - } - - [end] - MenuButton hidden_primary_menu_button { - tooltip-text: _("Main Menu"); - icon-name: "open-menu-symbolic"; - menu-model: primary_menu; - } - - [end] - ToggleButton hidden_search_button { - tooltip-text: _("Search"); - icon-name: "system-search-symbolic"; - action-name: "win.toggle_search"; - } - } - - SearchBar hidden_search_bar { - search-mode-enabled: bind-property hidden_search_button.active bidirectional; - key-capture-widget: hidden_library_view; - - Adw.Clamp { - maximum-size: 500; - tightening-threshold: 500; - - SearchEntry hidden_search_entry { - hexpand: true; - } - } - } - - Adw.Bin hidden_library_bin { - ScrolledWindow hidden_scrolledwindow { - hexpand: true; - vexpand: true; - - FlowBox hidden_library { - homogeneous: true; - halign: center; - valign: start; - column-spacing: 12; - row-spacing: 12; - margin-top: 15; - margin-bottom: 15; - margin-start: 15; - margin-end: 15; - selection-mode: none; - } - } - } - - styles [ - "background", - ] - } + Picture details_view_blurred_cover { + keep-aspect-ratio: false; } } } diff --git a/data/hu.kramo.Cartridges.gschema.xml.in b/data/hu.kramo.Cartridges.gschema.xml.in index 4fffaad..8468ac5 100644 --- a/data/hu.kramo.Cartridges.gschema.xml.in +++ b/data/hu.kramo.Cartridges.gschema.xml.in @@ -91,7 +91,7 @@ 1110 - 820 + 795 false diff --git a/flatpak/hu.kramo.Cartridges.Devel.json b/flatpak/hu.kramo.Cartridges.Devel.json index 1c984ab..7fb6a8e 100644 --- a/flatpak/hu.kramo.Cartridges.Devel.json +++ b/flatpak/hu.kramo.Cartridges.Devel.json @@ -1,7 +1,7 @@ { "id" : "hu.kramo.Cartridges.Devel", "runtime" : "org.gnome.Platform", - "runtime-version" : "44", + "runtime-version" : "master", "sdk" : "org.gnome.Sdk", "command" : "cartridges", "finish-args" : [ diff --git a/src/details_window.py b/src/details_window.py index 19eaa35..61280ff 100644 --- a/src/details_window.py +++ b/src/details_window.py @@ -219,7 +219,7 @@ class DetailsWindow(Adw.Window): self.game_cover.pictures.remove(self.cover) self.close() - self.win.show_details_view(self.game) + self.win.show_details_page(self.game) def update_cover_callback(self, manager: SGDBManager): # Set the game as not loading diff --git a/src/game.py b/src/game.py index 34dbf84..0f281c0 100644 --- a/src/game.py +++ b/src/game.py @@ -141,8 +141,8 @@ class Game(Gtk.Box): self.hidden = not self.hidden self.save() - if self.win.stack.get_visible_child() == self.win.details_view: - self.win.on_go_back_action() + if self.win.navigation_view.get_visible_page() == self.win.details_page: + self.win.navigation_view.pop() self.update() @@ -161,8 +161,8 @@ class Game(Gtk.Box): self.save() self.update() - if self.win.stack.get_visible_child() == self.win.details_view: - self.win.on_go_back_action() + if self.win.navigation_view.get_visible_page() == self.win.details_page: + self.win.navigation_view.pop() # The variable is the title of the game self.create_toast( @@ -196,7 +196,7 @@ class Game(Gtk.Box): if shared.schema.get_boolean("cover-launches-game") ^ button: self.launch() else: - self.win.show_details_view(self) + self.win.show_details_page(self) def set_play_icon(self): self.play_button.set_icon_name( diff --git a/src/main.py b/src/main.py index d0afd3e..4b06667 100644 --- a/src/main.py +++ b/src/main.py @@ -114,7 +114,6 @@ class CartridgesApplication(Adw.Application): ("lutris_search",), ("hltb_search",), ("show_hidden", ("h",), self.win), - ("go_back", ("Left",), self.win), ("go_to_parent", ("Up",), self.win), ("go_home", ("Home",), self.win), ("toggle_search", ("f",), self.win), @@ -236,7 +235,7 @@ class CartridgesApplication(Adw.Application): self.win.active_game.remove_game() def on_remove_game_details_view_action(self, *_args): - if self.win.stack.get_visible_child() == self.win.details_view: + if self.win.navigation_view.get_visible_page() == self.win.details_page: self.on_remove_game_action() def search(self, uri): diff --git a/src/preferences.py b/src/preferences.py index f090b4a..4653764 100644 --- a/src/preferences.py +++ b/src/preferences.py @@ -222,8 +222,8 @@ class PreferencesWindow(Adw.PreferencesWindow): game.save() game.update() - if self.win.stack.get_visible_child() == self.win.details_view: - self.win.on_go_back_action() + if self.win.navigation_view.get_visible_page() == self.win.details_page: + self.win.navigation_view.pop() self.add_toast(self.toast) diff --git a/src/store/managers/display_manager.py b/src/store/managers/display_manager.py index 7d3a8f0..bd66e92 100644 --- a/src/store/managers/display_manager.py +++ b/src/store/managers/display_manager.py @@ -57,10 +57,10 @@ class DisplayManager(Manager): game.win.game_covers[game.game_id] = game.game_cover if ( - game.win.stack.get_visible_child() == game.win.details_view + game.win.navigation_view.get_visible_page() == game.win.details_page and game.win.active_game == game ): - game.win.show_details_view(game) + game.win.show_details_page(game) if not game.removed and not game.blacklisted: if game.hidden: diff --git a/src/window.py b/src/window.py index a3d1df4..33b7786 100644 --- a/src/window.py +++ b/src/window.py @@ -27,25 +27,26 @@ from src.utils.relative_date import relative_date class CartridgesWindow(Adw.ApplicationWindow): __gtype_name__ = "CartridgesWindow" + navigation_view = Gtk.Template.Child() toast_overlay = Gtk.Template.Child() primary_menu_button = Gtk.Template.Child() - stack = Gtk.Template.Child() details_view = Gtk.Template.Child() + library_page = Gtk.Template.Child() library_view = Gtk.Template.Child() library = Gtk.Template.Child() scrolledwindow = Gtk.Template.Child() - library_bin = Gtk.Template.Child() + library_overlay = Gtk.Template.Child() notice_empty = Gtk.Template.Child() notice_no_results = Gtk.Template.Child() search_bar = Gtk.Template.Child() search_entry = Gtk.Template.Child() search_button = Gtk.Template.Child() + details_page = Gtk.Template.Child() details_view_box = Gtk.Template.Child() details_view_cover = Gtk.Template.Child() details_view_spinner = Gtk.Template.Child() details_view_title = Gtk.Template.Child() - details_view_header_bar_title = Gtk.Template.Child() details_view_blurred_cover = Gtk.Template.Child() details_view_play_button = Gtk.Template.Child() details_view_developer = Gtk.Template.Child() @@ -53,11 +54,12 @@ class CartridgesWindow(Adw.ApplicationWindow): details_view_last_played = Gtk.Template.Child() details_view_hide_button = Gtk.Template.Child() + hidden_library_page = Gtk.Template.Child() hidden_primary_menu_button = Gtk.Template.Child() hidden_library = Gtk.Template.Child() hidden_library_view = Gtk.Template.Child() hidden_scrolledwindow = Gtk.Template.Child() - hidden_library_bin = Gtk.Template.Child() + hidden_library_overlay = Gtk.Template.Child() hidden_notice_empty = Gtk.Template.Child() hidden_notice_no_results = Gtk.Template.Child() hidden_search_bar = Gtk.Template.Child() @@ -73,8 +75,6 @@ class CartridgesWindow(Adw.ApplicationWindow): def __init__(self, **kwargs): super().__init__(**kwargs) - self.previous_page = self.library_view - self.details_view.set_measure_overlay(self.details_view_box, True) self.details_view.set_clip_overlay(self.details_view_box, False) @@ -99,12 +99,11 @@ class CartridgesWindow(Adw.ApplicationWindow): self.search_entry.connect("search-changed", self.search_changed, False) self.hidden_search_entry.connect("search-changed", self.search_changed, True) - self.search_entry.connect("activate", self.show_details_view_search) - self.hidden_search_entry.connect("activate", self.show_details_view_search) + self.search_entry.connect("activate", self.show_details_page_search) + self.hidden_search_entry.connect("activate", self.show_details_page_search) - back_mouse_button = Gtk.GestureClick(button=8) - (back_mouse_button).connect("pressed", self.on_go_back_action) - self.add_controller(back_mouse_button) + self.navigation_view.connect("popped", self.set_show_hidden) + self.navigation_view.connect("pushed", self.set_show_hidden) style_manager = Adw.StyleManager.get_default() style_manager.connect("notify::dark", self.set_details_view_opacity) @@ -121,25 +120,38 @@ class CartridgesWindow(Adw.ApplicationWindow): if game.removed or game.blacklisted: continue if game.hidden: - if game.filtered and hidden_child != self.hidden_scrolledwindow: + if game.filtered and hidden_child: hidden_child = self.hidden_notice_no_results continue - hidden_child = self.hidden_scrolledwindow + hidden_child = None else: - if game.filtered and child != self.scrolledwindow: + if game.filtered and child: child = self.notice_no_results continue - child = self.scrolledwindow + child = None - self.library_bin.set_child(child) - self.hidden_library_bin.set_child(hidden_child) + def remove_from_overlay(widget): + if isinstance(widget.get_parent(), Gtk.Overlay): + widget.get_parent().remove_overlay(widget) + + if child: + self.library_overlay.add_overlay(child) + else: + remove_from_overlay(self.notice_empty) + remove_from_overlay(self.notice_no_results) + + if hidden_child: + self.hidden_library_overlay.add_overlay(hidden_child) + else: + remove_from_overlay(self.hidden_notice_empty) + remove_from_overlay(self.hidden_notice_no_results) def filter_func(self, child): game = child.get_child() text = ( ( self.hidden_search_entry - if self.stack.get_visible_child() == self.hidden_library_view + if self.navigation_view.get_visible_page() == self.hidden_library_page else self.search_entry ) .get_text() @@ -159,7 +171,7 @@ class CartridgesWindow(Adw.ApplicationWindow): def set_active_game(self, _widget, _pspec, game): self.active_game = game - def show_details_view(self, game): + def show_details_page(self, game): self.active_game = game self.details_view_cover.set_opacity(int(not game.loading)) @@ -186,7 +198,7 @@ class CartridgesWindow(Adw.ApplicationWindow): ) self.details_view_title.set_label(game.name) - self.details_view_header_bar_title.set_title(game.name) + self.details_page.set_title(game.name) date = relative_date(game.added) self.details_view_added.set_label( @@ -201,14 +213,14 @@ class CartridgesWindow(Adw.ApplicationWindow): _("Last played: {}").format(last_played_date) ) - if self.stack.get_visible_child() != self.details_view: - self.navigate(self.details_view) + if self.navigation_view.get_visible_page() != self.details_page: + self.navigation_view.push(self.details_page) self.set_focus(self.details_view_play_button) self.set_details_view_opacity() def set_details_view_opacity(self, *_args): - if self.stack.get_visible_child() != self.details_view: + if self.navigation_view.get_visible_page() != self.details_page: return if ( @@ -243,42 +255,20 @@ class CartridgesWindow(Adw.ApplicationWindow): return ((get_value(0) > get_value(1)) ^ order) * 2 - 1 - def navigate(self, next_page): - levels = (self.library_view, self.hidden_library_view, self.details_view) - self.stack.set_transition_type( - Gtk.StackTransitionType.UNDER_RIGHT - if levels.index(self.stack.get_visible_child()) - levels.index(next_page) - > 0 - else Gtk.StackTransitionType.OVER_LEFT + def set_show_hidden(self, widget, *_args): + self.lookup_action("show_hidden").set_enabled( + widget.get_visible_page() == self.library_page ) - if next_page in (self.library_view, self.hidden_library_view): - self.previous_page = next_page - self.lookup_action("show_hidden").set_enabled( - next_page == self.library_view - ) - - self.stack.set_visible_child(next_page) - - def on_go_back_action(self, *_args): - if self.stack.get_visible_child() == self.hidden_library_view: - self.navigate(self.library_view) - elif self.stack.get_visible_child() == self.details_view: - self.on_go_to_parent_action() - def on_go_to_parent_action(self, *_args): - if self.stack.get_visible_child() == self.details_view: - self.navigate( - self.hidden_library_view - if self.previous_page == self.hidden_library_view - else self.library_view - ) + if self.navigation_view.get_visible_page() == self.details_page: + self.navigation_view.pop() def on_go_home_action(self, *_args): - self.navigate(self.library_view) + self.navigation_view.pop_to_page(self.library_page) def on_show_hidden_action(self, *_args): - self.navigate(self.hidden_library_view) + self.navigation_view.push(self.hidden_library_page) def on_sort_action(self, action, state): action.set_state(state) @@ -288,10 +278,10 @@ class CartridgesWindow(Adw.ApplicationWindow): shared.state_schema.set_string("sort-mode", self.sort_state) def on_toggle_search_action(self, *_args): - if self.stack.get_visible_child() == self.library_view: + if self.navigation_view.get_visible_page() == self.library_page: search_bar = self.search_bar search_entry = self.search_entry - elif self.stack.get_visible_child() == self.hidden_library_view: + elif self.navigation_view.get_visible_page() == self.hidden_library_page: search_bar = self.hidden_search_bar search_entry = self.hidden_search_entry else: @@ -311,9 +301,9 @@ class CartridgesWindow(Adw.ApplicationWindow): ): self.on_toggle_search_action() else: - self.on_go_back_action() + self.navigation_view.pop() - def show_details_view_search(self, widget): + def show_details_page_search(self, widget): library = ( self.hidden_library if widget == self.hidden_search_entry else self.library ) @@ -324,7 +314,7 @@ class CartridgesWindow(Adw.ApplicationWindow): break if self.filter_func(child): - self.show_details_view(child.get_child()) + self.show_details_page(child.get_child()) break index += 1 @@ -349,9 +339,9 @@ class CartridgesWindow(Adw.ApplicationWindow): self.toasts.pop((game, undo)) def on_open_menu_action(self, *_args): - if self.stack.get_visible_child() == self.library_view: + if self.navigation_view.get_visible_page() == self.library_page: self.primary_menu_button.popup() - elif self.stack.get_visible_child() == self.hidden_library_view: + elif self.navigation_view.get_visible_page() == self.hidden_library_page: self.hidden_primary_menu_button.popup() def on_close_action(self, *_args):