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

Windows (No wine)

Refactoring
This commit is contained in:
Dummerle 2020-12-26 21:09:01 +01:00
parent f9037ff873
commit 493bcba526
16 changed files with 427 additions and 519 deletions

View file

@ -14,12 +14,9 @@ Rare is currently considered beta software and in no way feature-complete. You *
### Implemented
- Launch, install and uninstall games
- Authentication(Import from existing installation and via Browser)**(Please test it!)**
- In-app Browser to buy games
### Todos
- Sync saves
- Settings
- Search Games
- In-app Browser to buy games
- ...
If you have features you want to have in this app, create an issue on github or build it yourself. Please report bugs(Especially Windows)

View file

@ -1,4 +1,7 @@
import json
import os
import re
import webbrowser
from getpass import getuser
from json import loads
from logging import getLogger
@ -7,6 +10,7 @@ from PyQt5.QtCore import QUrl, pyqtSignal
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEnginePage
from PyQt5.QtWidgets import QDialog, QWidget, QVBoxLayout, QLabel, QPushButton, QStackedLayout, QLineEdit, QButtonGroup, \
QRadioButton
from legendary.core import LegendaryCore
logger = getLogger("LoginWindow")
@ -110,7 +114,53 @@ class ImportWidget(QWidget):
self.login_text.setText("Error: No valid session found")
class SystemBrowserWidget(QWidget):
signal = pyqtSignal(bool)
def __init__(self, core: LegendaryCore):
super(SystemBrowserWidget, self).__init__()
self.core = core
self.layout = QVBoxLayout()
self.text = QLabel("Insert Sid from Browser")
self.layout.addWidget(self.text)
self.input = QLineEdit()
self.input.setPlaceholderText("Insert sid from Browser")
self.layout.addWidget(self.input)
self.loading_text = QLabel("")
self.layout.addWidget(self.loading_text)
self.back_button = QPushButton("Back")
self.back_button.clicked.connect(self.back)
self.layout.addWidget(self.back_button)
self.submit_button = QPushButton("Login")
self.submit_button.clicked.connect(self.login)
self.layout.addWidget(self.submit_button)
self.setLayout(self.layout)
def login(self):
self.loading_text.setText("Loading")
token = self.input.text()
if token.startswith("{") and token.endswith("}"):
token = json.loads(token)['sid']
token = self.core.auth_sid(token)
if self.core.auth_code(token):
logger.info("Successfully logged in")
self.signal.emit(True)
else:
logger.warning("Login failed")
self.loading_text.setText("Login failed")
def back(self):
self.signal.emit(False)
class LoginWindow(QDialog):
signal = pyqtSignal(bool)
def __init__(self, core: LegendaryCore):
super(LoginWindow, self).__init__()
self.core = core
@ -120,8 +170,10 @@ class LoginWindow(QDialog):
self.welcome_layout = QVBoxLayout()
self.title = QLabel(
"<h2>Welcome to Rare the graphical interface for Legendary, an open source Epic Games alternative.</h2>\n<h3>Select one Option to Login</h3>")
self.browser_btn = QPushButton("Use browser to login")
self.browser_btn = QPushButton("Use built in browser to login")
self.browser_btn.clicked.connect(self.browser_login)
self.browser_btn_normal = QPushButton("Use System browser")
self.browser_btn_normal.clicked.connect(self.sys_browser_login)
self.import_btn = QPushButton("Import from existing Epic Games installation")
self.import_btn.clicked.connect(self.import_login)
@ -131,6 +183,7 @@ class LoginWindow(QDialog):
self.welcome_layout.addWidget(self.title)
self.welcome_layout.addWidget(self.browser_btn)
self.welcome_layout.addWidget(self.browser_btn_normal)
self.welcome_layout.addWidget(self.import_btn)
self.welcome_layout.addWidget(self.text)
self.welcome_layout.addWidget(self.exit_btn)
@ -140,20 +193,25 @@ class LoginWindow(QDialog):
self.browser.loadFinished.connect(self.check_for_sid_page)
self.import_widget = ImportWidget(self.core)
self.import_widget.signal.connect(self.import_resp)
self.import_widget.signal.connect(self.login_signal)
self.sys_browser_widget = SystemBrowserWidget(core)
self.sys_browser_widget.signal.connect(self.login_signal)
self.layout = QStackedLayout()
self.layout.addWidget(self.widget)
self.layout.addWidget(self.browser)
self.layout.addWidget(self.import_widget)
self.layout.addWidget(self.sys_browser_widget)
self.setLayout(self.layout)
self.show()
def import_resp(self, b: bool):
def login_signal(self, b: bool):
if b:
self.success()
else:
self.layout.setCurrentIndex(0)
self.text.setText("<h4 style='color: red'>No valid session found</h4>")
self.text.setText("<h4 style='color: red'>Login failed</h4>")
def login(self):
self.exec_()
@ -176,6 +234,11 @@ class LoginWindow(QDialog):
'https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect'))
self.layout.setCurrentIndex(1)
def sys_browser_login(self):
self.layout.setCurrentIndex(3)
webbrowser.open(
"https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect")
def import_login(self):
self.layout.setCurrentIndex(2)

