From d8939e800e87736bb7ed2e520f0aa1afda15507e Mon Sep 17 00:00:00 2001 From: Vivien Graffin Date: Thu, 11 Apr 2024 17:13:39 +0200 Subject: [PATCH 1/4] [Linux] Support Flatpak + TECH-PREVIEW --- linux/lib.py | 98 +++++++++++++++++++++++++++++++------ linux/lutris_console.sh | 36 ++++++++++++-- linux/lutris_gui.sh | 106 ++++++++++++++++++++++++++++------------ 3 files changed, 189 insertions(+), 51 deletions(-) diff --git a/linux/lib.py b/linux/lib.py index 1a15ec634..78b360e11 100644 --- a/linux/lib.py +++ b/linux/lib.py @@ -34,27 +34,92 @@ def get_translation(): return translation_request.text def get_game_path(directory,mode): - res=directory+"/drive_c/Program Files/Roberts Space Industries/StarCitizen" + res=Path(directory,"drive_c/Program Files/Roberts Space Industries/StarCitizen") match mode: case GameMode.LIVE.value: return Path(res,"LIVE") case GameMode.PTU.value: return Path(res,"PTU") + case GameMode.TECH_PREVIEW.value: + return Path(res,"TECH-PREVIEW") -class GameMode(Enum): - LIVE = 1 - PTU = 2 - +class MyEnum(Enum): @classmethod def list(cls): return list(map(lambda c:c, cls)) - @classmethod def list_array(cls): return list(map(lambda c:[c.value,c.name],cls)) + @classmethod + def name_list(cls): + return list(map(lambda c:c.name,cls)) + @classmethod + def from_name(cls,name): + for item in cls.list(): + if item.name==name: + return item.value + raise Exception('Incorrect Name') + @classmethod + def from_value(cls,value): + for item in cls.list(): + if item.value==value: + return item.name + raise Exception('Incorrect Value') + +class LutrisVersion(MyEnum): + flatpak = 'Flatpak' + system = 'Système' + +class GameMode(MyEnum): + LIVE = 1 + PTU = 2 + TECH_PREVIEW = 3 + +def lutris_flatpak_pkg(): + return "net.lutris.Lutris" -def get_lutris_games(): - return json.loads(subprocess.run(['lutris','-loj'],capture_output=True).stdout) +def get_lutris_versions(): + res=[] + if has_system_lutris(): + res.append('system') + if has_flatpak_lutris(): + res.append('flatpak') + return res + +def command_exists(command): + return subprocess.run(['which',command],capture_output=True).returncode==0 + +def get_flatpak_pkgs(): + lines=subprocess.run(['flatpak','list','--columns=application'],capture_output=True).stdout.decode('utf-8').split('\n') + lines.pop() + return lines + +def has_flatpak_lutris(): + if not command_exists('flatpak'): + return False + return lutris_flatpak_pkg() in get_flatpak_pkgs() + +def has_system_lutris(): + return command_exists('lutris') + +def get_lutris_gamelist(command): + command.extend(['-loj']) + return json.loads(subprocess.run(command,capture_output=True).stdout) + +def get_flatpak_lutris_games(): + return get_lutris_gamelist(['flatpak','run',lutris_flatpak_pkg()]) + +def get_system_lutris_games(): + return get_lutris_gamelist(['lutris']) + +def get_lutris_games(version): + if version=='flatpak': + if has_flatpak_lutris(): + return get_flatpak_lutris_games() + else: + if has_system_lutris(): + return get_system_lutris_games() + return [] def write_user_cfg(directory): file=Path(directory,"user.cfg") @@ -64,13 +129,19 @@ def write_user_cfg(directory): class GUI: def __init__(self): - self.lutris_games=get_lutris_games() + self.versions=get_lutris_versions() def display(self): raise Exception("Méthode non implémenté") def get_directory(self): raise Exception("Méthode non implémenté") def get_mode(self): raise Exception("Méthode non implémenté") + def get_selected_version(self): + raise Exception("Méthode non implémenté") + def get_version(self): + if len(self.versions)==1: + return self.versions[0] + return self.get_selected_version() def install(self): try: path=get_game_path(self.get_directory(),self.get_mode()) @@ -84,18 +155,15 @@ def install(self): self.display_error("Le mode du jeu n'a pas été sélectionné") except Exception as e: self.display_error(e.args[0]) - - def get_datas_of_lutris_games(self): - res=[] - for game in self.lutris_games: - res.append([game["id"],game["name"],game["directory"]]) - return res def display_error(self,message): raise Exception("Méthode non implémenté") def display_info(self,message): raise Exception("Méthode non implémenté") + + def get_versions_name(self): + return list(map(lambda c: LutrisVersion.from_name(c),self.versions)) class GUIErrors(Enum): NO_DIRECTORY = 1 diff --git a/linux/lutris_console.sh b/linux/lutris_console.sh index 0a9f6db8e..4fb278516 100755 --- a/linux/lutris_console.sh +++ b/linux/lutris_console.sh @@ -1,6 +1,6 @@ #!/bin/python3 -from lib import apply_translation,get_game_path,get_lutris_games,GameMode +from lib import apply_translation,get_game_path,get_lutris_games,get_lutris_versions,GameMode,LutrisVersion def display_list(left,center,right): print(f"{left : <20}{center : ^15}{right : >40}") @@ -8,8 +8,33 @@ def display_list(left,center,right): def display_game_mode(left,right): print(f"{left : <20}{right : <20}") -def select_lutris_game(): - games=get_lutris_games() +def select_lutris_version(): + versions=get_lutris_versions() + + if len(versions)==0: + raise Exception("Lutris n'est pas installé") + elif len(versions)==1: + return versions[0] + + display_list("ID","Version","") + i=1 + versions=list(map(lambda c:LutrisVersion.from_name(c),versions)) + for version in versions: + display_list(str(i),version,"") + + i=int(input("Entrez l'ID de la version de Lutris: ")) + + if i>len(versions) or i<1: + return select_lutris_version() + + return LutrisVersion.from_value(versions[i-1]) + +def select_lutris_game(version): + games=get_lutris_games(version) + + if len(games)==0: + raise Exception("Il n'y a pas de jeux") + display_list("ID","Nom du jeu","Répertoire") for game in games: display_list(str(game["id"]),game["name"],game["directory"]) @@ -25,11 +50,12 @@ def select_game_mode(): for mode in GameMode.list(): display_game_mode(str(mode.value),mode.name) i=int(input("Sélectionnez un ID correspondant au mode de Star Citizen: ")) - if i!=GameMode.LIVE.value and i!=GameMode.PTU.value: + if i!=GameMode.LIVE.value and i!=GameMode.PTU.value and i!=GameMode.TECH_PREVIEW.value: return select_game_mode() return i -game=select_lutris_game() +version=select_lutris_version() +game=select_lutris_game(version) mode=select_game_mode() path=get_game_path(game["directory"],mode) apply_translation(path) \ No newline at end of file diff --git a/linux/lutris_gui.sh b/linux/lutris_gui.sh index 875a589f4..9344056ff 100755 --- a/linux/lutris_gui.sh +++ b/linux/lutris_gui.sh @@ -1,8 +1,8 @@ #!/bin/python3 import sys -from lib import apply_translation,get_game_path,get_lutris_games,GameMode,GUI,GUIErrors,GUIException -from PyQt6.QtWidgets import QApplication,QWidget,QVBoxLayout,QLabel,QTableView,QPushButton,QMessageBox +from lib import apply_translation,get_game_path,get_lutris_games,GameMode,GUI,GUIErrors,GUIException,LutrisVersion +from PyQt6.QtWidgets import QApplication,QWidget,QVBoxLayout,QLabel,QTableView,QPushButton,QMessageBox,QComboBox from PyQt6 import QtCore from PyQt6.QtCore import Qt @@ -11,29 +11,40 @@ class GUIQT6(GUI): self.application = QApplication(sys.argv) self.window = QWidget() self.window.setWindowTitle("Installation de la traduction française de Star Citizen") - + # Disposition horizontale layout=QVBoxLayout() + self.versionLabel=QLabel("Version de Lutris") + layout.addWidget(self.versionLabel) + + # Table de la version de lutris + self.lutrisVersion=self.create_combobox(layout,self.get_versions_name()) + self.lutrisVersion.currentTextChanged.connect(self.sync_table_game_to_table_version) + layout.addWidget(QLabel("Jeux")) - # Table de la liste des jeux lutris - self.gameTable=QTableView() - datas=self.get_datas_of_lutris_games() - self.gameTable.setModel(TableModel(datas)) + self.gameTable=self.create_table(layout,self.get_datas_of_lutris_games("system")) self.gameTable.clicked.connect(self.select_line_of_table_game) - self.gameTable.resizeColumnsToContents() - layout.addWidget(self.gameTable) + self.flatpakGames=self.create_table(layout,self.get_datas_of_lutris_games("flatpak")) + self.flatpakGames.clicked.connect(self.select_line_of_flatpak_games) + + if len(self.versions)==0: + raise Exception("Lutris n'est pas installé") + elif len(self.versions)==1: + self.versionLabel.hide() + self.lutrisVersion.hide() + if self.versions[0]=="system": + self.flatpakGames.hide() + else: + self.gameTable.hide() + else: + self.flatpakGames.hide() layout.addWidget(QLabel("Modes")) # Table de la liste des modes de Star Citizen - self.modeTable=QTableView() - modes_datas=GameMode.list_array() - self.modeTable.setModel(TableModel(modes_datas)) - self.modeTable.clicked.connect(self.select_line_of_table_mode) - self.modeTable.resizeColumnsToContents() - layout.addWidget(self.modeTable) + self.modeTable=self.create_combobox(layout,GameMode.name_list()) # Bouton Installation install_button=QPushButton("Installer/Mettre à jour") @@ -48,7 +59,29 @@ class GUIQT6(GUI): self.window.show() self.application.exec() - + + def create_table(self,layout,datas): + table=QTableView() + table.setModel(TableModel(datas)) + table.resizeColumnsToContents() + layout.addWidget(table) + return table + + def create_combobox(self,layout,datas): + combobox=QComboBox() + combobox.addItems(GameMode.name_list()) + layout.addWidget(combobox) + return combobox + + + def sync_table_game_to_table_version(self,index): + if self.get_version()=='flatpak': + self.flatpakGames.show() + self.gameTable.hide() + else: + self.flatpakGames.hide() + self.gameTable.show() + def select_line_of_table_game(self,index): row=index.row() model=index.model() @@ -56,30 +89,34 @@ class GUIQT6(GUI): for i in range(columnsTotal): self.gameTable.selectRow(row) - - def select_line_of_table_mode(self,index): + + def select_line_of_flatpak_games(self,index): row=index.row() model=index.model() columnsTotal=model.columnCount(None) for i in range(columnsTotal): - self.modeTable.selectRow(row) - + self.flatpakGames.selectRow(row) + def get_directory(self): - index = self.gameTable.selectedIndexes() + if self.get_version()=='system': + index = self.gameTable.selectedIndexes() + + if len(index)==0: + raise GUIException(GUIErrors.NO_DIRECTORY) + return index[2].data(0) + else: + index = self.flatpakGames.selectedIndexes() - if len(index)==0: - raise GUIException(GUIErrors.NO_DIRECTORY) - - return index[2].data(0) + if len(index)==0: + raise GUIException(GUIErrors.NO_DIRECTORY) + return index[2].data(0) def get_mode(self): - index = self.modeTable.selectedIndexes() + return GameMode.from_name(self.modeTable.currentText()) - if len(index)==0: - raise GUIException(GUIErrors.NO_MODE) - - return int(index[0].data(0)) + def get_selected_version(self): + return LutrisVersion.from_value(self.lutrisVersion.currentText()) def display_text_message(self,message,icon): dialog=QMessageBox(self.window) @@ -92,10 +129,17 @@ class GUIQT6(GUI): def display_error(self,message): self.display_text_message(message,QMessageBox.Icon.Warning) - + def display_info(self,message): self.display_text_message(message,QMessageBox.Icon.Information) + def get_datas_of_lutris_games(self,version): + res=[] + for game in get_lutris_games(version): + res.append([game["id"],game["name"],game["directory"]]) + if len(res)==0: + return [["","",""]] + return res class TableModel(QtCore.QAbstractTableModel): def __init__(self, data): From 0a5fffac1a94c4e895e78695e3b8bb4a1e0bb56f Mon Sep 17 00:00:00 2001 From: Vivien Graffin Date: Fri, 12 Apr 2024 16:54:38 +0200 Subject: [PATCH 2/4] =?UTF-8?q?Correction=20de=20la=20m=C3=A9thode=20creat?= =?UTF-8?q?e=5Fcombobox?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linux/lutris_gui.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/lutris_gui.sh b/linux/lutris_gui.sh index 9344056ff..e39a64970 100755 --- a/linux/lutris_gui.sh +++ b/linux/lutris_gui.sh @@ -69,7 +69,7 @@ class GUIQT6(GUI): def create_combobox(self,layout,datas): combobox=QComboBox() - combobox.addItems(GameMode.name_list()) + combobox.addItems(datas) layout.addWidget(combobox) return combobox From 3e2e95ef26b3b9fa197d3b4576b2d3af709e3089 Mon Sep 17 00:00:00 2001 From: Vivien Graffin Date: Sat, 4 May 2024 13:07:13 +0200 Subject: [PATCH 3/4] [Linux] Ajout du EPTU --- linux/lib.py | 3 +++ linux/lutris_console.sh | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/linux/lib.py b/linux/lib.py index 78b360e11..259d4e5d9 100644 --- a/linux/lib.py +++ b/linux/lib.py @@ -42,6 +42,8 @@ def get_game_path(directory,mode): return Path(res,"PTU") case GameMode.TECH_PREVIEW.value: return Path(res,"TECH-PREVIEW") + case GameMode.EPTU.value: + return Path(res,"EPTU") class MyEnum(Enum): @classmethod @@ -74,6 +76,7 @@ class GameMode(MyEnum): LIVE = 1 PTU = 2 TECH_PREVIEW = 3 + EPTU = 4 def lutris_flatpak_pkg(): return "net.lutris.Lutris" diff --git a/linux/lutris_console.sh b/linux/lutris_console.sh index 4fb278516..8f587f4a8 100755 --- a/linux/lutris_console.sh +++ b/linux/lutris_console.sh @@ -50,7 +50,7 @@ def select_game_mode(): for mode in GameMode.list(): display_game_mode(str(mode.value),mode.name) i=int(input("Sélectionnez un ID correspondant au mode de Star Citizen: ")) - if i!=GameMode.LIVE.value and i!=GameMode.PTU.value and i!=GameMode.TECH_PREVIEW.value: + if i!=GameMode.LIVE.value and i!=GameMode.PTU.value and i!=GameMode.TECH_PREVIEW.value and i!=GameMode.EPTU.value: return select_game_mode() return i From 7965b29743e56db3896a9c4ee46b0f72db42ecc8 Mon Sep 17 00:00:00 2001 From: Vivien Graffin Date: Mon, 6 May 2024 11:14:34 +0200 Subject: [PATCH 4/4] =?UTF-8?q?R=C3=A9organisation=20du=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- linux/lib.py | 20 ++++++++------------ linux/lutris_console.sh | 12 +++++++----- linux/lutris_gui.sh | 10 +++++----- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/linux/lib.py b/linux/lib.py index 259d4e5d9..107731d72 100644 --- a/linux/lib.py +++ b/linux/lib.py @@ -36,14 +36,10 @@ def get_translation(): def get_game_path(directory,mode): res=Path(directory,"drive_c/Program Files/Roberts Space Industries/StarCitizen") match mode: - case GameMode.LIVE.value: - return Path(res,"LIVE") - case GameMode.PTU.value: - return Path(res,"PTU") case GameMode.TECH_PREVIEW.value: return Path(res,"TECH-PREVIEW") - case GameMode.EPTU.value: - return Path(res,"EPTU") + case _: + return Path(res,mode.name) class MyEnum(Enum): @classmethod @@ -59,13 +55,13 @@ def name_list(cls): def from_name(cls,name): for item in cls.list(): if item.name==name: - return item.value + return item raise Exception('Incorrect Name') @classmethod def from_value(cls,value): for item in cls.list(): if item.value==value: - return item.name + return item raise Exception('Incorrect Value') class LutrisVersion(MyEnum): @@ -84,9 +80,9 @@ def lutris_flatpak_pkg(): def get_lutris_versions(): res=[] if has_system_lutris(): - res.append('system') + res.append(LutrisVersion.system) if has_flatpak_lutris(): - res.append('flatpak') + res.append(LutrisVersion.flatpak) return res def command_exists(command): @@ -116,7 +112,7 @@ def get_system_lutris_games(): return get_lutris_gamelist(['lutris']) def get_lutris_games(version): - if version=='flatpak': + if version==LutrisVersion.flatpak: if has_flatpak_lutris(): return get_flatpak_lutris_games() else: @@ -166,7 +162,7 @@ def display_info(self,message): raise Exception("Méthode non implémenté") def get_versions_name(self): - return list(map(lambda c: LutrisVersion.from_name(c),self.versions)) + return list(map(lambda c: c.value,self.versions)) class GUIErrors(Enum): NO_DIRECTORY = 1 diff --git a/linux/lutris_console.sh b/linux/lutris_console.sh index 8f587f4a8..d05013cd4 100755 --- a/linux/lutris_console.sh +++ b/linux/lutris_console.sh @@ -18,16 +18,15 @@ def select_lutris_version(): display_list("ID","Version","") i=1 - versions=list(map(lambda c:LutrisVersion.from_name(c),versions)) for version in versions: - display_list(str(i),version,"") + display_list(str(i),version.value,"") i=int(input("Entrez l'ID de la version de Lutris: ")) if i>len(versions) or i<1: return select_lutris_version() - return LutrisVersion.from_value(versions[i-1]) + return versions[i-1] def select_lutris_game(version): games=get_lutris_games(version) @@ -50,9 +49,12 @@ def select_game_mode(): for mode in GameMode.list(): display_game_mode(str(mode.value),mode.name) i=int(input("Sélectionnez un ID correspondant au mode de Star Citizen: ")) - if i!=GameMode.LIVE.value and i!=GameMode.PTU.value and i!=GameMode.TECH_PREVIEW.value and i!=GameMode.EPTU.value: + try: + res=GameMode.from_value(i) + return res + except e: return select_game_mode() - return i + version=select_lutris_version() game=select_lutris_game(version) diff --git a/linux/lutris_gui.sh b/linux/lutris_gui.sh index e39a64970..52c010e12 100755 --- a/linux/lutris_gui.sh +++ b/linux/lutris_gui.sh @@ -24,9 +24,9 @@ class GUIQT6(GUI): layout.addWidget(QLabel("Jeux")) - self.gameTable=self.create_table(layout,self.get_datas_of_lutris_games("system")) + self.gameTable=self.create_table(layout,self.get_datas_of_lutris_games(LutrisVersion.system)) self.gameTable.clicked.connect(self.select_line_of_table_game) - self.flatpakGames=self.create_table(layout,self.get_datas_of_lutris_games("flatpak")) + self.flatpakGames=self.create_table(layout,self.get_datas_of_lutris_games(LutrisVersion.flatpak)) self.flatpakGames.clicked.connect(self.select_line_of_flatpak_games) if len(self.versions)==0: @@ -34,7 +34,7 @@ class GUIQT6(GUI): elif len(self.versions)==1: self.versionLabel.hide() self.lutrisVersion.hide() - if self.versions[0]=="system": + if self.versions[0]==LutrisVersion.system: self.flatpakGames.hide() else: self.gameTable.hide() @@ -75,7 +75,7 @@ class GUIQT6(GUI): def sync_table_game_to_table_version(self,index): - if self.get_version()=='flatpak': + if self.get_version()==LutrisVersion.flatpak: self.flatpakGames.show() self.gameTable.hide() else: @@ -99,7 +99,7 @@ class GUIQT6(GUI): self.flatpakGames.selectRow(row) def get_directory(self): - if self.get_version()=='system': + if self.get_version()==LutrisVersion.system: index = self.gameTable.selectedIndexes() if len(index)==0: