diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e7d8cecb..0ab3d840 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -52,7 +52,7 @@ jobs:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
- python-version: '3.8'
+ python-version: '3.9.5'
- name: Install python deps
run: |
pip3 install cx_Freeze setuptools wheel
diff --git a/MANIFEST.in b/MANIFEST.in
index 3ee6d4e8..f1893424 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,5 @@
include README.md
include rare/languages/*.qm
-include rare/styles/*
\ No newline at end of file
+include rare/styles/*
+include rare/styles/qss/*
+include rare/styles/colors/*
diff --git a/custom_legendary/utils/manifests.py b/custom_legendary/utils/manifests.py
index 44b682c0..744ffa28 100644
--- a/custom_legendary/utils/manifests.py
+++ b/custom_legendary/utils/manifests.py
@@ -20,8 +20,19 @@ def combine_manifests(base_manifest: Manifest, delta_manifest: Manifest):
base_manifest.file_manifest_list.count = len(base_manifest.file_manifest_list.elements)
base_manifest.file_manifest_list._path_map = None
- # add chunks from delta manifest to main manifest and again clear path caches
- base_manifest.chunk_data_list.elements.extend(delta_manifest.chunk_data_list.elements)
+ # ensure guid map exists
+ try:
+ base_manifest.chunk_data_list.get_chunk_by_guid(0)
+ except:
+ pass
+
+ # add new chunks from delta manifest to main manifest and again clear maps and update count
+ existing_chunk_guids = base_manifest.chunk_data_list._guid_int_map.keys()
+
+ for chunk in delta_manifest.chunk_data_list.elements:
+ if chunk.guid_num not in existing_chunk_guids:
+ base_manifest.chunk_data_list.elements.append(chunk)
+
base_manifest.chunk_data_list.count = len(base_manifest.chunk_data_list.elements)
base_manifest.chunk_data_list._guid_map = None
base_manifest.chunk_data_list._guid_int_map = None
diff --git a/rare/__main__.py b/rare/__main__.py
index cbb387f8..271ddaff 100644
--- a/rare/__main__.py
+++ b/rare/__main__.py
@@ -1,8 +1,10 @@
+#!/usr/bin/python
+
import os
from argparse import ArgumentParser
from rare import __version__
-from rare.utils import singleton
+from rare.utils import singleton, utils
def main():
@@ -16,6 +18,11 @@ def main():
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")
+
+ parser.add_argument("--desktop-shortcut", action="store_true", dest="desktop_shortcut",
+ help="Use this, if there is no link on desktop to start Rare")
+ parser.add_argument("--startmenu-shortcut", action="store_true", dest="startmenu_shortcut",
+ help="Use this, if there is no link in start menu to launch Rare")
subparsers = parser.add_subparsers(title="Commands", dest="subparser")
launch_parser = subparsers.add_parser("launch")
@@ -23,6 +30,13 @@ def main():
args = parser.parse_args()
+ if args.desktop_shortcut:
+ utils.create_rare_desktop_link("desktop")
+ print("Link created")
+ if args.startmenu_shortcut:
+ utils.create_rare_desktop_link("start_menu")
+ print("link created")
+
if args.version:
print(__version__)
exit(0)
diff --git a/rare/components/dialogs/install_dialog.py b/rare/components/dialogs/install_dialog.py
index 92127ac0..42572669 100644
--- a/rare/components/dialogs/install_dialog.py
+++ b/rare/components/dialogs/install_dialog.py
@@ -1,24 +1,41 @@
import os
+from multiprocessing import Queue as MPQueue
-from PyQt5.QtWidgets import QDialog, QFormLayout, QVBoxLayout, QSpinBox, QFileDialog, QLabel, QPushButton, QHBoxLayout, \
- QCheckBox
+from PyQt5.QtCore import Qt, QObject, QRunnable, QThreadPool, pyqtSignal, pyqtSlot
+from PyQt5.QtGui import QCloseEvent
+from PyQt5.QtWidgets import QDialog, QFileDialog, QCheckBox, QMessageBox
from custom_legendary.core import LegendaryCore
+from custom_legendary.utils.selective_dl import games
+from rare.ui.components.dialogs.install_dialog import Ui_InstallDialog
from rare.utils.extra_widgets import PathEdit
+from rare.utils.models import InstallDownloadModel, InstallQueueItemModel
from rare.utils.utils import get_size
-class InstallDialog(QDialog):
- infos = 0
+class InstallDialog(QDialog, Ui_InstallDialog):
+ result_ready = pyqtSignal(InstallQueueItemModel)
+
+ def __init__(self, core: LegendaryCore, dl_item: InstallQueueItemModel, update=False, silent=False, parent=None):
+ super(InstallDialog, self).__init__(parent)
+ self.setupUi(self)
+ self.setAttribute(Qt.WA_DeleteOnClose, True)
+ self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint)
- def __init__(self, app_name, core: LegendaryCore, update=False):
- super(InstallDialog, self).__init__()
- self.layout = QVBoxLayout()
self.core = core
- self.game = self.core.get_game(app_name)
- self.form = QFormLayout()
- self.update_game = update
- self.layout.addWidget(QLabel(self.tr("
Install {}
").format(self.game.app_title)))
+ self.dl_item = dl_item
+ self.dl_item.status_q = MPQueue()
+ self.app_name = self.dl_item.options.app_name
+ self.game = self.core.get_game(self.app_name)
+ self.update = update
+ self.silent = silent
+
+ self.threadpool = QThreadPool(self)
+ self.threadpool.setMaxThreadCount(1)
+
+ header = self.tr("Update") if update else self.tr("Install")
+ self.install_dialog_label.setText(f"{header} \"{self.game.app_title}\"
")
+ self.setWindowTitle(f"{self.windowTitle()} - {header} \"{self.game.app_title}\"")
if self.core.lgd.config.has_option("Legendary", "install_dir"):
default_path = self.core.lgd.config.get("Legendary", "install_dir")
@@ -26,92 +43,218 @@ class InstallDialog(QDialog):
default_path = os.path.expanduser("~/legendary")
if not default_path:
default_path = os.path.expanduser("~/legendary")
- if not update:
- self.install_path_field = PathEdit(text=default_path, file_type=QFileDialog.DirectoryOnly)
- self.form.addRow(QLabel("Install directory"), self.install_path_field)
+
+ self.install_dir_edit = PathEdit(text=default_path,
+ file_type=QFileDialog.DirectoryOnly,
+ edit_func=self.option_changed)
+ self.install_dir_layout.addWidget(self.install_dir_edit)
+
+ if self.update:
+ self.install_dir_label.setVisible(False)
+ self.install_dir_edit.setVisible(False)
if self.core.lgd.config.has_option("Legendary", "max_workers"):
max_workers = self.core.lgd.config.get("Legendary", "max_workers")
else:
max_workers = 0
+ self.max_workers_spin.setValue(int(max_workers))
+ self.max_workers_spin.valueChanged.connect(self.option_changed)
- self.max_workes = QSpinBox()
- self.max_workes.setValue(int(max_workers))
- self.form.addRow(QLabel(self.tr("Max workers (0: Default)")), self.max_workes)
+ self.force_download_check.stateChanged.connect(self.option_changed)
+ self.ignore_space_check.stateChanged.connect(self.option_changed)
+ self.download_only_check.stateChanged.connect(self.option_changed)
- self.force = QCheckBox()
- self.force.setChecked(False)
- self.form.addRow(QLabel(self.tr("Force download")), self.force)
+ self.sdl_list_checks = list()
+ try:
+ for key, info in games[self.app_name].items():
+ cb = QDataCheckBox(info['name'], info['tags'])
+ if key == '__required':
+ self.dl_item.options.sdl_list.extend(info['tags'])
+ cb.setChecked(True)
+ cb.setDisabled(True)
+ self.sdl_list_layout.addWidget(cb)
+ self.sdl_list_checks.append(cb)
+ self.sdl_list_frame.resize(self.sdl_list_frame.minimumSize())
+ for cb in self.sdl_list_checks:
+ cb.stateChanged.connect(self.option_changed)
+ except KeyError:
+ self.sdl_list_frame.setVisible(False)
+ self.sdl_list_label.setVisible(False)
- self.ignore_free_space = QCheckBox()
- self.ignore_free_space.setChecked(False)
- self.form.addRow(QLabel(self.tr("Ignore free space (Warning!)")), self.ignore_free_space)
+ self.install_button.setEnabled(False)
- self.download_only = QCheckBox()
- self.download_only.setChecked(False)
- self.form.addRow(QLabel(self.tr("Do not install game")), self.download_only)
+ self.cancel_button.clicked.connect(self.cancel_clicked)
+ self.verify_button.clicked.connect(self.verify_clicked)
+ self.install_button.clicked.connect(self.install_clicked)
- self.layout.addLayout(self.form)
+ self.options_changed = False
+ self.worker_running = False
+ self.reject_close = True
- self.ok_btn = QPushButton("Next")
- self.ok_btn.clicked.connect(self.ok)
- self.cancel = QPushButton("Cancel")
- self.cancel.clicked.connect(lambda: self.close())
+ self.resize(self.minimumSize())
+ self.setFixedSize(self.size())
- self.button_layout = QHBoxLayout()
- self.button_layout.addStretch(1)
- self.button_layout.addWidget(self.ok_btn)
- self.button_layout.addWidget(self.cancel)
+ def execute(self):
+ if self.silent:
+ self.reject_close = False
+ self.get_download_info()
+ else:
+ self.show()
- self.layout.addLayout(self.button_layout)
+ def get_options(self):
+ self.dl_item.options.base_path = self.install_dir_edit.text() if not self.update else None
+ self.dl_item.options.max_workers = self.max_workers_spin.value()
+ self.dl_item.options.force = self.force_download_check.isChecked()
+ self.dl_item.options.ignore_space_req = self.ignore_space_check.isChecked()
+ self.dl_item.options.no_install = self.download_only_check.isChecked()
+ self.dl_item.options.sdl_list = ['']
+ for cb in self.sdl_list_checks:
+ if data := cb.isChecked():
+ self.dl_item.options.sdl_list.extend(data)
- self.setLayout(self.layout)
+ def get_download_info(self):
+ self.dl_item.download = None
+ info_worker = InstallInfoWorker(self.core, self.dl_item)
+ info_worker.setAutoDelete(True)
+ info_worker.signals.result.connect(self.on_worker_result)
+ info_worker.signals.failed.connect(self.on_worker_failed)
+ info_worker.signals.finished.connect(self.on_worker_finished)
+ self.worker_running = True
+ self.threadpool.start(info_worker)
- def get_information(self, path=None):
- if path:
- self.install_path_field.text_edit.setText(path)
- self.exec_()
- return self.infos
+ def verify_clicked(self):
+ message = self.tr("Updating...")
+ self.download_size_info_label.setText(message)
+ self.download_size_info_label.setStyleSheet("font-style: italic; font-weight: normal")
+ self.install_size_info_label.setText(message)
+ self.install_size_info_label.setStyleSheet("font-style: italic; font-weight: normal")
+ self.cancel_button.setEnabled(False)
+ self.verify_button.setEnabled(False)
+ self.install_button.setEnabled(False)
+ self.options_changed = False
+ self.get_options()
+ self.get_download_info()
- 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.download_only.isChecked()
+ def option_changed(self):
+ self.options_changed = True
+ self.install_button.setEnabled(False)
+ self.verify_button.setEnabled(not self.worker_running)
+
+ def cancel_clicked(self):
+ self.dl_item.download = None
+ self.reject_close = False
self.close()
-
-class InstallInfoDialog(QDialog):
- accept: bool = False
-
- def __init__(self, dl_size, install_size):
- super(InstallInfoDialog, self).__init__()
- self.layout = QVBoxLayout()
- self.infos = QLabel(self.tr(
- "Download size: {}\nInstall size: {}").format(get_size(dl_size), get_size(install_size)))
- self.layout.addWidget(self.infos)
-
- self.btn_layout = QHBoxLayout()
- self.install_btn = QPushButton(self.tr("Install"))
- self.install_btn.clicked.connect(self.install)
- self.cancel_button = QPushButton(self.tr("Cancel"))
- self.cancel_button.clicked.connect(self.cancel)
- self.btn_layout.addStretch(1)
- self.btn_layout.addWidget(self.install_btn)
- self.btn_layout.addWidget(self.cancel_button)
- self.layout.addLayout(self.btn_layout)
-
- self.setLayout(self.layout)
-
- def get_accept(self):
- self.exec_()
- return self.accept
-
- def install(self):
- self.accept = True
+ def install_clicked(self):
+ self.reject_close = False
self.close()
- def cancel(self):
- self.accept = False
- self.close()
+ def on_worker_result(self, dl_item: InstallDownloadModel):
+ self.dl_item.download = dl_item
+ # TODO: Check available size and act accordingly
+ # TODO: (show message in label | color it | disable install unless ignore)
+ # TODO: Find a way to get the installation size delta and show it
+ download_size = self.dl_item.download.analysis.dl_size
+ install_size = self.dl_item.download.analysis.install_size
+ if download_size:
+ self.download_size_info_label.setText("{}".format(get_size(download_size)))
+ self.download_size_info_label.setStyleSheet("font-style: normal; font-weight: bold")
+ self.install_button.setEnabled(not self.options_changed)
+ else:
+ self.install_size_info_label.setText(self.tr("Game already installed"))
+ self.install_size_info_label.setStyleSheet("font-style: italics; font-weight: normal")
+ self.install_size_info_label.setText("{}".format(get_size(install_size)))
+ self.install_size_info_label.setStyleSheet("font-style: normal; font-weight: bold")
+ self.verify_button.setEnabled(self.options_changed)
+ self.cancel_button.setEnabled(True)
+ if self.silent:
+ self.close()
+
+ def on_worker_failed(self, message: str):
+ error_text = self.tr("Error")
+ self.download_size_info_label.setText(error_text)
+ self.install_size_info_label.setText(error_text)
+ QMessageBox.critical(self, self.windowTitle(), message)
+ self.verify_button.setEnabled(self.options_changed)
+ self.cancel_button.setEnabled(True)
+ if self.silent:
+ self.close()
+
+ def on_worker_finished(self):
+ self.worker_running = False
+
+ # lk: happens when close() is called, also when top right 'X' is pressed.
+ # lk: reject any events not coming from the buttons in case the WM
+ # lk: doesn't honor the window hints
+ def closeEvent(self, a0: QCloseEvent) -> None:
+ if self.reject_close:
+ a0.ignore()
+ else:
+ self.threadpool.clear()
+ self.threadpool.waitForDone()
+ self.result_ready.emit(self.dl_item)
+ a0.accept()
+
+
+class InstallInfoWorkerSignals(QObject):
+ result = pyqtSignal(InstallDownloadModel)
+ failed = pyqtSignal(str)
+ finished = pyqtSignal()
+
+
+class InstallInfoWorker(QRunnable):
+
+ def __init__(self, core: LegendaryCore, dl_item: InstallQueueItemModel):
+ super(InstallInfoWorker, self).__init__()
+ self.signals = InstallInfoWorkerSignals()
+ self.core = core
+ self.dl_item = dl_item
+
+ @pyqtSlot()
+ def run(self):
+ try:
+ download = InstallDownloadModel(*self.core.prepare_download(
+ app_name=self.dl_item.options.app_name,
+ base_path=self.dl_item.options.base_path,
+ force=self.dl_item.options.force,
+ no_install=self.dl_item.options.no_install,
+ status_q=self.dl_item.status_q,
+ # max_shm=,
+ max_workers=self.dl_item.options.max_workers,
+ # game_folder=,
+ # disable_patching=,
+ # override_manifest=,
+ # override_old_manifest=,
+ # override_base_url=,
+ # platform_override=,
+ # file_prefix_filter=,
+ # file_exclude_filter=,
+ # file_install_tag=,
+ # dl_optimizations=,
+ # dl_timeout=,
+ repair=self.dl_item.options.repair,
+ # repair_use_latest=,
+ ignore_space_req=self.dl_item.options.ignore_space_req,
+ # disable_delta=,
+ # override_delta_manifest=,
+ # reset_sdl=,
+ sdl_prompt=lambda app_name, title: self.dl_item.options.sdl_list
+ ))
+ self.signals.result.emit(download)
+ except RuntimeError as e:
+ self.signals.failed.emit(str(e))
+ self.signals.finished.emit()
+
+
+class QDataCheckBox(QCheckBox):
+
+ def __init__(self, text, data=None, parent=None):
+ super(QDataCheckBox, self).__init__(parent)
+ self.setText(text)
+ self.data = data
+
+ def isChecked(self):
+ if super(QDataCheckBox, self).isChecked():
+ return self.data
+ else:
+ return False
diff --git a/rare/components/tab_widget.py b/rare/components/tab_widget.py
index 56ffd501..fe0213f2 100644
--- a/rare/components/tab_widget.py
+++ b/rare/components/tab_widget.py
@@ -14,7 +14,7 @@ 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
+from rare.utils.models import InstallQueueItemModel, InstallOptionsModel
class TabWidget(QTabWidget):
@@ -83,8 +83,8 @@ class TabWidget(QTabWidget):
# 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)))
+ self.games_tab.game_info.info.verify_game.connect(lambda app_name: self.start_download(
+ InstallOptionsModel(app_name, core.get_installed_game(app_name).install_path, repair=True)))
# Finished sync
self.cloud_saves.finished.connect(self.finished_sync)
@@ -96,18 +96,21 @@ class TabWidget(QTabWidget):
self.setIconSize(QSize(25, 25))
def install_game(self, app_name, disable_path=False):
+ install_dialog = InstallDialog(self.core,
+ InstallQueueItemModel(options=InstallOptionsModel(app_name=app_name)),
+ update=disable_path, parent=self)
+ install_dialog.result_ready.connect(self.on_install_dialog_closed)
+ install_dialog.execute()
- 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)
+ def on_install_dialog_closed(self, download_item: InstallQueueItemModel):
+ if download_item:
self.setCurrentIndex(1)
- self.start_download(options)
+ self.start_download(download_item)
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.setCurrentIndex(1)
self.downloadTab.install_game(options)
def game_imported(self, app_name: str):
diff --git a/rare/components/tabs/downloads/__init__.py b/rare/components/tabs/downloads/__init__.py
index 5ca1a62e..7e85e779 100644
--- a/rare/components/tabs/downloads/__init__.py
+++ b/rare/components/tabs/downloads/__init__.py
@@ -1,19 +1,17 @@
import datetime
from logging import getLogger
-from multiprocessing import Queue as MPQueue
-from PyQt5.QtCore import QThread, pyqtSignal, Qt, QSettings
-from PyQt5.QtWidgets import QWidget, QMessageBox, QVBoxLayout, QLabel, QGridLayout, QProgressBar, QPushButton, QDialog, \
- QListWidget, QHBoxLayout, QGroupBox
+from PyQt5.QtCore import QThread, pyqtSignal, QSettings
+from PyQt5.QtWidgets import QWidget, QMessageBox, QVBoxLayout, QLabel, QGridLayout, QProgressBar, QPushButton, \
+ QHBoxLayout, QGroupBox
from custom_legendary.core import LegendaryCore
from custom_legendary.models.downloading import UIUpdate
from custom_legendary.models.game import Game, InstalledGame
-from custom_legendary.utils.selective_dl import games
-from rare.components.dialogs.install_dialog import InstallInfoDialog, InstallDialog
+from rare.components.dialogs.install_dialog import InstallDialog
from rare.components.tabs.downloads.dl_queue_widget import DlQueueWidget
from rare.components.tabs.downloads.download_thread import DownloadThread
-from rare.utils.models import InstallOptions
+from rare.utils.models import InstallOptionsModel, InstallQueueItemModel
from rare.utils.utils import get_size
logger = getLogger("Download")
@@ -29,6 +27,7 @@ class DownloadTab(QWidget):
self.core = core
self.layout = QVBoxLayout()
self.active_game: Game = None
+ self.analysis = None
self.info_layout = QGridLayout()
@@ -85,7 +84,7 @@ class DownloadTab(QWidget):
widget = UpdateWidget(self.core, igame, self)
self.update_layout.addWidget(widget)
self.update_widgets[igame.app_name] = widget
- widget.update.connect(self.update_game)
+ widget.update_signal.connect(self.update_game)
if QSettings().value("auto_update", False, bool):
self.update_game(igame.app_name, True)
widget.update_button.setDisabled(True)
@@ -96,111 +95,26 @@ class DownloadTab(QWidget):
def stop_download(self):
self.thread.kill()
- def install_game(self, options: InstallOptions, from_update=False):
-
- status_queue = MPQueue()
- try:
- dlm, analysis, game, igame, repair, repair_file = self.core.prepare_download(
- app_name=options.app_name,
- base_path=options.path,
- force=options.force,
- no_install=options.download_only,
- status_q=status_queue,
- # max_shm=,
- max_workers=options.max_workers,
- # game_folder=,
- # disable_patching=,
- # override_manifest=,
- # override_old_manifest=,
- # override_base_url=,
- # platform_override=,
- # file_prefix_filter=,
- # file_exclude_filter=,
- # file_install_tag=,
- # dl_optimizations=,
- # dl_timeout=,
- repair=options.repair,
- # repair_use_latest=,
- ignore_space_req=options.ignore_free_space,
- # disable_delta=,
- # override_delta_manifest=,
- # reset_sdl=,
- sdl_prompt=self.sdl_prompt)
- except Exception as e:
- QMessageBox.warning(self, self.tr("Error preparing download"),
- str(e))
- return
-
- if not analysis.dl_size:
- QMessageBox.information(self, "Warning", self.tr("Download size is 0. Game already exists"))
- return
-
- # Information
- if not from_update:
- if not InstallInfoDialog(dl_size=analysis.dl_size, install_size=analysis.install_size).get_accept():
- self.finished.emit(False, None)
- return
-
+ def install_game(self, queue_item: InstallQueueItemModel):
if self.active_game is None:
- self.start_installation(dlm, game, status_queue, igame, repair_file, options, analysis,
- options.download_only)
+ self.start_installation(queue_item)
else:
- self.dl_queue.append(
- (dlm, game, status_queue, igame, repair_file, options, analysis, options.download_only))
+ self.dl_queue.append(queue_item)
self.queue_widget.update_queue(self.dl_queue)
- def start_installation(self, dlm, game, status_queue, igame, repair_file, options: InstallOptions, analysis,
- dl_only):
+ def start_installation(self, queue_item: InstallQueueItemModel):
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, dl_only)
+ self.active_game = queue_item.download.game
+ self.thread = DownloadThread(self.core, queue_item)
self.thread.status.connect(self.status)
self.thread.statistics.connect(self.statistics)
self.thread.start()
self.kill_button.setDisabled(False)
- self.analysis = analysis
+ self.analysis = queue_item.download.analysis
self.installing_game.setText(self.tr("Installing Game: ") + self.active_game.app_title)
- def sdl_prompt(self, app_name: str = '', title: str = '') -> list:
- sdl = QDialog()
- sdl.setWindowTitle('Select Additional Downloads')
-
- layout = QVBoxLayout(sdl)
- sdl.setLayout(layout)
-
- pack_list = QListWidget()
- layout.addWidget(pack_list)
-
- done = QPushButton(text='Done')
- done.clicked.connect(sdl.accept)
- layout.addWidget(done)
-
- tags = ['']
- if '__required' in games[app_name]:
- tags.extend(games[app_name]['__required']['tags'])
-
- # add available additional downloads to list
- pack_list.addItems([tag + ': ' + info['name'] for tag, info in games[app_name].items() if tag != '__required'])
-
- # enable checkboxes
- for i in range(len(pack_list)):
- item = pack_list.item(i)
- item.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled)
- item.setCheckState(Qt.Unchecked)
-
- sdl.exec_()
-
- # read checkboxes states
- for i in range(len(pack_list)):
- item = pack_list.item(i)
- if item.checkState() == Qt.Checked:
- tag = item.text().split(':')[0]
- tags.extend(games[app_name][tag]['tags'])
-
- return tags
-
def status(self, text):
if text == "dl_finished":
pass
@@ -223,7 +137,7 @@ class DownloadTab(QWidget):
self.active_game = None
if self.dl_queue:
- if self.dl_queue[0][1] == app_name:
+ if self.dl_queue[0].download.game.app_name == app_name:
self.dl_queue.pop(0)
self.queue_widget.update_queue(self.dl_queue)
@@ -241,7 +155,7 @@ class DownloadTab(QWidget):
self.reset_infos()
if len(self.dl_queue) != 0:
- self.start_installation(*self.dl_queue[0])
+ self.start_installation(self.dl_queue[0])
else:
self.queue_widget.update_queue(self.dl_queue)
@@ -253,7 +167,7 @@ class DownloadTab(QWidget):
self.active_game = None
self.finished.emit((False, None))
if self.dl_queue:
- self.start_installation(*self.dl_queue[0])
+ self.start_installation(self.dl_queue[0])
def reset_infos(self):
self.kill_button.setDisabled(True)
@@ -279,18 +193,18 @@ class DownloadTab(QWidget):
def update_game(self, app_name: str, auto=False):
logger.info("Update " + app_name)
- if not auto:
- infos = InstallDialog(app_name, self.core, True).get_information()
+ install_dialog = InstallDialog(self.core,
+ InstallQueueItemModel(options=InstallOptionsModel(app_name=app_name)),
+ update=True, silent=auto, parent=self)
+ install_dialog.result_ready.connect(self.on_install_dialog_closed)
+ install_dialog.execute()
+
+ def on_install_dialog_closed(self, download_item: InstallQueueItemModel):
+ if download_item:
+ self.install_game(download_item)
else:
- self.install_game(InstallOptions(app_name=app_name), True)
- return
- if infos != 0:
- 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, 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)
+ self.update_widgets[download_item.options.app_name].update_button.setDisabled(False)
+ self.update_widgets[download_item.options.app_name].update_with_settings.setDisabled(False)
class UpdateWidget(QWidget):
diff --git a/rare/components/tabs/downloads/dl_queue_widget.py b/rare/components/tabs/downloads/dl_queue_widget.py
index 72edd64f..b97a0e8e 100644
--- a/rare/components/tabs/downloads/dl_queue_widget.py
+++ b/rare/components/tabs/downloads/dl_queue_widget.py
@@ -4,6 +4,8 @@ from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QGroupBox, QVBoxLayout, QLabel, QHBoxLayout, QPushButton, QWidget
from qtawesome import icon
+from rare.utils.models import InstallQueueItemModel
+
logger = getLogger("QueueWidget")
@@ -12,9 +14,9 @@ class DlWidget(QWidget):
move_down = pyqtSignal(str) # app_name
remove = pyqtSignal(str) # app_name
- def __init__(self, index, item):
+ def __init__(self, index, queue_item: InstallQueueItemModel):
super(DlWidget, self).__init__()
- self.app_name = item[1].app_name
+ self.app_name = queue_item.download.game.app_name
self.layout = QHBoxLayout()
self.left_layout = QVBoxLayout()
@@ -33,11 +35,11 @@ class DlWidget(QWidget):
self.layout.addLayout(self.left_layout)
self.right_layout = QVBoxLayout()
- self.title = QLabel(item[1].app_title)
+ self.title = QLabel(queue_item.download.game.app_title)
self.right_layout.addWidget(self.title)
- dl_size = item[-1].dl_size
- install_size = item[-1].install_size
+ dl_size = queue_item.download.analysis.dl_size
+ install_size = queue_item.download.analysis.install_size
self.size = QHBoxLayout()
@@ -69,7 +71,7 @@ class DlQueueWidget(QGroupBox):
self.setLayout(self.layout)
def update_queue(self, dl_queue: list):
- logger.info("Update Queue " + ", ".join(i[1].app_title for i in dl_queue))
+ logger.info("Update Queue " + ", ".join(i.download.game.app_title for i in dl_queue))
self.dl_queue = dl_queue
self.setLayout(QVBoxLayout())
QWidget().setLayout(self.layout)
@@ -93,7 +95,7 @@ class DlQueueWidget(QGroupBox):
def remove(self, app_name):
for index, i in enumerate(self.dl_queue):
- if i[1].app_name == app_name:
+ if i.download.game.app_name == app_name:
self.dl_queue.pop(index)
break
else:
@@ -106,7 +108,7 @@ class DlQueueWidget(QGroupBox):
index: int
for i, item in enumerate(self.dl_queue):
- if item[1].app_name == app_name:
+ if item.download.game.app_name == app_name:
index = i
break
else:
@@ -120,7 +122,7 @@ class DlQueueWidget(QGroupBox):
index: int
for i, item in enumerate(self.dl_queue):
- if item[1].app_name == app_name:
+ if item.download.game.app_name == app_name:
index = i
break
else:
diff --git a/rare/components/tabs/downloads/download_thread.py b/rare/components/tabs/downloads/download_thread.py
index 195ff932..923c06ac 100644
--- a/rare/components/tabs/downloads/download_thread.py
+++ b/rare/components/tabs/downloads/download_thread.py
@@ -4,7 +4,6 @@ import subprocess
import sys
import time
from logging import getLogger
-from multiprocessing import Queue as MPQueue
from queue import Empty
import psutil
@@ -12,8 +11,8 @@ from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtWidgets import QMessageBox
from custom_legendary.core import LegendaryCore
-from custom_legendary.downloader.manager import DLManager
from custom_legendary.models.downloading import UIUpdate, WriterTask
+from rare.utils.models import InstallQueueItemModel
logger = getLogger("Download")
@@ -22,16 +21,15 @@ class DownloadThread(QThread):
status = pyqtSignal(str)
statistics = pyqtSignal(UIUpdate)
- def __init__(self, dlm: DLManager, core: LegendaryCore, status_queue: MPQueue, igame, repair=False,
- repair_file=None, dl_only=False):
+ def __init__(self, core: LegendaryCore, queue_item: InstallQueueItemModel):
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
- self.repair_file = repair_file
+ self.dlm = queue_item.download.dlmanager
+ self.no_install = queue_item.options.no_install
+ self.status_q = queue_item.status_q
+ self.igame = queue_item.download.igame
+ self.repair = queue_item.download.repair
+ self.repair_file = queue_item.download.repair_file
self._kill = False
def run(self):
@@ -105,7 +103,7 @@ class DownloadThread(QThread):
dl_stopped = True
try:
if not dl_stopped:
- self.statistics.emit(self.status_queue.get(timeout=1))
+ self.statistics.emit(self.status_q.get(timeout=1))
except queue.Empty:
pass
@@ -124,7 +122,7 @@ class DownloadThread(QThread):
logger.info(f"Download finished in {start_time - end_t}s")
game = self.core.get_game(self.igame.app_name)
- if not self.dl_only:
+ if not self.no_install:
postinstall = self.core.install_game(self.igame)
if postinstall:
self._handle_postinstall(postinstall, self.igame)
diff --git a/rare/components/tabs/games/game_info/__init__.py b/rare/components/tabs/games/game_info/__init__.py
index 465fd8b6..b9729dfa 100644
--- a/rare/components/tabs/games/game_info/__init__.py
+++ b/rare/components/tabs/games/game_info/__init__.py
@@ -7,7 +7,7 @@ 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 custom_legendary.models.game import Game, InstalledGame
from rare.components.tabs.games.game_info.dlcs import DlcTab
from rare.components.tabs.games.game_info.game_settings import GameSettings
from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
@@ -65,22 +65,26 @@ class GameInfo(QWidget, Ui_GameInfo):
def __init__(self, core: LegendaryCore, parent):
super(GameInfo, self).__init__(parent=parent)
self.setupUi(self)
- self.ratings = {"platinum": self.tr("Platimum"),
+ self.core = core
+
+ 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"}
+ "fail": self.tr("Could not get grade"),
+ "pending": self.tr("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
+
if os.name == "nt":
self.lbl_grade.setVisible(False)
self.grade.setVisible(False)
+ self.game_actions_stack.setCurrentIndex(0)
+ self.game_actions_stack.resize(self.game_actions_stack.minimumSize())
+
self.uninstall_button.clicked.connect(self.uninstall)
self.verify_button.clicked.connect(self.verify)
self.repair_button.clicked.connect(self.repair)
@@ -153,14 +157,15 @@ class GameInfo(QWidget, Ui_GameInfo):
if os.name != "nt" and self.grade_table:
try:
- grade = self.ratings.get(self.grade_table[app_name].get("grade"))
+ grade = self.grade_table[app_name]["grade"]
except KeyError:
- grade = (self.tr("Error"))
- self.grade.setText(grade)
+ grade = "fail"
+ self.grade.setText(self.ratings[grade])
if len(self.verify_threads.keys()) == 0 or not self.verify_threads.get(app_name):
self.verify_widget.setCurrentIndex(0)
elif self.verify_threads.get(app_name):
self.verify_widget.setCurrentIndex(1)
self.verify_progress.setValue(
- self.verify_threads[app_name].num / self.verify_threads[app_name].total * 100)
+ self.verify_threads[app_name].num / self.verify_threads[app_name].total * 100
+ )
diff --git a/rare/components/tabs/games/game_info/uninstalled_info.py b/rare/components/tabs/games/game_info/uninstalled_info.py
index fcb5b781..8a230516 100644
--- a/rare/components/tabs/games/game_info/uninstalled_info.py
+++ b/rare/components/tabs/games/game_info/uninstalled_info.py
@@ -1,15 +1,17 @@
import json
import os
-from PyQt5.QtCore import pyqtSignal, QSettings, Qt
+from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QPixmap, QKeyEvent
-from PyQt5.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QTabWidget, QTreeView
+from PyQt5.QtWidgets import QWidget, QTabWidget, QTreeView
from qtawesome import icon
from custom_legendary.core import LegendaryCore
from custom_legendary.models.game import Game
+from rare.ui.components.tabs.games.game_info.game_info import Ui_GameInfo
from rare.utils.extra_widgets import SideTabBar
from rare.utils.json_formatter import QJsonModel
+from rare.utils.utils import IMAGE_DIR
class UninstalledTabInfo(QTabWidget):
@@ -18,7 +20,6 @@ class UninstalledTabInfo(QTabWidget):
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"))
@@ -49,69 +50,44 @@ class UninstalledTabInfo(QTabWidget):
self.parent().layout.setCurrentIndex(0)
-class UninstalledInfo(QWidget):
+class UninstalledInfo(QWidget, Ui_GameInfo):
game: Game
install_game = pyqtSignal(str)
- def __init__(self, core: LegendaryCore, parent):
+ def __init__(self, core: LegendaryCore, parent=None):
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.setupUi(self)
+ self.core = core
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"}
+ "fail": self.tr("Could not get grade"),
+ "pending": self.tr("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.core = core
+ if os.name == "nt":
+ self.lbl_grade.setVisible(False)
+ self.grade.setVisible(False)
- self.settings = QSettings()
+ self.install_size.setEnabled(False)
+ self.lbl_install_size.setEnabled(False)
+ self.install_path.setEnabled(False)
+ self.lbl_install_path.setEnabled(False)
- 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.game_actions_stack.setCurrentIndex(1)
+ self.game_actions_stack.resize(self.game_actions_stack.minimumSize())
- 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"{self.game.app_title}
")
- self.app_name.setText("Appname: " + app_name)
-
- IMAGE_DIR = self.settings.value("img_dir", os.path.expanduser("~/.cache/rare/images"), str)
+ self.game_title.setText(f"{self.game.app_title}
")
if os.path.exists(f"{IMAGE_DIR}/{self.game.app_name}/FinalArt.png"):
pixmap = QPixmap(f"{IMAGE_DIR}/{self.game.app_name}/FinalArt.png")
@@ -127,13 +103,15 @@ class UninstalledInfo(QWidget):
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"):
+ 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("N/A")
+ self.install_path.setText("N/A")
+
+ if os.name != "nt" and self.grade_table:
try:
- rating = self.grade_table[app_name]["grade"]
+ grade = 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])
+ grade = "fail"
+ self.grade.setText(self.ratings[grade])
diff --git a/rare/components/tabs/games/game_list.py b/rare/components/tabs/games/game_list.py
index 36b56942..5954ba31 100644
--- a/rare/components/tabs/games/game_list.py
+++ b/rare/components/tabs/games/game_list.py
@@ -13,14 +13,14 @@ from rare.components.tabs.games.game_widgets.installed_list_widget import Instal
from rare.components.tabs.games.game_widgets.uninstalled_icon_widget import IconWidgetUninstalled
from rare.components.tabs.games.game_widgets.uninstalled_list_widget import ListWidgetUninstalled
from rare.utils.extra_widgets import FlowLayout
-from rare.utils.models import InstallOptions
+from rare.utils.models import InstallOptionsModel
from rare.utils.utils import download_image
logger = getLogger("Game list")
class GameList(QStackedWidget):
- install_game = pyqtSignal(InstallOptions)
+ install_game = pyqtSignal(InstallOptionsModel)
show_game_info = pyqtSignal(str)
update_game = pyqtSignal()
game_exited = pyqtSignal(str)
@@ -346,14 +346,14 @@ class GameList(QStackedWidget):
else:
installed_names = [i.app_name for i in self.core.get_installed_list()]
# get Uninstalled games
- uninstalled_games = []
+ uninstalled_names = []
games = self.core.get_game_list(True)
for game in sorted(games, key=lambda x: x.app_title):
if not game.app_name in installed_names:
- uninstalled_games.append(game.app_name)
+ uninstalled_names.append(game.app_name)
new_installed_games = list(set(installed_names) - set([i.app_name for i in self.installed]))
- new_uninstalled_games = list(set(uninstalled_games) - set([i.app_name for i in self.uninstalled_names]))
+ new_uninstalled_games = list(set(uninstalled_names) - set([i.app_name for i in self.uninstalled_games]))
if (not new_uninstalled_games) and (not new_installed_games):
return
@@ -388,7 +388,7 @@ class GameList(QStackedWidget):
for game in sorted(games, key=lambda x: x.app_title):
if not game.app_name in installed_names:
self.uninstalled_names.append(game)
- for name in uninstalled_games:
+ for name in uninstalled_names:
i_widget, list_widget = self.widgets[name]
self.icon_layout.addWidget(i_widget)
self.list_layout.addWidget(list_widget)
diff --git a/rare/components/tabs/settings/rare.py b/rare/components/tabs/settings/rare.py
index 3aaff5e4..2fafc3d9 100644
--- a/rare/components/tabs/settings/rare.py
+++ b/rare/components/tabs/settings/rare.py
@@ -9,6 +9,7 @@ from PyQt5.QtWidgets import QFileDialog, QWidget
from rare.components.tabs.settings.rpc_settings import RPCSettings
from rare.ui.components.tabs.settings.rare import Ui_RareSettings
+from rare.utils import utils
from rare.utils.extra_widgets import PathEdit
from rare.utils.utils import get_lang, get_possible_langs, get_color_schemes, get_style_sheets
@@ -99,10 +100,58 @@ class RareSettings(QWidget, Ui_RareSettings):
lambda: self.settings.setValue("save_size", self.save_size.isChecked())
)
+ if os.name == "posix":
+ self.desktop_file = os.path.expanduser("~/Desktop/Rare.desktop")
+ self.start_menu_link = os.path.expanduser("~/.local/share/applications/Rare.desktop")
+ elif os.name == "nt":
+ self.desktop_file = os.path.expanduser("~/Desktop/Rare.lnk")
+ self.start_menu_link = os.path.expandvars("%appdata%/Microsoft/Windows/Start Menu")
+ else:
+ self.desktop_file = ""
+ self.start_menu_link = ""
+
+ if os.path.exists(self.desktop_file):
+ self.desktop_link.setText(self.tr("Remove desktop link"))
+ if os.path.exists(self.start_menu_link):
+ self.startmenu_link.setText(self.tr("Remove start menu link"))
+
+ self.desktop_link.clicked.connect(self.create_desktop_link)
+ self.startmenu_link.clicked.connect(self.create_start_menu_link)
+
self.log_dir_open_button.clicked.connect(self.open_dir)
+ self.log_dir_clean_button.clicked.connect(self.clean_logdir)
+
+ logdir = os.path.expanduser("~/.cache/rare/logs")
+ # get size of logdir
+ size = 0
+ for i in os.listdir(logdir):
+ size += os.path.getsize(os.path.join(logdir, i))
+
+ self.log_dir_size_label.setText(utils.get_size(size))
# TODO: Implement
- self.log_dir_clean_button.setVisible(False)
- self.log_dir_size_label.setVisible(False)
+ # self.log_dir_clean_button.setVisible(False)
+ # self.log_dir_size_label.setVisible(False)
+
+ def clean_logdir(self):
+ for i in os.listdir(os.path.expanduser("~/.cache/rare/logs")):
+ os.remove(os.path.expanduser("~/.cache/rare/logs/") + i)
+ self.log_dir_size_label.setText("0KB")
+
+ def create_start_menu_link(self):
+ if not os.path.exists(self.start_menu_link):
+ utils.create_rare_desktop_link("start_menu")
+ self.startmenu_link.setText(self.tr("Remove start menu link"))
+ else:
+ os.remove(self.start_menu_link)
+ self.startmenu_link.setText(self.tr("Create start menu link"))
+
+ def create_desktop_link(self):
+ if not os.path.exists(self.desktop_file):
+ utils.create_rare_desktop_link("start_menu")
+ self.desktop_link.setText(self.tr("Remove Desktop link"))
+ else:
+ os.remove(self.desktop_file)
+ self.desktop_link.setText(self.tr("Create desktop link"))
def on_color_select_changed(self, color):
if color:
diff --git a/rare/styles/colors/Adapta-Nokto.scheme b/rare/styles/colors/Adapta-Nokto.scheme
new file mode 100644
index 00000000..0c2b5543
--- /dev/null
+++ b/rare/styles/colors/Adapta-Nokto.scheme
@@ -0,0 +1,25 @@
+[ColorScheme]
+Active\AlternateBase=#ff273339
+Active\Base=#ff2f3d44
+Active\BrightText=#ffffffff
+Active\Button=#ff263238
+Active\ButtonText=#ffb9c3c7
+Active\Dark=#ff1f292e
+Active\Highlight=#ff00bcd4
+Active\HighlightedText=#ffffffff
+Active\Light=#ff2f3e46
+Active\Link=#ff0000ff
+Active\LinkVisited=#ffff00ff
+Active\Mid=#ffb8b5b2
+Active\Midlight=#ffcbc7c4
+Active\PlaceholderText=#80b9c3c7
+Active\Shadow=#ff1d262b
+Active\Text=#ffb9c3c7
+Active\ToolTipBase=#ff263238
+Active\ToolTipText=#ffcfd8dc
+Active\Window=#ff263238
+Active\WindowText=#ffb9c3c7
+Disabled\ButtonText=#ff808080
+Disabled\HighlightedText=#ff808080
+Disabled\Text=#ff808080
+Disabled\WindowText=#ff808080
diff --git a/rare/styles/colors/Airy.scheme b/rare/styles/colors/Airy.scheme
new file mode 100644
index 00000000..f445a80a
--- /dev/null
+++ b/rare/styles/colors/Airy.scheme
@@ -0,0 +1,39 @@
+[ColorScheme]
+Active\AlternateBase=#ff5c5b5a
+Active\Base=#ffc8c8c8
+Active\BrightText=#ff0a0a0a
+Active\Button=#ffdcdcdc
+Active\ButtonText=#ff0a0a0a
+Active\Dark=#ff646464
+Active\Highlight=#ff0986d3
+Active\HighlightedText=#ff0a0a0a
+Active\Light=#ffdcdcdc
+Active\Link=#ff0986d3
+Active\LinkVisited=#ffa70b06
+Active\Mid=#ffe1e1e1
+Active\Midlight=#ff5e5c5b
+Active\PlaceholderText=#80000000
+Active\Shadow=#ffe7e4e0
+Active\Text=#ff000000
+Active\ToolTipBase=#ff646464
+Active\ToolTipText=#ff050505
+Active\Window=#ffffffff
+Active\WindowText=#ff000000
+Disabled\Base=#ff969696
+Disabled\BrightText=#ffffffff
+Disabled\Button=#ff424245
+Disabled\ButtonText=#ff808080
+Disabled\HighlightedText=#ff808080
+Disabled\Text=#ff808080
+Disabled\ToolTipText=#ffffffff
+Disabled\Window=#ffc8c8c8
+Disabled\WindowText=#ffffffff
+Inactive\Base=#ff969696
+Inactive\BrightText=#ff323232
+Inactive\Button=#ffb4b4b4
+Inactive\ButtonText=#ff323232
+Inactive\HighlightedText=#ff323232
+Inactive\Text=#ff323232
+Inactive\ToolTipText=#ff323232
+Inactive\Window=#ffc8c8c8
+Inactive\WindowText=#ff323232
diff --git a/rare/styles/colors/Arc-Dark.scheme b/rare/styles/colors/Arc-Dark.scheme
new file mode 100644
index 00000000..c734d720
--- /dev/null
+++ b/rare/styles/colors/Arc-Dark.scheme
@@ -0,0 +1,26 @@
+[ColorScheme]
+Active\AlternateBase=#ff3f4350
+Active\Base=#ff404552
+Active\BrightText=#ffffffff
+Active\Button=#ff383c4a
+Active\ButtonText=#ffd3dae3
+Active\Dark=#ff2e323d
+Active\Highlight=#ff5294e2
+Active\HighlightedText=#ffffffff
+Active\Light=#ff464b5c
+Active\Link=#ff0000ff
+Active\LinkVisited=#ffff00ff
+Active\Mid=#ffa0a0a4
+Active\Midlight=#ffe9e7e3
+Active\PlaceholderText=#80d3dae3
+Active\Shadow=#ff2b2e39
+Active\Text=#ffd3dae3
+Active\ToolTipBase=#ffffffdc
+Active\ToolTipText=#ffd3dae3
+Active\Window=#ff383c4a
+Active\WindowText=#ffd3dae3
+Disabled\ButtonText=#ff858b96
+Disabled\Highlight=#ffe2e2e2
+Disabled\Text=#ff858b96
+Disabled\WindowText=#ff858b96
+Inactive\Highlight=#ff4084d6
diff --git a/rare/styles/colors/Arc-Darker.scheme b/rare/styles/colors/Arc-Darker.scheme
new file mode 100644
index 00000000..0462ed08
--- /dev/null
+++ b/rare/styles/colors/Arc-Darker.scheme
@@ -0,0 +1,26 @@
+[ColorScheme]
+Active\AlternateBase=#fffafafa
+Active\Base=#ffffffff
+Active\BrightText=#ffffffff
+Active\Button=#fff5f6f7
+Active\ButtonText=#ff5c616c
+Active\Dark=#ffcccdce
+Active\Highlight=#ff5294e2
+Active\HighlightedText=#ffffffff
+Active\Light=#ffffffff
+Active\Link=#ff0000ff
+Active\LinkVisited=#ffff00ff
+Active\Mid=#ffa0a0a4
+Active\Midlight=#ffe9e7e3
+Active\PlaceholderText=#805c616c
+Active\Shadow=#ffbdbdbe
+Active\Text=#ff5c616c
+Active\ToolTipBase=#ffffffdc
+Active\ToolTipText=#ff5c616c
+Active\Window=#fff5f6f7
+Active\WindowText=#ff5c616c
+Disabled\ButtonText=#ffa8abb1
+Disabled\Highlight=#ffe2e2e2
+Disabled\Text=#ffa8abb1
+Disabled\WindowText=#ffa8abb1
+Inactive\Highlight=#ff4084d6
diff --git a/rare/styles/colors/Darker.scheme b/rare/styles/colors/Darker.scheme
new file mode 100644
index 00000000..db91755f
--- /dev/null
+++ b/rare/styles/colors/Darker.scheme
@@ -0,0 +1,25 @@
+[ColorScheme]
+Active\AlternateBase=#ff5c5b5a
+Active\Base=#ff3d3d3d
+Active\BrightText=#ffffffff
+Active\Button=#ff424245
+Active\ButtonText=#ffffffff
+Active\Dark=#ff302f2e
+Active\Highlight=#ff12608a
+Active\HighlightedText=#fff9f9f9
+Active\Light=#ff979797
+Active\Link=#ff0986d3
+Active\LinkVisited=#ffa70b06
+Active\Mid=#ff4a4947
+Active\Midlight=#ff5e5c5b
+Active\PlaceholderText=#80ffffff
+Active\Shadow=#ffe7e4e0
+Active\Text=#ffffffff
+Active\ToolTipBase=#ff3f3f36
+Active\ToolTipText=#ffffffff
+Active\Window=#ff222020
+Active\WindowText=#ffffffff
+Disabled\ButtonText=#ff808080
+Disabled\HighlightedText=#ff808080
+Disabled\Text=#ff808080
+Disabled\WindowText=#ff808080
diff --git a/rare/styles/colors/Dusk.scheme b/rare/styles/colors/Dusk.scheme
new file mode 100644
index 00000000..49e4012f
--- /dev/null
+++ b/rare/styles/colors/Dusk.scheme
@@ -0,0 +1,26 @@
+[ColorScheme]
+Active\AlternateBase=#ff7f7f7f
+Active\Base=#ff7f7f7f
+Active\BrightText=#ffffffff
+Active\Button=#ff7f7f7f
+Active\ButtonText=#ff000000
+Active\Dark=#ff7f7f7f
+Active\Highlight=#ff308cc6
+Active\HighlightedText=#ffffffff
+Active\Light=#ffffffff
+Active\Link=#ff0000ff
+Active\LinkVisited=#ffff00ff
+Active\Mid=#ffb8b5b2
+Active\Midlight=#ffcbc7c4
+Active\PlaceholderText=#80000000
+Active\Shadow=#ff707070
+Active\Text=#ff000000
+Active\ToolTipBase=#ff7f7f7f
+Active\ToolTipText=#ff000000
+Active\Window=#ff7f7f7f
+Active\WindowText=#ff000000
+Disabled\ButtonText=#ffbebebe
+Disabled\Highlight=#ff7f7f7f
+Disabled\Shadow=#ffb1aeab
+Disabled\Text=#ffbebebe
+Disabled\WindowText=#ffbebebe
diff --git a/rare/styles/colors/Numix-Dark.scheme b/rare/styles/colors/Numix-Dark.scheme
index 7aa182da..faab227e 100644
--- a/rare/styles/colors/Numix-Dark.scheme
+++ b/rare/styles/colors/Numix-Dark.scheme
@@ -1,61 +1,25 @@
[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
+Active\AlternateBase=#ff2f2f2f
+Active\Base=#ff333333
+Active\BrightText=#ffffffff
+Active\Button=#ff525252
+Active\ButtonText=#ffdddddd
+Active\Dark=#ff333333
+Active\Highlight=#fff0544c
+Active\HighlightedText=#ffffffff
+Active\Light=#ff555555
+Active\Link=#fffc6f5d
+Active\LinkVisited=#ff853931
+Active\Mid=#ffa0a0a4
+Active\Midlight=#ffe9e7e3
+Active\PlaceholderText=#80eeeeee
+Active\Shadow=#ff343434
+Active\Text=#ffeeeeee
+Active\ToolTipBase=#ff444444
+Active\ToolTipText=#ffeeeeee
+Active\Window=#ff444444
+Active\WindowText=#ffdddddd
+Disabled\ButtonText=#ff808080
+Disabled\HighlightedText=#ff808080
+Disabled\Text=#ff808080
+Disabled\WindowText=#ff808080
diff --git a/rare/styles/colors/Rare.scheme b/rare/styles/colors/Rare.scheme
index 1b954210..e2f3146c 100644
--- a/rare/styles/colors/Rare.scheme
+++ b/rare/styles/colors/Rare.scheme
@@ -1,61 +1,25 @@
[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
+Active\AlternateBase=#fff7f7f7
+Active\Base=#ff333344
+Active\BrightText=#ffffffff
+Active\Button=#ff3c3f41
+Active\ButtonText=#ffeeeeee
+Active\Dark=#ff9f0910
+Active\Highlight=#ff2f4f4f
+Active\HighlightedText=#ffeeeeee
+Active\Light=#ffffffff
+Active\Link=#ff0000ff
+Active\LinkVisited=#ffff00ff
+Active\Mid=#ffb80e35
+Active\Midlight=#ffca0651
+Active\PlaceholderText=#80eeeeee
+Active\Shadow=#ff767676
+Active\Text=#ffeeeeee
+Active\ToolTipBase=#ffffffdc
+Active\ToolTipText=#ffeeeeee
+Active\Window=#ff202225
+Active\WindowText=#ffeeeeee
+Disabled\ButtonText=#ff808080
+Disabled\HighlightedText=#ff808080
+Disabled\Text=#ff808080
+Disabled\WindowText=#ff808080
diff --git a/rare/styles/colors/Zukitre.scheme b/rare/styles/colors/Zukitre.scheme
new file mode 100644
index 00000000..85fd63bc
--- /dev/null
+++ b/rare/styles/colors/Zukitre.scheme
@@ -0,0 +1,25 @@
+[ColorScheme]
+Active\AlternateBase=#fff7f7f7
+Active\Base=#fff7f7f7
+Active\BrightText=#ffffffff
+Active\Button=#ffd6d6d6
+Active\ButtonText=#ff2c2c2c
+Active\Dark=#ffb3b3b3
+Active\Highlight=#ff258ef8
+Active\HighlightedText=#ffffffff
+Active\Light=#ffffffff
+Active\Link=#ff0000ff
+Active\LinkVisited=#ffff00ff
+Active\Mid=#ffa0a0a4
+Active\Midlight=#ffe9e7e3
+Active\PlaceholderText=#802c2c2c
+Active\Shadow=#ffa5a5a5
+Active\Text=#ff2c2c2c
+Active\ToolTipBase=#ffffffdc
+Active\ToolTipText=#ff000000
+Active\Window=#ffd6d6d6
+Active\WindowText=#ff2c2c2c
+Disabled\ButtonText=#ff808080
+Disabled\HighlightedText=#ff808080
+Disabled\Text=#ff808080
+Disabled\WindowText=#ff808080
diff --git a/rare/styles/colors/ia_ora.scheme b/rare/styles/colors/ia_ora.scheme
deleted file mode 100644
index 5fbbc868..00000000
--- a/rare/styles/colors/ia_ora.scheme
+++ /dev/null
@@ -1,61 +0,0 @@
-[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
diff --git a/rare/ui/components/dialogs/install_dialog.py b/rare/ui/components/dialogs/install_dialog.py
new file mode 100644
index 00000000..58a817ca
--- /dev/null
+++ b/rare/ui/components/dialogs/install_dialog.py
@@ -0,0 +1,149 @@
+# -*- coding: utf-8 -*-
+
+# Form implementation generated from reading ui file 'install_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, QtGui, QtWidgets
+
+
+class Ui_InstallDialog(object):
+ def setupUi(self, InstallDialog):
+ InstallDialog.setObjectName("InstallDialog")
+ InstallDialog.setWindowTitle("Rare")
+ self.install_dialog_layout = QtWidgets.QGridLayout(InstallDialog)
+ self.install_dialog_layout.setObjectName("install_dialog_layout")
+ self.force_download_label = QtWidgets.QLabel(InstallDialog)
+ self.force_download_label.setObjectName("force_download_label")
+ self.install_dialog_layout.addWidget(self.force_download_label, 3, 0, 1, 1, QtCore.Qt.AlignRight)
+ self.button_layout = QtWidgets.QHBoxLayout()
+ self.button_layout.setObjectName("button_layout")
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.button_layout.addItem(spacerItem)
+ self.cancel_button = QtWidgets.QPushButton(InstallDialog)
+ self.cancel_button.setObjectName("cancel_button")
+ self.button_layout.addWidget(self.cancel_button)
+ self.verify_button = QtWidgets.QPushButton(InstallDialog)
+ self.verify_button.setObjectName("verify_button")
+ self.button_layout.addWidget(self.verify_button)
+ self.install_button = QtWidgets.QPushButton(InstallDialog)
+ self.install_button.setObjectName("install_button")
+ self.button_layout.addWidget(self.install_button)
+ self.install_dialog_layout.addLayout(self.button_layout, 9, 0, 1, 3)
+ self.ignore_space_info_label = QtWidgets.QLabel(InstallDialog)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.ignore_space_info_label.setFont(font)
+ self.ignore_space_info_label.setObjectName("ignore_space_info_label")
+ self.install_dialog_layout.addWidget(self.ignore_space_info_label, 4, 2, 1, 1)
+ self.install_dir_label = QtWidgets.QLabel(InstallDialog)
+ self.install_dir_label.setObjectName("install_dir_label")
+ self.install_dialog_layout.addWidget(self.install_dir_label, 1, 0, 1, 1, QtCore.Qt.AlignRight)
+ self.ignore_space_check = QtWidgets.QCheckBox(InstallDialog)
+ self.ignore_space_check.setObjectName("ignore_space_check")
+ self.install_dialog_layout.addWidget(self.ignore_space_check, 4, 1, 1, 1)
+ self.max_workers_info_label = QtWidgets.QLabel(InstallDialog)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.max_workers_info_label.setFont(font)
+ self.max_workers_info_label.setObjectName("max_workers_info_label")
+ self.install_dialog_layout.addWidget(self.max_workers_info_label, 2, 2, 1, 1)
+ self.max_workers_spin = QtWidgets.QSpinBox(InstallDialog)
+ self.max_workers_spin.setObjectName("max_workers_spin")
+ self.install_dialog_layout.addWidget(self.max_workers_spin, 2, 1, 1, 1)
+ self.download_only_info_label = QtWidgets.QLabel(InstallDialog)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.download_only_info_label.setFont(font)
+ self.download_only_info_label.setObjectName("download_only_info_label")
+ self.install_dialog_layout.addWidget(self.download_only_info_label, 5, 2, 1, 1)
+ self.install_size_label = QtWidgets.QLabel(InstallDialog)
+ self.install_size_label.setObjectName("install_size_label")
+ self.install_dialog_layout.addWidget(self.install_size_label, 8, 0, 1, 1, QtCore.Qt.AlignRight)
+ self.install_dir_layout = QtWidgets.QHBoxLayout()
+ self.install_dir_layout.setObjectName("install_dir_layout")
+ self.install_dialog_layout.addLayout(self.install_dir_layout, 1, 1, 1, 2)
+ spacerItem1 = QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.install_dialog_layout.addItem(spacerItem1, 3, 2, 1, 1)
+ self.ignore_space_label = QtWidgets.QLabel(InstallDialog)
+ self.ignore_space_label.setObjectName("ignore_space_label")
+ self.install_dialog_layout.addWidget(self.ignore_space_label, 4, 0, 1, 1, QtCore.Qt.AlignRight)
+ self.download_only_label = QtWidgets.QLabel(InstallDialog)
+ self.download_only_label.setObjectName("download_only_label")
+ self.install_dialog_layout.addWidget(self.download_only_label, 5, 0, 1, 1, QtCore.Qt.AlignRight)
+ self.max_workers_label = QtWidgets.QLabel(InstallDialog)
+ self.max_workers_label.setObjectName("max_workers_label")
+ self.install_dialog_layout.addWidget(self.max_workers_label, 2, 0, 1, 1, QtCore.Qt.AlignRight)
+ self.install_size_info_label = QtWidgets.QLabel(InstallDialog)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.install_size_info_label.setFont(font)
+ self.install_size_info_label.setObjectName("install_size_info_label")
+ self.install_dialog_layout.addWidget(self.install_size_info_label, 8, 1, 1, 2)
+ self.download_size_label = QtWidgets.QLabel(InstallDialog)
+ self.download_size_label.setObjectName("download_size_label")
+ self.install_dialog_layout.addWidget(self.download_size_label, 7, 0, 1, 1, QtCore.Qt.AlignRight)
+ self.download_size_info_label = QtWidgets.QLabel(InstallDialog)
+ font = QtGui.QFont()
+ font.setItalic(True)
+ self.download_size_info_label.setFont(font)
+ self.download_size_info_label.setObjectName("download_size_info_label")
+ self.install_dialog_layout.addWidget(self.download_size_info_label, 7, 1, 1, 2)
+ self.force_download_check = QtWidgets.QCheckBox(InstallDialog)
+ self.force_download_check.setObjectName("force_download_check")
+ self.install_dialog_layout.addWidget(self.force_download_check, 3, 1, 1, 1)
+ self.install_dialog_label = QtWidgets.QLabel(InstallDialog)
+ self.install_dialog_label.setObjectName("install_dialog_label")
+ self.install_dialog_layout.addWidget(self.install_dialog_label, 0, 0, 1, 3)
+ self.download_only_check = QtWidgets.QCheckBox(InstallDialog)
+ self.download_only_check.setText("")
+ self.download_only_check.setObjectName("download_only_check")
+ self.install_dialog_layout.addWidget(self.download_only_check, 5, 1, 1, 1)
+ self.sdl_list_frame = QtWidgets.QFrame(InstallDialog)
+ self.sdl_list_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
+ self.sdl_list_frame.setFrameShadow(QtWidgets.QFrame.Raised)
+ self.sdl_list_frame.setObjectName("sdl_list_frame")
+ self.sdl_list_layout = QtWidgets.QVBoxLayout(self.sdl_list_frame)
+ self.sdl_list_layout.setSpacing(0)
+ self.sdl_list_layout.setObjectName("sdl_list_layout")
+ self.install_dialog_layout.addWidget(self.sdl_list_frame, 6, 1, 1, 2, QtCore.Qt.AlignTop)
+ self.sdl_list_label = QtWidgets.QLabel(InstallDialog)
+ self.sdl_list_label.setObjectName("sdl_list_label")
+ self.install_dialog_layout.addWidget(self.sdl_list_label, 6, 0, 1, 1, QtCore.Qt.AlignRight)
+
+ self.retranslateUi(InstallDialog)
+ QtCore.QMetaObject.connectSlotsByName(InstallDialog)
+
+ def retranslateUi(self, InstallDialog):
+ _translate = QtCore.QCoreApplication.translate
+ self.force_download_label.setText(_translate("InstallDialog", "Force redownload"))
+ self.cancel_button.setText(_translate("InstallDialog", "Cancel"))
+ self.verify_button.setText(_translate("InstallDialog", "Verify"))
+ self.install_button.setText(_translate("InstallDialog", "Install"))
+ self.ignore_space_info_label.setText(_translate("InstallDialog", "Use with caution!"))
+ self.install_dir_label.setText(_translate("InstallDialog", "Install directory"))
+ self.max_workers_info_label.setText(_translate("InstallDialog", "Less is slower. (0: Default)"))
+ self.download_only_info_label.setText(_translate("InstallDialog", "Do not try to install."))
+ self.install_size_label.setText(_translate("InstallDialog", "Total install size"))
+ self.ignore_space_label.setText(_translate("InstallDialog", "Ignore free space"))
+ self.download_only_label.setText(_translate("InstallDialog", "Download only"))
+ self.max_workers_label.setText(_translate("InstallDialog", "Max workers"))
+ self.install_size_info_label.setText(_translate("InstallDialog", "Click verify..."))
+ self.download_size_label.setText(_translate("InstallDialog", "Download size"))
+ self.download_size_info_label.setText(_translate("InstallDialog", "Click verify..."))
+ self.install_dialog_label.setText(_translate("InstallDialog", "error"))
+ self.sdl_list_label.setText(_translate("InstallDialog", "Optional packs"))
+
+
+if __name__ == "__main__":
+ import sys
+ app = QtWidgets.QApplication(sys.argv)
+ InstallDialog = QtWidgets.QDialog()
+ ui = Ui_InstallDialog()
+ ui.setupUi(InstallDialog)
+ InstallDialog.show()
+ sys.exit(app.exec_())
diff --git a/rare/ui/components/dialogs/install_dialog.ui b/rare/ui/components/dialogs/install_dialog.ui
new file mode 100644
index 00000000..d6ee9141
--- /dev/null
+++ b/rare/ui/components/dialogs/install_dialog.ui
@@ -0,0 +1,221 @@
+
+
+ InstallDialog
+
+
+ Rare
+
+
+ -
+
+
+ Force redownload
+
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Cancel
+
+
+
+ -
+
+
+ Verify
+
+
+
+ -
+
+
+ Install
+
+
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Use with caution!
+
+
+
+ -
+
+
+ Install directory
+
+
+
+ -
+
+
+ -
+
+
+
+ true
+
+
+
+ Less is slower. (0: Default)
+
+
+
+ -
+
+
+ -
+
+
+
+ true
+
+
+
+ Do not try to install.
+
+
+
+ -
+
+
+ Total install size
+
+
+
+ -
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Ignore free space
+
+
+
+ -
+
+
+ Download only
+
+
+
+ -
+
+
+ Max workers
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Click verify...
+
+
+
+ -
+
+
+ Download size
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Click verify...
+
+
+
+ -
+
+
+ -
+
+
+ error
+
+
+
+ -
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 0
+
+
+
+
+ -
+
+
+ Optional packs
+
+
+
+
+
+
+
+
diff --git a/rare/ui/components/dialogs/launch_dialog.py b/rare/ui/components/dialogs/launch_dialog.py
index a563f459..bc78839f 100644
--- a/rare/ui/components/dialogs/launch_dialog.py
+++ b/rare/ui/components/dialogs/launch_dialog.py
@@ -8,7 +8,7 @@
# run again. Do not edit this file unless you know what you are doing.
-from PyQt5 import QtCore, QtWidgets
+from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_LaunchDialog(object):
@@ -40,7 +40,7 @@ class Ui_LaunchDialog(object):
def retranslateUi(self, LaunchDialog):
_translate = QtCore.QCoreApplication.translate
- LaunchDialog.setWindowTitle(_translate("LaunchDialog", "Dialog"))
+ LaunchDialog.setWindowTitle(_translate("LaunchDialog", "Launching Rare"))
self.title_label.setText(_translate("LaunchDialog", "Launching Rare
"))
self.image_info.setText(_translate("LaunchDialog", "Downloading images"))
self.steam_info.setText(_translate("LaunchDialog", "Getting Steam grades"))
@@ -48,7 +48,6 @@ class Ui_LaunchDialog(object):
if __name__ == "__main__":
import sys
-
app = QtWidgets.QApplication(sys.argv)
LaunchDialog = QtWidgets.QDialog()
ui = Ui_LaunchDialog()
diff --git a/rare/ui/components/dialogs/launch_dialog.ui b/rare/ui/components/dialogs/launch_dialog.ui
index a5b0a134..e82ac7af 100644
--- a/rare/ui/components/dialogs/launch_dialog.ui
+++ b/rare/ui/components/dialogs/launch_dialog.ui
@@ -1,56 +1,56 @@
- LaunchDialog
-
-
-
- 0
- 0
- 400
- 168
-
-
-
- Dialog
-
-
- -
-
-
- <h2>Launching Rare</h2>
-
-
-
- -
-
-
- 0
-
-
-
- -
-
-
- Downloading images
-
-
-
- -
-
-
- 0
-
-
-
- -
-
-
- Getting Steam grades
-
-
-
-
+ LaunchDialog
+
+
+
+ 0
+ 0
+ 400
+ 168
+
+
+
+ Launching Rare
+
+
+ -
+
+
+ <h2>Launching Rare</h2>
+
-
-
+
+ -
+
+
+ 0
+
+
+
+ -
+
+
+ Downloading images
+
+
+
+ -
+
+
+ 0
+
+
+
+ -
+
+
+ Getting Steam grades
+
+
+
+
+
+
+
diff --git a/rare/ui/components/tabs/games/game_info/game_info.py b/rare/ui/components/tabs/games/game_info/game_info.py
index 11f5b1d9..d320f7a9 100644
--- a/rare/ui/components/tabs/games/game_info/game_info.py
+++ b/rare/ui/components/tabs/games/game_info/game_info.py
@@ -22,7 +22,7 @@ class Ui_GameInfo(object):
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.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)
@@ -39,7 +39,7 @@ class Ui_GameInfo(object):
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.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)
@@ -70,43 +70,6 @@ class Ui_GameInfo(object):
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)
@@ -133,18 +96,18 @@ class Ui_GameInfo(object):
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.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.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.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)
@@ -168,23 +131,74 @@ class Ui_GameInfo(object):
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.setTextInteractionFlags(QtCore.Qt.LinksAccessibleByMouse|QtCore.Qt.TextSelectableByMouse)
self.grade.setObjectName("grade")
self.layout_game_info_form.addWidget(self.grade, 3, 1, 1, 1)
+ self.game_actions_stack = QtWidgets.QStackedWidget(GameInfo)
+ self.game_actions_stack.setMinimumSize(QtCore.QSize(250, 0))
+ self.game_actions_stack.setObjectName("game_actions_stack")
+ self.installed_page = QtWidgets.QWidget()
+ self.installed_page.setObjectName("installed_page")
+ self.installed_layout = QtWidgets.QVBoxLayout(self.installed_page)
+ self.installed_layout.setContentsMargins(0, 0, 0, 0)
+ self.installed_layout.setObjectName("installed_layout")
+ self.verify_widget = QtWidgets.QStackedWidget(self.installed_page)
+ 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.installed_layout.addWidget(self.verify_widget)
+ self.repair_button = QtWidgets.QPushButton(self.installed_page)
+ self.repair_button.setObjectName("repair_button")
+ self.installed_layout.addWidget(self.repair_button)
+ self.uninstall_button = QtWidgets.QPushButton(self.installed_page)
+ self.uninstall_button.setStyleSheet("background-color: #900")
+ self.uninstall_button.setObjectName("uninstall_button")
+ self.installed_layout.addWidget(self.uninstall_button)
+ self.game_actions_stack.addWidget(self.installed_page)
+ self.uninstalled_page = QtWidgets.QWidget()
+ self.uninstalled_page.setObjectName("uninstalled_page")
+ self.uninstalled_layout = QtWidgets.QVBoxLayout(self.uninstalled_page)
+ self.uninstalled_layout.setObjectName("uninstalled_layout")
+ self.install_button = QtWidgets.QPushButton(self.uninstalled_page)
+ self.install_button.setStyleSheet("background-color: #090")
+ self.install_button.setObjectName("install_button")
+ self.uninstalled_layout.addWidget(self.install_button)
+ self.game_actions_stack.addWidget(self.uninstalled_page)
+ self.layout_game_info_form.addWidget(self.game_actions_stack, 6, 1, 1, 1, QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
self.layout_game_info.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.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.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.game_actions_stack.setCurrentIndex(0)
self.verify_widget.setCurrentIndex(0)
QtCore.QMetaObject.connectSlotsByName(GameInfo)
@@ -194,18 +208,18 @@ class Ui_GameInfo(object):
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"))
+ self.verify_button.setText(_translate("GameInfo", "Verify Installation"))
+ self.repair_button.setText(_translate("GameInfo", "Repair Instalation"))
+ self.uninstall_button.setText(_translate("GameInfo", "Uninstall Game"))
+ self.install_button.setText(_translate("GameInfo", "Install Game"))
if __name__ == "__main__":
import sys
-
app = QtWidgets.QApplication(sys.argv)
GameInfo = QtWidgets.QWidget()
ui = Ui_GameInfo()
diff --git a/rare/ui/components/tabs/games/game_info/game_info.ui b/rare/ui/components/tabs/games/game_info/game_info.ui
index 1d1926b6..edec48ef 100644
--- a/rare/ui/components/tabs/games/game_info/game_info.ui
+++ b/rare/ui/components/tabs/games/game_info/game_info.ui
@@ -1,376 +1,390 @@
- GameInfo
-
-
-
- 0
- 0
- 436
- 317
-
-
-
- Game Info
-
-
- -
-
-
- 6
-
-
- 6
-
-
- 6
-
-
- 6
-
-
- 12
-
-
-
-
-
- error
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
-
-
- Developer
-
-
-
- -
-
-
- error
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
-
-
- Installation Path
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
-
-
- Installation Size
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 0
- 20
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 0
-
-
-
-
- -
-
-
-
- 250
- 0
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Uninstall Game
-
-
-
- -
-
-
- 0
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- Verify Installation
-
-
-
-
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
- 24
-
-
-
-
-
-
-
- -
-
-
- Repair Instalation
-
-
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
-
-
- Version
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
-
-
- Application Name
-
-
-
- -
-
-
- error
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
-
-
- error
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
-
-
- error
-
-
- true
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 75
- true
-
-
-
- Actions
-
-
-
- -
-
-
-
- 75
- true
-
-
-
- ProtonDB Grade
-
-
-
- -
-
-
- error
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
-
-
- -
-
-
- QFrame::StyledPanel
-
-
- QFrame::Sunken
-
-
-
-
-
-
- -
-
-
- error
-
-
- Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
-
-
-
+ GameInfo
+
+
+ Game Info
+
+
+ -
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 6
+
+
+ 12
+
+
-
+
+
+ error
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ Developer
+
+
+
+ -
+
+
+ error
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ Installation Path
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ Installation Size
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 0
+ 20
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ Version
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ Application Name
+
+
+
+ -
+
+
+ error
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+ error
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+ error
+
+
+ true
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 75
+ true
+
+
+
+ Actions
+
+
+
+ -
+
+
+
+ 75
+ true
+
+
+
+ ProtonDB Grade
+
+
+
+ -
+
+
+ error
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 250
+ 0
+
+
+
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ 0
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
-
+
+
+ Verify Installation
+
+
+
+
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ 24
+
+
+
+
+
+
+
+ -
+
+
+ Repair Instalation
+
+
+
+ -
+
+
+ background-color: #900
+
+
+ Uninstall Game
+
+
+
+
+
+
+ -
+
+
+ background-color: #090
+
+
+ Install Game
+
+
+
+
+
+
+
+
+
+ -
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Sunken
+
+
+
+
-
-
+
+ -
+
+
+ error
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+
+
+
+
diff --git a/rare/ui/components/tabs/settings/rare.py b/rare/ui/components/tabs/settings/rare.py
index b7f6b1ff..6e948018 100644
--- a/rare/ui/components/tabs/settings/rare.py
+++ b/rare/ui/components/tabs/settings/rare.py
@@ -16,56 +16,26 @@ class Ui_RareSettings(object):
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.rpc_layout = QtWidgets.QVBoxLayout()
+ self.rpc_layout.setObjectName("rpc_layout")
+ self.rare_layout.addLayout(self.rpc_layout, 1, 1, 1, 1)
+ self.groupBox = QtWidgets.QGroupBox(RareSettings)
+ self.groupBox.setObjectName("groupBox")
+ self.verticalLayout = QtWidgets.QVBoxLayout(self.groupBox)
+ self.verticalLayout.setObjectName("verticalLayout")
+ self.desktop_link = QtWidgets.QPushButton(self.groupBox)
+ self.desktop_link.setObjectName("desktop_link")
+ self.verticalLayout.addWidget(self.desktop_link)
+ self.startmenu_link = QtWidgets.QPushButton(self.groupBox)
+ self.startmenu_link.setObjectName("startmenu_link")
+ self.verticalLayout.addWidget(self.startmenu_link)
+ self.rare_layout.addWidget(self.groupBox, 2, 1, 1, 1, QtCore.Qt.AlignTop)
self.settings_group = QtWidgets.QGroupBox(RareSettings)
self.settings_group.setObjectName("settings_group")
self.behavior_layout = QtWidgets.QGridLayout(self.settings_group)
self.behavior_layout.setObjectName("behavior_layout")
- spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
- self.behavior_layout.addItem(spacerItem1, 2, 1, 2, 1)
+ spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.behavior_layout.addItem(spacerItem, 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)
@@ -101,11 +71,52 @@ class Ui_RareSettings(object):
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)
+ 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.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)
+ spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
+ self.interface_layout.addItem(spacerItem1, 1, 2, 1, 1)
+ 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.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.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)
spacerItem2 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
- self.rare_layout.addItem(spacerItem2, 2, 1, 1, 1)
+ self.rare_layout.addItem(spacerItem2, 3, 0, 1, 2)
self.retranslateUi(RareSettings)
QtCore.QMetaObject.connectSlotsByName(RareSettings)
@@ -113,14 +124,9 @@ class Ui_RareSettings(object):
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.groupBox.setTitle(_translate("RareSettings", "Shortcuts"))
+ self.desktop_link.setText(_translate("RareSettings", "Create Desktop link"))
+ self.startmenu_link.setText(_translate("RareSettings", "Create start menu link"))
self.settings_group.setTitle(_translate("RareSettings", "Behavior"))
self.save_size.setText(_translate("RareSettings", "Restore window size on application startup"))
self.notification.setText(_translate("RareSettings", "Show notification on download completion"))
@@ -131,11 +137,18 @@ class Ui_RareSettings(object):
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"))
+ self.interface_group.setTitle(_translate("RareSettings", "Interface"))
+ self.color_select.setItemText(0, _translate("RareSettings", "None"))
+ self.style_label.setText(_translate("RareSettings", "Style Sheet"))
+ self.style_select.setItemText(0, _translate("RareSettings", "None"))
+ self.interface_info.setText(_translate("RareSettings", "Restart Rare to apply."))
+ self.lang_label.setText(_translate("RareSettings", "Language"))
+ self.color_label.setText(_translate("RareSettings", "Color Scheme"))
+ self.img_dir_group.setTitle(_translate("RareSettings", "Image Cache Directory"))
if __name__ == "__main__":
import sys
-
app = QtWidgets.QApplication(sys.argv)
RareSettings = QtWidgets.QWidget()
ui = Ui_RareSettings()
diff --git a/rare/ui/components/tabs/settings/rare.ui b/rare/ui/components/tabs/settings/rare.ui
index 0b0c6193..377f874c 100644
--- a/rare/ui/components/tabs/settings/rare.ui
+++ b/rare/ui/components/tabs/settings/rare.ui
@@ -1,219 +1,242 @@
- RareSettings
-
-
- RareSettings
+ RareSettings
+
+
+ RareSettings
+
+
+ -
+
+
+ -
+
+
+ Shortcuts
+
+
+
-
+
+
+ Create Desktop link
-
-
-
-
-
-
- 0
- 0
-
-
-
- Interface
-
-
-
-
-
-
-
-
- None
-
-
-
-
- -
-
-
- Style Sheet
-
-
-
- -
-
-
- Language
-
-
-
- -
-
-
- -
-
-
- Color Scheme
-
-
-
- -
-
-
-
- true
-
-
-
- Restart Rare to apply.
-
-
- true
-
-
-
- -
-
-
-
-
- None
-
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
-
- -
-
-
- Image Cache Directory
-
-
-
-
- -
-
-
- Behavior
-
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- Restore window size on application startup
-
-
-
- -
-
-
- Show notification on download completion
-
-
-
- -
-
-
- Automatically sync with cloud
-
-
-
- -
-
-
- Confirm game launch
-
-
-
- -
-
-
- Update games on application startup
-
-
-
- -
-
-
- Exit to System tray
-
-
-
-
-
-
- -
-
-
- Logs
-
-
-
-
-
-
- Open Log directory
-
-
-
- -
-
-
- Clean Log directory
-
-
-
- -
-
-
-
-
-
- true
-
-
-
-
-
-
- -
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
-
+
+
+ -
+
+
+ Create start menu link
+
+
+
+
-
-
+
+ -
+
+
+ Behavior
+
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Restore window size on application startup
+
+
+
+ -
+
+
+ Show notification on download completion
+
+
+
+ -
+
+
+ Automatically sync with cloud
+
+
+
+ -
+
+
+ Confirm game launch
+
+
+
+ -
+
+
+ Update games on application startup
+
+
+
+ -
+
+
+ Exit to System tray
+
+
+
+
+
+
+ -
+
+
+ Logs
+
+
+
-
+
+
+ Open Log directory
+
+
+
+ -
+
+
+ Clean Log directory
+
+
+
+ -
+
+
+
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Interface
+
+
+
-
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Style Sheet
+
+
+
+ -
+
+
-
+
+ None
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ true
+
+
+
+ Restart Rare to apply.
+
+
+ true
+
+
+
+ -
+
+
+ Language
+
+
+
+ -
+
+
+ -
+
+
+ Color Scheme
+
+
+
+
+
+
+ -
+
+
+ Image Cache Directory
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
diff --git a/rare/utils/extra_widgets.py b/rare/utils/extra_widgets.py
index 31db79cf..121ab59d 100644
--- a/rare/utils/extra_widgets.py
+++ b/rare/utils/extra_widgets.py
@@ -152,6 +152,9 @@ class PathEdit(QWidget, Ui_PathEdit):
def text(self):
return self.text_edit.text()
+ def setText(self, text: str):
+ self.text_edit.setText(text)
+
def save(self):
self.save_func()
self.save_path_button.setDisabled(True)
diff --git a/rare/utils/models.py b/rare/utils/models.py
index 503d0532..44400ddc 100644
--- a/rare/utils/models.py
+++ b/rare/utils/models.py
@@ -1,15 +1,36 @@
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,
+class InstallOptionsModel:
+ def __init__(self, app_name: str, base_path: str = os.path.expanduser("~/legendary"),
+ max_workers: int = os.cpu_count() * 2, repair: bool = False, no_install: bool = False,
+ ignore_space_req: bool = False, force: bool = False, sdl_list: list = ['']
):
self.app_name = app_name
- self.path = path
+ self.base_path = base_path
self.max_workers = max_workers
self.repair = repair
- self.download_only = download_only
- self.ignore_free_space = ignore_free_space
+ self.no_install = no_install
+ self.ignore_space_req = ignore_space_req
self.force = force
+ self.sdl_list = sdl_list
+
+
+class InstallDownloadModel:
+ def __init__(self, dlmanager, analysis, game, igame, repair: bool, repair_file: str):
+ self.dlmanager = dlmanager
+ self.analysis = analysis
+ self.game = game
+ self.igame = igame
+ self.repair = repair
+ self.repair_file = repair_file
+
+
+class InstallQueueItemModel:
+ def __init__(self, status_q=None, download: InstallDownloadModel = None, options: InstallOptionsModel = None):
+ self.status_q = status_q
+ self.download = download
+ self.options = options
+
+ def __bool__(self):
+ return (self.status_q is not None) and (self.download is not None) and (self.options is not None)
diff --git a/rare/utils/utils.py b/rare/utils/utils.py
index c09c4f1a..f295a28b 100644
--- a/rare/utils/utils.py
+++ b/rare/utils/utils.py
@@ -157,7 +157,7 @@ color_group_map = {
def load_color_scheme(path: str):
- custom_palette = QPalette()
+ palette = QPalette()
settings = QSettings(path, QSettings.IniFormat)
try:
settings.beginGroup("ColorScheme")
@@ -166,17 +166,16 @@ def load_color_scheme(path: str):
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])))
+ color = settings.value(color_role_map[r], None)
+ if color is not None:
+ palette.setColor(group, role, QColor(color))
+ else:
+ palette.setColor(group, role, palette.color(QPalette.Active, role))
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
+ palette = None
+ return palette
def get_color_schemes():
@@ -219,8 +218,58 @@ def get_size(b: int) -> str:
b /= 1024
+def create_rare_desktop_link(type_of_link):
+ # Linux
+ if os.name == "posix":
+ if type_of_link == "desktop":
+ path = os.path.expanduser(f"~/Desktop/")
+ elif type_of_link == "start_menu":
+ path = os.path.expanduser("~/.local/share/applications/")
+ else:
+ return
+
+ with open(f"{path}Rare.desktop", "w") as desktop_file:
+ desktop_file.write("[Desktop Entry]\n"
+ f"Name=Rare\n"
+ f"Type=Application\n"
+ f"Icon={os.path.join(style_path, 'Logo.png')}\n"
+ f"Exec={os.path.abspath(sys.argv[0])}\n"
+ "Terminal=false\n"
+ "StartupWMClass=rare\n"
+ )
+ desktop_file.close()
+ os.chmod(os.path.expanduser(f"{path}Rare.desktop"), 0o755)
+
+ elif os.name == "nt":
+ # Target of shortcut
+ if type_of_link == "desktop":
+ target_folder = os.path.expanduser('~/Desktop/')
+ elif type_of_link == "start_menu":
+ target_folder = os.path.expandvars("%appdata%/Microsoft/Windows/Start Menu")
+ else:
+ logger.warning("No valid type of link")
+ return
+ linkName = "Rare.lnk"
+
+ # Path to location of link file
+ pathLink = os.path.join(target_folder, linkName)
+
+ # Add shortcut
+ shell = Dispatch('WScript.Shell')
+ shortcut = shell.CreateShortCut(pathLink)
+ shortcut.Targetpath = os.path.abspath(sys.argv[0])
+ shortcut.Arguments = ""
+ shortcut.WorkingDirectory = os.getcwd()
+
+ # Icon
+ shortcut.IconLocation = os.path.join(style_path, "Logo.ico")
+
+ shortcut.save()
+
+
def create_desktop_link(app_name, core: LegendaryCore, type_of_link="desktop"):
igame = core.get_installed_game(app_name)
+
if os.path.exists(
os.path.join(QSettings('Rare', 'Rare').value('img_dir', os.path.expanduser('~/.cache/rare/images'), str),
igame.app_name, 'Thumbnail.png')):