View file

@ -2,6 +2,10 @@ import logging
import sys
from PyQt5.QtWidgets import QApplication
from Rare.Styles import dark
from Rare.utils import RareConfig
from legendary.core import LegendaryCore
from Rare.Launch import LaunchDialog
@ -18,7 +22,8 @@ core = LegendaryCore()
def main():
app = QApplication(sys.argv)
if RareConfig.THEME == "dark":
app.setStyleSheet(dark)
logger.info("Try if you are logged in")
try:
if core.login():
@ -34,6 +39,8 @@ def main():
if not login_window.login():
return
launch_dialog = LaunchDialog(core)
if RareConfig.THEME == "dark":
launch_dialog.setStyleSheet(dark)
launch_dialog.exec_()
mainwindow = MainWindow(core)
app.exec_()

View file

@ -1,6 +1,7 @@
from PyQt5.QtWidgets import QMainWindow, QTabWidget, QWidget
from Rare.TabWidgets import GameListInstalled, GameListUninstalled, UpdateList, BrowserTab, Settings
from Rare.TabWidgets import GameListInstalled, GameListUninstalled, BrowserTab
from Rare.Tabs import SettingsTab, UpdateTab
class MainWindow(QMainWindow):
@ -24,11 +25,11 @@ class TabWidget(QTabWidget):
self.uninstalled_games = GameListUninstalled(self, core)
self.addTab(self.uninstalled_games, "Install Games")
self.update_tab = UpdateList(self, core)
self.update_tab = UpdateTab(self, core)
self.addTab(self.update_tab, "Updates")
self.browser = BrowserTab(self)
self.addTab(self.browser, "Store")
self.settings = Settings(self)
self.settings = SettingsTab(self, core)
self.addTab(self.settings, "Settings")

View file

@ -1,260 +0,0 @@
obit = """
/*Copyright (c) DevSec Studio. All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*-----QWidget-----*/
QWidget
{
background-color: #232430;
color: #000000;
border-color: #000000;
}
/*-----QLabel-----*/
QLabel
{
background-color: #232430;
color: #c1c1c1;
border-color: #000000;
}
/*-----QPushButton-----*/
QPushButton
{
background-color: #ff9c2b;
color: #000000;
font-weight: bold;
border-style: solid;
border-color: #000000;
padding: 6px;
}
QPushButton::hover
{
background-color: #ffaf5d;
}
QPushButton::pressed
{
background-color: #dd872f;
}
/*-----QToolButton-----*/
QToolButton
{
background-color: #ff9c2b;
color: #000000;
font-weight: bold;
border-style: solid;
border-color: #000000;
padding: 6px;
}
QToolButton::hover
{
background-color: #ffaf5d;
}
QToolButton::pressed
{
background-color: #dd872f;
}
/*-----QLineEdit-----*/
QLineEdit
{
background-color: #38394e;
color: #c1c1c1;
border-style: solid;
border-width: 1px;
border-color: #4a4c68;
}
/*-----QTableView-----*/
QTableView,
QHeaderView,
QTableView::item
{
background-color: #232430;
color: #c1c1c1;
border: none;
}
QTableView::item:selected
{
background-color: #41424e;
color: #c1c1c1;
}
QHeaderView::section:horizontal
{
background-color: #232430;
border: 1px solid #37384d;
padding: 5px;
}
QTableView::indicator{
background-color: #1d1d28;
border: 1px solid #37384d;
}
QTableView::indicator:checked{
image:url("./ressources/check.png"); /*To replace*/
background-color: #1d1d28;
}
/*-----QTabWidget-----*/
QTabWidget::pane
{
border: none;
}
QTabWidget::tab-bar
{
left: 5px;
}
QTabBar::tab
{
color: #c1c1c1;
min-width: 1px;
padding-left: 25px;
margin-left:-22px;
height: 28px;
border: none;
}
QTabBar::tab:selected
{
color: #c1c1c1;
font-weight: bold;
height: 28px;
}
QTabBar::tab:!first
{
margin-left: -20px;
}
QTabBar::tab:hover
{
color: #DDD;
}
/*-----QScrollBar-----*/
QScrollBar:horizontal
{
background-color: transparent;
height: 8px;
margin: 0px;
padding: 0px;
}
QScrollBar::handle:horizontal
{
border: none;
min-width: 100px;
background-color: #56576c;
}
QScrollBar::add-line:horizontal,
QScrollBar::sub-line:horizontal,
QScrollBar::add-page:horizontal,
QScrollBar::sub-page:horizontal
{
width: 0px;
background-color: transparent;
}
QScrollBar:vertical
{
background-color: transparent;
width: 8px;
margin: 0;
}
QScrollBar::handle:vertical
{
border: none;
min-height: 100px;
background-color: #56576c;
}
QScrollBar::add-line:vertical,
QScrollBar::sub-line:vertical,
QScrollBar::add-page:vertical,
QScrollBar::sub-page:vertical
{
height: 0px;
background-color: transparent;
}
"""

View file

@ -1,2 +1 @@
from Rare.Styles.dark import dark
from Rare.Styles.Obit import obit

View file

