VRUtil/vrutil/geproton.py

184 lines
6.9 KiB
Python
Raw Normal View History

import os
import re
import shutil
import tarfile
import tempfile
from pathlib import Path
import dearpygui.dearpygui as dpg
import requests
from vrutil.dialogs import Dialogs
from vrutil.utils import loaded
_GE_PROTON_GITHUB = 'GloriousEggroll/proton-ge-custom'
_GE_PROTON_INSTALL_DIR = '{steam_dir}/compatibilitytools.d'
class GeProtonSettings:
"""GE Proton related settings"""
def __init__(self, steam_dir: str, dialogs: Dialogs):
self._install_dir = _GE_PROTON_INSTALL_DIR.format(steam_dir=steam_dir)
self._dialogs = dialogs
self._installed_list = None
self._available_list = None
self._page_indicator_item = None
self._cur_page = 0
self._max_page = 0
self._page_links = {
'first': '',
'prev': '',
'next': '',
'last': ''
}
def create_views(self):
with dpg.collapsing_header(label='GE Proton', default_open=True):
with dpg.group(horizontal=True):
# INSTALLED
with dpg.group(horizontal=False):
dpg.add_text('Installed versions:')
dpg.add_button(label='Delete', callback=self._delete_installed)
self._installed_list = dpg.add_listbox(
items=self._get_installed(),
width=250,
num_items=8
)
# AVAILABLE
with dpg.group(horizontal=False):
dpg.add_text('Available versions:')
with dpg.group(horizontal=True):
dpg.add_button(label='Install', callback=self._install)
dpg.add_button(label='Reload', callback=self.reload_available)
dpg.add_button(arrow=True, direction=dpg.mvDir_Left, user_data='first', callback=self._switch_page)
dpg.add_button(arrow=True, direction=dpg.mvDir_Left, user_data='prev', callback=self._switch_page)
self._page_indicator_item = dpg.add_text('0/0')
dpg.add_button(arrow=True, direction=dpg.mvDir_Right, user_data='next', callback=self._switch_page)
dpg.add_button(arrow=True, direction=dpg.mvDir_Right, user_data='last', callback=self._switch_page)
self._available_list = dpg.add_listbox(
items=(),
width=250,
num_items=8
)
dpg.add_spacer(height=10)
# region Installed
def reload_installed(self):
dpg.configure_item(self._installed_list, items=self._get_installed())
def _get_installed(self):
installed = os.listdir(self._install_dir)
sorted_versions = tuple(sorted(installed, reverse=True))
loaded('GE Proton installed', sorted_versions)
return sorted_versions
def _delete_installed(self):
version = dpg.get_value(self._installed_list)
install_path = f'{self._install_dir}/{version}'
self._dialogs.show_alert(
title=f'Delete {version}?',
message=f'Will remove\n{install_path}',
confirm='Delete',
on_confirm=lambda: self._confirmed_delete_installed(install_path),
on_dismiss=lambda: self._dialogs.hide_alert()
)
def _confirmed_delete_installed(self, version):
self._dialogs.hide_alert()
self._dialogs.show_loading(title='Deleting...', message=version)
print(f'Deleting {version}')
shutil.rmtree(version)
self.reload_installed()
print('Done deleting')
self._dialogs.hide_loading()
# endregion
# region Available
def reload_available(self):
self._cur_page = 1
self._max_page = 1
dpg.configure_item(self._available_list, items=self._get_available())
def _get_available(self, link=None):
url = link or f'https://api.github.com/repos/{_GE_PROTON_GITHUB}/releases'
response = requests.get(url)
self._update_page_links(response.headers['Link'])
releases = response.json()
release_names = list(map(lambda release: release['tag_name'], releases))
sorted_releases = tuple(sorted(release_names, reverse=True))
loaded('GE Proton releases', sorted_releases)
return sorted_releases
def _update_page_links(self, links):
matches = re.findall('<(\\S+)>; rel=\\"(\\w+)\\"', links)
for link in self._page_links:
self._page_links[link] = ''
for match in matches:
self._page_links[match[1]] = match[0]
if self._page_links['last'] != '':
self._max_page = self._page_links['last'].split('=')[1]
dpg.set_value(self._page_indicator_item, f'{self._cur_page}/{self._max_page}')
def _switch_page(self, sender, app_data, user_data):
print(f'Switching page {user_data}')
link = self._page_links[user_data]
if link != '':
self._cur_page = link.split('=')[1]
dpg.configure_item(self._available_list, items=self._get_available(link))
def _install(self):
version = dpg.get_value(self._available_list)
url = f'https://github.com/{_GE_PROTON_GITHUB}/releases/download/{version}/{version}.tar.gz'
tar_file_path = f'{tempfile.gettempdir()}/{version}.tar.gz'
target_extract_path = self._install_dir
if version is None or version == '':
self._dialogs.show_alert(
title=f'No version selected!',
message='Reload the release list and select a version to install.',
on_confirm=lambda: self._dialogs.hide_alert()
)
return
if version in self._get_installed():
self._dialogs.show_alert(
title=f'Version {version} already installed!',
message='To download again, delete it first',
on_confirm=lambda: self._dialogs.hide_alert()
)
return
print(f'Loading {url} to {tar_file_path}')
title = f'Installing {version}'
self._dialogs.show_loading(title=title, message='Downloading...')
response = requests.get(url, stream=True)
if response.status_code == 200:
with open(tar_file_path, 'wb') as temp_file:
temp_file.write(response.raw.read())
print('Download complete, start extracting...')
self._dialogs.show_loading(title=title, message='Extracting...')
with tarfile.open(tar_file_path) as tar_file:
tar_file.extractall(target_extract_path)
print('Done installing')
else:
print(response.status_code)
print(response.text)
if Path(tar_file_path).exists():
os.remove(tar_file_path)
self._dialogs.hide_loading()
self.reload_installed()
dpg.set_value(self._installed_list, version)
# endregion