Windows (No wine)
Refactoring
This commit is contained in:
parent
f9037ff873
commit
493bcba526
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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_()
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
"""
|
|
@ -1,2 +1 @@
|
|||
from Rare.Styles.dark import dark
|
||||
from Rare.Styles.Obit import obit
|
||||
|
|
|
@ -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
|
||||
|
|
104
Rare/Tabs/Settings/Legendary.py
Normal file
104
Rare/Tabs/Settings/Legendary.py
Normal 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)
|
49
Rare/Tabs/Settings/Rare.py
Normal file
49
Rare/Tabs/Settings/Rare.py
Normal 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)
|
46
Rare/Tabs/Settings/SettingsTab.py
Normal file
46
Rare/Tabs/Settings/SettingsTab.py
Normal 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)
|
0
Rare/Tabs/Settings/__init__.py
Normal file
0
Rare/Tabs/Settings/__init__.py
Normal file
140
Rare/Tabs/Update.py
Normal file
140
Rare/Tabs/Update.py
Normal 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
2
Rare/Tabs/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
from Rare.Tabs.Update import UpdateTab
|
||||
from Rare.Tabs.Settings.SettingsTab import SettingsTab
|
|
@ -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"]
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue