Compare commits
5 Commits
v0.1.9
...
debian-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
b8773f3b68
|
|||
|
f4275dd465
|
|||
|
c8b91c4687
|
|||
|
4aaeb2e809
|
|||
|
b6ea9350fa
|
@@ -8,6 +8,36 @@ env:
|
||||
PACKAGE: "portprotonqt"
|
||||
|
||||
jobs:
|
||||
build-deb:
|
||||
name: Build Debian Package
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y build-essential git python3-dev python3-pip python3-wheel debhelper dh-python \
|
||||
devscripts python3-all bash-completion python3-setuptools
|
||||
|
||||
- name: Checkout repo
|
||||
uses: https://gitea.com/actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 # v6
|
||||
|
||||
- name: Build Debian package
|
||||
run: |
|
||||
# Copy the debian directory to the root for proper packaging
|
||||
cp -r build-aux/debian .
|
||||
|
||||
# Build the package
|
||||
dpkg-buildpackage -us -uc -b
|
||||
|
||||
mv ../*.deb .
|
||||
|
||||
- name: Upload Debian package
|
||||
uses: https://gitea.com/actions/gitea-upload-artifact@v4
|
||||
with:
|
||||
name: PortProtonQt-Debian
|
||||
path: "*.deb"
|
||||
|
||||
build-appimage:
|
||||
name: Build AppImage
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
@@ -147,9 +147,37 @@ jobs:
|
||||
name: PortProtonQt-RPM-Fedora-${{ matrix.fedora_version }}
|
||||
path: /home/rpmbuild/RPMS/**/*.rpm
|
||||
|
||||
build-deb:
|
||||
name: Build Debian Package
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y build-essential git python3-dev python3-pip python3-wheel debhelper dh-python \
|
||||
devscripts python3-all bash-completion python3-setuptools
|
||||
|
||||
- name: Checkout repo
|
||||
uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
- name: Build Debian package
|
||||
run: |
|
||||
# Copy the debian directory to the root for proper packaging
|
||||
cp -r build-aux/debian .
|
||||
|
||||
# Build the package
|
||||
dpkg-buildpackage -us -uc -b
|
||||
|
||||
- name: Upload Debian package
|
||||
uses: https://gitea.com/actions/gitea-upload-artifact@v4
|
||||
with:
|
||||
name: PortProtonQt-Debian
|
||||
path: "*.deb"
|
||||
|
||||
release:
|
||||
name: Create and Publish Release
|
||||
needs: [build-appimage, build-arch, build-fedora]
|
||||
needs: [build-appimage, build-arch, build-fedora, build-deb]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: https://gitea.com/actions/checkout@v4
|
||||
|
||||
@@ -16,7 +16,7 @@ source .venv/bin/activate
|
||||
|
||||
### Установка (release)
|
||||
|
||||
Выберите подходящий пакет для вашей системы или AppImage.
|
||||
Выберите подходящий пакет для вашей системы (deb, rpm, arch) или AppImage.
|
||||
|
||||
Запуск производится по команде portprotonqt или по ярлыку в меню
|
||||
|
||||
|
||||
5
build-aux/debian/changelog
Normal file
5
build-aux/debian/changelog
Normal file
@@ -0,0 +1,5 @@
|
||||
portprotonqt (0.1.9-1) unstable; urgency=medium
|
||||
|
||||
* Initial release for Debian packaging
|
||||
|
||||
-- Boris Yumankulov <boria138@altlinux.org> Wed, 03 Dec 2025 12:00:00 +0000
|
||||
44
build-aux/debian/control
Normal file
44
build-aux/debian/control
Normal file
@@ -0,0 +1,44 @@
|
||||
Source: portprotonqt
|
||||
Section: python
|
||||
Priority: optional
|
||||
Maintainer: Boris Yumankulov <boria138@altlinux.org>
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
dh-python,
|
||||
python3-all,
|
||||
python3-setuptools,
|
||||
python3-pip
|
||||
Standards-Version: 4.6.0
|
||||
Homepage: https://git.linux-gaming.ru/Boria138/PortProtonQt
|
||||
Rules-Requires-Root: no
|
||||
X-Python3-Version: >= 3.10
|
||||
|
||||
Package: portprotonqt
|
||||
Architecture: all
|
||||
Depends: ${python3:Depends}, ${misc:Depends},
|
||||
python3-babel,
|
||||
python3-beautifulsoup4,
|
||||
python3-evdev,
|
||||
python3-icoextract,
|
||||
python3-numpy,
|
||||
python3-orjson,
|
||||
python3-pillow,
|
||||
python3-psutil,
|
||||
python3-pyside6,
|
||||
python3-pyudev,
|
||||
python3-rapidfuzz,
|
||||
python3-requests,
|
||||
python3-tqdm,
|
||||
python3-vdf,
|
||||
python3-websocket-client,
|
||||
perl-image-exiftool,
|
||||
xdg-utils,
|
||||
cabextract,
|
||||
curl,
|
||||
gzip,
|
||||
unzip,
|
||||
unrar
|
||||
Description: Modern GUI for managing and launching games from PortProton, Steam, and Epic Games Store
|
||||
This application provides a sleek, intuitive graphical interface for managing and launching games from PortProton, Steam, and Epic Games Store.
|
||||
It consolidates your game libraries into a single, user-friendly hub for seamless navigation and organization.
|
||||
Its lightweight structure and cross-platform support deliver a cohesive gaming experience, eliminating the need for multiple launchers.
|
||||
Unique PortProton integration enhances Linux gaming, enabling effortless play of Windows-based titles with minimal setup.
|
||||
24
build-aux/debian/copyright
Normal file
24
build-aux/debian/copyright
Normal file
@@ -0,0 +1,24 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: PortProtonQt
|
||||
Source: https://git.linux-gaming.ru/Boria138/PortProtonQt
|
||||
|
||||
Files: *
|
||||
Copyright: 2023-2025 Boria138, BlackSnaker, Mikhail Tergoev(Castro-Fidel)
|
||||
License: GPL-3.0+
|
||||
|
||||
License: GPL-3.0+
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
.
|
||||
On Debian systems, the complete text of the GPL-3.0+ license
|
||||
can be found in /usr/share/common-licenses/GPL-3.
|
||||
25
build-aux/debian/rules
Executable file
25
build-aux/debian/rules
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@ --with python3
|
||||
|
||||
override_dh_auto_build:
|
||||
python3 -m pip install --user --no-deps --ignore-installed .
|
||||
|
||||
override_dh_auto_install:
|
||||
# Install Python modules
|
||||
python3 -m pip install --no-deps --ignore-installed --prefix=$(CURDIR)/debian/portprotonqt/usr .
|
||||
|
||||
# Install desktop files and icons
|
||||
install -d $(CURDIR)/debian/portprotonqt/usr/share/applications
|
||||
install -m 644 $(CURDIR)/../build-aux/share/applications/ru.linux_gaming.PortProtonQt.desktop \
|
||||
$(CURDIR)/debian/portprotonqt/usr/share/applications/
|
||||
|
||||
install -d $(CURDIR)/debian/portprotonqt/usr/share/icons/hicolor/scalable/apps
|
||||
install -m 644 $(CURDIR)/../build-aux/share/icons/hicolor/scalable/apps/ru.linux_gaming.PortProtonQt.svg \
|
||||
$(CURDIR)/debian/portprotonqt/usr/share/icons/hicolor/scalable/apps/
|
||||
|
||||
# Install metainfo file
|
||||
install -d $(CURDIR)/debian/portprotonqt/usr/share/metainfo
|
||||
install -m 644 $(CURDIR)/../build-aux/share/metainfo/ru.linux_gaming.PortProtonQt.metainfo.xml \
|
||||
$(CURDIR)/debian/portprotonqt/usr/share/metainfo/
|
||||
1
build-aux/debian/source/format
Normal file
1
build-aux/debian/source/format
Normal file
@@ -0,0 +1 @@
|
||||
3.0 (quilt)
|
||||
7
build-aux/debian/source/options
Normal file
7
build-aux/debian/source/options
Normal file
@@ -0,0 +1,7 @@
|
||||
extend-diff-ignore = "^[^/]*[.]egg-info/"
|
||||
compression = "gzip"
|
||||
tar-ignore = "dev-scripts"
|
||||
tar-ignore = ".*"
|
||||
tar-ignore = "__pycache__"
|
||||
tar-ignore = "build-aux"
|
||||
tar-ignore = "data"
|
||||
@@ -0,0 +1,2 @@
|
||||
"""PortProtonQt - A project to rewrite PortProton (PortWINE) using PySide."""
|
||||
__version__ = "0.1.9"
|
||||
|
||||
@@ -183,23 +183,39 @@ def get_portproton_start_command():
|
||||
if not portproton_path:
|
||||
return None
|
||||
|
||||
# Check if flatpak command exists before trying to run it
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["flatpak", "list"],
|
||||
subprocess.run(
|
||||
["flatpak", "--version"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
timeout=10
|
||||
timeout=5
|
||||
)
|
||||
if "ru.linux_gaming.PortProton" in result.stdout:
|
||||
logger.info("Detected Flatpak installation")
|
||||
return ["flatpak", "run", "ru.linux_gaming.PortProton"]
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.warning("Flatpak list command timed out")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.warning(f"Error checking flatpak list: {e}")
|
||||
pass
|
||||
flatpak_available = True
|
||||
except FileNotFoundError:
|
||||
flatpak_available = False
|
||||
except Exception:
|
||||
flatpak_available = False
|
||||
|
||||
if flatpak_available:
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["flatpak", "list"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
timeout=10
|
||||
)
|
||||
if "ru.linux_gaming.PortProton" in result.stdout:
|
||||
logger.info("Detected Flatpak installation")
|
||||
return ["flatpak", "run", "ru.linux_gaming.PortProton"]
|
||||
except subprocess.TimeoutExpired:
|
||||
logger.warning("Flatpak list command timed out")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.warning(f"Error checking flatpak list: {e}")
|
||||
pass
|
||||
|
||||
start_sh_path = os.path.join(portproton_path, "data", "scripts", "start.sh")
|
||||
if os.path.exists(start_sh_path):
|
||||
|
||||
@@ -505,17 +505,25 @@ class GameLibraryManager:
|
||||
"""Clears all widgets from the layout."""
|
||||
if layout is None:
|
||||
return
|
||||
# Remove all widgets from the layout and clean up caches
|
||||
while layout.count():
|
||||
child = layout.takeAt(0)
|
||||
if child.widget():
|
||||
widget = child.widget()
|
||||
# Clean up cache if widget exists in it
|
||||
for key, card in list(self.game_card_cache.items()):
|
||||
if card == widget:
|
||||
del self.game_card_cache[key]
|
||||
if key in self.pending_images:
|
||||
del self.pending_images[key]
|
||||
break
|
||||
# Always schedule widget for deletion regardless of cache state
|
||||
widget.deleteLater()
|
||||
|
||||
# Also clear the cache completely if needed (in case layout wasn't in sync)
|
||||
self.game_card_cache.clear()
|
||||
self.pending_images.clear()
|
||||
|
||||
def set_games(self, games: list[tuple]):
|
||||
"""Sets the games list and updates the filtered games."""
|
||||
self.games = games
|
||||
|
||||
@@ -1939,8 +1939,10 @@ class InputManager(QObject):
|
||||
active_win.show_next()
|
||||
return True # Consume event to prevent tab switching
|
||||
|
||||
# Handle tab switching with Left/Right arrow keys when not in GameCard focus or QLineEdit
|
||||
if key in (Qt.Key.Key_Left, Qt.Key.Key_Right) and not isinstance(focused, GameCard | QLineEdit) and not self.file_explorer:
|
||||
# Handle tab switching with Left/Right arrow keys when not in GameCard focus or QLineEdit or QTableWidget or AutoSizeButton
|
||||
if (key in (Qt.Key.Key_Left, Qt.Key.Key_Right) and
|
||||
not isinstance(focused, GameCard | QLineEdit | QTableWidget | AutoSizeButton) and
|
||||
not self.file_explorer):
|
||||
idx = self._parent.stackedWidget.currentIndex()
|
||||
total = len(self._parent.tabButtons)
|
||||
if key == Qt.Key.Key_Left:
|
||||
@@ -1976,12 +1978,6 @@ class InputManager(QObject):
|
||||
self.dpad_moved.emit(dpad_code, dpad_value, now)
|
||||
return True
|
||||
|
||||
# Launch/stop game on detail page
|
||||
if self._parent.currentDetailPage and key in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
|
||||
if self._parent.current_exec_line:
|
||||
self._parent.toggleGame(self._parent.current_exec_line, None)
|
||||
return True
|
||||
|
||||
# Context menu for GameCard
|
||||
if isinstance(focused, GameCard):
|
||||
if key == Qt.Key.Key_F10 and modifiers & Qt.KeyboardModifier.ShiftModifier:
|
||||
@@ -1991,6 +1987,18 @@ class InputManager(QObject):
|
||||
|
||||
# General actions: Activate, Back, Add
|
||||
if key in (Qt.Key.Key_Return, Qt.Key.Key_Enter):
|
||||
# Special handling for table widgets with checkboxes
|
||||
if isinstance(focused, QTableWidget):
|
||||
current_row = focused.currentRow()
|
||||
current_col = focused.currentColumn()
|
||||
if current_row >= 0 and current_col >= 0:
|
||||
# Check if the cell contains a checkbox
|
||||
item = focused.item(current_row, current_col)
|
||||
if item and (item.flags() & Qt.ItemFlag.ItemIsUserCheckable):
|
||||
# Toggle the checkbox state
|
||||
new_state = Qt.CheckState.Checked if item.checkState() == Qt.CheckState.Unchecked else Qt.CheckState.Unchecked
|
||||
item.setCheckState(new_state)
|
||||
return True
|
||||
self._parent.activateFocusedWidget()
|
||||
return True
|
||||
elif key in (Qt.Key.Key_Escape, Qt.Key.Key_Backspace):
|
||||
|
||||
@@ -1199,7 +1199,7 @@ class MainWindow(QMainWindow):
|
||||
self.progress_bar.setRange(0, 0) # Indeterminate
|
||||
self.update_status_message.emit(_("Refreshing game library..."), 0)
|
||||
|
||||
# Clear the game card cache to force reload of custom data
|
||||
# Clear the game card cache and layout to force reload of custom data
|
||||
if hasattr(self, 'game_library_manager') and self.game_library_manager:
|
||||
# Clear the cache to ensure custom data is reloaded
|
||||
self.game_library_manager.game_card_cache.clear()
|
||||
@@ -1209,6 +1209,19 @@ class MainWindow(QMainWindow):
|
||||
# Mark for full rebuild of search indices
|
||||
self.game_library_manager.dirty = True # Force full update
|
||||
|
||||
# Also clear the layout to ensure old widgets are removed
|
||||
if (hasattr(self.game_library_manager, 'gamesListLayout') and
|
||||
self.game_library_manager.gamesListLayout and
|
||||
hasattr(self.game_library_manager, 'gamesListWidget') and
|
||||
self.game_library_manager.gamesListWidget):
|
||||
# Remove all widgets from the layout
|
||||
self.game_library_manager.clear_layout(self.game_library_manager.gamesListLayout)
|
||||
|
||||
# Force layout update to ensure UI changes are visible
|
||||
self.game_library_manager.gamesListWidget.updateGeometry()
|
||||
if hasattr(self.game_library_manager, 'gamesListLayout'):
|
||||
self.game_library_manager.gamesListLayout.update()
|
||||
|
||||
# Reload games using the existing loadGames functionality
|
||||
# Use a small delay to allow UI to update before starting the refresh
|
||||
QTimer.singleShot(50, lambda: self.loadGames())
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[build-system]
|
||||
requires = ["setuptools >= 77.0.3"]
|
||||
requires = ["setuptools >= 77.0.3", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
@@ -46,12 +46,13 @@ dependencies = [
|
||||
[project.scripts]
|
||||
portprotonqt = "portprotonqt.app:main"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["portprotonqt"]
|
||||
include-package-data = true
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"portprotonqt" = ["themes/**/*", "locales/**/*"]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
exclude = ["build-aux", "dev-scripts", "documentation", "data"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
"E", # pycodestyle errors
|
||||
|
||||
Reference in New Issue
Block a user