1
0
Fork 0
mirror of synced 2024-06-02 10:44:40 +12:00

Merge branch 'main' into patch-1

This commit is contained in:
ChemicalXandco 2021-05-21 16:06:20 +01:00 committed by GitHub
commit efba9362c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
72 changed files with 7665 additions and 1854 deletions

View file

@ -1,9 +1,6 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
name: Bug report about: Create a report to help us improve title: ''
labels: bug assignees: ''
---
@ -12,6 +9,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@ -24,8 +22,9 @@ A clear and concise description of what you expected to happen.
If applicable, add screenshots to help explain your problem.
**System information (please complete the following information):**
- OS (e.g. Ubuntu 20.04 or Windows 10)
- Python version
- OS (e.g. Ubuntu 20.04 or Windows 10)
- Python version
**Additional context**
Add any other context about the problem here.

View file

@ -1,13 +1,12 @@
name: New Release
on:
release:
types: [ published ]
jobs:
pypy-deploy:
if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
@ -29,6 +28,7 @@ jobs:
twine upload dist/*
aur-publish:
if: "!github.event.release.prerelease"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
@ -71,7 +71,7 @@ jobs:
overwrite: true
deb-package:
runs-on: ubuntu-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Deps
@ -84,10 +84,10 @@ jobs:
run: |
python3 setup.py sdist
python3 setup.py --command-packages=stdeb.command bdist_deb
- name: move file
run: mv deb_dist/*.deb Rare.deb
- name: Upload files to GitHub
uses: svenstaro/upload-release-action@2.2.1
with:

View file

@ -4,7 +4,8 @@
### Add translations
1. Execute ```pylupdate5 $(find -name "*.py") -ts Rare/languages/de.ts``` in source directory. Replace *de* with your language code
1. Execute ```pylupdate5 $(find -name "*.py") -ts Rare/languages/de.ts``` in source directory. Replace *de* with your
language code
2. Modify the .ts file manually or in Qt Linguist
3. Compile the file with ```lrelease Rare/languages/{lang}.ts```
@ -18,11 +19,12 @@ examples:
### Add features
Select one Card of the project and implement it, or if you want to add another feature ask me on Discord, or create an issue on GitHub
Select one Card of the project and implement it, or if you want to add another feature ask me on Discord, or create an
issue on GitHub
## Git crash-course
To contribute fork the repository and clone **your** repo. Then make your changes, add it to git with `git add File.xy` and upload it to GitHub with `git commit -m "message"` and `git push`.
Some IDEs can do this automatically.
To contribute fork the repository and clone **your** repo. Then make your changes, add it to git with `git add File.xy`
and upload it to GitHub with `git commit -m "message"` and `git push`. Some IDEs can do this automatically.
If you uploaded your changes, create a pull request

View file

@ -2,9 +2,9 @@
## 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. You will probably run into issues, so it is
recommend to make a backup. If you run into an issue, please report it by creating an issue on github or on Discord: https://discord.gg/YvmABK9YSk
Rare is a GUI for Legendary, a command line aternative to Epic Games launcher. It is currently considered beta software.
You will probably run into issues, so it is recommend to make a backup. If you run into an issue, please report it by
creating an issue on github or on Discord: https://discord.gg/YvmABK9YSk
![Discord Shield](https://discordapp.com/api/guilds/826881530310819914/widget.png?style=shield)
@ -12,43 +12,51 @@ recommend to make a backup. If you run into an issue, please report it by creati
### Installation via pip (recommend)
Execute `pip install Rare` for all users Or `pip install Rare --user` for only one user. Then execute `rare` in your terminal or cmd
Execute `pip install Rare` for all users Or `pip install Rare --user` for only one user. Then execute `rare` in your
terminal or cmd
**Note**: On Linux must be `/home/user/.local/bin` in PATH and on Windows must be `PythonInstallationDirectory\Scripts` in PATH.
**Note**: On Linux must be `/home/user/.local/bin` in PATH and on Windows must be `PythonInstallationDirectory\Scripts`
in PATH.
### Windows Simple
Download Rare.exe from the [releases page](https://github.com/Dummerle/Rare/releases) and execute it.
Download Rare.exe from the [releases page](https://github.com/Dummerle/Rare/releases) and execute it.
**Note:**
Using the exe file could cause errors with Windows Defender or other Anti Virus. Sometimes it is not possible to download games and sometimes the app crashes. In this case please use pip
Using the exe file could cause errors with Windows Defender or other Anti Virus. Sometimes it is not possible to
download games and sometimes the app crashes. In this case please use pip
### Linux
#### Arch based
There are some AUR packages available:
- [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](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
#### Debian based
There is a `.deb` package available from the [releases page](https://github.com/Dummerle/Rare/releases): `sudo dpkg i Rare.deb`
There is a `.deb` package available from
the [releases page](https://github.com/Dummerle/Rare/releases): `sudo dpkg i Rare.deb`
#### Other
Install via `pip`.
## Run from source
1. Run `pip install -r requirements.txt` to get dependencies. If you use `pacman` you can run `sudo pacman --needed -S python-wheel python-setuptools python-pyqt5 python-qtawesome python-requests python-pillow`
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`
## Why Rare?
- Rare only uses ~50MB of RAM which is much less than the electron based [HeroicGamesLauncher](https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher) uses.
- Rare supports all major platforms (Windows, Linux, Mac) unlike the alternatives.
**Note** Mac should work too, but I have no Mac and I can't test it.
- 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, Mac) unlike the alternatives.
**Note** Mac should work too, but I have no Mac and I can't test it.
## Features
@ -60,12 +68,14 @@ Install via `pip`.
- Translations (English, German and French)
## Planned Features
- More Translations (Need help)
- More Information about Games
More planned features are in [projects](https://github.com/Dummerle/Rare/projects/1)
- More Information about Games More planned features are in [projects](https://github.com/Dummerle/Rare/projects/1)
## Contributing
There are more options to contribute.
There are more options to contribute.
- If you can Python and PyQt you can implement new Features (Some ideas are in Projects).
- If you are a designer, you can add Stylesheets or create a logo or a banner
- You can translate the application in your language

View file

@ -24,18 +24,18 @@ 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
('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}
@ -44,9 +44,9 @@ else:
name = 'Rare'
src_files += [
'LICENSE',
'README.md',
'rare/styles/Logo.ico',
'LICENSE',
'README.md',
'rare/styles/Logo.ico',
]
# Dependencies are automatically detected, but it might need fine tuning.
@ -58,17 +58,17 @@ 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,
),
],
)
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

@ -7,9 +7,15 @@ from rare.utils import singleton
def main():
parser = ArgumentParser()
parser.add_argument("-V", "--version", action="store_true")
parser.add_argument("-S", "--silent", action="store_true")
parser.add_argument("--offline", action="store_true")
parser.add_argument("-V", "--version", action="store_true", help="Shows version and exits")
parser.add_argument("-S", "--silent", action="store_true",
help="Launch Rare in background. Open it from System Tray Icon")
parser.add_argument("--offline", action="store_true", help="Launch Rare in offline mode")
if os.name != "nt":
parser.add_argument("--disable-protondb", action="store_true", dest="disable_protondb",
help="Do not download and check data from ProtonDB. Disable it, if you don't need grades")
parser.add_argument("--enable-protondb", action="store_true", dest="enable_protondb",
help="Enable ProtonDB data, after disabled")
subparsers = parser.add_subparsers(title="Commands", dest="subparser")
launch_parser = subparsers.add_parser("launch")

View file

@ -6,14 +6,14 @@ import time
from PyQt5.QtCore import QSettings, QTranslator
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QStyleFactory
from custom_legendary.core import LegendaryCore
from rare import lang_path, style_path
from rare.components.dialogs.launch_dialog import LaunchDialog
from rare.components.main_window import MainWindow
from rare.components.tray_icon import TrayIcon
from rare.utils.utils import get_lang
from rare.utils.utils import get_lang, load_color_scheme
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")
@ -32,7 +32,6 @@ class App(QApplication):
def __init__(self, args):
super(App, self).__init__(sys.argv)
self.args = args # add some options
# init Legendary
try:
self.core = LegendaryCore()
@ -49,11 +48,21 @@ class App(QApplication):
self.core.lgd.config.add_section("Legendary")
self.core.lgd.save_config()
# workaround if egl sync enabled, but no programdata path
if self.core.egl_sync_enabled and not os.path.exists(self.core.egl.programdata_path):
self.core.lgd.config.remove_option("Legendary", "egl-sync")
self.core.lgd.save_config()
# set Application name for settings
self.mainwindow = None
self.setApplicationName("Rare")
self.setOrganizationName("Rare")
settings = QSettings()
if os.name != "nt":
if args.disable_protondb:
settings.setValue("disable_protondb", True)
if args.enable_protondb:
settings.remove("disable_protondb")
# Translator
self.translator = QTranslator()
@ -66,8 +75,19 @@ class App(QApplication):
self.installTranslator(self.translator)
# Style
self.setStyleSheet(open(style_path + "RareStyle.qss").read())
self.setWindowIcon(QIcon(style_path + "Logo.png"))
self.setStyle(QStyleFactory.create("Fusion"))
if settings.value("color_scheme", None) is None and settings.value("style_sheet", None) is None:
settings.setValue("color_scheme", "")
settings.setValue("style_sheet", "RareStyle")
if color := settings.value("color_scheme", False):
settings.setValue("style_sheet", "")
custom_palette = load_color_scheme(os.path.join(style_path, "colors", color + ".scheme"))
if custom_palette is not None:
self.setPalette(custom_palette)
elif style := settings.value("style_sheet", False):
settings.setValue("color_scheme", "")
self.setStyleSheet(open(os.path.join(style_path, "qss", style + ".qss")).read())
self.setWindowIcon(QIcon(os.path.join(style_path, "Logo.png")))
# launch app
self.launch_dialog = LaunchDialog(self.core, args.offline)
@ -106,4 +126,4 @@ def start(args):
if exit_code != -133742:
break
# restart app
del app
del app

View file

@ -5,6 +5,7 @@ from PyQt5.QtWidgets import QDialog, QFormLayout, QVBoxLayout, QSpinBox, QFileDi
from custom_legendary.core import LegendaryCore
from rare.utils.extra_widgets import PathEdit
from rare.utils.utils import get_size
class InstallDialog(QDialog):
@ -26,7 +27,7 @@ class InstallDialog(QDialog):
if not default_path:
default_path = os.path.expanduser("~/legendary")
if not update:
self.install_path_field = PathEdit(text=default_path, type_of_file=QFileDialog.DirectoryOnly)
self.install_path_field = PathEdit(text=default_path, file_type=QFileDialog.DirectoryOnly)
self.form.addRow(QLabel("Install directory"), self.install_path_field)
if self.core.lgd.config.has_option("Legendary", "max_workers"):
@ -46,6 +47,10 @@ class InstallDialog(QDialog):
self.ignore_free_space.setChecked(False)
self.form.addRow(QLabel(self.tr("Ignore free space (Warning!)")), self.ignore_free_space)
self.download_only = QCheckBox()
self.download_only.setChecked(False)
self.form.addRow(QLabel(self.tr("Do not install game")), self.download_only)
self.layout.addLayout(self.form)
self.ok_btn = QPushButton("Next")
@ -69,7 +74,11 @@ class InstallDialog(QDialog):
return self.infos
def ok(self):
self.infos = self.install_path_field.text() if not self.update_game else None, self.max_workes.value(), self.force.isChecked(), self.ignore_free_space.isChecked()
self.infos = self.install_path_field.text() if not self.update_game else None, \
self.max_workes.value(), \
self.force.isChecked(), \
self.ignore_free_space.isChecked(), \
self.download_only.isChecked()
self.close()
@ -80,8 +89,7 @@ class InstallInfoDialog(QDialog):
super(InstallInfoDialog, self).__init__()
self.layout = QVBoxLayout()
self.infos = QLabel(self.tr(
"Download size: {}GB\nInstall size: {}GB").format(round(dl_size / 1024 ** 3, 2),
round(install_size / 1024 ** 3, 2)))
"Download size: {}\nInstall size: {}").format(get_size(dl_size), get_size(install_size)))
self.layout.addWidget(self.infos)
self.btn_layout = QHBoxLayout()

View file

@ -1,29 +1,69 @@
import json
import os
from logging import getLogger
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QDialog, QLabel, QProgressBar, QVBoxLayout
from PyQt5.QtCore import QThread, pyqtSignal, QSettings
from PyQt5.QtWidgets import QDialog
from requests.exceptions import ConnectionError
from custom_legendary.core import LegendaryCore
from rare.components.dialogs.login import LoginDialog
from rare.ui.components.dialogs.launch_dialog import Ui_LaunchDialog
from rare.utils import steam_grades
from rare.utils.utils import download_images
logger = getLogger("Login")
class LaunchThread(QThread):
class ImageThread(QThread):
download_progess = pyqtSignal(int)
action = pyqtSignal(str)
def __init__(self, core: LegendaryCore, parent=None):
super(LaunchThread, self).__init__(parent)
super(ImageThread, self).__init__(parent)
self.core = core
def run(self):
self.action.emit("Login")
self.action.emit(self.tr("Downloading Images"))
download_images(self.download_progess, self.core)
self.action.emit("finish")
self.download_progess.emit(100)
class SteamThread(QThread):
progress = pyqtSignal(int)
action = pyqtSignal(str)
def __init__(self, core: LegendaryCore, parent):
super(SteamThread, self).__init__(parent)
self.core = core
def run(self) -> None:
gamelist = self.core.get_game_list(True)
if not os.path.exists(os.path.expanduser("~/.cache/rare/game_list.json")):
self.action.emit(self.tr("Getting data from ProtonDB"))
steam_grades.upgrade_all([(i.app_title, i.app_name) for i in gamelist], self.progress)
self.progress.emit(99)
self.action.emit(self.tr("Checking Games for data"))
grades = json.load(open(os.path.expanduser("~/.cache/rare/game_list.json")))
ids = json.load(open(os.path.expanduser("~/.cache/rare/steam_ids.json")))
for game in gamelist:
if not grades.get(game.app_name):
steam_id = steam_grades.get_steam_id(game.app_title, ids)
grade = steam_grades.get_grade(steam_id)
grades[game.app_name] = {
"steam_id": steam_id,
"grade": grade
}
if not grades[game.app_name].get("steam_id"):
grades[game.app_name]["steam_id"] = steam_grades.get_steam_id(game.app_title)
if not grades[game.app_name].get("grade"):
grades[game.app_name]["grade"] = steam_grades.get_grade(game.app_title)
with open(os.path.expanduser("~/.cache/rare/game_list.json"), "w") as f:
f.write(json.dumps(grades))
f.close()
self.action.emit("Ready")
self.progress.emit(100)
class LoginThread(QThread):
@ -50,11 +90,17 @@ class LoginThread(QThread):
self.start_app.emit(True)
class LaunchDialog(QDialog):
class LaunchDialog(QDialog, Ui_LaunchDialog):
start_app = pyqtSignal(bool)
finished = False
def __init__(self, core: LegendaryCore, offline):
super(LaunchDialog, self).__init__()
self.setupUi(self)
if os.name == "nt":
self.finished = True
self.steam_info.setVisible(False)
self.steam_prog_bar.setVisible(False)
self.core = core
if not offline:
self.login_thread = LoginThread(core)
@ -62,18 +108,7 @@ class LaunchDialog(QDialog):
self.login_thread.start_app.connect(self.launch)
self.login_thread.start()
self.title = QLabel("<h3>" + self.tr("Launching Rare") + "</h3>")
self.info_pb = QProgressBar()
self.info_text = QLabel(self.tr("Logging in"))
self.layout = QVBoxLayout()
self.layout.addWidget(self.title)
self.layout.addWidget(self.info_pb)
self.layout.addWidget(self.info_text)
self.setLayout(self.layout)
if offline:
else:
self.launch(offline)
def login(self):
@ -86,20 +121,40 @@ class LaunchDialog(QDialog):
def launch(self, offline=False):
# self.core = core
if not os.path.exists(p := os.path.expanduser("~/.cache/rare/images")):
os.makedirs(p)
self.offline = offline
self.info_text.setText(self.tr("Downloading Images"))
self.thread = LaunchThread(self.core, self)
self.thread.download_progess.connect(self.update_pb)
self.thread.action.connect(self.info)
self.thread.start()
def update_pb(self, i: int):
self.info_pb.setValue(i)
if not offline:
def info(self, text: str):
if text == "finish":
self.info_text.setText(self.tr("Starting..."))
self.info_pb.setValue(100)
self.image_info.setText(self.tr("Downloading Images"))
self.img_thread = ImageThread(self.core, self)
self.img_thread.download_progess.connect(self.update_image_progbar)
self.img_thread.finished.connect(self.finish)
self.img_thread.start()
# not disabled and not windows
if (not QSettings().value("disable_protondb", False, bool)) and (not os.name == "nt"):
self.steam_thread = SteamThread(self.core, self)
self.steam_thread.progress.connect(self.update_steam_prog_bar)
self.steam_thread.action.connect(lambda x: self.steam_info.setText(x))
self.steam_thread.finished.connect(self.finish)
self.steam_thread.start()
else:
self.finished = True
self.steam_info.setVisible(False)
self.steam_prog_bar.setVisible(False)
def update_steam_prog_bar(self, value):
self.steam_prog_bar.setValue(value)
def update_image_progbar(self, i: int):
self.image_prog_bar.setValue(i)
def finish(self):
if self.finished:
self.image_info.setText(self.tr("Starting..."))
self.image_prog_bar.setValue(100)
self.steam_prog_bar.setValue(100)
self.start_app.emit(self.offline)
else:
self.info_text.setText(text)
self.finished = True

View file

@ -3,16 +3,17 @@ import webbrowser
from PyQt5.QtCore import QSize, pyqtSignal
from PyQt5.QtWidgets import QMenu, QTabWidget, QWidget, QWidgetAction
from qtawesome import icon
from rare.utils import legendary_utils
from custom_legendary.core import LegendaryCore
from rare.components.dialogs.install_dialog import InstallDialog
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.tab_utils import TabBar, TabButtonWidget
from rare.components.tabs.account import MiniWidget
from rare.components.tabs.cloud_saves import SyncSaves
from rare.components.tabs.downloads.__init__ import DownloadTab
from rare.components.tabs.downloads import DownloadTab
from rare.components.tabs.games import GameTab
from rare.components.tabs.settings import SettingsTab
from rare.utils import legendary_utils
from rare.utils.models import InstallOptions
@ -74,11 +75,13 @@ class TabWidget(QTabWidget):
if not offline:
# Download finished
self.downloadTab.finished.connect(self.dl_finished)
# start download
self.games_tab.default_widget.game_list.install_game.connect(self.start_download)
# show uninstalled info
self.games_tab.default_widget.game_list.show_uninstalled_info.connect(self.games_tab.show_uninstalled)
# install dlc
self.games_tab.game_info.dlc_tab.install_dlc.connect(self.start_download)
self.games_tab.game_info.dlc_tab.install_dlc.connect(self.install_game)
# install game
self.games_tab.uninstalled_info_widget.info.install_game.connect(self.install_game)
# repair game
self.games_tab.game_info.info.verify_game.connect(lambda app_name: self.downloadTab.install_game(
InstallOptions(app_name, core.get_installed_game(app_name).install_path, repair=True)))
@ -92,6 +95,21 @@ class TabWidget(QTabWidget):
self.tabBarClicked.connect(lambda x: self.games_tab.layout.setCurrentIndex(0) if x == 0 else None)
self.setIconSize(QSize(25, 25))
def install_game(self, app_name, disable_path=False):
infos = InstallDialog(app_name, self.core, disable_path).get_information()
if infos != 0:
path, max_workers, force, ignore_free_space, dl_only = infos
options = InstallOptions(app_name=app_name, max_workers=max_workers, path=path, force=force,
ignore_free_space=ignore_free_space, download_only=dl_only)
self.setCurrentIndex(1)
self.start_download(options)
def start_download(self, options):
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) + 1
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
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:
@ -119,6 +137,7 @@ class TabWidget(QTabWidget):
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys())
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.downloadTab.update_text.setVisible(len(self.downloadTab.update_widgets) == 0)
# Update gamelist and set text of Downlaods to "Downloads"
def dl_finished(self, update_list):
@ -127,11 +146,6 @@ class TabWidget(QTabWidget):
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys())
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
def start_download(self, options):
downloads = len(self.downloadTab.dl_queue) + len(self.downloadTab.update_widgets.keys()) + 1
self.setTabText(1, "Downloads" + ((" (" + str(downloads) + ")") if downloads != 0 else ""))
self.downloadTab.install_game(options)
def resizeEvent(self, event):
self.tabBar().setMinimumWidth(self.width())
super(TabWidget, self).resizeEvent(event)

View file

@ -142,18 +142,20 @@ class DownloadTab(QWidget):
return
if self.active_game is None:
self.start_installation(dlm, game, status_queue, igame, repair_file, options, analysis)
self.start_installation(dlm, game, status_queue, igame, repair_file, options, analysis,
options.download_only)
else:
self.dl_queue.append((dlm, game, status_queue, igame, repair_file, options, analysis))
self.dl_queue.append(
(dlm, game, status_queue, igame, repair_file, options, analysis, options.download_only))
self.queue_widget.update_queue(self.dl_queue)
def start_installation(self, dlm, game, status_queue, igame, repair_file, options: InstallOptions, analysis):
print("start installation", game.app_title)
def start_installation(self, dlm, game, status_queue, igame, repair_file, options: InstallOptions, analysis,
dl_only):
if self.dl_queue:
self.dl_queue.pop(0)
self.queue_widget.update_queue(self.dl_queue)
self.active_game = game
self.thread = DownloadThread(dlm, self.core, status_queue, igame, options.repair, repair_file)
self.thread = DownloadThread(dlm, self.core, status_queue, igame, options.repair, repair_file, dl_only)
self.thread.status.connect(self.status)
self.thread.statistics.connect(self.statistics)
self.thread.start()
@ -265,8 +267,9 @@ class DownloadTab(QWidget):
def statistics(self, ui_update: UIUpdate):
self.prog_bar.setValue(ui_update.progress)
self.dl_speed.setText(self.tr("Download speed") + f": {ui_update.download_speed / 1024 / 1024:.02f}MB/s")
self.cache_used.setText(self.tr("Cache used") + f": {ui_update.cache_usage / 1024 / 1024:.02f}MB")
self.dl_speed.setText(self.tr("Download speed") + f": {get_size(ui_update.download_speed)}/s")
self.cache_used.setText(
self.tr("Cache used") + f": {get_size(ui_update.cache_usage) if ui_update.cache_usage > 1023 else '0KB'}")
self.downloaded.setText(
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))
@ -282,13 +285,16 @@ class DownloadTab(QWidget):
self.install_game(InstallOptions(app_name=app_name), True)
return
if infos != 0:
path, max_workers, force, ignore_free_space = infos
path, max_workers, force, ignore_free_space, dl_only = infos
self.install_game(InstallOptions(app_name=app_name, max_workers=max_workers, path=path,
force=force, ignore_free_space=ignore_free_space), True)
force=force, ignore_free_space=ignore_free_space, dl_only=dl_only), True)
else:
self.update_widgets[app_name].update_button.setDisabled(False)
self.update_widgets[app_name].update_with_settings.setDisabled(False)
class UpdateWidget(QWidget):
update = pyqtSignal(str)
update_signal = pyqtSignal(str, bool)
def __init__(self, core: LegendaryCore, game: InstalledGame, parent):
super(UpdateWidget, self).__init__(parent=parent)
@ -300,12 +306,18 @@ class UpdateWidget(QWidget):
self.layout.addWidget(self.title)
self.update_button = QPushButton(self.tr("Update Game"))
self.update_button.clicked.connect(self.update_game)
self.update_button.clicked.connect(lambda: self.update_game(True))
self.update_with_settings = QPushButton("Update with settings")
self.update_with_settings.clicked.connect(lambda: self.update_game(False))
self.layout.addWidget(self.update_button)
self.layout.addWidget(QLabel(self.tr("Version: ") + self.game.version + " -> " + self.core.get_asset(self.game.app_name, True).build_version))
self.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)
def update_game(self):
def update_game(self, auto: bool):
self.update_button.setDisabled(True)
self.update.emit(self.game.app_name)
self.update_with_settings.setDisabled(True)
self.update_signal.emit(self.game.app_name, auto) # True if settings

View file

@ -23,10 +23,11 @@ class DownloadThread(QThread):
statistics = pyqtSignal(UIUpdate)
def __init__(self, dlm: DLManager, core: LegendaryCore, status_queue: MPQueue, igame, repair=False,
repair_file=None):
repair_file=None, dl_only=False):
super(DownloadThread, self).__init__()
self.dlm = dlm
self.core = core
self.dl_only = dl_only
self.status_queue = status_queue
self.igame = igame
self.repair = repair
@ -120,24 +121,26 @@ class DownloadThread(QThread):
return
self.status.emit("dl_finished")
end_t = time.time()
logger.info(f"Download finished in {start_time - end_t}s")
game = self.core.get_game(self.igame.app_name)
postinstall = self.core.install_game(self.igame)
if postinstall:
self._handle_postinstall(postinstall, self.igame)
dlcs = self.core.get_dlc_for_game(self.igame.app_name)
if dlcs:
print('The following DLCs are available for this game:')
for dlc in dlcs:
print(f' - {dlc.app_title} (App name: {dlc.app_name}, version: {dlc.app_version})')
print('Manually installing DLCs works the same; just use the DLC app name instead.')
if not self.dl_only:
postinstall = self.core.install_game(self.igame)
if postinstall:
self._handle_postinstall(postinstall, self.igame)
# install_dlcs = QMessageBox.question(self, "", "Do you want to install the prequisites", QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes
# TODO
if game.supports_cloud_saves and not game.is_dlc:
logger.info('This game supports cloud saves, syncing is handled by the "sync-saves" command.')
logger.info(f'To download saves for this game run "legendary sync-saves {game.app_name}"')
dlcs = self.core.get_dlc_for_game(self.igame.app_name)
if dlcs:
print('The following DLCs are available for this game:')
for dlc in dlcs:
print(f' - {dlc.app_title} (App name: {dlc.app_name}, version: {dlc.app_version})')
print('Manually installing DLCs works the same; just use the DLC app name instead.')
# install_dlcs = QMessageBox.question(self, "", "Do you want to install the prequisites", QMessageBox.Yes|QMessageBox.No) == QMessageBox.Yes
# TODO
if game.supports_cloud_saves and not game.is_dlc:
logger.info('This game supports cloud saves, syncing is handled by the "sync-saves" command.')
logger.info(f'To download saves for this game run "legendary sync-saves {game.app_name}"')
old_igame = self.core.get_installed_game(game.app_name)
if old_igame and self.repair and os.path.exists(self.repair_file):
if old_igame.needs_verification:

View file

@ -4,6 +4,7 @@ from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QLineEdit, QPushB
from qtawesome import icon
from rare.components.tabs.games.game_info import InfoTabs
from rare.components.tabs.games.game_info.uninstalled_info import UninstalledInfo, UninstalledTabInfo
from rare.components.tabs.games.game_list import GameList
from rare.components.tabs.games.import_widget import ImportWidget
from rare.utils.extra_widgets import SelectViewWidget
@ -28,13 +29,23 @@ class GameTab(QWidget):
self.import_widget = ImportWidget(core, self)
self.layout.addWidget(self.import_widget)
self.import_widget.back_button.clicked.connect(lambda: self.layout.setCurrentIndex(0))
# self.import_widget.update_list.connect(self.update_list)
self.import_widget.update_list.connect(self.update_list)
self.uninstalled_info_widget = UninstalledTabInfo(core, self)
self.layout.addWidget(self.uninstalled_info_widget)
# self.uninstalled_info_widget.back.clicked.connect(lambda: self.layout.setCurrentIndex(0))
self.setLayout(self.layout)
def update_list(self, app_name=None):
self.default_widget.game_list.update_list(app_name)
self.layout.setCurrentIndex(0)
def show_uninstalled(self, app_name):
self.uninstalled_info_widget.update_game(app_name)
self.uninstalled_info_widget.setCurrentIndex(1)
self.layout.setCurrentIndex(3)
def show_info(self, app_name):
self.game_info.update_game(app_name, self.default_widget.game_list.dlcs)
self.game_info.setCurrentIndex(1)

View file

@ -1,17 +1,16 @@
import json
import os
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QPixmap, QKeyEvent
from PyQt5.QtWidgets import QWidget, QPushButton, QVBoxLayout, QLabel, QHBoxLayout, QTabWidget, QMessageBox, \
QProgressBar, QStackedWidget, QGroupBox, QScrollArea
from PyQt5.QtWidgets import QWidget, QTabWidget, QMessageBox
from qtawesome import icon
from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import InstalledGame, Game
from rare.components.dialogs.uninstall_dialog import UninstallDialog
from rare.components.tabs.games.game_info.dlcs import DlcTab
from rare.components.tabs.games.game_info.game_settings import GameSettings
from rare.utils import legendary_utils
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
from rare.utils.extra_widgets import SideTabBar
from rare.utils.legendary_utils import VerifyThread
from rare.utils.utils import IMAGE_DIR, get_size
@ -55,7 +54,7 @@ class InfoTabs(QTabWidget):
self.parent().layout.setCurrentIndex(0)
class GameInfo(QScrollArea):
class GameInfo(QWidget, Ui_GameInfo):
igame: InstalledGame
game: Game
uninstall_game = pyqtSignal(str)
@ -65,55 +64,26 @@ class GameInfo(QScrollArea):
def __init__(self, core: LegendaryCore, parent):
super(GameInfo, self).__init__(parent=parent)
self.setupUi(self)
self.ratings = {"platinum": self.tr("Platimum"),
"gold": self.tr("Gold"),
"silver": self.tr("Silver"),
"bronze": self.tr("Bronze"),
"fail": self.tr("Could not get grade from ProtonDB"),
"pending": "Not enough reports"}
if os.path.exists(p := os.path.expanduser("~/.cache/rare/game_list.json")):
self.grade_table = json.load(open(p))
else:
self.grade_table = {}
self.widget = QWidget()
self.core = core
self.layout = QVBoxLayout()
self.setWidgetResizable(True)
if os.name == "nt":
self.lbl_grade.setVisible(False)
self.grade.setVisible(False)
top_layout = QHBoxLayout()
# No Game at start. Game is set when clicked info
self.image = QLabel()
top_layout.addWidget(self.image)
right_layout = QVBoxLayout()
self.game_title = QLabel("Error")
self.game_title.setTextInteractionFlags(Qt.TextSelectableByMouse)
right_layout.addWidget(self.game_title)
self.dev = QLabel("Error")
self.dev.setTextInteractionFlags(Qt.TextSelectableByMouse)
right_layout.addWidget(self.dev)
self.app_name = QLabel("Error")
self.app_name.setTextInteractionFlags(Qt.TextSelectableByMouse)
right_layout.addWidget(self.app_name)
self.version = QLabel("Error")
self.version.setTextInteractionFlags(Qt.TextSelectableByMouse)
right_layout.addWidget(self.version)
self.install_size = QLabel("Error")
right_layout.addWidget(self.install_size)
self.install_path = QLabel("Error")
self.install_path.setTextInteractionFlags(Qt.TextSelectableByMouse)
self.install_path.setWordWrap(True)
right_layout.addWidget(self.install_path)
top_layout.addLayout(right_layout)
top_layout.addStretch()
self.game_actions = GameActions()
self.game_actions.uninstall_button.clicked.connect(self.uninstall)
self.game_actions.verify_button.clicked.connect(self.verify)
self.game_actions.repair_button.clicked.connect(self.repair)
self.layout.addLayout(top_layout)
self.layout.addWidget(self.game_actions)
self.layout.addStretch()
self.widget.setLayout(self.layout)
self.setWidget(self.widget)
self.uninstall_button.clicked.connect(self.uninstall)
self.verify_button.clicked.connect(self.verify)
self.repair_button.clicked.connect(self.repair)
def uninstall(self):
self.uninstall_game.emit(self.game.app_name)
@ -128,18 +98,18 @@ class GameInfo(QScrollArea):
self.verify_game.emit(self.game.app_name)
def verify(self):
self.game_actions.verify_widget.setCurrentIndex(1)
self.verify_widget.setCurrentIndex(1)
verify_thread = VerifyThread(self.core, self.game.app_name)
verify_thread.status.connect(self.verify_satistics)
verify_thread.summary.connect(self.finish_verify)
verify_thread.start()
self.game_actions.verify_progress_bar.setValue(0)
self.verify_progress.setValue(0)
self.verify_threads[self.game.app_name] = verify_thread
def verify_satistics(self, progress):
# checked, max, app_name
if progress[2] == self.game.app_name:
self.game_actions.verify_progress_bar.setValue(progress[0] * 100 / progress[1])
self.verify_progress.setValue(progress[0] * 100 / progress[1])
def finish_verify(self, failed):
failed, missing, app_name = failed
@ -152,7 +122,7 @@ class GameInfo(QScrollArea):
failed, missing), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
if ans == QMessageBox.Yes:
self.verify_game.emit(self.game.app_name)
self.game_actions.verify_widget.setCurrentIndex(0)
self.verify_widget.setCurrentIndex(0)
self.verify_threads.pop(app_name)
def update_game(self, app_name):
@ -174,56 +144,23 @@ class GameInfo(QScrollArea):
w = 200
pixmap = pixmap.scaled(w, int(w * 4 / 3))
self.image.setPixmap(pixmap)
self.app_name.setText("App name: " + self.game.app_name)
self.version.setText("Version: " + self.game.app_version)
self.dev.setText(self.tr("Developer: ") + self.game.metadata["developer"])
self.install_size.setText(
self.tr("Install size: ") + get_size(self.igame.install_size))
self.install_path.setText(self.tr("Install path: ") + self.igame.install_path)
self.app_name.setText(self.game.app_name)
self.version.setText(self.game.app_version)
self.dev.setText(self.game.metadata["developer"])
self.install_size.setText(get_size(self.igame.install_size))
self.install_path.setText(self.igame.install_path)
if os.name != "nt" and self.grade_table:
try:
grade = self.ratings.get(self.grade_table[app_name].get("grade"))
except KeyError:
grade = (self.tr("Error"))
self.grade.setText(grade)
if len(self.verify_threads.keys()) == 0 or not self.verify_threads.get(app_name):
self.game_actions.verify_widget.setCurrentIndex(0)
self.verify_widget.setCurrentIndex(0)
elif self.verify_threads.get(app_name):
self.game_actions.verify_widget.setCurrentIndex(1)
self.game_actions.verify_progress_bar.setValue(
self.verify_widget.setCurrentIndex(1)
self.verify_progress.setValue(
self.verify_threads[app_name].num / self.verify_threads[app_name].total * 100)
class GameActions(QGroupBox):
def __init__(self):
super(GameActions, self).__init__()
self.setTitle(f"{self.tr('Game actions')}")
self.setStyleSheet("QGroupBox{font-size: 20px}")
self.layout = QVBoxLayout()
uninstall_layout = QHBoxLayout()
self.uninstall_game = QLabel(self.tr("Uninstall game"))
uninstall_layout.addWidget(self.uninstall_game)
self.uninstall_button = QPushButton(self.tr("Uninstall"))
self.uninstall_button.setFixedWidth(250)
uninstall_layout.addWidget(self.uninstall_button)
self.layout.addLayout(uninstall_layout)
verify_layout = QHBoxLayout()
self.verify_game = QLabel(self.tr("Verify Game"))
verify_layout.addWidget(self.verify_game)
self.verify_widget = QStackedWidget()
self.verify_widget.setMaximumHeight(20)
self.verify_widget.setFixedWidth(250)
self.verify_button = QPushButton(self.tr("Verify"))
self.verify_widget.addWidget(self.verify_button)
self.verify_progress_bar = QProgressBar()
self.verify_progress_bar.setMaximum(100)
self.verify_widget.addWidget(self.verify_progress_bar)
verify_layout.addWidget(self.verify_widget)
self.layout.addLayout(verify_layout)
repair_layout = QHBoxLayout()
repair_info = QLabel(self.tr("Repair Game"))
repair_layout.addWidget(repair_info)
self.repair_button = QPushButton(self.tr("Repair"))
self.repair_button.setFixedWidth(250)
repair_layout.addWidget(self.repair_button)
self.layout.addLayout(repair_layout)
self.setLayout(self.layout)

View file

@ -6,13 +6,11 @@ from PyQt5.QtWidgets import QGroupBox, QHBoxLayout, QVBoxLayout, QScrollArea, QL
from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import Game
from rare.components.dialogs.install_dialog import InstallDialog
from rare.utils.models import InstallOptions
from rare.utils.utils import download_image
class DlcTab(QScrollArea):
install_dlc = pyqtSignal(InstallOptions)
install_dlc = pyqtSignal(str, bool)
game: Game
def __init__(self, core: LegendaryCore, parent):
@ -74,12 +72,7 @@ class DlcTab(QScrollArea):
QMessageBox.warning(self, "Error", self.tr("Base Game is not installed. Please install {} first").format(
self.game.app_title))
return
infos = InstallDialog(self.game.app_name, self.core, True).get_information()
if infos != 0:
path, max_workers, force, ignore_free_space = infos
self.install_dlc.emit(
InstallOptions(app_name=app_name, max_workers=max_workers, path=path, force=force,
ignore_free_space=ignore_free_space))
self.install_dlc.emit(app_name, True)
class DLCWidget(QGroupBox):

View file

@ -1,17 +1,36 @@
import os
from PyQt5.QtCore import QSettings
from PyQt5.QtWidgets import QWidget, QLabel, QVBoxLayout, QComboBox, QFileDialog, QPushButton, QMessageBox, QLineEdit, \
QScrollArea, QCheckBox
from PyQt5.QtWidgets import QWidget, QFileDialog, QMessageBox
from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import InstalledGame, Game
from rare.components.tabs.settings.linux import LinuxSettings
from rare.components.tabs.settings.settings_widget import SettingsWidget
from rare.ui.components.tabs.games.game_info.game_settings import Ui_GameSettings
from rare.utils.extra_widgets import PathEdit
class GameSettings(QScrollArea):
def find_proton_wrappers():
possible_proton_wrappers = []
compatibilitytools_dirs = [
os.path.expanduser("~/.steam/steam/steamapps/common"),
"/usr/share/steam/compatibilitytools.d"
]
for c in compatibilitytools_dirs:
if os.path.exists(c):
for i in os.listdir(c):
proton = os.path.join(c, i, "proton")
compatibilitytool = os.path.join(c, i, "compatibilitytool.vdf")
toolmanifest = os.path.join(c, i, "toolmanifest.vdf")
if os.path.exists(proton) and (os.path.exists(compatibilitytool) or os.path.exists(toolmanifest)):
wrapper = '"' + proton + '" run'
possible_proton_wrappers.append(wrapper)
if not possible_proton_wrappers:
print("Unable to find any Proton version")
return possible_proton_wrappers
class GameSettings(QWidget, Ui_GameSettings):
game: Game
igame: InstalledGame
@ -20,138 +39,105 @@ class GameSettings(QScrollArea):
def __init__(self, core: LegendaryCore, parent):
super(GameSettings, self).__init__(parent=parent)
self.setupUi(self)
self.core = core
self.widget = QWidget()
self.settings = QSettings()
self.setWidgetResizable(True)
self.layout = QVBoxLayout()
self.title = QLabel("Error")
self.layout.addWidget(self.title)
self.offline = QComboBox()
self.offline.addItems(["unset", "true", "false"])
self.offline_widget = SettingsWidget(self.tr("Launch Game offline"), self.offline)
self.offline.currentIndexChanged.connect(lambda x: self.update_combobox(x, "offline"))
self.skip_update = QComboBox()
self.skip_update.addItems(["unset", "true", "false"])
self.skip_update_widget = SettingsWidget(self.tr("Skip update check before launching"), self.skip_update)
self.layout.addWidget(self.skip_update_widget)
self.skip_update.currentIndexChanged.connect(lambda x: self.update_combobox(x, "skip_update_check"))
self.launch_params = QLineEdit("")
self.launch_params.setPlaceholderText(self.tr("Start parameter"))
self.launch_params_accept_button = QPushButton(self.tr("Save"))
self.launch_params_widget = SettingsWidget(self.tr("Launch parameters"), self.launch_params,
self.launch_params_accept_button)
self.layout.addWidget(self.launch_params_widget)
self.launch_params_accept_button.clicked.connect(
lambda: self.save_line_edit("start_params", self.launch_params.text()))
self.cloud_sync = QCheckBox("Sync with cloud")
self.cloud_sync_widget = SettingsWidget(self.tr("Auto sync with cloud"), self.cloud_sync)
self.layout.addWidget(self.cloud_sync_widget)
self.cloud_sync.stateChanged.connect(lambda: self.settings.setValue(f"{self.game.app_name}/auto_sync_cloud",
self.cloud_sync.isChecked()))
self.layout.addWidget(self.offline_widget)
self.wrapper = QLineEdit("")
self.wrapper.setPlaceholderText("Wrapper")
self.wrapper_save_button = QPushButton(self.tr("Save"))
self.wrapper_save_button.clicked.connect(lambda: self.save_line_edit("wrapper", self.wrapper.text()))
self.wrapper_widget = SettingsWidget(self.tr("Wrapper (e.g. optirun)"), self.wrapper, self.wrapper_save_button)
self.layout.addWidget(self.wrapper_widget)
self.offline.currentIndexChanged.connect(
lambda x: self.update_combobox(x, "offline")
)
self.skip_update.currentIndexChanged.connect(
lambda x: self.update_combobox(x, "skip_update_check")
)
self.cloud_sync.stateChanged.connect(
lambda: self.settings.setValue(f"{self.game.app_name}/auto_sync_cloud", self.cloud_sync.isChecked())
)
self.launch_params.textChanged.connect(lambda: self.launch_params_button.setEnabled(True))
self.launch_params_button.clicked.connect(
lambda: self.save_line_edit("start_params", self.launch_params.text())
)
self.launch_params_button.setEnabled(False)
self.wrapper.textChanged.connect(lambda: self.wrapper_button.setEnabled(True))
self.wrapper_button.clicked.connect(
lambda: self.save_line_edit("wrapper", self.wrapper.text())
)
self.wrapper_button.setEnabled(False)
if os.name != "nt":
self.possible_proton_wrappers = find_proton_wrappers()
self.proton_wrapper.addItems(self.possible_proton_wrappers)
self.proton_wrapper.currentIndexChanged.connect(self.change_proton)
self.proton_prefix = PathEdit("None", QFileDialog.DirectoryOnly, save_func=self.update_prefix)
self.proton_prefix_layout.addWidget(self.proton_prefix)
self.linux_settings = LinuxAppSettings(core)
self.layout.addWidget(self.linux_settings)
self.possible_proton_wrappers = []
try:
for i in os.listdir(os.path.expanduser("~/.steam/steam/steamapps/common")):
if i.startswith("Proton"):
wrapper = '"' + os.path.join(os.path.expanduser("~/.steam/steam/steamapps/common"), i,
"proton") + '" run'
self.possible_proton_wrappers.append(wrapper)
except FileNotFoundError as e:
print("Unable to find any Proton version")
self.select_proton = QComboBox()
self.select_proton.addItems(["Don't use Proton"] + self.possible_proton_wrappers)
self.select_proton.currentIndexChanged.connect(self.change_proton)
self.select_proton_widget = SettingsWidget(self.tr("Proton Wrapper"), self.select_proton)
self.linux_settings.layout.addWidget(self.select_proton_widget)
self.proton_prefix = PathEdit("x", QFileDialog.DirectoryOnly)
self.proton_prefix_accept_button = QPushButton(self.tr("Save"))
self.proton_prefix_accept_button.clicked.connect(self.update_prefix)
self.proton_prefix_widget = SettingsWidget(self.tr("Proton prefix"), self.proton_prefix,
self.proton_prefix_accept_button)
self.linux_settings.layout.addWidget(self.proton_prefix_widget)
self.linux_layout.addWidget(self.linux_settings)
else:
self.proton_groupbox.setVisible(False)
# startparams, skip_update_check
self.layout.addStretch(1)
self.widget.setLayout(self.layout)
self.setWidget(self.widget)
def save_line_edit(self, option, value):
if value != "":
if not self.game.app_name in self.core.lgd.config.sections():
if value:
if self.game.app_name not in self.core.lgd.config.sections():
self.core.lgd.config.add_section(self.game.app_name)
self.core.lgd.config.set(self.game.app_name, option, value)
else:
if self.game.app_name in self.core.lgd.config.sections() and self.core.lgd.config.get(
f"{self.game.app_name}", option, fallback="") != "":
f"{self.game.app_name}", option, fallback=None) is not None:
self.core.lgd.config.remove_option(self.game.app_name, option)
if not self.core.lgd.config.get(self.game.app_name):
if not self.core.lgd.config[self.game.app_name]:
self.core.lgd.config.remove_section(self.game.app_name)
self.core.lgd.save_config()
self.sender().setEnabled(False)
def update_combobox(self, i, option):
if self.change:
# remove section
if i == 0:
if i:
if self.game.app_name not in self.core.lgd.config.sections():
self.core.lgd.config.add_section(self.game.app_name)
if i == 1:
self.core.lgd.config.set(self.game.app_name, option, "true")
if i == 2:
self.core.lgd.config.set(self.game.app_name, option, "false")
else:
if self.game.app_name in self.core.lgd.config.sections():
if self.core.lgd.config.get(f"{self.game.app_name}", option, fallback="") != "":
if self.core.lgd.config.get(f"{self.game.app_name}", option, fallback=False):
self.core.lgd.config.remove_option(self.game.app_name, option)
if self.core.lgd.config[self.game.app_name] == {}:
if not self.core.lgd.config[self.game.app_name]:
self.core.lgd.config.remove_section(self.game.app_name)
elif i == 1:
self.core.lgd.config.add_section(self.game.app_name)
self.core.lgd.config.set(self.game.app_name, option, "true")
elif i == 2:
self.core.lgd.config.add_section(self.game.app_name)
self.core.lgd.config.set(self.game.app_name, option, "false")
self.core.lgd.save_config()
def change_proton(self, i):
if self.change:
# Dont use Proton
if i == 0:
self.proton_prefix_widget.setVisible(False)
self.wrapper_widget.setVisible(True)
self.proton_prefix.setEnabled(False)
self.wrapper_widget.setEnabled(True)
self.linux_settings.wine_groupbox.setEnabled(True)
if f"{self.game.app_name}" in self.core.lgd.config.sections():
if self.core.lgd.config.get(f"{self.game.app_name}", "wrapper", fallback="") != "":
if self.core.lgd.config.get(f"{self.game.app_name}", "wrapper", fallback=False):
self.core.lgd.config.remove_option(self.game.app_name, "wrapper")
if self.core.lgd.config.get(f"{self.game.app_name}", "no_wine", fallback="") != "":
if self.core.lgd.config.get(f"{self.game.app_name}", "no_wine", fallback=False):
self.core.lgd.config.remove_option(self.game.app_name, "no_wine")
if self.core.lgd.config[self.game.app_name] == {}:
if not self.core.lgd.config[self.game.app_name]:
self.core.lgd.config.remove_section(self.game.app_name)
if f"{self.game.app_name}.env" in self.core.lgd.config.sections():
if self.core.lgd.config.get(f"{self.game.app_name}.env", "STEAM_COMPAT_DATA_PATH",
fallback="") != "":
if self.core.lgd.config.get(f"{self.game.app_name}.env", "STEAM_COMPAT_DATA_PATH", fallback=False):
self.core.lgd.config.remove_option(f"{self.game.app_name}.env", "STEAM_COMPAT_DATA_PATH")
if self.core.lgd.config[self.game.app_name + ".env"] == {}:
if not self.core.lgd.config[self.game.app_name + ".env"]:
self.core.lgd.config.remove_section(self.game.app_name + ".env")
else:
self.proton_prefix_widget.setVisible(True)
self.wrapper_widget.setVisible(False)
self.proton_prefix.setEnabled(True)
self.wrapper_widget.setEnabled(False)
self.linux_settings.wine_groupbox.setEnabled(False)
wrapper = self.possible_proton_wrappers[i - 1]
if not self.game.app_name in self.core.lgd.config.sections():
if self.game.app_name not in self.core.lgd.config.sections():
self.core.lgd.config[self.game.app_name] = {}
if not self.game.app_name + ".env" in self.core.lgd.config.sections():
if self.game.app_name + ".env" not in self.core.lgd.config.sections():
self.core.lgd.config[self.game.app_name + ".env"] = {}
self.core.lgd.config.set(self.game.app_name, "wrapper", wrapper)
self.core.lgd.config.set(self.game.app_name, "no_wine", "true")
@ -160,16 +146,16 @@ class GameSettings(QScrollArea):
self.proton_prefix.text_edit.setText(os.path.expanduser("~/.proton"))
# Dont use Wine
self.linux_settings.select_wine_exec.setText("")
self.linux_settings.save_setting(self.linux_settings.select_wine_exec, "wine_exec")
self.linux_settings.select_path.text_edit.setText("")
self.linux_settings.save_setting(self.linux_settings.select_path, "wine_prefix")
self.linux_settings.wine_exec.text_edit.setText("")
self.linux_settings.save_setting(self.linux_settings.wine_exec, "wine_exec")
self.linux_settings.wine_prefix.text_edit.setText("")
self.linux_settings.save_setting(self.linux_settings.wine_prefix, "wine_prefix")
self.core.lgd.save_config()
def update_prefix(self):
text = self.proton_prefix.text()
if text == "":
if not text:
text = os.path.expanduser("~/.proton")
self.proton_prefix.text_edit.setText(text)
if not os.path.exists(text):
@ -197,9 +183,9 @@ class GameSettings(QScrollArea):
else:
self.offline.setCurrentIndex(0)
self.offline_widget.setVisible(True)
self.offline.setEnabled(True)
else:
self.offline_widget.setVisible(False)
self.offline.setEnabled(False)
skip_update = self.core.lgd.config.get(self.game.app_name, "skip_update_check", fallback="unset")
if skip_update == "true":
@ -215,25 +201,25 @@ class GameSettings(QScrollArea):
self.title.setText(f"<h2>{self.game.app_title}</h2>")
if os.name != "nt":
self.linux_settings.update_game(app_name)
self.linux_settings.dxvk_widget.update_settings(app_name)
self.linux_settings.dxvk.update_settings(app_name)
proton = self.core.lgd.config.get(f"{app_name}", "wrapper", fallback="").replace('"', "")
if proton != "":
self.proton_prefix_widget.setVisible(True)
self.select_proton.setCurrentText(f'"{proton.replace(" run", "")}" run')
self.proton_prefix.setEnabled(True)
self.proton_wrapper.setCurrentText(f'"{proton.replace(" run", "")}" run')
proton_prefix = self.core.lgd.config.get(f"{app_name}.env", "STEAM_COMPAT_DATA_PATH",
fallback=self.tr(
"Please select path for proton prefix"))
self.proton_prefix.text_edit.setText(proton_prefix)
self.wrapper_widget.setVisible(False)
self.wrapper_widget.setEnabled(False)
else:
self.select_proton.setCurrentIndex(0)
self.proton_prefix_widget.setVisible(False)
self.wrapper_widget.setVisible(True)
self.proton_wrapper.setCurrentIndex(0)
self.proton_prefix.setEnabled(False)
self.wrapper_widget.setEnabled(True)
if not self.game.supports_cloud_saves:
self.cloud_sync_widget.setVisible(False)
self.cloud_sync.setEnabled(False)
else:
self.cloud_sync_widget.setVisible(True)
self.cloud_sync.setEnabled(True)
sync_cloud = self.settings.value(f"{self.game.app_name}/auto_sync_cloud", True, bool)
self.cloud_sync.setChecked(sync_cloud)
@ -247,7 +233,7 @@ class LinuxAppSettings(LinuxSettings):
def update_game(self, app_name):
self.name = app_name
self.select_path.text_edit.setText(self.core.lgd.config.get(self.name, "wine_prefix", fallback=""))
self.select_wine_exec.setText(self.core.lgd.config.get(self.name, "wine_executable", fallback=""))
self.dxvk_widget.name = app_name
self.dxvk_widget.more_settings_widget.name = app_name
self.wine_prefix.text_edit.setText(self.core.lgd.config.get(self.name, "wine_prefix", fallback=""))
self.wine_exec.text_edit.setText(self.core.lgd.config.get(self.name, "wine_executable", fallback=""))
self.dxvk.name = app_name
self.dxvk.more_settings_widget.name = app_name

View file

@ -0,0 +1,139 @@
import json
import os
from PyQt5.QtCore import pyqtSignal, QSettings, Qt
from PyQt5.QtGui import QPixmap, QKeyEvent
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTabWidget, QTreeView
from qtawesome import icon
from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import Game
from rare.utils.extra_widgets import SideTabBar
from rare.utils.json_formatter import QJsonModel
class UninstalledTabInfo(QTabWidget):
def __init__(self, core, parent):
super(UninstalledTabInfo, self).__init__(parent=parent)
self.app_name = ""
self.core = core
self.setTabBar(SideTabBar())
self.setTabPosition(QTabWidget.West)
self.addTab(QWidget(), icon("mdi.keyboard-backspace", color="white"), self.tr("Back"))
self.tabBarClicked.connect(lambda x: self.parent().layout.setCurrentIndex(0) if x == 0 else None)
self.info = UninstalledInfo(core, self)
self.addTab(self.info, self.tr("Game Info"))
self.view = QTreeView()
self.view.setColumnWidth(0, 300)
self.view.setWordWrap(True)
self.model = QJsonModel()
self.view.setModel(self.model)
self.addTab(self.view, self.tr("Metadata"))
# self.setTabEnabled(1, False)
self.setCurrentIndex(1)
def update_game(self, app_name):
self.info.update_game(app_name)
self.model.clear()
self.model.load(json.load(open(os.path.expanduser(f"~/.config/legendary/metadata/{app_name}.json"), "r")))
def keyPressEvent(self, e: QKeyEvent):
if e.key() == Qt.Key_Escape:
self.parent().layout.setCurrentIndex(0)
class UninstalledInfo(QWidget):
game: Game
install_game = pyqtSignal(str)
def __init__(self, core: LegendaryCore, parent):
super(UninstalledInfo, self).__init__(parent=parent)
self.layout = QVBoxLayout()
if os.path.exists(p := os.path.expanduser("~/.cache/rare/game_list.json")):
self.grade_table = json.load(open(p))
else:
self.grade_table = {}
self.ratings = {"platinum": self.tr("Platinum"),
"gold": self.tr("Gold"),
"silver": self.tr("Silver"),
"bronze": self.tr("Bronze"),
"fail": self.tr("Could not get grade from ProtonDB"),
"pending": "Not enough reports"}
self.core = core
self.settings = QSettings()
self.top_layout = QHBoxLayout()
left_layout = QVBoxLayout()
self.image = QLabel()
left_layout.addWidget(self.image)
left_layout.addStretch(1)
self.top_layout.addLayout(left_layout)
self.right_layout = QVBoxLayout()
self.title = QLabel("Error")
self.right_layout.addWidget(self.title)
self.app_name = QLabel("Error")
self.right_layout.addWidget(self.app_name)
if os.name != "nt":
self.rating = QLabel("Rating: Error")
self.right_layout.addWidget(self.rating)
self.install_button = QPushButton(self.tr("Install"))
self.install_button.setFixedWidth(300)
self.install_button.setStyleSheet("""background-color: #090""")
self.install_button.clicked.connect(lambda: self.install_game.emit(self.game.app_name))
self.right_layout.addWidget(self.install_button)
self.version = QLabel("Error")
self.right_layout.addWidget(self.version)
self.right_layout.addStretch(1)
self.top_layout.addLayout(self.right_layout)
self.top_layout.addStretch(1)
self.layout.addLayout(self.top_layout)
self.setLayout(self.layout)
def update_game(self, app_name):
self.game = self.core.get_game(app_name)
self.title.setText(f"<h2>{self.game.app_title}</h2>")
self.app_name.setText("Appname: " + app_name)
IMAGE_DIR = self.settings.value("img_dir", os.path.expanduser("~/.cache/rare/images"), str)
if os.path.exists(f"{IMAGE_DIR}/{self.game.app_name}/FinalArt.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{self.game.app_name}/FinalArt.png")
elif os.path.exists(f"{IMAGE_DIR}/{self.game.app_name}/DieselGameBoxTall.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{self.game.app_name}/DieselGameBoxTall.png")
elif os.path.exists(f"{IMAGE_DIR}/{self.game.app_name}/DieselGameBoxLogo.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{self.game.app_name}/DieselGameBoxLogo.png")
else:
# logger.warning(f"No Image found: {self.game.title}")
pixmap = None
if pixmap:
w = 200
pixmap = pixmap.scaled(w, int(w * 4 / 3))
self.image.setPixmap(pixmap)
self.version.setText(self.game.asset_info.build_version)
if self.grade_table and (not os.name == "nt"):
try:
rating = self.grade_table[app_name]["grade"]
except KeyError:
rating = "fail"
if rating not in ["fail", "pending"]:
self.rating.setText(self.tr("Rating from ProtonDB: ") + self.ratings[rating])
else:
self.rating.setText(self.ratings[rating])

View file

@ -25,6 +25,7 @@ class GameList(QStackedWidget):
update_game = pyqtSignal()
game_exited = pyqtSignal(str)
game_started = pyqtSignal(str)
show_uninstalled_info = pyqtSignal(str)
running_games = []
active_game = ("", 0)
@ -77,17 +78,19 @@ class GameList(QStackedWidget):
self.icon_layout.addWidget(icon_widget)
self.list_layout.addWidget(list_widget)
self.uninstalled_names = []
self.uninstalled_games = []
installed = [i.app_name for i in self.core.get_installed_list()]
# get Uninstalled games
games, self.dlcs = self.core.get_game_and_dlc_list()
for game in sorted(games, key=lambda x: x.app_title):
if not game.app_name in installed:
self.uninstalled_names.append(game)
self.uninstalled_games.append(game)
# add uninstalled games
for game in self.uninstalled_names:
for game in self.uninstalled_games:
icon_widget, list_widget = self.add_uninstalled_widget(game)
self.icon_layout.addWidget(icon_widget)
self.list_layout.addWidget(list_widget)
@ -123,10 +126,10 @@ class GameList(QStackedWidget):
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)
icon_widget.show_uninstalled_info.connect(self.show_install_info)
list_widget = ListWidgetUninstalled(self.core, game, pixmap)
list_widget.install_game.connect(self.install)
list_widget.show_uninstalled_info.connect(self.show_install_info)
self.widgets[game.app_name] = (icon_widget, list_widget)
@ -204,13 +207,8 @@ class GameList(QStackedWidget):
return True, pid
return False, 0
def install(self, options: InstallOptions):
icon_widget, list_widget = self.widgets[options.app_name]
icon_widget.mousePressEvent = lambda e: None
icon_widget.installing = True
list_widget.install_button.setDisabled(True)
list_widget.installing = True
self.install_game.emit(options)
def show_install_info(self, app_name):
self.show_uninstalled_info.emit(app_name)
def finished(self, app_name):
self.running_games.remove(app_name)
@ -279,7 +277,8 @@ class GameList(QStackedWidget):
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):
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)
@ -332,7 +331,8 @@ class GameList(QStackedWidget):
self.update()
# uninstalled
elif not self.core.is_installed(widgets[0].game.app_name) and isinstance(widgets[0], BaseInstalledWidget):
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])
@ -392,5 +392,3 @@ class GameList(QStackedWidget):
i_widget, list_widget = self.widgets[name]
self.icon_layout.addWidget(i_widget)
self.list_layout.addWidget(list_widget)

View file

@ -1,4 +1,3 @@
import logging
import os
from logging import getLogger
@ -48,13 +47,18 @@ class BaseInstalledWidget(QGroupBox):
self.addAction(self.create_desktop)
if os.name == "posix":
if os.path.exists(os.path.expanduser(f"~/.local/share/applications/{self.igame.title}.desktop")):
self.create_start_menu = QAction(self.tr("Remove start menu link"))
else:
self.create_start_menu = QAction(self.tr("Create start menu link"))
start_menu_file = os.path.expanduser(f"~/.local/share/applications/{self.igame.title}.desktop")
elif os.name == "nt":
start_menu_file = os.path.expandvars("%appdata%/Microsoft/Windows/Start Menu")
else:
start_menu_file = ""
if os.path.exists(start_menu_file):
self.create_start_menu = QAction(self.tr("Remove start menu link"))
else:
self.create_start_menu = QAction(self.tr("Create start menu link"))
self.create_start_menu.triggered.connect(lambda: self.create_desktop_link("start_menu"))
self.addAction(self.create_start_menu)
self.create_start_menu.triggered.connect(lambda: self.create_desktop_link("start_menu"))
self.addAction(self.create_start_menu)
uninstall = QAction(self.tr("Uninstall"), self)
uninstall.triggered.connect(self.uninstall)

View file

@ -3,14 +3,11 @@ from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QGroupBox
from rare.components.dialogs.install_dialog import InstallDialog
from rare.utils.models import InstallOptions
logger = getLogger("Uninstalled")
class BaseUninstalledWidget(QGroupBox):
install_game = pyqtSignal(InstallOptions)
show_uninstalled_info = pyqtSignal(str)
def __init__(self, game, core, pixmap):
super(BaseUninstalledWidget, self).__init__()
@ -22,9 +19,4 @@ class BaseUninstalledWidget(QGroupBox):
self.setContentsMargins(0, 0, 0, 0)
def install(self):
infos = InstallDialog(self.game.app_name, self.core).get_information()
if infos != 0:
path, max_workers, force, ignore_free_space = infos
self.install_game.emit(
InstallOptions(app_name=self.game.app_name, max_workers=max_workers, path=path, force=force,
ignore_free_space=ignore_free_space))
self.show_uninstalled_info.emit(self.game.app_name)

View file

@ -1,19 +1,16 @@
from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QVBoxLayout, QLabel
from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import Game
from rare.components.tabs.games.game_widgets.base_uninstalled_widget import BaseUninstalledWidget
from rare.utils.extra_widgets import ClickableLabel
from rare.utils.models import InstallOptions
logger = getLogger("Uninstalled")
class IconWidgetUninstalled(BaseUninstalledWidget):
install_game = pyqtSignal(InstallOptions)
def __init__(self, game: Game, core: LegendaryCore, pixmap):
super(IconWidgetUninstalled, self).__init__(game, core, pixmap)
@ -42,7 +39,7 @@ class IconWidgetUninstalled(BaseUninstalledWidget):
def enterEvent(self, e):
if not self.installing:
self.info_label.setText(self.tr("Install Game"))
self.info_label.setText(self.tr("Game Info"))
else:
self.info_label.setText(self.tr("Installation running"))

View file

@ -1,10 +1,9 @@
import json
import os
import string
from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QPushButton, QVBoxLayout, QFileDialog, QMessageBox, QLineEdit, \
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QPushButton, QVBoxLayout, QFileDialog, QLineEdit, \
QGroupBox
from qtawesome import icon
@ -44,7 +43,7 @@ class ImportWidget(QWidget):
self.gb_layout.addWidget(self.import_game_info)
self.override_app_name_label = QLabel(
self.tr("Override app name (Only if imported game from legendary or the app could not find the app name)"))
self.tr("Override app name (Only if the app could not find the app name)"))
self.override_app_name_label.setWordWrap(True)
self.app_name_input = QLineEdit()
self.app_name_input.setFixedHeight(32)
@ -55,8 +54,7 @@ class ImportWidget(QWidget):
self.app_name_input.setLayout(minilayout)
self.app_name_input.textChanged.connect(self.app_name_changed)
self.path_edit = PathEdit(os.path.expanduser("~"), QFileDialog.DirectoryOnly)
self.path_edit.text_edit.textChanged.connect(self.path_changed)
self.path_edit = PathEdit(os.path.expanduser("~"), QFileDialog.DirectoryOnly, edit_func=self.path_changed)
self.gb_layout.addWidget(self.path_edit)
self.gb_layout.addWidget(self.override_app_name_label)
@ -72,13 +70,9 @@ class ImportWidget(QWidget):
self.layout.addWidget(self.import_one_game)
self.layout.addStretch(1)
self.auto_import = QLabel(f"<h3>{self.tr('Auto import all existing games')}</h3>")
self.auto_import = QLabel(
f"<h4>{self.tr('To import games from Epic Games Store, please enable EGL Sync in legendary settings')}</h4>")
self.layout.addWidget(self.auto_import)
self.auto_import_button = QPushButton(self.tr("Import all games from Epic Games Launcher"))
self.auto_import_button.clicked.connect(self.import_games_prepare)
self.layout.addWidget(self.auto_import_button)
self.layout.addStretch(1)
self.main_layout.addLayout(self.layout)
@ -130,45 +124,3 @@ class ImportWidget(QWidget):
logger.warning("Failed to import" + app_name)
self.info_label.setText(self.tr("Failed to import {}").format(app_name))
return
def auto_import_games(self, game_path):
imported = 0
if not os.path.exists(game_path):
return 0
if os.listdir(game_path) == 0:
logger.info(f"No Games found in {game_path}")
return 0
for path in os.listdir(game_path):
json_path = game_path + path
if not os.path.isdir(json_path):
logger.info(f"Game at {game_path + path} doesn't exist")
continue
app_name = self.find_app_name(json_path)
if not app_name:
logger.warning("Could not find app name at " + game_path)
continue
if legendary_utils.import_game(self.core, app_name, game_path + path):
imported += 1
return imported
def import_games_prepare(self):
# Automatically import from windows
imported = 0
if os.name == "nt":
available_drives = ['%s:' % d for d in string.ascii_uppercase if os.path.exists('%s:' % d)]
for drive in available_drives:
path = f"{drive}/Program Files/Epic Games/"
if os.path.exists(path):
imported += self.auto_import_games(path)
else:
possible_wineprefixes = [os.path.expanduser("~/.wine"), os.path.expanduser("~/Games/epic-games-store")]
for wine_prefix in possible_wineprefixes:
imported += self.auto_import_games(os.path.join(wine_prefix, "drive_c/Program Files/Epic Games/"))
if imported > 0:
QMessageBox.information(self, "Imported Games",
self.tr("Successfully imported {} Games. Reloading Library").format(imported))
self.update_list.emit("")
else:
QMessageBox.information(self, "Imported Games", self.tr("No Games were found"))

View file

@ -1,8 +1,9 @@
import webbrowser
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QPushButton
from PyQt5.QtWidgets import QWidget
from rare import __version__
from rare.ui.components.tabs.settings.about import Ui_About
from rare.utils.utils import get_latest_version
@ -13,45 +14,27 @@ def versiontuple(v):
return tuple((9, 9, 9)) # It is a beta version and newer
class About(QWidget):
class About(QWidget, Ui_About):
def __init__(self):
super(About, self).__init__()
self.layout = QVBoxLayout()
self.setupUi(self)
self.title = QLabel("<h2>About</h2>")
self.layout.addWidget(self.title)
self.version.setText(__version__)
self.update_label.setVisible(False)
self.update.setVisible(False)
self.open_browser.setVisible(False)
self.version = QLabel("Version: " + __version__)
self.layout.addWidget(self.version)
latest_tag = get_latest_version()
self.update_available = versiontuple(latest_tag) > versiontuple(__version__)
self.update.setText("{} -> {}".format(__version__, latest_tag))
self.open_browser.clicked.connect(
lambda: webbrowser.open("https://github.com/Dummerle/Rare/releases/latest"))
if self.update_available:
print(f"Update available: {__version__} -> {latest_tag}")
self.update_available = QLabel(self.tr("Update available: {} -> {}").format(__version__, latest_tag))
self.layout.addWidget(self.update_available)
self.open_browser = QPushButton(self.tr("Download latest release"))
self.layout.addWidget(self.open_browser)
self.open_browser.clicked.connect(
lambda: webbrowser.open("https://github.com/Dummerle/Rare/releases/latest"))
self.dev = QLabel(self.tr("Developer:") + "<a href='https://github.com/Dummerle'>Dummerle</a>")
self.dev.setToolTip("Github")
self.dev.setOpenExternalLinks(True)
self.dev.setWordWrap(True)
self.layout.addWidget(self.dev)
self.lgd_dev = QLabel(self.tr("Legendary developer:") + "<a href='https://github.com/derrod/'>derrod</a>")
self.lgd_dev.setOpenExternalLinks(True)
self.lgd_dev.setToolTip("Github")
self.layout.addWidget(self.lgd_dev)
self.license = QLabel("License: GNU General Public License v3.0")
self.layout.addWidget(self.license)
self.info_text = QLabel(
self.tr("This is a beta version, so you can get bugs. If you get a bug, please report it by creating a "
"Issue on <a href='https://github.com/Dummerle/Rare/issues'>Github</a>. You can also contact me "
"on Discord (Dummerle#7419). Or you can join the <a href='https://discord.gg/YvmABK9YSk'>Discord server</a>"))
self.info_text.setWordWrap(True)
self.info_text.setOpenExternalLinks(True)
self.layout.addWidget(self.info_text)
self.layout.addStretch()
self.setLayout(self.layout)
self.update_label.setVisible(True)
self.update.setVisible(True)
self.open_browser.setVisible(True)

View file

@ -1,16 +1,102 @@
from logging import getLogger
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QCheckBox, QVBoxLayout, QWidgetAction, QMenu, QToolButton, QHBoxLayout, QGroupBox
from PyQt5.QtWidgets import QGroupBox
from PyQt5.QtWidgets import QWidget, QCheckBox, QVBoxLayout, QWidgetAction, QMenu, QToolButton, QHBoxLayout
from custom_legendary.core import LegendaryCore
from rare.ui.components.tabs.settings.dxvk import Ui_DxvkSettings
logger = getLogger("DXVK Settings")
class DxvkSettings(QGroupBox, Ui_DxvkSettings):
def __init__(self, core: LegendaryCore, name=None):
super(DxvkSettings, self).__init__()
self.setupUi(self)
self.name = name if name is not None else "default"
self.core = core
self.dxvk_options_map = {
"devinfo": self.devinfo,
"fps": self.fps,
"frametime": self.frametime,
"memory": self.memory,
"gpuload": self.gpuload,
"version": self.version,
"api": self.api,
}
self.load_settings()
self.show_dxvk.currentIndexChanged.connect(self.store_settings)
for opt in self.dxvk_options_map:
self.dxvk_options_map[opt].stateChanged.connect(self.store_settings)
# Show HUD ComboBox
# System Default, index 0, removes DXVK_HUD to use setting from env
# Hidden , index 1, adds DXVK_HUD=0 to override system configuration
# Visible , index 2, adds DXVK_HUD=1 to override system configuration
# Custom Options, index 3, adds DXVK_HUD=devinfo,fps and enables the customization panel
def load_settings(self):
dxvk_options = self.core.lgd.config.get(f"{self.name}.env", "DXVK_HUD", fallback=None)
self.gb_dxvk_options.setDisabled(True)
if dxvk_options is not None:
if dxvk_options == "0":
self.show_dxvk.setCurrentIndex(1)
elif dxvk_options == "1":
self.show_dxvk.setCurrentIndex(2)
else:
self.show_dxvk.setCurrentIndex(3)
self.gb_dxvk_options.setDisabled(False)
for opt in dxvk_options.split(","):
try:
self.dxvk_options_map[opt].setChecked(True)
except KeyError:
print("Malformed DXVK Option: " + opt)
continue
else:
self.show_dxvk.setCurrentIndex(0)
def store_settings(self):
show_dxvk_index = self.show_dxvk.currentIndex()
if show_dxvk_index:
if f"{self.name}.env" not in self.core.lgd.config.sections():
print("add section dxvk")
self.core.lgd.config.add_section(f"{self.name}.env")
if show_dxvk_index == 1:
self.core.lgd.config[f"{self.name}.env"]["DXVK_HUD"] = "0"
if show_dxvk_index == 2:
self.core.lgd.config[f"{self.name}.env"]["DXVK_HUD"] = "1"
if show_dxvk_index == 3:
dxvk_options = []
for opt in self.dxvk_options_map:
if self.dxvk_options_map[opt].isChecked():
dxvk_options.append(opt)
if not dxvk_options:
# Check if this is the first activation
stored = self.core.lgd.config.get(f"{self.name}.env", "DXVK_HUD", fallback=None)
if stored not in [None, "0", "1"]:
self.core.lgd.config[f"{self.name}.env"]["DXVK_HUD"] = "0"
else:
dxvk_options = ["devinfo", "fps"]
# Check again if dxvk_options changed due to first activation
if dxvk_options:
self.core.lgd.config[f"{self.name}.env"]["DXVK_HUD"] = ",".join(dxvk_options)
else:
if self.core.lgd.config.get(f"{self.name}.env", "DXVK_HUD", fallback=None) is not None:
self.core.lgd.config.remove_option(f"{self.name}.env", "DXVK_HUD")
if not self.core.lgd.config[f"{self.name}.env"]:
self.core.lgd.config.remove_section(f"{self.name}.env")
self.core.lgd.save_config()
self.load_settings()
class DxvkWidget(QGroupBox):
def __init__(self, core: LegendaryCore):
def __init__(self, core: LegendaryCore, name=None):
super(DxvkWidget, self).__init__()
self.core = core
self.setObjectName("settings_widget")
@ -23,7 +109,7 @@ class DxvkWidget(QGroupBox):
"api": [False, self.tr("D3D Level of application")],
"frametime": [False, self.tr("Frame time graph")]
}
self.name = "default"
self.name = name
self.layout = QVBoxLayout()
self.child_layout = QHBoxLayout()
self.setTitle(self.tr("dxvk settings"))

View file

@ -1,71 +1,166 @@
import os.path
from logging import getLogger
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QIntValidator
from PyQt5.QtWidgets import QVBoxLayout, QFileDialog, QPushButton, QLineEdit, QGroupBox, QMessageBox, \
QScrollArea
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QStackedWidget, QVBoxLayout, QDialog, QCheckBox, QLabel, \
QHBoxLayout, QPushButton, QGroupBox, QWidget
from custom_legendary.core import LegendaryCore
from rare.components.tabs.settings.settings_widget import SettingsWidget
from rare.ui.components.tabs.settings.legendary import Ui_legendary_settings
from rare.utils.extra_widgets import PathEdit
from rare.utils.utils import get_size
logger = getLogger("LegendarySettings")
class LegendarySettings(QScrollArea):
class LegendarySettings(QStackedWidget, Ui_legendary_settings):
def __init__(self, core: LegendaryCore):
super(LegendarySettings, self).__init__()
self.widget = QGroupBox(self.tr("Legendary settings"))
self.setWidgetResizable(True)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.layout = QVBoxLayout()
self.setupUi(self)
self.core = core
self.widget.setObjectName("group")
# Default installation directory
self.select_path = PathEdit(core.get_default_install_dir(), type_of_file=QFileDialog.DirectoryOnly,
infotext="Default")
self.select_path.text_edit.textChanged.connect(lambda t: self.save_path_button.setDisabled(False))
self.save_path_button = QPushButton("Save")
self.save_path_button.clicked.connect(self.save_path)
self.install_dir_widget = SettingsWidget(self.tr("Default installation directory"), self.select_path,
self.save_path_button)
self.layout.addWidget(self.install_dir_widget)
self.install_dir = PathEdit(core.get_default_install_dir(),
file_type=QFileDialog.DirectoryOnly,
save_func=self.save_path)
self.layout_install_dir.addWidget(self.install_dir)
# Max Workers
self.max_worker_select = QLineEdit(self.core.lgd.config["Legendary"].get("max_workers"))
self.max_worker_select.setValidator(QIntValidator())
self.max_worker_select.setPlaceholderText("Default")
self.max_worker_select.textChanged.connect(self.max_worker_save)
self.max_worker_widget = SettingsWidget(self.tr("Max workers for Download (Less: slower download)(0: Default)"),
self.max_worker_select)
self.layout.addWidget(self.max_worker_widget)
max_workers = self.core.lgd.config["Legendary"].get("max_workers", fallback=0)
self.max_worker_select.setValue(int(max_workers))
self.max_worker_select.valueChanged.connect(self.max_worker_save)
# cleanup
self.clean_layout = QVBoxLayout()
self.cleanup_widget = QGroupBox(self.tr("Cleanup"))
self.clean_button = QPushButton(self.tr("Remove everything"))
self.clean_button.clicked.connect(lambda: self.cleanup(False))
self.clean_layout.addWidget(self.clean_button)
# Cleanup
self.clean_button.clicked.connect(
lambda: self.cleanup(False)
)
self.clean_button_without_manifests.clicked.connect(
lambda: self.cleanup(True)
)
self.setCurrentIndex(0)
self.clean_button_without_manifests = QPushButton(self.tr("Clean, but keep manifests"))
self.clean_button_without_manifests.clicked.connect(lambda: self.cleanup(True))
self.clean_layout.addWidget(self.clean_button_without_manifests)
self.back_button.clicked.connect(lambda: self.setCurrentIndex(0))
self.cleanup_widget.setLayout(self.clean_layout)
self.layout.addWidget(self.cleanup_widget)
self.path_info.setText(self.tr(r"EGL path is at C:\ProgramData\Epic\EpicGamesLauncher\Data\Manifests"))
path = os.path.expanduser("~/")
if self.core.egl.programdata_path:
path = self.core.egl.programdata_path
else:
possible_wine_prefixes = [os.path.expanduser("~/.wine"),
os.path.expanduser("~/Games/epic-games-store")]
for i in possible_wine_prefixes:
if os.path.exists(p := os.path.join(i, "drive_c/ProgramData/Epic/EpicGamesLauncher/Data/Manifests")):
path = p
self.layout.addStretch(1)
self.widget.setLayout(self.layout)
self.setWidget(self.widget)
self.path_edit = PathEdit(path, QFileDialog.DirectoryOnly, save_func=self.save_egl_path)
self.pathedit_placeholder.addWidget(self.path_edit)
if os.name != "nt":
self.core.lgd.config.set("Legendary", "egl_programdata")
self.core.egl.programdata_path = path
self.importable_widgets = []
self.exportable_widgets = []
if self.core.egl_sync_enabled:
self.sync_button.setText(self.tr("Disable sync"))
else:
self.sync_button.setText(self.tr("Enable Sync"))
self.sync_button.clicked.connect(self.sync)
self.enable_sync_button.clicked.connect(self.enable_sync)
self.sync_once_button.clicked.connect(self.core.egl_sync)
def enable_sync(self):
if not self.core.egl.programdata_path:
if os.path.exists(path := self.path_edit.text()):
self.core.lgd.config.set("Legendary", "egl_programdata", path)
self.core.lgd.save_config()
self.core.egl.programdata_path = path
self.core.lgd.config.set('Legendary', 'egl_sync', "true")
self.core.egl_sync()
self.core.lgd.save_config()
self.sync_button.setText(self.tr("Disable Sync"))
self.enable_sync_button.setDisabled(True)
def export_all(self):
for w in self.exportable_widgets:
w.export_game()
def import_all(self):
for w in self.importable_widgets:
w.import_game()
def save_egl_path(self):
self.core.lgd.config.set("Legendary", "egl_programdata", self.path_edit.text())
self.core.egl.programdata_path = self.path_edit.text()
self.core.lgd.save_config()
self.update_egl_widget()
def sync(self):
if self.core.egl_sync_enabled:
# disable sync
info = DisableSyncDialog().get_information()
if info[0] == 0:
if info[1]:
self.core.lgd.config.remove_option('Legendary', 'egl_sync')
else:
self.core.lgd.config.remove_option('Legendary', 'egl_programdata')
self.core.lgd.config.remove_option('Legendary', 'egl_sync')
# remove EGL GUIDs from all games, DO NOT remove .egstore folders because that would fuck things up.
for igame in self.core.get_installed_list():
igame.egl_guid = ''
self.core.install_game(igame)
self.core.lgd.save_config()
self.sync_button.setText(self.tr("Enable Sync"))
else:
# enable sync
self.enable_sync_button.setDisabled(False)
self.update_egl_widget()
self.setCurrentIndex(1)
def update_egl_widget(self):
self.exportable_widgets = []
QWidget().setLayout(self.exportable_games.layout())
QWidget().setLayout(self.importable_games.layout())
importable_layout = QVBoxLayout()
self.importable_games.setLayout(importable_layout)
exportable_layout = QVBoxLayout()
self.exportable_games.setLayout(exportable_layout)
if not self.core.egl.programdata_path:
self.importable_games.setVisible(False)
self.exportable_games.setVisible(False)
self.export_all_button.setVisible(False)
self.import_all_button.setVisible(False)
return
self.importable_games.setVisible(True)
self.exportable_games.setVisible(True)
self.export_all_button.setVisible(True)
self.import_all_button.setVisible(True)
for igame in self.core.egl_get_exportable():
w = EGLSyncWidget(igame, True, self.core)
self.importable_widgets.append(w)
self.exportable_games.layout().addWidget(w)
if len(self.core.egl_get_exportable()) == 0:
self.exportable_games.layout().addWidget(QLabel(self.tr("No games to export")))
self.importable_widgets = []
for game in self.core.egl_get_importable():
w = EGLSyncWidget(game, False, self.core)
self.importable_widgets.append(w)
self.importable_games.layout().addWidget(w)
if len(self.core.egl_get_importable()) == 0:
self.importable_games.layout().addWidget(QLabel(self.tr("No games to import")))
def save_path(self):
self.core.lgd.config["Legendary"]["install_dir"] = self.select_path.text()
if self.select_path.text() == "" and "install_dir" in self.core.lgd.config["Legendary"].keys():
self.core.lgd.config["Legendary"]["install_dir"] = self.install_dir.text()
if self.install_dir.text() == "" and "install_dir" in self.core.lgd.config["Legendary"].keys():
self.core.lgd.config["Legendary"].pop("install_dir")
else:
logger.info("Set config install_dir to " + self.select_path.text())
logger.info("Set config install_dir to " + self.install_dir.text())
self.core.lgd.save_config()
def max_worker_save(self, num_workers: str):
@ -102,3 +197,75 @@ class LegendarySettings(QScrollArea):
get_size(before - after)))
else:
QMessageBox.information(self, "Cleanup", "Nothing to clean")
class DisableSyncDialog(QDialog):
info = 1, False
def __init__(self):
super(DisableSyncDialog, self).__init__()
self.layout = QVBoxLayout()
self.question = QLabel(self.tr("Do you really want to disable sync with Epic Games Store"))
self.layout.addWidget(self.question)
self.remove_metadata = QCheckBox(self.tr("Remove metadata from installed games"))
self.layout.addWidget(self.remove_metadata)
self.button_layout = QHBoxLayout()
self.button_layout.addStretch(1)
self.ok_button = QPushButton(self.tr("Ok"))
self.cancel_button = QPushButton(self.tr("Cancel"))
self.ok_button.clicked.connect(self.ok)
self.cancel_button.clicked.connect(self.cancel)
self.button_layout.addWidget(self.ok_button)
self.button_layout.addWidget(self.cancel_button)
self.layout.addStretch(1)
self.layout.addLayout(self.button_layout)
self.setLayout(self.layout)
def ok(self):
self.info = 0, self.remove_metadata.isChecked()
self.close()
def cancel(self):
self.close()
def get_information(self):
self.exec_()
return self.info
class EGLSyncWidget(QGroupBox):
def __init__(self, game, export: bool, core: LegendaryCore):
super(EGLSyncWidget, self).__init__()
self.layout = QVBoxLayout()
self.export = export
self.core = core
self.game = game
if export:
self.app_title_label = QLabel(game.title)
else:
title = self.core.get_game(game.app_name).app_title
self.app_title_label = QLabel(title)
self.layout.addWidget(self.app_title_label)
self.button = QPushButton(self.tr("Export") if export else self.tr("Import"))
if export:
self.button.clicked.connect(self.export_game)
else:
self.button.clicked.connect(self.import_game)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
def export_game(self):
self.core.egl_export(self.game.app_name)
def import_game(self):
self.core.egl_import(self.game.app_name)

View file

@ -1,55 +1,50 @@
from logging import getLogger
from PyQt5.QtWidgets import QVBoxLayout, QPushButton, QFileDialog, QLineEdit, QGroupBox
from PyQt5.QtWidgets import QFileDialog, QWidget
from custom_legendary.core import LegendaryCore
from rare.components.tabs.settings.dxvk import DxvkWidget
from rare.components.tabs.settings.settings_widget import SettingsWidget
from rare.components.tabs.settings.dxvk import DxvkSettings, DxvkWidget
from rare.ui.components.tabs.settings.linux import Ui_LinuxSettings
from rare.utils.extra_widgets import PathEdit
logger = getLogger("LinuxSettings")
class LinuxSettings(QGroupBox):
def __init__(self, core: LegendaryCore, name="default"):
class LinuxSettings(QWidget, Ui_LinuxSettings):
def __init__(self, core: LegendaryCore, name=None):
super(LinuxSettings, self).__init__()
self.layout = QVBoxLayout()
self.name = name
self.setupUi(self)
self.name = name if name is not None else "default"
self.core = core
self.setTitle(self.tr("Linux settings"))
self.setObjectName("group")
# Wineprefix
self.select_path = PathEdit(self.core.lgd.config.get(self.name, "wine_prefix", fallback=""),
type_of_file=QFileDialog.DirectoryOnly,
infotext="Default")
self.select_path.text_edit.textChanged.connect(lambda t: self.save_path_button.setDisabled(False))
self.save_path_button = QPushButton("Save")
self.save_path_button.clicked.connect(lambda: self.save_setting(self.select_path, "wine_prefix"))
self.install_dir_widget = SettingsWidget(self.tr("Default Wine Prefix"), self.select_path,
self.save_path_button)
self.layout.addWidget(self.install_dir_widget)
# Wine prefix
self.wine_prefix = PathEdit(self.core.lgd.config.get(self.name, "wine_prefix", fallback=""),
file_type=QFileDialog.DirectoryOnly,
save_func=lambda: self.save_setting(self.wine_prefix, "wine_prefix"))
self.prefix_layout.addWidget(self.wine_prefix)
# Wine executable
self.select_wine_exec = QLineEdit(self.core.lgd.config.get(self.name, "wine_executable", fallback=""))
self.save_wine_exec = QPushButton("Save")
self.save_wine_exec.clicked.connect(lambda: self.save_setting(self.select_wine_exec, "wine_executable"))
self.install_dir_widget = SettingsWidget(self.tr("Default Wine executable"), self.select_wine_exec,
self.save_wine_exec)
self.layout.addWidget(self.install_dir_widget)
self.wine_exec = PathEdit(self.core.lgd.config.get(self.name, "wine_executable", fallback=""),
file_type=QFileDialog.ExistingFile,
name_filter="Wine executable (wine wine64)",
save_func=lambda: self.save_setting(self.wine_exec, "wine_executable"))
self.exec_layout.addWidget(self.wine_exec)
# dxvk
self.dxvk_widget = DxvkWidget(core)
self.layout.addWidget(self.dxvk_widget)
if name == "default":
self.layout.addStretch(1)
self.setLayout(self.layout)
# FIXME: Remove this check when done with per game settings
if name is None:
self.dxvk = DxvkSettings(core, self.name)
else:
self.dxvk = DxvkWidget(core)
self.dxvk_layout.addWidget(self.dxvk)
def save_setting(self, widget: QLineEdit, setting_name: str):
if not self.name in self.core.lgd.config.sections():
def save_setting(self, widget: PathEdit, setting_name: str):
if self.name not in self.core.lgd.config.sections():
self.core.lgd.config.add_section(self.name)
self.core.lgd.config.set(self.name, setting_name, widget.text())
if widget.text() == "":
if not widget.text():
self.core.lgd.config.remove_option(self.name, setting_name)
else:
logger.info("Set config of wine_prefix to " + widget.text())

View file

@ -5,12 +5,12 @@ import sys
from logging import getLogger
from PyQt5.QtCore import QSettings, Qt
from PyQt5.QtWidgets import QVBoxLayout, QFileDialog, QComboBox, QPushButton, QCheckBox, QGroupBox, QScrollArea
from PyQt5.QtWidgets import QFileDialog, QWidget
from rare.components.tabs.settings.rpc_settings import RPCSettings
from rare.components.tabs.settings.settings_widget import SettingsWidget
from rare.ui.components.tabs.settings.rare import Ui_RareSettings
from rare.utils.extra_widgets import PathEdit
from rare.utils.utils import get_lang, get_possible_langs
from rare.utils.utils import get_lang, get_possible_langs, get_color_schemes, get_style_sheets
logger = getLogger("RareSettings")
@ -21,89 +21,130 @@ languages = [
]
class RareSettings(QScrollArea):
class RareSettings(QWidget, Ui_RareSettings):
def __init__(self):
super(RareSettings, self).__init__()
self.widget = QGroupBox(self.tr("Rare settings"))
self.widget.setObjectName("group")
self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
self.setWidgetResizable(True)
# (option_name, group_text, checkbox_text, default
self.setupUi(self)
# (widget_name, option_name, default)
self.checkboxes = [
("sys_tray", self.tr("Hide to System Tray Icon"), self.tr("Exit to System Tray Icon"), True),
("auto_update", self.tr("Automatically update Games on startup"), self.tr("Auto updates"),
False),
("confirm_start", self.tr("Confirm launch of game"), self.tr("Confirm launch of game"),
False),
("auto_sync_cloud", self.tr("Auto sync with cloud"), self.tr("Sync with cloud"), True),
("notification", self.tr("Show Notifications after Downloads"), self.tr("Show notification"),
True),
("save_size", self.tr("Save size of window after restart"), self.tr("Save size"), False)
(self.sys_tray, "sys_tray", True),
(self.auto_update, "auto_update", False),
(self.confirm_start, "confirm_start", False),
(self.auto_sync_cloud, "auto_sync_cloud", True),
(self.notification, "notification", True),
(self.save_size, "save_size", False)
]
self.layout = QVBoxLayout()
self.settings = QSettings()
img_dir = self.settings.value("img_dir", os.path.expanduser("~/.cache/rare/images/"), type=str)
self.img_dir_path = self.settings.value("img_dir", os.path.expanduser("~/.cache/rare/images/"), type=str)
language = self.settings.value("language", get_lang(), type=str)
# select Image dir
self.select_path = PathEdit(img_dir, type_of_file=QFileDialog.DirectoryOnly)
self.select_path.text_edit.textChanged.connect(lambda t: self.save_path_button.setDisabled(False))
self.save_path_button = QPushButton(self.tr("Save"))
self.save_path_button.clicked.connect(self.save_path)
self.img_dir = SettingsWidget(self.tr("Image Directory"), self.select_path, self.save_path_button)
self.layout.addWidget(self.img_dir)
self.logdir = os.path.expanduser("~/.cache/rare/logs")
# Select Image directory
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)
# Select lang
self.select_lang = QComboBox()
self.select_lang.addItems([i[1] for i in languages])
self.lang_select.addItems([i[1] for i in languages])
if language in get_possible_langs():
index = [lang[0] for lang in languages].index(language)
self.select_lang.setCurrentIndex(index)
self.lang_select.setCurrentIndex(index)
else:
self.select_lang.setCurrentIndex(0)
self.lang_widget = SettingsWidget(self.tr("Language"), self.select_lang)
self.select_lang.currentIndexChanged.connect(self.update_lang)
self.layout.addWidget(self.lang_widget)
self.lang_select.setCurrentIndex(0)
self.lang_select.currentIndexChanged.connect(self.update_lang)
colors = get_color_schemes()
self.color_select.addItems(colors)
if (color := self.settings.value("color_scheme")) in colors:
self.color_select.setCurrentIndex(self.color_select.findText(color))
self.color_select.setDisabled(False)
self.style_select.setDisabled(True)
else:
self.color_select.setCurrentIndex(0)
self.color_select.currentIndexChanged.connect(self.on_color_select_changed)
styles = get_style_sheets()
self.style_select.addItems(styles)
if (style := self.settings.value("style_sheet")) in styles:
self.style_select.setCurrentIndex(self.style_select.findText(style))
self.style_select.setDisabled(False)
self.color_select.setDisabled(True)
else:
self.style_select.setCurrentIndex(0)
self.style_select.currentIndexChanged.connect(self.on_style_select_changed)
self.interface_info.setVisible(False)
self.rpc = RPCSettings()
self.layout.addWidget(self.rpc)
self.rpc_layout.addWidget(self.rpc, alignment=Qt.AlignTop)
for option, head_text, text, default in self.checkboxes:
checkbox = SettingsCheckbox(option, text, default)
settings_widget = SettingsWidget(head_text, checkbox)
self.layout.addWidget(settings_widget)
self.init_checkboxes(self.checkboxes)
self.sys_tray.stateChanged.connect(
lambda: self.settings.setValue("sys_tray", self.sys_tray.isChecked())
)
self.auto_update.stateChanged.connect(
lambda: self.settings.setValue("auto_update", self.auto_update.isChecked())
)
self.confirm_start.stateChanged.connect(
lambda: self.settings.setValue("confirm_start", self.confirm_start.isChecked())
)
self.auto_sync_cloud.stateChanged.connect(
lambda: self.settings.setValue("auto_sync_cloud", self.auto_sync_cloud.isChecked())
)
self.notification.stateChanged.connect(
lambda: self.settings.setValue("notification", self.notification.isChecked())
)
self.save_size.stateChanged.connect(
lambda: self.settings.setValue("save_size", self.save_size.isChecked())
)
self.open_log_dir = QPushButton(self.tr("Open Log directory"))
self.layout.addWidget(self.open_log_dir)
self.open_log_dir.clicked.connect(self.open_dir)
self.log_dir_open_button.clicked.connect(self.open_dir)
# TODO: Implement
self.log_dir_clean_button.setVisible(False)
self.log_dir_size_label.setVisible(False)
self.layout.addStretch()
self.widget.setLayout(self.layout)
self.setWidget(self.widget)
def on_color_select_changed(self, color):
if color:
self.style_select.setCurrentIndex(0)
self.style_select.setDisabled(True)
self.settings.setValue("color_scheme", self.color_select.currentText())
else:
self.settings.setValue("color_scheme", "")
self.style_select.setDisabled(False)
self.interface_info.setVisible(True)
def on_style_select_changed(self, style):
if style:
self.color_select.setCurrentIndex(0)
self.color_select.setDisabled(True)
self.settings.setValue("style_sheet", self.style_select.currentText())
else:
self.settings.setValue("style_sheet", "")
self.color_select.setDisabled(False)
self.interface_info.setVisible(True)
def open_dir(self):
logdir = os.path.expanduser("~/.cache/rare/logs")
if os.name == "nt":
os.startfile(logdir)
os.startfile(self.logdir)
else:
opener = "open" if sys.platform == "darwin" else "xdg-open"
subprocess.Popen([opener, logdir])
subprocess.Popen([opener, self.logdir])
def save_window_size(self):
self.settings.setValue("save_size", self.save_size.isChecked())
self.settings.remove("window_size")
def save_path(self):
self.save_path_button.setDisabled(True)
self.update_path()
def update_lang(self, i: int):
self.settings.setValue("language", languages[i][0])
self.lang_widget.info_text.setText(self.tr("Restart Application to activate changes"))
self.interface_info.setVisible(True)
def update_path(self):
old_path = self.settings.value("img_dir", type=str)
new_path = self.select_path.text()
old_path = self.img_dir_path
new_path = self.img_dir.text()
if old_path != new_path:
if not os.path.exists(new_path):
@ -113,15 +154,15 @@ class RareSettings(QScrollArea):
return
logger.info("Move Images")
for i in os.listdir(old_path):
shutil.move(os.path.join(old_path, i), os.path.join(new_path, i))
try:
shutil.move(os.path.join(old_path, i), os.path.join(new_path, i))
except:
pass
os.rmdir(old_path)
self.img_dir_path = new_path
self.settings.setValue("img_dir", new_path)
class SettingsCheckbox(QCheckBox):
def __init__(self, option, text, default):
super(SettingsCheckbox, self).__init__(text)
self.option = option
self.settings = QSettings()
self.setChecked(self.settings.value(option, default, bool))
self.stateChanged.connect(lambda: self.settings.setValue(option, self.isChecked()))
def init_checkboxes(self, checkboxes):
for cb in checkboxes:
widget, option, default = cb
widget.setChecked(self.settings.value(option, default, bool))

View file

@ -1,40 +1,35 @@
from PyQt5.QtCore import QSettings, pyqtSignal
from PyQt5.QtWidgets import QGroupBox, QCheckBox, QVBoxLayout, QComboBox
from PyQt5.QtWidgets import QGroupBox
from rare.ui.components.tabs.settings.rpc_settings import Ui_RPCSettings
class RPCSettings(QGroupBox):
class RPCSettings(QGroupBox, Ui_RPCSettings):
update_settings = pyqtSignal()
def __init__(self):
super(RPCSettings, self).__init__()
self.setTitle(self.tr("Discord RPC"))
self.setObjectName("settings_widget")
self.settings = QSettings()
self.layout = QVBoxLayout()
self.setupUi(self)
self.settings = QSettings()
self.enable = QComboBox()
self.enable_states = [self.tr("Show when playing"), self.tr("Show always"), self.tr("Show never")]
self.enable.addItems(self.enable_states)
self.enable.setCurrentIndex(self.settings.value("rpc_enable", 0, int))
self.layout.addWidget(self.enable)
self.enable.currentIndexChanged.connect(self.changed)
self.show_game = QCheckBox(self.tr("Show Game"))
self.show_game.setChecked((self.settings.value("rpc_name", True, bool)))
self.layout.addWidget(self.show_game)
self.show_game.stateChanged.connect(lambda: self.settings.setValue("rpc_game", self.show_game.isChecked()))
self.show_game.stateChanged.connect(
lambda: self.settings.setValue("rpc_game", self.show_game.isChecked())
)
self.show_os = QCheckBox(self.tr("Show OS"))
self.layout.addWidget(self.show_os)
self.show_os.setChecked((self.settings.value("rpc_os", True, bool)))
self.show_os.stateChanged.connect(lambda: self.settings.setValue("rpc_os", self.show_os.isChecked()))
self.show_os.stateChanged.connect(
lambda: self.settings.setValue("rpc_os", self.show_os.isChecked())
)
self.show_time = QCheckBox(self.tr("Show Time playing"))
self.layout.addWidget(self.show_time)
self.show_time.setChecked((self.settings.value("rpc_time", True, bool)))
self.show_time.stateChanged.connect(lambda: self.settings.setValue("rpc_time", self.show_time.isChecked()))
self.setLayout(self.layout)
self.show_time.stateChanged.connect(
lambda: self.settings.setValue("rpc_time", self.show_time.isChecked())
)
def changed(self, i):
self.settings.setValue("rpc_enable", i)

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,153 +0,0 @@
QWidget {
background-color: #202225;
color: white;
}
QLabel {
background-color: transparent;
}
QTabBar#main_tab_bar {
border-bottom: none;
background-color: #2b2b2c;
}
QTabBar::tab#main_tab_bar {
border-bottom: none;
}
QTabBar::tab#main_tab_bar {
border-bottom: none;
padding: 5px
}
QTabBar::tab:selected#main_tab_bar {
background-color: gray;
}
QTabBar::tab:hover#main_tab_bar {
border-bottom: 2px solid black;
}
QGroupBox {
padding: 4px;
margin: 8px;
}
QGroupBox#settings_widget {
border: 1px solid gray;
font-size: 13px;
border-radius: 3px;
margin-top: 1ex;
padding-top: 4px;
padding-bottom: 4px;
}
QGroupBox#game_widget_icon {
border: none;
padding: 0;
margin: 0;
}
QGroupBox#group {
font-size: 15px;
font-weight: bold;
border: 1px solid white;
margin-top: 10px;
padding: 8px;
}
QTabBar::tab:disabled {
color: transparent;
background-color: transparent;
}
QToolButton {
padding: 6px;
}
QPushButton {
border: 1px solid white;
border-radius: 4px;
background-color: #3c3f41;
padding: 3px;
}
QPushButton:hover {
background-color: #223;
}
QPushButton::menu-indicator {
subcontrol-position: right center;
subcontrol-origin: padding;
left: -2px;
border-style: none;
}
QPushButton#menu {
padding: 0px;
margin: 0px;
border-style: none;
}
QPushButton#menu_button {
background-color: transparent;
border: none;
}
QPushButton:hover#menu_button {
background-color: #334;
}
QLineEdit {
border: 1px solid white;
}
QCheckBox {
color: #F0F0F0;
background-color: none;
}
QCheckBox::indicator {
}
#list_widget {
border-top: 2px solid white;
}
QPushButton:hover#installed_menu_button {
background-color: green;
}
QTabBar::tab#settings_bar {
border-radius: 0;
}
QTabBar::tab:hover#settings_bar {
border-left: 2px solid white;
}
QTabBar::tab::selected#settings_bar {
background-color: darkslategrey;
}
#search_bar {
padding: 3px;
border-radius: 5px;
background-color: #334;
}
/*
QScrollBar:vertical{
border: 1px solid white;
}
QScrollBar::handle:vertical{
background-color: gray;
border-radius: 4px;
}
*/

View file

@ -0,0 +1,61 @@
[ColorScheme]
Active\AlternateBase=#2f2f2f
Active\Base=#333333
Active\BrightText=#ffffff
Active\Button=#525252
Active\ButtonText=#dddddd
Active\Dark=#333333
Active\Highlight=#f0544c
Active\HighlightedText=#ffffff
Active\Light=#555555
Active\Link=#fc6f5d
Active\LinkVisited=#853931
Active\Mid=#a0a0a4
Active\Midlight=#e9e7e3
Active\PlaceholderText=#eeeeee
Active\Shadow=#343434
Active\Text=#eeeeee
Active\ToolTipBase=#444444
Active\ToolTipText=#eeeeee
Active\Window=#444444
Active\WindowText=#dddddd
Disabled\AlternateBase=#2f2f2f
Disabled\Base=#333333
Disabled\BrightText=#ffffff
Disabled\Button=#525252
Disabled\ButtonText=#808080
Disabled\Dark=#333333
Disabled\Highlight=#f0544c
Disabled\HighlightedText=#808080
Disabled\Light=#555555
Disabled\Link=#fc6f5d
Disabled\LinkVisited=#853931
Disabled\Mid=#a0a0a4
Disabled\Midlight=#e9e7e3
Disabled\PlaceholderText=#eeeeee
Disabled\Shadow=#343434
Disabled\Text=#808080
Disabled\ToolTipBase=#444444
Disabled\ToolTipText=#eeeeee
Disabled\Window=#444444
Disabled\WindowText=#808080
Inactive\AlternateBase=#2f2f2f
Inactive\Base=#333333
Inactive\BrightText=#ffffff
Inactive\Button=#525252
Inactive\ButtonText=#dddddd
Inactive\Dark=#333333
Inactive\Highlight=#f0544c
Inactive\HighlightedText=#ffffff
Inactive\Light=#555555
Inactive\Link=#fc6f5d
Inactive\LinkVisited=#853931
Inactive\Mid=#a0a0a4
Inactive\Midlight=#e9e7e3
Inactive\PlaceholderText=#eeeeee
Inactive\Shadow=#343434
Inactive\Text=#eeeeee
Inactive\ToolTipBase=#444444
Inactive\ToolTipText=#eeeeee
Inactive\Window=#444444
Inactive\WindowText=#dddddd

View file

@ -0,0 +1,61 @@
[ColorScheme]
Active\AlternateBase=#f7f7f7
Active\Base=#333344
Active\BrightText=#ffffff
Active\Button=#3c3f41
Active\ButtonText=#eeeeee
Active\Dark=#9f0910
Active\Highlight=#2f4f4f
Active\HighlightedText=#eeeeee
Active\Light=#ffffff
Active\Link=#0000ff
Active\LinkVisited=#ff00ff
Active\Mid=#b80e35
Active\Midlight=#ca0651
Active\PlaceholderText=#eeeeee
Active\Shadow=#767676
Active\Text=#eeeeee
Active\ToolTipBase=#ffffdc
Active\ToolTipText=#eeeeee
Active\Window=#202225
Active\WindowText=#eeeeee
Disabled\AlternateBase=#f7f7f7
Disabled\Base=#333344
Disabled\BrightText=#ffffff
Disabled\Button=#3c3f41
Disabled\ButtonText=#808080
Disabled\Dark=#9f0910
Disabled\Highlight=#2f4f4f
Disabled\HighlightedText=#808080
Disabled\Light=#ffffff
Disabled\Link=#0000ff
Disabled\LinkVisited=#ff00ff
Disabled\Mid=#b80e35
Disabled\Midlight=#ca0651
Disabled\PlaceholderText=#eeeeee
Disabled\Shadow=#767676
Disabled\Text=#808080
Disabled\ToolTipBase=#ffffdc
Disabled\ToolTipText=#eeeeee
Disabled\Window=#202225
Disabled\WindowText=#808080
Inactive\AlternateBase=#f7f7f7
Inactive\Base=#333344
Inactive\BrightText=#ffffff
Inactive\Button=#3c3f41
Inactive\ButtonText=#eeeeee
Inactive\Dark=#9f0910
Inactive\Highlight=#2f4f4f
Inactive\HighlightedText=#eeeeee
Inactive\Light=#ffffff
Inactive\Link=#0000ff
Inactive\LinkVisited=#ff00ff
Inactive\Mid=#b80e35
Inactive\Midlight=#ca0651
Inactive\PlaceholderText=#eeeeee
Inactive\Shadow=#767676
Inactive\Text=#eeeeee
Inactive\ToolTipBase=#ffffdc
Inactive\ToolTipText=#eeeeee
Inactive\Window=#202225
Inactive\WindowText=#eeeeee

