1
0
Fork 0
mirror of synced 2024-07-01 04:30:20 +12:00

Merge branch 'main' into dev

This commit is contained in:
Dummerle 2021-05-21 13:20:58 +02:00 committed by GitHub
commit 9edfd302bd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 478 additions and 188 deletions

View file

@ -46,7 +46,7 @@ jobs:
ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }} ssh_private_key: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
commit_message: Update AUR package commit_message: Update AUR package
pyinstaller-windows: cx-freeze-windows:
runs-on: windows-latest runs-on: windows-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -55,25 +55,18 @@ jobs:
python-version: '3.8' python-version: '3.8'
- name: Install python deps - name: Install python deps
run: | run: |
pip3 install pyinstaller setuptools wheel pip3 install cx_Freeze setuptools wheel
pip3 install -r requirements.txt pip3 install -r requirements.txt
- name: Prepare
run: cp rare/__main__.py ./
- name: Build - name: Build
run: pyinstaller run: python3 freeze.py bdist_msi
--icon=rare/styles/Logo.ico - name: Copy File
--onefile run: cp dist/*.msi Rare.msi
--name Rare
--add-data="Rare/languages/*;Rare/languages"
--add-data="Rare/Styles/*;Rare/Styles"
--windowed
__main__.py
- name: Upload files to GitHub - name: Upload files to GitHub
uses: svenstaro/upload-release-action@2.2.1 uses: svenstaro/upload-release-action@2.2.1
with: with:
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/Rare.exe file: Rare.msi
asset_name: Rare.exe asset_name: Rare.msi
tag: ${{ github.ref }} tag: ${{ github.ref }}
overwrite: true overwrite: true

2
.gitignore vendored
View file

@ -6,5 +6,7 @@ __pycache__
/.vscode /.vscode
/build /build
/dist /dist
/deb_dist
*.tar.gz
/Rare.egg-info/ /Rare.egg-info/
/venv /venv

View file

@ -41,12 +41,14 @@ Install via `pip`.
## Run from source ## 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` 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? ## 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 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 ## Features
@ -60,7 +62,7 @@ Install via `pip`.
## Planned Features ## Planned Features
- More Translations (Need help) - More Translations (Need help)
- More Information about Games - More Information about Games
More planned features are in projects More planned features are in [projects](https://github.com/Dummerle/Rare/projects/1)
## Contributing ## Contributing
There are more options to contribute. There are more options to contribute.

74
freeze.py Normal file
View file

@ -0,0 +1,74 @@
import sys
from cx_Freeze import setup, Executable
from rare import __version__
# Packages to include
python_packages = []
# 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,
),
],
)

View file

@ -1,5 +1,5 @@
import os import os
__version__ = "1.3.0" __version__ = "1.4.1"
style_path = os.path.join(os.path.dirname(__file__), "styles/") style_path = os.path.join(os.path.dirname(__file__), "styles/")
lang_path = os.path.join(os.path.dirname(__file__), "languages/") lang_path = os.path.join(os.path.dirname(__file__), "languages/")

View file

@ -1,7 +1,6 @@
import configparser import configparser
import logging import logging
import os import os
import shutil
import sys import sys
import time import time
@ -16,7 +15,7 @@ from rare.components.main_window import MainWindow
from rare.components.tray_icon import TrayIcon from rare.components.tray_icon import TrayIcon
from rare.utils.utils import get_lang, load_color_scheme from rare.utils.utils import get_lang, load_color_scheme
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") file_name = os.path.expanduser(f"~/.cache/rare/logs/Rare_{start_time}.log")
if not os.path.exists(os.path.dirname(file_name)): if not os.path.exists(os.path.dirname(file_name)):
os.makedirs(os.path.dirname(file_name)) os.makedirs(os.path.dirname(file_name))

View file

@ -3,9 +3,14 @@ import webbrowser
from PyQt5.QtCore import QSize, pyqtSignal from PyQt5.QtCore import QSize, pyqtSignal
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction
from qtawesome import icon from qtawesome import icon
from rare.utils import legendary_utils
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
from rare.components.dialogs.install_dialog import InstallDialog from rare.components.dialogs.install_dialog import InstallDialog
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.tab_utils import TabBar, TabButtonWidget from rare.components.tab_utils import TabBar, TabButtonWidget
from rare.components.tabs.account import MiniWidget from rare.components.tabs.account import MiniWidget
from rare.components.tabs.cloud_saves import SyncSaves from rare.components.tabs.cloud_saves import SyncSaves
@ -64,6 +69,12 @@ class TabWidget(QTabWidget):
# open download tab # open download tab
self.games_tab.default_widget.game_list.update_game.connect(lambda: self.setCurrentIndex(1)) 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)
# imported
self.games_tab.import_widget.update_list.connect(self.game_imported)
if not offline: if not offline:
# Download finished # Download finished
self.downloadTab.finished.connect(self.dl_finished) self.downloadTab.finished.connect(self.dl_finished)
@ -87,6 +98,7 @@ class TabWidget(QTabWidget):
self.tabBarClicked.connect(lambda x: self.games_tab.layout.setCurrentIndex(0) if x == 0 else None) self.tabBarClicked.connect(lambda x: self.games_tab.layout.setCurrentIndex(0) if x == 0 else None)
self.setIconSize(QSize(25, 25)) self.setIconSize(QSize(25, 25))
def install_game(self, app_name, disable_path=False): def install_game(self, app_name, disable_path=False):
infos = InstallDialog(app_name, self.core, disable_path).get_information() infos = InstallDialog(app_name, self.core, disable_path).get_information()
@ -102,16 +114,38 @@ class TabWidget(QTabWidget):
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.downloadTab.install_game(options) self.downloadTab.install_game(options)
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 # Sync game and delete dc rpc
def game_finished(self, app_name): def game_finished(self, app_name):
self.delete_presence.emit() self.delete_presence.emit()
if self.core.get_game(app_name).supports_cloud_saves: if self.core.get_game(app_name).supports_cloud_saves:
self.cloud_saves.sync_game(app_name, True) 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 ""))
self.downloadTab.update_text.setVisible(len(self.downloadTab.update_widgets) == 0)
# Update gamelist and set text of Downlaods to "Downloads" # Update gamelist and set text of Downlaods to "Downloads"
def dl_finished(self, update_list): def dl_finished(self, update_list):
if update_list: if update_list[0]:
self.games_tab.default_widget.game_list.update_list() self.games_tab.default_widget.game_list.update_list(update_list[1])
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys())
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))

View file

@ -1,7 +1,7 @@
import os import os
from logging import getLogger 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 PyQt5.QtWidgets import QVBoxLayout, QPushButton, QHBoxLayout, QLabel, QGroupBox
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
@ -167,6 +167,11 @@ class SyncWidget(QGroupBox):
self.layout.addStretch(1) self.layout.addStretch(1)
self.setLayout(self.layout) 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): def change_path(self):
path = PathInputDialog("Select directory", "Select savepath. Warning: Do not change if you are not sure", path = PathInputDialog("Select directory", "Select savepath. Warning: Do not change if you are not sure",
self.igame.save_path).get_path() self.igame.save_path).get_path()

View file

@ -20,7 +20,7 @@ logger = getLogger("Download")
class DownloadTab(QWidget): class DownloadTab(QWidget):
finished = pyqtSignal(bool) finished = pyqtSignal(tuple)
thread: QThread thread: QThread
dl_queue = [] dl_queue = []
@ -75,18 +75,22 @@ class DownloadTab(QWidget):
self.update_text.setVisible(len(updates) == 0) self.update_text.setVisible(len(updates) == 0)
for igame in updates: for igame in updates:
widget = UpdateWidget(core, igame, self)
self.update_layout.addWidget(widget) self.add_update(igame)
self.update_widgets[igame.app_name] = widget
widget.update_signal.connect(self.update_game)
if QSettings().value("auto_update", False, bool):
self.update_game(igame.app_name, True)
widget.update_button.setDisabled(True)
self.layout.addStretch(1) self.layout.addStretch(1)
self.setLayout(self.layout) 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): def update_dl_queue(self, dl_queue):
self.dl_queue = dl_queue self.dl_queue = dl_queue
@ -135,7 +139,7 @@ class DownloadTab(QWidget):
# Information # Information
if not from_update: if not from_update:
if not InstallInfoDialog(dl_size=analysis.dl_size, install_size=analysis.install_size).get_accept(): 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 return
if self.active_game is None: if self.active_game is None:
@ -213,23 +217,25 @@ class DownloadTab(QWidget):
# QMessageBox.information(self, "Info", "Download finished") # QMessageBox.information(self, "Info", "Download finished")
logger.info("Download finished: " + self.active_game.app_title) 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:
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.dl_queue.pop(0)
self.queue_widget.update_queue(self.dl_queue) self.queue_widget.update_queue(self.dl_queue)
if self.active_game.app_name in self.update_widgets.keys(): if app_name in self.update_widgets.keys():
self.update_widgets[self.active_game.app_name].setVisible(False) self.update_widgets[app_name].setVisible(False)
self.update_widgets.pop(self.active_game.app_name) self.update_widgets.pop(app_name)
if len(self.update_widgets) == 0: if len(self.update_widgets) == 0:
self.update_text.setVisible(True) self.update_text.setVisible(True)
self.active_game = None
for i in self.update_widgets.values(): for i in self.update_widgets.values():
i.update_button.setDisabled(False) i.update_button.setDisabled(False)
self.finished.emit(True) self.finished.emit((True, app_name))
self.reset_infos() self.reset_infos()
if len(self.dl_queue) != 0: if len(self.dl_queue) != 0:
@ -243,7 +249,7 @@ class DownloadTab(QWidget):
elif text == "stop": elif text == "stop":
self.reset_infos() self.reset_infos()
self.active_game = None self.active_game = None
self.finished.emit(False) self.finished.emit((False, None))
if self.dl_queue: if self.dl_queue:
self.start_installation(*self.dl_queue[0]) self.start_installation(*self.dl_queue[0])
@ -302,6 +308,7 @@ class UpdateWidget(QWidget):
self.update_with_settings.clicked.connect(lambda: self.update_game(False)) self.update_with_settings.clicked.connect(lambda: self.update_game(False))
self.layout.addWidget(self.update_button) self.layout.addWidget(self.update_button)
self.layout.addWidget(self.update_with_settings) self.layout.addWidget(self.update_with_settings)
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) self.setLayout(self.layout)

View file

@ -1,5 +1,6 @@
from PyQt5.QtCore import QSettings, QSize from PyQt5.QtCore import QSettings, QSize, pyqtSignal
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QCheckBox, QLineEdit, QPushButton, QStackedLayout, QLabel from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QStackedLayout, \
QLabel, QComboBox
from qtawesome import icon from qtawesome import icon
from rare.components.tabs.games.game_info import InfoTabs from rare.components.tabs.games.game_info import InfoTabs
@ -36,8 +37,8 @@ class GameTab(QWidget):
self.setLayout(self.layout) self.setLayout(self.layout)
def update_list(self): def update_list(self, app_name=None):
self.default_widget.game_list.update_list(self.default_widget.head_bar.view.isChecked()) self.default_widget.game_list.update_list(app_name)
self.layout.setCurrentIndex(0) self.layout.setCurrentIndex(0)
def show_uninstalled(self, app_name): def show_uninstalled(self, app_name):
@ -62,11 +63,10 @@ class Games(QWidget):
self.game_list = GameList(core, self, offline) self.game_list = GameList(core, self, offline)
self.head_bar.search_bar.textChanged.connect( 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.head_bar)
self.layout.addWidget(self.game_list) self.layout.addWidget(self.game_list)
# self.layout.addStretch(1) # self.layout.addStretch(1)
@ -81,14 +81,23 @@ class Games(QWidget):
class GameListHeadBar(QWidget): class GameListHeadBar(QWidget):
filter_changed_signal = pyqtSignal(str)
def __init__(self, parent): def __init__(self, parent):
super(GameListHeadBar, self).__init__(parent=parent) super(GameListHeadBar, self).__init__(parent=parent)
self.layout = QHBoxLayout() self.layout = QHBoxLayout()
self.installed_only = QCheckBox(self.tr("Installed only")) # self.installed_only = QCheckBox(self.tr("Installed only"))
self.settings = QSettings() self.settings = QSettings()
self.installed_only.setChecked(self.settings.value("installed_only", False, bool)) # self.installed_only.setChecked(self.settings.value("installed_only", False, bool))
self.layout.addWidget(self.installed_only) # self.layout.addWidget(self.installed_only)
self.filter = QComboBox()
self.filter.addItems([self.tr("All"),
self.tr("Installed only"),
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) self.layout.addStretch(1)
self.import_game = QPushButton(icon("mdi.import", color="white"), self.tr("Import Game")) self.import_game = QPushButton(icon("mdi.import", color="white"), self.tr("Import Game"))
@ -118,3 +127,6 @@ class GameListHeadBar(QWidget):
self.layout.addWidget(self.refresh_list) self.layout.addWidget(self.refresh_list)
self.setLayout(self.layout) self.setLayout(self.layout)
def filter_changed(self, i):
self.filter_changed_signal.emit(["", "installed", "offline", "32bit"][i])

View file

@ -59,7 +59,8 @@ class InfoTabs(QTabWidget):
class GameInfo(QWidget, Ui_GameInfo): class GameInfo(QWidget, Ui_GameInfo):
igame: InstalledGame igame: InstalledGame
game: Game game: Game
update_list = pyqtSignal() uninstall_game = pyqtSignal(str)
update_list = pyqtSignal(str)
verify_game = pyqtSignal(str) verify_game = pyqtSignal(str)
verify_threads = {} verify_threads = {}
@ -87,12 +88,8 @@ class GameInfo(QWidget, Ui_GameInfo):
self.repair_button.clicked.connect(self.repair) self.repair_button.clicked.connect(self.repair)
def uninstall(self): def uninstall(self):
infos = UninstallDialog(self.game).get_information() self.uninstall_game.emit(self.game.app_name)
if infos == 0: self.update_list.emit(self.game.app_name)
print("Cancel Uninstall")
return
legendary_utils.uninstall(self.game.app_name, self.core, infos)
self.update_list.emit()
def repair(self): def repair(self):
repair_file = os.path.join(self.core.lgd.get_tmp_path(), f'{self.game.app_name}.repair') repair_file = os.path.join(self.core.lgd.get_tmp_path(), f'{self.game.app_name}.repair')

View file

@ -4,9 +4,10 @@ from logging import getLogger
import psutil import psutil
from PyQt5.QtCore import Qt, pyqtSignal, QSettings, QTimer from PyQt5.QtCore import Qt, pyqtSignal, QSettings, QTimer
from PyQt5.QtGui import QPixmap 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 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_icon_widget import GameWidgetInstalled
from rare.components.tabs.games.game_widgets.installed_list_widget import InstalledListWidget from rare.components.tabs.games.game_widgets.installed_list_widget import InstalledListWidget
from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled
@ -63,93 +64,36 @@ class GameList(QStackedWidget):
self.list_layout = QVBoxLayout() self.list_layout = QVBoxLayout()
self.list_layout.addWidget(QLabel(self.info_text)) 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.updates = []
self.widgets = {} 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) self.installed = sorted(self.core.get_installed_list(), key=lambda x: x.title)
# Installed Games # Installed Games
for igame in self.installed: for igame in self.installed:
if os.path.exists(f"{IMAGE_DIR}/{igame.app_name}/FinalArt.png"): icon_widget, list_widget = self.add_installed_widget(igame)
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)
self.icon_layout.addWidget(icon_widget) self.icon_layout.addWidget(icon_widget)
list_widget = InstalledListWidget(igame, self.core, pixmap, self.offline)
self.list_layout.addWidget(list_widget) self.list_layout.addWidget(list_widget)
icon_widget.show_info.connect(self.show_game_info.emit) self.uninstalled_names = []
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 = []
installed = [i.app_name for i in self.core.get_installed_list()] installed = [i.app_name for i in self.core.get_installed_list()]
# get Uninstalled games # get Uninstalled games
games, self.dlcs = self.core.get_game_and_dlc_list() games, self.dlcs = self.core.get_game_and_dlc_list()
for game in sorted(games, key=lambda x: x.app_title): for game in sorted(games, key=lambda x: x.app_title):
if not game.app_name in installed: if not game.app_name in installed:
self.uninstalled_games.append(game) self.uninstalled_names.append(game)
# add uninstalled games # 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(): for game in self.uninstalled_games:
logger.info(igame.app_title + " has a corrupt image.") icon_widget, list_widget = self.add_uninstalled_widget(game)
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.show_uninstalled_info.connect(self.install)
list_widget = ListWidgetUninstalled(self.core, igame, pixmap)
list_widget.show_uninstalled_info.connect(self.install)
self.icon_layout.addWidget(icon_widget) self.icon_layout.addWidget(icon_widget)
self.list_layout.addWidget(list_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.addLayout(self.icon_layout)
self.icon_parent_layout.addStretch(1) self.icon_parent_layout.addStretch(1)
self.list_layout.addStretch(1) self.list_layout.addStretch(1)
@ -165,8 +109,81 @@ class GameList(QStackedWidget):
if not icon_view: if not icon_view:
self.setCurrentIndex(1) self.setCurrentIndex(1)
if self.settings.value("installed_only", False, bool): if filter_games := self.settings.value("filter", "", str):
self.installed_only(True) 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): def is_finished(self):
if psutil.pid_exists(self.active_game[1]): if psutil.pid_exists(self.active_game[1]):
@ -226,7 +243,7 @@ class GameList(QStackedWidget):
self.widgets[app_name][1].launch_button.setDisabled(True) self.widgets[app_name][1].launch_button.setDisabled(True)
self.widgets[app_name][1].launch_button.setText(self.tr("Game running")) 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 t in self.widgets.values():
for w in t: for w in t:
if text.lower() in w.game.app_title.lower() + w.game.app_name.lower(): if text.lower() in w.game.app_title.lower() + w.game.app_name.lower():
@ -234,31 +251,151 @@ class GameList(QStackedWidget):
else: else:
w.setVisible(False) w.setVisible(False)
def installed_only(self, i_o: bool): def filter(self, filter="installed"):
for t in self.widgets.values(): for t in self.widgets.values():
for w in t: for w in t:
w.setVisible(not (not self.core.is_installed(w.game.app_name) and i_o)) if filter == "installed":
self.settings.setValue("installed_only", i_o) 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)
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)
self.settings.setValue("filter", filter)
def update_list(self, icon_view=True): def update_list(self, app_name=None):
self.settings.setValue("icon_view", icon_view) # self.settings.setValue("icon_view", icon_view)
if app_name:
if widgets := self.widgets.get(app_name):
uninstalled_games = [] # from update
installed = [i.app_name for i in self.core.get_installed_list()] 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_label.setText("")
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)
# 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 # 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) games = self.core.get_game_list(True)
for game in sorted(games, key=lambda x: x.app_title): for game in sorted(games, key=lambda x: x.app_title):
if not game.app_name in installed: if not game.app_name in installed_names:
uninstalled_games.append(game.app_name) uninstalled_games.append(game.app_name)
# get new uninstalled/ installed games that changed new_installed_games = list(set(installed_names) - set([i.app_name for i in self.installed]))
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_names]))
new_uninstalled_games = list(set(uninstalled_games) - set([i.app_name for i in self.uninstalled_games]))
if not new_uninstalled_games and not new_installed_games: if (not new_uninstalled_games) and (not new_installed_games):
return return
self.removeWidget(self.icon_scrollarea) if new_installed_games:
self.removeWidget(self.list_scrollarea) for name in new_installed_games:
self.init_ui(icon_view) self.icon_layout.removeWidget(self.widgets[app_name][0])
self.update() 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)

View file

@ -147,4 +147,4 @@ class BaseInstalledWidget(QGroupBox):
print("Cancel Uninstall") print("Cancel Uninstall")
return return
legendary_utils.uninstall(self.game.app_name, self.core, infos) legendary_utils.uninstall(self.game.app_name, self.core, infos)
self.update_list.emit() self.update_list.emit(self.game.app_name)

View file

@ -14,7 +14,7 @@ logger = getLogger("GameWidgetInstalled")
class GameWidgetInstalled(BaseInstalledWidget): class GameWidgetInstalled(BaseInstalledWidget):
update_list = pyqtSignal() update_list = pyqtSignal(str)
show_info = pyqtSignal(str) show_info = pyqtSignal(str)
update_game = pyqtSignal() update_game = pyqtSignal()

View file

@ -16,7 +16,7 @@ logger = getLogger("Import")
class ImportWidget(QWidget): class ImportWidget(QWidget):
update_list = pyqtSignal() update_list = pyqtSignal(str)
def __init__(self, core: LegendaryCore, parent): def __init__(self, core: LegendaryCore, parent):
super(ImportWidget, self).__init__(parent=parent) super(ImportWidget, self).__init__(parent=parent)
@ -119,7 +119,7 @@ class ImportWidget(QWidget):
self.core.get_installed_game(app_name).title)) self.core.get_installed_game(app_name).title))
self.app_name_input.setText("") self.app_name_input.setText("")
self.update_list.emit() self.update_list.emit(app_name)
else: else:
logger.warning("Failed to import" + app_name) logger.warning("Failed to import" + app_name)
self.info_label.setText(self.tr("Failed to import {}").format(app_name)) self.info_label.setText(self.tr("Failed to import {}").format(app_name))

View file

@ -1362,82 +1362,83 @@ Installationsgröße: {} GB</translation>
<context> <context>
<name>RareSettings</name> <name>RareSettings</name>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="25"/> <location filename="../components/tabs/settings/rare.py" line="27"/>
<source>Rare settings</source> <source>Rare settings</source>
<translation type="obsolete">Rare Einstellungen</translation> <translation type="obsolete">Rare Einstellungen</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="48"/> <location filename="../components/tabs/settings/rare.py" line="51"/>
<source>Save</source> <source>Save</source>
<translation type="obsolete">Speichern</translation> <translation type="obsolete">Speichern</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="50"/> <location filename="../components/tabs/settings/rare.py" line="53"/>
<source>Image Directory</source> <source>Image Directory</source>
<translation type="obsolete">Ordner für Bilder</translation> <translation type="obsolete">Ordner für Bilder</translation>
</message> </message>
<message> <message>
<location filename="../ui/components/tabs/settings/rare.py" line="119"/> <location filename="../ui/components/tabs/settings/rare.py" line="119"/>
<source>Language</source> <source>Language</source>
<translation>Sprache</translation> <translation>Sprache</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="87"/> <location filename="../components/tabs/settings/rare.py" line="102"/>
<source>Restart Application to activate changes</source> <source>Restart Application to activate changes</source>
<translation type="obsolete">Starte die App neu um die Änderungen zu aktivieren</translation> <translation type="obsolete">Starte die App neu um die Änderungen zu aktivieren</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="33"/> <location filename="../components/tabs/settings/rare.py" line="36"/>
<source>Confirm launch of game</source> <source>Confirm launch of game</source>
<translation type="obsolete">Start des Spiels bestätigen</translation> <translation type="obsolete">Start des Spiels bestätigen</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="30"/> <location filename="../components/tabs/settings/rare.py" line="33"/>
<source>Exit to System Tray Icon</source> <source>Exit to System Tray Icon</source>
<translation type="obsolete">Beim verlassen auf das System Tray Icon minimieren</translation> <translation type="obsolete">Beim verlassen auf das System Tray Icon minimieren</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="30"/> <location filename="../components/tabs/settings/rare.py" line="33"/>
<source>Hide to System Tray Icon</source> <source>Hide to System Tray Icon</source>
<translation type="obsolete">In das System Tray Icon minimieren</translation> <translation type="obsolete">In das System Tray Icon minimieren</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="35"/> <location filename="../components/tabs/settings/rare.py" line="38"/>
<source>Auto sync with cloud</source> <source>Auto sync with cloud</source>
<translation type="obsolete">Speicherstände automatisch mit der Cloud synchronisieren</translation> <translation type="obsolete">Speicherstände automatisch mit der Cloud synchronisieren</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="35"/> <location filename="../components/tabs/settings/rare.py" line="38"/>
<source>Sync with cloud</source> <source>Sync with cloud</source>
<translation type="obsolete">Automatisch Synchronisieren</translation> <translation type="obsolete">Automatisch Synchronisieren</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="38"/> <location filename="../components/tabs/settings/rare.py" line="41"/>
<source>Save size</source> <source>Save size</source>
<translation type="obsolete">Größe Speichern</translation> <translation type="obsolete">Größe Speichern</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="38"/> <location filename="../components/tabs/settings/rare.py" line="41"/>
<source>Save size of window after restart</source> <source>Save size of window after restart</source>
<translation type="obsolete">Die Fenstergröße nach dem Beenden speichern</translation> <translation type="obsolete">Die Fenstergröße nach dem Beenden speichern</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="31"/> <location filename="../components/tabs/settings/rare.py" line="34"/>
<source>Automatically update Games on startup</source> <source>Automatically update Games on startup</source>
<translation type="obsolete">Spiele automatisch updaten</translation> <translation type="obsolete">Spiele automatisch updaten</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="31"/> <location filename="../components/tabs/settings/rare.py" line="34"/>
<source>Auto updates</source> <source>Auto updates</source>
<translation type="obsolete">Automatische Updates</translation> <translation type="obsolete">Automatische Updates</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="36"/> <location filename="../components/tabs/settings/rare.py" line="39"/>
<source>Show Notifications after Downloads</source> <source>Show Notifications after Downloads</source>
<translation type="obsolete">Benachrichtigung nach Abschluss des Downloads anzeigen</translation> <translation type="obsolete">Benachrichtigung nach Abschluss des Downloads anzeigen</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/settings/rare.py" line="36"/> <location filename="../components/tabs/settings/rare.py" line="39"/>
<source>Show notification</source> <source>Show notification</source>
<translation type="obsolete">Benachrichtigung anzeigen</translation> <translation type="obsolete">Benachrichtigung anzeigen</translation>
</message> </message>
@ -1526,6 +1527,11 @@ Installationsgröße: {} GB</translation>
<source>Behavior</source> <source>Behavior</source>
<translation>Optionen</translation> <translation>Optionen</translation>
</message> </message>
<message>
<location filename="../components/tabs/settings/rare.py" line="76"/>
<source>Open Log directory</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SyncSaves</name> <name>SyncSaves</name>
@ -1643,22 +1649,22 @@ Installationsgröße: {} GB</translation>
<translation>Pfad ändern</translation> <translation>Pfad ändern</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/cloud_saves/sync_widget.py" line="181"/> <location filename="../components/tabs/cloud_saves/sync_widget.py" line="186"/>
<source>Uploading...</source> <source>Uploading...</source>
<translation>Hochladen...</translation> <translation>Hochladen...</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/cloud_saves/sync_widget.py" line="189"/> <location filename="../components/tabs/cloud_saves/sync_widget.py" line="194"/>
<source>Upload finished</source> <source>Upload finished</source>
<translation>Hochladen abgeschlossen</translation> <translation>Hochladen abgeschlossen</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/cloud_saves/sync_widget.py" line="199"/> <location filename="../components/tabs/cloud_saves/sync_widget.py" line="204"/>
<source>Downloading...</source> <source>Downloading...</source>
<translation>Runterladen...</translation> <translation>Runterladen...</translation>
</message> </message>
<message> <message>
<location filename="../components/tabs/cloud_saves/sync_widget.py" line="205"/> <location filename="../components/tabs/cloud_saves/sync_widget.py" line="210"/>
<source>Download finished</source> <source>Download finished</source>
<translation>Download abgeschlossen</translation> <translation>Download abgeschlossen</translation>
</message> </message>

View file

@ -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")): 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")) 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: try:
# Remove DLC first so directory is empty when game uninstall runs # Remove DLC first so directory is empty when game uninstall runs
dlcs = core.get_dlc_for_game(app_name) dlcs = core.get_dlc_for_game(app_name)

View file

@ -14,12 +14,13 @@ if os.name == "nt":
from win32com.client import Dispatch from win32com.client import Dispatch
from rare import lang_path, style_path from rare import lang_path, style_path
# Mac not supported
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
logger = getLogger("Utils") logger = getLogger("Utils")
s = QSettings("Rare", "Rare") s = QSettings("Rare", "Rare")
IMAGE_DIR = s.value("img_dir", os.path.expanduser("~/.cache/rare/images"), type=str) 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): def download_images(signal: pyqtSignal, core: LegendaryCore):
@ -246,7 +247,8 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"):
"Terminal=false\n" "Terminal=false\n"
"StartupWMClass=rare-game\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 # Windows
elif os.name == "nt": elif os.name == "nt":
@ -261,7 +263,12 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"):
target = os.path.abspath(sys.argv[0]) target = os.path.abspath(sys.argv[0])
# Name of link file # 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 # Path to location of link file
pathLink = os.path.join(target_folder, linkName) pathLink = os.path.join(target_folder, linkName)
@ -279,4 +286,5 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"):
img.save(icon + ".ico") img.save(icon + ".ico")
logger.info("Create Icon") logger.info("Create Icon")
shortcut.IconLocation = os.path.join(icon + ".ico") shortcut.IconLocation = os.path.join(icon + ".ico")
shortcut.save() shortcut.save()

View file

@ -5,3 +5,4 @@ QtAwesome
notify-py notify-py
psutil psutil
pypresence pypresence
pywin32; platform_system == "Windows"

View file

@ -1,3 +1,5 @@
import os
import setuptools import setuptools
from rare import __version__ as version from rare import __version__ as version
@ -5,6 +7,21 @@ from rare import __version__ as version
with open("README.md", "r") as fh: with open("README.md", "r") as fh:
long_description = fh.read() 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( setuptools.setup(
name="Rare", name="Rare",
version=version, version=version,
@ -25,15 +42,5 @@ setuptools.setup(
], ],
python_requires=">=3.8", python_requires=">=3.8",
entry_points=dict(console_scripts=["rare=rare.__main__:main"]), entry_points=dict(console_scripts=["rare=rare.__main__:main"]),
install_requires=[ install_requires=requirements,
"requests<3.0",
"pillow",
"setuptools",
"wheel",
"PyQt5",
"QtAwesome",
"notify-py",
"psutil",
"pypresence"
],
) )