@ -1,17 +1,11 @@
import os
import shutil
from logging import getLogger
from PyQt5.QtCore import QUrl, Qt, QProcess
from PyQt5.QtCore import QUrl, Qt
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineProfile, QWebEnginePage
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QScrollArea, QLineEdit, QPushButton, QFormLayout, QGroupBox, \
QComboBox, QHBoxLayout, QTableWidget, QTableWidgetItem
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QScrollArea, QLineEdit
from legendary.core import LegendaryCore
from Rare.GameWidget import GameWidget, UninstalledGameWidget
from Rare.Styles import dark, obit
from Rare.utils import legendaryConfig, RareConfig
from Rare.utils.legendaryUtils import logout, get_updates, get_name, update
logger = getLogger("TabWidgets")
@ -29,163 +23,6 @@ class BrowserTab(QWebEngineView):
return self
class Settings(QScrollArea):
def __init__(self, parent):
super(Settings, self).__init__(parent=parent)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
# Settings
self.layout = QVBoxLayout()
self.layout.addWidget(QLabel("<h1>Rare Settings</h1>"))
self.logged_in_as = QLabel(f"Logged in as {get_name()}")
self.get_legendary_config()
self.gen_form_legendary()
self.gen_form_rare()
if RareConfig.THEME == "dark":
self.parent().parent().setStyleSheet(dark)
self.style_combo_box.setCurrentIndex(1)
if RareConfig.THEME == "obit":
self.parent().parent().setStyleSheet(obit)
self.style_combo_box.setCurrentIndex(2)
self.image_dir_edit.setText(RareConfig.IMAGE_DIR)
self.logout_button = QPushButton("Logout")
self.logout_button.clicked.connect(self.logout)
self.layout.addWidget(self.logged_in_as)
self.layout.addWidget(self.rare_form_group_box)
self.update_rare_button = QPushButton("Update Rare Settings")
self.update_rare_button.clicked.connect(self.update_rare_settings)
self.layout.addWidget(self.update_rare_button)
self.layout.addWidget(self.form_group_box)
self.update_legendary_button = QPushButton("Update Legendary Settings")
self.update_legendary_button.clicked.connect(self.update_legendary_settings)
self.layout.addWidget(self.update_legendary_button)
self.layout.addStretch(1)
self.layout.addWidget(self.logout_button)
self.info_label = QLabel("<h2>Credits</h2>")
self.infotext = QLabel("Developers : Dummerle, CommandMC\nLegendary Dev: Derrod\nLicence: GPL v.3")
self.layout.addWidget(self.info_label)
self.layout.addWidget(self.infotext)
self.setLayout(self.layout)
def update_rare_settings(self):
logger.info("Update Rare settings")
config = {"Rare": {}}
if self.style_combo_box.currentIndex() == 1:
self.parent().parent().parent().setStyleSheet(dark)
config["Rare"]["theme"] = "dark"
elif self.style_combo_box.currentIndex() == 2:
self.parent().parent().parent().setStyleSheet(obit)
config["Rare"]["theme"] = "obit"
else:
self.parent().parent().parent().setStyleSheet("")
config["Rare"]["theme"] = "light"
config["Rare"]["IMAGE_DIR"] = self.image_dir_edit.text()
if self.image_dir_edit.text() != RareConfig.IMAGE_DIR:
shutil.rmtree(RareConfig.IMAGE_DIR)
restart = True
else:
restart = False
RareConfig.set_config(config)
if restart:
logger.info("Restart App to download Images")
# TODO Restart automatically
def update_legendary_settings(self):
print("Legendary update")
self.config["Legendary"]["wine_executable"] = self.lgd_conf_wine_exec.text()
self.config["Legendary"]["wine_prefix"] = self.lgd_conf_wine_prefix.text()
self.config["Legendary"]["locale"] = self.lgd_conf_locale.text()
# self.config["default.env"] = self.lgd_conf_env_vars.toPlainText()
self.config["default.env"] = {}
for row in range(self.table.rowCount()):
self.config["default.env"][self.table.item(row, 0).text()] = self.table.item(row, 1).text()
print(self.config["default.env"])
legendaryConfig.set_config(self.config)
def logout(self):
logout()
exit(0)
def gen_form_legendary(self):
# Default Config
if not self.config.get("Legendary"):
self.config["Legendary"] = {}
if not self.config["Legendary"].get("wine_executable"):
self.config["Legendary"]["wine_executable"] = "wine"
if not self.config["Legendary"].get("wine_prefix"):
self.config["Legendary"]["wine_prefix"] = f"{os.path.expanduser('~')}/.wine"
if not self.config["Legendary"].get("locale"):
self.config["Legendary"]["locale"] = "en-US"
env_vars = self.config.get("default.env")
if env_vars:
self.table = QTableWidget(len(env_vars), 2)
for i, label in enumerate(env_vars):
self.table.setItem(i, 0, QTableWidgetItem(label))
self.table.setItem(i, 1, QTableWidgetItem(env_vars[label]))
else:
self.table = QTableWidget(0, 2)
self.table.setHorizontalHeaderLabels(["Variable", "Value"])
self.form_group_box = QGroupBox("Legendary Defaults")
self.form = QFormLayout()
self.lgd_conf_wine_prefix = QLineEdit(self.config["Legendary"]["wine_prefix"])
self.lgd_conf_wine_exec = QLineEdit(self.config["Legendary"]["wine_executable"])
self.lgd_conf_locale = QLineEdit(self.config["Legendary"]["locale"])
self.add_button = QPushButton("Add Environment Variable")
self.delete_env_var = QPushButton("Delete selected Variable")
self.delete_env_var.clicked.connect(self.delete_var)
self.add_button.clicked.connect(self.add_variable)
self.form.addRow(QLabel("Default Wineprefix"), self.lgd_conf_wine_prefix)
self.form.addRow(QLabel("Wine executable"), self.lgd_conf_wine_exec)
self.form.addRow(QLabel("Environment Variables"), self.table)
self.form.addRow(QLabel("Add Variable"), self.add_button)
self.form.addRow(QLabel("Delete Variable"), self.delete_env_var)
self.form.addRow(QLabel("Locale"), self.lgd_conf_locale)
self.form_group_box.setLayout(self.form)
def add_variable(self):
print("add row")
self.table.insertRow(self.table.rowCount())
self.table.setItem(self.table.rowCount(), 0, QTableWidgetItem(""))
self.table.setItem(self.table.rowCount(), 1, QTableWidgetItem(""))
def delete_var(self):
self.table.removeRow(self.table.currentRow())
def gen_form_rare(self):
self.rare_form_group_box = QGroupBox("Rare Settings")
self.rare_form = QFormLayout()
self.style_combo_box = QComboBox()
self.style_combo_box.addItems(["Light", "Dark", "Obit"])
self.rare_form.addRow(QLabel("Style"), self.style_combo_box)
self.image_dir_edit = QLineEdit()
self.image_dir_edit.setPlaceholderText("Image directory")
self.rare_form.addRow(QLabel("Image Directory"),self.image_dir_edit)
self.rare_form_group_box.setLayout(self.rare_form)
def get_legendary_config(self):
self.config = legendaryConfig.get_config()
class GameListInstalled(QScrollArea):
def __init__(self, parent, core: LegendaryCore):
super(GameListInstalled, self).__init__(parent=parent)
@ -250,76 +87,3 @@ class GameListUninstalled(QScrollArea):
i.setVisible(True)
else:
i.setVisible(False)
class UpdateList(QWidget):
class UpdateWidget(QWidget):
def __init__(self, game):
super().__init__()
self.updating = False
self.game = game
self.layout = QHBoxLayout()
self.label = QLabel("Update available for " + self.game.title)
self.button = QPushButton("Update")
self.button.clicked.connect(self.update_game)
self.layout.addWidget(self.label)
self.layout.addWidget(self.button)
self.setLayout(self.layout)
def update_game(self):
if not self.updating:
logger.info("Update " + self.game.title)
self.proc = update(self.game.app_name)
self.proc = QProcess()
self.proc.setProcessChannelMode(QProcess.MergedChannels)
self.proc.start("legendary", ["-y", "update", self.game.app_name])
self.proc.started.connect(self.start)
self.proc.finished.connect(self.finished)
self.proc.readyRead.connect(self.dataReady)
else:
logger.info("Terminate process")
self.proc.kill()
self.button.setText("Update")
self.updating = False
def start(self):
self.button.setText("Cancel")
self.updating = True
def finished(self, code):
if code == 0:
logger.info("Update finished")
self.setVisible(False)
else:
logger.info("Update finished with exit code " + str(code))
def dataReady(self):
bytes = self.process.readAllStandardOutput()
byte_list = bytes.split('\n')
data = []
for i in byte_list:
data.append(byte_list)
# TODO Daten verarbeiten
print(data)
def __init__(self, parent, core: LegendaryCore):
super(UpdateList, self).__init__(parent=parent)
self.core = core
self.layout = QVBoxLayout()
update_games = []
for game in core.get_installed_list():
update_games.append(game) if core.get_game(game.app_name).app_version != game.version else None
if update_games:
for game in get_updates():
self.layout.addWidget(self.UpdateWidget(game))
else:
self.layout.addWidget(QLabel("No updates available"))
self.layout.addStretch(1)
self.setLayout(self.layout)
# TODO Remove when finished