View file

@ -0,0 +1,61 @@
[ColorScheme]
Active\AlternateBase=#eff3f7
Active\Base=#eff3f7
Active\BrightText=#ffffff
Active\Button=#eff3f7
Active\ButtonText=#000000
Active\Dark=#c7cbce
Active\Highlight=#4965ae
Active\HighlightedText=#ffffff
Active\Light=#ffffff
Active\Link=#0000ff
Active\LinkVisited=#ff00ff
Active\Mid=#a0a0a4
Active\Midlight=#e9e7e3
Active\PlaceholderText=#000000
Active\Shadow=#b8bbbe
Active\Text=#000000
Active\ToolTipBase=#ffffdc
Active\ToolTipText=#000000
Active\Window=#eff3f7
Active\WindowText=#000000
Disabled\AlternateBase=#eff3f7
Disabled\Base=#eff3f7
Disabled\BrightText=#ffffff
Disabled\Button=#eff3f7
Disabled\ButtonText=#808080
Disabled\Dark=#c7cbce
Disabled\Highlight=#4965ae
Disabled\HighlightedText=#808080
Disabled\Light=#ffffff
Disabled\Link=#0000ff
Disabled\LinkVisited=#ff00ff
Disabled\Mid=#a0a0a4
Disabled\Midlight=#e9e7e3
Disabled\PlaceholderText=#000000
Disabled\Shadow=#b8bbbe
Disabled\Text=#808080
Disabled\ToolTipBase=#ffffdc
Disabled\ToolTipText=#000000
Disabled\Window=#eff3f7
Disabled\WindowText=#808080
Inactive\AlternateBase=#eff3f7
Inactive\Base=#eff3f7
Inactive\BrightText=#ffffff
Inactive\Button=#eff3f7
Inactive\ButtonText=#000000
Inactive\Dark=#c7cbce
Inactive\Highlight=#4965ae
Inactive\HighlightedText=#ffffff
Inactive\Light=#ffffff
Inactive\Link=#0000ff
Inactive\LinkVisited=#ff00ff
Inactive\Mid=#a0a0a4
Inactive\Midlight=#e9e7e3
Inactive\PlaceholderText=#000000
Inactive\Shadow=#b8bbbe
Inactive\Text=#000000
Inactive\ToolTipBase=#ffffdc
Inactive\ToolTipText=#000000
Inactive\Window=#eff3f7
Inactive\WindowText=#000000

