forked from Boria138/PortProtonQt
Compare commits
4 Commits
92d52938a9
...
14b5d6ce6f
Author | SHA1 | Date | |
---|---|---|---|
14b5d6ce6f
|
|||
90e27a49ca
|
|||
08c154ade6
|
|||
6efaff284f
|
@@ -10,7 +10,7 @@
|
|||||||
- Начальная поддержка EGS (Без EOS, скачивания игр и запуска игр из сторонних магазинов)
|
- Начальная поддержка EGS (Без EOS, скачивания игр и запуска игр из сторонних магазинов)
|
||||||
- Автодополнение bash для комманды portprotonqt
|
- Автодополнение bash для комманды portprotonqt
|
||||||
- Поддержка геймпадов в диалоге выбора игры
|
- Поддержка геймпадов в диалоге выбора игры
|
||||||
- Быстрый запуск игры через контекстное меню
|
- Быстрый запуск и остановка игры через контекстное меню
|
||||||
- Иконки в контекстом меню
|
- Иконки в контекстом меню
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@@ -20,9 +20,9 @@ Current translation status:
|
|||||||
|
|
||||||
| Locale | Progress | Translated |
|
| Locale | Progress | Translated |
|
||||||
| :----- | -------: | ---------: |
|
| :----- | -------: | ---------: |
|
||||||
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 of 183 |
|
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 of 185 |
|
||||||
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 of 183 |
|
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 of 185 |
|
||||||
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 183 of 183 |
|
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 185 of 185 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
| Локаль | Прогресс | Переведено |
|
| Локаль | Прогресс | Переведено |
|
||||||
| :----- | -------: | ---------: |
|
| :----- | -------: | ---------: |
|
||||||
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 из 183 |
|
| [de_DE](./de_DE/LC_MESSAGES/messages.po) | 0% | 0 из 185 |
|
||||||
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 из 183 |
|
| [es_ES](./es_ES/LC_MESSAGES/messages.po) | 0% | 0 из 185 |
|
||||||
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 183 из 183 |
|
| [ru_RU](./ru_RU/LC_MESSAGES/messages.po) | 100% | 185 из 185 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@@ -6,6 +6,8 @@ import subprocess
|
|||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
import orjson
|
import orjson
|
||||||
|
import psutil
|
||||||
|
import signal
|
||||||
from PySide6.QtWidgets import QMessageBox, QDialog, QMenu
|
from PySide6.QtWidgets import QMessageBox, QDialog, QMenu
|
||||||
from PySide6.QtCore import QUrl, QPoint, QObject, Signal, Qt
|
from PySide6.QtCore import QUrl, QPoint, QObject, Signal, Qt
|
||||||
from PySide6.QtGui import QDesktopServices, QIcon
|
from PySide6.QtGui import QDesktopServices, QIcon
|
||||||
@@ -120,6 +122,35 @@ class ContextMenuManager:
|
|||||||
logger.error("Failed to read installed.json: %s", e)
|
logger.error("Failed to read installed.json: %s", e)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _is_game_running(self, game_card) -> bool:
|
||||||
|
"""
|
||||||
|
Check if the game associated with the game_card is currently running.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
game_card: The GameCard instance containing game data.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool: True if the game is running, False otherwise.
|
||||||
|
"""
|
||||||
|
if game_card.game_source == "epic":
|
||||||
|
exe_path = get_egs_executable(game_card.appid, self.legendary_config_path)
|
||||||
|
if not exe_path or not os.path.exists(exe_path):
|
||||||
|
return False
|
||||||
|
current_exe = os.path.basename(exe_path)
|
||||||
|
else:
|
||||||
|
exec_line = self._get_exec_line(game_card.name, game_card.exec_line)
|
||||||
|
if not exec_line:
|
||||||
|
return False
|
||||||
|
exe_path = self._parse_exe_path(exec_line, game_card.name)
|
||||||
|
if not exe_path:
|
||||||
|
return False
|
||||||
|
current_exe = os.path.basename(exe_path)
|
||||||
|
|
||||||
|
# Check if the current_exe matches the target_exe in MainWindow
|
||||||
|
if hasattr(self.parent, 'target_exe') and self.parent.target_exe == current_exe:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def show_context_menu(self, game_card, pos: QPoint):
|
def show_context_menu(self, game_card, pos: QPoint):
|
||||||
"""
|
"""
|
||||||
Show the context menu for a game card at the specified position.
|
Show the context menu for a game card at the specified position.
|
||||||
@@ -140,7 +171,11 @@ class ContextMenuManager:
|
|||||||
menu = QMenu(self.parent)
|
menu = QMenu(self.parent)
|
||||||
menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE)
|
menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE)
|
||||||
|
|
||||||
launch_action = menu.addAction(get_safe_icon("play"), _("Launch Game"))
|
# Check if the game is running
|
||||||
|
is_running = self._is_game_running(game_card)
|
||||||
|
action_text = _("Stop Game") if is_running else _("Launch Game")
|
||||||
|
action_icon = "stop" if is_running else "play"
|
||||||
|
launch_action = menu.addAction(get_safe_icon(action_icon), action_text)
|
||||||
launch_action.triggered.connect(
|
launch_action.triggered.connect(
|
||||||
lambda: self._launch_game(game_card)
|
lambda: self._launch_game(game_card)
|
||||||
)
|
)
|
||||||
@@ -153,7 +188,7 @@ class ContextMenuManager:
|
|||||||
favorite_action.triggered.connect(lambda: self.toggle_favorite(game_card, not is_favorite))
|
favorite_action.triggered.connect(lambda: self.toggle_favorite(game_card, not is_favorite))
|
||||||
|
|
||||||
if game_card.game_source == "epic":
|
if game_card.game_source == "epic":
|
||||||
import_action = menu.addAction(get_safe_icon("import"), _("Import to Legendary"))
|
import_action = menu.addAction(get_safe_icon("epic_games"), _("Import to Legendary"))
|
||||||
import_action.triggered.connect(
|
import_action.triggered.connect(
|
||||||
lambda: self.import_to_legendary(game_card.name, game_card.appid)
|
lambda: self.import_to_legendary(game_card.name, game_card.appid)
|
||||||
)
|
)
|
||||||
@@ -240,13 +275,44 @@ class ContextMenuManager:
|
|||||||
|
|
||||||
def _launch_game(self, game_card):
|
def _launch_game(self, game_card):
|
||||||
"""
|
"""
|
||||||
Launch a game using a validated exec_line, handling EGS games specifically.
|
Launch or stop a game based on its current state.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
game_card: The GameCard instance containing game data.
|
game_card: The GameCard instance containing game data.
|
||||||
"""
|
"""
|
||||||
if not self._check_portproton():
|
if not self._check_portproton():
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Check if the game is running
|
||||||
|
if self._is_game_running(game_card):
|
||||||
|
# Stop the game
|
||||||
|
if hasattr(self.parent, 'game_processes') and self.parent.game_processes:
|
||||||
|
for proc in self.parent.game_processes:
|
||||||
|
try:
|
||||||
|
parent = psutil.Process(proc.pid)
|
||||||
|
children = parent.children(recursive=True)
|
||||||
|
for child in children:
|
||||||
|
try:
|
||||||
|
child.terminate()
|
||||||
|
except psutil.NoSuchProcess:
|
||||||
|
pass
|
||||||
|
psutil.wait_procs(children, timeout=5)
|
||||||
|
for child in children:
|
||||||
|
if child.is_running():
|
||||||
|
child.kill()
|
||||||
|
os.killpg(os.getpgid(proc.pid), signal.SIGTERM)
|
||||||
|
except psutil.NoSuchProcess:
|
||||||
|
pass
|
||||||
|
self.parent.game_processes = []
|
||||||
|
self.parent.resetPlayButton()
|
||||||
|
if hasattr(self.parent, 'checkProcessTimer') and self.parent.checkProcessTimer is not None:
|
||||||
|
self.parent.checkProcessTimer.stop()
|
||||||
|
self.parent.checkProcessTimer.deleteLater()
|
||||||
|
self.parent.checkProcessTimer = None
|
||||||
|
self._show_status_message(_("Stopped '{game_name}'").format(game_name=game_card.name))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Launch the game
|
||||||
if game_card.game_source == "epic":
|
if game_card.game_source == "epic":
|
||||||
if not os.path.exists(self.legendary_path):
|
if not os.path.exists(self.legendary_path):
|
||||||
self.signals.show_warning_dialog.emit(
|
self.signals.show_warning_dialog.emit(
|
||||||
|
Binary file not shown.
@@ -9,7 +9,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2025-07-01 15:54+0500\n"
|
"POT-Creation-Date: 2025-07-02 10:43+0500\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language: de_DE\n"
|
"Language: de_DE\n"
|
||||||
@@ -26,6 +26,9 @@ msgstr ""
|
|||||||
msgid "PortProton is not found"
|
msgid "PortProton is not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Stop Game"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Launch Game"
|
msgid "Launch Game"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -65,6 +68,10 @@ msgstr ""
|
|||||||
msgid "Delete from PortProton"
|
msgid "Delete from PortProton"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Stopped '{game_name}'"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Legendary executable not found at {path}"
|
msgid "Legendary executable not found at {path}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Binary file not shown.
@@ -9,7 +9,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2025-07-01 15:54+0500\n"
|
"POT-Creation-Date: 2025-07-02 10:43+0500\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language: es_ES\n"
|
"Language: es_ES\n"
|
||||||
@@ -26,6 +26,9 @@ msgstr ""
|
|||||||
msgid "PortProton is not found"
|
msgid "PortProton is not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Stop Game"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Launch Game"
|
msgid "Launch Game"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -65,6 +68,10 @@ msgstr ""
|
|||||||
msgid "Delete from PortProton"
|
msgid "Delete from PortProton"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Stopped '{game_name}'"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Legendary executable not found at {path}"
|
msgid "Legendary executable not found at {path}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@@ -9,7 +9,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PortProtonQt 0.1.1\n"
|
"Project-Id-Version: PortProtonQt 0.1.1\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2025-07-01 15:54+0500\n"
|
"POT-Creation-Date: 2025-07-02 10:43+0500\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -24,6 +24,9 @@ msgstr ""
|
|||||||
msgid "PortProton is not found"
|
msgid "PortProton is not found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "Stop Game"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "Launch Game"
|
msgid "Launch Game"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -63,6 +66,10 @@ msgstr ""
|
|||||||
msgid "Delete from PortProton"
|
msgid "Delete from PortProton"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Stopped '{game_name}'"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Legendary executable not found at {path}"
|
msgid "Legendary executable not found at {path}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Binary file not shown.
@@ -9,8 +9,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PROJECT VERSION\n"
|
"Project-Id-Version: PROJECT VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
|
||||||
"POT-Creation-Date: 2025-07-01 15:54+0500\n"
|
"POT-Creation-Date: 2025-07-02 10:43+0500\n"
|
||||||
"PO-Revision-Date: 2025-07-01 15:54+0500\n"
|
"PO-Revision-Date: 2025-07-02 10:43+0500\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language: ru_RU\n"
|
"Language: ru_RU\n"
|
||||||
"Language-Team: ru_RU <LL@li.org>\n"
|
"Language-Team: ru_RU <LL@li.org>\n"
|
||||||
@@ -27,6 +27,9 @@ msgstr "Ошибка"
|
|||||||
msgid "PortProton is not found"
|
msgid "PortProton is not found"
|
||||||
msgstr "PortProton не найден"
|
msgstr "PortProton не найден"
|
||||||
|
|
||||||
|
msgid "Stop Game"
|
||||||
|
msgstr "Остановить игру"
|
||||||
|
|
||||||
msgid "Launch Game"
|
msgid "Launch Game"
|
||||||
msgstr "Запустить игру"
|
msgstr "Запустить игру"
|
||||||
|
|
||||||
@@ -66,6 +69,10 @@ msgstr "Редактировать"
|
|||||||
msgid "Delete from PortProton"
|
msgid "Delete from PortProton"
|
||||||
msgstr "Удалить из PortProton"
|
msgstr "Удалить из PortProton"
|
||||||
|
|
||||||
|
#, python-brace-format
|
||||||
|
msgid "Stopped '{game_name}'"
|
||||||
|
msgstr "Остановлен(а) '{game_name}'"
|
||||||
|
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Legendary executable not found at {path}"
|
msgid "Legendary executable not found at {path}"
|
||||||
msgstr "Legendary не найден по пути {path}"
|
msgstr "Legendary не найден по пути {path}"
|
||||||
|
Reference in New Issue
Block a user