Compare commits
16 Commits
1a8c733580
...
v0.1.4
Author | SHA1 | Date | |
---|---|---|---|
85e9aba836
|
|||
4d3499d2c1
|
|||
a13c15bc28
|
|||
83076d3dfc
|
|||
04aaf68e36
|
|||
e91037708a
|
|||
1b743026c2
|
|||
30b4cec4d1
|
|||
db68c9050c
|
|||
1a93d5b82c
|
|||
cc0690cf9e
|
|||
809ba2c976
|
|||
68c9636e10
|
|||
f0df1f89be
|
|||
f25224b668
|
|||
0cda47fdfd
|
@@ -17,10 +17,12 @@ jobs:
|
|||||||
- name: Install required dependencies
|
- name: Install required dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y binutils coreutils desktop-file-utils gtk-update-icon-cache fakeroot fuse libgdk-pixbuf2.0-dev patchelf python3-pip python3-dev python3-setuptools squashfs-tools strace util-linux zsync
|
sudo apt install -y binutils coreutils desktop-file-utils gtk-update-icon-cache fakeroot fuse libgdk-pixbuf2.0-dev patchelf python3-pip python3-dev python3-setuptools squashfs-tools strace util-linux zsync git
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: pip3 install appimage-builder uv
|
run: |
|
||||||
|
pip3 install git+https://github.com/Frederic98/appimage-builder.git
|
||||||
|
pip3 install uv
|
||||||
|
|
||||||
- name: Build AppImage
|
- name: Build AppImage
|
||||||
run: |
|
run: |
|
||||||
|
@@ -8,7 +8,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
# Common version, will be used for tagging the release
|
# Common version, will be used for tagging the release
|
||||||
VERSION: 0.1.3
|
VERSION: 0.1.4
|
||||||
PKGDEST: "/tmp/portprotonqt"
|
PKGDEST: "/tmp/portprotonqt"
|
||||||
PACKAGE: "portprotonqt"
|
PACKAGE: "portprotonqt"
|
||||||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
@@ -23,10 +23,12 @@ jobs:
|
|||||||
- name: Install required dependencies
|
- name: Install required dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -y binutils coreutils desktop-file-utils gtk-update-icon-cache fakeroot fuse libgdk-pixbuf2.0-dev patchelf python3-pip python3-dev python3-setuptools squashfs-tools strace util-linux zsync
|
sudo apt install -y binutils coreutils desktop-file-utils gtk-update-icon-cache fakeroot fuse libgdk-pixbuf2.0-dev patchelf python3-pip python3-dev python3-setuptools squashfs-tools strace util-linux zsync git
|
||||||
|
|
||||||
- name: Install tools
|
- name: Install tools
|
||||||
run: pip3 install appimage-builder uv
|
run: |
|
||||||
|
pip3 install git+https://github.com/Frederic98/appimage-builder.git
|
||||||
|
pip3 install uv
|
||||||
|
|
||||||
- name: Build AppImage
|
- name: Build AppImage
|
||||||
run: |
|
run: |
|
||||||
|
187
.gitea/workflows/code-build.yml
Normal file
187
.gitea/workflows/code-build.yml
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
name: Build Check - AppImage, Arch, Fedora
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'build-aux/**'
|
||||||
|
|
||||||
|
env:
|
||||||
|
PKGDEST: "/tmp/portprotonqt"
|
||||||
|
PACKAGE: "portprotonqt"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
changes:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
appimage: ${{ steps.check.outputs.appimage }}
|
||||||
|
fedora: ${{ steps.check.outputs.fedora }}
|
||||||
|
arch: ${{ steps.check.outputs.arch }}
|
||||||
|
steps:
|
||||||
|
- uses: https://gitea.com/actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Ensure git is installed
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y git
|
||||||
|
|
||||||
|
- name: Check changed files
|
||||||
|
id: check
|
||||||
|
run: |
|
||||||
|
# Get changed files
|
||||||
|
git diff --name-only ${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }} > changed_files.txt
|
||||||
|
|
||||||
|
echo "Changed files:"
|
||||||
|
cat changed_files.txt
|
||||||
|
|
||||||
|
# Check AppImage files
|
||||||
|
if grep -q "build-aux/AppImageBuilder.yml" changed_files.txt; then
|
||||||
|
echo "appimage=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "appimage=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Fedora spec files (only fedora-git.spec)
|
||||||
|
if grep -q "build-aux/fedora-git.spec" changed_files.txt; then
|
||||||
|
echo "fedora=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "fedora=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check Arch PKGBUILD-git
|
||||||
|
if grep -q "build-aux/PKGBUILD-git" changed_files.txt; then
|
||||||
|
echo "arch=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "arch=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
build-appimage:
|
||||||
|
name: Build AppImage
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.appimage == 'true' || github.event_name == 'workflow_dispatch'
|
||||||
|
steps:
|
||||||
|
- uses: https://gitea.com/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install required dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y binutils coreutils desktop-file-utils gtk-update-icon-cache fakeroot fuse libgdk-pixbuf2.0-dev patchelf python3-pip python3-dev python3-setuptools squashfs-tools strace util-linux zsync git
|
||||||
|
|
||||||
|
- name: Install tools
|
||||||
|
run: |
|
||||||
|
pip3 install git+https://github.com/Frederic98/appimage-builder.git
|
||||||
|
pip3 install uv
|
||||||
|
|
||||||
|
- name: Build AppImage
|
||||||
|
run: |
|
||||||
|
cd build-aux
|
||||||
|
appimage-builder
|
||||||
|
|
||||||
|
- name: Upload AppImage
|
||||||
|
uses: https://gitea.com/actions/gitea-upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: PortProtonQt-AppImage
|
||||||
|
path: build-aux/PortProtonQt*.AppImage
|
||||||
|
|
||||||
|
build-fedora:
|
||||||
|
name: Build Fedora RPM
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.fedora == 'true' || github.event_name == 'workflow_dispatch'
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
fedora_version: [41, 42, rawhide]
|
||||||
|
|
||||||
|
container:
|
||||||
|
image: fedora:${{ matrix.fedora_version }}
|
||||||
|
options: --privileged
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Install build dependencies
|
||||||
|
run: |
|
||||||
|
dnf install -y git rpmdevtools python3-devel python3-wheel python3-pip \
|
||||||
|
python3-build pyproject-rpm-macros python3-setuptools \
|
||||||
|
redhat-rpm-config nodejs npm
|
||||||
|
|
||||||
|
- name: Setup rpmbuild environment
|
||||||
|
run: |
|
||||||
|
useradd rpmbuild -u 5002 -g users || true
|
||||||
|
mkdir -p /home/rpmbuild/{BUILD,RPMS,SPECS,SRPMS,SOURCES}
|
||||||
|
chown -R rpmbuild:users /home/rpmbuild
|
||||||
|
echo '%_topdir /home/rpmbuild' > /home/rpmbuild/.rpmmacros
|
||||||
|
|
||||||
|
- name: Checkout repo
|
||||||
|
uses: https://gitea.com/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Copy fedora-git.spec
|
||||||
|
run: |
|
||||||
|
cp build-aux/fedora-git.spec /home/rpmbuild/SPECS/${{ env.PACKAGE }}.spec
|
||||||
|
chown -R rpmbuild:users /home/rpmbuild
|
||||||
|
|
||||||
|
- name: Build RPM
|
||||||
|
run: |
|
||||||
|
su rpmbuild -c "rpmbuild -ba /home/rpmbuild/SPECS/${{ env.PACKAGE }}.spec"
|
||||||
|
|
||||||
|
- name: Upload RPM package
|
||||||
|
uses: https://gitea.com/actions/gitea-upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: PortProtonQt-RPM-Fedora-${{ matrix.fedora_version }}
|
||||||
|
path: /home/rpmbuild/RPMS/**/*.rpm
|
||||||
|
|
||||||
|
build-arch:
|
||||||
|
name: Build Arch Package
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.arch == 'true' || github.event_name == 'workflow_dispatch'
|
||||||
|
container:
|
||||||
|
image: archlinux:base-devel
|
||||||
|
volumes:
|
||||||
|
- /usr:/usr-host
|
||||||
|
- /opt:/opt-host
|
||||||
|
options: --privileged
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Prepare container
|
||||||
|
run: |
|
||||||
|
pacman -Sy --noconfirm --disable-download-timeout --needed git wget gnupg nodejs npm
|
||||||
|
sed -i 's/#MAKEFLAGS="-j2"/MAKEFLAGS="-j$(nproc) -l$(nproc)"/g' /etc/makepkg.conf
|
||||||
|
sed -i 's/OPTIONS=(.*)/OPTIONS=(strip docs !libtool !staticlibs emptydirs zipman purge lto)/g' /etc/makepkg.conf
|
||||||
|
yes | pacman -Scc
|
||||||
|
pacman-key --init
|
||||||
|
pacman -S --noconfirm archlinux-keyring
|
||||||
|
mkdir -p /__w/portproton-repo
|
||||||
|
pacman-key --recv-key 3056513887B78AEB --keyserver keyserver.ubuntu.com
|
||||||
|
pacman-key --lsign-key 3056513887B78AEB
|
||||||
|
pacman -U --noconfirm 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst'
|
||||||
|
pacman -U --noconfirm 'https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst'
|
||||||
|
cat << EOM >> /etc/pacman.conf
|
||||||
|
|
||||||
|
[chaotic-aur]
|
||||||
|
Include = /etc/pacman.d/chaotic-mirrorlist
|
||||||
|
EOM
|
||||||
|
pacman -Syy
|
||||||
|
useradd -m user -G wheel && echo "user ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||||
|
echo "PACKAGER=\"Boris Yumankulov <boria138@altlinux.org>\"" >> /etc/makepkg.conf
|
||||||
|
chown user -R /tmp
|
||||||
|
chown user -R ..
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: |
|
||||||
|
cd /__w/portproton-repo
|
||||||
|
git clone https://git.linux-gaming.ru/Boria138/PortProtonQt.git
|
||||||
|
cd /__w/portproton-repo/PortProtonQt/build-aux
|
||||||
|
chown user -R ..
|
||||||
|
su user -c "yes '' | makepkg --noconfirm -s -p PKGBUILD-git"
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
uses: https://gitea.com/actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Upload Arch package
|
||||||
|
uses: https://gitea.com/actions/gitea-upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: PortProtonQt-Arch
|
||||||
|
path: ${{ env.PKGDEST }}/*
|
@@ -1,4 +1,4 @@
|
|||||||
name: Code and build check
|
name: Code check
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
@@ -35,20 +35,3 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
source .venv/bin/activate
|
source .venv/bin/activate
|
||||||
pre-commit run --show-diff-on-failure --color=always --all-files
|
pre-commit run --show-diff-on-failure --color=always --all-files
|
||||||
|
|
||||||
build-uv:
|
|
||||||
name: Build with uv
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: https://gitea.com/actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Install uv
|
|
||||||
uses: https://github.com/astral-sh/setup-uv@v6
|
|
||||||
with:
|
|
||||||
enable-cache: true
|
|
||||||
|
|
||||||
- name: Sync dependencies
|
|
||||||
run: uv sync
|
|
||||||
|
|
||||||
- name: Build project
|
|
||||||
run: uv build
|
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
Все заметные изменения в этом проекте фиксируются в этом файле.
|
Все заметные изменения в этом проекте фиксируются в этом файле.
|
||||||
Формат основан на [Keep a Changelog](https://keepachangelog.com/) и придерживается принципов [Semantic Versioning](https://semver.org/).
|
Формат основан на [Keep a Changelog](https://keepachangelog.com/) и придерживается принципов [Semantic Versioning](https://semver.org/).
|
||||||
|
|
||||||
## [Unreleased]
|
## [0.1.4] - 2025-07-21
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
- Переводы в переопределениях (за подробностями в документацию)
|
- Переводы в переопределениях (за подробностями в документацию)
|
||||||
@@ -15,10 +15,15 @@
|
|||||||
- Оптимизированны обложки автоинсталлов
|
- Оптимизированны обложки автоинсталлов
|
||||||
- Папка custom_data исключена из сборки модуля для уменьшение его размера
|
- Папка custom_data исключена из сборки модуля для уменьшение его размера
|
||||||
- Бейдж PortProton теперь открывает PortProtonDB
|
- Бейдж PortProton теперь открывает PortProtonDB
|
||||||
|
- Отключено переключение полноэкранного режима через F11 или кнопку Select на геймпаде в gamescope сессии
|
||||||
|
- Удалён аргумент `--session` так как тестирование gamescope сессии завершено
|
||||||
|
- В контекстном меню игр без exe файла теперь отображается только пункт "Удалить из PortProton"
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Запрос к GitHub API при загрузке legendary теперь не игнорирует настройки прокси
|
- Запрос к GitHub API при загрузке legendary теперь не игнорирует настройки прокси
|
||||||
- Путь к portprotonqt-session-select в оверлее
|
- Путь к portprotonqt-session-select в оверлее
|
||||||
|
- Работа exiftool в AppImage
|
||||||
|
- Открытие контекстного меню у игр без exe
|
||||||
|
|
||||||
### Contributors
|
### Contributors
|
||||||
- @Vector_null
|
- @Vector_null
|
||||||
|
@@ -51,11 +51,11 @@ pre-commit run --all-files
|
|||||||
|
|
||||||
PortProtonQt использует код и зависимости от следующих проектов:
|
PortProtonQt использует код и зависимости от следующих проектов:
|
||||||
|
|
||||||
- [Legendary](https://github.com/derrod/legendary) — инструмент для работы с Epic Games Store, лицензия [GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html).
|
- [Legendary](https://github.com/derrod/legendary) — инструмент для работы с Epic Games Store, лицензия [GPL-3.0](https://github.com/derrod/legendary/blob/master/LICENSE).
|
||||||
- [Icoextract](https://github.com/jlu5/icoextract) — библиотека для извлечения иконок, лицензия [MIT](https://opensource.org/licenses/MIT).
|
- [Icoextract](https://github.com/jlu5/icoextract) — библиотека для извлечения иконок, лицензия [MIT](https://github.com/jlu5/icoextract/blob/master/LICENSE).
|
||||||
- [PortProton 2.0](https://git.linux-gaming.ru/CastroFidel/PortProton_2.0) — библиотека для взаимодействия с PortProton, лицензия [MIT](https://opensource.org/licenses/MIT).
|
- [HowLongToBeat Python API](https://github.com/ScrappyCocco/HowLongToBeat-PythonAPI) — библиотека для взаимодействия с HowLongToBeat, лицензия [MIT](https://github.com/ScrappyCocco/HowLongToBeat-PythonAPI/blob/master/LICENSE.md).
|
||||||
|
|
||||||
Полный текст лицензий см. в файлах [LICENSE](LICENSE), [LICENSE-icoextract](documentation/licenses/icoextract), [LICENSE-portproton](documentation/licenses/portproton), [LICENSE-legendary](documentation/licenses/legendary).
|
Полный текст лицензий см. в файле [LICENSE](LICENSE).
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> Проект находится на стадии WIP (work in progress) корректная работоспособность не гарантирована
|
> Проект находится на стадии WIP (work in progress) корректная работоспособность не гарантирована
|
||||||
|
4
TODO.md
4
TODO.md
@@ -17,7 +17,6 @@
|
|||||||
- [ ] Убрать логи Steam API в релизной версии, так как они замедляют выполнение кода
|
- [ ] Убрать логи Steam API в релизной версии, так как они замедляют выполнение кода
|
||||||
- [X] Решить проблему с ограничением Steam API в 50 тысяч игр за один запрос (иногда нужные игры не попадают в выборку и остаются без обложки)
|
- [X] Решить проблему с ограничением Steam API в 50 тысяч игр за один запрос (иногда нужные игры не попадают в выборку и остаются без обложки)
|
||||||
- [X] Избавиться от вызовов yad
|
- [X] Избавиться от вызовов yad
|
||||||
- [ ] Реализовать собственный механизм запрета ухода в спящий режим вместо использования механизма PortProton
|
|
||||||
- [X] Реализовать собственный системный трей вместо использования трея PortProton
|
- [X] Реализовать собственный системный трей вместо использования трея PortProton
|
||||||
- [X] Добавить экранную клавиатуру в поиск (реализация собственной клавиатуры слишком затратна, поэтому используется встроенная в DE клавиатура: Maliit в KDE, gjs-osk в GNOME, Squeekboard в Phosh, клавиатура SteamOS и т.д.)
|
- [X] Добавить экранную клавиатуру в поиск (реализация собственной клавиатуры слишком затратна, поэтому используется встроенная в DE клавиатура: Maliit в KDE, gjs-osk в GNOME, Squeekboard в Phosh, клавиатура SteamOS и т.д.)
|
||||||
- [X] Добавить сортировку карточек по различным критериям (доступны: по недавности, количеству наигранного времени, избранному или алфавиту)
|
- [X] Добавить сортировку карточек по различным критериям (доступны: по недавности, количеству наигранного времени, избранному или алфавиту)
|
||||||
@@ -42,7 +41,7 @@
|
|||||||
- [X] Получать slug через GraphQL [запрос](https://launcher.store.epicgames.com/graphql)
|
- [X] Получать slug через GraphQL [запрос](https://launcher.store.epicgames.com/graphql)
|
||||||
- [X] Добавить на карточку бейдж, указывающий, что игра из Steam
|
- [X] Добавить на карточку бейдж, указывающий, что игра из Steam
|
||||||
- [X] Добавить поддержку версий Steam для Flatpak и Snap
|
- [X] Добавить поддержку версий Steam для Flatpak и Snap
|
||||||
- [ ] Реализовать добавлление игры как сторонней в Steam без
|
- [ ] Реализовать добавление игры как сторонней в Steam без перезапуска
|
||||||
- [X] Отображать данные о самом последнем пользователе Steam, а не первом попавшемся
|
- [X] Отображать данные о самом последнем пользователе Steam, а не первом попавшемся
|
||||||
- [X] Исправить склонения в детальном выводе времени, например, не «3 часов назад», а «3 часа назад»
|
- [X] Исправить склонения в детальном выводе времени, например, не «3 часов назад», а «3 часа назад»
|
||||||
- [X] Добавить перевод через gettext [Документация](documentation/localization_guide)
|
- [X] Добавить перевод через gettext [Документация](documentation/localization_guide)
|
||||||
@@ -65,6 +64,5 @@
|
|||||||
- [X] Скопировать логику управления с D-pad на стрелки с клавиатуры
|
- [X] Скопировать логику управления с D-pad на стрелки с клавиатуры
|
||||||
- [ ] Доделать светлую тему
|
- [ ] Доделать светлую тему
|
||||||
- [ ] Добавить подсказки к управлению с геймпада
|
- [ ] Добавить подсказки к управлению с геймпада
|
||||||
- [ ] Добавить загрузку звуков в темы например для добавления звука запуска в тему и тд
|
|
||||||
- [X] Добавить миниатюры к выбору файлов в диалоге добавления игры
|
- [X] Добавить миниатюры к выбору файлов в диалоге добавления игры
|
||||||
- [X] Добавить быстрый доступ к смонтированным дискам к выбору файлов в диалоге добавления игры
|
- [X] Добавить быстрый доступ к смонтированным дискам к выбору файлов в диалоге добавления игры
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
version: 1
|
version: 1
|
||||||
|
|
||||||
script:
|
script:
|
||||||
# 1) чистим старый AppDir
|
# 1) чистим старый AppDir
|
||||||
- rm -rf AppDir || true
|
- rm -rf AppDir || true
|
||||||
@@ -17,26 +16,45 @@ script:
|
|||||||
- rm -f AppDir/usr/local/lib/python3.10/dist-packages/PySide6/{Qt3D*,QtBluetooth*,QtCharts*,QtConcurrent*,QtDataVisualization*,QtDesigner*,QtHelp*,QtMultimedia*,QtNetwork*,QtOpenGL*,QtPositioning*,QtPrintSupport*,QtQml*,QtQuick*,QtRemoteObjects*,QtScxml*,QtSensors*,QtSerialPort*,QtSql*,QtStateMachine*,QtTest*,QtWeb*,QtXml*}
|
- rm -f AppDir/usr/local/lib/python3.10/dist-packages/PySide6/{Qt3D*,QtBluetooth*,QtCharts*,QtConcurrent*,QtDataVisualization*,QtDesigner*,QtHelp*,QtMultimedia*,QtNetwork*,QtOpenGL*,QtPositioning*,QtPrintSupport*,QtQml*,QtQuick*,QtRemoteObjects*,QtScxml*,QtSensors*,QtSerialPort*,QtSql*,QtStateMachine*,QtTest*,QtWeb*,QtXml*}
|
||||||
- shopt -s extglob
|
- shopt -s extglob
|
||||||
- rm -rf AppDir/usr/local/lib/python3.10/dist-packages/PySide6/Qt/lib/!(libQt6Core*|libQt6Gui*|libQt6Widgets*|libQt6OpenGL*|libQt6XcbQpa*|libQt6Wayland*|libQt6Egl*|libicudata*|libicuuc*|libicui18n*|libQt6DBus*|libQt6Svg*|libQt6Qml*|libQt6Network*)
|
- rm -rf AppDir/usr/local/lib/python3.10/dist-packages/PySide6/Qt/lib/!(libQt6Core*|libQt6Gui*|libQt6Widgets*|libQt6OpenGL*|libQt6XcbQpa*|libQt6Wayland*|libQt6Egl*|libicudata*|libicuuc*|libicui18n*|libQt6DBus*|libQt6Svg*|libQt6Qml*|libQt6Network*)
|
||||||
|
|
||||||
AppDir:
|
AppDir:
|
||||||
path: ./AppDir
|
path: ./AppDir
|
||||||
|
after_bundle:
|
||||||
|
# Документация, справка, примеры
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/man || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/doc || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/doc-base || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/info || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/help || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/gtk-doc || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/devhelp || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/examples || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/pkgconfig || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/bash-completion || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/pixmaps || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/mime || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/share/metainfo || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/include || true
|
||||||
|
- rm -rf $TARGET_APPDIR/usr/lib/pkgconfig || true
|
||||||
|
# Статика и отладка
|
||||||
|
- find $TARGET_APPDIR -type f \( -name '*.a' -o -name '*.la' -o -name '*.h' -o -name '*.cmake' -o -name '*.pdb' \) -delete || true
|
||||||
|
# Strip ELF бинарников (исключая Python extensions)
|
||||||
|
- "find $TARGET_APPDIR -type f -executable -exec file {} \\; | grep ELF | grep -v '/dist-packages/' | grep -v '/site-packages/' | cut -d: -f1 | xargs strip --strip-unneeded || true"
|
||||||
|
# Удаление пустых папок
|
||||||
|
- find $TARGET_APPDIR -type d -empty -delete || true
|
||||||
app_info:
|
app_info:
|
||||||
id: ru.linux_gaming.PortProtonQt
|
id: ru.linux_gaming.PortProtonQt
|
||||||
name: PortProtonQt
|
name: PortProtonQt
|
||||||
icon: ru.linux_gaming.PortProtonQt
|
icon: ru.linux_gaming.PortProtonQt
|
||||||
version: 0.1.3
|
version: 0.1.4
|
||||||
exec: usr/bin/python3
|
exec: usr/bin/python3
|
||||||
exec_args: "-m portprotonqt.app $@"
|
exec_args: "-m portprotonqt.app $@"
|
||||||
|
|
||||||
apt:
|
apt:
|
||||||
arch: amd64
|
arch: amd64
|
||||||
sources:
|
sources:
|
||||||
- sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse'
|
- sourceline: 'deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse'
|
||||||
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
key_url: 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x871920d1991bc93c'
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- python3
|
- python3-minimal
|
||||||
- python3-pkg-resources
|
- python3-pkg-resources
|
||||||
- libopengl0
|
- libopengl0
|
||||||
- libk5crypto3
|
- libk5crypto3
|
||||||
@@ -45,13 +63,24 @@ AppDir:
|
|||||||
- libxcb-cursor0
|
- libxcb-cursor0
|
||||||
- libimage-exiftool-perl
|
- libimage-exiftool-perl
|
||||||
- xdg-utils
|
- xdg-utils
|
||||||
exclude: []
|
exclude:
|
||||||
|
# Документация и man-страницы
|
||||||
|
- "*-doc"
|
||||||
|
- "*-man"
|
||||||
|
- manpages
|
||||||
|
- mandb
|
||||||
|
# Статические библиотеки
|
||||||
|
- "*-dev"
|
||||||
|
- "*-static"
|
||||||
|
# Дебаг-символы
|
||||||
|
- "*-dbg"
|
||||||
|
- "*-dbgsym"
|
||||||
runtime:
|
runtime:
|
||||||
env:
|
env:
|
||||||
PYTHONHOME: '${APPDIR}/usr'
|
PYTHONHOME: '${APPDIR}/usr'
|
||||||
PYTHONPATH: '${APPDIR}/usr/local/lib/python3.10/dist-packages'
|
PYTHONPATH: '${APPDIR}/usr/local/lib/python3.10/dist-packages'
|
||||||
|
PERLLIB: '${APPDIR}/usr/share/perl5:${APPDIR}/usr/lib/x86_64-linux-gnu/perl/5.34:${APPDIR}/usr/share/perl/5.34'
|
||||||
AppImage:
|
AppImage:
|
||||||
sign-key: None
|
sign-key: None
|
||||||
|
comp: xz
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
pkgname=portprotonqt
|
pkgname=portprotonqt
|
||||||
pkgver=0.1.3
|
pkgver=0.1.4
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Modern GUI for managing and launching games from PortProton, Steam, and Epic Games Store"
|
pkgdesc="Modern GUI for managing and launching games from PortProton, Steam, and Epic Games Store"
|
||||||
arch=('any')
|
arch=('any')
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
%global pypi_name portprotonqt
|
%global pypi_name portprotonqt
|
||||||
%global pypi_version 0.1.3
|
%global pypi_version 0.1.4
|
||||||
%global oname PortProtonQt
|
%global oname PortProtonQt
|
||||||
%global _python_no_extras_requires 1
|
%global _python_no_extras_requires 1
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ _portprotonqt() {
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
if [[ "$cur" == -* ]]; then
|
if [[ "$cur" == -* ]]; then
|
||||||
COMPREPLY=( $( compgen -W '--fullscreen --session' -- "$cur" ) )
|
COMPREPLY=( $( compgen -W '--fullscreen' -- "$cur" ) )
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@@ -1,6 +1,4 @@
|
|||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
from PySide6.QtCore import QLocale, QTranslator, QLibraryInfo
|
from PySide6.QtCore import QLocale, QTranslator, QLibraryInfo
|
||||||
from PySide6.QtWidgets import QApplication
|
from PySide6.QtWidgets import QApplication
|
||||||
from PySide6.QtGui import QIcon
|
from PySide6.QtGui import QIcon
|
||||||
@@ -14,7 +12,7 @@ logger = get_logger(__name__)
|
|||||||
|
|
||||||
__app_id__ = "ru.linux_gaming.PortProtonQt"
|
__app_id__ = "ru.linux_gaming.PortProtonQt"
|
||||||
__app_name__ = "PortProtonQt"
|
__app_name__ = "PortProtonQt"
|
||||||
__app_version__ = "0.1.3"
|
__app_version__ = "0.1.4"
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
app = QApplication(sys.argv)
|
app = QApplication(sys.argv)
|
||||||
@@ -35,13 +33,6 @@ def main():
|
|||||||
|
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
|
|
||||||
if args.session:
|
|
||||||
gamescope_cmd = os.getenv("GAMESCOPE_CMD", "gamescope -f --xwayland-count 2")
|
|
||||||
cmd = f"{gamescope_cmd} -- portprotonqt"
|
|
||||||
logger.info(f"Executing: {cmd}")
|
|
||||||
subprocess.Popen(cmd, shell=True)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
if args.fullscreen:
|
if args.fullscreen:
|
||||||
logger.info("Launching in fullscreen mode due to --fullscreen flag")
|
logger.info("Launching in fullscreen mode due to --fullscreen flag")
|
||||||
save_fullscreen_config(True)
|
save_fullscreen_config(True)
|
||||||
|
@@ -13,9 +13,4 @@ def parse_args():
|
|||||||
action="store_true",
|
action="store_true",
|
||||||
help="Запустить приложение в полноэкранном режиме и сохранить эту настройку"
|
help="Запустить приложение в полноэкранном режиме и сохранить эту настройку"
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
|
||||||
"--session",
|
|
||||||
action="store_true",
|
|
||||||
help="Запустить приложение с использованием gamescope"
|
|
||||||
)
|
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
@@ -148,10 +148,7 @@ class ContextMenuManager:
|
|||||||
return False
|
return False
|
||||||
current_exe = os.path.basename(exe_path)
|
current_exe = os.path.basename(exe_path)
|
||||||
|
|
||||||
# Check if the current_exe matches the target_exe in MainWindow
|
return hasattr(self.parent, 'target_exe') and self.parent.target_exe == current_exe
|
||||||
if hasattr(self.parent, 'target_exe') and self.parent.target_exe == current_exe:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def show_context_menu(self, game_card, pos: QPoint):
|
def show_context_menu(self, game_card, pos: QPoint):
|
||||||
"""
|
"""
|
||||||
@@ -161,7 +158,6 @@ class ContextMenuManager:
|
|||||||
game_card: The GameCard instance requesting the context menu.
|
game_card: The GameCard instance requesting the context menu.
|
||||||
pos: The position (in widget coordinates) where the menu should appear.
|
pos: The position (in widget coordinates) where the menu should appear.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def get_safe_icon(icon_name: str) -> QIcon:
|
def get_safe_icon(icon_name: str) -> QIcon:
|
||||||
icon = self.theme_manager.get_icon(icon_name)
|
icon = self.theme_manager.get_icon(icon_name)
|
||||||
if isinstance(icon, QIcon):
|
if isinstance(icon, QIcon):
|
||||||
@@ -173,7 +169,18 @@ class ContextMenuManager:
|
|||||||
menu = QMenu(self.parent)
|
menu = QMenu(self.parent)
|
||||||
menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE)
|
menu.setStyleSheet(self.theme.CONTEXT_MENU_STYLE)
|
||||||
|
|
||||||
# Check if the game is running
|
# For non-Steam and non-Epic games, check if exe exists
|
||||||
|
if game_card.game_source not in ("steam", "epic"):
|
||||||
|
exec_line = self._get_exec_line(game_card.name, game_card.exec_line)
|
||||||
|
exe_path = self._parse_exe_path(exec_line, game_card.name) if exec_line else None
|
||||||
|
if not exe_path:
|
||||||
|
# Show only "Delete from PortProton" if no valid exe
|
||||||
|
delete_action = menu.addAction(get_safe_icon("delete"), _("Delete from PortProton"))
|
||||||
|
delete_action.triggered.connect(lambda: self.delete_game(game_card.name, game_card.exec_line))
|
||||||
|
menu.exec(game_card.mapToGlobal(pos))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Normal menu for games with valid exe or from Steam/Epic
|
||||||
is_running = self._is_game_running(game_card)
|
is_running = self._is_game_running(game_card)
|
||||||
action_text = _("Stop Game") if is_running else _("Launch Game")
|
action_text = _("Stop Game") if is_running else _("Launch Game")
|
||||||
action_icon = "stop" if is_running else "play"
|
action_icon = "stop" if is_running else "play"
|
||||||
@@ -697,15 +704,12 @@ Icon={icon_path}
|
|||||||
return None
|
return None
|
||||||
return exec_line
|
return exec_line
|
||||||
|
|
||||||
def _parse_exe_path(self, exec_line, game_name):
|
def _parse_exe_path(self, exec_line: str, game_name: str) -> str | None:
|
||||||
"""Parse the executable path from exec_line."""
|
"""Parse the executable path from exec_line."""
|
||||||
try:
|
try:
|
||||||
entry_exec_split = shlex.split(exec_line)
|
entry_exec_split = shlex.split(exec_line)
|
||||||
if not entry_exec_split:
|
if not entry_exec_split:
|
||||||
self.signals.show_warning_dialog.emit(
|
logger.debug("Invalid executable command for '%s': %s", game_name, exec_line)
|
||||||
_("Error"),
|
|
||||||
_("Invalid executable command: {exec_line}").format(exec_line=exec_line)
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
if entry_exec_split[0] == "env" and len(entry_exec_split) >= 3:
|
if entry_exec_split[0] == "env" and len(entry_exec_split) >= 3:
|
||||||
exe_path = entry_exec_split[2]
|
exe_path = entry_exec_split[2]
|
||||||
@@ -714,17 +718,11 @@ Icon={icon_path}
|
|||||||
else:
|
else:
|
||||||
exe_path = entry_exec_split[-1]
|
exe_path = entry_exec_split[-1]
|
||||||
if not exe_path or not os.path.exists(exe_path):
|
if not exe_path or not os.path.exists(exe_path):
|
||||||
self.signals.show_warning_dialog.emit(
|
logger.debug("Executable not found for '%s': %s", game_name, exe_path or "None")
|
||||||
_("Error"),
|
|
||||||
_("Executable not found: {path}").format(path=exe_path or "None")
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
return exe_path
|
return exe_path
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.signals.show_warning_dialog.emit(
|
logger.debug("Failed to parse executable for '%s': %s", game_name, e)
|
||||||
_("Error"),
|
|
||||||
_("Failed to parse executable: {error}").format(error=str(e))
|
|
||||||
)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _remove_file(self, file_path, error_message, success_message, game_name, location=""):
|
def _remove_file(self, file_path, error_message, success_message, game_name, location=""):
|
||||||
|
@@ -111,6 +111,8 @@ class InputManager(QObject):
|
|||||||
self.stick_value = 0 # Текущее значение стика (для плавности)
|
self.stick_value = 0 # Текущее значение стика (для плавности)
|
||||||
self.dead_zone = 8000 # Мертвая зона стика
|
self.dead_zone = 8000 # Мертвая зона стика
|
||||||
|
|
||||||
|
self._is_gamescope_session = 'gamescope' in os.environ.get('DESKTOP_SESSION', '').lower()
|
||||||
|
|
||||||
# Add variables for continuous D-pad movement
|
# Add variables for continuous D-pad movement
|
||||||
self.dpad_timer = QTimer(self)
|
self.dpad_timer = QTimer(self)
|
||||||
self.dpad_timer.timeout.connect(self.handle_dpad_repeat)
|
self.dpad_timer.timeout.connect(self.handle_dpad_repeat)
|
||||||
@@ -849,7 +851,7 @@ class InputManager(QObject):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
# Toggle fullscreen with F11
|
# Toggle fullscreen with F11
|
||||||
if key == Qt.Key.Key_F11:
|
if key == Qt.Key.Key_F11 and not self._is_gamescope_session:
|
||||||
self.toggle_fullscreen.emit(not self._is_fullscreen)
|
self.toggle_fullscreen.emit(not self._is_fullscreen)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -946,7 +948,7 @@ class InputManager(QObject):
|
|||||||
continue
|
continue
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if event.type == ecodes.EV_KEY and event.value == 1:
|
if event.type == ecodes.EV_KEY and event.value == 1:
|
||||||
if event.code in BUTTONS['menu']:
|
if event.code in BUTTONS['menu'] and not self._is_gamescope_session:
|
||||||
self.toggle_fullscreen.emit(not self._is_fullscreen)
|
self.toggle_fullscreen.emit(not self._is_fullscreen)
|
||||||
else:
|
else:
|
||||||
self.button_pressed.emit(event.code)
|
self.button_pressed.emit(event.code)
|
||||||
|
@@ -1518,6 +1518,8 @@ class MainWindow(QMainWindow):
|
|||||||
self._animations = {}
|
self._animations = {}
|
||||||
imageLabel = QLabel()
|
imageLabel = QLabel()
|
||||||
imageLabel.setFixedSize(300, 400)
|
imageLabel.setFixedSize(300, 400)
|
||||||
|
self._detail_page_active = True
|
||||||
|
self._current_detail_page = detailPage
|
||||||
|
|
||||||
if cover_path:
|
if cover_path:
|
||||||
def on_pixmap_ready(pixmap):
|
def on_pixmap_ready(pixmap):
|
||||||
@@ -1768,6 +1770,11 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
# Время прохождения (Main Story, Main + Sides, Completionist)
|
# Время прохождения (Main Story, Main + Sides, Completionist)
|
||||||
def on_hltb_results(results):
|
def on_hltb_results(results):
|
||||||
|
if not hasattr(self, '_detail_page_active') or not self._detail_page_active:
|
||||||
|
return
|
||||||
|
if not self._current_detail_page or self._current_detail_page.isHidden() or not self._current_detail_page.parent():
|
||||||
|
return
|
||||||
|
|
||||||
if results:
|
if results:
|
||||||
game = results[0] # Берем первый результат
|
game = results[0] # Берем первый результат
|
||||||
main_story_time = hltb.format_game_time(game, "main_story")
|
main_story_time = hltb.format_game_time(game, "main_story")
|
||||||
@@ -1941,6 +1948,8 @@ class MainWindow(QMainWindow):
|
|||||||
def goBackDetailPage(self, page: QWidget | None) -> None:
|
def goBackDetailPage(self, page: QWidget | None) -> None:
|
||||||
if page is None or page != self.stackedWidget.currentWidget():
|
if page is None or page != self.stackedWidget.currentWidget():
|
||||||
return
|
return
|
||||||
|
self._detail_page_active = False
|
||||||
|
self._current_detail_page = None
|
||||||
self.stackedWidget.setCurrentIndex(0)
|
self.stackedWidget.setCurrentIndex(0)
|
||||||
self.stackedWidget.removeWidget(page)
|
self.stackedWidget.removeWidget(page)
|
||||||
page.deleteLater()
|
page.deleteLater()
|
||||||
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "portprotonqt"
|
name = "portprotonqt"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
description = "A project to rewrite PortProton (PortWINE) using PySide"
|
description = "A project to rewrite PortProton (PortWINE) using PySide"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
license = { text = "GPL-3.0" }
|
license = { text = "GPL-3.0" }
|
||||||
|
Reference in New Issue
Block a user