works
This commit is contained in:
parent
7f13810d92
commit
868ecf3a03
488
Rare.py
488
Rare.py
|
@ -1,488 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
import configparser
|
|
||||||
import json
|
|
||||||
import math
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from PIL import Image
|
|
||||||
from PyQt5.QtCore import *
|
|
||||||
from PyQt5.QtGui import *
|
|
||||||
from PyQt5.QtWidgets import *
|
|
||||||
|
|
||||||
print('Rare v1 starting up...')
|
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QScrollArea):
|
|
||||||
def __init__(self, allGames, installedGames):
|
|
||||||
super().__init__()
|
|
||||||
self.allGames = allGames
|
|
||||||
self.installedGames = installedGames
|
|
||||||
self.initUI()
|
|
||||||
|
|
||||||
def initUI(self):
|
|
||||||
|
|
||||||
self.widget = QWidget()
|
|
||||||
self.layout = QGridLayout()
|
|
||||||
|
|
||||||
self.gamesPerRow = int((ScreenInfo().screenWidth * .7) / 250)
|
|
||||||
|
|
||||||
j = 0
|
|
||||||
for game in self.installedGames:
|
|
||||||
self.addImage('images/' + game + '/FinalArt.png', self.layout,
|
|
||||||
math.floor(j / self.gamesPerRow), j % self.gamesPerRow)
|
|
||||||
j += 1
|
|
||||||
|
|
||||||
for game in self.allGames:
|
|
||||||
if not game["app_name"] in self.installedGames:
|
|
||||||
self.addImage('images/' + game["app_name"] + '/UninstalledArt.png', self.layout,
|
|
||||||
math.floor(j / self.gamesPerRow), j % self.gamesPerRow)
|
|
||||||
j += 1
|
|
||||||
|
|
||||||
self.widget.setLayout(self.layout)
|
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
|
|
||||||
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
||||||
self.resize(250 * self.gamesPerRow, int(.7 * ScreenInfo().screenHeight))
|
|
||||||
center(self)
|
|
||||||
self.setWindowTitle('Rare v1')
|
|
||||||
self.setWidget(self.widget)
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def addImage(self, pathToImage, layout, x, y):
|
|
||||||
self.label = ExtendedQLabel()
|
|
||||||
self.label.setPixmap(QPixmap(pathToImage).scaled(240, 320))
|
|
||||||
self.label.clicked.connect(lambda: self.clickedGame(pathToImage.split('/', 2)[1]))
|
|
||||||
self.label.rightClicked.connect(lambda: self.gameSettings(pathToImage.split('/', 2)[1]))
|
|
||||||
layout.addWidget(self.label, x, y)
|
|
||||||
|
|
||||||
def clickedGame(self, game):
|
|
||||||
self.game = game
|
|
||||||
if self.game in self.installedGames:
|
|
||||||
self.launchGame(self.game)
|
|
||||||
else:
|
|
||||||
self.installGame(self.game)
|
|
||||||
|
|
||||||
def launchGame(self, game):
|
|
||||||
self.window = LaunchWindow(game)
|
|
||||||
self.window.show()
|
|
||||||
self.window.outputWindow.appendPlainText('> legendary launch ' + game + '\n')
|
|
||||||
self.window.reader.start('legendary', ['launch', game])
|
|
||||||
|
|
||||||
def installGame(self, game):
|
|
||||||
self.window = InstallWindow(game)
|
|
||||||
self.window.show()
|
|
||||||
|
|
||||||
def gameSettings(self, game):
|
|
||||||
self.window = GameSettingsWindow(game)
|
|
||||||
self.window.show()
|
|
||||||
|
|
||||||
|
|
||||||
class LaunchWindow(QMainWindow):
|
|
||||||
def __init__(self, game):
|
|
||||||
super().__init__()
|
|
||||||
self.game = game
|
|
||||||
self.initUI()
|
|
||||||
|
|
||||||
def initUI(self):
|
|
||||||
self.widget = QWidget()
|
|
||||||
self.layout = QVBoxLayout()
|
|
||||||
|
|
||||||
self.outputWindow = TerminalOutput()
|
|
||||||
|
|
||||||
self.reader = ProcessOutputReader()
|
|
||||||
self.reader.produce_output.connect(self.outputWindow.append_output)
|
|
||||||
|
|
||||||
self.layout.addWidget(self.outputWindow)
|
|
||||||
|
|
||||||
self.widget.setLayout(self.layout)
|
|
||||||
self.setWindowTitle('Launching ' + self.game)
|
|
||||||
self.setCentralWidget(self.widget)
|
|
||||||
|
|
||||||
self.resize(int(.3 * ScreenInfo().screenWidth), int(.3 * ScreenInfo().screenHeight))
|
|
||||||
center(self)
|
|
||||||
|
|
||||||
|
|
||||||
class InstallWindow(QMainWindow):
|
|
||||||
def __init__(self, game):
|
|
||||||
super().__init__()
|
|
||||||
self.game = game
|
|
||||||
self.initUI()
|
|
||||||
|
|
||||||
def initUI(self):
|
|
||||||
self.widget = QWidget()
|
|
||||||
self.layout = QVBoxLayout()
|
|
||||||
self.buttonLayout = QHBoxLayout()
|
|
||||||
|
|
||||||
self.installConfirmation = QLabel()
|
|
||||||
self.installConfirmation.setText('Do you really want to install ' + self.game + '?')
|
|
||||||
self.layout.addWidget(self.installConfirmation)
|
|
||||||
self.layout.setAlignment(Qt.AlignCenter)
|
|
||||||
|
|
||||||
self.yesButton = QPushButton()
|
|
||||||
self.yesButton.setText('Yes')
|
|
||||||
self.yesButton.clicked.connect(self.installGame)
|
|
||||||
self.noButton = QPushButton()
|
|
||||||
self.noButton.setText('No')
|
|
||||||
self.noButton.clicked.connect(self.close)
|
|
||||||
self.buttonLayout.addWidget(self.yesButton)
|
|
||||||
self.buttonLayout.addWidget(self.noButton)
|
|
||||||
self.layout.addLayout(self.buttonLayout)
|
|
||||||
|
|
||||||
self.widget.setLayout(self.layout)
|
|
||||||
self.setWindowTitle('Install ' + self.game + '?')
|
|
||||||
self.setCentralWidget(self.widget)
|
|
||||||
self.resize(int(.3 * ScreenInfo().screenWidth), int(.3 * ScreenInfo().screenHeight))
|
|
||||||
center(self)
|
|
||||||
|
|
||||||
def installGame(self):
|
|
||||||
self.outputWindow = TerminalOutput()
|
|
||||||
self.reader = ProcessOutputReader()
|
|
||||||
self.reader.produce_output.connect(self.outputWindow.append_output)
|
|
||||||
self.reader.start('legendary', ['-y', 'install', self.game])
|
|
||||||
self.progressWindowCancel = QPushButton()
|
|
||||||
self.progressWindowCancel.setText('Cancel')
|
|
||||||
self.progressWindowCancel.pressed.connect(lambda: (self.reader.close(), self.progressWindow.close()))
|
|
||||||
|
|
||||||
self.progressWindow = QMainWindow()
|
|
||||||
self.progressWindowWidget = QWidget()
|
|
||||||
self.progressWindowLayout = QVBoxLayout()
|
|
||||||
self.progressWindowLayout.addWidget(self.outputWindow)
|
|
||||||
self.progressWindowLayout.addWidget(self.progressWindowCancel)
|
|
||||||
|
|
||||||
self.progressWindowWidget.setLayout(self.progressWindowLayout)
|
|
||||||
self.progressWindow.setCentralWidget(self.progressWindowWidget)
|
|
||||||
self.progressWindow.setWindowTitle('Installing ' + self.game)
|
|
||||||
self.progressWindow.resize(int(.3 * ScreenInfo().screenWidth), int(.3 * ScreenInfo().screenHeight))
|
|
||||||
center(self.progressWindow)
|
|
||||||
self.progressWindow.show()
|
|
||||||
self.close()
|
|
||||||
|
|
||||||
|
|
||||||
class GameSettingsWindow(QMainWindow):
|
|
||||||
def __init__(self, game):
|
|
||||||
super().__init__()
|
|
||||||
self.game = game
|
|
||||||
self.initUI()
|
|
||||||
|
|
||||||
def initUI(self):
|
|
||||||
self.widget = QWidget()
|
|
||||||
self.layout = QGridLayout()
|
|
||||||
|
|
||||||
self.config = configparser.ConfigParser()
|
|
||||||
self.config.optionxform = lambda option: option
|
|
||||||
self.config.read(os.path.expanduser("~") + '/.config/legendary/config.ini')
|
|
||||||
|
|
||||||
self.wineSetting_label = QLabel()
|
|
||||||
self.wineSetting_label.setText('Wine executable: ')
|
|
||||||
self.wineSetting = QLineEdit()
|
|
||||||
self.wrapperSetting_label = QLabel()
|
|
||||||
self.wrapperSetting_label.setText('Wrapper: ')
|
|
||||||
self.wrapperSetting = QLineEdit()
|
|
||||||
self.noWineSetting_label = QLabel()
|
|
||||||
self.noWineSetting_label.setText('Don\'t use \'wine_executable\'')
|
|
||||||
self.noWineSetting = QCheckBox()
|
|
||||||
|
|
||||||
self.OKButton = QPushButton()
|
|
||||||
self.OKButton.setText('OK')
|
|
||||||
self.OKButton.clicked.connect(lambda: (self.writeSettings(self.config), self.close()))
|
|
||||||
self.cancelButton = QPushButton()
|
|
||||||
self.cancelButton.setText('Cancel')
|
|
||||||
self.cancelButton.clicked.connect(self.close)
|
|
||||||
self.applyButton = QPushButton()
|
|
||||||
self.applyButton.setText('Apply')
|
|
||||||
self.applyButton.clicked.connect(lambda: self.writeSettings(self.config))
|
|
||||||
|
|
||||||
self.buttonLayout = QHBoxLayout()
|
|
||||||
self.buttonLayout.addWidget(self.OKButton)
|
|
||||||
self.buttonLayout.addWidget(self.cancelButton)
|
|
||||||
self.buttonLayout.addWidget(self.applyButton)
|
|
||||||
|
|
||||||
if self.game not in self.config:
|
|
||||||
self.config[self.game] = {}
|
|
||||||
self.gameSettings = self.config[self.game]
|
|
||||||
|
|
||||||
self.wineSetting.setText(self.gameSettings.get('wine_executable', ''))
|
|
||||||
self.wineSetting.setPlaceholderText('Unset, [default] value: \'' +
|
|
||||||
self.config['default'].get('wine_executable', '') + '\'')
|
|
||||||
self.wrapperSetting.setText(self.gameSettings.get('wrapper', ''))
|
|
||||||
self.wrapperSetting.setPlaceholderText('Unset, not using default value '
|
|
||||||
'(not supported for \'wrapper\' and \'no_wine\'')
|
|
||||||
self.noWineSetting.setChecked(self.gameSettings.getboolean('no_wine', False))
|
|
||||||
|
|
||||||
self.layout.addWidget(self.wineSetting_label, 0, 0)
|
|
||||||
self.layout.addWidget(self.wineSetting, 0, 1)
|
|
||||||
self.layout.addWidget(self.wrapperSetting_label, 1, 0)
|
|
||||||
self.layout.addWidget(self.wrapperSetting, 1, 1)
|
|
||||||
self.layout.addWidget(self.noWineSetting_label, 2, 0)
|
|
||||||
self.layout.addWidget(self.noWineSetting, 2, 1)
|
|
||||||
self.layout.addLayout(self.buttonLayout, 3, 1)
|
|
||||||
|
|
||||||
self.widget.setLayout(self.layout)
|
|
||||||
self.setWindowTitle('Settings for ' + self.game)
|
|
||||||
self.setCentralWidget(self.widget)
|
|
||||||
self.resize(int(.4 * ScreenInfo().screenWidth), int(.3 * ScreenInfo().screenHeight))
|
|
||||||
center(self)
|
|
||||||
|
|
||||||
def writeSettings(self, configToSave):
|
|
||||||
if not self.wineSetting.text() == '':
|
|
||||||
self.config.set(self.game, 'wine_executable', self.wineSetting.text())
|
|
||||||
if not self.wrapperSetting.text() == '':
|
|
||||||
self.config.set(self.game, 'wrapper', self.wrapperSetting.text())
|
|
||||||
self.config.set(self.game, 'no_wine', str(self.noWineSetting.isChecked()))
|
|
||||||
with open(os.path.expanduser("~") + '/.config/legendary/config.ini', 'w') as configfile:
|
|
||||||
configToSave.write(configfile)
|
|
||||||
|
|
||||||
|
|
||||||
class LoginWindow(QMainWindow):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
self.initUI()
|
|
||||||
|
|
||||||
def initUI(self):
|
|
||||||
self.widget = QWidget()
|
|
||||||
self.layout = QVBoxLayout()
|
|
||||||
|
|
||||||
self.loginMessage = QLabel()
|
|
||||||
self.loginMessage.setText('You\'re currently not logged in.'
|
|
||||||
' Click "Open login window" to open a browser window to login.\n'
|
|
||||||
'After you do, copy the "sid" value into the Text Input field below'
|
|
||||||
' and click "Submit".')
|
|
||||||
self.layout.addWidget(self.loginMessage)
|
|
||||||
self.loginOpenButton = QPushButton()
|
|
||||||
self.loginOpenButton.setText('Open login window')
|
|
||||||
self.layout.addWidget(self.loginOpenButton)
|
|
||||||
self.loginOpenButton.pressed.connect(lambda: QDesktopServices.openUrl(QUrl(
|
|
||||||
'https://www.epicgames.com/id/login?redirectUrl=https%3A%2F%2Fwww.epicgames.com%2Fid%2Fapi%2Fredirect')))
|
|
||||||
self.loginInputField = QLineEdit()
|
|
||||||
self.loginInputField.setPlaceholderText('Paste the "sid" value here')
|
|
||||||
self.layout.addWidget(self.loginInputField)
|
|
||||||
self.loginSubmitButton = QPushButton()
|
|
||||||
self.loginSubmitButton.setText('Submit')
|
|
||||||
self.loginSubmitButton.pressed.connect(lambda: self.tryLogin(self.loginInputField.text()))
|
|
||||||
self.layout.addWidget(self.loginSubmitButton)
|
|
||||||
|
|
||||||
self.widget.setLayout(self.layout)
|
|
||||||
self.setWindowTitle('Not logged in')
|
|
||||||
self.setCentralWidget(self.widget)
|
|
||||||
self.resize(int(.4 * ScreenInfo().screenWidth), int(.3 * ScreenInfo().screenHeight))
|
|
||||||
center(self)
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
def tryLogin(self, sid):
|
|
||||||
legendaryProcess = subprocess.Popen('legendary auth --sid ' + sid, shell=True, stdout=subprocess.DEVNULL,
|
|
||||||
stderr=subprocess.STDOUT, stdin=subprocess.PIPE)
|
|
||||||
try:
|
|
||||||
legendaryProcess.wait(20)
|
|
||||||
except subprocess.TimeoutExpired:
|
|
||||||
pass
|
|
||||||
if os.path.isfile(os.path.expanduser("~") + '/.config/legendary/user.json'):
|
|
||||||
self.close()
|
|
||||||
# Run list-games once to get game list + info for newly logged in account
|
|
||||||
installedGames = subprocess.Popen('legendary list-games', shell=True,
|
|
||||||
stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
||||||
installedGames.wait()
|
|
||||||
startMainProcess(True)
|
|
||||||
else:
|
|
||||||
self.errorWindow = QMainWindow()
|
|
||||||
self.errorWindowWidget = QWidget()
|
|
||||||
self.errorWindowLayout = QVBoxLayout()
|
|
||||||
self.errorWindow.setCentralWidget(self.errorWindowWidget)
|
|
||||||
self.errorWindowWidget.setLayout(self.errorWindowLayout)
|
|
||||||
self.errorText = QLabel()
|
|
||||||
self.errorText.setText('There was an error logging in.\n'
|
|
||||||
'Please double-check you typed in the "sid" value.')
|
|
||||||
self.errorWindowLayout.addWidget(self.errorText)
|
|
||||||
self.errorButton = QPushButton()
|
|
||||||
self.errorButton.setText('OK')
|
|
||||||
self.errorButton.pressed.connect(self.errorWindow.close)
|
|
||||||
self.errorWindowLayout.addWidget(self.errorButton)
|
|
||||||
self.errorWindow.resize(int(.2 * ScreenInfo().screenWidth), int(.15 * ScreenInfo().screenHeight))
|
|
||||||
center(self.errorWindow)
|
|
||||||
self.errorWindow.show()
|
|
||||||
|
|
||||||
|
|
||||||
class ProcessOutputReader(QProcess):
|
|
||||||
produce_output = pyqtSignal(str)
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
# merge stderr channel into stdout channel
|
|
||||||
self.setProcessChannelMode(QProcess.MergedChannels)
|
|
||||||
|
|
||||||
# prepare decoding process' output to Unicode
|
|
||||||
codec = QTextCodec.codecForLocale()
|
|
||||||
self._decoder_stdout = codec.makeDecoder()
|
|
||||||
|
|
||||||
self.readyReadStandardOutput.connect(self._ready_read_standard_output)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def _ready_read_standard_output(self):
|
|
||||||
raw_bytes = self.readAllStandardOutput()
|
|
||||||
text = self._decoder_stdout.toUnicode(raw_bytes)
|
|
||||||
self.produce_output.emit(text)
|
|
||||||
|
|
||||||
|
|
||||||
class TerminalOutput(QPlainTextEdit):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__()
|
|
||||||
|
|
||||||
self.setReadOnly(True)
|
|
||||||
|
|
||||||
self._cursor_output = self.textCursor()
|
|
||||||
|
|
||||||
@pyqtSlot(str)
|
|
||||||
def append_output(self, text):
|
|
||||||
self._cursor_output.insertText(text)
|
|
||||||
self.scroll_to_last_line()
|
|
||||||
|
|
||||||
def scroll_to_last_line(self):
|
|
||||||
cursor = self.textCursor()
|
|
||||||
cursor.movePosition(QTextCursor.End)
|
|
||||||
cursor.movePosition(QTextCursor.Up if cursor.atBlockStart() else
|
|
||||||
QTextCursor.StartOfLine)
|
|
||||||
self.setTextCursor(cursor)
|
|
||||||
|
|
||||||
|
|
||||||
class ExtendedQLabel(QLabel):
|
|
||||||
clicked = pyqtSignal()
|
|
||||||
rightClicked = pyqtSignal()
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
QLabel.__init__(self, parent)
|
|
||||||
|
|
||||||
def mousePressEvent(self, ev):
|
|
||||||
if ev.button() == Qt.LeftButton:
|
|
||||||
self.clicked.emit()
|
|
||||||
if ev.button() == Qt.RightButton:
|
|
||||||
self.rightClicked.emit()
|
|
||||||
|
|
||||||
|
|
||||||
class ScreenInfo():
|
|
||||||
def __init__(self):
|
|
||||||
self.screenWidth = QDesktopWidget().screenGeometry(-1).width()
|
|
||||||
self.screenHeight = QDesktopWidget().screenGeometry(-1).height()
|
|
||||||
|
|
||||||
|
|
||||||
def center(self):
|
|
||||||
qr = self.frameGeometry()
|
|
||||||
qr.moveCenter(QDesktopWidget().availableGeometry().center())
|
|
||||||
self.move(qr.topLeft())
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# Check if Legendary is installed
|
|
||||||
try:
|
|
||||||
subprocess.Popen('legendary', shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
|
|
||||||
except FileNotFoundError:
|
|
||||||
print('Legendary does not appear to be installed. Install it using\'pip install legendary-gl\'')
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
if os.path.isfile(os.path.expanduser("~") + '/.config/legendary/user.json'):
|
|
||||||
startMainProcess()
|
|
||||||
else:
|
|
||||||
notLoggedIn()
|
|
||||||
|
|
||||||
|
|
||||||
def startMainProcess(loggedIn=False):
|
|
||||||
print('Creating directorys')
|
|
||||||
try:
|
|
||||||
os.mkdir('images')
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
print('Parsing game metadata')
|
|
||||||
allGames = []
|
|
||||||
for filename in os.listdir(os.path.expanduser("~") + '/.config/legendary/metadata/'):
|
|
||||||
with open(os.path.expanduser("~") + '/.config/legendary/metadata/' + filename, 'r') as f:
|
|
||||||
game = json.load(f)
|
|
||||||
allGames.append(game)
|
|
||||||
try:
|
|
||||||
os.mkdir('images/' + game["app_name"])
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
print('Parsing installed games')
|
|
||||||
installedGames = []
|
|
||||||
for line in subprocess.Popen('legendary list-installed --csv | tail -n +2', shell=True,
|
|
||||||
stdout=subprocess.PIPE, universal_newlines=True).stdout:
|
|
||||||
installedGames.append(line.split(',', 1)[0])
|
|
||||||
|
|
||||||
print('Downloading and scaling cover images, this could take a little on first boot')
|
|
||||||
for game in allGames:
|
|
||||||
for image in game["metadata"]["keyImages"]:
|
|
||||||
# Check if the game's type is either the background or the logo, since that's the only two images we need
|
|
||||||
if image["type"] == "DieselGameBoxTall" or image["type"] == "DieselGameBoxLogo":
|
|
||||||
# If a cover was already downloaded, we don't have to download it again
|
|
||||||
if not os.path.isfile('images/' + game["app_name"] + '/' + image["type"] + '.png'):
|
|
||||||
print('Downloading ' + image["type"] + ' for ' + game["app_name"])
|
|
||||||
url = image["url"].replace('"', '')
|
|
||||||
with open('images/' + game["app_name"] + '/' + image["type"] + '.png', 'wb') as f:
|
|
||||||
f.write(requests.get(url).content)
|
|
||||||
# Since some games have the background and logo split into two files,
|
|
||||||
# we have to do some extra logic to combine those
|
|
||||||
if not os.path.isfile('images/' + game["app_name"] + '/FinalArt.png'):
|
|
||||||
try:
|
|
||||||
print('Scaling cover for ' + game["app_name"])
|
|
||||||
# First off, check if the extra logo file is even there
|
|
||||||
if os.path.isfile('images/' + game["app_name"] + '/DieselGameBoxLogo.png'):
|
|
||||||
# Load in the two images that need to be combined
|
|
||||||
bg = Image.open('images/' + game["app_name"] + '/DieselGameBoxTall.png')
|
|
||||||
# To make sure the background is actually horizontal (3/4) (looking at you Celeste), resize the image
|
|
||||||
bg = bg.resize((int(bg.size[1] * 3 / 4), bg.size[1]))
|
|
||||||
# Since the logo is transparent, we have to convert it to RGBA
|
|
||||||
logo = Image.open('images/' + game["app_name"] + '/DieselGameBoxLogo.png').convert('RGBA')
|
|
||||||
# Resize the logo to be ~ 3/4 as wide as the background (EGL does something like this)
|
|
||||||
wpercent = ((bg.size[0] * (3 / 4)) / float(logo.size[0]))
|
|
||||||
hsize = int((float(logo.size[1]) * float(wpercent)))
|
|
||||||
logo = logo.resize((int(bg.size[0] * (3 / 4)), hsize), Image.ANTIALIAS)
|
|
||||||
# Calculate where the image has to be placed
|
|
||||||
pasteX = int((bg.size[0] - logo.size[0]) / 2)
|
|
||||||
pasteY = int((bg.size[1] - logo.size[1]) / 2)
|
|
||||||
# And finally copy the background and paste in the image
|
|
||||||
finalArt = bg.copy()
|
|
||||||
finalArt.paste(logo, (pasteX, pasteY), logo)
|
|
||||||
# Write out the file
|
|
||||||
finalArt.save('images/' + game["app_name"] + '/FinalArt.png')
|
|
||||||
|
|
||||||
# And we have to do part of that again
|
|
||||||
# since the cover for an uninstalled game has the logo half-transparent
|
|
||||||
logoCopy = logo.copy()
|
|
||||||
logoCopy.putalpha(int(256 * 3 / 4))
|
|
||||||
logo.paste(logoCopy, logo)
|
|
||||||
uninstalledArt = bg.copy()
|
|
||||||
uninstalledArt.paste(logo, (pasteX, pasteY), logo)
|
|
||||||
uninstalledArt = uninstalledArt.convert('L')
|
|
||||||
uninstalledArt.save('images/' + game["app_name"] + '/UninstalledArt.png')
|
|
||||||
# And if the logo and background aren't split
|
|
||||||
else:
|
|
||||||
# We just open up the background and save that as the final image
|
|
||||||
finalArt = Image.open('images/' + game["app_name"] + '/DieselGameBoxTall.png')
|
|
||||||
finalArt.save('images/' + game["app_name"] + '/FinalArt.png')
|
|
||||||
# And same with the grayscale one
|
|
||||||
uninstalledArt = finalArt.convert('L')
|
|
||||||
uninstalledArt.save('images/' + game["app_name"] + '/UninstalledArt.png')
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
# If the user had to login first, the QApplication will already be running, so we don't have to start it again
|
|
||||||
if not loggedIn:
|
|
||||||
# Start GUI stuff
|
|
||||||
app = QApplication([])
|
|
||||||
mainWindow = MainWindow(allGames, installedGames)
|
|
||||||
app.exec_()
|
|
||||||
else:
|
|
||||||
mainWindow = MainWindow(allGames, installedGames)
|
|
||||||
mainWindow.show()
|
|
||||||
|
|
||||||
|
|
||||||
def notLoggedIn():
|
|
||||||
app = QApplication([])
|
|
||||||
window = LoginWindow()
|
|
||||||
app.exec_()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,11 +1,35 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
|
from logging import getLogger
|
||||||
|
|
||||||
|
from PyQt5.QtCore import QThread, pyqtSignal
|
||||||
from PyQt5.QtGui import QPixmap
|
from PyQt5.QtGui import QPixmap
|
||||||
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QPushButton, QStyle
|
from PyQt5.QtWidgets import QWidget, QLabel, QHBoxLayout, QVBoxLayout, QPushButton, QStyle
|
||||||
|
|
||||||
from Rare.Dialogs import InstallDialog
|
from Rare.Dialogs import InstallDialog
|
||||||
from Rare.utils import legendaryUtils
|
from Rare.utils import legendaryUtils
|
||||||
|
|
||||||
|
logger = getLogger("Game")
|
||||||
|
|
||||||
|
|
||||||
|
class Thread(QThread):
|
||||||
|
signal = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, proc):
|
||||||
|
super(Thread, self).__init__()
|
||||||
|
self.proc: subprocess.Popen = proc
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.sleep(3)
|
||||||
|
logger.info("Running ")
|
||||||
|
while True:
|
||||||
|
if not self.proc.poll():
|
||||||
|
self.sleep(3)
|
||||||
|
else:
|
||||||
|
self.signal.emit()
|
||||||
|
self.quit()
|
||||||
|
logger.info("Kill")
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class GameWidget(QWidget):
|
class GameWidget(QWidget):
|
||||||
proc: subprocess.Popen
|
proc: subprocess.Popen
|
||||||
|
@ -53,14 +77,25 @@ class GameWidget(QWidget):
|
||||||
|
|
||||||
def launch(self):
|
def launch(self):
|
||||||
if not self.game_running:
|
if not self.game_running:
|
||||||
print(f"launch {self.title}")
|
logger.info(f"launching {self.title}")
|
||||||
self.launch_button.setText("Kill")
|
resp = legendaryUtils.launch_game(self.app_name)
|
||||||
self.proc = legendaryUtils.launch_game(self.app_name)
|
if resp != 1:
|
||||||
self.game_running = True
|
self.proc = resp
|
||||||
|
self.thread = Thread(self.proc)
|
||||||
|
self.thread.signal.connect(self.kill)
|
||||||
|
self.thread.start()
|
||||||
|
self.launch_button.setText("Kill")
|
||||||
|
self.game_running = True
|
||||||
|
else:
|
||||||
|
logger.warning("Error")
|
||||||
else:
|
else:
|
||||||
self.proc.kill()
|
self.kill()
|
||||||
self.launch_button.setText("Launch")
|
|
||||||
self.game_running = False
|
|
||||||
|
def kill(self):
|
||||||
|
self.proc.kill()
|
||||||
|
self.launch_button.setText("Launch3")
|
||||||
|
self.game_running = False
|
||||||
|
|
||||||
def get_rating(self) -> str:
|
def get_rating(self) -> str:
|
||||||
return "gold" # TODO
|
return "gold" # TODO
|
||||||
|
@ -100,11 +135,11 @@ class UninstalledGameWidget(QWidget):
|
||||||
self.setLayout(self.layout)
|
self.setLayout(self.layout)
|
||||||
|
|
||||||
def install(self):
|
def install(self):
|
||||||
print("install " + self.title)
|
logger.info("install " + self.title)
|
||||||
dia = InstallDialog(self.game)
|
dia = InstallDialog(self.game)
|
||||||
data = dia.get_data()
|
data = dia.get_data()
|
||||||
if data != 0:
|
if data != 0:
|
||||||
path = data.get("install_path")
|
path = data.get("install_path")
|
||||||
# TODO
|
# TODO
|
||||||
print(f"install {self.app_name} in path {path}")
|
logger.info(f"install {self.app_name} in path {path}")
|
||||||
legendaryUtils.install(self.app_name)
|
legendaryUtils.install(self.app_name)
|
||||||
|
|
14
Rare/Main.py
14
Rare/Main.py
|
@ -13,6 +13,7 @@ from Rare.utils import legendaryUtils
|
||||||
|
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
format='[%(name)s] %(levelname)s: %(message)s',
|
format='[%(name)s] %(levelname)s: %(message)s',
|
||||||
|
level=logging.INFO
|
||||||
)
|
)
|
||||||
logger = logging.getLogger("Rare")
|
logger = logging.getLogger("Rare")
|
||||||
|
|
||||||
|
@ -50,10 +51,13 @@ class TabWidget(QTabWidget):
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
if os.path.isfile(os.path.expanduser("~") + '/.config/legendary/user.json'):
|
|
||||||
logger.info("Launching Rare")
|
if legendaryUtils.core.login():
|
||||||
download_images()
|
|
||||||
|
logger.info("Login credentials found")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
logger.info("No login data found")
|
||||||
dia = LoginDialog()
|
dia = LoginDialog()
|
||||||
code = dia.get_login()
|
code = dia.get_login()
|
||||||
if code == 1:
|
if code == 1:
|
||||||
|
@ -62,7 +66,7 @@ def main():
|
||||||
exit(0)
|
exit(0)
|
||||||
elif code == 0:
|
elif code == 0:
|
||||||
logger.info("Login successfully")
|
logger.info("Login successfully")
|
||||||
|
download_images()
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
app.exec_()
|
app.exec_()
|
||||||
|
|
||||||
|
@ -89,7 +93,7 @@ def download_images():
|
||||||
if not os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/FinalArt.png"):
|
if not os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/FinalArt.png"):
|
||||||
logger.info("Scaling cover for " + game.app_name)
|
logger.info("Scaling cover for " + game.app_name)
|
||||||
if os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo"):
|
if os.path.isfile(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo"):
|
||||||
bg: Image.Image = Image.open()
|
bg: Image.Image = Image.open(f"{IMAGE_DIR}/{game.app_name}/DieselGameBoxLogo")
|
||||||
bg = bg.resize((int(bg.size[1] * 3 / 4), bg.size[1]))
|
bg = bg.resize((int(bg.size[1] * 3 / 4), bg.size[1]))
|
||||||
logo = Image.open('images/' + game["app_name"] + '/DieselGameBoxLogo.png').convert('RGBA')
|
logo = Image.open('images/' + game["app_name"] + '/DieselGameBoxLogo.png').convert('RGBA')
|
||||||
wpercent = ((bg.size[0] * (3 / 4)) / float(logo.size[0]))
|
wpercent = ((bg.size[0] * (3 / 4)) / float(logo.size[0]))
|
||||||
|
|
|
@ -25,7 +25,7 @@ class Settings(QWidget):
|
||||||
self.layout.addWidget(self.logout_button)
|
self.layout.addWidget(self.logout_button)
|
||||||
|
|
||||||
self.info_label = QLabel("<h2>Credits</h2>")
|
self.info_label = QLabel("<h2>Credits</h2>")
|
||||||
self.infotext = QLabel("""Developers : Dummerle, CommandMC\nLicence: GPL v3""")
|
self.infotext = QLabel("""Developers : Dummerle, CommandMC\nLegendary Dev: Derrod\nLicence: GPL v3""")
|
||||||
|
|
||||||
self.layout.addWidget(self.info_label)
|
self.layout.addWidget(self.info_label)
|
||||||
self.layout.addWidget(self.infotext)
|
self.layout.addWidget(self.infotext)
|
||||||
|
|
|
@ -55,10 +55,13 @@ def launch_game(app_name: str, offline: bool = False, skip_version_check: bool =
|
||||||
no_wine: bool = os.name == "nt", extra: [] = None):
|
no_wine: bool = os.name == "nt", extra: [] = None):
|
||||||
game = core.get_installed_game(app_name)
|
game = core.get_installed_game(app_name)
|
||||||
if not game:
|
if not game:
|
||||||
|
print("Game not found")
|
||||||
return 1
|
return 1
|
||||||
if game.is_dlc:
|
if game.is_dlc:
|
||||||
|
print("Game is dlc")
|
||||||
return 1
|
return 1
|
||||||
if not os.path.exists(game.install_path):
|
if not os.path.exists(game.install_path):
|
||||||
|
print("Game doesn't exist")
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
if not offline:
|
if not offline:
|
||||||
|
@ -84,11 +87,6 @@ def launch_game(app_name: str, offline: bool = False, skip_version_check: bool =
|
||||||
return subprocess.Popen(params, cwd=cwd, env=env)
|
return subprocess.Popen(params, cwd=cwd, env=env)
|
||||||
|
|
||||||
|
|
||||||
def auth(sid: str):
|
|
||||||
# cli.auth(Namespace(session_id=sid))
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def auth_import(lutris: bool = False, wine_prefix: str = None) -> bool:
|
def auth_import(lutris: bool = False, wine_prefix: str = None) -> bool:
|
||||||
'''
|
'''
|
||||||
import Data from existing Egl installation
|
import Data from existing Egl installation
|
||||||
|
@ -159,5 +157,6 @@ def login(sid):
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_name():
|
def get_name():
|
||||||
return core.lgd.userdata["displayName"]
|
return core.lgd.userdata["displayName"]
|
Loading…
Reference in a new issue