View file

@ -0,0 +1,104 @@
import os
from logging import getLogger
from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem, QFormLayout, QGroupBox, QLineEdit, QPushButton, \
QLabel
from Rare.utils import legendaryConfig
logger = getLogger("Legendary Settings")
class LegendarySettingsForm(QGroupBox):
config: dict
def __init__(self):
config: dict
super(LegendarySettingsForm, self).__init__("Legendary Settings")
self.config = legendaryConfig.get_config()
if not self.config.get("Legendary"):
self.config["Legendary"] = {}
if not self.config["Legendary"].get("wine_executable"):
self.config["Legendary"]["wine_executable"] = ""
if not self.config["Legendary"].get("wine_prefix"):
self.config["Legendary"]["wine_prefix"] = ""
if not self.config["Legendary"].get("locale"):
self.config["Legendary"]["locale"] = ""
env_vars = self.config.get("default.env")
if env_vars:
self.table = QTableWidget(len(env_vars), 2)
for i, label in enumerate(env_vars):
self.table.setItem(i, 0, QTableWidgetItem(label))
self.table.setItem(i, 1, QTableWidgetItem(env_vars[label]))
else:
self.table = QTableWidget(0, 2)
self.table.setHorizontalHeaderLabels(["Variable", "Value"])
self.form = QFormLayout()
self.lgd_conf_wine_prefix = QLineEdit(self.config["Legendary"]["wine_prefix"])
self.lgd_conf_wine_prefix.setPlaceholderText("Default")
self.lgd_conf_wine_exec = QLineEdit(self.config["Legendary"]["wine_executable"])
self.lgd_conf_wine_exec.setPlaceholderText("Default")
self.lgd_conf_locale = QLineEdit(self.config["Legendary"]["locale"])
self.lgd_conf_locale.setPlaceholderText("Default")
self.add_button = QPushButton("Add Environment Variable")
self.delete_env_var = QPushButton("Delete selected Variable")
self.delete_env_var.clicked.connect(self.delete_var)
self.add_button.clicked.connect(self.add_variable)
if os.name != "nt":
self.form.addRow(QLabel("Default Wineprefix"), self.lgd_conf_wine_prefix)
self.form.addRow(QLabel("Wine executable"), self.lgd_conf_wine_exec)
self.form.addRow(QLabel("Environment Variables"), self.table)
self.form.addRow(QLabel("Add Variable"), self.add_button)
self.form.addRow(QLabel("Delete Variable"), self.delete_env_var)
self.form.addRow(QLabel("Locale"), self.lgd_conf_locale)
self.submit_button = QPushButton("Update")
self.submit_button.clicked.connect(self.update_legendary_settings)
self.form.addRow(self.submit_button)
self.setLayout(self.form)
def add_variable(self):
print("add row")
self.table.insertRow(self.table.rowCount())
self.table.setItem(self.table.rowCount(), 0, QTableWidgetItem(""))
self.table.setItem(self.table.rowCount(), 1, QTableWidgetItem(""))
def delete_var(self):
self.table.removeRow(self.table.currentRow())
def update_legendary_settings(self):
logger.info("Updating Legendary Settings")
# Wine exec
if self.lgd_conf_wine_exec.text() != "":
self.config["Legendary"]["wine_executable"] = self.lgd_conf_wine_exec.text()
elif "wine_executable" in self.config["Legendary"]:
self.config["Legendary"].pop("wine_executable")
# Wineprefix
if self.lgd_conf_wine_exec.text() != '':
self.config["Legendary"]["wine_prefix"] = self.lgd_conf_wine_exec.text()
elif "wine_prefix" in self.config["Legendary"]:
self.config["Legendary"].pop("wine_prefix")
# Locale
if self.lgd_conf_locale.text() != "":
self.config["Legendary"]["wine_prefix"] = self.lgd_conf_wine_prefix.text()
elif "locale" in self.config["Legendary"]:
self.config["Legendary"].pop("locale")
# Env vars
if self.table.rowCount() != 0:
self.config["default.env"] = {}
for row in range(self.table.rowCount()):
self.config["default.env"][self.table.item(row, 0).text()] = self.table.item(row, 1).text()
else:
self.config.pop("default.env")
legendaryConfig.set_config(self.config)
print(self.config)

