feat: added system overlay to guide button
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
This commit is contained in:
@ -25,6 +25,8 @@ class MainWindowProtocol(Protocol):
|
|||||||
...
|
...
|
||||||
def toggleGame(self, exec_line: str | None, button: QWidget | None = None) -> None:
|
def toggleGame(self, exec_line: str | None, button: QWidget | None = None) -> None:
|
||||||
...
|
...
|
||||||
|
def openSystemOverlay(self) -> None:
|
||||||
|
...
|
||||||
stackedWidget: QStackedWidget
|
stackedWidget: QStackedWidget
|
||||||
tabButtons: dict[int, QWidget]
|
tabButtons: dict[int, QWidget]
|
||||||
gamesListWidget: QWidget
|
gamesListWidget: QWidget
|
||||||
@ -42,6 +44,7 @@ BUTTONS = {
|
|||||||
'confirm_stick': {ecodes.BTN_THUMBL, ecodes.BTN_THUMBR},
|
'confirm_stick': {ecodes.BTN_THUMBL, ecodes.BTN_THUMBR},
|
||||||
'context_menu': {ecodes.BTN_START},
|
'context_menu': {ecodes.BTN_START},
|
||||||
'menu': {ecodes.BTN_SELECT},
|
'menu': {ecodes.BTN_SELECT},
|
||||||
|
'guide': {ecodes.BTN_MODE},
|
||||||
}
|
}
|
||||||
|
|
||||||
class InputManager(QObject):
|
class InputManager(QObject):
|
||||||
@ -131,6 +134,12 @@ class InputManager(QObject):
|
|||||||
focused = QApplication.focusWidget()
|
focused = QApplication.focusWidget()
|
||||||
popup = QApplication.activePopupWidget()
|
popup = QApplication.activePopupWidget()
|
||||||
|
|
||||||
|
# Handle Guide button to open system overlay
|
||||||
|
if button_code in BUTTONS['guide']:
|
||||||
|
if not popup and not isinstance(active, QDialog):
|
||||||
|
self._parent.openSystemOverlay()
|
||||||
|
return
|
||||||
|
|
||||||
# Handle QMenu (context menu)
|
# Handle QMenu (context menu)
|
||||||
if isinstance(popup, QMenu):
|
if isinstance(popup, QMenu):
|
||||||
if button_code in BUTTONS['confirm'] or button_code in BUTTONS['confirm_stick']:
|
if button_code in BUTTONS['confirm'] or button_code in BUTTONS['confirm_stick']:
|
||||||
@ -244,7 +253,7 @@ class InputManager(QObject):
|
|||||||
focused = QApplication.focusWidget()
|
focused = QApplication.focusWidget()
|
||||||
popup = QApplication.activePopupWidget()
|
popup = QApplication.activePopupWidget()
|
||||||
|
|
||||||
# Handle AddGameDialog navigation with D-pad
|
# Handle SystemOverlay or AddGameDialog navigation with D-pad
|
||||||
if isinstance(active, QDialog) and code == ecodes.ABS_HAT0Y and value != 0:
|
if isinstance(active, QDialog) and code == ecodes.ABS_HAT0Y and value != 0:
|
||||||
if not focused or not active.focusWidget():
|
if not focused or not active.focusWidget():
|
||||||
# If no widget is focused, focus the first focusable widget
|
# If no widget is focused, focus the first focusable widget
|
||||||
|
@ -13,6 +13,7 @@ from portprotonqt.game_card import GameCard
|
|||||||
from portprotonqt.custom_widgets import FlowLayout, ClickableLabel, AutoSizeButton, NavLabel
|
from portprotonqt.custom_widgets import FlowLayout, ClickableLabel, AutoSizeButton, NavLabel
|
||||||
from portprotonqt.input_manager import InputManager
|
from portprotonqt.input_manager import InputManager
|
||||||
from portprotonqt.context_menu_manager import ContextMenuManager
|
from portprotonqt.context_menu_manager import ContextMenuManager
|
||||||
|
from portprotonqt.system_overlay import SystemOverlay
|
||||||
|
|
||||||
from portprotonqt.image_utils import load_pixmap_async, round_corners, ImageCarousel
|
from portprotonqt.image_utils import load_pixmap_async, round_corners, ImageCarousel
|
||||||
from portprotonqt.steam_api import get_steam_game_info_async, get_full_steam_game_info_async, get_steam_installed_games
|
from portprotonqt.steam_api import get_steam_game_info_async, get_full_steam_game_info_async, get_steam_installed_games
|
||||||
@ -500,6 +501,11 @@ class MainWindow(QMainWindow):
|
|||||||
btn.setChecked(i == index)
|
btn.setChecked(i == index)
|
||||||
self.stackedWidget.setCurrentIndex(index)
|
self.stackedWidget.setCurrentIndex(index)
|
||||||
|
|
||||||
|
def openSystemOverlay(self):
|
||||||
|
"""Opens the system overlay dialog."""
|
||||||
|
overlay = SystemOverlay(self, self.theme)
|
||||||
|
overlay.exec()
|
||||||
|
|
||||||
def createSearchWidget(self) -> tuple[QWidget, QLineEdit]:
|
def createSearchWidget(self) -> tuple[QWidget, QLineEdit]:
|
||||||
self.container = QWidget()
|
self.container = QWidget()
|
||||||
self.container.setStyleSheet(self.theme.CONTAINER_STYLE)
|
self.container.setStyleSheet(self.theme.CONTAINER_STYLE)
|
||||||
|
100
portprotonqt/system_overlay.py
Normal file
100
portprotonqt/system_overlay.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
import subprocess
|
||||||
|
from PySide6.QtWidgets import QDialog, QVBoxLayout, QPushButton, QLabel, QMessageBox
|
||||||
|
from PySide6.QtWidgets import QApplication
|
||||||
|
from PySide6.QtCore import Qt
|
||||||
|
from portprotonqt.logger import get_logger
|
||||||
|
from portprotonqt.localization import _
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
class SystemOverlay(QDialog):
|
||||||
|
"""Overlay dialog for system actions like reboot, sleep, shutdown, suspend, and exit."""
|
||||||
|
def __init__(self, parent, theme):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.theme = theme
|
||||||
|
self.setWindowTitle(_("System Overlay"))
|
||||||
|
self.setModal(True)
|
||||||
|
self.setFixedSize(400, 300)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
layout.setContentsMargins(20, 20, 20, 20)
|
||||||
|
layout.setSpacing(10)
|
||||||
|
|
||||||
|
title = QLabel(_("System Actions"))
|
||||||
|
title.setStyleSheet(self.theme.TAB_TITLE_STYLE)
|
||||||
|
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
||||||
|
layout.addWidget(title)
|
||||||
|
|
||||||
|
# Reboot button
|
||||||
|
reboot_button = QPushButton(_("Reboot"))
|
||||||
|
#reboot_button.setStyleSheet(self.theme.ACTION_BUTTON_STYLE)
|
||||||
|
reboot_button.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
|
reboot_button.clicked.connect(self.reboot)
|
||||||
|
layout.addWidget(reboot_button)
|
||||||
|
|
||||||
|
# Shutdown button
|
||||||
|
shutdown_button = QPushButton(_("Shutdown"))
|
||||||
|
#shutdown_button.setStyleSheet(self.theme.ACTION_BUTTON_STYLE)
|
||||||
|
shutdown_button.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
|
shutdown_button.clicked.connect(self.shutdown)
|
||||||
|
layout.addWidget(shutdown_button)
|
||||||
|
|
||||||
|
# Suspend button
|
||||||
|
suspend_button = QPushButton(_("Suspend"))
|
||||||
|
#suspend_button.setStyleSheet(self.theme.ACTION_BUTTON_STYLE)
|
||||||
|
suspend_button.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
|
suspend_button.clicked.connect(self.suspend)
|
||||||
|
layout.addWidget(suspend_button)
|
||||||
|
|
||||||
|
# Exit application button
|
||||||
|
exit_button = QPushButton(_("Exit Application"))
|
||||||
|
#exit_button.setStyleSheet(self.theme.ACTION_BUTTON_STYLE)
|
||||||
|
exit_button.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
|
exit_button.clicked.connect(self.exit_application)
|
||||||
|
layout.addWidget(exit_button)
|
||||||
|
|
||||||
|
# Cancel button
|
||||||
|
cancel_button = QPushButton(_("Cancel"))
|
||||||
|
#cancel_button.setStyleSheet(self.theme.ACTION_BUTTON_STYLE)
|
||||||
|
cancel_button.setFocusPolicy(Qt.FocusPolicy.StrongFocus)
|
||||||
|
cancel_button.clicked.connect(self.reject)
|
||||||
|
layout.addWidget(cancel_button)
|
||||||
|
|
||||||
|
# Set focus to the first button
|
||||||
|
reboot_button.setFocus()
|
||||||
|
|
||||||
|
def reboot(self):
|
||||||
|
try:
|
||||||
|
subprocess.run(["systemctl", "reboot"], check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
logger.error(f"Failed to reboot: {e}")
|
||||||
|
QMessageBox.warning(self, _("Error"), _("Failed to reboot the system"))
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
def sleep(self):
|
||||||
|
try:
|
||||||
|
subprocess.run(["systemctl", "suspend-then-hibernate"], check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
logger.error(f"Failed to sleep: {e}")
|
||||||
|
QMessageBox.warning(self, _("Error"), _("Failed to put the system to sleep"))
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
try:
|
||||||
|
subprocess.run(["systemctl", "poweroff"], check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
logger.error(f"Failed to shutdown: {e}")
|
||||||
|
QMessageBox.warning(self, _("Error"), _("Failed to shutdown the system"))
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
def suspend(self):
|
||||||
|
try:
|
||||||
|
subprocess.run(["systemctl", "suspend"], check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
logger.error(f"Failed to suspend: {e}")
|
||||||
|
QMessageBox.warning(self, _("Error"), _("Failed to suspend the system"))
|
||||||
|
self.accept()
|
||||||
|
|
||||||
|
def exit_application(self):
|
||||||
|
QApplication.quit()
|
||||||
|
self.accept()
|
Reference in New Issue
Block a user