2024-07-06 00:11:56 +02:00
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import shutil
|
|
|
|
import tarfile
|
|
|
|
import tempfile
|
|
|
|
from pathlib import Path
|
|
|
|
|
|
|
|
import dearpygui.dearpygui as dpg
|
|
|
|
import requests
|
|
|
|
|
2024-07-07 15:05:16 +02:00
|
|
|
from vrutil.dialogs import Dialogs
|
|
|
|
from vrutil.utils import loaded
|
2024-07-06 00:11:56 +02:00
|
|
|
|
|
|
|
_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(label='⇇', user_data='first', callback=self._switch_page)
|
|
|
|
dpg.add_button(label='←', user_data='prev', callback=self._switch_page)
|
|
|
|
self._page_indicator_item = dpg.add_text('0/0')
|
|
|
|
dpg.add_button(label='→', user_data='next', callback=self._switch_page)
|
|
|
|
dpg.add_button(label='⇉', 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
|