From 6acf8f0f0b71ffd529520d46664e2b98c0584c4c Mon Sep 17 00:00:00 2001 From: ChemicalXandco <32775248+ChemicalXandco@users.noreply.github.com> Date: Tue, 13 Apr 2021 22:54:46 +0100 Subject: [PATCH 01/21] Use windows .msi installer for desktop shortcut --- .github/workflows/release.yml | 17 ++----- rare/utils/utils.py | 12 ----- setup.py | 95 +++++++++++++++++++++++------------ 3 files changed, 66 insertions(+), 58 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 067e06c9..1d83449e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,25 +55,16 @@ jobs: python-version: '3.8' - name: Install python deps run: | - pip3 install pyinstaller setuptools wheel + pip3 install cx_Freeze setuptools wheel pip3 install -r requirements.txt - - name: Prepare - run: cp rare/__main__.py ./ - name: Build - run: pyinstaller - --icon=rare/styles/Logo.ico - --onefile - --name Rare - --add-data="Rare/languages/*;Rare/languages" - --add-data="Rare/Styles/*;Rare/Styles" - --windowed - __main__.py + run: python3 setup.py bdist_msi - name: Upload files to GitHub uses: svenstaro/upload-release-action@2.2.1 with: repo_token: ${{ secrets.GITHUB_TOKEN }} - file: dist/Rare.exe - asset_name: Rare.exe + file: dist/Rare*.msi + asset_name: Rare.msi tag: ${{ github.ref }} overwrite: true diff --git a/rare/utils/utils.py b/rare/utils/utils.py index bffea2f7..eb8443bb 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -164,15 +164,3 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): "StartupWMClass=rare-game\n" ) os.chmod(os.path.expanduser(f"~/Desktop/{igame.title}.desktop"), 0o755) - - # Windows - elif os.name == "nt": - if type_of_link == "desktop": - path = os.path.expanduser(f"~/Desktop/") - elif type_of_link == "start_menu": - logger.info("Startmenu link is not supported on windows") - return - else: - return - with open(path+igame.title+".bat", "w") as desktop_file: - desktop_file.write(f"rare launch {app_name}") \ No newline at end of file diff --git a/setup.py b/setup.py index 87eb2725..49d70fae 100644 --- a/setup.py +++ b/setup.py @@ -1,39 +1,68 @@ -import setuptools +import sys -from rare import __version__ as version +from cx_Freeze import setup, Executable -with open("README.md", "r") as fh: - long_description = fh.read() +import rare -setuptools.setup( - name="Rare", - version=version, - author="Dummerle", - license="GPL-3", - description="A gui for Legendary", - long_description=long_description, - long_description_content_type="text/markdown", - include_package_data=True, - url="https://github.com/Dummerle/Rare", - packages=setuptools.find_packages(), - classifiers=[ - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', - "Operating System :: OS Independent" +base = None +name = None +shortcutName = None +shortcutDir = None +bdist_msi_options = None +if sys.platform == 'win32': + base = 'Win32GUI' + name = 'Rare.exe' + shortcut_table = [ + ('DesktopShortcut', # Shortcut + 'DesktopFolder', # Directory + 'Rare', # Name + 'TARGETDIR', # Component + '[TARGETDIR]'+name, # Target + None, # Arguments + 'A gui for Legendary.', # Description + None, # Hotkey + None, # Icon + None, # IconIndex + None, # ShowCmd + 'TARGETDIR' # Working Directory + )] + msi_data = {"Shortcut": shortcut_table} + bdist_msi_options = {'data': msi_data} +else: + name = 'Rare' + +opts = { + 'packages': [ + 'requests', + 'PIL', + 'qtawesome', + 'notifypy', + 'psutil', + 'pypresence', ], - python_requires=">=3.8", - entry_points=dict(console_scripts=["rare=rare.__main__:main"]), - install_requires=[ - "requests<3.0", - "pillow", - "setuptools", - "wheel", - "PyQt5", - "QtAwesome", - "notify-py", - "psutil", - "pypresence" + 'zip_include_packages': [ + 'PyQt5.QtCore', + 'PyQt5.QtGui', + 'PyQt5.QtWidgets', + ], + 'include_files': [ + 'LICENSE', + 'README.MD', + 'rare/styles/Logo.ico', + ], +} + +setup(name = 'Rare', + version = rare.__version__, + description = 'A gui for Legendary.', + options = {'build_exe': opts, "bdist_msi": bdist_msi_options}, + executables = [ + Executable('rare/__main__.py', + targetName=name, + icon='rare/styles/Logo.ico', + base=base, + shortcutName=shortcutName, + shortcutDir=shortcutDir, + ), ], ) From 0b31fe9ee23ff85e3748c391487cf882f97de10b Mon Sep 17 00:00:00 2001 From: ChemicalXandco <32775248+ChemicalXandco@users.noreply.github.com> Date: Wed, 14 Apr 2021 21:50:38 +0100 Subject: [PATCH 02/21] linux support for new build system --- .gitignore | 4 +++- setup.py | 62 ++++++++++++++++++++++++++++++------------------------ 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/.gitignore b/.gitignore index 2547711d..af20f06c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,5 +6,7 @@ __pycache__ /.vscode /build /dist +/deb_dist +*.tar.gz /Rare.egg-info/ -/venv \ No newline at end of file +/venv diff --git a/setup.py b/setup.py index 49d70fae..3833d298 100644 --- a/setup.py +++ b/setup.py @@ -4,33 +4,6 @@ from cx_Freeze import setup, Executable import rare -base = None -name = None -shortcutName = None -shortcutDir = None -bdist_msi_options = None -if sys.platform == 'win32': - base = 'Win32GUI' - name = 'Rare.exe' - shortcut_table = [ - ('DesktopShortcut', # Shortcut - 'DesktopFolder', # Directory - 'Rare', # Name - 'TARGETDIR', # Component - '[TARGETDIR]'+name, # Target - None, # Arguments - 'A gui for Legendary.', # Description - None, # Hotkey - None, # Icon - None, # IconIndex - None, # ShowCmd - 'TARGETDIR' # Working Directory - )] - msi_data = {"Shortcut": shortcut_table} - bdist_msi_options = {'data': msi_data} -else: - name = 'Rare' - opts = { 'packages': [ 'requests', @@ -52,10 +25,43 @@ opts = { ], } +setup_options = {'build_exe': opts} +base = None +name = None +shortcutName = None +shortcutDir = None +bdist_msi_options = None + +if sys.platform == 'win32': + base = 'Win32GUI' + name = 'Rare.exe' + shortcut_table = [ + ('DesktopShortcut', # Shortcut + 'DesktopFolder', # Directory + 'Rare', # Name + 'TARGETDIR', # Component + '[TARGETDIR]'+name, # Target + None, # Arguments + 'A gui for Legendary.', # Description + None, # Hotkey + None, # Icon + None, # IconIndex + None, # ShowCmd + 'TARGETDIR' # Working Directory + )] + msi_data = {"Shortcut": shortcut_table} + bdist_msi_options = {'data': msi_data} + setup_options.update({"bdist_msi": bdist_msi_options}) +else: + name = 'Rare' + setup(name = 'Rare', version = rare.__version__, description = 'A gui for Legendary.', - options = {'build_exe': opts, "bdist_msi": bdist_msi_options}, + options = setup_options, + setup_requires=[ + 'cx_Freeze', + ], executables = [ Executable('rare/__main__.py', targetName=name, From 887dcf6ff746042f99708cda59cebf93bc306c4b Mon Sep 17 00:00:00 2001 From: ChemicalXandco <32775248+ChemicalXandco@users.noreply.github.com> Date: Sat, 8 May 2021 16:47:49 +0100 Subject: [PATCH 03/21] split build into setup.py and freeze.py --- .github/workflows/release.yml | 4 +- freeze.py | 82 +++++++++++++++++++++++++++ setup.py | 101 +++++++++++----------------------- 3 files changed, 117 insertions(+), 70 deletions(-) create mode 100644 freeze.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1d83449e..f671a082 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,7 +46,7 @@ jobs: ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} commit_message: Update AUR package - pyinstaller-windows: + cx-freeze-windows: runs-on: windows-latest steps: - uses: actions/checkout@v2 @@ -58,7 +58,7 @@ jobs: pip3 install cx_Freeze setuptools wheel pip3 install -r requirements.txt - name: Build - run: python3 setup.py bdist_msi + run: python3 freeze.py bdist_msi - name: Upload files to GitHub uses: svenstaro/upload-release-action@2.2.1 with: diff --git a/freeze.py b/freeze.py new file mode 100644 index 00000000..05ce3716 --- /dev/null +++ b/freeze.py @@ -0,0 +1,82 @@ +import sys + +from cx_Freeze import setup, Executable + +from rare import __version__ + +# Packages to include +python_packages = [ + "PyQt5", + 'requests', + 'PIL', + 'qtawesome', + 'notifypy', + 'psutil', + 'pypresence', +] + +# Modules to include +python_modules = [] + +base = None +name = None +build_options = {} +build_exe_options = {} +shortcutName = None +shortcutDir = None +bdist_msi_options = None +src_files = [] +external_so_files = [] + +if sys.platform == 'win32': + base = 'Win32GUI' + name = 'Rare.exe' + shortcut_table = [ + ('DesktopShortcut', # Shortcut + 'DesktopFolder', # Directory + 'Rare', # Name + 'TARGETDIR', # Component + '[TARGETDIR]'+name, # Target + None, # Arguments + 'A gui for Legendary.', # Description + None, # Hotkey + None, # Icon + None, # IconIndex + None, # ShowCmd + 'TARGETDIR' # Working Directory + )] + msi_data = {"Shortcut": shortcut_table} + bdist_msi_options = {'data': msi_data, "all_users": True} + build_options["bdist_msi"] = bdist_msi_options +else: + name = 'Rare' + +src_files += [ + 'LICENSE', + 'README.md', + 'rare/styles/Logo.ico', +] + +# Dependencies are automatically detected, but it might need fine tuning. +build_exe_options["packages"] = python_packages +build_exe_options["include_files"] = src_files + external_so_files +build_exe_options["includes"] = python_modules +build_exe_options["excludes"] = ["setuptools", "tkinter", "pkg_resources"] + +# Set options +build_options["build_exe"] = build_exe_options + +setup(name = 'Rare', + version = __version__, + description = 'A gui for Legendary.', + options = build_options, + executables = [ + Executable('rare/__main__.py', + targetName=name, + icon='rare/styles/Logo.ico', + base=base, + shortcutName=shortcutName, + shortcutDir=shortcutDir, + ), + ], +) diff --git a/setup.py b/setup.py index 3833d298..87eb2725 100644 --- a/setup.py +++ b/setup.py @@ -1,74 +1,39 @@ -import sys +import setuptools -from cx_Freeze import setup, Executable +from rare import __version__ as version -import rare +with open("README.md", "r") as fh: + long_description = fh.read() -opts = { - 'packages': [ - 'requests', - 'PIL', - 'qtawesome', - 'notifypy', - 'psutil', - 'pypresence', +setuptools.setup( + name="Rare", + version=version, + author="Dummerle", + license="GPL-3", + description="A gui for Legendary", + long_description=long_description, + long_description_content_type="text/markdown", + include_package_data=True, + url="https://github.com/Dummerle/Rare", + packages=setuptools.find_packages(), + classifiers=[ + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', + "Operating System :: OS Independent" ], - 'zip_include_packages': [ - 'PyQt5.QtCore', - 'PyQt5.QtGui', - 'PyQt5.QtWidgets', - ], - 'include_files': [ - 'LICENSE', - 'README.MD', - 'rare/styles/Logo.ico', - ], -} - -setup_options = {'build_exe': opts} -base = None -name = None -shortcutName = None -shortcutDir = None -bdist_msi_options = None - -if sys.platform == 'win32': - base = 'Win32GUI' - name = 'Rare.exe' - shortcut_table = [ - ('DesktopShortcut', # Shortcut - 'DesktopFolder', # Directory - 'Rare', # Name - 'TARGETDIR', # Component - '[TARGETDIR]'+name, # Target - None, # Arguments - 'A gui for Legendary.', # Description - None, # Hotkey - None, # Icon - None, # IconIndex - None, # ShowCmd - 'TARGETDIR' # Working Directory - )] - msi_data = {"Shortcut": shortcut_table} - bdist_msi_options = {'data': msi_data} - setup_options.update({"bdist_msi": bdist_msi_options}) -else: - name = 'Rare' - -setup(name = 'Rare', - version = rare.__version__, - description = 'A gui for Legendary.', - options = setup_options, - setup_requires=[ - 'cx_Freeze', - ], - executables = [ - Executable('rare/__main__.py', - targetName=name, - icon='rare/styles/Logo.ico', - base=base, - shortcutName=shortcutName, - shortcutDir=shortcutDir, - ), + python_requires=">=3.8", + entry_points=dict(console_scripts=["rare=rare.__main__:main"]), + install_requires=[ + "requests<3.0", + "pillow", + "setuptools", + "wheel", + "PyQt5", + "QtAwesome", + "notify-py", + "psutil", + "pypresence" ], ) From 378b5193e809a0ceaab154c6fe1de2677baf8180 Mon Sep 17 00:00:00 2001 From: ChemicalXandco <32775248+ChemicalXandco@users.noreply.github.com> Date: Sun, 9 May 2021 15:05:43 +0100 Subject: [PATCH 04/21] add support for game shortcuts on windows --- README.md | 6 +++--- freeze.py | 10 +--------- rare/utils/utils.py | 27 +++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6edd8c6e..dc275b4d 100644 --- a/README.md +++ b/README.md @@ -42,12 +42,12 @@ Install via `pip`. ## Run from source 1. Run `pip install -r requirements.txt` to get dependencies. If you use `pacman` you can run `sudo pacman --needed -S python-wheel python-setuptools python-pyqt5 python-qtawesome python-requests python-pillow` -2. For unix operating systems run `sh start.sh`. For windows run `set PYTHONPATH=%CD% && python Rare` +2. For unix operating systems run `sh start.sh`. For windows run `set PYTHONPATH=%CD% && python rare` ## Why Rare? -- Rare uses much less RAM than electron based apps such as [HeroicGL](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) and EpicGL which allows the games to run better. -- Rare supports all major platforms (Windows, Linux, MacOS) unlike the alternatives. +- Rare only uses ~50MB of RAM which is much less than the electron based [HeroicGamesLauncher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) uses. +- Rare supports all major platforms (Windows, Linux, macOS) unlike the alternatives. ## Features diff --git a/freeze.py b/freeze.py index 05ce3716..10fe3052 100644 --- a/freeze.py +++ b/freeze.py @@ -5,15 +5,7 @@ from cx_Freeze import setup, Executable from rare import __version__ # Packages to include -python_packages = [ - "PyQt5", - 'requests', - 'PIL', - 'qtawesome', - 'notifypy', - 'psutil', - 'pypresence', -] +python_packages = [] # Modules to include python_modules = [] diff --git a/rare/utils/utils.py b/rare/utils/utils.py index eb8443bb..8f365bbc 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -2,12 +2,17 @@ import json import os import shutil import sys +import sysconfig from logging import getLogger import requests from PIL import Image, UnidentifiedImageError from PyQt5.QtCore import pyqtSignal, QLocale, QSettings +# Windows +if os.name == "nt": + from win32com.client import Dispatch + from rare import lang_path, __version__, style_path from custom_legendary.core import LegendaryCore @@ -164,3 +169,25 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): "StartupWMClass=rare-game\n" ) os.chmod(os.path.expanduser(f"~/Desktop/{igame.title}.desktop"), 0o755) + + # Windows + elif os.name == "nt": + # Target of shortcut + target = sys.argv[0] + + # Name of link file + linkName = igame.title + '.lnk' + + desktopFolder = os.path.expanduser('~/Desktop/') + + # Path to location of link file + pathLink = os.path.join(desktopFolder, linkName) + + # Add shortcut + shell = Dispatch('WScript.Shell') + shortcut = shell.CreateShortCut(pathLink) + shortcut.Targetpath = target + shortcut.Arguments = f'launch {app_name}' + shortcut.WorkingDirectory = os.getcwd() + shortcut.IconLocation = os.path.join(os.getcwd(), 'Logo.ico') + shortcut.save() From bfc8b1f8f54012a3469e0ed33924567d682f1348 Mon Sep 17 00:00:00 2001 From: ChemicalXandco <32775248+ChemicalXandco@users.noreply.github.com> Date: Sun, 9 May 2021 15:25:27 +0100 Subject: [PATCH 05/21] add pywin32 to requirements.txt --- rare/utils/utils.py | 1 - requirements.txt | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rare/utils/utils.py b/rare/utils/utils.py index cf911e5a..afe92281 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -2,7 +2,6 @@ import json import os import shutil import sys -import sysconfig from logging import getLogger import requests diff --git a/requirements.txt b/requirements.txt index 1dfa98c3..67376a60 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,4 +4,5 @@ PyQt5 QtAwesome notify-py psutil -pypresence \ No newline at end of file +pypresence +pywin32; platform_system == "Windows" From 264860049e35a1ee164cff3c60036251b43b9f71 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Tue, 11 May 2021 16:24:02 +0200 Subject: [PATCH 06/21] Fixed Windows Desktop link --- rare/__main__.py | 1 + rare/utils/utils.py | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/rare/__main__.py b/rare/__main__.py index a88e67ea..9ff86e54 100644 --- a/rare/__main__.py +++ b/rare/__main__.py @@ -1,4 +1,5 @@ import os +import sys from argparse import ArgumentParser from rare import __version__ diff --git a/rare/utils/utils.py b/rare/utils/utils.py index afe92281..49666893 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -179,15 +179,22 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): # Windows elif os.name == "nt": # Target of shortcut - target = sys.argv[0] + if type_of_link == "desktop": + target_folder = os.path.expanduser('~/Desktop/') + elif type_of_link == "start_menu": + target_folder = os.path.expandvars("%appdata%/Microsoft/Windows/Start Menu") + else: + logger.warning("No valid type of link") + return + target = os.path.abspath(sys.argv[0]) # Name of link file linkName = igame.title + '.lnk' - desktopFolder = os.path.expanduser('~/Desktop/') + image_path = QSettings("Rare", "Rare").value("img_dir", os.path.expanduser("~/.cache/rare/images"), str) # Path to location of link file - pathLink = os.path.join(desktopFolder, linkName) + pathLink = os.path.join(target_folder, linkName) # Add shortcut shell = Dispatch('WScript.Shell') @@ -195,5 +202,9 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): shortcut.Targetpath = target shortcut.Arguments = f'launch {app_name}' shortcut.WorkingDirectory = os.getcwd() - shortcut.IconLocation = os.path.join(os.getcwd(), 'Logo.ico') + + if os.path.exists(os.path.join(image_path, f"{igame.app_name}/Thumbnail.png")): + shortcut.IconLocation = os.path.join(image_path, f"{igame.app_name}/Thumbnail.png") + else: + shortcut.IconLocation = os.path.join(image_path, f"{igame.app_name}/DieselGameBoxTall.png") shortcut.save() From f2922bc677b15b54e9f8f10d465a29c4c526258b Mon Sep 17 00:00:00 2001 From: Dummerle Date: Tue, 11 May 2021 16:39:02 +0200 Subject: [PATCH 07/21] Fixed Windows Desktop link: Icons --- rare/utils/utils.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/rare/utils/utils.py b/rare/utils/utils.py index 49666893..d0fc0ee9 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -152,10 +152,10 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): os.path.join(QSettings('Rare', 'Rare').value('img_dir', os.path.expanduser('~/.cache/rare/images'), str), igame.app_name, 'Thumbnail.png')): icon = os.path.join(QSettings('Rare', 'Rare').value('img_dir', os.path.expanduser('~/.cache/rare/images'), str), - igame.app_name, 'Thumbnail.png') + igame.app_name, 'Thumbnail') else: icon = os.path.join(QSettings('Rare', 'Rare').value('img_dir', os.path.expanduser('~/.cache/rare/images'), str), - igame.app_name, 'DieselGameBoxTall.png') + igame.app_name, 'DieselGameBoxTall') # Linux if os.name == "posix": if type_of_link == "desktop": @@ -169,7 +169,7 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): desktop_file.write("[Desktop Entry]\n" f"Name={igame.title}\n" f"Type=Application\n" - f"Icon={icon}\n" + f"Icon={icon}.png\n" f"Exec=rare launch {app_name}\n" "Terminal=false\n" "StartupWMClass=rare-game\n" @@ -191,8 +191,6 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): # Name of link file linkName = igame.title + '.lnk' - image_path = QSettings("Rare", "Rare").value("img_dir", os.path.expanduser("~/.cache/rare/images"), str) - # Path to location of link file pathLink = os.path.join(target_folder, linkName) @@ -203,8 +201,10 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): shortcut.Arguments = f'launch {app_name}' shortcut.WorkingDirectory = os.getcwd() - if os.path.exists(os.path.join(image_path, f"{igame.app_name}/Thumbnail.png")): - shortcut.IconLocation = os.path.join(image_path, f"{igame.app_name}/Thumbnail.png") - else: - shortcut.IconLocation = os.path.join(image_path, f"{igame.app_name}/DieselGameBoxTall.png") + # Icon + if not os.path.exists(icon+".ico"): + img = Image.open(icon+".png") + img.save(icon+".ico") + logger.info("Create Icon") + shortcut.IconLocation = os.path.join(icon) shortcut.save() From 4378df27914247521a02daeea3fd0a08cb90923e Mon Sep 17 00:00:00 2001 From: Dummerle Date: Tue, 11 May 2021 16:42:41 +0200 Subject: [PATCH 08/21] Fixed Windows Desktop link: Icons --- rare/utils/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rare/utils/utils.py b/rare/utils/utils.py index d0fc0ee9..303d260d 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -206,5 +206,5 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): img = Image.open(icon+".png") img.save(icon+".ico") logger.info("Create Icon") - shortcut.IconLocation = os.path.join(icon) + shortcut.IconLocation = os.path.join(icon+ ".ico") shortcut.save() From b4d10cc77e78d2e95974ec0957ebf0474d6c1b55 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Wed, 12 May 2021 09:19:50 +0200 Subject: [PATCH 09/21] Auto sync saves on startup if enabled --- .../tabs/cloud_saves/sync_widget.py | 7 ++- rare/languages/de.ts | 47 ++++++++++--------- rare/utils/utils.py | 21 +++++---- 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/rare/components/tabs/cloud_saves/sync_widget.py b/rare/components/tabs/cloud_saves/sync_widget.py index 46ccdd5a..889a7ee3 100644 --- a/rare/components/tabs/cloud_saves/sync_widget.py +++ b/rare/components/tabs/cloud_saves/sync_widget.py @@ -1,7 +1,7 @@ import os from logging import getLogger -from PyQt5.QtCore import QThread, pyqtSignal, Qt +from PyQt5.QtCore import QThread, pyqtSignal, Qt, QSettings from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QLabel, QGroupBox from custom_legendary.core import LegendaryCore @@ -167,6 +167,11 @@ class SyncWidget(QGroupBox): self.layout.addStretch(1) self.setLayout(self.layout) + if self.res == SaveGameStatus.REMOTE_NEWER: + settings = QSettings() + if settings.value(f"{igame.app_name}/auto_sync_cloud", False, bool): + self.download() + def change_path(self): path = PathInputDialog("Select directory", "Select savepath. Warning: Do not change if you are not sure", self.igame.save_path).get_path() diff --git a/rare/languages/de.ts b/rare/languages/de.ts index 0c7262a6..862212dd 100644 --- a/rare/languages/de.ts +++ b/rare/languages/de.ts @@ -830,7 +830,7 @@ Installationsgröße: {} GB MainWindow - + There is a download active. Do you really want to exit app? Ein Download läuft noch. Möchtest du die App wirklich beenden? @@ -938,85 +938,90 @@ Installationsgröße: {} GB RareSettings - + Rare settings Rare Einstellungen - + Save Speichern - + Image Directory Ordner für Bilder - + Language Sprache - + Restart Application to activate changes Starte die App neu um die Änderungen zu aktivieren - + Confirm launch of game Start des Spiels bestätigen - + Exit to System Tray Icon Beim verlassen auf das System Tray Icon minimieren - + Hide to System Tray Icon In das System Tray Icon minimieren - + Auto sync with cloud Speicherstände automatisch mit der Cloud synchronisieren - + Sync with cloud Automatisch Synchronisieren - + Save size Größe Speichern - + Save size of window after restart Die Fenstergröße nach dem Beenden speichern - + Automatically update Games on startup Spiele automatisch updaten - + Auto updates Automatische Updates - + Show Notifications after Downloads Benachrichtigung nach Abschluss des Downloads anzeigen - + Show notification Benachrichtigung anzeigen + + + Open Log directory + + SyncSaves @@ -1134,22 +1139,22 @@ Installationsgröße: {} GB Pfad ändern - + Uploading... Hochladen... - + Upload finished Hochladen abgeschlossen - + Downloading... Runterladen... - + Download finished Download abgeschlossen diff --git a/rare/utils/utils.py b/rare/utils/utils.py index 303d260d..62177aec 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -11,14 +11,15 @@ from PyQt5.QtCore import pyqtSignal, QLocale, QSettings # Windows if os.name == "nt": from win32com.client import Dispatch +# Mac not supported -from rare import lang_path, __version__, style_path + +from rare import lang_path from custom_legendary.core import LegendaryCore logger = getLogger("Utils") s = QSettings("Rare", "Rare") IMAGE_DIR = s.value("img_dir", os.path.expanduser("~/.cache/rare/images"), type=str) -logger.info("IMAGE DIRECTORY: " + IMAGE_DIR) def download_images(signal: pyqtSignal, core: LegendaryCore): @@ -38,7 +39,7 @@ def download_images(signal: pyqtSignal, core: LegendaryCore): except json.decoder.JSONDecodeError: shutil.rmtree(f"{IMAGE_DIR}/{game.app_name}") download_image(game) - signal.emit(i/len(game_list)*100) + signal.emit(i / len(game_list) * 100) def download_image(game, force=False): @@ -69,7 +70,7 @@ def download_image(game, force=False): f.write(requests.get(url).content) try: img = Image.open(f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png") - img = img.resize((200, int(200*4/3))) + img = img.resize((200, int(200 * 4 / 3))) img.save(f"{IMAGE_DIR}/{game.app_name}/{image['type']}.png") except UnidentifiedImageError as e: logger.warning(e) @@ -84,7 +85,7 @@ def download_image(game, force=False): bg = Image.open(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxTall.png") uninstalledArt = bg.convert('L') - uninstalledArt = uninstalledArt.resize((200, int(200*4/3))) + uninstalledArt = uninstalledArt.resize((200, int(200 * 4 / 3))) uninstalledArt.save(f'{IMAGE_DIR}/{game.app_name}/UninstalledArt.png') elif os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png"): bg: Image.Image = Image.open(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo.png") @@ -202,9 +203,11 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): shortcut.WorkingDirectory = os.getcwd() # Icon - if not os.path.exists(icon+".ico"): - img = Image.open(icon+".png") - img.save(icon+".ico") + if not os.path.exists(icon + ".ico"): + img = Image.open(icon + ".png") + img.save(icon + ".ico") logger.info("Create Icon") - shortcut.IconLocation = os.path.join(icon+ ".ico") + shortcut.IconLocation = os.path.join(icon + ".ico") + + # Save shortcut shortcut.save() From 80eec00ccdc9423e38d4a73f62418faccca3649e Mon Sep 17 00:00:00 2001 From: Dummerle Date: Wed, 12 May 2021 09:35:50 +0200 Subject: [PATCH 10/21] Ready for new Release --- README.md | 6 ++++-- rare/__init__.py | 2 +- rare/__main__.py | 1 - rare/app.py | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index e2a752c1..ff0486ab 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,9 @@ Install via `pip`. ## Why Rare? - Rare only uses ~50MB of RAM which is much less than the electron based [HeroicGamesLauncher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) uses. -- Rare supports all major platforms (Windows, Linux, macOS) unlike the alternatives. +- Rare supports all major platforms (Windows, Linux, Mac) unlike the alternatives. + +**Note** Mac should work too, but I have no Mac and I can't test it. ## Features @@ -60,7 +62,7 @@ Install via `pip`. ## Planned Features - More Translations (Need help) - More Information about Games -More planned features are in projects +More planned features are in [projects](https://github.com/Dummerle/Rare/projects/1) ## Contributing There are more options to contribute. diff --git a/rare/__init__.py b/rare/__init__.py index 4a55d0b2..800d9762 100644 --- a/rare/__init__.py +++ b/rare/__init__.py @@ -1,5 +1,5 @@ import os -__version__ = "1.3.0" +__version__ = "1.4.0" style_path = os.path.join(os.path.dirname(__file__), "styles/") lang_path = os.path.join(os.path.dirname(__file__), "languages/") diff --git a/rare/__main__.py b/rare/__main__.py index 9ff86e54..a88e67ea 100644 --- a/rare/__main__.py +++ b/rare/__main__.py @@ -1,5 +1,4 @@ import os -import sys from argparse import ArgumentParser from rare import __version__ diff --git a/rare/app.py b/rare/app.py index a58d3bfc..5ab20159 100644 --- a/rare/app.py +++ b/rare/app.py @@ -1,7 +1,6 @@ import configparser import logging import os -import shutil import sys import time From deef7dede58aedb596626d8b0635756b3bd46557 Mon Sep 17 00:00:00 2001 From: Dummerle <44114474+Dummerle@users.noreply.github.com> Date: Wed, 12 May 2021 10:07:37 +0200 Subject: [PATCH 11/21] Update release.yml --- .github/workflows/release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2262e30b..643f779e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -59,11 +59,13 @@ jobs: pip3 install -r requirements.txt - name: Build run: python3 freeze.py bdist_msi + - name: Copy File + run: cp dist/*.msi Rare.msi - name: Upload files to GitHub uses: svenstaro/upload-release-action@2.2.1 with: repo_token: ${{ secrets.GITHUB_TOKEN }} - file: dist/Rare*.msi + file: Rare.msi asset_name: Rare.msi tag: ${{ github.ref }} overwrite: true From d7c481bbafc87a6b917894eeec1a4162b71c5ef5 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Wed, 12 May 2021 10:27:23 +0200 Subject: [PATCH 12/21] Filter options for Games: Installed / offline --- rare/components/tabs/games/__init__.py | 34 ++++++++++++++++++------- rare/components/tabs/games/game_list.py | 19 ++++++++++---- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index f5283e01..cc65888c 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -1,5 +1,6 @@ -from PyQt5.QtCore import QSettings, QSize -from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QCheckBox, QLineEdit, QPushButton, QStackedLayout, QLabel +from PyQt5.QtCore import QSettings, QSize, pyqtSignal +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QStackedLayout, \ + QLabel, QComboBox from qtawesome import icon from rare.components.tabs.games.game_info import InfoTabs @@ -51,11 +52,10 @@ class Games(QWidget): self.game_list = GameList(core, self, offline) self.head_bar.search_bar.textChanged.connect( - lambda: self.game_list.filter(self.head_bar.search_bar.text())) + lambda: self.game_list.search(self.head_bar.search_bar.text())) + + self.head_bar.filter_changed_signal.connect(self.game_list.filter) - self.head_bar.installed_only.stateChanged.connect(lambda: - self.game_list.installed_only( - self.head_bar.installed_only.isChecked())) self.layout.addWidget(self.head_bar) self.layout.addWidget(self.game_list) # self.layout.addStretch(1) @@ -70,14 +70,22 @@ class Games(QWidget): class GameListHeadBar(QWidget): + filter_changed_signal = pyqtSignal(str) + def __init__(self, parent): super(GameListHeadBar, self).__init__(parent=parent) self.layout = QHBoxLayout() - self.installed_only = QCheckBox(self.tr("Installed only")) + # self.installed_only = QCheckBox(self.tr("Installed only")) self.settings = QSettings() - self.installed_only.setChecked(self.settings.value("installed_only", False, bool)) - self.layout.addWidget(self.installed_only) + # self.installed_only.setChecked(self.settings.value("installed_only", False, bool)) + # self.layout.addWidget(self.installed_only) + self.filter = QComboBox() + self.filter.addItems([self.tr("All"), + self.tr("Installed only"), + self.tr("Offline Games")]) + self.filter.currentIndexChanged.connect(self.filter_changed) + self.layout.addWidget(self.filter) self.layout.addStretch(1) self.import_game = QPushButton(icon("mdi.import", color="white"), self.tr("Import Game")) @@ -107,3 +115,11 @@ class GameListHeadBar(QWidget): self.layout.addWidget(self.refresh_list) self.setLayout(self.layout) + + def filter_changed(self, i): + if i == 0: + self.filter_changed_signal.emit("") + elif i == 1: + self.filter_changed_signal.emit("installed") + elif i == 2: + self.filter_changed_signal.emit("offline") diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py index 4217c180..8203407c 100644 --- a/rare/components/tabs/games/game_list.py +++ b/rare/components/tabs/games/game_list.py @@ -165,7 +165,7 @@ class GameList(QStackedWidget): self.setCurrentIndex(1) if self.settings.value("installed_only", False, bool): - self.installed_only(True) + self.filter(True) def is_finished(self): if psutil.pid_exists(self.active_game[1]): @@ -223,7 +223,7 @@ class GameList(QStackedWidget): self.widgets[app_name][1].launch_button.setDisabled(True) self.widgets[app_name][1].launch_button.setText(self.tr("Game running")) - def filter(self, text: str): + def search(self, text: str): for t in self.widgets.values(): for w in t: if text.lower() in w.game.app_title.lower() + w.game.app_name.lower(): @@ -231,11 +231,20 @@ class GameList(QStackedWidget): else: w.setVisible(False) - def installed_only(self, i_o: bool): + def filter(self, filter="installed"): for t in self.widgets.values(): for w in t: - w.setVisible(not (not self.core.is_installed(w.game.app_name) and i_o)) - self.settings.setValue("installed_only", i_o) + if filter == "installed": + w.setVisible(self.core.is_installed(w.game.app_name)) + elif filter == "offline": + if self.core.is_installed(w.game.app_name): + w.setVisible(w.igame.can_run_offline) + else: + w.setVisible(False) + else: + # All visible + w.setVisible(True) + self.settings.setValue("filter", filter) def update_list(self, icon_view=True): self.settings.setValue("icon_view", icon_view) From 97704851aca4feef70052ea02a63f2f9d8462b5e Mon Sep 17 00:00:00 2001 From: Dummerle Date: Wed, 12 May 2021 11:06:31 +0200 Subject: [PATCH 13/21] Filter options for Games: 32 Bit --- rare/components/tabs/games/__init__.py | 10 +++------- rare/components/tabs/games/game_list.py | 10 ++++++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index cc65888c..b7ff8586 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -83,7 +83,8 @@ class GameListHeadBar(QWidget): self.filter = QComboBox() self.filter.addItems([self.tr("All"), self.tr("Installed only"), - self.tr("Offline Games")]) + self.tr("Offline Games"), + self.tr("32 Bit Games")]) self.filter.currentIndexChanged.connect(self.filter_changed) self.layout.addWidget(self.filter) self.layout.addStretch(1) @@ -117,9 +118,4 @@ class GameListHeadBar(QWidget): self.setLayout(self.layout) def filter_changed(self, i): - if i == 0: - self.filter_changed_signal.emit("") - elif i == 1: - self.filter_changed_signal.emit("installed") - elif i == 2: - self.filter_changed_signal.emit("offline") + self.filter_changed_signal.emit(["", "installed", "offline", "32bit"][i]) diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py index 8203407c..c87d72d6 100644 --- a/rare/components/tabs/games/game_list.py +++ b/rare/components/tabs/games/game_list.py @@ -66,6 +66,8 @@ class GameList(QStackedWidget): self.updates = [] self.widgets = {} + self.bit32 = [i.app_name for i in self.core.get_game_and_dlc_list(True, "Win32")[0]] + self.mac_games = [i.app_name for i in self.core.get_game_and_dlc_list(True, "Mac")[0]] self.installed = sorted(self.core.get_installed_list(), key=lambda x: x.title) # Installed Games @@ -164,8 +166,8 @@ class GameList(QStackedWidget): if not icon_view: self.setCurrentIndex(1) - if self.settings.value("installed_only", False, bool): - self.filter(True) + if filter_games := self.settings.value("filter", "", str): + self.filter(filter_games) def is_finished(self): if psutil.pid_exists(self.active_game[1]): @@ -241,6 +243,10 @@ class GameList(QStackedWidget): w.setVisible(w.igame.can_run_offline) else: w.setVisible(False) + elif filter == "32bit": + w.setVisible(w.game.app_name in self.bit32) + elif filter == "mac": + w.setVisible(w.game.app_name in self.mac_games) else: # All visible w.setVisible(True) From 5a6a8fc1e7a3a0381ff3c386a4dc1f65349f3d21 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Wed, 12 May 2021 11:45:10 +0200 Subject: [PATCH 14/21] Remove Windows Desktop files on uninstall --- rare/utils/legendary_utils.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rare/utils/legendary_utils.py b/rare/utils/legendary_utils.py index 958a0a2e..dac21139 100644 --- a/rare/utils/legendary_utils.py +++ b/rare/utils/legendary_utils.py @@ -61,6 +61,12 @@ def uninstall(app_name: str, core: LegendaryCore, options=None): if os.path.exists(os.path.expanduser(f"~/.local/share/applications/{igame.title}.desktop")): os.remove(os.path.expanduser(f"~/.local/share/applications/{igame.title}.desktop")) + elif os.name == "nt": + if os.path.exists(os.path.expanduser(f"~/Desktop/{igame.title.split(':')[0]}.lnk")): + os.remove(os.path.expanduser(f"~/Desktop/{igame.title.split(':')[0]}.lnk")) + elif os.path.exists(os.path.expandvars(f"%appdata%/Microsoft/Windows/Start Menu/{igame.title.split(':')[0]}.lnk")): + os.remove(os.path.expandvars(f"%appdata%/Microsoft/Windows/Start Menu/{igame.title.split(':')[0]}.lnk")) + try: # Remove DLC first so directory is empty when game uninstall runs dlcs = core.get_dlc_for_game(app_name) From 5db828ab1dd780823d8e935d043318dbf01a77a1 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Wed, 12 May 2021 23:06:44 +0200 Subject: [PATCH 15/21] Show changed version in update widget --- rare/components/tabs/downloads/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/rare/components/tabs/downloads/__init__.py b/rare/components/tabs/downloads/__init__.py index 6cb7ad29..adec5cee 100644 --- a/rare/components/tabs/downloads/__init__.py +++ b/rare/components/tabs/downloads/__init__.py @@ -297,6 +297,7 @@ class UpdateWidget(QWidget): self.update_button = QPushButton(self.tr("Update Game")) self.update_button.clicked.connect(self.update_game) self.layout.addWidget(self.update_button) + self.layout.addWidget(QLabel(self.tr("Version: ") + self.game.version + " -> " + self.core.get_asset(self.game.app_name, True).build_version)) self.setLayout(self.layout) From 9a121e0bee32eb3ed3892e505c281d33f53a6a01 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Mon, 17 May 2021 10:03:52 +0200 Subject: [PATCH 16/21] Add pywin32 in setup.py --- setup.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/setup.py b/setup.py index 87eb2725..456839c3 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,5 @@ +import os + import setuptools from rare import __version__ as version @@ -5,6 +7,21 @@ from rare import __version__ as version with open("README.md", "r") as fh: long_description = fh.read() +requirements = [ + "requests<3.0", + "pillow", + "setuptools", + "wheel", + "PyQt5", + "QtAwesome", + "notify-py", + "psutil", + "pypresence" + ] + +if os.name == "nt": + requirements.append("pywin32") + setuptools.setup( name="Rare", version=version, @@ -25,15 +42,5 @@ setuptools.setup( ], python_requires=">=3.8", entry_points=dict(console_scripts=["rare=rare.__main__:main"]), - install_requires=[ - "requests<3.0", - "pillow", - "setuptools", - "wheel", - "PyQt5", - "QtAwesome", - "notify-py", - "psutil", - "pypresence" - ], + install_requires=requirements, ) From 89d30b489932c523cb4c28a19f4fd0e1ac91bfac Mon Sep 17 00:00:00 2001 From: Dummerle Date: Mon, 17 May 2021 11:38:30 +0200 Subject: [PATCH 17/21] Fix bugs with windows filenames --- rare/app.py | 2 +- rare/utils/utils.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/rare/app.py b/rare/app.py index 5ab20159..683d5641 100644 --- a/rare/app.py +++ b/rare/app.py @@ -15,7 +15,7 @@ from rare.components.main_window import MainWindow from rare.components.tray_icon import TrayIcon from rare.utils.utils import get_lang -start_time = time.strftime('%y-%m-%d--%H:%M') # year-month-day-hour-minute +start_time = time.strftime('%y-%m-%d--%H-%M') # year-month-day-hour-minute file_name = os.path.expanduser(f"~/.cache/rare/logs/Rare_{start_time}.log") if not os.path.exists(os.path.dirname(file_name)): os.makedirs(os.path.dirname(file_name)) diff --git a/rare/utils/utils.py b/rare/utils/utils.py index 62177aec..e1c984a4 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -190,7 +190,11 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): target = os.path.abspath(sys.argv[0]) # Name of link file - linkName = igame.title + '.lnk' + linkName = igame.title + for c in r'<>?":|\/*': + linkName.replace(c, "") + + linkName = linkName.strip() + '.lnk' # Path to location of link file pathLink = os.path.join(target_folder, linkName) From 83f1061e16f38f8076c2cd0622d22ec7ae4a06b8 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Mon, 17 May 2021 20:22:29 +0200 Subject: [PATCH 18/21] Optimize Library reload --- rare/__init__.py | 2 +- rare/components/tab_widget.py | 22 +- rare/components/tabs/downloads/__init__.py | 22 +- rare/components/tabs/games/__init__.py | 4 +- .../tabs/games/game_info/__init__.py | 11 +- rare/components/tabs/games/game_list.py | 292 ++++++++++++------ .../game_widgets/base_installed_widget.py | 2 +- .../game_widgets/installed_icon_widget.py | 2 +- rare/components/tabs/games/import_widget.py | 6 +- 9 files changed, 250 insertions(+), 113 deletions(-) diff --git a/rare/__init__.py b/rare/__init__.py index 800d9762..e826caf3 100644 --- a/rare/__init__.py +++ b/rare/__init__.py @@ -1,5 +1,5 @@ import os -__version__ = "1.4.0" +__version__ = "1.4.1" style_path = os.path.join(os.path.dirname(__file__), "styles/") lang_path = os.path.join(os.path.dirname(__file__), "languages/") diff --git a/rare/components/tab_widget.py b/rare/components/tab_widget.py index 5e04be84..1dd0ede6 100644 --- a/rare/components/tab_widget.py +++ b/rare/components/tab_widget.py @@ -3,8 +3,10 @@ import webbrowser from PyQt5.QtCore import QSize, pyqtSignal from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction from qtawesome import icon +from rare.utils import legendary_utils from custom_legendary.core import LegendaryCore +from rare.components.dialogs.uninstall_dialog import UninstallDialog from rare.components.tab_utils import TabBar, TabButtonWidget from rare.components.tabs.account import MiniWidget from rare.components.tabs.cloud_saves import SyncSaves @@ -63,6 +65,9 @@ class TabWidget(QTabWidget): # open download tab self.games_tab.default_widget.game_list.update_game.connect(lambda: self.setCurrentIndex(1)) + # uninstall + self.games_tab.game_info.info.uninstall_game.connect(self.uninstall_game) + if not offline: # Download finished self.downloadTab.finished.connect(self.dl_finished) @@ -90,10 +95,23 @@ class TabWidget(QTabWidget): if self.core.get_game(app_name).supports_cloud_saves: self.cloud_saves.sync_game(app_name, True) + def uninstall_game(self, app_name): + game = self.core.get_game(app_name) + infos = UninstallDialog(game).get_information() + if infos == 0: + return + legendary_utils.uninstall(game.app_name, self.core, infos) + if app_name in self.downloadTab.update_widgets.keys(): + self.downloadTab.update_layout.removeWidget(self.downloadTab.update_widgets[app_name]) + self.downloadTab.update_widgets.pop(app_name) + downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) + self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) + # Update gamelist and set text of Downlaods to "Downloads" + def dl_finished(self, update_list): - if update_list: - self.games_tab.default_widget.game_list.update_list() + if update_list[0]: + self.games_tab.default_widget.game_list.update_list(update_list[1]) downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) diff --git a/rare/components/tabs/downloads/__init__.py b/rare/components/tabs/downloads/__init__.py index adec5cee..f7a9ff8d 100644 --- a/rare/components/tabs/downloads/__init__.py +++ b/rare/components/tabs/downloads/__init__.py @@ -20,7 +20,7 @@ logger = getLogger("Download") class DownloadTab(QWidget): - finished = pyqtSignal(bool) + finished = pyqtSignal(tuple) thread: QThread dl_queue = [] @@ -135,7 +135,7 @@ class DownloadTab(QWidget): # Information if not from_update: if not InstallInfoDialog(dl_size=analysis.dl_size, install_size=analysis.install_size).get_accept(): - self.finished.emit(False) + self.finished.emit(False, None) return if self.active_game is None: @@ -214,23 +214,25 @@ class DownloadTab(QWidget): # QMessageBox.information(self, "Info", "Download finished") logger.info("Download finished: " + self.active_game.app_title) + app_name = self.active_game.app_name + self.active_game = None + if self.dl_queue: - if self.dl_queue[0][1] == self.active_game.app_name: + if self.dl_queue[0][1] == app_name: self.dl_queue.pop(0) self.queue_widget.update_queue(self.dl_queue) - if self.active_game.app_name in self.update_widgets.keys(): - self.update_widgets[self.active_game.app_name].setVisible(False) - self.update_widgets.pop(self.active_game.app_name) + if app_name in self.update_widgets.keys(): + self.update_widgets[app_name].setVisible(False) + self.update_widgets.pop(app_name) if len(self.update_widgets) == 0: self.update_text.setVisible(True) - self.active_game = None - for i in self.update_widgets.values(): i.update_button.setDisabled(False) - self.finished.emit(True) + self.finished.emit((True, app_name)) + self.reset_infos() if len(self.dl_queue) != 0: @@ -244,7 +246,7 @@ class DownloadTab(QWidget): elif text == "stop": self.reset_infos() self.active_game = None - self.finished.emit(False) + self.finished.emit((False, None)) if self.dl_queue: self.start_installation(*self.dl_queue[0]) diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index b7ff8586..6760a654 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -31,8 +31,8 @@ class GameTab(QWidget): self.import_widget.update_list.connect(self.update_list) self.setLayout(self.layout) - def update_list(self): - self.default_widget.game_list.update_list(self.default_widget.head_bar.view.isChecked()) + def update_list(self, app_name=None): + self.default_widget.game_list.update_list(app_name) self.layout.setCurrentIndex(0) def show_info(self, app_name): diff --git a/rare/components/tabs/games/game_info/__init__.py b/rare/components/tabs/games/game_info/__init__.py index 71220ef2..f5ef8c30 100644 --- a/rare/components/tabs/games/game_info/__init__.py +++ b/rare/components/tabs/games/game_info/__init__.py @@ -58,7 +58,8 @@ class InfoTabs(QTabWidget): class GameInfo(QScrollArea): igame: InstalledGame game: Game - update_list = pyqtSignal() + uninstall_game = pyqtSignal(str) + update_list = pyqtSignal(str) verify_game = pyqtSignal(str) verify_threads = {} @@ -115,12 +116,8 @@ class GameInfo(QScrollArea): self.setWidget(self.widget) def uninstall(self): - infos = UninstallDialog(self.game).get_information() - if infos == 0: - print("Cancel Uninstall") - return - legendary_utils.uninstall(self.game.app_name, self.core, infos) - self.update_list.emit() + self.uninstall_game.emit(self.game.app_name) + self.update_list.emit(self.game.app_name) def repair(self): repair_file = os.path.join(self.core.lgd.get_tmp_path(), f'{self.game.app_name}.repair') diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py index c87d72d6..6455b4d5 100644 --- a/rare/components/tabs/games/game_list.py +++ b/rare/components/tabs/games/game_list.py @@ -1,12 +1,14 @@ import os from logging import getLogger +import gi import psutil from PyQt5.QtCore import Qt, pyqtSignal, QSettings, QTimer from PyQt5.QtGui import QPixmap -from PyQt5.QtWidgets import * +from PyQt5.QtWidgets import QScrollArea, QWidget, QLabel, QVBoxLayout, QStackedWidget from custom_legendary.core import LegendaryCore +from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget from rare.components.tabs.games.game_widgets.installed_icon_widget import GameWidgetInstalled from rare.components.tabs.games.game_widgets.installed_list_widget import InstalledListWidget from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled @@ -62,7 +64,7 @@ class GameList(QStackedWidget): self.list_layout = QVBoxLayout() self.list_layout.addWidget(QLabel(self.info_text)) - IMAGE_DIR = self.settings.value("img_dir", os.path.expanduser("~/.cache/rare/images"), str) + self.IMAGE_DIR = self.settings.value("img_dir", os.path.expanduser("~/.cache/rare/images"), str) self.updates = [] self.widgets = {} @@ -72,85 +74,24 @@ class GameList(QStackedWidget): # Installed Games for igame in self.installed: - if os.path.exists(f"{IMAGE_DIR}/{igame.app_name}/FinalArt.png"): - pixmap = QPixmap(f"{IMAGE_DIR}/{igame.app_name}/FinalArt.png") - elif os.path.exists(f"{IMAGE_DIR}/{igame.app_name}/DieselGameBoxTall.png"): - pixmap = QPixmap(f"{IMAGE_DIR}/{igame.app_name}/DieselGameBoxTall.png") - elif os.path.exists(f"{IMAGE_DIR}/{igame.app_name}/DieselGameBoxLogo.png"): - pixmap = QPixmap(f"{IMAGE_DIR}/{igame.app_name}/DieselGameBoxLogo.png") - else: - logger.warning(f"No Image found: {igame.title}") - pixmap = None - - if pixmap.isNull(): - logger.info(igame.title + " has a corrupt image.") - download_image(igame, force=True) - pixmap = QPixmap(f"{IMAGE_DIR}/{igame.app_name}/DieselGameBoxTall.png") - - icon_widget = GameWidgetInstalled(igame, self.core, pixmap, self.offline) + icon_widget, list_widget = self.add_installed_widget(igame) self.icon_layout.addWidget(icon_widget) - - list_widget = InstalledListWidget(igame, self.core, pixmap, self.offline) self.list_layout.addWidget(list_widget) - icon_widget.show_info.connect(self.show_game_info.emit) - list_widget.show_info.connect(self.show_game_info.emit) - - icon_widget.launch_signal.connect(self.launch) - icon_widget.finish_signal.connect(self.finished) - icon_widget.update_list.connect(lambda: self.update_list(self.settings.value("icon_view", True, bool))) - list_widget.launch_signal.connect(self.launch) - list_widget.finish_signal.connect(self.finished) - list_widget.update_list.connect(lambda: self.update_list(self.settings.value("icon_view", True, bool))) - - if icon_widget.update_available: - self.updates.append(igame) - - self.widgets[igame.app_name] = (icon_widget, list_widget) - active, pid = self.check_for_active_game(igame) - if active: - # Only one game works: Workaround for Satisfactory EA and Exp. - self.launch(igame.app_name) - icon_widget.game_running = True - list_widget.game_running = True - self.active_game = (igame.app_name, pid) - self.timer = QTimer() - self.timer.timeout.connect(self.is_finished) - self.timer.start(10000) - - self.uninstalled_games = [] + self.uninstalled_names = [] installed = [i.app_name for i in self.core.get_installed_list()] # get Uninstalled games games, self.dlcs = self.core.get_game_and_dlc_list() for game in sorted(games, key=lambda x: x.app_title): if not game.app_name in installed: - self.uninstalled_games.append(game) + self.uninstalled_names.append(game) # add uninstalled games - for igame in self.uninstalled_games: - if os.path.exists(f"{IMAGE_DIR}/{igame.app_name}/UninstalledArt.png"): - pixmap = QPixmap(f"{IMAGE_DIR}/{igame.app_name}/UninstalledArt.png") - - if pixmap.isNull(): - logger.info(igame.app_title + " has a corrupt image.") - download_image(igame, force=True) - pixmap = QPixmap(f"{IMAGE_DIR}/{igame.app_name}/UninstalledArt.png") - else: - logger.warning(f"No Image found: {igame.app_title}") - download_image(igame, force=True) - pixmap = QPixmap(f"{IMAGE_DIR}/{igame.app_name}/UninstalledArt.png") - - icon_widget = IconWidgetUninstalled(igame, self.core, pixmap) - icon_widget.install_game.connect(self.install) - - list_widget = ListWidgetUninstalled(self.core, igame, pixmap) - list_widget.install_game.connect(self.install) - + for game in self.uninstalled_names: + icon_widget, list_widget = self.add_uninstalled_widget(game) self.icon_layout.addWidget(icon_widget) self.list_layout.addWidget(list_widget) - self.widgets[igame.app_name] = (icon_widget, list_widget) - self.icon_parent_layout.addLayout(self.icon_layout) self.icon_parent_layout.addStretch(1) self.list_layout.addStretch(1) @@ -169,6 +110,79 @@ class GameList(QStackedWidget): if filter_games := self.settings.value("filter", "", str): self.filter(filter_games) + def add_uninstalled_widget(self, game): + if os.path.exists(f"{self.IMAGE_DIR}/{game.app_name}/UninstalledArt.png"): + pixmap = QPixmap(f"{self.IMAGE_DIR}/{game.app_name}/UninstalledArt.png") + + if pixmap.isNull(): + logger.info(game.app_title + " has a corrupt image.") + download_image(game, force=True) + pixmap = QPixmap(f"{self.IMAGE_DIR}/{game.app_name}/UninstalledArt.png") + else: + logger.warning(f"No Image found: {game.app_title}") + download_image(game, force=True) + pixmap = QPixmap(f"{self.IMAGE_DIR}/{game.app_name}/UninstalledArt.png") + + icon_widget = IconWidgetUninstalled(game, self.core, pixmap) + icon_widget.install_game.connect(self.install) + + list_widget = ListWidgetUninstalled(self.core, game, pixmap) + list_widget.install_game.connect(self.install) + + self.widgets[game.app_name] = (icon_widget, list_widget) + + return icon_widget, list_widget + + def add_installed_widget(self, igame): + if os.path.exists(f"{self.IMAGE_DIR}/{igame.app_name}/FinalArt.png"): + pixmap = QPixmap(f"{self.IMAGE_DIR}/{igame.app_name}/FinalArt.png") + elif os.path.exists(f"{self.IMAGE_DIR}/{igame.app_name}/DieselGameBoxTall.png"): + pixmap = QPixmap(f"{self.IMAGE_DIR}/{igame.app_name}/DieselGameBoxTall.png") + elif os.path.exists(f"{self.IMAGE_DIR}/{igame.app_name}/DieselGameBoxLogo.png"): + pixmap = QPixmap(f"{self.IMAGE_DIR}/{igame.app_name}/DieselGameBoxLogo.png") + else: + logger.warning(f"No Image found: {igame.title}") + pixmap = None + + if pixmap.isNull(): + logger.info(igame.title + " has a corrupt image.") + download_image(igame, force=True) + pixmap = QPixmap(f"{self.IMAGE_DIR}/{igame.app_name}/DieselGameBoxTall.png") + + icon_widget = GameWidgetInstalled(igame, self.core, pixmap, self.offline) + # self.icon_layout.addWidget(icon_widget) + + list_widget = InstalledListWidget(igame, self.core, pixmap, self.offline) + # self.list_layout.addWidget(list_widget) + + self.widgets[igame.app_name] = (icon_widget, list_widget) + + icon_widget.show_info.connect(self.show_game_info.emit) + list_widget.show_info.connect(self.show_game_info.emit) + + icon_widget.launch_signal.connect(self.launch) + icon_widget.finish_signal.connect(self.finished) + icon_widget.update_list.connect(self.update_list) + list_widget.launch_signal.connect(self.launch) + list_widget.finish_signal.connect(self.finished) + list_widget.update_list.connect(self.update_list) + + if icon_widget.update_available: + self.updates.append(igame) + + active, pid = self.check_for_active_game(igame) + if active: + # Only one game works: Workaround for Satisfactory EA and Exp. + self.launch(igame.app_name) + icon_widget.game_running = True + list_widget.game_running = True + self.active_game = (igame.app_name, pid) + self.timer = QTimer() + self.timer.timeout.connect(self.is_finished) + self.timer.start(10000) + + return icon_widget, list_widget + def is_finished(self): if psutil.pid_exists(self.active_game[1]): self.timer.start(10000) @@ -252,25 +266,131 @@ class GameList(QStackedWidget): w.setVisible(True) self.settings.setValue("filter", filter) - def update_list(self, icon_view=True): - self.settings.setValue("icon_view", icon_view) + def update_list(self, app_name=None): + # self.settings.setValue("icon_view", icon_view) + if app_name: + if widgets := self.widgets.get(app_name): - uninstalled_games = [] - installed = [i.app_name for i in self.core.get_installed_list()] - # get Uninstalled games - games = self.core.get_game_list(True) - for game in sorted(games, key=lambda x: x.app_title): - if not game.app_name in installed: - uninstalled_games.append(game.app_name) + # from update + if self.core.is_installed(widgets[0].game.app_name) and isinstance(widgets[0], BaseInstalledWidget): + igame = self.core.get_installed_game(app_name) + for w in widgets: + w.igame = igame + w.update_available = self.core.get_asset(w.game.app_name, True).build_version != igame.version + widgets[0].info_text = "" + # new installed + elif self.core.is_installed(widgets[0].game.app_name) and not isinstance(widgets[0], BaseInstalledWidget): + self.widgets.pop(widgets[0].game.app_name) - # get new uninstalled/ installed games that changed - new_installed_games = list(set(installed) - set([i.app_name for i in self.installed])) - new_uninstalled_games = list(set(uninstalled_games) - set([i.app_name for i in self.uninstalled_games])) + # QWidget().setLayout(self.icon_layout) + icon_layout = FlowLayout() + + # QWidget().setLayout(self.list_layout) + list_layout = QVBoxLayout() + + igame = self.core.get_installed_game(app_name) + self.add_installed_widget(igame) + + for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title): + i_widget, l_widget = self.widgets[igame.app_name] + icon_layout.addWidget(i_widget) + list_layout.addWidget(l_widget) + + self.uninstalled_names = [] + installed_names = [i.app_name for i in self.core.get_installed_list()] + # get Uninstalled games + games, self.dlcs = self.core.get_game_and_dlc_list() + for game in sorted(games, key=lambda x: x.app_title): + if not game.app_name in installed_names: + self.uninstalled_names.append(game) + for game in self.uninstalled_names: + i_widget, list_widget = self.widgets[game.app_name] + icon_layout.addWidget(i_widget) + list_layout.addWidget(list_widget) + + QWidget().setLayout(self.icon_layout) + QWidget().setLayout(self.list_layout) + + self.icon_widget = QWidget() + self.list_widget = QWidget() + + self.icon_widget.setLayout(icon_layout) + self.list_widget.setLayout(list_layout) + + self.list_scrollarea.setWidget(QWidget()) + self.icon_scrollarea.setWidget(QWidget()) + + self.icon_scrollarea.setWidget(self.icon_widget) + self.list_scrollarea.setWidget(self.list_widget) + + self.icon_layout = icon_layout + self.list_layout = list_layout + + self.icon_widget.setLayout(self.icon_layout) + self.list_widget.setLayout(self.list_layout) + + self.update() + + # uninstalled + elif not self.core.is_installed(widgets[0].game.app_name) and isinstance(widgets[0], BaseInstalledWidget): + self.list_layout.removeWidget(widgets[1]) + self.icon_layout.removeWidget(widgets[0]) + + self.widgets.pop(app_name) + + game = self.core.get_game(app_name, True) + self.add_uninstalled_widget(game) + + self.icon_layout.addWidget(self.widgets[app_name][0]) + self.list_layout.addWidget(self.widgets[app_name][1]) + else: + installed_names = [i.app_name for i in self.core.get_installed_list()] + # get Uninstalled games + uninstalled_games = [] + games = self.core.get_game_list(True) + for game in sorted(games, key=lambda x: x.app_title): + if not game.app_name in installed_names: + uninstalled_games.append(game.app_name) + + new_installed_games = list(set(installed_names) - set([i.app_name for i in self.installed])) + new_uninstalled_games = list(set(uninstalled_games) - set([i.app_name for i in self.uninstalled_names])) + + if (not new_uninstalled_games) and (not new_installed_games): + return + + if new_installed_games: + for name in new_installed_games: + self.icon_layout.removeWidget(self.widgets[app_name][0]) + self.list_layout.removeWidget(self.widgets[app_name][1]) + + self.widgets.pop(name) + + igame = self.core.get_installed_game(name) + self.add_installed_widget(igame) + + for name in new_uninstalled_games: + self.icon_layout.removeWidget(self.widgets[app_name][0]) + self.list_layout.removeWidget(self.widgets[app_name][1]) + + self.widgets.pop(name) + + game = self.core.get_game(name, True) + self.add_uninstalled_widget(game) + + for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title): + i_widget, list_widget = self.widgets[igame.app_name] + + self.icon_layout.addWidget(i_widget) + self.list_layout.addWidget(list_widget) + + # get Uninstalled games + games, self.dlcs = self.core.get_game_and_dlc_list() + for game in sorted(games, key=lambda x: x.app_title): + if not game.app_name in installed_names: + self.uninstalled_names.append(game) + for name in uninstalled_games: + i_widget, list_widget = self.widgets[name] + self.icon_layout.addWidget(i_widget) + self.list_layout.addWidget(list_widget) - if not new_uninstalled_games and not new_installed_games: - return - self.removeWidget(self.icon_scrollarea) - self.removeWidget(self.list_scrollarea) - self.init_ui(icon_view) - self.update() diff --git a/rare/components/tabs/games/game_widgets/base_installed_widget.py b/rare/components/tabs/games/game_widgets/base_installed_widget.py index 0a21ac05..c70f5c35 100644 --- a/rare/components/tabs/games/game_widgets/base_installed_widget.py +++ b/rare/components/tabs/games/game_widgets/base_installed_widget.py @@ -142,4 +142,4 @@ class BaseInstalledWidget(QGroupBox): print("Cancel Uninstall") return legendary_utils.uninstall(self.game.app_name, self.core, infos) - self.update_list.emit() + self.update_list.emit(self.game.app_name) diff --git a/rare/components/tabs/games/game_widgets/installed_icon_widget.py b/rare/components/tabs/games/game_widgets/installed_icon_widget.py index 26051a0c..e78e753b 100644 --- a/rare/components/tabs/games/game_widgets/installed_icon_widget.py +++ b/rare/components/tabs/games/game_widgets/installed_icon_widget.py @@ -14,7 +14,7 @@ logger = getLogger("GameWidgetInstalled") class GameWidgetInstalled(BaseInstalledWidget): - update_list = pyqtSignal() + update_list = pyqtSignal(str) show_info = pyqtSignal(str) update_game = pyqtSignal() diff --git a/rare/components/tabs/games/import_widget.py b/rare/components/tabs/games/import_widget.py index 0cd15230..fedea121 100644 --- a/rare/components/tabs/games/import_widget.py +++ b/rare/components/tabs/games/import_widget.py @@ -16,7 +16,7 @@ logger = getLogger("Import") class ImportWidget(QWidget): - update_list = pyqtSignal() + update_list = pyqtSignal(str) def __init__(self, core: LegendaryCore, parent): super(ImportWidget, self).__init__(parent=parent) @@ -125,7 +125,7 @@ class ImportWidget(QWidget): self.core.get_installed_game(app_name).title)) self.app_name_input.setText("") - self.update_list.emit() + self.update_list.emit(app_name) else: logger.warning("Failed to import" + app_name) self.info_label.setText(self.tr("Failed to import {}").format(app_name)) @@ -169,6 +169,6 @@ class ImportWidget(QWidget): if imported > 0: QMessageBox.information(self, "Imported Games", self.tr("Successfully imported {} Games. Reloading Library").format(imported)) - self.update_list.emit() + self.update_list.emit("") else: QMessageBox.information(self, "Imported Games", self.tr("No Games were found")) From 82d38578536b481afb277e2c3f7d767e40ffed94 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Mon, 17 May 2021 21:29:51 +0200 Subject: [PATCH 19/21] remove unused import --- rare/components/tabs/games/game_list.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py index 6455b4d5..d28a18fb 100644 --- a/rare/components/tabs/games/game_list.py +++ b/rare/components/tabs/games/game_list.py @@ -1,7 +1,6 @@ import os from logging import getLogger -import gi import psutil from PyQt5.QtCore import Qt, pyqtSignal, QSettings, QTimer from PyQt5.QtGui import QPixmap From 2ee1ec11621f1e724d37ac5242fc5f6598147ad1 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Tue, 18 May 2021 10:32:46 +0200 Subject: [PATCH 20/21] Import optimizations --- rare/components/tab_widget.py | 14 +++++++++++++- rare/components/tabs/downloads/__init__.py | 17 ++++++++++------- rare/components/tabs/games/__init__.py | 2 +- rare/components/tabs/games/game_list.py | 1 + 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/rare/components/tab_widget.py b/rare/components/tab_widget.py index 1dd0ede6..c1d6066d 100644 --- a/rare/components/tab_widget.py +++ b/rare/components/tab_widget.py @@ -68,6 +68,9 @@ class TabWidget(QTabWidget): # uninstall self.games_tab.game_info.info.uninstall_game.connect(self.uninstall_game) + # imported + self.games_tab.import_widget.update_list.connect(self.game_imported) + if not offline: # Download finished self.downloadTab.finished.connect(self.dl_finished) @@ -89,6 +92,15 @@ class TabWidget(QTabWidget): self.tabBarClicked.connect(lambda x: self.games_tab.layout.setCurrentIndex(0) if x == 0 else None) self.setIconSize(QSize(25, 25)) + def game_imported(self, app_name: str): + igame = self.core.get_installed_game(app_name) + if self.core.get_asset(app_name, True).build_version != igame.version: + self.downloadTab.add_update(igame) + downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) + self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) + self.games_tab.default_widget.game_list.update_list(app_name) + self.games_tab.layout.setCurrentIndex(0) + # Sync game and delete dc rpc def game_finished(self, app_name): self.delete_presence.emit() @@ -106,7 +118,7 @@ class TabWidget(QTabWidget): self.downloadTab.update_widgets.pop(app_name) downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) - + self.downloadTab.update_text.setVisible(len(self.downloadTab.update_widgets) == 0) # Update gamelist and set text of Downlaods to "Downloads" def dl_finished(self, update_list): diff --git a/rare/components/tabs/downloads/__init__.py b/rare/components/tabs/downloads/__init__.py index f7a9ff8d..1e13dd67 100644 --- a/rare/components/tabs/downloads/__init__.py +++ b/rare/components/tabs/downloads/__init__.py @@ -75,18 +75,21 @@ class DownloadTab(QWidget): self.update_text.setVisible(len(updates) == 0) for igame in updates: - widget = UpdateWidget(core, igame, self) - self.update_layout.addWidget(widget) - self.update_widgets[igame.app_name] = widget - widget.update.connect(self.update_game) - if QSettings().value("auto_update", False, bool): - self.update_game(igame.app_name, True) - widget.update_button.setDisabled(True) + self.add_update(igame) self.layout.addStretch(1) self.setLayout(self.layout) + def add_update(self, igame: InstalledGame): + widget = UpdateWidget(self.core, igame, self) + self.update_layout.addWidget(widget) + self.update_widgets[igame.app_name] = widget + widget.update.connect(self.update_game) + if QSettings().value("auto_update", False, bool): + self.update_game(igame.app_name, True) + widget.update_button.setDisabled(True) + def update_dl_queue(self, dl_queue): self.dl_queue = dl_queue diff --git a/rare/components/tabs/games/__init__.py b/rare/components/tabs/games/__init__.py index 6760a654..3fa17ac2 100644 --- a/rare/components/tabs/games/__init__.py +++ b/rare/components/tabs/games/__init__.py @@ -28,7 +28,7 @@ class GameTab(QWidget): self.import_widget = ImportWidget(core, self) self.layout.addWidget(self.import_widget) self.import_widget.back_button.clicked.connect(lambda: self.layout.setCurrentIndex(0)) - self.import_widget.update_list.connect(self.update_list) + # self.import_widget.update_list.connect(self.update_list) self.setLayout(self.layout) def update_list(self, app_name=None): diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py index d28a18fb..900f9d2c 100644 --- a/rare/components/tabs/games/game_list.py +++ b/rare/components/tabs/games/game_list.py @@ -276,6 +276,7 @@ class GameList(QStackedWidget): for w in widgets: w.igame = igame w.update_available = self.core.get_asset(w.game.app_name, True).build_version != igame.version + widgets[0].info_label.setText("") widgets[0].info_text = "" # new installed elif self.core.is_installed(widgets[0].game.app_name) and not isinstance(widgets[0], BaseInstalledWidget): From 9049d348984f9f13ae9b6d8584beab8c38d654d3 Mon Sep 17 00:00:00 2001 From: Dummerle Date: Tue, 18 May 2021 17:07:39 +0200 Subject: [PATCH 21/21] Fix bug with linux startmenu links --- rare/utils/utils.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rare/utils/utils.py b/rare/utils/utils.py index e1c984a4..c660ac18 100644 --- a/rare/utils/utils.py +++ b/rare/utils/utils.py @@ -175,7 +175,8 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"): "Terminal=false\n" "StartupWMClass=rare-game\n" ) - os.chmod(os.path.expanduser(f"~/Desktop/{igame.title}.desktop"), 0o755) + desktop_file.close() + os.chmod(os.path.expanduser(f"{path}{igame.title}.desktop"), 0o755) # Windows elif os.name == "nt":