View file

@ -0,0 +1,49 @@
import shutil
from logging import getLogger
from PyQt5.QtWidgets import QGroupBox, QComboBox, QFormLayout, QLineEdit, QLabel, QPushButton
from Rare.Styles import dark
from Rare.utils import RareConfig
logger = getLogger("Rare Settings")
class RareSettingsForm(QGroupBox):
def __init__(self):
super(RareSettingsForm, self).__init__("Rare Settings")
self.rare_form = QFormLayout()
self.style_combo_box = QComboBox()
self.style_combo_box.addItems(["Light", "Dark"])
if RareConfig.THEME == "dark":
self.style_combo_box.setCurrentIndex(1)
self.rare_form.addRow(QLabel("Style"), self.style_combo_box)
self.image_dir_edit = QLineEdit()
self.image_dir_edit.setPlaceholderText("Image directory")
self.image_dir_edit.setText(RareConfig.IMAGE_DIR)
self.rare_form.addRow(QLabel("Image Directory"), self.image_dir_edit)
self.submit_button = QPushButton("Update Rare Settings")
self.submit_button.clicked.connect(self.update_rare_settings)
self.rare_form.addRow(self.submit_button)
self.setLayout(self.rare_form)
def update_rare_settings(self):
logger.info("Update Rare settings")
config = {"Rare": {}}
if self.style_combo_box.currentIndex() == 1:
self.parent().parent().parent().setStyleSheet(dark)
config["Rare"]["theme"] = "dark"
else:
self.parent().parent().parent().setStyleSheet("")
config["Rare"]["theme"] = "light"
config["Rare"]["IMAGE_DIR"] = self.image_dir_edit.text()
print(config["Rare"]["IMAGE_DIR"])
if self.image_dir_edit.text() != RareConfig.IMAGE_DIR:
print("Move")
shutil.move(RareConfig.IMAGE_DIR, self.image_dir_edit.text())
RareConfig.set_config(config)

