mirror of
https://github.com/lutris/lutris
synced 2024-11-02 10:19:50 +00:00
Migrate hidden field to database
This commit is contained in:
parent
e6e6818eec
commit
b3236a99d3
9 changed files with 75 additions and 92 deletions
|
@ -12,22 +12,27 @@ PGA_DB = settings.PGA_DB
|
|||
|
||||
def get_games(
|
||||
name_filter=None,
|
||||
extra_filters=None,
|
||||
filters=None,
|
||||
excludes=None,
|
||||
sorts=None
|
||||
):
|
||||
"""Get the list of every game in database."""
|
||||
query = "select * from games"
|
||||
params = []
|
||||
filters = []
|
||||
sql_filters = []
|
||||
if name_filter:
|
||||
filters.append("name LIKE ?")
|
||||
sql_filters.append("name LIKE ?")
|
||||
params.append("%" + name_filter + "%")
|
||||
for field in extra_filters or {}:
|
||||
if extra_filters[field]:
|
||||
filters.append("%s = ?" % field)
|
||||
params.append(extra_filters[field])
|
||||
if filters:
|
||||
query += " WHERE " + " AND ".join(filters)
|
||||
for field in filters or {}:
|
||||
if filters[field]:
|
||||
sql_filters.append("%s = ?" % field)
|
||||
params.append(filters[field])
|
||||
for field in excludes or {}:
|
||||
if excludes[field]:
|
||||
sql_filters.append("%s IS NOT ?" % field)
|
||||
params.append(excludes[field])
|
||||
if sql_filters:
|
||||
query += " WHERE " + " AND ".join(sql_filters)
|
||||
if sorts:
|
||||
query += " ORDER BY %s" % ", ".join(
|
||||
["%s %s" % (sort[0], sort[1]) for sort in sorts]
|
||||
|
@ -201,15 +206,6 @@ def get_used_runners():
|
|||
return [result[0] for result in results if result[0]]
|
||||
|
||||
|
||||
def get_used_runners_game_count():
|
||||
"""Return a dictionary listing for each runner in use, how many games are using it."""
|
||||
with sql.db_cursor(PGA_DB) as cursor:
|
||||
query = "select runner, count(*) from games where runner is not null group by runner order by runner"
|
||||
rows = cursor.execute(query)
|
||||
results = rows.fetchall()
|
||||
return {result[0]: result[1] for result in results if result[0]}
|
||||
|
||||
|
||||
def get_used_platforms():
|
||||
"""Return a list of platforms currently in use"""
|
||||
with sql.db_cursor(PGA_DB) as cursor:
|
||||
|
@ -220,36 +216,3 @@ def get_used_platforms():
|
|||
rows = cursor.execute(query)
|
||||
results = rows.fetchall()
|
||||
return [result[0] for result in results if result[0]]
|
||||
|
||||
|
||||
def get_used_platforms_game_count():
|
||||
"""Return a dictionary listing for each platform in use, how many games are using it."""
|
||||
with sql.db_cursor(PGA_DB) as cursor:
|
||||
# The extra check for 'installed is 1' is needed because
|
||||
# the platform lists don't show uninstalled games, but the platform of a game
|
||||
# is remembered even after the game is uninstalled.
|
||||
query = (
|
||||
"select platform, count(*) from games "
|
||||
"where platform is not null and platform is not '' and installed is 1 "
|
||||
"group by platform "
|
||||
"order by platform"
|
||||
)
|
||||
rows = cursor.execute(query)
|
||||
results = rows.fetchall()
|
||||
return {result[0]: result[1] for result in results if result[0]}
|
||||
|
||||
|
||||
def get_hidden_ids():
|
||||
"""Return a list of game IDs to be excluded from the library view"""
|
||||
# Load the ignore string and filter out empty strings to prevent issues
|
||||
ignores_raw = settings.read_setting("library_ignores", section="lutris", default="").split(",")
|
||||
ignores = [ignore for ignore in ignores_raw if not ignore == ""]
|
||||
|
||||
# Turn the strings into integers
|
||||
return [int(game_id) for game_id in ignores]
|
||||
|
||||
|
||||
def set_hidden_ids(games):
|
||||
"""Writes a list of game IDs that are to be hidden into the config file"""
|
||||
ignores_str = [str(game_id) for game_id in games]
|
||||
settings.write_setting("library_ignores", ','.join(ignores_str), section="lutris")
|
||||
|
|
|
@ -90,6 +90,10 @@ DATABASE = {
|
|||
"name": "playtime",
|
||||
"type": "REAL"
|
||||
},
|
||||
{
|
||||
"name": "hidden",
|
||||
"type": "INTEGER"
|
||||
},
|
||||
],
|
||||
"store_games": [
|
||||
{
|
||||
|
|
|
@ -68,6 +68,7 @@ class Game(GObject.Object):
|
|||
|
||||
self.game_config_id = game_data.get("configpath") or ""
|
||||
self.is_installed = bool(game_data.get("installed") and self.game_config_id)
|
||||
self.is_hidden = bool(game_data.get("hidden"))
|
||||
self.platform = game_data.get("platform") or ""
|
||||
self.year = game_data.get("year") or ""
|
||||
self.lastplayed = game_data.get("lastplayed") or 0
|
||||
|
@ -128,25 +129,15 @@ class Game(GObject.Object):
|
|||
categories_db.remove_category_from_game(self.id, favorite["id"])
|
||||
self.emit("game-updated")
|
||||
|
||||
@property
|
||||
def is_hidden(self):
|
||||
"""Is the game hidden in the UI?"""
|
||||
return self.id in games_db.get_hidden_ids()
|
||||
|
||||
def hide(self):
|
||||
"""Do not show this game in the UI"""
|
||||
# Append the new hidden ID and save it
|
||||
ignores = games_db.get_hidden_ids() + [self.id]
|
||||
games_db.set_hidden_ids(ignores)
|
||||
self.emit("game-updated")
|
||||
self.is_hidden = True
|
||||
self.save()
|
||||
|
||||
def unhide(self):
|
||||
"""Remove the game from hidden games"""
|
||||
# Remove the ID to unhide and save it
|
||||
ignores = games_db.get_hidden_ids()
|
||||
ignores.remove(self.id)
|
||||
games_db.set_hidden_ids(ignores)
|
||||
self.emit("game-updated")
|
||||
self.is_hidden = False
|
||||
self.save()
|
||||
|
||||
@property
|
||||
def log_buffer(self):
|
||||
|
@ -301,6 +292,7 @@ class Game(GObject.Object):
|
|||
steamid=self.steamid,
|
||||
id=self.id,
|
||||
playtime=self.playtime,
|
||||
hidden=self.is_hidden,
|
||||
)
|
||||
self.emit("game-updated")
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
default_height = 600
|
||||
|
||||
__gtype_name__ = "LutrisWindow"
|
||||
__gsignals__ = {
|
||||
"view-updated": (GObject.SIGNAL_RUN_LAST, None, ()),
|
||||
}
|
||||
|
||||
main_box = GtkTemplate.Child()
|
||||
games_scrollwindow = GtkTemplate.Child()
|
||||
|
@ -65,8 +68,6 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
viewtype_icon = GtkTemplate.Child()
|
||||
|
||||
def __init__(self, application, **kwargs):
|
||||
# pylint: disable=too-many-statements
|
||||
# TODO: refactor
|
||||
width = int(settings.read_setting("width") or self.default_width)
|
||||
height = int(settings.read_setting("height") or self.default_height)
|
||||
super().__init__(
|
||||
|
@ -234,18 +235,8 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
def hidden_state_change(self, action, value):
|
||||
"""Hides or shows the hidden games"""
|
||||
action.set_state(value)
|
||||
|
||||
# Add or remove hidden games
|
||||
ignores = games_db.get_hidden_ids()
|
||||
settings.write_setting("show_hidden_games", str(self.show_hidden_games).lower(), section="lutris")
|
||||
|
||||
# If we have to show the hidden games now, we need to add them back to
|
||||
# the view. If we need to hide them, we just remove them from the view
|
||||
if value:
|
||||
self.game_store.add_games(games_db.get_games_by_ids(ignores))
|
||||
else:
|
||||
for game_id in ignores:
|
||||
self.game_store.remove_game(game_id)
|
||||
self.emit("view-updated")
|
||||
|
||||
@property
|
||||
def current_view_type(self):
|
||||
|
@ -342,6 +333,7 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
game_ids = categories_db.get_game_ids_for_category(self.filters["category"])
|
||||
return games_db.get_games_by_ids(game_ids)
|
||||
sql_filters = {}
|
||||
sql_excludes = {}
|
||||
if self.filters.get("runner"):
|
||||
sql_filters["runner"] = self.filters["runner"]
|
||||
if self.filters.get("platform"):
|
||||
|
@ -352,9 +344,12 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
search_query = self.filters["text"]
|
||||
else:
|
||||
search_query = None
|
||||
if not self.show_hidden_games:
|
||||
sql_excludes["hidden"] = 1
|
||||
games = games_db.get_games(
|
||||
name_filter=search_query,
|
||||
extra_filters=sql_filters,
|
||||
filters=sql_filters,
|
||||
excludes=sql_excludes,
|
||||
sorts=self.sort_params
|
||||
)
|
||||
logger.info("Returned %s games from %s, %s", len(games), self.filters, self.view_sorting)
|
||||
|
@ -364,10 +359,10 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
"""Return an instance of the game store"""
|
||||
return GameStore([], self.icon_type)
|
||||
|
||||
def update_store(self, games=None):
|
||||
def update_store(self, *_args, **_kwargs):
|
||||
self.game_store.games = []
|
||||
self.game_store.store.clear()
|
||||
games = games or self.get_games_from_filters()
|
||||
games = self.get_games_from_filters()
|
||||
for game in games:
|
||||
self.game_store.add_game(game)
|
||||
self.no_results_overlay.props.visible = not bool(games)
|
||||
|
@ -429,6 +424,7 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
This must be called each time the view is rebuilt.
|
||||
"""
|
||||
|
||||
self.connect("view-updated", self.update_store)
|
||||
self.view.connect("game-selected", self.game_selection_changed)
|
||||
self.view.connect("game-activated", self.on_game_activated)
|
||||
|
||||
|
@ -498,8 +494,6 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
self.games_scrollwindow.add(self.view)
|
||||
self._connect_signals()
|
||||
|
||||
GLib.idle_add(self.update_store)
|
||||
|
||||
self.zoom_adjustment.props.value = list(IMAGE_SIZES.keys()).index(self.icon_type)
|
||||
|
||||
if view_type:
|
||||
|
@ -507,6 +501,7 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
settings.write_setting("view_type", view_type)
|
||||
|
||||
self.view.show_all()
|
||||
self.emit("view-updated")
|
||||
|
||||
def set_viewtype_icon(self, view_type):
|
||||
self.viewtype_icon.set_from_icon_name("view-%s-symbolic" % view_type, Gtk.IconSize.BUTTON)
|
||||
|
@ -640,12 +635,13 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
"""Callback to handle uninstalled game filter switch"""
|
||||
action.set_state(value)
|
||||
self.set_show_installed_state(value.get_boolean())
|
||||
self.emit("view-updated")
|
||||
|
||||
def set_show_installed_state(self, filter_installed):
|
||||
"""Shows or hide uninstalled games"""
|
||||
settings.write_setting("filter_installed", bool(filter_installed))
|
||||
self.filters["installed"] = filter_installed
|
||||
self.update_store()
|
||||
self.emit("view-updated")
|
||||
|
||||
@GtkTemplate.Callback
|
||||
def on_search_entry_changed(self, entry):
|
||||
|
@ -695,7 +691,8 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
except ValueError:
|
||||
self.game_store.add_games(games_db.get_games_by_ids([game.id]))
|
||||
|
||||
self.game_panel.refresh()
|
||||
GLib.idle_add(self.game_panel.refresh)
|
||||
self.emit("view-updated")
|
||||
return True
|
||||
|
||||
def game_selection_changed(self, _widget, game):
|
||||
|
@ -767,12 +764,12 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
self.actions["view-sorting"].set_state(value)
|
||||
value = str(value).strip("'")
|
||||
settings.write_setting("view_sorting", value)
|
||||
GLib.idle_add(self.update_store)
|
||||
self.emit("view-updated")
|
||||
|
||||
def on_view_sorting_direction_change(self, action, value):
|
||||
self.actions["view-sorting-ascending"].set_state(value)
|
||||
settings.write_setting("view_sorting_ascending", bool(value))
|
||||
GLib.idle_add(self.update_store)
|
||||
self.emit("view-updated")
|
||||
|
||||
def on_left_side_panel_state_change(self, action, value):
|
||||
"""Callback to handle left side panel toggle"""
|
||||
|
@ -804,7 +801,7 @@ class LutrisWindow(Gtk.ApplicationWindow): # pylint: disable=too-many-public-me
|
|||
self.filters.pop(filter_type)
|
||||
if row:
|
||||
self.filters[row.type] = row.id
|
||||
self.update_store()
|
||||
self.emit("view-updated")
|
||||
|
||||
def show_invalid_credential_warning(self):
|
||||
dialogs.ErrorDialog(_("Could not connect to your Lutris account. Please sign in again."))
|
||||
|
|
|
@ -99,7 +99,7 @@ class LutrisStatusIcon:
|
|||
@staticmethod
|
||||
def add_games():
|
||||
"""Adds installed games in order of last use"""
|
||||
installed_games = get_games(extra_filters={"installed": "1"})
|
||||
installed_games = get_games(filters={"installed": 1})
|
||||
installed_games.sort(
|
||||
key=lambda game: max(game["lastplayed"] or 0, game["installed_at"] or 0),
|
||||
reverse=True,
|
||||
|
|
|
@ -5,7 +5,7 @@ import importlib
|
|||
from lutris import settings
|
||||
from lutris.util.log import logger
|
||||
|
||||
MIGRATION_VERSION = 8 # Never decrease this number
|
||||
MIGRATION_VERSION = 9 # Never decrease this number
|
||||
|
||||
# Replace deprecated migrations with empty lists
|
||||
MIGRATIONS = [
|
||||
|
@ -17,6 +17,7 @@ MIGRATIONS = [
|
|||
["d9vk_to_dxvk"],
|
||||
["fix_playtime_type"],
|
||||
["mess_to_mame"],
|
||||
["migrate_hidden_ids"],
|
||||
]
|
||||
|
||||
|
||||
|
|
26
lutris/migrations/migrate_hidden_ids.py
Normal file
26
lutris/migrations/migrate_hidden_ids.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
"""Move hidden games from settings to database"""
|
||||
from lutris import settings
|
||||
from lutris.game import Game
|
||||
|
||||
|
||||
def get_hidden_ids():
|
||||
"""Return a list of game IDs to be excluded from the library view"""
|
||||
# Load the ignore string and filter out empty strings to prevent issues
|
||||
ignores_raw = settings.read_setting("library_ignores", section="lutris", default="").split(",")
|
||||
ignores = [ignore for ignore in ignores_raw if not ignore == ""]
|
||||
|
||||
# Turn the strings into integers
|
||||
return [int(game_id) for game_id in ignores]
|
||||
|
||||
|
||||
def migrate():
|
||||
"""Run migration"""
|
||||
try:
|
||||
game_ids = get_hidden_ids()
|
||||
except:
|
||||
print("Failed to read hidden game IDs")
|
||||
return []
|
||||
for game_id in game_ids:
|
||||
game = Game(game_id)
|
||||
game.hide()
|
||||
settings.write_setting("library_ignores", '', section="lutris")
|
|
@ -136,7 +136,7 @@ def fill_missing_platforms():
|
|||
"""Sets the platform on games where it's missing.
|
||||
This should never happen.
|
||||
"""
|
||||
pga_games = get_games(extra_filters={"installed": "1"})
|
||||
pga_games = get_games(filters={"installed": 1})
|
||||
for pga_game in pga_games:
|
||||
if pga_game.get("platform") or not pga_game["runner"]:
|
||||
continue
|
||||
|
|
|
@ -54,7 +54,7 @@ class TestPersonnalGameArchive(DatabaseTester):
|
|||
def test_can_filter_by_installed_games(self):
|
||||
games_db.add_game(name="installed_game", runner="Linux", installed=1)
|
||||
games_db.add_game(name="bang", runner="Linux", installed=0)
|
||||
game_list = games_db.get_games(filter_installed=True)
|
||||
game_list = games_db.get_games(filters={'installed': 1})
|
||||
self.assertEqual(len(game_list), 1)
|
||||
self.assertEqual(game_list[0]['name'], 'installed_game')
|
||||
|
||||
|
|
Loading…
Reference in a new issue