View file

@ -0,0 +1,262 @@
QWidget {
background-color: #202225;
color: #eee;
}
QLabel {
background-color: transparent;
padding: 4px;
}
QLineEdit {
border: 1px solid darkslategrey;
border-radius: 2px;
background-color: #334;
padding: 2px;
}
QScrollBar {
border: 1px solid darkslategrey;
border-radius: 4px;
background-color: #334;
padding: 1px;
}
QScrollBar::add-line:vertical {
border: none;
background: transparent;
height: 0px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical {
border: none;
background: transparent;
height: 0px;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::add-line:horizontal {
border: none;
background: transparent;
height: 0px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal {
border: none;
background: green;
height: 0px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar::handle {
border: 1px solid darkslategrey;
background-color: gray;
border-radius: 4px;
min-height: 20px;
min-width: 20px;
}
QTabBar#main_tab_bar {
border-bottom: none;
background-color: #2b2b2c;
}
QTabBar::tab#main_tab_bar {
border-bottom: none;
}
QTabBar::tab#main_tab_bar {
border-bottom: none;
padding: 5px
}
QTabBar::tab:selected#main_tab_bar {
background-color: gray;
}
QTabBar::tab:hover#main_tab_bar {
border-bottom: 2px solid black;
}
QGroupBox {
border: 1px solid gray;
font-size: 13px;
font-weight: bold;
border-radius: 6px;
margin-top: 3ex;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
}
QGroupBox#settings_widget {
border: 1px solid gray;
font-size: 13px;
font-weight: bold;
border-radius: 6px;
margin-top: 3ex;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
}
QGroupBox#game_widget_icon {
border: none;
padding: 0;
margin: 0;
}
QGroupBox#group {
border: 1px solid gray;
font-size: 13px;
font-weight: bold;
border-radius: 6px;
margin-top: 3ex;
padding-top: 0px;
padding-bottom: 0px;
padding-left: 0px;
padding-right: 0px;
}
QToolButton {
border: 1px solid gray;
border-radius: 2px;
background-color: #3c3f41;
padding: 4px;
}
QToolButton:hover {
background-color: #223;
}
QPushButton {
border: 1px solid gray;
border-radius: 2px;
background-color: #3c3f41;
padding: 5px;
}
QPushButton:hover {
background-color: #223;
}
QPushButton::menu-indicator {
subcontrol-position: right center;
subcontrol-origin: padding;
left: -2px;
border-style: none;
}
QPushButton#menu {
padding: 0px;
margin: 0px;
border-style: none;
}
QPushButton#menu_button {
background-color: transparent;
border: none;
}
QPushButton:hover#menu_button {
background-color: #334;
}
QRadioButton {
background-color: none;
border-radius: 50%;
}
QRadioButton::indicator {
border: 1px solid gray;
border-radius: 5%;
}
QCheckBox {
background-color: none;
}
QCheckBox::indicator {
border: 1px solid gray;
border-radius: 2px;
}
QCheckBox::indicator:checked {
width: -20ex;
height: -20ex;
background: #5F5F80;
border-radius: 10px;
}
QSpinBox {
border: 1px solid darkslategrey;
border-radius: 2px;
background-color: #334;
padding: 2px;
}
/*
QCheckBox::indicator {
border: 1px solid gray;
}
*/
QComboBox {
border: 1px solid gray;
border-radius: 2px;
background-color: #3c3f41;
padding: 5px;
}
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
/*
border-left-width: 1px;
border-left-color: darkgray;
border-left-style: solid;
*/
border-top-right-radius: 3px;
border-bottom-right-radius: 3px;
}
#list_widget {
border-top: 2px solid white;
}
QPushButton:hover#installed_menu_button {
background-color: green;
}
QTabBar::tab#settings_bar {
border-radius: 0;
}
QTabBar::tab:hover#settings_bar {
border-left: 2px solid white;
}
QTabBar::tab::selected#settings_bar {
background-color: darkslategrey;
}
#search_bar {
padding: 3px;
border-radius: 5px;
background-color: #334;
}
QTabBar::tab:disabled#settings_bar {
color: transparent;
background-color: transparent;
}

0
rare/ui/__init__.py Normal file
View file

View file

View file

