add icons to context menu #21
@@ -8,12 +8,13 @@ import logging
 | 
			
		||||
import orjson
 | 
			
		||||
from PySide6.QtWidgets import QMessageBox, QDialog, QMenu
 | 
			
		||||
from PySide6.QtCore import QUrl, QPoint, QObject, Signal, Qt
 | 
			
		||||
from PySide6.QtGui import QDesktopServices
 | 
			
		||||
from PySide6.QtGui import QDesktopServices, QIcon
 | 
			
		||||
from portprotonqt.localization import _
 | 
			
		||||
from portprotonqt.config_utils import parse_desktop_entry, read_favorites, save_favorites
 | 
			
		||||
from portprotonqt.steam_api import is_game_in_steam, add_to_steam, remove_from_steam
 | 
			
		||||
from portprotonqt.egs_api import add_egs_to_steam, get_egs_executable, remove_egs_from_steam
 | 
			
		||||
from portprotonqt.dialogs import AddGameDialog, FileExplorer, generate_thumbnail
 | 
			
		||||
from portprotonqt.theme_manager import ThemeManager
 | 
			
		||||
 | 
			
		||||
logger = logging.getLogger(__name__)
 | 
			
		||||
 | 
			
		||||
@@ -40,6 +41,7 @@ class ContextMenuManager:
 | 
			
		||||
        self.parent = parent
 | 
			
		||||
        self.portproton_location = portproton_location
 | 
			
		||||
        self.theme = theme
 | 
			
		||||
        self.theme_manager = ThemeManager()
 | 
			
		||||
        self.load_games = load_games_callback
 | 
			
		||||
        self.update_game_grid = update_game_grid_callback
 | 
			
		||||
        self.legendary_path = os.path.join(
 | 
			
		||||
@@ -129,16 +131,16 @@ class ContextMenuManager:
 | 
			
		||||
        menu = QMenu(self.parent)
 | 
			
		||||
        menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE)
 | 
			
		||||
 | 
			
		||||
        launch_action = menu.addAction(_("Launch Game"))
 | 
			
		||||
        launch_action = menu.addAction(QIcon(self.theme_manager.get_icon("play")), _("Launch Game"))
 | 
			
		||||
        launch_action.triggered.connect(
 | 
			
		||||
            lambda: self._launch_game(game_card)
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        favorites = read_favorites()
 | 
			
		||||
        is_favorite = game_card.name in favorites
 | 
			
		||||
        favorite_action = menu.addAction(
 | 
			
		||||
            _("Remove from Favorites") if is_favorite else _("Add to Favorites")
 | 
			
		||||
        )
 | 
			
		||||
        icon_name = "star_full" if is_favorite else "star"
 | 
			
		||||
        text = _("Remove from Favorites") if is_favorite else _("Add to Favorites")
 | 
			
		||||
        favorite_action = menu.addAction(QIcon(self.theme_manager.get_icon(icon_name)), text)
 | 
			
		||||
        favorite_action.triggered.connect(lambda: self.toggle_favorite(game_card, not is_favorite))
 | 
			
		||||
 | 
			
		||||
        if game_card.game_source == "epic":
 | 
			
		||||
@@ -148,23 +150,23 @@ class ContextMenuManager:
 | 
			
		||||
            )
 | 
			
		||||
            if self._is_egs_game_installed(game_card.appid):
 | 
			
		||||
                is_in_steam = is_game_in_steam(game_card.name)
 | 
			
		||||
                steam_action = menu.addAction(
 | 
			
		||||
                    _("Remove from Steam") if is_in_steam else _("Add to Steam")
 | 
			
		||||
                )
 | 
			
		||||
                icon_name = "delete" if is_in_steam else "steam"
 | 
			
		||||
                text = _("Remove from Steam") if is_in_steam else _("Add to Steam")
 | 
			
		||||
                steam_action = menu.addAction(QIcon(self.theme_manager.get_icon(icon_name)), text)
 | 
			
		||||
                steam_action.triggered.connect(
 | 
			
		||||
                    lambda: self.remove_from_steam(game_card.name, game_card.exec_line, game_card.game_source)
 | 
			
		||||
                    if is_in_steam
 | 
			
		||||
                    else self.add_egs_to_steam(game_card.name, game_card.appid)
 | 
			
		||||
                )
 | 
			
		||||
                open_folder_action = menu.addAction(_("Open Game Folder"))
 | 
			
		||||
                open_folder_action = menu.addAction(QIcon(self.theme_manager.get_icon("search")), _("Open Game Folder"))
 | 
			
		||||
                open_folder_action.triggered.connect(
 | 
			
		||||
                    lambda: self.open_egs_game_folder(game_card.appid)
 | 
			
		||||
                )
 | 
			
		||||
                desktop_dir = subprocess.check_output(['xdg-user-dir', 'DESKTOP']).decode('utf-8').strip()
 | 
			
		||||
                desktop_path = os.path.join(desktop_dir, f"{game_card.name}.desktop")
 | 
			
		||||
                desktop_action = menu.addAction(
 | 
			
		||||
                    _("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
 | 
			
		||||
                )
 | 
			
		||||
                icon_name = "delete" if os.path.exists(desktop_path) else "desktop"
 | 
			
		||||
                text = _("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
 | 
			
		||||
                desktop_action = menu.addAction(QIcon(self.theme_manager.get_icon(icon_name)), text)
 | 
			
		||||
                desktop_action.triggered.connect(
 | 
			
		||||
                    lambda: self.remove_egs_from_desktop(game_card.name)
 | 
			
		||||
                    if os.path.exists(desktop_path)
 | 
			
		||||
@@ -184,42 +186,44 @@ class ContextMenuManager:
 | 
			
		||||
        if game_card.game_source not in ("steam", "epic"):
 | 
			
		||||
            desktop_dir = subprocess.check_output(['xdg-user-dir', 'DESKTOP']).decode('utf-8').strip()
 | 
			
		||||
            desktop_path = os.path.join(desktop_dir, f"{game_card.name}.desktop")
 | 
			
		||||
            desktop_action = menu.addAction(
 | 
			
		||||
                _("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
 | 
			
		||||
            )
 | 
			
		||||
            icon_name = "delete" if os.path.exists(desktop_path) else "desktop"
 | 
			
		||||
            text = _("Remove from Desktop") if os.path.exists(desktop_path) else _("Add to Desktop")
 | 
			
		||||
            desktop_action = menu.addAction(QIcon(self.theme_manager.get_icon(icon_name)), text)
 | 
			
		||||
            desktop_action.triggered.connect(
 | 
			
		||||
                lambda: self.remove_from_desktop(game_card.name)
 | 
			
		||||
                if os.path.exists(desktop_path)
 | 
			
		||||
                else self.add_to_desktop(game_card.name, game_card.exec_line)
 | 
			
		||||
            )
 | 
			
		||||
            edit_action = menu.addAction(_("Edit Shortcut"))
 | 
			
		||||
            edit_action = menu.addAction(QIcon(self.theme_manager.get_icon("edit")), _("Edit Shortcut"))
 | 
			
		||||
            edit_action.triggered.connect(
 | 
			
		||||
                lambda: self.edit_game_shortcut(game_card.name, game_card.exec_line, game_card.cover_path)
 | 
			
		||||
            )
 | 
			
		||||
            delete_action = menu.addAction(_("Delete from PortProton"))
 | 
			
		||||
            delete_action = menu.addAction(QIcon(self.theme_manager.get_icon("delete")), _("Delete from PortProton"))
 | 
			
		||||
            delete_action.triggered.connect(lambda: self.delete_game(game_card.name, game_card.exec_line))
 | 
			
		||||
            open_folder_action = menu.addAction(_("Open Game Folder"))
 | 
			
		||||
            open_folder_action = menu.addAction(QIcon(self.theme_manager.get_icon("search")), _("Open Game Folder"))
 | 
			
		||||
            open_folder_action.triggered.connect(
 | 
			
		||||
                lambda: self.open_game_folder(game_card.name, game_card.exec_line)
 | 
			
		||||
            )
 | 
			
		||||
            applications_dir = os.path.join(os.path.expanduser("~"), ".local", "share", "applications")
 | 
			
		||||
            menu_path = os.path.join(applications_dir, f"{game_card.name}.desktop")
 | 
			
		||||
            menu_action = menu.addAction(
 | 
			
		||||
                _("Remove from Menu") if os.path.exists(menu_path) else _("Add to Menu")
 | 
			
		||||
            )
 | 
			
		||||
            icon_name = "delete" if os.path.exists(menu_path) else "menu"
 | 
			
		||||
            text = _("Remove from Menu") if os.path.exists(menu_path) else _("Add to Menu")
 | 
			
		||||
            menu_action = menu.addAction(QIcon(self.theme_manager.get_icon(icon_name)), text)
 | 
			
		||||
            menu_action.triggered.connect(
 | 
			
		||||
                lambda: self.remove_from_menu(game_card.name)
 | 
			
		||||
                if os.path.exists(menu_path)
 | 
			
		||||
                else self.add_to_menu(game_card.name, game_card.exec_line)
 | 
			
		||||
            )
 | 
			
		||||
            is_in_steam = is_game_in_steam(game_card.name)
 | 
			
		||||
            steam_action = menu.addAction(
 | 
			
		||||
                _("Remove from Steam") if is_in_steam else _("Add to Steam")
 | 
			
		||||
            )
 | 
			
		||||
            icon_name = "delete" if is_in_steam else "steam"
 | 
			
		||||
            text = _("Remove from Steam") if is_in_steam else _("Add to Steam")
 | 
			
		||||
            steam_action = menu.addAction(QIcon(self.theme_manager.get_icon(icon_name)), text)
 | 
			
		||||
            steam_action.triggered.connect(
 | 
			
		||||
                lambda: self.remove_from_steam(game_card.name, game_card.exec_line, game_card.game_source)
 | 
			
		||||
                if is_in_steam
 | 
			
		||||
                else self.add_to_steam(game_card.name, game_card.exec_line, game_card.cover_path)
 | 
			
		||||
                lambda: (
 | 
			
		||||
                    self.remove_from_steam(game_card.name, game_card.exec_line, game_card.game_source)
 | 
			
		||||
                    if is_in_steam
 | 
			
		||||
                    else self.add_to_steam(game_card.name, game_card.exec_line, game_card.cover_path)
 | 
			
		||||
                )
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        menu.exec(game_card.mapToGlobal(pos))
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								portprotonqt/themes/standart/images/icons/delete.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								portprotonqt/themes/standart/images/icons/delete.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m5.48 11.5 2.52-2.52 2.52 2.52 0.98-0.98-2.52-2.52 2.52-2.52-0.98-0.98-2.52 2.52-2.52-2.52-0.98 0.98 2.52 2.52-2.52 2.52zm2.52 3.5q-1.4525 0-2.73-0.55125t-2.2225-1.4962-1.4962-2.2225-0.55125-2.73 0.55125-2.73 1.4962-2.2225 2.2225-1.4962 2.73-0.55125 2.73 0.55125 2.2225 1.4962 1.4962 2.2225 0.55125 2.73-0.55125 2.73-1.4962 2.2225-2.2225 1.4962-2.73 0.55125zm0-1.4q2.345 0 3.9725-1.6275t1.6275-3.9725-1.6275-3.9725-3.9725-1.6275-3.9725 1.6275-1.6275 3.9725 1.6275 3.9725 3.9725 1.6275z" fill="#fff"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 634 B  | 
							
								
								
									
										1
									
								
								portprotonqt/themes/standart/images/icons/edit.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								portprotonqt/themes/standart/images/icons/edit.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m4.0723 1c-1.6982 0-3.0801 1.3818-3.0801 3.0801v7.8398c0 1.6982 1.3818 3.0801 3.0801 3.0801h7.8398c1.6982 0 3.0801-1.3818 3.0801-3.0801v-7.8398l-0.93359 0.93359v6.9063c0 1.1973-0.94916 2.1465-2.1465 2.1465h-7.8398c-1.1973 0-2.1465-0.94916-2.1465-2.1465v-7.8398c0-1.1973 0.94916-2.1465 2.1465-2.1465h7.0938l0.85547-0.85352 0.0078-0.00781c0.02511-0.02302 0.04987-0.044899 0.07617-0.066406-0.064467-0.0040524-0.12786-0.0058621-0.19334-0.0058621zm9.1211 0.042969c-0.14335 0-0.28025 0.028276-0.41016 0.082031-0.12991 0.053755-0.24991 0.12997-0.35742 0.22852l-7.0937 7.082v2.2832h2.2832l7.082-7.082c0.10751-0.10751 0.18705-0.22556 0.23633-0.35547 0.04927-0.12991 0.07422-0.26681 0.07422-0.41016 0-0.13439-0.02495-0.26796-0.07422-0.40234-0.049276-0.13439-0.12882-0.25106-0.23633-0.34961l-0.73828-0.75391c-0.09855-0.10751-0.21522-0.18648-0.34961-0.24023-0.13439-0.053755-0.27267-0.082031-0.41602-0.082031zm-1.5332 2.5801 0.37695 0.39062 0.38867 0.37695-5.2539 5.2539h-0.76562v-0.76562z" fill="#fff" fill-rule="evenodd" stop-color="#000000" stroke-width=".93333"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 1.2 KiB  | 
							
								
								
									
										1
									
								
								portprotonqt/themes/standart/images/icons/menu.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								portprotonqt/themes/standart/images/icons/menu.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m1 1.75v2h3.5v-2zm5.25 0v2h8.75v-2zm-5.25 5.25v2h3.5v-2zm5.25 0v2h8.75v-2zm-5.25 5.25v2h3.5v-2zm5.25 0v2h8.75v-2z" fill="#fff" stroke-width=".75593"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 284 B  | 
							
								
								
									
										1
									
								
								portprotonqt/themes/standart/images/icons/star.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								portprotonqt/themes/standart/images/icons/star.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="M 5.795,11.7275 8,10.3975 10.205,11.745 9.6275,9.225 11.57,7.545 9.015,7.3175 8,4.9375 6.985,7.3 4.43,7.5275 6.3725,9.225 Z M 3.6775,14.65 4.815,9.7325 1,6.425 6.04,5.9875 8,1.35 9.96,5.9875 15,6.425 11.185,9.7325 12.3225,14.65 8,12.0425 Z M 8,8.525 Z" fill="#fff" stroke-width=".0175"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 421 B  | 
							
								
								
									
										1
									
								
								portprotonqt/themes/standart/images/icons/star_full.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								portprotonqt/themes/standart/images/icons/star_full.svg
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
<svg width="16" height="16" version="1.1" viewBox="0 0 16 16" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><path d="m8 1.3496-1.9609 4.6387-5.0391 0.4375 3.8145 3.3066-1.1367 4.918 4.3223-2.6074 4.3223 2.6074-1.1367-4.918 3.8145-3.3066-5.0391-0.4375z" fill="#fff" stroke-width=".0175"/></svg>
 | 
			
		||||
| 
		 After Width: | Height: | Size: 304 B  | 
@@ -104,8 +104,11 @@ CONTEXT_MENU_STYLE = f"""
 | 
			
		||||
        font-size: {font_size_a};
 | 
			
		||||
        padding: 5px;
 | 
			
		||||
    }}
 | 
			
		||||
    QMenu::icon {{
 | 
			
		||||
    margin-left: 15px;
 | 
			
		||||
    }}
 | 
			
		||||
    QMenu::item {{
 | 
			
		||||
        padding: 8px 20px;
 | 
			
		||||
        padding: 8px 20px 8px 10px;
 | 
			
		||||
        background: {color_h};
 | 
			
		||||
        border-radius: {border_radius_a};
 | 
			
		||||
        color: {color_f};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user