View file

@ -0,0 +1,46 @@
from logging import getLogger
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QVBoxLayout, QLabel, QPushButton, QScrollArea
from Rare.Tabs.Settings.Legendary import LegendarySettingsForm
from Rare.Tabs.Settings.Rare import RareSettingsForm
from Rare.utils.legendaryUtils import get_name, logout
from legendary.core import LegendaryCore
logger = getLogger("Settings")
class SettingsTab(QScrollArea):
def __init__(self, parent, core: LegendaryCore):
super(SettingsTab, self).__init__(parent=parent)
self.core = core
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
# Settings
self.layout = QVBoxLayout()
self.layout.addWidget(QLabel("<h1>Rare Settings</h1>"))
self.logged_in_as = QLabel(f"Logged in as {get_name()}")
self.legendary_form = LegendarySettingsForm()
self.rare_form = RareSettingsForm()
self.logout_button = QPushButton("Logout")
self.logout_button.clicked.connect(self.logout)
self.layout.addWidget(self.logged_in_as)
self.layout.addWidget(self.rare_form)
self.layout.addWidget(self.legendary_form)
self.layout.addStretch(1)
self.layout.addWidget(self.logout_button)
self.info_label = QLabel("<h2>Credits</h2>")
self.infotext = QLabel("Developers : Dummerle, CommandMC\nLegendary Dev: Rodney\nLicense: GPL v.3")
self.layout.addWidget(self.info_label)
self.layout.addWidget(self.infotext)
self.setLayout(self.layout)
def logout(self):
self.core.lgd.invalidate_userdata()
exit(0)

View file

140
Rare/Tabs/Update.py Normal file
View file

