mirror of
https://github.com/lutris/lutris
synced 2024-10-14 11:42:36 +00:00
Use a GtkStack for the LutrisWindow views
So, now the scroll bars are updates when you switch. But still allocate each view when first used. There's still some waste here if you switch back and forth between grid and list views, but it should not be too bad. Resolves #3881
This commit is contained in:
parent
ee3133f1e9
commit
13df9d1367
|
@ -49,7 +49,7 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
"view-updated": (GObject.SIGNAL_RUN_FIRST, None, ()),
|
||||
}
|
||||
|
||||
games_scrollwindow = GtkTemplate.Child()
|
||||
games_stack = GtkTemplate.Child()
|
||||
sidebar_revealer = GtkTemplate.Child()
|
||||
sidebar_scrolled = GtkTemplate.Child()
|
||||
game_revealer = GtkTemplate.Child()
|
||||
|
@ -86,7 +86,8 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
self.set_service(self.filters.get("service"))
|
||||
self.icon_type = self.load_icon_type()
|
||||
self.game_store = GameStore(self.service, self.service_media)
|
||||
self.view = Gtk.Box()
|
||||
self.current_view = Gtk.Box()
|
||||
self.views = {}
|
||||
|
||||
self.connect("delete-event", self.on_window_delete)
|
||||
self.connect("configure-event", self.on_window_configure)
|
||||
|
@ -97,7 +98,7 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
self.init_template()
|
||||
self._init_actions()
|
||||
|
||||
self.set_viewtype_icon(self.view_type)
|
||||
self.set_viewtype_icon(self.current_view_type)
|
||||
|
||||
lutris_icon = Gtk.Image.new_from_icon_name("lutris", Gtk.IconSize.MENU)
|
||||
lutris_icon.set_margin_right(3)
|
||||
|
@ -195,12 +196,12 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
def on_load(self, widget, data=None):
|
||||
"""Finish initializing the view"""
|
||||
self._bind_zoom_adjustment()
|
||||
self.view.grab_focus()
|
||||
self.view.contextual_menu = ContextualMenu(self.game_actions.get_game_actions())
|
||||
self.current_view.grab_focus()
|
||||
self.current_view.contextual_menu = ContextualMenu(self.game_actions.get_game_actions())
|
||||
|
||||
def on_sidebar_realize(self, widget, data=None):
|
||||
"""Grab the initial focus after the sidebar is initialized - so the view is ready."""
|
||||
self.view.grab_focus()
|
||||
self.current_view.grab_focus()
|
||||
|
||||
def load_filters(self):
|
||||
"""Load the initial filters when creating the view"""
|
||||
|
@ -448,7 +449,8 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
self.hide_overlay()
|
||||
games = self.get_games_from_filters()
|
||||
logger.debug("Showing %d games", len(games))
|
||||
self.view.service = self.service.id if self.service else None
|
||||
for view in self.views.values():
|
||||
view.service = self.service.id if self.service else None
|
||||
GLib.idle_add(self.update_revealer)
|
||||
for game in games:
|
||||
self.game_store.add_game(game)
|
||||
|
@ -541,7 +543,7 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
# which keys actually start searching
|
||||
if event.keyval == Gdk.KEY_Escape:
|
||||
self.search_entry.set_text("")
|
||||
self.view.grab_focus()
|
||||
self.current_view.grab_focus()
|
||||
return Gtk.ApplicationWindow.do_key_press_event(self, event)
|
||||
|
||||
if ( # pylint: disable=too-many-boolean-expressions
|
||||
|
@ -575,25 +577,33 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
if not self.game_store:
|
||||
logger.error("No game store yet")
|
||||
return
|
||||
if self.view:
|
||||
self.view.destroy()
|
||||
self.game_store = GameStore(self.service, self.service_media)
|
||||
if self.view_type == "grid":
|
||||
self.view = GameGridView(
|
||||
self.game_store,
|
||||
self.game_store.service_media,
|
||||
hide_text=settings.read_setting("hide_text_under_icons") == "True"
|
||||
)
|
||||
else:
|
||||
self.view = GameListView(self.game_store, self.game_store.service_media)
|
||||
|
||||
self.view.connect("game-selected", self.on_game_selection_changed)
|
||||
self.view.connect("game-activated", self.on_game_activated)
|
||||
self.view.contextual_menu = ContextualMenu(self.game_actions.get_game_actions())
|
||||
for child in self.games_scrollwindow.get_children():
|
||||
child.destroy()
|
||||
self.games_scrollwindow.add(self.view)
|
||||
self.view.show_all()
|
||||
view_type = self.current_view_type
|
||||
|
||||
if view_type in self.views:
|
||||
self.current_view = self.views[view_type]
|
||||
self.current_view.set_game_store(self.game_store)
|
||||
else:
|
||||
if view_type == "grid":
|
||||
self.current_view = GameGridView(
|
||||
self.game_store,
|
||||
hide_text=settings.read_setting("hide_text_under_icons") == "True"
|
||||
)
|
||||
else:
|
||||
self.current_view = GameListView(self.game_store)
|
||||
|
||||
self.current_view.connect("game-selected", self.on_game_selection_changed)
|
||||
self.current_view.connect("game-activated", self.on_game_activated)
|
||||
self.current_view.contextual_menu = ContextualMenu(self.game_actions.get_game_actions())
|
||||
|
||||
scrolledwindow = Gtk.ScrolledWindow()
|
||||
scrolledwindow.add(self.current_view)
|
||||
scrolledwindow.show_all()
|
||||
self.games_stack.add_named(scrolledwindow, view_type)
|
||||
self.views[view_type] = self.current_view
|
||||
|
||||
self.games_stack.set_visible_child_name(view_type)
|
||||
self.update_store()
|
||||
|
||||
def set_viewtype_icon(self, view_type):
|
||||
|
@ -701,14 +711,14 @@ class LutrisWindow(Gtk.ApplicationWindow,
|
|||
def on_search_entry_key_press(self, widget, event):
|
||||
if event.keyval == Gdk.KEY_Down:
|
||||
if self.current_view_type == 'grid':
|
||||
self.view.select_path(Gtk.TreePath('0')) # needed for gridview only
|
||||
self.current_view.select_path(Gtk.TreePath('0')) # needed for gridview only
|
||||
# if game_bar is alive at this point it can mess grid item selection up
|
||||
# for some unknown reason,
|
||||
# it is safe to close it here, it will be reopened automatically.
|
||||
if self.game_bar:
|
||||
self.game_bar.destroy() # for gridview only
|
||||
self.view.set_cursor(Gtk.TreePath('0'), None, False) # needed for both view types
|
||||
self.view.grab_focus()
|
||||
self.current_view.set_cursor(Gtk.TreePath('0'), None, False) # needed for both view types
|
||||
self.current_view.grab_focus()
|
||||
|
||||
@GtkTemplate.Callback
|
||||
def on_about_clicked(self, *_args):
|
||||
|
|
|
@ -13,29 +13,37 @@ class GameGridView(Gtk.IconView, GameView):
|
|||
|
||||
min_width = 70 # Minimum width for a cell
|
||||
|
||||
def __init__(self, store, service_media, hide_text=False):
|
||||
self.game_store = store
|
||||
self.service_media = service_media
|
||||
self.model = self.game_store.store
|
||||
super().__init__(model=self.game_store.store)
|
||||
def __init__(self, store, hide_text=False):
|
||||
super().__init__()
|
||||
GameView.__init__(self)
|
||||
|
||||
self.service = None
|
||||
self.set_column_spacing(6)
|
||||
self.set_pixbuf_column(COL_ICON)
|
||||
self.set_item_padding(1)
|
||||
self.cell_width = max(service_media.size[0], self.min_width)
|
||||
if hide_text:
|
||||
self.cell_renderer = None
|
||||
else:
|
||||
self.cell_renderer = GridViewCellRendererText(self.cell_width)
|
||||
self.cell_renderer = GridViewCellRendererText()
|
||||
self.pack_end(self.cell_renderer, False)
|
||||
self.add_attribute(self.cell_renderer, "markup", COL_NAME)
|
||||
|
||||
self.set_game_store(store)
|
||||
|
||||
self.connect_signals()
|
||||
self.connect("item-activated", self.on_item_activated)
|
||||
self.connect("selection-changed", self.on_selection_changed)
|
||||
|
||||
def set_game_store(self, game_store):
|
||||
self.game_store = game_store
|
||||
self.service_media = game_store.service_media
|
||||
self.model = game_store.store
|
||||
self.set_model(self.model)
|
||||
|
||||
if self.cell_renderer:
|
||||
cell_width = max(game_store.service_media.size[0], self.min_width)
|
||||
self.cell_renderer.set_width(cell_width)
|
||||
|
||||
def select(self):
|
||||
self.select_path(self.current_path)
|
||||
|
||||
|
|
|
@ -21,21 +21,24 @@ class GameListView(Gtk.TreeView, GameView):
|
|||
|
||||
__gsignals__ = GameView.__gsignals__
|
||||
|
||||
def __init__(self, store, service_media):
|
||||
self.game_store = store
|
||||
self.service_media = service_media
|
||||
self.model = self.game_store.store
|
||||
super().__init__(model=self.model)
|
||||
def __init__(self, store):
|
||||
super().__init__()
|
||||
GameView.__init__(self)
|
||||
|
||||
self.set_rules_hint(True)
|
||||
|
||||
# Icon column
|
||||
if settings.SHOW_MEDIA:
|
||||
image_cell = Gtk.CellRendererPixbuf()
|
||||
column = Gtk.TreeViewColumn("", image_cell, pixbuf=COL_ICON)
|
||||
column.set_reorderable(True)
|
||||
column.set_sort_indicator(False)
|
||||
self.append_column(column)
|
||||
self.media_column = Gtk.TreeViewColumn("", image_cell, pixbuf=COL_ICON)
|
||||
self.media_column.set_reorderable(True)
|
||||
self.media_column.set_sort_indicator(False)
|
||||
self.media_column.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
|
||||
self.append_column(self.media_column)
|
||||
else:
|
||||
self.media_column = None
|
||||
|
||||
self.set_game_store(store)
|
||||
|
||||
# Text columns
|
||||
default_text_cell = self.set_text_cell()
|
||||
|
@ -59,6 +62,16 @@ class GameListView(Gtk.TreeView, GameView):
|
|||
self.connect("row-activated", self.on_row_activated)
|
||||
self.get_selection().connect("changed", self.on_cursor_changed)
|
||||
|
||||
def set_game_store(self, game_store):
|
||||
self.game_store = game_store
|
||||
self.service_media = game_store.service_media
|
||||
self.model = game_store.store
|
||||
self.set_model(self.model)
|
||||
|
||||
if self.media_column:
|
||||
media_width = game_store.service_media.size[0]
|
||||
self.media_column.set_fixed_width(media_width)
|
||||
|
||||
@staticmethod
|
||||
def set_text_cell():
|
||||
text_cell = Gtk.CellRendererText()
|
||||
|
|
|
@ -4,10 +4,12 @@ from gi.repository import Gtk, Pango
|
|||
class GridViewCellRendererText(Gtk.CellRendererText):
|
||||
"""CellRendererText adjusted for grid view display, removes extra padding"""
|
||||
|
||||
def __init__(self, width, *args, **kwargs):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.props.alignment = Pango.Alignment.CENTER
|
||||
self.props.wrap_mode = Pango.WrapMode.WORD
|
||||
self.props.xalign = 0.5
|
||||
self.props.yalign = 0
|
||||
|
||||
def set_width(self, width):
|
||||
self.props.wrap_width = width
|
||||
|
|
|
@ -76,18 +76,11 @@
|
|||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow" id="games_scrollwindow">
|
||||
<object class="GtkStack" id="games_stack">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="vexpand">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkViewport" id="games_viewport">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
|
Loading…
Reference in a new issue