1
0
Fork 0
mirror of synced 2024-06-29 11:40:37 +12:00

Merge branch 'main' into dev

This commit is contained in:
Dummerle 2021-09-04 22:49:08 +02:00 committed by GitHub
commit f7f7f83101
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 2501 additions and 2548 deletions

6
.github/GenPKG.sh vendored
View file

@ -1,6 +0,0 @@
export PYTHONPATH=$PWD
version=$(python3 rare --version)
cd .github
git clone https://aur.archlinux.org/rare.git
cd ..
sed -i "s/.*pkgver=.*/pkgver=$version/" .github/rare/PKGBUILD

1
.github/rare vendored

@ -1 +0,0 @@
Subproject commit f689dacef1b8902da34aae7eff85a1bbe8e0a0a4

View file

@ -76,7 +76,7 @@ jobs:
- name: Build Appimage - name: Build Appimage
run: | run: |
appimage-builder --skip-test appimage-builder --skip-test
mv Rare-*.AppImage ../Rare.AppImage mv Rare-*.AppImage Rare.AppImage
- name: Upload to GitHub - name: Upload to GitHub
uses: svenstaro/upload-release-action@2.2.1 uses: svenstaro/upload-release-action@2.2.1
@ -87,5 +87,65 @@ jobs:
tag: ${{ github.ref }} tag: ${{ github.ref }}
overwrite: true overwrite: true
cx_freeze:
runs-on: "windows-latest"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Dependencies
run: pip3 install -r requirements.txt
- name: cx_freeze
run: pip3 install --upgrade cx_freeze wheel
- name: prepare Files
run: mv rare/__main__.py rare/Rare.py
- name: Build
run: python freeze.py bdist_msi
- name: Rename File
run: mv dist/* dist/Rare.msi
- name: Upload to GitHub
uses: svenstaro/upload-release-action@2.2.1
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/Rare.msi
asset_name: Rare.msi
tag: ${{ github.ref }}
overwrite: true
mac_os:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.9'
- name: Rare Dependencies
run: pip install -r requirements.txt
- name: install pyinstaller
run: pip install pyinstaller
- name: copy files
run: mv rare/__main__.py __main__.py
- name: run pyinstaller
run: pyinstaller -F --name Rare --add-data "rare/languages/*:rare/languages" --add-data "rare/resources/colors/*:rare/resources/colors" --add-data "rare/resources/images/*:rare/resources/images/" --add-data "rare/resources/stylesheets/RareStyle/*:rare/resources/stylesheets/RareStyle/" --windowed --icon rare/resources/images/Rare.icns __main__.py
- name: upload to GitHub
uses: svenstaro/upload-release-action@2.2.1
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: dist/Rare.app
asset_name: Rare_MacOS.app
tag: ${{ github.ref }}
overwrite: true

67
.github/workflows/tests.yml vendored Normal file
View file

@ -0,0 +1,67 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
workflow_dispatch:
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: 'python'
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View file

@ -2,9 +2,8 @@
## A frontend for legendary, the open source Epic Games Launcher alternative ## A frontend for legendary, the open source Epic Games Launcher alternative
Rare is a GUI for Legendary, a command line aternative to Epic Games launcher. It is currently considered beta software. Rare is a GUI for Legendary, a command line alternative to Epic Games launcher. If you run into an issue, please report
You will probably run into issues, so it is recommend to make a backup. If you run into an issue, please report it by it by creating an issue on GitHub or on Discord: https://discord.gg/YvmABK9YSk
creating an issue on github or on Discord: https://discord.gg/YvmABK9YSk
![Discord Shield](https://discordapp.com/api/guilds/826881530310819914/widget.png?style=shield) ![Discord Shield](https://discordapp.com/api/guilds/826881530310819914/widget.png?style=shield)
@ -12,13 +11,14 @@ creating an issue on github or on Discord: https://discord.gg/YvmABK9YSk
### Installation via pip (recommend) ### Installation via pip (recommend)
Execute `pip install Rare` for all users Or `pip install Rare --user` for only one user. Execute `pip install Rare` for all users Or `pip install Rare --user` for only one user.
Linux: execute `rare` in your terminal. Linux: execute `rare` in your terminal.
Windows: execute `pythonw -m rare` in cmd Windows: execute `pythonw -m rare` in cmd
It is possible to create a desktop link, or a start menu link. Execute the command above with `--desktop-shortcut` or `--startmenu-shortcut` option It is possible to create a desktop link, or a start menu link. Execute the command above with `--desktop-shortcut`
or `--startmenu-shortcut` option
**Note**: On Linux must be `/home/user/.local/bin` in PATH and on Windows must be `PythonInstallationDirectory\Scripts` **Note**: On Linux must be `/home/user/.local/bin` in PATH and on Windows must be `PythonInstallationDirectory\Scripts`
in PATH. in PATH.
@ -32,16 +32,16 @@ There are some AUR packages available:
- [rare](https://aur.archlinux.org/packages/rare) - for stable releases - [rare](https://aur.archlinux.org/packages/rare) - for stable releases
- [rare-git](https://aur.archlinux.org/packages/rare-git) - for the latest features, which are not in a stable release - [rare-git](https://aur.archlinux.org/packages/rare-git) - for the latest features, which are not in a stable release
#### Debian based
There is a `.deb` package available from
the [releases page](https://github.com/Dummerle/Rare/releases): `sudo apt install ./Rare.deb`
#### Other #### Other
Install via `pip`. Install via `pip`.
## Run from source ### Packages
In [releases page](https://github.com/Dummerle/Rare/releases) are AppImages for Linux and a msi file for windows
available
### Run from source
1. Run `pip install -r requirements.txt` to get dependencies. If you use `pacman` you can 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` run `sudo pacman --needed -S python-wheel python-setuptools python-pyqt5 python-qtawesome python-requests python-pillow`

View file

@ -293,6 +293,37 @@ class LegendaryCore:
def _get_installed_game(self, app_name) -> InstalledGame: def _get_installed_game(self, app_name) -> InstalledGame:
return self.lgd.get_installed_game(app_name) return self.lgd.get_installed_game(app_name)
def get_non_asset_library_items(self, skip_ue=True) -> (List[Game], Dict[str, List[Game]]):
"""
Gets a list of Games without assets for installation, for instance Games delivered via
third-party stores that do not have assets for installation
:param skip_ue: Ingore Unreal Marketplace entries
:return: List of Games and DLC that do not have assets
"""
_ret = []
_dlc = defaultdict(list)
# get all the appnames we have to ignore
ignore = set(i.app_name for i in self.get_assets())
for libitem in self.egs.get_library_items():
if libitem['namespace'] == 'ue' and skip_ue:
continue
if libitem['appName'] in ignore:
continue
game = self.lgd.get_game_meta(libitem['appName'])
if not game:
eg_meta = self.egs.get_game_info(libitem['namespace'], libitem['catalogItemId'])
game = Game(app_name=libitem['appName'], app_version=None,
app_title=eg_meta['title'], asset_info=None, metadata=eg_meta)
self.lgd.set_game_meta(game.app_name, game)
if game.is_dlc:
_dlc[game.metadata['mainGameItem']['id']].append(game)
elif not any(i['path'] == 'mods' for i in game.metadata.get('categories', [])):
_ret.append(game)
return _ret, _dlc
def get_launch_parameters(self, app_name: str, offline: bool = False, def get_launch_parameters(self, app_name: str, offline: bool = False,
user: str = None, extra_args: list = None, user: str = None, extra_args: list = None,
wine_bin: str = None, wine_pfx: str = None, wine_bin: str = None, wine_pfx: str = None,

82
freeze.py Normal file
View file

@ -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',
'psutil',
'pypresence',
'win32com'
]
# 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": False}
build_options["bdist_msi"] = bdist_msi_options
else:
name = 'Rare'
src_files += [
'LICENSE',
'README.md',
'rare/resources/images/Rare.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/Rare.py',
targetName=name,
icon='rare/resources/images/Rare.ico',
base=base,
shortcutName=shortcutName,
shortcutDir=shortcutDir,
),
],
)

View file

@ -1,6 +1,6 @@
import os import os
__version__ = "1.5.0" __version__ = "1.6.2"
resources_path = os.path.join(os.path.dirname(__file__), "resources") resources_path = os.path.join(os.path.dirname(__file__), "resources")
languages_path = os.path.join(os.path.dirname(__file__), "languages") languages_path = os.path.join(os.path.dirname(__file__), "languages")

View file

@ -36,7 +36,7 @@ def main():
if args.version: if args.version:
print(__version__) print(__version__)
exit(0) return
try: try:
# this object only allows one instance per machine # this object only allows one instance per machine
me = singleton.SingleInstance() me = singleton.SingleInstance()
@ -49,14 +49,16 @@ def main():
else: else:
file.write("start") file.write("start")
file.close() file.close()
return
exit(0)
if args.subparser == "launch": if args.subparser == "launch":
args.silent = True args.silent = True
# start app
# Import start now, to not import everything # fix error in cx_freeze
import multiprocessing
multiprocessing.freeze_support()
from rare.app import start from rare.app import start
start(args) start(args)

View file

@ -4,8 +4,9 @@ import os
import sys import sys
import time import time
import qtawesome
from PyQt5.QtCore import QSettings, QTranslator from PyQt5.QtCore import QSettings, QTranslator
from PyQt5.QtGui import QIcon from PyQt5.QtGui import QIcon, QPalette
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QStyleFactory from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QStyleFactory
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
@ -72,8 +73,8 @@ class App(QApplication):
# Translator # Translator
self.translator = QTranslator() self.translator = QTranslator()
lang = settings.value("language", get_lang(), type=str) lang = settings.value("language", get_lang(), type=str)
if os.path.exists(languages_path + lang + ".qm"): if os.path.exists(p := os.path.join(languages_path, lang + ".qm")):
self.translator.load(languages_path + lang + ".qm") self.translator.load(p)
logger.info("Your language is supported: " + lang) logger.info("Your language is supported: " + lang)
elif not lang == "en": elif not lang == "en":
logger.info("Your language is not supported") logger.info("Your language is not supported")
@ -89,6 +90,8 @@ class App(QApplication):
custom_palette = load_color_scheme(os.path.join(resources_path, "colors", color + ".scheme")) custom_palette = load_color_scheme(os.path.join(resources_path, "colors", color + ".scheme"))
if custom_palette is not None: if custom_palette is not None:
self.setPalette(custom_palette) self.setPalette(custom_palette)
qtawesome.set_defaults(color=custom_palette.color(QPalette.Text))
elif style := settings.value("style_sheet", False): elif style := settings.value("style_sheet", False):
settings.setValue("color_scheme", "") settings.setValue("color_scheme", "")
stylesheet = open(os.path.join(resources_path, "stylesheets", style, "stylesheet.qss")).read() stylesheet = open(os.path.join(resources_path, "stylesheets", style, "stylesheet.qss")).read()
@ -96,6 +99,7 @@ class App(QApplication):
if os.name == "nt": if os.name == "nt":
style_resource_path = style_resource_path.replace('\\', '/') style_resource_path = style_resource_path.replace('\\', '/')
self.setStyleSheet(stylesheet.replace("@path@", style_resource_path)) self.setStyleSheet(stylesheet.replace("@path@", style_resource_path))
qtawesome.set_defaults(color="white")
# lk: for qresources stylesheets, not an ideal solution for modability, # lk: for qresources stylesheets, not an ideal solution for modability,
# lk: too many extra steps and I don't like binary files in git, even as strings. # lk: too many extra steps and I don't like binary files in git, even as strings.
# importlib.import_module("rare.resources.stylesheets." + style) # importlib.import_module("rare.resources.stylesheets." + style)
@ -126,7 +130,8 @@ class App(QApplication):
self.mainwindow.tab_widget.downloadTab.finished.connect(lambda x: self.tray_icon.showMessage( self.mainwindow.tab_widget.downloadTab.finished.connect(lambda x: self.tray_icon.showMessage(
self.tr("Download finished"), self.tr("Download finished"),
self.tr("Download finished. {} is playable now").format(self.core.get_game(x[1]).app_title), self.tr("Download finished. {} is playable now").format(self.core.get_game(x[1]).app_title),
QSystemTrayIcon.Information, 4000) if x[0] else None) QSystemTrayIcon.Information, 4000) if (
x[0] and QSettings().value("notification", True, bool)) else None)
if not self.args.silent: if not self.args.silent:
self.mainwindow.show() self.mainwindow.show()

View file

@ -27,6 +27,6 @@ class TabButtonWidget(QToolButton):
super(TabButtonWidget, self).__init__() super(TabButtonWidget, self).__init__()
self.setText("Icon") self.setText("Icon")
self.setPopupMode(QToolButton.InstantPopup) self.setPopupMode(QToolButton.InstantPopup)
self.setIcon(icon(button_icon, color="white", scale_factor=1.25)) self.setIcon(icon(button_icon, scale_factor=1.25))
self.setToolTip(tool_tip) self.setToolTip(tool_tip)
self.setIconSize(QSize(25, 25)) self.setIconSize(QSize(25, 25))

View file

@ -1,5 +1,5 @@
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, QShortcut
from qtawesome import icon from qtawesome import icon
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
@ -55,7 +55,7 @@ class TabWidget(QTabWidget):
account_button.menu().addAction(account_action) account_button.menu().addAction(account_action)
self.tabBar().setTabButton(disabled_tab + 1, self.tabBar().RightSide, account_button) self.tabBar().setTabButton(disabled_tab + 1, self.tabBar().RightSide, account_button)
self.addTab(self.settings, icon("fa.gear", color='white'), self.addTab(self.settings, icon("fa.gear"),
"(!)" if self.settings.about.update_available else "") "(!)" if self.settings.about.update_available else "")
# Signals # Signals
@ -100,12 +100,22 @@ class TabWidget(QTabWidget):
# Open game list on click on Games tab button # Open game list on click on Games tab button
self.tabBarClicked.connect(self.mouse_clicked) self.tabBarClicked.connect(self.mouse_clicked)
self.setIconSize(QSize(25, 25)) self.setIconSize(QSize(25, 25))
# shortcuts
QShortcut("Alt+1", self).activated.connect(lambda: self.setCurrentIndex(0))
QShortcut("Alt+2", self).activated.connect(lambda: self.setCurrentIndex(1))
QShortcut("Alt+3", self).activated.connect(lambda: self.setCurrentIndex(2))
QShortcut("Alt+4", self).activated.connect(lambda: self.setCurrentIndex(5))
self.downloadTab.dl_status.connect(
self.games_tab.default_widget.game_list.installing_widget.image_widget.set_status)
def mouse_clicked(self, tab_num): def mouse_clicked(self, tab_num):
if tab_num == 0: if tab_num == 0:
self.games_tab.layout.setCurrentIndex(0) self.games_tab.layout.setCurrentIndex(0)
if tab_num == 3: if tab_num == 3:
self.store.load() self.store.load()
# TODO; maybe pass InstallOptionsModel only, not split arguments # TODO; maybe pass InstallOptionsModel only, not split arguments
def install_game(self, options: InstallOptionsModel, update=False, silent=False): def install_game(self, options: InstallOptionsModel, update=False, silent=False):
@ -125,6 +135,7 @@ class TabWidget(QTabWidget):
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else "")) self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.setCurrentIndex(1) self.setCurrentIndex(1)
self.downloadTab.install_game(download_item) self.downloadTab.install_game(download_item)
self.games_tab.default_widget.game_list.start_download(download_item.options.app_name)
def game_imported(self, app_name: str): def game_imported(self, app_name: str):
igame = self.core.get_installed_game(app_name) igame = self.core.get_installed_game(app_name)
@ -159,6 +170,7 @@ class TabWidget(QTabWidget):
if update_list[0]: if update_list[0]:
self.games_tab.default_widget.game_list.update_list(update_list[1]) self.games_tab.default_widget.game_list.update_list(update_list[1])
self.cloud_saves.reload(update_list[1]) self.cloud_saves.reload(update_list[1])
self.games_tab.default_widget.game_list.installing_widget.setVisible(False)
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

@ -86,7 +86,9 @@ class SyncWidget(QGroupBox):
if not igame.save_path: if not igame.save_path:
igame.save_path = os.path.expanduser(f"~/{igame.app_name}/") igame.save_path = os.path.expanduser(f"~/{igame.app_name}/")
QMessageBox.warning(self, "Savepath error", self.tr("Please edit save path of game {} manually in Cload saves tab").format(igame.title)) QMessageBox.warning(self, "Savepath error",
self.tr("Please edit save path of game {} manually in Cload saves tab").format(
igame.title))
if igame.save_path and not os.path.exists(igame.save_path): if igame.save_path and not os.path.exists(igame.save_path):
os.makedirs(igame.save_path) os.makedirs(igame.save_path)
self.core.lgd.set_installed_game(self.igame.app_name, self.igame) self.core.lgd.set_installed_game(self.igame.app_name, self.igame)

View file

@ -21,6 +21,7 @@ class DownloadTab(QWidget):
finished = pyqtSignal(tuple) finished = pyqtSignal(tuple)
thread: QThread thread: QThread
dl_queue = [] dl_queue = []
dl_status = pyqtSignal(int)
def __init__(self, core: LegendaryCore, updates: list, parent): def __init__(self, core: LegendaryCore, updates: list, parent):
super(DownloadTab, self).__init__(parent=parent) super(DownloadTab, self).__init__(parent=parent)
@ -120,16 +121,6 @@ class DownloadTab(QWidget):
pass pass
elif text == "finish": elif text == "finish":
self.installing_game.setText(self.tr("Download finished. Reload library")) self.installing_game.setText(self.tr("Download finished. Reload library"))
if QSettings().value("notification", True, bool):
try:
from notifypy import Notify
except ModuleNotFoundError:
logger.warning("No Notification Module found")
else:
notification = Notify()
notification.title = self.tr("Installation finished")
notification.message = self.tr("Finished Download of game {}").format(self.active_game.app_title)
notification.send()
# 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)
@ -184,6 +175,7 @@ class DownloadTab(QWidget):
self.downloaded.setText( self.downloaded.setText(
self.tr("Downloaded") + f": {get_size(ui_update.total_downloaded)} / {get_size(self.analysis.dl_size)}") self.tr("Downloaded") + f": {get_size(ui_update.total_downloaded)} / {get_size(self.analysis.dl_size)}")
self.time_left.setText(self.tr("Time left: ") + self.get_time(ui_update.estimated_time_left)) self.time_left.setText(self.tr("Time left: ") + self.get_time(ui_update.estimated_time_left))
self.dl_status.emit(int(100 * ui_update.total_downloaded / self.analysis.dl_size))
def get_time(self, seconds: int) -> str: def get_time(self, seconds: int) -> str:
return str(datetime.timedelta(seconds=seconds)) return str(datetime.timedelta(seconds=seconds))

View file

@ -20,14 +20,14 @@ class DlWidget(QWidget):
self.layout = QHBoxLayout() self.layout = QHBoxLayout()
self.left_layout = QVBoxLayout() self.left_layout = QVBoxLayout()
self.move_up_button = QPushButton(icon("fa.arrow-up", color="white"), "") self.move_up_button = QPushButton(icon("fa.arrow-up"), "")
if index == 0: if index == 0:
self.move_up_button.setDisabled(True) self.move_up_button.setDisabled(True)
self.move_up_button.clicked.connect(lambda: self.move_up.emit(self.app_name)) self.move_up_button.clicked.connect(lambda: self.move_up.emit(self.app_name))
self.move_up_button.setFixedWidth(20) self.move_up_button.setFixedWidth(20)
self.left_layout.addWidget(self.move_up_button) self.left_layout.addWidget(self.move_up_button)
self.move_down_buttton = QPushButton(icon("fa.arrow-down", color="white"), "") self.move_down_buttton = QPushButton(icon("fa.arrow-down"), "")
self.move_down_buttton.clicked.connect(lambda: self.move_down.emit(self.app_name)) self.move_down_buttton.clicked.connect(lambda: self.move_down.emit(self.app_name))
self.left_layout.addWidget(self.move_down_buttton) self.left_layout.addWidget(self.move_down_buttton)
self.move_down_buttton.setFixedWidth(20) self.move_down_buttton.setFixedWidth(20)

View file

@ -95,12 +95,13 @@ class GameListHeadBar(QWidget):
self.filter.addItems([self.tr("All"), self.filter.addItems([self.tr("All"),
self.tr("Installed only"), self.tr("Installed only"),
self.tr("Offline Games"), self.tr("Offline Games"),
self.tr("32 Bit Games")]) self.tr("32 Bit Games"),
self.tr("Installable Games")])
self.filter.currentIndexChanged.connect(self.filter_changed) self.filter.currentIndexChanged.connect(self.filter_changed)
self.layout.addWidget(self.filter) 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"), self.tr("Import Game"))
self.layout.addWidget(self.import_game) self.layout.addWidget(self.import_game)
self.layout.addStretch(1) self.layout.addStretch(1)
@ -109,24 +110,23 @@ class GameListHeadBar(QWidget):
self.search_bar.setObjectName("search_bar") self.search_bar.setObjectName("search_bar")
self.search_bar.setFrame(False) self.search_bar.setFrame(False)
icon_label = QLabel() icon_label = QLabel()
icon_label.setPixmap(icon("fa.search", color="white").pixmap(QSize(20, 20))) icon_label.setPixmap(icon("fa.search").pixmap(QSize(20, 20)))
self.layout.addWidget(icon_label) self.layout.addWidget(icon_label)
self.search_bar.setMinimumWidth(200) self.search_bar.setMinimumWidth(200)
self.search_bar.setPlaceholderText(self.tr("Search Game")) self.search_bar.setPlaceholderText(self.tr("Search Game"))
self.layout.addWidget(self.search_bar) self.layout.addWidget(self.search_bar)
self.layout.addStretch(2) self.layout.addStretch(2)
checked = QSettings().value("icon_view", True, bool) checked = QSettings().value("icon_view", True, bool)
self.view = SelectViewWidget(checked) self.view = SelectViewWidget(checked)
self.layout.addWidget(self.view) self.layout.addWidget(self.view)
self.layout.addStretch(1) self.layout.addStretch(1)
self.refresh_list = QPushButton() self.refresh_list = QPushButton()
self.refresh_list.setIcon(icon("fa.refresh", color="white")) # Reload icon self.refresh_list.setIcon(icon("fa.refresh")) # Reload icon
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): def filter_changed(self, i):
self.filter_changed_signal.emit(["", "installed", "offline", "32bit"][i]) self.filter_changed_signal.emit(["", "installed", "offline", "32bit", "installable"][i])

View file

@ -27,7 +27,7 @@ class InfoTabs(QTabWidget):
self.setTabBar(SideTabBar()) self.setTabBar(SideTabBar())
self.setTabPosition(QTabWidget.West) self.setTabPosition(QTabWidget.West)
self.addTab(QWidget(), icon("mdi.keyboard-backspace", color="white"), self.tr("Back")) self.addTab(QWidget(), icon("mdi.keyboard-backspace"), self.tr("Back"))
self.tabBarClicked.connect(lambda x: self.parent().layout.setCurrentIndex(0) if x == 0 else None) self.tabBarClicked.connect(lambda x: self.parent().layout.setCurrentIndex(0) if x == 0 else None)
self.info = GameInfo(core, self) self.info = GameInfo(core, self)
@ -60,7 +60,6 @@ class InfoTabs(QTabWidget):
self.parent().layout.setCurrentIndex(0) self.parent().layout.setCurrentIndex(0)
class GameInfo(QWidget, Ui_GameInfo): class GameInfo(QWidget, Ui_GameInfo):
igame: InstalledGame igame: InstalledGame
game: Game game: Game

View file

@ -25,7 +25,7 @@ class UninstalledTabInfo(QTabWidget):
self.setTabBar(SideTabBar()) self.setTabBar(SideTabBar())
self.setTabPosition(QTabWidget.West) self.setTabPosition(QTabWidget.West)
self.addTab(QWidget(), icon("mdi.keyboard-backspace", color="white"), self.tr("Back")) self.addTab(QWidget(), icon("mdi.keyboard-backspace"), self.tr("Back"))
self.tabBarClicked.connect(lambda x: self.parent().layout.setCurrentIndex(0) if x == 0 else None) self.tabBarClicked.connect(lambda x: self.parent().layout.setCurrentIndex(0) if x == 0 else None)
self.info = UninstalledInfo(core, self) self.info = UninstalledInfo(core, self)
@ -46,7 +46,10 @@ class UninstalledTabInfo(QTabWidget):
def update_game(self, app_name): def update_game(self, app_name):
self.info.update_game(app_name) self.info.update_game(app_name)
self.model.clear() self.model.clear()
self.model.load(json.load(open(os.path.expanduser(f"~/.config/legendary/metadata/{app_name}.json"), "r"))) try:
self.model.load(json.load(open(os.path.expanduser(f"~/.config/legendary/metadata/{app_name}.json"), "r")))
except: # ignore if no metadata
pass
def keyPressEvent(self, e: QKeyEvent): def keyPressEvent(self, e: QKeyEvent):
if e.key() == Qt.Key_Escape: if e.key() == Qt.Key_Escape:
@ -62,6 +65,8 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
self.setupUi(self) self.setupUi(self)
self.core = core self.core = core
self.no_install_label.setVisible(False)
if platform.system() != "Windows": if platform.system() != "Windows":
self.steam_worker = SteamWorker(self.core) self.steam_worker = SteamWorker(self.core)
self.steam_worker.rating_signal.connect(self.grade.setText) self.steam_worker.rating_signal.connect(self.grade.setText)
@ -71,6 +76,8 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
self.lbl_grade.setVisible(False) self.lbl_grade.setVisible(False)
self.grade.setVisible(False) self.grade.setVisible(False)
self.non_asset_games = [i.app_name for i in self.core.get_non_asset_library_items()[0]]
self.install_size.setEnabled(False) self.install_size.setEnabled(False)
self.lbl_install_size.setEnabled(False) self.lbl_install_size.setEnabled(False)
self.install_path.setEnabled(False) self.install_path.setEnabled(False)
@ -83,6 +90,7 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
def update_game(self, app_name): def update_game(self, app_name):
self.game = self.core.get_game(app_name) self.game = self.core.get_game(app_name)
self.game_title.setText(f"<h2>{self.game.app_title}</h2>") self.game_title.setText(f"<h2>{self.game.app_title}</h2>")
pixmap = get_pixmap(app_name) pixmap = get_pixmap(app_name)
@ -96,6 +104,13 @@ class UninstalledInfo(QWidget, Ui_GameInfo):
self.install_size.setText("N/A") self.install_size.setText("N/A")
self.install_path.setText("N/A") self.install_path.setText("N/A")
if app_name in self.non_asset_games:
self.no_install_label.setVisible(True)
self.install_button.setEnabled(False)
else:
self.no_install_label.setVisible(False)
self.install_button.setEnabled(True)
if platform.system() != "Windows": if platform.system() != "Windows":
self.grade.setText(self.tr("Loading")) self.grade.setText(self.tr("Loading"))
self.steam_worker.set_app_name(app_name) self.steam_worker.set_app_name(app_name)

View file

@ -9,6 +9,7 @@ from rare import data_dir
from rare.components.tabs.games.game_widgets.base_installed_widget import BaseInstalledWidget 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.installing_game_widget import InstallingGameWidget
from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled
from rare.components.tabs.games.game_widgets.uninstalled_list_widget import ListWidgetUninstalled from rare.components.tabs.games.game_widgets.uninstalled_list_widget import ListWidgetUninstalled
from rare.utils.extra_widgets import FlowLayout from rare.utils.extra_widgets import FlowLayout
@ -34,7 +35,7 @@ class GameList(QStackedWidget):
self.core = core self.core = core
self.setObjectName("list_widget") self.setObjectName("list_widget")
self.offline = offline self.offline = offline
self.installing_widget = InstallingGameWidget()
self.settings = QSettings() self.settings = QSettings()
icon_view = self.settings.value("icon_view", True, bool) icon_view = self.settings.value("icon_view", True, bool)
self.procs = [] self.procs = []
@ -77,11 +78,16 @@ class GameList(QStackedWidget):
if not self.offline: if not self.offline:
self.bit32 = [i.app_name for i in self.core.get_game_and_dlc_list(True, "Win32")[0]] 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.mac_games = [i.app_name for i in self.core.get_game_and_dlc_list(True, "Mac")[0]]
self.no_assets = [i.app_name for i in self.core.get_non_asset_library_items()[0]]
else: else:
self.bit32 = [] self.bit32 = []
self.mac_games = [] self.mac_games = []
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)
self.installing_widget = InstallingGameWidget()
self.icon_layout.addWidget(self.installing_widget)
self.installing_widget.setVisible(False)
# Installed Games # Installed Games
for igame in self.installed: for igame in self.installed:
icon_widget, list_widget = self.add_installed_widget(igame) icon_widget, list_widget = self.add_installed_widget(igame)
@ -92,13 +98,13 @@ class GameList(QStackedWidget):
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(update_assets=not self.offline) games, self.dlcs = self.core.get_game_and_dlc_list(update_assets=not self.offline)
for game in sorted(games, key=lambda x: x.app_title): for game in games:
if not game.app_name in installed: if not game.app_name in installed:
self.uninstalled_games.append(game) self.uninstalled_games.append(game)
# add uninstalled games # add uninstalled games
self.uninstalled_games += self.core.get_non_asset_library_items()[0]
for game in self.uninstalled_games: for game in sorted(self.uninstalled_games, key=lambda x: x.app_title):
icon_widget, list_widget = self.add_uninstalled_widget(game) icon_widget, list_widget = self.add_uninstalled_widget(game)
self.icon_layout.addWidget(icon_widget) self.icon_layout.addWidget(icon_widget)
@ -124,6 +130,10 @@ class GameList(QStackedWidget):
if filter_games := self.settings.value("filter", "", str): if filter_games := self.settings.value("filter", "", str):
self.filter(filter_games) self.filter(filter_games)
def start_download(self, app_name):
self.installing_widget.set_game(self.core.get_game(app_name))
self.installing_widget.setVisible(True)
def add_uninstalled_widget(self, game): def add_uninstalled_widget(self, game):
pixmap = get_uninstalled_pixmap(game.app_name) pixmap = get_uninstalled_pixmap(game.app_name)
if pixmap.isNull(): if pixmap.isNull():
@ -256,6 +266,8 @@ class GameList(QStackedWidget):
w.setVisible(w.game.app_name in self.bit32) w.setVisible(w.game.app_name in self.bit32)
elif filter == "mac": elif filter == "mac":
w.setVisible(w.game.app_name in self.mac_games) w.setVisible(w.game.app_name in self.mac_games)
elif filter == "installable":
w.setVisible(w.game.app_name not in self.no_assets)
else: else:
# All visible # All visible
w.setVisible(True) w.setVisible(True)
@ -348,6 +360,7 @@ class GameList(QStackedWidget):
i_widget, list_widget = self.widgets[name] i_widget, list_widget = self.widgets[name]
self.icon_layout.addWidget(i_widget) self.icon_layout.addWidget(i_widget)
self.list_layout.addWidget(list_widget) self.list_layout.addWidget(list_widget)
self.installing_widget.setVisible(False)
def _update_games(self): def _update_games(self):
# new layouts to remove from old layout # new layouts to remove from old layout
@ -355,6 +368,7 @@ class GameList(QStackedWidget):
# QWidget().setLayout(self.list_layout) # QWidget().setLayout(self.list_layout)
list_layout = QVBoxLayout() list_layout = QVBoxLayout()
icon_layout.addWidget(self.installing_widget)
for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title): for igame in sorted(self.core.get_installed_list(), key=lambda x: x.title):
i_widget, l_widget = self.widgets[igame.app_name] i_widget, l_widget = self.widgets[igame.app_name]
icon_layout.addWidget(i_widget) icon_layout.addWidget(i_widget)

View file

@ -50,7 +50,7 @@ class GameWidgetInstalled(BaseInstalledWidget):
# Info Button # Info Button
self.menu_btn = QPushButton() self.menu_btn = QPushButton()
self.menu_btn.setIcon(icon("ei.info-circle", color="white")) self.menu_btn.setIcon(icon("ei.info-circle"))
# self.menu_btn.setObjectName("installed_menu_button") # self.menu_btn.setObjectName("installed_menu_button")
self.menu_btn.setIconSize(QSize(18, 18)) self.menu_btn.setIconSize(QSize(18, 18))
self.menu_btn.enterEvent = lambda x: self.info_label.setText("Information") self.menu_btn.enterEvent = lambda x: self.info_label.setText("Information")

View file

@ -1,4 +1,3 @@
import os
from logging import getLogger from logging import getLogger
from PyQt5.QtCore import QProcess, pyqtSignal, Qt from PyQt5.QtCore import QProcess, pyqtSignal, Qt
@ -34,7 +33,7 @@ class InstalledListWidget(BaseInstalledWidget):
self.image.setPixmap(self.pixmap) self.image.setPixmap(self.pixmap)
self.layout.addWidget(self.image) self.layout.addWidget(self.image)
play_icon = icon("ei.play", color="white") play_icon = icon("ei.play")
self.title_widget = QLabel(f"<h1>{self.igame.title}</h1>") self.title_widget = QLabel(f"<h1>{self.igame.title}</h1>")
self.app_name_label = QLabel(self.igame.app_name) self.app_name_label = QLabel(self.igame.app_name)
self.launch_button = QPushButton(play_icon, self.tr("Launch")) self.launch_button = QPushButton(play_icon, self.tr("Launch"))

View file

@ -0,0 +1,80 @@
from PyQt5.QtCore import Qt, QRect
from PyQt5.QtGui import QPaintEvent, QPainter, QPixmap, QPen, QFont, QColor
from PyQt5.QtWidgets import QGroupBox, QVBoxLayout, QLabel, QHBoxLayout, QWidget
from custom_legendary.models.game import Game
from rare.utils.utils import get_pixmap, get_uninstalled_pixmap, optimal_text_background, text_color_for_background
class InstallingGameWidget(QGroupBox):
def __init__(self):
super(InstallingGameWidget, self).__init__()
self.setObjectName("game_widget_icon")
self.setLayout(QVBoxLayout())
self.pixmap = QPixmap()
w = 200
# self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3), transformMode=Qt.SmoothTransformation)
self.image_widget = PaintWidget()
self.image_widget.setFixedSize(w, int(w * 4 / 3))
self.layout().addWidget(self.image_widget)
self.title_label = QLabel(f"<h4>Error</h4>")
self.title_label.setAutoFillBackground(False)
self.title_label.setWordWrap(True)
self.title_label.setFixedWidth(175)
minilayout = QHBoxLayout()
self.setObjectName("game_widget")
minilayout.addWidget(self.title_label)
self.layout().addLayout(minilayout)
def set_game(self, game: Game):
self.title_label.setText(f"<h4>{game.app_title}</h4>")
self.pixmap = get_pixmap(game.app_name)
w = 200
self.pixmap = self.pixmap.scaled(w, int(w * 4 / 3), transformMode=Qt.SmoothTransformation)
self.image_widget.set_game(self.pixmap, game.app_name)
class PaintWidget(QWidget):
def __init__(self):
super(PaintWidget, self).__init__()
def set_game(self, pixmap: QPixmap, app_name):
self.image = pixmap
self.setFixedSize(self.image.size())
self.new_image = get_uninstalled_pixmap(app_name)
self.status = 0
pixel_list = []
for x in range(self.image.width()):
for y in range(self.image.height()):
# convert pixmap to qimage, get pixel and remove alpha channel
pixel_list.append(self.image.toImage().pixelColor(x, y).getRgb()[:-1])
self.rgb_tuple = optimal_text_background(pixel_list)
def paintEvent(self, a0: QPaintEvent) -> None:
painter = QPainter()
painter.begin(self)
painter.drawPixmap(self.rect(), self.image)
w = self.image.width() * (1 - self.status / 100)
painter.drawPixmap(self.image.width() - w, 0, w, self.image.height(),
self.new_image.copy(QRect(self.image.width() - w, 0, w, self.image.height())))
# Draw Circle
pen = QPen(QColor(*self.rgb_tuple), 3)
painter.setPen(pen)
painter.setBrush(QColor(*self.rgb_tuple))
painter.drawEllipse(int(self.width() / 2) - 20, int(self.height() / 2) - 20, 40, 40)
# draw text
painter.setPen(QColor(*text_color_for_background(self.rgb_tuple)))
painter.setFont(QFont(None, 16))
painter.drawText(a0.rect(), Qt.AlignCenter, str(self.status) + "%")
painter.end()
def set_status(self, s: int):
self.status = s
self.repaint()

View file

@ -23,7 +23,7 @@ class ImportWidget(QWidget):
self.game_list = [i.app_name for i in self.core.get_game_list()] self.game_list = [i.app_name for i in self.core.get_game_list()]
self.main_layout = QHBoxLayout() self.main_layout = QHBoxLayout()
self.back_button = QPushButton(icon("mdi.keyboard-backspace", color="white"), self.tr("Back")) self.back_button = QPushButton(icon("mdi.keyboard-backspace"), self.tr("Back"))
self.right_layout = QVBoxLayout() self.right_layout = QVBoxLayout()
self.right_layout.addWidget(self.back_button) self.right_layout.addWidget(self.back_button)
self.right_layout.addStretch(1) self.right_layout.addStretch(1)

View file

@ -42,7 +42,7 @@ class LegendarySettings(QStackedWidget, Ui_legendary_settings):
self.back_button.clicked.connect(lambda: self.setCurrentIndex(0)) self.back_button.clicked.connect(lambda: self.setCurrentIndex(0))
self.path_info.setText(self.tr(r"EGL path is at C:\ProgramData\Epic\EpicGamesLauncher\Data\Manifests")) self.path_info.setText(self.tr("EGL path is at C:\\ProgramData\\Epic\\EpicGamesLauncher\\Data\\Manifests"))
path = os.path.expanduser("~/") path = os.path.expanduser("~/")
if self.core.egl.programdata_path: if self.core.egl.programdata_path:
path = self.core.egl.programdata_path path = self.core.egl.programdata_path

View file

@ -45,6 +45,7 @@ class RareSettings(QWidget, Ui_RareSettings):
language = self.settings.value("language", get_lang(), type=str) language = self.settings.value("language", get_lang(), type=str)
self.logdir = os.path.join(cache_dir, "logs") self.logdir = os.path.join(cache_dir, "logs")
# Select Image directory # Select Image directory
# self.img_dir = PathEdit(self.img_dir_path, file_type=QFileDialog.DirectoryOnly, save_func=self.save_path) # self.img_dir = PathEdit(self.img_dir_path, file_type=QFileDialog.DirectoryOnly, save_func=self.save_path)
# self.img_dir_layout.addWidget(self.img_dir) # self.img_dir_layout.addWidget(self.img_dir)

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

View file

@ -14,6 +14,7 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_GameInfo(object): class Ui_GameInfo(object):
def setupUi(self, GameInfo): def setupUi(self, GameInfo):
GameInfo.setObjectName("GameInfo") GameInfo.setObjectName("GameInfo")
GameInfo.resize(571, 326)
self.layout_game_info = QtWidgets.QGridLayout(GameInfo) self.layout_game_info = QtWidgets.QGridLayout(GameInfo)
self.layout_game_info.setObjectName("layout_game_info") self.layout_game_info.setObjectName("layout_game_info")
self.layout_game_info_form = QtWidgets.QGridLayout() self.layout_game_info_form = QtWidgets.QGridLayout()
@ -182,15 +183,20 @@ class Ui_GameInfo(object):
self.install_button.setStyleSheet("") self.install_button.setStyleSheet("")
self.install_button.setObjectName("install_button") self.install_button.setObjectName("install_button")
self.uninstalled_layout.addWidget(self.install_button) self.uninstalled_layout.addWidget(self.install_button)
self.no_install_label = QtWidgets.QLabel(self.uninstalled_page)
self.no_install_label.setWordWrap(True)
self.no_install_label.setObjectName("no_install_label")
self.uninstalled_layout.addWidget(self.no_install_label)
self.game_actions_stack.addWidget(self.uninstalled_page) self.game_actions_stack.addWidget(self.uninstalled_page)
self.layout_game_info_form.addWidget(self.game_actions_stack, 6, 1, 1, 1, QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.layout_game_info_form.addWidget(self.game_actions_stack, 6, 1, 1, 1,
QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
self.layout_game_info.addLayout(self.layout_game_info_form, 2, 1, 1, 1) self.layout_game_info.addLayout(self.layout_game_info_form, 2, 1, 1, 1)
self.image = QtWidgets.QLabel(GameInfo) self.image = QtWidgets.QLabel(GameInfo)
self.image.setFrameShape(QtWidgets.QFrame.StyledPanel) self.image.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.image.setFrameShadow(QtWidgets.QFrame.Sunken) self.image.setFrameShadow(QtWidgets.QFrame.Sunken)
self.image.setText("") self.image.setText("")
self.image.setObjectName("image") self.image.setObjectName("image")
self.layout_game_info.addWidget(self.image, 2, 0, 1, 1, QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop) self.layout_game_info.addWidget(self.image, 2, 0, 1, 1, QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
self.game_title = QtWidgets.QLabel(GameInfo) self.game_title = QtWidgets.QLabel(GameInfo)
self.game_title.setText("error") self.game_title.setText("error")
self.game_title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse) self.game_title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
@ -198,7 +204,7 @@ class Ui_GameInfo(object):
self.layout_game_info.addWidget(self.game_title, 0, 0, 1, 3) self.layout_game_info.addWidget(self.game_title, 0, 0, 1, 3)
self.retranslateUi(GameInfo) self.retranslateUi(GameInfo)
self.game_actions_stack.setCurrentIndex(0) self.game_actions_stack.setCurrentIndex(1)
self.verify_widget.setCurrentIndex(0) self.verify_widget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(GameInfo) QtCore.QMetaObject.connectSlotsByName(GameInfo)
@ -216,6 +222,8 @@ class Ui_GameInfo(object):
self.repair_button.setText(_translate("GameInfo", "Repair Instalation")) self.repair_button.setText(_translate("GameInfo", "Repair Instalation"))
self.uninstall_button.setText(_translate("GameInfo", "Uninstall Game")) self.uninstall_button.setText(_translate("GameInfo", "Uninstall Game"))
self.install_button.setText(_translate("GameInfo", "Install Game")) self.install_button.setText(_translate("GameInfo", "Install Game"))
self.no_install_label.setText(
_translate("GameInfo", "It is not possible to install the Game. It could be from a third party store"))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -2,16 +2,24 @@
<ui version="4.0"> <ui version="4.0">
<class>GameInfo</class> <class>GameInfo</class>
<widget class="QWidget" name="GameInfo"> <widget class="QWidget" name="GameInfo">
<property name="windowTitle"> <property name="geometry">
<string>Game Info</string> <rect>
</property> <x>0</x>
<layout class="QGridLayout" name="layout_game_info"> <y>0</y>
<item row="2" column="1"> <width>571</width>
<layout class="QGridLayout" name="layout_game_info_form"> <height>326</height>
<property name="leftMargin"> </rect>
<number>6</number>
</property> </property>
<property name="topMargin"> <property name="windowTitle">
<string>Game Info</string>
</property>
<layout class="QGridLayout" name="layout_game_info">
<item row="2" column="1">
<layout class="QGridLayout" name="layout_game_info_form">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number> <number>6</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
@ -248,29 +256,29 @@
</size> </size>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="installed_page"> <widget class="QWidget" name="installed_page">
<layout class="QVBoxLayout" name="installed_layout"> <layout class="QVBoxLayout" name="installed_layout">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="topMargin"> <property name="topMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="rightMargin"> <property name="rightMargin">
<number>0</number> <number>0</number>
</property> </property>
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item>
<widget class="QStackedWidget" name="verify_widget"> <widget class="QStackedWidget" name="verify_widget">
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>0</number>
</property> </property>
<widget class="QWidget" name="page_verify_button"> <widget class="QWidget" name="page_verify_button">
<layout class="QVBoxLayout" name="layout_verify_button"> <layout class="QVBoxLayout" name="layout_verify_button">
<property name="spacing"> <property name="spacing">
<number>0</number> <number>0</number>
</property> </property>
@ -343,18 +351,28 @@
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="uninstalled_page"> <widget class="QWidget" name="uninstalled_page">
<layout class="QVBoxLayout" name="uninstalled_layout"> <layout class="QVBoxLayout" name="uninstalled_layout">
<item> <item>
<widget class="QPushButton" name="install_button"> <widget class="QPushButton" name="install_button">
<property name="styleSheet"> <property name="styleSheet">
<string notr="true"/> <string notr="true"/>
</property> </property>
<property name="text"> <property name="text">
<string>Install Game</string> <string>Install Game</string>
</property> </property>
</widget> </widget>
</item> </item>
</layout> <item>
<widget class="QLabel" name="no_install_label">
<property name="text">
<string>It is not possible to install the Game. It could be from a third party store</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</widget> </widget>
</item> </item>

View file

@ -14,51 +14,13 @@ from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_RareSettings(object): class Ui_RareSettings(object):
def setupUi(self, RareSettings): def setupUi(self, RareSettings):
RareSettings.setObjectName("RareSettings") RareSettings.setObjectName("RareSettings")
RareSettings.resize(544, 532)
self.rare_layout = QtWidgets.QGridLayout(RareSettings) RareSettings.resize(694, 532)
self.rare_layout.setObjectName("rare_layout") self.gridLayout = QtWidgets.QGridLayout(RareSettings)
self.rpc_layout = QtWidgets.QVBoxLayout() self.gridLayout.setObjectName("gridLayout")
self.rpc_layout.setObjectName("rpc_layout") self.verticalLayout_4 = QtWidgets.QVBoxLayout()
self.rare_layout.addLayout(self.rpc_layout, 1, 1, 1, 1) self.verticalLayout_4.setObjectName("verticalLayout_4")
self.groupBox = QtWidgets.QGroupBox(RareSettings)
self.groupBox.setObjectName("groupBox")
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox)
self.verticalLayout.setObjectName("verticalLayout")
self.desktop_link = QtWidgets.QPushButton(self.groupBox)
self.desktop_link.setObjectName("desktop_link")
self.verticalLayout.addWidget(self.desktop_link)
self.startmenu_link = QtWidgets.QPushButton(self.groupBox)
self.startmenu_link.setObjectName("startmenu_link")
self.verticalLayout.addWidget(self.startmenu_link)
self.rare_layout.addWidget(self.groupBox, 2, 1, 1, 1, QtCore.Qt.AlignTop)
self.settings_group = QtWidgets.QGroupBox(RareSettings)
self.settings_group.setObjectName("settings_group")
self.behavior_layout = QtWidgets.QGridLayout(self.settings_group)
self.behavior_layout.setObjectName("behavior_layout")
self.confirm_start = QtWidgets.QCheckBox(self.settings_group)
self.confirm_start.setObjectName("confirm_start")
self.behavior_layout.addWidget(self.confirm_start, 2, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.behavior_layout.addItem(spacerItem, 2, 1, 2, 1)
self.auto_sync_cloud = QtWidgets.QCheckBox(self.settings_group)
self.auto_sync_cloud.setObjectName("auto_sync_cloud")
self.behavior_layout.addWidget(self.auto_sync_cloud, 3, 0, 1, 1)
self.sys_tray = QtWidgets.QCheckBox(self.settings_group)
self.sys_tray.setObjectName("sys_tray")
self.behavior_layout.addWidget(self.sys_tray, 0, 0, 1, 1)
self.save_size = QtWidgets.QCheckBox(self.settings_group)
self.save_size.setObjectName("save_size")
self.behavior_layout.addWidget(self.save_size, 5, 0, 1, 1)
self.notification = QtWidgets.QCheckBox(self.settings_group)
self.notification.setObjectName("notification")
self.behavior_layout.addWidget(self.notification, 4, 0, 1, 1)
self.auto_update = QtWidgets.QCheckBox(self.settings_group)
self.auto_update.setObjectName("auto_update")
self.behavior_layout.addWidget(self.auto_update, 1, 0, 1, 1)
self.log_games = QtWidgets.QCheckBox(self.settings_group)
self.log_games.setObjectName("log_games")
self.behavior_layout.addWidget(self.log_games, 6, 0, 1, 1)
self.rare_layout.addWidget(self.settings_group, 2, 0, 1, 1, QtCore.Qt.AlignTop)
self.log_dir_group = QtWidgets.QGroupBox(RareSettings) self.log_dir_group = QtWidgets.QGroupBox(RareSettings)
self.log_dir_group.setObjectName("log_dir_group") self.log_dir_group.setObjectName("log_dir_group")
self.log_dir_layout = QtWidgets.QVBoxLayout(self.log_dir_group) self.log_dir_layout = QtWidgets.QVBoxLayout(self.log_dir_group)
@ -70,11 +32,36 @@ class Ui_RareSettings(object):
self.log_dir_clean_button.setObjectName("log_dir_clean_button") self.log_dir_clean_button.setObjectName("log_dir_clean_button")
self.log_dir_layout.addWidget(self.log_dir_clean_button) self.log_dir_layout.addWidget(self.log_dir_clean_button)
self.log_dir_size_label = QtWidgets.QLabel(self.log_dir_group) self.log_dir_size_label = QtWidgets.QLabel(self.log_dir_group)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Maximum)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.log_dir_size_label.sizePolicy().hasHeightForWidth())
self.log_dir_size_label.setText("") self.log_dir_size_label.setText("")
self.log_dir_size_label.setWordWrap(True) self.log_dir_size_label.setWordWrap(True)
self.log_dir_size_label.setObjectName("log_dir_size_label") self.log_dir_size_label.setObjectName("log_dir_size_label")
self.log_dir_layout.addWidget(self.log_dir_size_label) self.log_dir_layout.addWidget(self.log_dir_size_label)
self.rare_layout.addWidget(self.log_dir_group, 0, 1, 1, 1, QtCore.Qt.AlignTop)
self.verticalLayout_4.addWidget(self.log_dir_group)
self.rpc_layout = QtWidgets.QVBoxLayout()
self.rpc_layout.setObjectName("rpc_layout")
self.verticalLayout_4.addLayout(self.rpc_layout)
self.groupBox = QtWidgets.QGroupBox(RareSettings)
self.groupBox.setObjectName("groupBox")
self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox)
self.verticalLayout.setObjectName("verticalLayout")
self.desktop_link = QtWidgets.QPushButton(self.groupBox)
self.desktop_link.setObjectName("desktop_link")
self.verticalLayout.addWidget(self.desktop_link)
self.startmenu_link = QtWidgets.QPushButton(self.groupBox)
self.startmenu_link.setObjectName("startmenu_link")
self.verticalLayout.addWidget(self.startmenu_link)
self.verticalLayout_4.addWidget(self.groupBox)
self.gridLayout.addLayout(self.verticalLayout_4, 0, 1, 1, 1)
self.verticalLayout_3 = QtWidgets.QVBoxLayout()
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.interface_group = QtWidgets.QGroupBox(RareSettings) self.interface_group = QtWidgets.QGroupBox(RareSettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
@ -84,6 +71,16 @@ class Ui_RareSettings(object):
self.interface_group.setObjectName("interface_group") self.interface_group.setObjectName("interface_group")
self.interface_layout = QtWidgets.QGridLayout(self.interface_group) self.interface_layout = QtWidgets.QGridLayout(self.interface_group)
self.interface_layout.setObjectName("interface_layout") self.interface_layout.setObjectName("interface_layout")
self.style_label = QtWidgets.QLabel(self.interface_group)
self.style_label.setObjectName("style_label")
self.interface_layout.addWidget(self.style_label, 2, 0, 1, 1, QtCore.Qt.AlignRight)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.interface_layout.addItem(spacerItem, 1, 2, 1, 1)
self.lang_select = QtWidgets.QComboBox(self.interface_group)
self.lang_select.setObjectName("lang_select")
self.interface_layout.addWidget(self.lang_select, 0, 1, 1, 1)
self.color_select = QtWidgets.QComboBox(self.interface_group) self.color_select = QtWidgets.QComboBox(self.interface_group)
self.color_select.setObjectName("color_select") self.color_select.setObjectName("color_select")
self.color_select.addItem("") self.color_select.addItem("")
@ -104,23 +101,40 @@ class Ui_RareSettings(object):
self.interface_info.setWordWrap(True) self.interface_info.setWordWrap(True)
self.interface_info.setObjectName("interface_info") self.interface_info.setObjectName("interface_info")
self.interface_layout.addWidget(self.interface_info, 3, 0, 1, 3) self.interface_layout.addWidget(self.interface_info, 3, 0, 1, 3)
self.lang_label = QtWidgets.QLabel(self.interface_group)
self.lang_label.setObjectName("lang_label") self.verticalLayout_3.addWidget(self.interface_group)
self.interface_layout.addWidget(self.lang_label, 0, 0, 1, 1, QtCore.Qt.AlignRight) self.settings_group = QtWidgets.QGroupBox(RareSettings)
self.lang_select = QtWidgets.QComboBox(self.interface_group) self.settings_group.setObjectName("settings_group")
self.lang_select.setObjectName("lang_select") self.behavior_layout = QtWidgets.QGridLayout(self.settings_group)
self.interface_layout.addWidget(self.lang_select, 0, 1, 1, 1) self.behavior_layout.setObjectName("behavior_layout")
self.color_label = QtWidgets.QLabel(self.interface_group) self.save_size = QtWidgets.QCheckBox(self.settings_group)
self.color_label.setObjectName("color_label") self.save_size.setObjectName("save_size")
self.interface_layout.addWidget(self.color_label, 1, 0, 1, 1, QtCore.Qt.AlignRight) self.behavior_layout.addWidget(self.save_size, 5, 0, 1, 1)
self.rare_layout.addWidget(self.interface_group, 1, 0, 1, 1, QtCore.Qt.AlignTop) self.notification = QtWidgets.QCheckBox(self.settings_group)
self.img_dir_group = QtWidgets.QGroupBox(RareSettings) self.notification.setObjectName("notification")
self.img_dir_group.setObjectName("img_dir_group") self.behavior_layout.addWidget(self.notification, 4, 0, 1, 1)
self.img_dir_layout = QtWidgets.QVBoxLayout(self.img_dir_group) self.auto_sync_cloud = QtWidgets.QCheckBox(self.settings_group)
self.img_dir_layout.setObjectName("img_dir_layout") self.auto_sync_cloud.setObjectName("auto_sync_cloud")
self.rare_layout.addWidget(self.img_dir_group, 0, 0, 1, 1, QtCore.Qt.AlignTop) self.behavior_layout.addWidget(self.auto_sync_cloud, 3, 0, 1, 1)
self.auto_update = QtWidgets.QCheckBox(self.settings_group)
self.auto_update.setObjectName("auto_update")
self.behavior_layout.addWidget(self.auto_update, 1, 0, 1, 1)
self.sys_tray = QtWidgets.QCheckBox(self.settings_group)
self.sys_tray.setObjectName("sys_tray")
self.behavior_layout.addWidget(self.sys_tray, 0, 0, 1, 1)
self.log_games = QtWidgets.QCheckBox(self.settings_group)
self.log_games.setObjectName("log_games")
self.behavior_layout.addWidget(self.log_games, 6, 0, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.behavior_layout.addItem(spacerItem1, 2, 1, 2, 1)
self.confirm_start = QtWidgets.QCheckBox(self.settings_group)
self.confirm_start.setObjectName("confirm_start")
self.behavior_layout.addWidget(self.confirm_start, 2, 0, 1, 1)
self.verticalLayout_3.addWidget(self.settings_group)
self.gridLayout.addLayout(self.verticalLayout_3, 0, 0, 1, 1)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.rare_layout.addItem(spacerItem2, 3, 0, 1, 2) self.gridLayout.addItem(spacerItem2, 1, 0, 1, 2)
self.retranslateUi(RareSettings) self.retranslateUi(RareSettings)
QtCore.QMetaObject.connectSlotsByName(RareSettings) QtCore.QMetaObject.connectSlotsByName(RareSettings)
@ -128,20 +142,14 @@ class Ui_RareSettings(object):
def retranslateUi(self, RareSettings): def retranslateUi(self, RareSettings):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
RareSettings.setWindowTitle(_translate("RareSettings", "RareSettings")) RareSettings.setWindowTitle(_translate("RareSettings", "RareSettings"))
self.groupBox.setTitle(_translate("RareSettings", "Shortcuts"))
self.desktop_link.setText(_translate("RareSettings", "Create Desktop link"))
self.startmenu_link.setText(_translate("RareSettings", "Create start menu link"))
self.settings_group.setTitle(_translate("RareSettings", "Behavior"))
self.confirm_start.setText(_translate("RareSettings", "Confirm game launch"))
self.auto_sync_cloud.setText(_translate("RareSettings", "Automatically sync with cloud"))
self.sys_tray.setText(_translate("RareSettings", "Exit to System tray"))
self.save_size.setText(_translate("RareSettings", "Restore window size on application startup"))
self.notification.setText(_translate("RareSettings", "Show notification on download completion"))
self.auto_update.setText(_translate("RareSettings", "Update games on application startup"))
self.log_games.setText(_translate("RareSettings", "Open console for game output"))
self.log_dir_group.setTitle(_translate("RareSettings", "Logs")) self.log_dir_group.setTitle(_translate("RareSettings", "Logs"))
self.log_dir_open_button.setText(_translate("RareSettings", "Open Log directory")) self.log_dir_open_button.setText(_translate("RareSettings", "Open Log directory"))
self.log_dir_clean_button.setText(_translate("RareSettings", "Clean Log directory")) self.log_dir_clean_button.setText(_translate("RareSettings", "Clean Log directory"))
self.groupBox.setTitle(_translate("RareSettings", "Shortcuts"))
self.desktop_link.setText(_translate("RareSettings", "Create Desktop link"))
self.startmenu_link.setText(_translate("RareSettings", "Create start menu link"))
self.interface_group.setTitle(_translate("RareSettings", "Interface")) self.interface_group.setTitle(_translate("RareSettings", "Interface"))
self.color_select.setItemText(0, _translate("RareSettings", "None")) self.color_select.setItemText(0, _translate("RareSettings", "None"))
self.style_label.setText(_translate("RareSettings", "Style Sheet")) self.style_label.setText(_translate("RareSettings", "Style Sheet"))
@ -149,7 +157,17 @@ class Ui_RareSettings(object):
self.interface_info.setText(_translate("RareSettings", "Restart Rare to apply.")) self.interface_info.setText(_translate("RareSettings", "Restart Rare to apply."))
self.lang_label.setText(_translate("RareSettings", "Language")) self.lang_label.setText(_translate("RareSettings", "Language"))
self.color_label.setText(_translate("RareSettings", "Color Scheme")) self.color_label.setText(_translate("RareSettings", "Color Scheme"))
self.img_dir_group.setTitle(_translate("RareSettings", "Image Cache Directory"))
self.interface_info.setText(_translate("RareSettings", "Restart Rare to apply."))
self.settings_group.setTitle(_translate("RareSettings", "Behavior"))
self.save_size.setText(_translate("RareSettings", "Restore window size on application startup"))
self.notification.setText(_translate("RareSettings", "Show notification on download completion"))
self.auto_sync_cloud.setText(_translate("RareSettings", "Automatically sync with cloud"))
self.auto_update.setText(_translate("RareSettings", "Update games on application startup"))
self.sys_tray.setText(_translate("RareSettings", "Exit to System tray"))
self.log_games.setText(_translate("RareSettings", "Show console for game debug"))
self.confirm_start.setText(_translate("RareSettings", "Confirm game launch"))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -13,134 +13,251 @@
<property name="windowTitle"> <property name="windowTitle">
<string>RareSettings</string> <string>RareSettings</string>
</property> </property>
<layout class="QGridLayout" name="rare_layout">
<item row="1" column="1"> <layout class="QGridLayout" name="gridLayout">
<layout class="QVBoxLayout" name="rpc_layout"/> <item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QGroupBox" name="log_dir_group">
<property name="title">
<string>Logs</string>
</property>
<layout class="QVBoxLayout" name="log_dir_layout">
<item>
<widget class="QPushButton" name="log_dir_open_button">
<property name="text">
<string>Open Log directory</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="log_dir_clean_button">
<property name="text">
<string>Clean Log directory</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="log_dir_size_label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string notr="true"/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="rpc_layout"/>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Shortcuts</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="desktop_link">
<property name="text">
<string>Create Desktop link</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="startmenu_link">
<property name="text">
<string>Create start menu link</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item> </item>
<item row="2" column="1" alignment="Qt::AlignTop"> <item row="0" column="0">
<widget class="QGroupBox" name="groupBox"> <layout class="QVBoxLayout" name="verticalLayout_3">
<property name="title"> <item>
<string>Shortcuts</string> <widget class="QGroupBox" name="interface_group">
</property> <property name="sizePolicy">
<layout class="QVBoxLayout" name="verticalLayout"> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<item> <horstretch>0</horstretch>
<widget class="QPushButton" name="desktop_link"> <verstretch>0</verstretch>
<property name="text"> </sizepolicy>
<string>Create Desktop link</string> </property>
</property> <property name="title">
</widget> <string>Interface</string>
</item> </property>
<item> <layout class="QGridLayout" name="interface_layout">
<widget class="QPushButton" name="startmenu_link"> <item row="2" column="0" alignment="Qt::AlignRight">
<property name="text"> <widget class="QLabel" name="style_label">
<string>Create start menu link</string> <property name="text">
</property> <string>Style Sheet</string>
</widget> </property>
</item> </widget>
</layout> </item>
</widget> <item row="1" column="2">
</item> <spacer name="interface_hspacer">
<item row="2" column="0" alignment="Qt::AlignTop"> <property name="orientation">
<widget class="QGroupBox" name="settings_group"> <enum>Qt::Horizontal</enum>
<property name="title"> </property>
<string>Behavior</string> <property name="sizeHint" stdset="0">
</property> <size>
<layout class="QGridLayout" name="behavior_layout"> <width>40</width>
<item row="2" column="0"> <height>20</height>
<widget class="QCheckBox" name="confirm_start"> </size>
<property name="text"> </property>
<string>Confirm game launch</string> </spacer>
</property> </item>
</widget> <item row="0" column="1">
</item> <widget class="QComboBox" name="lang_select"/>
<item row="2" column="1" rowspan="2"> </item>
<spacer name="settings_hspacer"> <item row="1" column="1">
<property name="orientation"> <widget class="QComboBox" name="color_select">
<enum>Qt::Horizontal</enum> <item>
</property> <property name="text">
<property name="sizeHint" stdset="0"> <string>None</string>
<size> </property>
<width>40</width> </item>
<height>20</height> </widget>
</size> </item>
</property> <item row="2" column="1">
</spacer> <widget class="QComboBox" name="style_select">
</item> <item>
<item row="3" column="0"> <property name="text">
<widget class="QCheckBox" name="auto_sync_cloud"> <string>None</string>
<property name="text"> </property>
<string>Automatically sync with cloud</string> </item>
</property> </widget>
</widget> </item>
</item> <item row="0" column="0" alignment="Qt::AlignRight">
<item row="0" column="0"> <widget class="QLabel" name="lang_label">
<widget class="QCheckBox" name="sys_tray"> <property name="text">
<property name="text"> <string>Language</string>
<string>Exit to System tray</string> </property>
</property> </widget>
</widget> </item>
</item> <item row="1" column="0" alignment="Qt::AlignRight">
<item row="5" column="0"> <widget class="QLabel" name="color_label">
<widget class="QCheckBox" name="save_size"> <property name="text">
<property name="text"> <string>Color Scheme</string>
<string>Restore window size on application startup</string> </property>
</property> </widget>
</widget> </item>
</item> <item row="3" column="0" colspan="3">
<item row="4" column="0"> <widget class="QLabel" name="interface_info">
<widget class="QCheckBox" name="notification"> <property name="font">
<property name="text"> <font>
<string>Show notification on download completion</string> <italic>true</italic>
</property> </font>
</widget> </property>
</item> <property name="text">
<item row="1" column="0"> <string>Restart Rare to apply.</string>
<widget class="QCheckBox" name="auto_update"> </property>
<property name="text"> <property name="wordWrap">
<string>Update games on application startup</string> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="0"> </layout>
<widget class="QCheckBox" name="log_games"> </widget>
<property name="text"> </item>
<string>Open console for game output</string> <item>
</property> <widget class="QGroupBox" name="settings_group">
</widget> <property name="title">
</item> <string>Behavior</string>
</layout> </property>
</widget> <layout class="QGridLayout" name="behavior_layout">
</item> <item row="5" column="0">
<item row="0" column="1" alignment="Qt::AlignTop"> <widget class="QCheckBox" name="save_size">
<widget class="QGroupBox" name="log_dir_group"> <property name="text">
<property name="title"> <string>Restore window size on application startup</string>
<string>Logs</string> </property>
</property> </widget>
<layout class="QVBoxLayout" name="log_dir_layout"> </item>
<item> <item row="4" column="0">
<widget class="QPushButton" name="log_dir_open_button"> <widget class="QCheckBox" name="notification">
<property name="text"> <property name="text">
<string>Open Log directory</string> <string>Show notification on download completion</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="3" column="0">
<widget class="QPushButton" name="log_dir_clean_button"> <widget class="QCheckBox" name="auto_sync_cloud">
<property name="text"> <property name="text">
<string>Clean Log directory</string> <string>Automatically sync with cloud</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="1" column="0">
<widget class="QLabel" name="log_dir_size_label"> <widget class="QCheckBox" name="auto_update">
<property name="text"> <property name="text">
<string notr="true"/> <string>Update games on application startup</string>
</property> </property>
<property name="wordWrap"> </widget>
<bool>true</bool> </item>
</property> <item row="0" column="0">
</widget> <widget class="QCheckBox" name="sys_tray">
</item> <property name="text">
<string>Exit to System tray</string>
</property>
</widget>
</item>
<item row="6" column="0">
<widget class="QCheckBox" name="log_games">
<property name="text">
<string>Show console for game debug</string>
</property>
</widget>
</item>
<item row="2" column="1" rowspan="2">
<spacer name="settings_hspacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="confirm_start">
<property name="text">
<string>Confirm game launch</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item row="1" column="0" colspan="2">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View file

@ -88,6 +88,8 @@ class FlowLayout(QLayout):
lineheight = 0 lineheight = 0
for item in self._items: for item in self._items:
widget = item.widget() widget = item.widget()
if not widget.isVisible():
continue
hspace = self.horizontalSpacing() hspace = self.horizontalSpacing()
if hspace == -1: if hspace == -1:
hspace = widget.style().layoutSpacing( hspace = widget.style().layoutSpacing(
@ -229,9 +231,9 @@ class SelectViewWidget(QWidget):
self.list_view = QPushButton() self.list_view = QPushButton()
if icon_view: if icon_view:
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="orange")) self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="orange"))
self.list_view.setIcon(icon("fa5s.list", color="white")) self.list_view.setIcon(icon("fa5s.list"))
else: else:
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="white")) self.icon_view_button.setIcon(icon("mdi.view-grid-outline"))
self.list_view.setIcon(icon("fa5s.list", color="orange")) self.list_view.setIcon(icon("fa5s.list", color="orange"))
self.icon_view_button.clicked.connect(self.icon) self.icon_view_button.clicked.connect(self.icon)
@ -248,12 +250,12 @@ class SelectViewWidget(QWidget):
def icon(self): def icon(self):
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="orange")) self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="orange"))
self.list_view.setIcon(icon("fa5s.list", color="white")) self.list_view.setIcon(icon("fa5s.list"))
self.icon_view = False self.icon_view = False
self.toggled.emit() self.toggled.emit()
def list(self): def list(self):
self.icon_view_button.setIcon(icon("mdi.view-grid-outline", color="white")) self.icon_view_button.setIcon(icon("mdi.view-grid-outline"))
self.list_view.setIcon(icon("fa5s.list", color="orange")) self.list_view.setIcon(icon("fa5s.list", color="orange"))
self.icon_view = True self.icon_view = True
self.toggled.emit() self.toggled.emit()

View file

@ -87,6 +87,13 @@ def uninstall(app_name: str, core: LegendaryCore, options=None):
except Exception as e: except Exception as e:
logger.warning(f'Removing game failed: {e!r}, please remove {igame.install_path} manually.') logger.warning(f'Removing game failed: {e!r}, please remove {igame.install_path} manually.')
logger.info("Removing sections in config file")
if core.lgd.config.has_section(app_name):
core.lgd.config.remove_section(app_name)
if core.lgd.config.has_section(app_name + ".env"):
core.lgd.config.remove_section(app_name + ".env")
core.lgd.save_config()
class VerifyThread(QThread): class VerifyThread(QThread):
status = pyqtSignal(tuple) status = pyqtSignal(tuple)

View file

@ -46,7 +46,9 @@ def get_rating(app_name: str, core: LegendaryCore):
grades = {} grades = {}
if not grades.get(app_name): if not grades.get(app_name):
steam_id = get_steam_id(core.get_game(app_name).app_title) game = core.get_game(app_name)
steam_id = get_steam_id(game.app_title)
grade = get_grade(steam_id) grade = get_grade(steam_id)
grades[app_name] = { grades[app_name] = {
"steam_id": steam_id, "steam_id": steam_id,
@ -118,7 +120,6 @@ def get_steam_id(title: str):
return 0 return 0
def check_time(): # this function check if it's time to update def check_time(): # this function check if it's time to update
global file global file
text = open(file, 'r') text = open(file, 'r')

View file

@ -1,9 +1,11 @@
import json import json
import math
import os import os
import platform import platform
import shutil import shutil
import sys import sys
from logging import getLogger from logging import getLogger
from typing import Tuple
import requests import requests
from PIL import Image, UnidentifiedImageError from PIL import Image, UnidentifiedImageError
@ -21,7 +23,7 @@ from rare import languages_path, resources_path, image_dir
from custom_legendary.core import LegendaryCore from custom_legendary.core import LegendaryCore
logger = getLogger("Utils") logger = getLogger("Utils")
s = QSettings("Rare", "Rare") settings = QSettings("Rare", "Rare")
@ -35,7 +37,10 @@ def download_images(signal: pyqtSignal, core: LegendaryCore):
dlc_list = [] dlc_list = []
for i in dlcs.values(): for i in dlcs.values():
dlc_list.append(i[0]) dlc_list.append(i[0])
game_list = games + dlc_list
no_assets = core.get_non_asset_library_items()[0]
game_list = games + dlc_list + no_assets
for i, game in enumerate(game_list): for i, game in enumerate(game_list):
try: try:
download_image(game) download_image(game)
@ -377,3 +382,38 @@ def get_uninstalled_pixmap(app_name: str) -> QPixmap:
pixmap = QPixmap() pixmap = QPixmap()
return pixmap return pixmap
def optimal_text_background(image: list) -> Tuple[int, int, int]:
"""
Finds an optimal background color for text on the image by calculating the
average color of the image and inverting it.
The image list is supposed to be a one-dimensional list of arbitrary length
containing RGB tuples, ranging from 0 to 255.
"""
# cursed, I know
average = map(lambda value: value / len(image), map(sum, zip(*image)))
inverted = map(lambda value: 255 - value, average)
return tuple(inverted)
def text_color_for_background(background: Tuple[int, int, int]) -> Tuple[int,
int,
int]:
"""
Calculates whether a black or white text color would fit better for the
given background, and returns that color. This is done by calculating the
luminance and simple comparing of bounds
"""
# see https://alienryderflex.com/hsp.html
(red, green, blue) = background
luminance = math.sqrt(
0.299 * red ** 2 +
0.587 * green ** 2 +
0.114 * blue ** 2)
if luminance < 127:
return 255, 255, 255
else:
return 0, 0, 0

View file

@ -2,7 +2,6 @@ requests
Pillow Pillow
PyQt5 PyQt5
QtAwesome QtAwesome
notify-py
psutil psutil
pypresence pypresence
pywin32; platform_system == "Windows" pywin32; platform_system == "Windows"

View file

@ -14,7 +14,6 @@ requirements = [
"wheel", "wheel",
"PyQt5", "PyQt5",
"QtAwesome", "QtAwesome",
"notify-py",
"psutil", "psutil",
"pypresence", "pypresence",
'pywin32; platform_system == "Windows"' 'pywin32; platform_system == "Windows"'