@ -0,0 +1,140 @@
import time
from logging import getLogger
from PyQt5.QtCore import QThread, QProcess
from PyQt5.QtWidgets import QVBoxLayout, QProgressBar, QPushButton, QLabel, QWidget, QHBoxLayout
from legendary.core import LegendaryCore
from legendary.models.game import InstalledGame
from multiprocessing import Queue as MPQueue
logger = getLogger("Updates")
class UpdateThread(QThread):
def __init__(self, dlm):
super(UpdateThread, self).__init__()
self.dlm = dlm
logging_queue = MPQueue(-1)
self.dlm.logging_queue = logging_queue
def run(self):
self.dlm.start()
self.dlm.join()
class UpdateProc(QProcess):
def __init__(self):
super(UpdateProc, self).__init__()
class UpdateWidget(QWidget):
def __init__(self, game: InstalledGame, core: LegendaryCore):
super(UpdateWidget, self).__init__()
self.updating = False
self.game = game
self.core = core
self.layout = QVBoxLayout()
self.childlayout = QHBoxLayout()
self.label = QLabel("Update available for " + self.game.title)
self.button = QPushButton("Update")
self.button.clicked.connect(self.update_game)
self.childlayout.addWidget(self.label)
self.childlayout.addWidget(self.button)
self.layout.addLayout(self.childlayout)
self.progress_bar = QProgressBar()
self.progress_bar.setMaximum(100)
self.layout.addWidget(self.progress_bar)
self.setLayout(self.layout)
def update_game2(self):
if not self.updating:
logger.info("Update " + self.game.title)
game = self.core.get_game(self.game.app_name)
logger.info("Prepare Download")
dlm, analysis, manifest = self.core.prepare_download(game=game, base_game=game)
if not analysis.dl_size:
logger.info("Game is up to date, sorry")
logger.info(f"Install size: {round(analysis.install_size / (1024 ** 3),2)} GB")
logger.info(f"Download size: {round(analysis.dl_size/(1024**3), 2)} GB")
installed_game = self.core.get_installed_game(self.game.app_name)
res = self.core.check_installation_conditions(analysis, installed_game, self.core.get_game(self.game.app_name), True)
if res.failures:
logger.error("Fail")
if res.warnings:
for warn in sorted(res.warnings):
logger.warning(warn)
start_time = time.time()
self.update_thread = UpdateThread(dlm)
self.update_thread.finished.connect(self.finished)
self.update_thread.start()
self.button.setDisabled(True)
# TODO Wird 1000% nicht funktionieren
else:
logger.info("Terminate process")
self.thread.kill()
self.button.setText("Update")
self.updating = False
def update_game(self):
self.proc = QProcess()
self.proc.start("legendary", ["-y", "update", self.game.app_name])
def finished(self):
self.setVisible(False)
def start(self):
self.button.setText("Cancel")
self.updating = True
def get_update_info(self):
shit, infos, game = self.core.prepare_download(self.core.get_game(self.game.app_name),
self.core.get_game(self.game.app_name))
def dataReady(self):
bytes = self.thread.readAllStandardOutput()
byte_list = bytes.split('\n')
data = []
for i in byte_list:
data.append(byte_list)
text = data[0].decode()
print(data)
class UpdateTab(QWidget):
def __init__(self, parent, core: LegendaryCore):
super(UpdateTab, self).__init__(parent=parent)
self.core = core
self.layout = QVBoxLayout()
update_games = self.get_updates()
if update_games:
for game in self.get_updates():
self.layout.addWidget(UpdateWidget(game, core))
else:
self.layout.addWidget(QLabel("No updates available"))
self.layout.addStretch(1)
self.setLayout(self.layout)
def get_updates(self):
self.core.get_assets(True)
update_games = []
games=sorted(self.core.get_installed_list(), key=lambda x: x.title)
versions={}
for game in games:
try:
versions[game.app_name] = self.core.get_asset(game.app_name).build_version
except:
logger.error(f"Metadata for {game.title} is missing")
if versions[game.app_name] != game.version:
update_games.append(game)
return update_games

2
Rare/Tabs/__init__.py Normal file
View file

@ -0,0 +1,2 @@
from Rare.Tabs.Update import UpdateTab
from Rare.Tabs.Settings.SettingsTab import SettingsTab

View file

@ -23,7 +23,6 @@ elif not rare_config.sections():
rare_config.write(open(config_path + "config.ini", "w"))
def get_config() -> {}:
return rare_config.__dict__["_sections"]
@ -32,5 +31,6 @@ def set_config(new_config: {}):
rare_config.__dict__["_sections"] = new_config
rare_config.write(open(config_path + "config.ini", "w"))
IMAGE_DIR = rare_config["Rare"]["IMAGE_DIR"]
THEME = rare_config["Rare"]["theme"]
THEME = rare_config["Rare"]["theme"]

View file

@ -2,7 +2,7 @@ import logging
import os
import subprocess
from PyQt5.QtCore import QProcess, QProcessEnvironment
from PyQt5.QtCore import QProcess, QProcessEnvironment, QThread
from legendary.core import LegendaryCore
logger = logging.getLogger("LGD")
@ -91,7 +91,6 @@ def launch_game(app_name: str, lgd_core: LegendaryCore, offline: bool = False, s
for e in env:
environment.insert(e, env[e])
process.setProcessEnvironment(environment)
process.start(params[0], params[1:])
return process
@ -129,6 +128,3 @@ def uninstall(app_name: str, lgd_core):
# logger.info("Uninstalling " + app_name)
def update(app_name) -> subprocess.Popen:
logger.info(f"Updating {app_name}")
return subprocess.Popen(f"legendary -y update {app_name}".split())

View file

@ -1,4 +1,4 @@
legendary_gl==0.20.4
legendary_gl>=0.20.1
requests==2.25.1
Pillow==8.0.1
PyQt5==5.15.2