View file

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'launch_dialog.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_LaunchDialog(object):
def setupUi(self, LaunchDialog):
LaunchDialog.setObjectName("LaunchDialog")
LaunchDialog.resize(400, 168)
self.verticalLayout = QtWidgets.QVBoxLayout(LaunchDialog)
self.verticalLayout.setObjectName("verticalLayout")
self.title_label = QtWidgets.QLabel(LaunchDialog)
self.title_label.setObjectName("title_label")
self.verticalLayout.addWidget(self.title_label)
self.image_prog_bar = QtWidgets.QProgressBar(LaunchDialog)
self.image_prog_bar.setProperty("value", 0)
self.image_prog_bar.setObjectName("image_prog_bar")
self.verticalLayout.addWidget(self.image_prog_bar)
self.image_info = QtWidgets.QLabel(LaunchDialog)
self.image_info.setObjectName("image_info")
self.verticalLayout.addWidget(self.image_info)
self.steam_prog_bar = QtWidgets.QProgressBar(LaunchDialog)
self.steam_prog_bar.setProperty("value", 0)
self.steam_prog_bar.setObjectName("steam_prog_bar")
self.verticalLayout.addWidget(self.steam_prog_bar)
self.steam_info = QtWidgets.QLabel(LaunchDialog)
self.steam_info.setObjectName("steam_info")
self.verticalLayout.addWidget(self.steam_info)
self.retranslateUi(LaunchDialog)
QtCore.QMetaObject.connectSlotsByName(LaunchDialog)
def retranslateUi(self, LaunchDialog):
_translate = QtCore.QCoreApplication.translate
LaunchDialog.setWindowTitle(_translate("LaunchDialog", "Dialog"))
self.title_label.setText(_translate("LaunchDialog", "<h2>Launching Rare</h2>"))
self.image_info.setText(_translate("LaunchDialog", "Downloading images"))
self.steam_info.setText(_translate("LaunchDialog", "Getting Steam grades"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
LaunchDialog = QtWidgets.QDialog()
ui = Ui_LaunchDialog()
ui.setupUi(LaunchDialog)
LaunchDialog.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LaunchDialog</class>
<widget class="QDialog" name="LaunchDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>168</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="title_label">
<property name="text">
<string>&lt;h2&gt;Launching Rare&lt;/h2&gt;</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="image_prog_bar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="image_info">
<property name="text">
<string>Downloading images</string>
</property>
</widget>
</item>
<item>
<widget class="QProgressBar" name="steam_prog_bar">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="steam_info">
<property name="text">
<string>Getting Steam grades</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

View file

@ -0,0 +1,214 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'game_info.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_GameInfo(object):
def setupUi(self, GameInfo):
GameInfo.setObjectName("GameInfo")
self.layout_game_info = QtWidgets.QGridLayout(GameInfo)
self.layout_game_info.setObjectName("layout_game_info")
self.layout_game_info_form = QtWidgets.QGridLayout()
self.layout_game_info_form.setContentsMargins(6, 6, 6, 6)
self.layout_game_info_form.setSpacing(12)
self.layout_game_info_form.setObjectName("layout_game_info_form")
self.install_size = QtWidgets.QLabel(GameInfo)
self.install_size.setText("error")
self.install_size.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.install_size.setObjectName("install_size")
self.layout_game_info_form.addWidget(self.install_size, 4, 1, 1, 1)
self.lbl_dev = QtWidgets.QLabel(GameInfo)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_dev.sizePolicy().hasHeightForWidth())
self.lbl_dev.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lbl_dev.setFont(font)
self.lbl_dev.setObjectName("lbl_dev")
self.layout_game_info_form.addWidget(self.lbl_dev, 0, 0, 1, 1, QtCore.Qt.AlignRight)
self.version = QtWidgets.QLabel(GameInfo)
self.version.setText("error")
self.version.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.version.setObjectName("version")
self.layout_game_info_form.addWidget(self.version, 2, 1, 1, 1)
self.lbl_install_path = QtWidgets.QLabel(GameInfo)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_install_path.sizePolicy().hasHeightForWidth())
self.lbl_install_path.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lbl_install_path.setFont(font)
self.lbl_install_path.setObjectName("lbl_install_path")
self.layout_game_info_form.addWidget(self.lbl_install_path, 5, 0, 1, 1, QtCore.Qt.AlignRight)
self.lbl_install_size = QtWidgets.QLabel(GameInfo)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_install_size.sizePolicy().hasHeightForWidth())
self.lbl_install_size.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lbl_install_size.setFont(font)
self.lbl_install_size.setObjectName("lbl_install_size")
self.layout_game_info_form.addWidget(self.lbl_install_size, 4, 0, 1, 1, QtCore.Qt.AlignRight)
spacerItem = QtWidgets.QSpacerItem(0, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.layout_game_info_form.addItem(spacerItem, 7, 1, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.layout_game_info_form.addItem(spacerItem1, 7, 0, 1, 1)
self.wg_game_actions = QtWidgets.QWidget(GameInfo)
self.wg_game_actions.setMinimumSize(QtCore.QSize(250, 0))
self.wg_game_actions.setObjectName("wg_game_actions")
self.layout_game_actions = QtWidgets.QVBoxLayout(self.wg_game_actions)
self.layout_game_actions.setContentsMargins(0, 0, 0, 0)
self.layout_game_actions.setObjectName("layout_game_actions")
self.uninstall_button = QtWidgets.QPushButton(self.wg_game_actions)
self.uninstall_button.setObjectName("uninstall_button")
self.layout_game_actions.addWidget(self.uninstall_button)
self.verify_widget = QtWidgets.QStackedWidget(self.wg_game_actions)
self.verify_widget.setObjectName("verify_widget")
self.page_verify_button = QtWidgets.QWidget()
self.page_verify_button.setObjectName("page_verify_button")
self.layout_verify_button = QtWidgets.QVBoxLayout(self.page_verify_button)
self.layout_verify_button.setContentsMargins(0, 0, 0, 0)
self.layout_verify_button.setSpacing(0)
self.layout_verify_button.setObjectName("layout_verify_button")
self.verify_button = QtWidgets.QPushButton(self.page_verify_button)
self.verify_button.setObjectName("verify_button")
self.layout_verify_button.addWidget(self.verify_button)
self.verify_widget.addWidget(self.page_verify_button)
self.page_verify_progress = QtWidgets.QWidget()
self.page_verify_progress.setObjectName("page_verify_progress")
self.layout_verify_progress = QtWidgets.QVBoxLayout(self.page_verify_progress)
self.layout_verify_progress.setContentsMargins(0, 0, 0, 0)
self.layout_verify_progress.setSpacing(0)
self.layout_verify_progress.setObjectName("layout_verify_progress")
self.verify_progress = QtWidgets.QProgressBar(self.page_verify_progress)
self.verify_progress.setProperty("value", 24)
self.verify_progress.setObjectName("verify_progress")
self.layout_verify_progress.addWidget(self.verify_progress)
self.verify_widget.addWidget(self.page_verify_progress)
self.layout_game_actions.addWidget(self.verify_widget)
self.repair_button = QtWidgets.QPushButton(self.wg_game_actions)
self.repair_button.setObjectName("repair_button")
self.layout_game_actions.addWidget(self.repair_button)
self.layout_game_info_form.addWidget(self.wg_game_actions, 6, 1, 1, 1, QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop)
self.lbl_version = QtWidgets.QLabel(GameInfo)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_version.sizePolicy().hasHeightForWidth())
self.lbl_version.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lbl_version.setFont(font)
self.lbl_version.setObjectName("lbl_version")
self.layout_game_info_form.addWidget(self.lbl_version, 2, 0, 1, 1, QtCore.Qt.AlignRight)
self.lbl_app_name = QtWidgets.QLabel(GameInfo)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_app_name.sizePolicy().hasHeightForWidth())
self.lbl_app_name.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lbl_app_name.setFont(font)
self.lbl_app_name.setObjectName("lbl_app_name")
self.layout_game_info_form.addWidget(self.lbl_app_name, 1, 0, 1, 1, QtCore.Qt.AlignRight)
self.dev = QtWidgets.QLabel(GameInfo)
self.dev.setText("error")
self.dev.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.dev.setObjectName("dev")
self.layout_game_info_form.addWidget(self.dev, 0, 1, 1, 1)
self.app_name = QtWidgets.QLabel(GameInfo)
self.app_name.setText("error")
self.app_name.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.app_name.setObjectName("app_name")
self.layout_game_info_form.addWidget(self.app_name, 1, 1, 1, 1)
self.install_path = QtWidgets.QLabel(GameInfo)
self.install_path.setText("error")
self.install_path.setWordWrap(True)
self.install_path.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.install_path.setObjectName("install_path")
self.layout_game_info_form.addWidget(self.install_path, 5, 1, 1, 1)
self.lbl_game_actions = QtWidgets.QLabel(GameInfo)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_game_actions.sizePolicy().hasHeightForWidth())
self.lbl_game_actions.setSizePolicy(sizePolicy)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lbl_game_actions.setFont(font)
self.lbl_game_actions.setObjectName("lbl_game_actions")
self.layout_game_info_form.addWidget(self.lbl_game_actions, 6, 0, 1, 1, QtCore.Qt.AlignRight)
self.lbl_grade = QtWidgets.QLabel(GameInfo)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lbl_grade.setFont(font)
self.lbl_grade.setObjectName("lbl_grade")
self.layout_game_info_form.addWidget(self.lbl_grade, 3, 0, 1, 1, QtCore.Qt.AlignRight)
self.grade = QtWidgets.QLabel(GameInfo)
self.grade.setText("error")
self.grade.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.grade.setObjectName("grade")
self.layout_game_info_form.addWidget(self.grade, 3, 1, 1, 1)
self.layout_game_info.addLayout(self.layout_game_info_form, 2, 1, 1, 1)
self.image = QtWidgets.QLabel(GameInfo)
self.image.setFrameShape(QtWidgets.QFrame.StyledPanel)
self.image.setFrameShadow(QtWidgets.QFrame.Sunken)
self.image.setText("")
self.image.setObjectName("image")
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.setText("error")
self.game_title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.game_title.setObjectName("game_title")
self.layout_game_info.addWidget(self.game_title, 0, 0, 1, 3)
self.retranslateUi(GameInfo)
self.verify_widget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(GameInfo)
def retranslateUi(self, GameInfo):
_translate = QtCore.QCoreApplication.translate
GameInfo.setWindowTitle(_translate("GameInfo", "Game Info"))
self.lbl_dev.setText(_translate("GameInfo", "Developer"))
self.lbl_install_path.setText(_translate("GameInfo", "Installation Path"))
self.lbl_install_size.setText(_translate("GameInfo", "Installation Size"))
self.uninstall_button.setText(_translate("GameInfo", "Uninstall Game"))
self.verify_button.setText(_translate("GameInfo", "Verify Installation"))
self.repair_button.setText(_translate("GameInfo", "Repair Instalation"))
self.lbl_version.setText(_translate("GameInfo", "Version"))
self.lbl_app_name.setText(_translate("GameInfo", "Application Name"))
self.lbl_game_actions.setText(_translate("GameInfo", "Actions"))
self.lbl_grade.setText(_translate("GameInfo", "ProtonDB Grade"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
GameInfo = QtWidgets.QWidget()
ui = Ui_GameInfo()
ui.setupUi(GameInfo)
GameInfo.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,376 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GameInfo</class>
<widget class="QWidget" name="GameInfo">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>436</width>
<height>317</height>
</rect>
</property>
<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>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<property name="spacing">
<number>12</number>
</property>
<item row="4" column="1">
<widget class="QLabel" name="install_size">
<property name="text">
<string notr="true">error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_dev">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Developer</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="version">
<property name="text">
<string notr="true">error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_install_path">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Installation Path</string>
</property>
</widget>
</item>
<item row="4" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_install_size">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Installation Size</string>
</property>
</widget>
</item>
<item row="7" column="1">
<spacer name="hs_game_info_form">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="7" column="0">
<spacer name="vs_game_info_form">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="6" column="1" alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QWidget" name="wg_game_actions" native="true">
<property name="minimumSize">
<size>
<width>250</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="layout_game_actions">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="uninstall_button">
<property name="text">
<string>Uninstall Game</string>
</property>
</widget>
</item>
<item>
<widget class="QStackedWidget" name="verify_widget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page_verify_button">
<layout class="QVBoxLayout" name="layout_verify_button">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QPushButton" name="verify_button">
<property name="text">
<string>Verify Installation</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="page_verify_progress">
<layout class="QVBoxLayout" name="layout_verify_progress">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QProgressBar" name="verify_progress">
<property name="value">
<number>24</number>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QPushButton" name="repair_button">
<property name="text">
<string>Repair Instalation</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_version">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Version</string>
</property>
</widget>
</item>
<item row="1" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_app_name">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Application Name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="dev">
<property name="text">
<string notr="true">error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="app_name">
<property name="text">
<string notr="true">error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="install_path">
<property name="text">
<string notr="true">error</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="6" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_game_actions">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Actions</string>
</property>
</widget>
</item>
<item row="3" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_grade">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>ProtonDB Grade</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="grade">
<property name="text">
<string notr="true">error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0" alignment="Qt::AlignLeft|Qt::AlignTop">
<widget class="QLabel" name="image">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="game_title">
<property name="text">
<string notr="true">error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,155 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'game_settings.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_GameSettings(object):
def setupUi(self, GameSettings):
GameSettings.setObjectName("GameSettings")
GameSettings.resize(759, 617)
self.game_settings_layout = QtWidgets.QVBoxLayout(GameSettings)
self.game_settings_layout.setObjectName("game_settings_layout")
self.title = QtWidgets.QLabel(GameSettings)
self.title.setText("error")
self.title.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse | QtCore.Qt.TextSelectableByMouse)
self.title.setObjectName("title")
self.game_settings_layout.addWidget(self.title)
self.launch_settings_groupbox = QtWidgets.QGroupBox(GameSettings)
self.launch_settings_groupbox.setObjectName("launch_settings_groupbox")
self.launch_settings_layout = QtWidgets.QGridLayout(self.launch_settings_groupbox)
self.launch_settings_layout.setObjectName("launch_settings_layout")
self.skip_update = QtWidgets.QComboBox(self.launch_settings_groupbox)
self.skip_update.setObjectName("skip_update")
self.skip_update.addItem("")
self.skip_update.addItem("")
self.skip_update.addItem("")
self.launch_settings_layout.addWidget(self.skip_update, 0, 1, 1, 1, QtCore.Qt.AlignLeft)
self.cloud_sync = QtWidgets.QCheckBox(self.launch_settings_groupbox)
self.cloud_sync.setText("")
self.cloud_sync.setObjectName("cloud_sync")
self.launch_settings_layout.addWidget(self.cloud_sync, 2, 1, 1, 1, QtCore.Qt.AlignLeft)
self.launch_params_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.launch_params_label.setObjectName("launch_params_label")
self.launch_settings_layout.addWidget(self.launch_params_label, 3, 0, 1, 1, QtCore.Qt.AlignRight)
self.wrapper_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.wrapper_label.setObjectName("wrapper_label")
self.launch_settings_layout.addWidget(self.wrapper_label, 4, 0, 1, 1, QtCore.Qt.AlignRight)
self.skip_update_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.skip_update_label.setObjectName("skip_update_label")
self.launch_settings_layout.addWidget(self.skip_update_label, 0, 0, 1, 1, QtCore.Qt.AlignRight)
self.wrapper_widget = QtWidgets.QWidget(self.launch_settings_groupbox)
self.wrapper_widget.setObjectName("wrapper_widget")
self.wrapper_layout = QtWidgets.QHBoxLayout(self.wrapper_widget)
self.wrapper_layout.setContentsMargins(0, 0, 0, 0)
self.wrapper_layout.setObjectName("wrapper_layout")
self.wrapper = QtWidgets.QLineEdit(self.wrapper_widget)
self.wrapper.setMinimumSize(QtCore.QSize(400, 0))
self.wrapper.setObjectName("wrapper")
self.wrapper_layout.addWidget(self.wrapper)
self.wrapper_button = QtWidgets.QPushButton(self.wrapper_widget)
self.wrapper_button.setObjectName("wrapper_button")
self.wrapper_layout.addWidget(self.wrapper_button)
self.launch_settings_layout.addWidget(self.wrapper_widget, 4, 1, 1, 1)
self.offline_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.offline_label.setObjectName("offline_label")
self.launch_settings_layout.addWidget(self.offline_label, 1, 0, 1, 1, QtCore.Qt.AlignRight)
self.offline = QtWidgets.QComboBox(self.launch_settings_groupbox)
self.offline.setObjectName("offline")
self.offline.addItem("")
self.offline.addItem("")
self.offline.addItem("")
self.launch_settings_layout.addWidget(self.offline, 1, 1, 1, 1, QtCore.Qt.AlignLeft)
self.launch_params_widget = QtWidgets.QWidget(self.launch_settings_groupbox)
self.launch_params_widget.setObjectName("launch_params_widget")
self.launch_params_layout = QtWidgets.QHBoxLayout(self.launch_params_widget)
self.launch_params_layout.setContentsMargins(0, 0, 0, 0)
self.launch_params_layout.setObjectName("launch_params_layout")
self.launch_params = QtWidgets.QLineEdit(self.launch_params_widget)
self.launch_params.setMinimumSize(QtCore.QSize(400, 0))
self.launch_params.setObjectName("launch_params")
self.launch_params_layout.addWidget(self.launch_params)
self.launch_params_button = QtWidgets.QPushButton(self.launch_params_widget)
self.launch_params_button.setObjectName("launch_params_button")
self.launch_params_layout.addWidget(self.launch_params_button)
self.launch_settings_layout.addWidget(self.launch_params_widget, 3, 1, 1, 1)
self.cloud_sync_label = QtWidgets.QLabel(self.launch_settings_groupbox)
self.cloud_sync_label.setObjectName("cloud_sync_label")
self.launch_settings_layout.addWidget(self.cloud_sync_label, 2, 0, 1, 1, QtCore.Qt.AlignRight)
self.game_settings_layout.addWidget(self.launch_settings_groupbox)
self.proton_groupbox = QtWidgets.QGroupBox(GameSettings)
self.proton_groupbox.setObjectName("proton_groupbox")
self.proton_layout = QtWidgets.QGridLayout(self.proton_groupbox)
self.proton_layout.setObjectName("proton_layout")
self.proton_wrapper = QtWidgets.QComboBox(self.proton_groupbox)
self.proton_wrapper.setObjectName("proton_wrapper")
self.proton_wrapper.addItem("")
self.proton_layout.addWidget(self.proton_wrapper, 0, 1, 1, 1, QtCore.Qt.AlignLeft)
self.proton_wrapper_label = QtWidgets.QLabel(self.proton_groupbox)
self.proton_wrapper_label.setObjectName("proton_wrapper_label")
self.proton_layout.addWidget(self.proton_wrapper_label, 0, 0, 1, 1, QtCore.Qt.AlignRight)
self.proton_prefix_label = QtWidgets.QLabel(self.proton_groupbox)
self.proton_prefix_label.setObjectName("proton_prefix_label")
self.proton_layout.addWidget(self.proton_prefix_label, 1, 0, 1, 1, QtCore.Qt.AlignRight)
spacerItem = QtWidgets.QSpacerItem(20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Maximum)
self.proton_layout.addItem(spacerItem, 4, 1, 1, 1)
self.proton_prefix_layout = QtWidgets.QVBoxLayout()
self.proton_prefix_layout.setObjectName("proton_prefix_layout")
self.proton_layout.addLayout(self.proton_prefix_layout, 1, 1, 2, 1)
self.proton_prefix_alignment_label = QtWidgets.QLabel(self.proton_groupbox)
self.proton_prefix_alignment_label.setEnabled(False)
self.proton_prefix_alignment_label.setText("")
self.proton_prefix_alignment_label.setObjectName("proton_prefix_alignment_label")
self.proton_layout.addWidget(self.proton_prefix_alignment_label, 2, 0, 1, 1)
self.linux_layout = QtWidgets.QVBoxLayout()
self.linux_layout.setSpacing(0)
self.linux_layout.setObjectName("linux_layout")
self.proton_layout.addLayout(self.linux_layout, 3, 0, 1, 2)
self.game_settings_layout.addWidget(self.proton_groupbox)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.game_settings_layout.addItem(spacerItem1)
self.retranslateUi(GameSettings)
QtCore.QMetaObject.connectSlotsByName(GameSettings)
def retranslateUi(self, GameSettings):
_translate = QtCore.QCoreApplication.translate
GameSettings.setWindowTitle(_translate("GameSettings", "GameSettings"))
self.launch_settings_groupbox.setTitle(_translate("GameSettings", "Launch Settings"))
self.skip_update.setItemText(0, _translate("GameSettings", "Default"))
self.skip_update.setItemText(1, _translate("GameSettings", "Yes"))
self.skip_update.setItemText(2, _translate("GameSettings", "No"))
self.launch_params_label.setText(_translate("GameSettings", "Launch parameters"))
self.wrapper_label.setText(_translate("GameSettings", "Wrapper"))
self.skip_update_label.setText(_translate("GameSettings", "Skip update check"))
self.wrapper.setPlaceholderText(_translate("GameSettings", "e.g. optirun"))
self.wrapper_button.setText(_translate("GameSettings", "Save"))
self.offline_label.setText(_translate("GameSettings", "Offline mode"))
self.offline.setItemText(0, _translate("GameSettings", "Default"))
self.offline.setItemText(1, _translate("GameSettings", "Yes"))
self.offline.setItemText(2, _translate("GameSettings", "No"))
self.launch_params.setPlaceholderText(_translate("GameSettings", "parameters"))
self.launch_params_button.setText(_translate("GameSettings", "Save"))
self.cloud_sync_label.setText(_translate("GameSettings", "Sync with cloud"))
self.proton_groupbox.setTitle(_translate("GameSettings", "Linux Settings"))
self.proton_wrapper.setItemText(0, _translate("GameSettings", "Don\'t use Proton"))
self.proton_wrapper_label.setText(_translate("GameSettings", "Proton"))
self.proton_prefix_label.setText(_translate("GameSettings", "Prefix"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
GameSettings = QtWidgets.QWidget()
ui = Ui_GameSettings()
ui.setupUi(GameSettings)
GameSettings.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,277 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GameSettings</class>
<widget class="QWidget" name="GameSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>759</width>
<height>617</height>
</rect>
</property>
<property name="windowTitle">
<string>GameSettings</string>
</property>
<layout class="QVBoxLayout" name="game_settings_layout">
<item>
<widget class="QLabel" name="title">
<property name="text">
<string notr="true">error</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="launch_settings_groupbox">
<property name="title">
<string>Launch Settings</string>
</property>
<layout class="QGridLayout" name="launch_settings_layout">
<item row="0" column="1" alignment="Qt::AlignLeft">
<widget class="QComboBox" name="skip_update">
<item>
<property name="text">
<string>Default</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
<item>
<property name="text">
<string>No</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1" alignment="Qt::AlignLeft">
<widget class="QCheckBox" name="cloud_sync">
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="3" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="launch_params_label">
<property name="text">
<string>Launch parameters</string>
</property>
</widget>
</item>
<item row="4" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="wrapper_label">
<property name="text">
<string>Wrapper</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="skip_update_label">
<property name="text">
<string>Skip update check</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QWidget" name="wrapper_widget" native="true">
<layout class="QHBoxLayout" name="wrapper_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="wrapper">
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string>e.g. optirun</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="wrapper_button">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="offline_label">
<property name="text">
<string>Offline mode</string>
</property>
</widget>
</item>
<item row="1" column="1" alignment="Qt::AlignLeft">
<widget class="QComboBox" name="offline">
<item>
<property name="text">
<string>Default</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
<item>
<property name="text">
<string>No</string>
</property>
</item>
</widget>
</item>
<item row="3" column="1">
<widget class="QWidget" name="launch_params_widget" native="true">
<layout class="QHBoxLayout" name="launch_params_layout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="launch_params">
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string>parameters</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="launch_params_button">
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="cloud_sync_label">
<property name="text">
<string>Sync with cloud</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="proton_groupbox">
<property name="title">
<string>Linux Settings</string>
</property>
<layout class="QGridLayout" name="proton_layout">
<item row="0" column="1" alignment="Qt::AlignLeft">
<widget class="QComboBox" name="proton_wrapper">
<item>
<property name="text">
<string>Don't use Proton</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="proton_wrapper_label">
<property name="text">
<string>Proton</string>
</property>
</widget>
</item>
<item row="1" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="proton_prefix_label">
<property name="text">
<string>Prefix</string>
</property>
</widget>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Maximum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1" rowspan="2">
<layout class="QVBoxLayout" name="proton_prefix_layout"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="proton_prefix_alignment_label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<layout class="QVBoxLayout" name="linux_layout">
<property name="spacing">
<number>0</number>
</property>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="game_settings_vspacer">
<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>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,120 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'about.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_About(object):
def setupUi(self, About):
About.setObjectName("About")
About.resize(499, 396)
self.gridLayout = QtWidgets.QGridLayout(About)
self.gridLayout.setObjectName("gridLayout")
self.open_browser = QtWidgets.QPushButton(About)
self.open_browser.setObjectName("open_browser")
self.gridLayout.addWidget(self.open_browser, 4, 1, 1, 1)
self.version_label = QtWidgets.QLabel(About)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.version_label.setFont(font)
self.version_label.setObjectName("version_label")
self.gridLayout.addWidget(self.version_label, 2, 0, 1, 1, QtCore.Qt.AlignRight)
self.license_label = QtWidgets.QLabel(About)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.license_label.setFont(font)
self.license_label.setObjectName("license_label")
self.gridLayout.addWidget(self.license_label, 7, 0, 1, 1, QtCore.Qt.AlignRight)
self.lgd_dev_label = QtWidgets.QLabel(About)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.lgd_dev_label.setFont(font)
self.lgd_dev_label.setObjectName("lgd_dev_label")
self.gridLayout.addWidget(self.lgd_dev_label, 6, 0, 1, 1, QtCore.Qt.AlignRight)
self.dev = QtWidgets.QLabel(About)
self.dev.setText("<a href=\'https://github.com/Dummerle\'>Dummerle</a>")
self.dev.setOpenExternalLinks(True)
self.dev.setObjectName("dev")
self.gridLayout.addWidget(self.dev, 5, 1, 1, 1)
self.update_label = QtWidgets.QLabel(About)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.update_label.setFont(font)
self.update_label.setObjectName("update_label")
self.gridLayout.addWidget(self.update_label, 3, 0, 1, 1, QtCore.Qt.AlignRight)
self.version = QtWidgets.QLabel(About)
self.version.setText("error")
self.version.setObjectName("version")
self.gridLayout.addWidget(self.version, 2, 1, 1, 1)
self.dev_label = QtWidgets.QLabel(About)
font = QtGui.QFont()
font.setBold(True)
font.setWeight(75)
self.dev_label.setFont(font)
self.dev_label.setObjectName("dev_label")
self.gridLayout.addWidget(self.dev_label, 5, 0, 1, 1, QtCore.Qt.AlignRight)
self.license = QtWidgets.QLabel(About)
self.license.setObjectName("license")
self.gridLayout.addWidget(self.license, 7, 1, 1, 1)
self.update = QtWidgets.QLabel(About)
self.update.setText("error")
self.update.setObjectName("update")
self.gridLayout.addWidget(self.update, 3, 1, 1, 1)
self.lgd_dev = QtWidgets.QLabel(About)
self.lgd_dev.setText("<a href=\'https://github.com/derrod/\'>derrod</a>")
self.lgd_dev.setOpenExternalLinks(True)
self.lgd_dev.setObjectName("lgd_dev")
self.gridLayout.addWidget(self.lgd_dev, 6, 1, 1, 1)
self.info_text = QtWidgets.QLabel(About)
self.info_text.setWordWrap(True)
self.info_text.setOpenExternalLinks(True)
self.info_text.setObjectName("info_text")
self.gridLayout.addWidget(self.info_text, 14, 0, 1, 3)
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem, 15, 0, 1, 3)
self.title = QtWidgets.QLabel(About)
self.title.setObjectName("title")
self.gridLayout.addWidget(self.title, 1, 0, 1, 3)
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem1, 2, 2, 6, 1)
self.retranslateUi(About)
QtCore.QMetaObject.connectSlotsByName(About)
def retranslateUi(self, About):
_translate = QtCore.QCoreApplication.translate
About.setWindowTitle(_translate("About", "About"))
self.open_browser.setText(_translate("About", "Download latest release"))
self.version_label.setText(_translate("About", "Version"))
self.license_label.setText(_translate("About", "License"))
self.lgd_dev_label.setText(_translate("About", "Legendary Developer"))
self.dev.setToolTip(_translate("About", "Github"))
self.update_label.setText(_translate("About", "Update available"))
self.dev_label.setText(_translate("About", "Rare Developer"))
self.license.setText(_translate("About", "GNU General Public License v3.0"))
self.lgd_dev.setToolTip(_translate("About", "Github"))
self.info_text.setText(_translate("About",
"This is a beta version, so you can get bugs. If you get a bug, please report it by creating an Issue on <a href=\'https://github.com/Dummerle/Rare/issues\'>Github</a>. You can also contact me on Discord (Dummerle#7419). Or you can join the <a href=\'https://discord.gg/YvmABK9YSk\'>Discord server</a>"))
self.title.setText(_translate("About", "<h2>About</h2>"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
About = QtWidgets.QWidget()
ui = Ui_About()
ui.setupUi(About)
About.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,190 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>About</class>
<widget class="QWidget" name="About">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>499</width>
<height>396</height>
</rect>
</property>
<property name="windowTitle">
<string>About</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="4" column="1">
<widget class="QPushButton" name="open_browser">
<property name="text">
<string>Download latest release</string>
</property>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="version_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Version</string>
</property>
</widget>
</item>
<item row="7" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="license_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>License</string>
</property>
</widget>
</item>
<item row="6" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lgd_dev_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Legendary Developer</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="dev">
<property name="toolTip">
<string>Github</string>
</property>
<property name="text">
<string notr="true">&lt;a href='https://github.com/Dummerle'&gt;Dummerle&lt;/a&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="update_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Update available</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLabel" name="version">
<property name="text">
<string notr="true">error</string>
</property>
</widget>
</item>
<item row="5" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="dev_label">
<property name="font">
<font>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="text">
<string>Rare Developer</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QLabel" name="license">
<property name="text">
<string>GNU General Public License v3.0</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="update">
<property name="text">
<string notr="true">error</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QLabel" name="lgd_dev">
<property name="toolTip">
<string>Github</string>
</property>
<property name="text">
<string notr="true">&lt;a href='https://github.com/derrod/'&gt;derrod&lt;/a&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="14" column="0" colspan="3">
<widget class="QLabel" name="info_text">
<property name="text">
<string>This is a beta version, so you can get bugs. If you get a bug, please report it by
creating an Issue on &lt;a href='https://github.com/Dummerle/Rare/issues'&gt;Github&lt;/a&gt;.
You can also contact me on Discord (Dummerle#7419). Or you can join the &lt;a
href='https://discord.gg/YvmABK9YSk'&gt;Discord server&lt;/a&gt;
</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="15" column="0" colspan="3">
<spacer name="about_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" colspan="3">
<widget class="QLabel" name="title">
<property name="text">
<string>&lt;h2&gt;About&lt;/h2&gt;</string>
</property>
</widget>
</item>
<item row="2" column="2" rowspan="6">
<spacer name="about_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>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'dxvk.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_DxvkSettings(object):
def setupUi(self, DxvkSettings):
DxvkSettings.setObjectName("DxvkSettings")
self.dxvk_layout = QtWidgets.QGridLayout(DxvkSettings)
self.dxvk_layout.setObjectName("dxvk_layout")
self.gb_dxvk_options = QtWidgets.QGroupBox(DxvkSettings)
self.gb_dxvk_options.setObjectName("gb_dxvk_options")
self.layout_dxvk_options = QtWidgets.QGridLayout(self.gb_dxvk_options)
self.layout_dxvk_options.setObjectName("layout_dxvk_options")
self.version = QtWidgets.QCheckBox(self.gb_dxvk_options)
self.version.setObjectName("version")
self.layout_dxvk_options.addWidget(self.version, 0, 2, 1, 1)
self.fps = QtWidgets.QCheckBox(self.gb_dxvk_options)
self.fps.setObjectName("fps")
self.layout_dxvk_options.addWidget(self.fps, 1, 0, 1, 1)
self.memory = QtWidgets.QCheckBox(self.gb_dxvk_options)
self.memory.setObjectName("memory")
self.layout_dxvk_options.addWidget(self.memory, 0, 1, 1, 1)
self.devinfo = QtWidgets.QCheckBox(self.gb_dxvk_options)
self.devinfo.setObjectName("devinfo")
self.layout_dxvk_options.addWidget(self.devinfo, 0, 0, 1, 1)
self.gpuload = QtWidgets.QCheckBox(self.gb_dxvk_options)
self.gpuload.setObjectName("gpuload")
self.layout_dxvk_options.addWidget(self.gpuload, 1, 1, 1, 1)
self.frametime = QtWidgets.QCheckBox(self.gb_dxvk_options)
self.frametime.setObjectName("frametime")
self.layout_dxvk_options.addWidget(self.frametime, 2, 0, 1, 1)
spacerItem = QtWidgets.QSpacerItem(0, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.layout_dxvk_options.addItem(spacerItem, 0, 3, 3, 1)
self.api = QtWidgets.QCheckBox(self.gb_dxvk_options)
self.api.setObjectName("api")
self.layout_dxvk_options.addWidget(self.api, 1, 2, 1, 1)
self.dxvk_layout.addWidget(self.gb_dxvk_options, 2, 0, 1, 3)
self.lbl_show_dxvk = QtWidgets.QLabel(DxvkSettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_show_dxvk.sizePolicy().hasHeightForWidth())
self.lbl_show_dxvk.setSizePolicy(sizePolicy)
self.lbl_show_dxvk.setObjectName("lbl_show_dxvk")
self.dxvk_layout.addWidget(self.lbl_show_dxvk, 0, 0, 1, 1)
self.show_dxvk = QtWidgets.QComboBox(DxvkSettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Fixed)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.show_dxvk.sizePolicy().hasHeightForWidth())
self.show_dxvk.setSizePolicy(sizePolicy)
self.show_dxvk.setObjectName("show_dxvk")
self.show_dxvk.addItem("")
self.show_dxvk.addItem("")
self.show_dxvk.addItem("")
self.show_dxvk.addItem("")
self.dxvk_layout.addWidget(self.show_dxvk, 0, 1, 1, 2)
self.retranslateUi(DxvkSettings)
QtCore.QMetaObject.connectSlotsByName(DxvkSettings)
def retranslateUi(self, DxvkSettings):
_translate = QtCore.QCoreApplication.translate
DxvkSettings.setWindowTitle(_translate("DxvkSettings", "DxvkSettings"))
DxvkSettings.setTitle(_translate("DxvkSettings", "DXVK Settings"))
self.gb_dxvk_options.setTitle(_translate("DxvkSettings", "DXVK HUD Options"))
self.version.setText(_translate("DxvkSettings", "DXVK Version"))
self.fps.setText(_translate("DxvkSettings", "FPS"))
self.memory.setText(_translate("DxvkSettings", "Memory Usage"))
self.devinfo.setText(_translate("DxvkSettings", "Device Info"))
self.gpuload.setText(_translate("DxvkSettings", "GPU Usage"))
self.frametime.setText(_translate("DxvkSettings", "Frame Time graph"))
self.api.setText(_translate("DxvkSettings", "D3D Version"))
self.lbl_show_dxvk.setText(_translate("DxvkSettings", "Show HUD"))
self.show_dxvk.setItemText(0, _translate("DxvkSettings", "System Default"))
self.show_dxvk.setItemText(1, _translate("DxvkSettings", "Hidden"))
self.show_dxvk.setItemText(2, _translate("DxvkSettings", "Visible"))
self.show_dxvk.setItemText(3, _translate("DxvkSettings", "Custom Options"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
DxvkSettings = QtWidgets.QGroupBox()
ui = Ui_DxvkSettings()
ui.setupUi(DxvkSettings)
DxvkSettings.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DxvkSettings</class>
<widget class="QGroupBox" name="DxvkSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>419</width>
<height>185</height>
</rect>
</property>
<property name="windowTitle">
<string>DxvkSettings</string>
</property>
<property name="title">
<string>DXVK Settings</string>
</property>
<layout class="QGridLayout" name="dxvk_layout">
<item row="2" column="0" colspan="3">
<widget class="QGroupBox" name="gb_dxvk_options">
<property name="title">
<string>DXVK HUD Options</string>
</property>
<layout class="QGridLayout" name="layout_dxvk_options">
<item row="0" column="2">
<widget class="QCheckBox" name="version">
<property name="text">
<string>DXVK Version</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="fps">
<property name="text">
<string>FPS</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QCheckBox" name="memory">
<property name="text">
<string>Memory Usage</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="devinfo">
<property name="text">
<string>Device Info</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="gpuload">
<property name="text">
<string>GPU Usage</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="frametime">
<property name="text">
<string>Frame Time graph</string>
</property>
</widget>
</item>
<item row="0" column="3" rowspan="3">
<spacer name="hs_dxvk_options">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="api">
<property name="text">
<string>D3D Version</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lbl_show_dxvk">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show HUD</string>
</property>
</widget>
</item>
<item row="0" column="1" colspan="2">
<widget class="QComboBox" name="show_dxvk">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>System Default</string>
</property>
</item>
<item>
<property name="text">
<string>Hidden</string>
</property>
</item>
<item>
<property name="text">
<string>Visible</string>
</property>
</item>
<item>
<property name="text">
<string>Custom Options</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'legendary.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_legendary_settings(object):
def setupUi(self, legendary_settings):
legendary_settings.setObjectName("legendary_settings")
legendary_settings.resize(532, 383)
self.settings = QtWidgets.QWidget()
self.settings.setObjectName("settings")
self.gridLayout_2 = QtWidgets.QGridLayout(self.settings)
self.gridLayout_2.setObjectName("gridLayout_2")
self.gb_clean = QtWidgets.QGroupBox(self.settings)
self.gb_clean.setObjectName("gb_clean")
self.layout_clean = QtWidgets.QVBoxLayout(self.gb_clean)
self.layout_clean.setObjectName("layout_clean")
self.clean_button_without_manifests = QtWidgets.QPushButton(self.gb_clean)
self.clean_button_without_manifests.setObjectName("clean_button_without_manifests")
self.layout_clean.addWidget(self.clean_button_without_manifests)
self.clean_button = QtWidgets.QPushButton(self.gb_clean)
self.clean_button.setObjectName("clean_button")
self.layout_clean.addWidget(self.clean_button)
self.gridLayout_2.addWidget(self.gb_clean, 0, 1, 1, 1)
self.egl_sync = QtWidgets.QGroupBox(self.settings)
self.egl_sync.setObjectName("egl_sync")
self.verticalLayout = QtWidgets.QVBoxLayout(self.egl_sync)
self.verticalLayout.setObjectName("verticalLayout")
self.sync_button = QtWidgets.QPushButton(self.egl_sync)
self.sync_button.setObjectName("sync_button")
self.verticalLayout.addWidget(self.sync_button)
self.gridLayout_2.addWidget(self.egl_sync, 1, 1, 1, 1)
self.gb_downloads = QtWidgets.QGroupBox(self.settings)
self.gb_downloads.setObjectName("gb_downloads")
self.layout_downloads = QtWidgets.QGridLayout(self.gb_downloads)
self.layout_downloads.setObjectName("layout_downloads")
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.layout_downloads.addItem(spacerItem, 0, 4, 1, 1)
self.max_worker_select = QtWidgets.QSpinBox(self.gb_downloads)
self.max_worker_select.setObjectName("max_worker_select")
self.layout_downloads.addWidget(self.max_worker_select, 0, 1, 1, 1)
self.lbl_max_workers = QtWidgets.QLabel(self.gb_downloads)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.lbl_max_workers.sizePolicy().hasHeightForWidth())
self.lbl_max_workers.setSizePolicy(sizePolicy)
self.lbl_max_workers.setObjectName("lbl_max_workers")
self.layout_downloads.addWidget(self.lbl_max_workers, 0, 0, 1, 1, QtCore.Qt.AlignRight)
self.lbl_max_workers_info = QtWidgets.QLabel(self.gb_downloads)
font = QtGui.QFont()
font.setItalic(True)
self.lbl_max_workers_info.setFont(font)
self.lbl_max_workers_info.setObjectName("lbl_max_workers_info")
self.layout_downloads.addWidget(self.lbl_max_workers_info, 0, 2, 1, 1)
self.gridLayout_2.addWidget(self.gb_downloads, 1, 0, 1, 1)
self.gb_install_dir = QtWidgets.QGroupBox(self.settings)
self.gb_install_dir.setObjectName("gb_install_dir")
self.layout_install_dir = QtWidgets.QVBoxLayout(self.gb_install_dir)
self.layout_install_dir.setObjectName("layout_install_dir")
self.gridLayout_2.addWidget(self.gb_install_dir, 0, 0, 1, 1)
spacerItem1 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.gridLayout_2.addItem(spacerItem1, 2, 1, 1, 1)
legendary_settings.addWidget(self.settings)
self.egl_sync_page = QtWidgets.QWidget()
self.egl_sync_page.setObjectName("egl_sync_page")
self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.egl_sync_page)
self.verticalLayout_2.setObjectName("verticalLayout_2")
self.back_button = QtWidgets.QPushButton(self.egl_sync_page)
self.back_button.setObjectName("back_button")
self.verticalLayout_2.addWidget(self.back_button)
self.title = QtWidgets.QLabel(self.egl_sync_page)
self.title.setObjectName("title")
self.verticalLayout_2.addWidget(self.title)
self.pathedit_placeholder = QtWidgets.QVBoxLayout()
self.pathedit_placeholder.setObjectName("pathedit_placeholder")
self.verticalLayout_2.addLayout(self.pathedit_placeholder)
self.path_info = QtWidgets.QLabel(self.egl_sync_page)
self.path_info.setObjectName("path_info")
self.verticalLayout_2.addWidget(self.path_info)
self.gridLayout = QtWidgets.QGridLayout()
self.gridLayout.setObjectName("gridLayout")
self.exportable_games = QtWidgets.QGroupBox(self.egl_sync_page)
self.exportable_games.setObjectName("exportable_games")
self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.exportable_games)
self.verticalLayout_3.setObjectName("verticalLayout_3")
self.gridLayout.addWidget(self.exportable_games, 0, 0, 1, 1)
self.importable_games = QtWidgets.QGroupBox(self.egl_sync_page)
self.importable_games.setObjectName("importable_games")
self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.importable_games)
self.verticalLayout_4.setObjectName("verticalLayout_4")
self.gridLayout.addWidget(self.importable_games, 0, 1, 1, 1)
self.export_all_button = QtWidgets.QPushButton(self.egl_sync_page)
self.export_all_button.setObjectName("export_all_button")
self.gridLayout.addWidget(self.export_all_button, 1, 0, 1, 1)
self.import_all_button = QtWidgets.QPushButton(self.egl_sync_page)
self.import_all_button.setObjectName("import_all_button")
self.gridLayout.addWidget(self.import_all_button, 1, 1, 1, 1)
self.verticalLayout_2.addLayout(self.gridLayout)
self.groupBox = QtWidgets.QGroupBox(self.egl_sync_page)
self.groupBox.setObjectName("groupBox")
self.horizontalLayout = QtWidgets.QHBoxLayout(self.groupBox)
self.horizontalLayout.setObjectName("horizontalLayout")
self.sync_once_button = QtWidgets.QPushButton(self.groupBox)
self.sync_once_button.setObjectName("sync_once_button")
self.horizontalLayout.addWidget(self.sync_once_button)
self.enable_sync_button = QtWidgets.QPushButton(self.groupBox)
self.enable_sync_button.setObjectName("enable_sync_button")
self.horizontalLayout.addWidget(self.enable_sync_button)
self.verticalLayout_2.addWidget(self.groupBox)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout_2.addItem(spacerItem2)
legendary_settings.addWidget(self.egl_sync_page)
self.retranslateUi(legendary_settings)
legendary_settings.setCurrentIndex(1)
QtCore.QMetaObject.connectSlotsByName(legendary_settings)
def retranslateUi(self, legendary_settings):
_translate = QtCore.QCoreApplication.translate
legendary_settings.setWindowTitle(_translate("legendary_settings", "StackedWidget"))
self.gb_clean.setTitle(_translate("legendary_settings", "Cleanup"))
self.clean_button_without_manifests.setText(_translate("legendary_settings", "Clean, but keep manifests"))
self.clean_button.setText(_translate("legendary_settings", "Remove everything"))
self.egl_sync.setTitle(_translate("legendary_settings", "EGL Sync"))
self.sync_button.setText(_translate("legendary_settings", "Sync Settings"))
self.gb_downloads.setTitle(_translate("legendary_settings", "Download Settings"))
self.lbl_max_workers.setText(_translate("legendary_settings", "Max Workers"))
self.lbl_max_workers_info.setText(_translate("legendary_settings", "Less is slower (0: Default)"))
self.gb_install_dir.setTitle(_translate("legendary_settings", "Default Installation Directory"))
self.back_button.setText(_translate("legendary_settings", "Back"))
self.title.setText(_translate("legendary_settings", "<h2>Sync Games with Epic Games Store</h2>"))
self.path_info.setText(_translate("legendary_settings", "TextLabel"))
self.exportable_games.setTitle(_translate("legendary_settings", "Exportable Games"))
self.importable_games.setTitle(_translate("legendary_settings", "Importable"))
self.export_all_button.setText(_translate("legendary_settings", "Export all Games"))
self.import_all_button.setText(_translate("legendary_settings", "Import all Games"))
self.groupBox.setTitle(_translate("legendary_settings", "Enable Sync"))
self.sync_once_button.setText(_translate("legendary_settings", "Sync once"))
self.enable_sync_button.setText(_translate("legendary_settings", "Enable automatic sync"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
legendary_settings = QtWidgets.QStackedWidget()
ui = Ui_legendary_settings()
ui.setupUi(legendary_settings)
legendary_settings.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,234 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>legendary_settings</class>
<widget class="QStackedWidget" name="legendary_settings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>532</width>
<height>383</height>
</rect>
</property>
<property name="windowTitle">
<string>StackedWidget</string>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="settings">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1">
<widget class="QGroupBox" name="gb_clean">
<property name="title">
<string>Cleanup</string>
</property>
<layout class="QVBoxLayout" name="layout_clean">
<item>
<widget class="QPushButton" name="clean_button_without_manifests">
<property name="text">
<string>Clean, but keep manifests</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="clean_button">
<property name="text">
<string>Remove everything</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="egl_sync">
<property name="title">
<string>EGL Sync</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="sync_button">
<property name="text">
<string>Sync Settings</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QGroupBox" name="gb_downloads">
<property name="title">
<string>Download Settings</string>
</property>
<layout class="QGridLayout" name="layout_downloads">
<item row="0" column="4">
<spacer name="hs_downloads">
<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="0" column="1">
<widget class="QSpinBox" name="max_worker_select"/>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lbl_max_workers">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Max Workers</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lbl_max_workers_info">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Less is slower (0: Default)</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="gb_install_dir">
<property name="title">
<string>Default Installation Directory</string>
</property>
<layout class="QVBoxLayout" name="layout_install_dir"/>
</widget>
</item>
<item row="2" column="1">
<spacer name="vs_legendary">
<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>
</widget>
<widget class="QWidget" name="egl_sync_page">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="back_button">
<property name="text">
<string>Back</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="title">
<property name="text">
<string>&lt;h2&gt;Sync Games with Epic Games Store&lt;/h2&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="pathedit_placeholder"/>
</item>
<item>
<widget class="QLabel" name="path_info">
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="exportable_games">
<property name="title">
<string>Exportable Games</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3"/>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="importable_games">
<property name="title">
<string>Importable</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4"/>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="export_all_button">
<property name="text">
<string>Export all Games</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="import_all_button">
<property name="text">
<string>Import all Games</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Enable Sync</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="sync_once_button">
<property name="text">
<string>Sync once</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="enable_sync_button">
<property name="text">
<string>Enable automatic sync</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<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>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'linux.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_LinuxSettings(object):
def setupUi(self, LinuxSettings):
LinuxSettings.setObjectName("LinuxSettings")
LinuxSettings.resize(569, 454)
self.linux_layout = QtWidgets.QGridLayout(LinuxSettings)
self.linux_layout.setObjectName("linux_layout")
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.linux_layout.addItem(spacerItem, 3, 0, 1, 1)
self.wine_groupbox = QtWidgets.QGroupBox(LinuxSettings)
self.wine_groupbox.setObjectName("wine_groupbox")
self.wine_layout = QtWidgets.QGridLayout(self.wine_groupbox)
self.wine_layout.setObjectName("wine_layout")
self.exec_label = QtWidgets.QLabel(self.wine_groupbox)
self.exec_label.setObjectName("exec_label")
self.wine_layout.addWidget(self.exec_label, 2, 0, 1, 1, QtCore.Qt.AlignRight)
self.prefix_label = QtWidgets.QLabel(self.wine_groupbox)
self.prefix_label.setObjectName("prefix_label")
self.wine_layout.addWidget(self.prefix_label, 0, 0, 1, 1, QtCore.Qt.AlignRight)
self.prefix_alignment_label = QtWidgets.QLabel(self.wine_groupbox)
self.prefix_alignment_label.setEnabled(False)
self.prefix_alignment_label.setText("")
self.prefix_alignment_label.setObjectName("prefix_alignment_label")
self.wine_layout.addWidget(self.prefix_alignment_label, 1, 0, 1, 1)
self.exec_alignment_label = QtWidgets.QLabel(self.wine_groupbox)
self.exec_alignment_label.setEnabled(False)
self.exec_alignment_label.setText("")
self.exec_alignment_label.setObjectName("exec_alignment_label")
self.wine_layout.addWidget(self.exec_alignment_label, 3, 0, 1, 1)
self.prefix_layout = QtWidgets.QVBoxLayout()
self.prefix_layout.setObjectName("prefix_layout")
self.wine_layout.addLayout(self.prefix_layout, 0, 1, 2, 1)
self.exec_layout = QtWidgets.QVBoxLayout()
self.exec_layout.setObjectName("exec_layout")
self.wine_layout.addLayout(self.exec_layout, 2, 1, 2, 1)
self.linux_layout.addWidget(self.wine_groupbox, 0, 0, 1, 1)
self.dxvk_layout = QtWidgets.QVBoxLayout()
self.dxvk_layout.setObjectName("dxvk_layout")
self.linux_layout.addLayout(self.dxvk_layout, 1, 0, 1, 1)
self.retranslateUi(LinuxSettings)
QtCore.QMetaObject.connectSlotsByName(LinuxSettings)
def retranslateUi(self, LinuxSettings):
_translate = QtCore.QCoreApplication.translate
LinuxSettings.setWindowTitle(_translate("LinuxSettings", "LinuxSettings"))
self.wine_groupbox.setTitle(_translate("LinuxSettings", "Wine Settings"))
self.exec_label.setText(_translate("LinuxSettings", "Executable"))
self.prefix_label.setText(_translate("LinuxSettings", "Prefix"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
LinuxSettings = QtWidgets.QWidget()
ui = Ui_LinuxSettings()
ui.setupUi(LinuxSettings)
LinuxSettings.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>LinuxSettings</class>
<widget class="QWidget" name="LinuxSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>569</width>
<height>454</height>
</rect>
</property>
<property name="windowTitle">
<string>LinuxSettings</string>
</property>
<layout class="QGridLayout" name="linux_layout">
<item row="3" column="0">
<spacer name="linux_vspacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="wine_groupbox">
<property name="title">
<string>Wine Settings</string>
</property>
<layout class="QGridLayout" name="wine_layout">
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="exec_label">
<property name="text">
<string>Executable</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="prefix_label">
<property name="text">
<string>Prefix</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="prefix_alignment_label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="exec_alignment_label">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string notr="true"/>
</property>
</widget>
</item>
<item row="0" column="1" rowspan="2">
<layout class="QVBoxLayout" name="prefix_layout"/>
</item>
<item row="2" column="1" rowspan="2">
<layout class="QVBoxLayout" name="exec_layout"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<layout class="QVBoxLayout" name="dxvk_layout"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,144 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rare.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_RareSettings(object):
def setupUi(self, RareSettings):
RareSettings.setObjectName("RareSettings")
self.rare_layout = QtWidgets.QGridLayout(RareSettings)
self.rare_layout.setObjectName("rare_layout")
self.interface_group = QtWidgets.QGroupBox(RareSettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.interface_group.sizePolicy().hasHeightForWidth())
self.interface_group.setSizePolicy(sizePolicy)
self.interface_group.setObjectName("interface_group")
self.interface_layout = QtWidgets.QGridLayout(self.interface_group)
self.interface_layout.setObjectName("interface_layout")
self.color_select = QtWidgets.QComboBox(self.interface_group)
self.color_select.setObjectName("color_select")
self.color_select.addItem("")
self.interface_layout.addWidget(self.color_select, 1, 1, 1, 1)
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)
self.lang_label = QtWidgets.QLabel(self.interface_group)
self.lang_label.setObjectName("lang_label")
self.interface_layout.addWidget(self.lang_label, 0, 0, 1, 1, QtCore.Qt.AlignRight)
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_label = QtWidgets.QLabel(self.interface_group)
self.color_label.setObjectName("color_label")
self.interface_layout.addWidget(self.color_label, 1, 0, 1, 1, QtCore.Qt.AlignRight)
self.interface_info = QtWidgets.QLabel(self.interface_group)
font = QtGui.QFont()
font.setItalic(True)
self.interface_info.setFont(font)
self.interface_info.setWordWrap(True)
self.interface_info.setObjectName("interface_info")
self.interface_layout.addWidget(self.interface_info, 3, 0, 1, 3)
self.style_select = QtWidgets.QComboBox(self.interface_group)
self.style_select.setObjectName("style_select")
self.style_select.addItem("")
self.interface_layout.addWidget(self.style_select, 2, 1, 1, 1)
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.interface_layout.addItem(spacerItem, 1, 2, 1, 1)
self.rare_layout.addWidget(self.interface_group, 1, 0, 1, 1, QtCore.Qt.AlignTop)
self.img_dir_group = QtWidgets.QGroupBox(RareSettings)
self.img_dir_group.setObjectName("img_dir_group")
self.img_dir_layout = QtWidgets.QVBoxLayout(self.img_dir_group)
self.img_dir_layout.setObjectName("img_dir_layout")
self.rare_layout.addWidget(self.img_dir_group, 0, 0, 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")
spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.behavior_layout.addItem(spacerItem1, 2, 1, 2, 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_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.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.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.rare_layout.addWidget(self.settings_group, 2, 0, 1, 1, QtCore.Qt.AlignTop)
self.log_dir_group = QtWidgets.QGroupBox(RareSettings)
self.log_dir_group.setObjectName("log_dir_group")
self.log_dir_layout = QtWidgets.QVBoxLayout(self.log_dir_group)
self.log_dir_layout.setObjectName("log_dir_layout")
self.log_dir_open_button = QtWidgets.QPushButton(self.log_dir_group)
self.log_dir_open_button.setObjectName("log_dir_open_button")
self.log_dir_layout.addWidget(self.log_dir_open_button)
self.log_dir_clean_button = QtWidgets.QPushButton(self.log_dir_group)
self.log_dir_clean_button.setObjectName("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.setText("")
self.log_dir_size_label.setWordWrap(True)
self.log_dir_size_label.setObjectName("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.rpc_layout = QtWidgets.QVBoxLayout()
self.rpc_layout.setObjectName("rpc_layout")
self.rare_layout.addLayout(self.rpc_layout, 1, 1, 1, 1)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.rare_layout.addItem(spacerItem2, 2, 1, 1, 1)
self.retranslateUi(RareSettings)
QtCore.QMetaObject.connectSlotsByName(RareSettings)
def retranslateUi(self, RareSettings):
_translate = QtCore.QCoreApplication.translate
RareSettings.setWindowTitle(_translate("RareSettings", "RareSettings"))
self.interface_group.setTitle(_translate("RareSettings", "Interface"))
self.color_select.setItemText(0, _translate("RareSettings", "None"))
self.style_label.setText(_translate("RareSettings", "Style Sheet"))
self.lang_label.setText(_translate("RareSettings", "Language"))
self.color_label.setText(_translate("RareSettings", "Color Scheme"))
self.interface_info.setText(_translate("RareSettings", "Restart Rare to apply."))
self.style_select.setItemText(0, _translate("RareSettings", "None"))
self.img_dir_group.setTitle(_translate("RareSettings", "Image Cache Directory"))
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.confirm_start.setText(_translate("RareSettings", "Confirm game launch"))
self.auto_update.setText(_translate("RareSettings", "Update games on application startup"))
self.sys_tray.setText(_translate("RareSettings", "Exit to System tray"))
self.log_dir_group.setTitle(_translate("RareSettings", "Logs"))
self.log_dir_open_button.setText(_translate("RareSettings", "Open Log directory"))
self.log_dir_clean_button.setText(_translate("RareSettings", "Clean Log directory"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
RareSettings = QtWidgets.QWidget()
ui = Ui_RareSettings()
ui.setupUi(RareSettings)
RareSettings.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,219 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RareSettings</class>
<widget class="QWidget" name="RareSettings">
<property name="windowTitle">
<string>RareSettings</string>
</property>
<layout class="QGridLayout" name="rare_layout">
<item row="1" column="0" alignment="Qt::AlignTop">
<widget class="QGroupBox" name="interface_group">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Interface</string>
</property>
<layout class="QGridLayout" name="interface_layout">
<item row="1" column="1">
<widget class="QComboBox" name="color_select">
<item>
<property name="text">
<string>None</string>
</property>
</item>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="style_label">
<property name="text">
<string>Style Sheet</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="lang_label">
<property name="text">
<string>Language</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="lang_select"/>
</item>
<item row="1" column="0" alignment="Qt::AlignRight">
<widget class="QLabel" name="color_label">
<property name="text">
<string>Color Scheme</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QLabel" name="interface_info">
<property name="font">
<font>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Restart Rare to apply.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="style_select">
<item>
<property name="text">
<string>None</string>
</property>
</item>
</widget>
</item>
<item row="1" column="2">
<spacer name="interface_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>
</layout>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignTop">
<widget class="QGroupBox" name="img_dir_group">
<property name="title">
<string>Image Cache Directory</string>
</property>
<layout class="QVBoxLayout" name="img_dir_layout"/>
</widget>
</item>
<item row="2" column="0" alignment="Qt::AlignTop">
<widget class="QGroupBox" name="settings_group">
<property name="title">
<string>Behavior</string>
</property>
<layout class="QGridLayout" name="behavior_layout">
<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="5" column="0">
<widget class="QCheckBox" name="save_size">
<property name="text">
<string>Restore window size on application startup</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QCheckBox" name="notification">
<property name="text">
<string>Show notification on download completion</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="auto_sync_cloud">
<property name="text">
<string>Automatically sync with cloud</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="confirm_start">
<property name="text">
<string>Confirm game launch</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="auto_update">
<property name="text">
<string>Update games on application startup</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QCheckBox" name="sys_tray">
<property name="text">
<string>Exit to System tray</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="1" alignment="Qt::AlignTop">
<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="text">
<string notr="true"/>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="rpc_layout"/>
</item>
<item row="2" column="1">
<spacer name="rare_vspacer">
<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>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -0,0 +1,67 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'rpc_settings.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_RPCSettings(object):
def setupUi(self, RPCSettings):
RPCSettings.setObjectName("RPCSettings")
self.layout = QtWidgets.QGridLayout(RPCSettings)
self.layout.setObjectName("layout")
self.enable = QtWidgets.QComboBox(RPCSettings)
self.enable.setObjectName("enable")
self.enable.addItem("")
self.enable.addItem("")
self.enable.addItem("")
self.layout.addWidget(self.enable, 0, 1, 1, 1)
self.label = QtWidgets.QLabel(RPCSettings)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.label.sizePolicy().hasHeightForWidth())
self.label.setSizePolicy(sizePolicy)
self.label.setObjectName("label")
self.layout.addWidget(self.label, 0, 0, 1, 1)
self.show_game = QtWidgets.QCheckBox(RPCSettings)
self.show_game.setObjectName("show_game")
self.layout.addWidget(self.show_game, 1, 0, 1, 2)
self.show_os = QtWidgets.QCheckBox(RPCSettings)
self.show_os.setObjectName("show_os")
self.layout.addWidget(self.show_os, 2, 0, 1, 2)
self.show_time = QtWidgets.QCheckBox(RPCSettings)
self.show_time.setObjectName("show_time")
self.layout.addWidget(self.show_time, 3, 0, 1, 2)
self.retranslateUi(RPCSettings)
QtCore.QMetaObject.connectSlotsByName(RPCSettings)
def retranslateUi(self, RPCSettings):
_translate = QtCore.QCoreApplication.translate
RPCSettings.setWindowTitle(_translate("RPCSettings", "DiscordRPC"))
RPCSettings.setTitle(_translate("RPCSettings", "Discord RPC"))
self.enable.setItemText(0, _translate("RPCSettings", "When Playing"))
self.enable.setItemText(1, _translate("RPCSettings", "Always"))
self.enable.setItemText(2, _translate("RPCSettings", "Never"))
self.label.setText(_translate("RPCSettings", "Show"))
self.show_game.setText(_translate("RPCSettings", "Show Game"))
self.show_os.setText(_translate("RPCSettings", "Show OS"))
self.show_time.setText(_translate("RPCSettings", "Show Time playing"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
RPCSettings = QtWidgets.QGroupBox()
ui = Ui_RPCSettings()
ui.setupUi(RPCSettings)
RPCSettings.show()
sys.exit(app.exec_())

View file

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RPCSettings</class>
<widget class="QGroupBox" name="RPCSettings">
<property name="windowTitle">
<string>DiscordRPC</string>
</property>
<property name="title">
<string>Discord RPC</string>
</property>
<layout class="QGridLayout" name="layout">
<item row="0" column="1">
<widget class="QComboBox" name="enable">
<item>
<property name="text">
<string>When Playing</string>
</property>
</item>
<item>
<property name="text">
<string>Always</string>
</property>
</item>
<item>
<property name="text">
<string>Never</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<widget class="QCheckBox" name="show_game">
<property name="text">
<string>Show Game</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="show_os">
<property name="text">
<string>Show OS</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QCheckBox" name="show_time">
<property name="text">
<string>Show Time playing</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

56
rare/ui/utils/pathedit.py Normal file
View file

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'pathedit.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtWidgets
class Ui_PathEdit(object):
def setupUi(self, PathEdit):
PathEdit.setObjectName("PathEdit")
self.layout_pathedit = QtWidgets.QGridLayout(PathEdit)
self.layout_pathedit.setContentsMargins(0, 0, 0, 0)
self.layout_pathedit.setObjectName("layout_pathedit")
self.path_select = QtWidgets.QToolButton(PathEdit)
self.path_select.setObjectName("path_select")
self.layout_pathedit.addWidget(self.path_select, 0, 1, 1, 1)
self.text_edit = QtWidgets.QLineEdit(PathEdit)
self.text_edit.setMinimumSize(QtCore.QSize(300, 0))
self.text_edit.setObjectName("text_edit")
self.layout_pathedit.addWidget(self.text_edit, 0, 0, 1, 1)
self.layout_pathedit_save = QtWidgets.QHBoxLayout()
self.layout_pathedit_save.setObjectName("layout_pathedit_save")
spacerItem = QtWidgets.QSpacerItem(40, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.layout_pathedit_save.addItem(spacerItem)
self.save_path_button = QtWidgets.QPushButton(PathEdit)
self.save_path_button.setEnabled(True)
self.save_path_button.setObjectName("save_path_button")
self.layout_pathedit_save.addWidget(self.save_path_button)
self.layout_pathedit.addLayout(self.layout_pathedit_save, 1, 0, 1, 2)
self.retranslateUi(PathEdit)
QtCore.QMetaObject.connectSlotsByName(PathEdit)
def retranslateUi(self, PathEdit):
_translate = QtCore.QCoreApplication.translate
PathEdit.setWindowTitle(_translate("PathEdit", "PathEdit"))
self.path_select.setText(_translate("PathEdit", "Browse..."))
self.text_edit.setPlaceholderText(_translate("PathEdit", "Default"))
self.save_path_button.setText(_translate("PathEdit", "Save"))
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
PathEdit = QtWidgets.QWidget()
ui = Ui_PathEdit()
ui.setupUi(PathEdit)
PathEdit.show()
sys.exit(app.exec_())

72
rare/ui/utils/pathedit.ui Normal file
View file

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PathEdit</class>
<widget class="QWidget" name="PathEdit">
<property name="windowTitle">
<string>PathEdit</string>
</property>
<layout class="QGridLayout" name="layout_pathedit">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="0" column="1">
<widget class="QToolButton" name="path_select">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLineEdit" name="text_edit">
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="placeholderText">
<string>Default</string>
</property>
</widget>
</item>
<item row="1" column="0" colspan="2">
<layout class="QHBoxLayout" name="layout_pathedit_save">
<item>
<spacer name="hs_save">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="save_path_button">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -2,11 +2,12 @@ import os
from PyQt5.QtCore import Qt, QRect, QSize, QPoint, pyqtSignal
from PyQt5.QtGui import QMovie
from PyQt5.QtWidgets import QLayout, QStyle, QSizePolicy, QLabel, QFileDialog, QHBoxLayout, QWidget, QLineEdit, \
QPushButton, QStyleOptionTab, QStylePainter, QTabBar
from PyQt5.QtWidgets import QLayout, QStyle, QSizePolicy, QLabel, QFileDialog, QHBoxLayout, QWidget, QPushButton, \
QStyleOptionTab, QStylePainter, QTabBar
from qtawesome import icon
from rare import style_path
from rare.ui.utils.pathedit import Ui_PathEdit
class FlowLayout(QLayout):
@ -120,33 +121,51 @@ class ClickableLabel(QLabel):
super(ClickableLabel, self).__init__()
class PathEdit(QWidget):
def __init__(self, text: str = "",
type_of_file: QFileDialog.FileType = QFileDialog.AnyFile,
infotext: str = "", filter: str = None):
class PathEdit(QWidget, Ui_PathEdit):
def __init__(self,
text: str = "",
file_type: QFileDialog.FileType = QFileDialog.AnyFile,
type_filter: str = None,
name_filter: str = None,
edit_func: callable = None,
save_func: callable = None):
super(PathEdit, self).__init__()
self.filter = filter
self.type_of_file = type_of_file
self.info_text = infotext
self.layout = QHBoxLayout()
self.text_edit = QLineEdit(text)
self.path_select = QPushButton(self.tr("Select Path"))
self.path_select.clicked.connect(self.set_path)
self.layout.addWidget(self.text_edit)
self.layout.addWidget(self.path_select)
self.setLayout(self.layout)
self.setupUi(self)
def setPlaceholderText(self, text: str):
self.text_edit.setPlaceholderText(text)
self.type_filter = type_filter
self.name_filter = name_filter
self.file_type = file_type
self.edit_func = edit_func
self.save_func = save_func
if text:
self.text_edit.setText(text)
if self.edit_func is not None:
self.text_edit.textChanged.connect(self.edit_func)
if self.save_func is None:
self.save_path_button.setVisible(False)
else:
self.text_edit.textChanged.connect(lambda t: self.save_path_button.setDisabled(False))
self.save_path_button.clicked.connect(self.save)
self.save_path_button.setDisabled(True)
self.path_select.clicked.connect(self.set_path)
def text(self):
return self.text_edit.text()
def save(self):
self.save_func()
self.save_path_button.setDisabled(True)
def set_path(self):
dlg = QFileDialog(self, self.tr("Choose Path"), os.path.expanduser("~/"))
dlg.setFileMode(self.type_of_file)
if self.filter:
dlg.setFilter([self.filter])
dlg_path = self.text_edit.text()
if not dlg_path:
dlg_path = os.path.expanduser("~/")
dlg = QFileDialog(self, self.tr("Choose Path"), dlg_path)
dlg.setFileMode(self.file_type)
if self.type_filter:
dlg.setFilter([self.type_filter])
if self.name_filter:
dlg.setNameFilter(self.name_filter)
if dlg.exec_():
names = dlg.selectedFiles()
self.text_edit.setText(names[0])

View file

@ -0,0 +1,325 @@
"""Python adaptation of https://github.com/dridk/QJsonModel
Supports Python 2 and 3 with PySide, PySide2, PyQt4 or PyQt5.
Requires https://github.com/mottosso/Qt.py
Usage:
Use it like you would the C++ version.
>>> import qjsonmodel
>>> model = qjsonmodel.QJsonModel()
>>> model.load({"key": "value"})
Test:
Run the provided example to sanity check your Python,
dependencies and Qt binding.
$ python qjsonmodel.py
Changes:
This module differs from the C++ version in the following ways.
1. Setters and getters are replaced by Python properties
2. Objects are sorted by default, disabled via load(sort=False)
3. load() takes a Python dictionary as opposed to
a string or file handle.
- To load from a string, use built-in `json.loads()`
>>> import json
>>> document = json.loads("{'key': 'value'}")
>>> model.load(document)
- To load from a file, use `with open(fname)`
>>> import json
>>> with open("file.json") as f:
... document = json.load(f)
... model.load(document)
"""
import json
from PyQt5 import QtCore, QtWidgets
class QJsonTreeItem(object):
def __init__(self, parent=None):
self._parent = parent
self._key = ""
self._value = ""
self._type = None
self._children = list()
def appendChild(self, item):
self._children.append(item)
def child(self, row):
return self._children[row]
def parent(self):
return self._parent
def childCount(self):
return len(self._children)
def row(self):
return (
self._parent._children.index(self)
if self._parent else 0
)
@property
def key(self):
return self._key
@key.setter
def key(self, key):
self._key = key
@property
def value(self):
return self._value
@value.setter
def value(self, value):
self._value = value
@property
def type(self):
return self._type
@type.setter
def type(self, typ):
self._type = typ
@classmethod
def load(self, value, parent=None, sort=True):
rootItem = QJsonTreeItem(parent)
rootItem.key = "root"
if isinstance(value, dict):
items = (
sorted(value.items())
if sort else value.items()
)
for key, value in items:
child = self.load(value, rootItem)
child.key = key
child.type = type(value)
rootItem.appendChild(child)
elif isinstance(value, list):
for index, value in enumerate(value):
child = self.load(value, rootItem)
child.key = index
child.type = type(value)
rootItem.appendChild(child)
else:
rootItem.value = value
rootItem.type = type(value)
return rootItem
class QJsonModel(QtCore.QAbstractItemModel):
def __init__(self, parent=None):
super(QJsonModel, self).__init__(parent)
self._rootItem = QJsonTreeItem()
self._headers = ("key", "value")
def clear(self):
self.load({})
def load(self, document):
"""Load from dictionary
Arguments:
document (dict): JSON-compatible dictionary
"""
assert isinstance(document, (dict, list, tuple)), (
"`document` must be of dict, list or tuple, "
"not %s" % type(document)
)
self.beginResetModel()
self._rootItem = QJsonTreeItem.load(document)
self._rootItem.type = type(document)
self.endResetModel()
return True
def json(self, root=None):
"""Serialise model as JSON-compliant dictionary
Arguments:
root (QJsonTreeItem, optional): Serialise from here
defaults to the the top-level item
Returns:
model as dict
"""
root = root or self._rootItem
return self.genJson(root)
def data(self, index, role):
if not index.isValid():
return None
item = index.internalPointer()
if role == QtCore.Qt.DisplayRole:
if index.column() == 0:
return item.key
if index.column() == 1:
return item.value
elif role == QtCore.Qt.EditRole:
if index.column() == 1:
return item.value
def setData(self, index, value, role):
if role == QtCore.Qt.EditRole:
if index.column() == 1:
item = index.internalPointer()
item.value = str(value)
self.dataChanged.emit(index, index, [QtCore.Qt.EditRole])
return True
return False
def headerData(self, section, orientation, role):
if role != QtCore.Qt.DisplayRole:
return None
if orientation == QtCore.Qt.Horizontal:
return self._headers[section]
def index(self, row, column, parent=QtCore.QModelIndex()):
if not self.hasIndex(row, column, parent):
return QtCore.QModelIndex()
if not parent.isValid():
parentItem = self._rootItem
else:
parentItem = parent.internalPointer()
childItem = parentItem.child(row)
if childItem:
return self.createIndex(row, column, childItem)
else:
return QtCore.QModelIndex()
def parent(self, index):
if not index.isValid():
return QtCore.QModelIndex()
childItem = index.internalPointer()
parentItem = childItem.parent()
if parentItem == self._rootItem:
return QtCore.QModelIndex()
return self.createIndex(parentItem.row(), 0, parentItem)
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.column() > 0:
return 0
if not parent.isValid():
parentItem = self._rootItem
else:
parentItem = parent.internalPointer()
return parentItem.childCount()
def columnCount(self, parent=QtCore.QModelIndex()):
return 2
def flags(self, index):
flags = super(QJsonModel, self).flags(index)
if index.column() == 1:
return QtCore.Qt.ItemIsEditable | flags
else:
return flags
def genJson(self, item):
nchild = item.childCount()
if item.type is dict:
document = {}
for i in range(nchild):
ch = item.child(i)
document[ch.key] = self.genJson(ch)
return document
elif item.type == list:
document = []
for i in range(nchild):
ch = item.child(i)
document.append(self.genJson(ch))
return document
else:
return item.value
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
view = QtWidgets.QTreeView()
model = QJsonModel()
view.setModel(model)
document = json.loads("""\
{
"firstName": "John",
"lastName": "Smith",
"age": 25,
"address": {
"streetAddress": "21 2nd Street",
"city": "New York",
"state": "NY",
"postalCode": "10021"
},
"phoneNumber": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "fax",
"number": "646 555-4567"
}
]
}
""")
model.load(document)
model.clear()
model.load(document)
# Sanity check
assert (
json.dumps(model.json(), sort_keys=True) ==
json.dumps(document, sort_keys=True)
)
view.show()
view.resize(500, 300)
app.exec_()

View file

@ -64,7 +64,8 @@ def uninstall(app_name: str, core: LegendaryCore, options=None):
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")):
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:

View file

@ -4,7 +4,8 @@ import os
class InstallOptions:
def __init__(self, app_name: str, path: str = os.path.expanduser("~/legendary"),
max_workers: int = os.cpu_count() * 2, repair: bool = False,
download_only: bool = False, ignore_free_space: bool = False, force: bool = False):
download_only: bool = False, ignore_free_space: bool = False, force: bool = False,
):
self.app_name = app_name
self.path = path
self.max_workers = max_workers
@ -12,4 +13,3 @@ class InstallOptions:
self.download_only = download_only
self.ignore_free_space = ignore_free_space
self.force = force

View file

@ -4,7 +4,6 @@ from logging import getLogger
import pypresence.exceptions
from PyQt5.QtCore import QObject, QSettings
from PyQt5.QtWidgets import QMessageBox
from pypresence import Presence
from custom_legendary.core import LegendaryCore
@ -76,7 +75,8 @@ class DiscordRPC(QObject):
self.update_rpc(app_name)
def update_rpc(self, app_name=None):
if self.settings.value("rpc_enable", 0, int) == 2 or (app_name is None and self.settings.value("rpc_enable", 0, int) == 0):
if self.settings.value("rpc_enable", 0, int) == 2 or (
app_name is None and self.settings.value("rpc_enable", 0, int) == 0):
self.remove_rpc()
return
title = None

116
rare/utils/steam_grades.py Normal file
View file

@ -0,0 +1,116 @@
import difflib
import json
import os
from datetime import date
import requests
from PyQt5.QtCore import pyqtSignal
replace_chars = ",;.:-_ "
file = os.path.expanduser("~/.cache/rare/game_list.json")
url = "https://api.steampowered.com/ISteamApps/GetAppList/v2/"
# you should iniciate the module with the game's steam code
def get_grade(steam_code):
if steam_code == 0:
return "fail"
steam_code = str(steam_code)
url = 'https://www.protondb.com/api/v1/reports/summaries/'
res = requests.get(url + steam_code + '.json')
try:
lista = json.loads(res.text)
except json.decoder.JSONDecodeError:
return "fail"
return lista['tier']
def load_json() -> dict:
if not os.path.exists(p := os.path.expanduser("~/.cache/rare/steam_ids.json")):
response = requests.get(url)
steam_ids = json.loads(response.text)["applist"]["apps"]
ids = {}
for game in steam_ids:
ids[game["name"]] = game["appid"]
with open(os.path.expanduser(p), "w") as f:
f.write(json.dumps(ids))
f.close()
return ids
else:
return json.loads(open(os.path.expanduser("~/.cache/rare/steam_ids.json"), "r").read())
def upgrade_all(games, progress: pyqtSignal = None):
ids = load_json()
data = {}
for i, (title, app_name) in enumerate(games):
title = title.replace("Early Access", "").replace("Experimental", "").strip()
data[app_name] = {}
steam_id = get_steam_id(title, ids)
data[app_name] = {
"steam_id": steam_id,
"grade": get_grade(steam_id)}
if progress:
progress.emit(int(i / len(games) * 100))
with open(os.path.expanduser("~/.cache/rare/game_list.json"), "w") as f:
f.write(json.dumps(data))
f.close()
def get_steam_id(title: str, json_data=None):
title = title.replace("Early Access", "").replace("Experimental", "").strip()
if not json_data:
if not os.path.exists(p := os.path.expanduser("~/.cache/rare/steam_ids.json")):
response = requests.get(url)
ids = {}
steam_ids = json.loads(response.text)["applist"]["apps"]
for game in steam_ids:
ids[game["name"]] = game["appid"]
with open(os.path.expanduser(p), "w") as f:
f.write(json.dumps(steam_ids))
f.close()
else:
ids = json.loads(open(os.path.expanduser("~/.cache/rare/steam_ids.json"), "r").read())
else:
ids = json_data
steam_name = difflib.get_close_matches(title, ids.keys(), n=1)
if steam_name:
return ids[steam_name[0]]
else:
return 0
# print(x)
# for game in steam_ids:
# num = difflib.SequenceMatcher(None, game["name"], title).ratio()
# if num > most_similar[2] and num > 0.5:
# most_similar = (game["appid"], game["name"], num)
# print(time.time()-t)
# name = difflib.get_close_matches(steam_ids.keys(), title)
# return most_similar
def check_time(): # this function check if it's time to update
global file
text = open(file, 'r')
json_table = json.load(text)
text.close()
today = date.today()
day = 0 # it controls how many days it's necessary for an update
for i in 'ymd':
if i == 'd':
day = 7
else:
day = 0
if int(today.strftime('%' + i)) > int(json_table['data'][i]) + day:
return 1
else:
return 0

View file

@ -7,14 +7,15 @@ from logging import getLogger
import requests
from PIL import Image, UnidentifiedImageError
from PyQt5.QtCore import pyqtSignal, QLocale, QSettings
from PyQt5.QtGui import QPalette, QColor
# Windows
if os.name == "nt":
from win32com.client import Dispatch
from rare import lang_path, style_path
# Mac not supported
from rare import lang_path
from custom_legendary.core import LegendaryCore
logger = getLogger("Utils")
@ -123,6 +124,77 @@ def get_lang():
return QLocale.system().name().split("_")[0]
color_role_map = {
0: "WindowText",
1: "Button",
2: "Light",
3: "Midlight",
4: "Dark",
5: "Mid",
6: "Text",
7: "BrightText",
8: "ButtonText",
9: "Base",
10: "Window",
11: "Shadow",
12: "Highlight",
13: "HighlightedText",
14: "Link",
15: "LinkVisited",
16: "AlternateBase",
# 17: "NoRole",
18: "ToolTipBase",
19: "ToolTipText",
20: "PlaceholderText",
# 21: "NColorRoles",
}
color_group_map = {
0: "Active",
1: "Disabled",
2: "Inactive",
}
def load_color_scheme(path: str):
custom_palette = QPalette()
settings = QSettings(path, QSettings.IniFormat)
try:
settings.beginGroup("ColorScheme")
for g in color_group_map:
settings.beginGroup(color_group_map[g])
group = QPalette.ColorGroup(g)
for r in color_role_map:
role = QPalette.ColorRole(r)
custom_palette.setColor(group, role, QColor(settings.value(color_role_map[r])))
settings.endGroup()
settings.endGroup()
text_color = custom_palette.text().color()
text_color.setAlpha(128)
custom_palette.setColor(custom_palette.Active, custom_palette.PlaceholderText, text_color)
custom_palette.setColor(custom_palette.Inactive, custom_palette.PlaceholderText, text_color)
custom_palette.setColor(custom_palette.Disabled, custom_palette.PlaceholderText, text_color)
except:
custom_palette = None
return custom_palette
def get_color_schemes():
colors = []
for file in os.listdir(os.path.join(style_path, "colors")):
if file.endswith(".scheme") and os.path.isfile(os.path.join(style_path, "colors", file)):
colors.append(file.replace(".scheme", ""))
return colors
def get_style_sheets():
styles = []
for file in os.listdir(os.path.join(style_path, "qss")):
if file.endswith(".qss") and os.path.isfile(os.path.join(style_path, "qss", file)):
styles.append(file.replace(".qss", ""))
return styles
def get_possible_langs():
langs = ["en"]
for i in os.listdir(lang_path):
@ -191,6 +263,7 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"):
target = os.path.abspath(sys.argv[0])
# Name of link file
linkName = igame.title
for c in r'<>?":|\/*':
linkName.replace(c, "")
@ -214,5 +287,4 @@ def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"):
logger.info("Create Icon")
shortcut.IconLocation = os.path.join(icon + ".ico")
# Save shortcut
shortcut.save()

View file

@ -8,16 +8,17 @@ with open("README.md", "r") as fh:
long_description = fh.read()
requirements = [
"requests<3.0",
"pillow",
"setuptools",
"wheel",
"PyQt5",
"QtAwesome",
"notify-py",
"psutil",
"pypresence"
]
"requests<3.0",
"pillow",
"setuptools",
"wheel",
"PyQt5",
"QtAwesome",
"notify-py",
"psutil",
"pypresence",
'pywin32; platform_system == "Windows"'
]
if os.name == "nt":
requirements.append("pywin32")