From e020be766ffd210d7ee8bd2408d25034574f0184 Mon Sep 17 00:00:00 2001 From: Mikhail Tergoev Date: Thu, 15 Feb 2024 17:26:29 +0300 Subject: [PATCH] drop plugin folder from data --- data_from_portwine/plugins/pp-games-lib | 484 ------------------------ 1 file changed, 484 deletions(-) delete mode 100755 data_from_portwine/plugins/pp-games-lib diff --git a/data_from_portwine/plugins/pp-games-lib b/data_from_portwine/plugins/pp-games-lib deleted file mode 100755 index 69fcb8e..0000000 --- a/data_from_portwine/plugins/pp-games-lib +++ /dev/null @@ -1,484 +0,0 @@ -#!/usr/bin/env python3 - -import os -import re -import shlex -import shutil -import logging -from configparser import RawConfigParser -from pathlib import Path -from subprocess import run -from types import SimpleNamespace -try: - from PyQt6.QtCore import * # type: ignore - from PyQt6.QtGui import * # type: ignore - from PyQt6.QtWidgets import * # type: ignore -except ModuleNotFoundError: - from PyQt5.QtCore import * # type: ignore - from PyQt5.QtGui import * # type: ignore - from PyQt5.QtWidgets import * # type: ignore - -settings = QSettings('PPGL', 'PortProtonGamesLib') -g = SimpleNamespace(locale = '') - -class MainWindow(QMainWindow): - def __init__(self): - super().__init__() - - self.resize(QSize(800, 600)) - geometry = settings.value('geometry_main') - if geometry: - self.restoreGeometry(geometry) - - shortcut = RawConfigParser() - shortcut.read(os.getenv('HOME') + '/.local/share/applications/PortProton.desktop') - scripts_dir = shortcut.get('Desktop Entry', 'Path', fallback=os.getenv('HOME') + '/.local/share/PortWINE/PortProton/data/scripts') - if not scripts_dir or not Path(scripts_dir).is_dir(): - QMessageBox.critical(self, 'Error', 'Can not find installed PortProton') - exit(1) - g.scripts_dir = scripts_dir.rstrip('/') - g.pp_icon = shortcut.get('Desktop Entry', 'Icon', fallback='/usr/share/pixmaps/portproton.png') - pp_icon = QIcon(g.pp_icon) - self.setWindowIcon(pp_icon) - self.setWindowTitle('PortProton games library') - - g.base_dir = str(Path(scripts_dir + '/../..').resolve()) - g.install_pfx = g.base_dir + '/data/prefixes/INSTALL' - g.shortcuts_dir = g.base_dir + '/shortcuts' - g.games_dir = g.base_dir + '/games' - - loc_path = Path(g.base_dir + '/data/tmp/PortProton_loc') - if loc_path.exists(): - g.locale = loc_path.read_text().strip() - - Path(g.shortcuts_dir).mkdir(parents=True, exist_ok=True) - Path(g.games_dir).mkdir(parents=True, exist_ok=True) - - sep = QFrame(self) - sep.setFrameShape(QFrame.Shape.VLine) - sep.setFrameShadow(QFrame.Shadow.Sunken) - self._status_size = QLabel(self) - self._status_dir = QLabel(self) - self._status_wine = QLabel(self) - self.statusBar().setVisible(False) - self.statusBar().addWidget(self._status_dir, 1) - self.statusBar().addWidget(self._status_wine) - self.statusBar().addWidget(sep) - self.statusBar().addWidget(self._status_size) - - - self.game_list = GameList(self) - self.setCentralWidget(self.game_list) - - self.toolbar = self.addToolBar('Main') - self.toolbar.setIconSize(QSize(32, 32)) - self.toolbar.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon) - self.toolbar.setMovable(False) - action = QAction(self.style().standardIcon(QStyle.StandardPixmap.SP_FileDialogNewFolder), _tr('Install new game'), self) - action.triggered.connect(self.install_game) - self.toolbar.addAction(action) - action = QAction(self.style().standardIcon(QStyle.StandardPixmap.SP_FileLinkIcon), _tr('Add game entry'), self) - action.triggered.connect(self.add_game) - self.toolbar.addAction(action) - action = QAction(self.style().standardIcon(QStyle.StandardPixmap.SP_BrowserReload), _tr('Reload list'), self) - action.triggered.connect(self.reload_list) - self.toolbar.addAction(action) - action = QAction(self.style().standardIcon(QStyle.StandardPixmap.SP_TrashIcon), _tr('Drop install prefix'), self) - action.triggered.connect(self.drop_prefix) - self.toolbar.addAction(action) - spacer = QWidget(self) - spacer.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) - self.toolbar.addWidget(spacer) - action = QAction(pp_icon, 'PortProton', self) - action.triggered.connect(self.run_pp) - self.toolbar.addAction(action) - - def install_game(self): - InstallGame(self) - - def add_game(self): - InstallGame(self, False) - - def reload_list(self): - self.game_list.reload() - - def drop_prefix(self): - res = QMessageBox.question(self, _tr('Are you sure ?'), _tr('Do you really want to remove
{0} ?', g.install_pfx)) - if res == QMessageBox.StandardButton.Yes: - shutil.rmtree(g.install_pfx, True) - - def run_pp(self): - self.setDisabled(True) - app.processEvents() - run([g.scripts_dir + '/start.sh']) - self.setDisabled(False) - - def set_status(self, item): - self.statusBar().setVisible(bool(item)) - if item: - self._status_size.setText('Size: ' + item.dir_size_human) - self._status_dir.setText(' ' + item.game_dir) - self._status_wine.setText(item.wine_use) - - def closeEvent(self, event): - geometry = self.saveGeometry() - settings.setValue('geometry_main', geometry) - super().closeEvent(event) - -class LoadListThread(QThread): - completed = pyqtSignal(list) - def __init__(self, parent, install_dir): - super().__init__(parent) - self.install_dir = install_dir - def run(self): - exe_list = list(Path(self.install_dir).glob('**/*.exe')) - self.completed.emit(exe_list) - -class InstallGame(QDialog): - def __init__(self, parent, installing=True): - super().__init__(parent) - self._installing = installing - self.install_dir = g.install_pfx + '/drive_c/Games' if installing else g.games_dir - self._exe_list_widget = QListWidget(self) - self._exe_list_widget.setIconSize(QSize(16, 16)) - self._exe_list_widget.itemDoubleClicked.connect(self._handleDoubleClick) - layout = QVBoxLayout() - layout.addWidget(self._exe_list_widget) - - self._pbar = QProgressBar(self) - self._pbar.setMaximum(0) - layout.addWidget(self._pbar) - thread = LoadListThread(self, self.install_dir) - thread.completed.connect(self.load) - thread.start() - - if self._installing: - setup_btn = QPushButton(self) - setup_btn.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_FileDialogStart)) - setup_btn.setText(_tr('Run another setup')) - setup_btn.clicked.connect(self._runSetup) - layout.addWidget(setup_btn) - self.setLayout(layout) - self.resize(400, 300) - self.setModal(True) - self.setWindowTitle(_tr('Select game exe file')) - geometry = settings.value('geometry_install') - if geometry: - self.restoreGeometry(geometry) - self.show() - - def load(self, exe_list): - if self._installing and len(exe_list) == 0: - self._runSetup() - exe_list = list(Path(self.install_dir).glob('**/*.exe')) - if len(exe_list) == 0: - return self.close() - def render_list(): - pixmap = QPixmap(16, 16) - pixmap.fill(Qt.GlobalColor.transparent) - empty_icon = QIcon(pixmap) - for exe in sorted(exe_list): - ico_file = str(exe) + '.ico' - item = QListWidgetItem(self._exe_list_widget) - item.setText(str(exe)[len(self.install_dir)+1:]) - try: - if not Path(ico_file).exists(): - run(['wrestool', '-x', '-t14', '-o', ico_file, exe], capture_output=True) - item.setIcon(QIcon(ico_file)) - except Exception: - pass - if item.icon().pixmap(16, 16).isNull(): - item.setIcon(empty_icon) - self._exe_list_widget.addItem(item) - self._pbar.setVisible(False) - thread = QThread(self) - thread.run = render_list - thread.start() - - def _runSetup(self): - downloads_dir = QStandardPaths.writableLocation(QStandardPaths.StandardLocation.DownloadLocation) - exe_file, _ = QFileDialog.getOpenFileName(self, caption=_tr('Choose setup file'), filter='Exe files (*.exe)', directory=downloads_dir) - if not exe_file: - return - ppdb = shlex.quote(exe_file + '.ppdb') - script = f""" - mkdir -p {shlex.quote(g.install_pfx + '/drive_c/Games')} - echo ' - export PW_VULKAN_USE=1 - export PW_GUI_DISABLED_CS=1 - export PW_PREFIX_NAME=INSTALL - export PW_DLL_INSTALL=mfc42 - ' > {ppdb} - {shlex.quote(g.scripts_dir + '/start.sh')} {shlex.quote(exe_file)} - rm -f {ppdb} - """ - self.setDisabled(True) - app.processEvents() - run(['bash', '-c', script]) - self.setDisabled(False) - - def _handleDoubleClick(self, item): - game_dir = item.text().split('/')[0] - dlg = QInputDialog(self) - dlg.setWindowTitle(_tr('Please enter game entry name')) - dlg.setLabelText(_tr('New game entry')) - dlg.setTextValue(game_dir) - dlg.resize(300, 0) - ok = dlg.exec() - shortcut_name = dlg.textValue() - if not ok or not shortcut_name: - return - file_name = re.sub(r'[<>:/\\|?*]', '_', shortcut_name) - shortcut = f"{g.shortcuts_dir}/{file_name}.desktop" - if Path(shortcut).exists(): - res = QMessageBox.question(self, _tr('Shortcut already exists'), _tr('Shortcut {0} already exists. Overwrite ?', file_name)) - if res != QMessageBox.StandardButton.Yes: - return - src_dir = self.install_dir + '/' + game_dir - dst_dir = g.games_dir + '/' + game_dir - exe_file = shlex.quote(g.games_dir + '/' + item.text()) - ppdb = shlex.quote(g.games_dir + '/' + item.text() + '.ppdb') - self.setDisabled(True) - if self._installing and Path(dst_dir).exists(): - res = QMessageBox.question(self, _tr('Dir already exists'), _tr('Dir {0} already exists. Overwrite ?', game_dir)) - if res != QMessageBox.StandardButton.Yes: - return - if self._installing: - os.rename(src_dir, dst_dir) - script = f""" - export INSTALLING_PORT=1 - export portwine_exe={exe_file} - cd {shlex.quote(g.scripts_dir)} - . {shlex.quote(g.scripts_dir + '/runlib')} - pw_init_db - [ -f {ppdb} ] && . {ppdb} - echo -e "export PW_VULKAN_USE=${{PW_VULKAN_USE:-1}}\nexport PW_GUI_DISABLED_CS=1" >> {ppdb} - """ - run(['bash', '-c', script]) - icon_path = g.games_dir + '/' + item.text() + '.ico' - if not Path(icon_path).exists(): - icon_path = g.pp_icon - Path(shortcut).write_text(f"""[Desktop Entry] -Name={shortcut_name} -Exec=env {shlex.quote(g.scripts_dir + '/start.sh')} {exe_file} -Type=Application -Categories=Game -StartupNotify=true -Path={shlex.quote(g.scripts_dir)} -Icon={icon_path} -""", encoding='utf-8') - os.chmod(shortcut, 0o755) - win.reload_list() - self.close() - - def closeEvent(self, event): - geometry = self.saveGeometry() - settings.setValue('geometry_install', geometry) - super().closeEvent(event) - - -class GameList(QListWidget): - def __init__(self, parent): - super().__init__(parent) - self.itemActivated.connect(self.runGame) - self.currentItemChanged.connect(self.selectItem) - self.setViewMode(QListWidget.ViewMode.IconMode) - self.setResizeMode(QListWidget.ResizeMode.Adjust) - self.setIconSize(QSize(64, 64)) - self.setWordWrap(True) - self.setSpacing(3) - self.reload() - - def reload(self): - self.clear() - shortcuts = list(Path(g.shortcuts_dir).glob('*.desktop')) - shortcuts += list(Path(g.base_dir).glob('*.desktop')) - for shortcut in shortcuts: - try: - item = GameItem(self, shortcut) - self.addItem(item) - except ValueError: - pass - except: - logging.exception('Error while parse "%s"', shortcut) - self.sortItems() - self.setCurrentIndex(QModelIndex()) - - def runGame(self, item): - win.setDisabled(True) - app.processEvents() - run(['bash', '-c', item.get('Exec')]) - win.setDisabled(False) - - def selectItem(self, item): - win.set_status(item) - - def contextMenuEvent(self, event): - selected = self.selectedItems() - if len(selected) == 0: - return - selected = selected[0] - menu = QMenu(self) - desktop = menu.addAction(self.style().standardIcon(QStyle.StandardPixmap.SP_DesktopIcon), _tr('Add to desktop')) - restore_gui = menu.addAction(self.style().standardIcon(QStyle.StandardPixmap.SP_DialogResetButton), _tr('Restore PortProton GUI')) - default_wine = menu.addAction(self.style().standardIcon(QStyle.StandardPixmap.SP_DialogOkButton), _tr('Set default wine')) - remove = menu.addAction(self.style().standardIcon(QStyle.StandardPixmap.SP_TrashIcon), _tr('Remove game entry')) - uninstall = menu.addAction(self.style().standardIcon(QStyle.StandardPixmap.SP_DialogCloseButton), _tr('Uninstall game')) - if not selected.pp_gui_disabled: - restore_gui.setVisible(False) - if not selected.wine_use: - default_wine.setVisible(False) - if not selected.game_dir.startswith(g.games_dir): - uninstall.setVisible(False) - action = menu.exec(self.mapToGlobal(event.pos())) - desktop_shortcut = QStandardPaths.writableLocation(QStandardPaths.StandardLocation.DesktopLocation) + '/' + Path(selected.desktop_file).name - if action == desktop: - if Path(desktop_shortcut).exists(): - res = QMessageBox.question(self, _tr('Shortcut already exists'), _tr('Shortcut {0} already exists. Overwrite ?', desktop_shortcut)) - if res != QMessageBox.StandardButton.Yes: - return - shutil.copy(selected.desktop_file, desktop_shortcut) - if action == restore_gui or action == default_wine: - ignore_line = 'PW_GUI_DISABLED_CS' if action == restore_gui else 'PW_WINE_USE' - ppdb = shlex.split(selected.get('Exec'))[-1] + '.ppdb' - if not Path(ppdb).exists(): - return - with open(ppdb, 'r') as read: - with open(ppdb + '.new', 'w') as write: - while (line := read.readline()): - if ignore_line not in line: - write.write(line) - os.rename(ppdb + '.new', ppdb) - if action == restore_gui: - selected.pp_gui_disabled = False - if action == default_wine: - selected.wine_use = None - self.selectItem(selected) - def remove_shortcut(): - Path(desktop_shortcut).unlink(True) - Path(selected.desktop_file).unlink(True) - def_icon_path = g.base_dir + '/data/img/' + Path(shlex.split(selected.get('Exec'))[-1]).stem + '.png' - Path(def_icon_path).unlink(True) - if action == remove: - remove_shortcut() - self.reload() - if action == uninstall: - res = QMessageBox.question(self, - _tr('Are you sure ?'), - _tr('Do you really want to uninstall {0}
located in "{1}" ?', selected.get('Name'), selected.game_dir) - ) - if res != QMessageBox.StandardButton.Yes: - return - remove_shortcut() - if selected.game_dir.startswith(g.games_dir): - shutil.rmtree(selected.game_dir, True) - self.reload() - - -def human_size(num): - if not num: - return "-" - for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: - if abs(num) < 1024.0: - return f"{num:.2f} {unit}B" - num /= 1024.0 - return f"{num:.2f} YiB" - -class GameItem(QListWidgetItem): - def __init__(self, parent, desktop_file): - self.desktop_file = desktop_file - self.config = RawConfigParser() - self.config.read(desktop_file) - text = self.get('Name', Path(desktop_file).stem) - if not self.get('Exec') or text == 'PortProton': - raise ValueError('Validation fail') - exe_file = shlex.split(self.get('Exec'))[-1] - if exe_file.startswith(g.games_dir): - self.game_dir = g.games_dir + '/' + exe_file[len(g.games_dir)+1:].split('/')[0] - else: - self.game_dir = str(Path(exe_file).parent) - if self.game_dir == '.': - raise ValueError('Can not determine game dir') - self.pp_gui_disabled = False - self.wine_use = None - ppdb = exe_file + '.ppdb' - if Path(ppdb).exists(): - ppdb_conf = RawConfigParser(strict=False) - with open(ppdb) as f: - ppdb_conf.read_string('[dummy]\n' + f.read()) - pp_gui_disabled = ppdb_conf.get('dummy', 'export PW_GUI_DISABLED_CS', fallback='').strip('"') - try: self.pp_gui_disabled = bool(int(pp_gui_disabled)) - except: self.pp_gui_disabled = bool(pp_gui_disabled) - self.wine_use = ppdb_conf.get('dummy', 'export PW_WINE_USE', fallback='').strip('"') - - super().__init__(parent) - - self.setToolTip(text) - self.setText(text) - icon_path = self.get('Icon') if Path(self.get('Icon')).exists() else g.pp_icon - qicon = QIcon(icon_path) - self.setIcon(qicon) - self.setTextAlignment(Qt.AlignmentFlag.AlignHCenter | Qt.AlignmentFlag.AlignTop) - self.setSizeHint(QSize(100, 105)) - - self._set_dir_size(None) - dir_size_cache = self.game_dir + '/.size' - if Path(dir_size_cache).exists(): - self._set_dir_size(int(Path(dir_size_cache).read_text())) - else: - def calc_dir_size(): - if not Path(self.game_dir).exists(): - return - dir_size = sum(p.stat(follow_symlinks=False).st_size for p in Path(self.game_dir).rglob('*')) - self._set_dir_size(dir_size) - Path(dir_size_cache).write_text(str(dir_size)) - thread = QThread(parent) - thread.run = calc_dir_size - thread.start() - - def get(self, name, fallback=None): - return self.config.get('Desktop Entry', name, fallback=fallback) - - def _set_dir_size(self, size): - self.dir_size = size - self.dir_size_human = human_size(size) - -import signal -signal.signal(signal.SIGINT, signal.SIG_DFL) - -lang = { - 'RUS': { - 'Install new game': 'Установить игру', - 'Add game entry': 'Добавить в список', - 'Reload list': 'Обновить список', - 'Drop install prefix': 'Удалить установочный префикс', - 'Are you sure ?': 'Вы уверены ?', - 'Do you really want to remove
{0} ?': 'Вы действительно хотите удалить
{0} ?', - 'Run another setup': 'Запустить установку', - 'Select game exe file': 'Выберите exe файл игры', - 'Choose setup file': 'Выберите установочный файл', - 'Please enter game entry name': 'Введите название игры', - 'New game entry': 'Название игры', - 'Shortcut already exists': 'Ярлык уже существует', - 'Shortcut {0} already exists. Overwrite ?': 'Ярлык {0} уже существует. Перезаписать ?', - 'Dir already exists': 'Директория уже существует', - 'Dir {0} already exists. Overwrite ?': 'Директория {0} уже существует. Перезаписать ?', - 'Add to desktop': 'Добавить на рабочий стол', - 'Restore PortProton GUI': 'Восстановить PortProton GUI', - 'Set default wine': 'Выбрать дефолтный wine', - 'Remove game entry': 'Убрать из списка', - 'Uninstall game': 'Удалить игру', - 'Do you really want to uninstall {0}
located in "{1}" ?': 'Вы действительно хотите удалить {0}
расположеную в "{1}" ?' - } -} -def _tr(text, *fmt): - res = lang.get(g.locale, {}).get(text, text) - if fmt: - res = res.format(*fmt) - return res - -app = QApplication([]) -app.setDesktopFileName('PortProton') -win = MainWindow() -win.show() -app.exec()