Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 51133e4042 | |||
|
bcf6ac2656
|
|||
| d59261f021 | |||
|
44923b771a
|
|||
| eaaf14c58a | |||
| 7779131cf9 | |||
|
87fa678ccb
|
|||
| c5e24b3984 | |||
|
21cc6a4813
|
|||
| ee73049248 | |||
|
3a8ad5bd5d
|
@@ -5,6 +5,35 @@ All notable changes to RigDoctor are recorded here. Format follows
|
|||||||
(`MAJOR.MINOR.PATCH`, pre-1.0). `__version__` and `pyproject.toml` must match the git
|
(`MAJOR.MINOR.PATCH`, pre-1.0). `__version__` and `pyproject.toml` must match the git
|
||||||
release tag (so the auto-updater, D18, can compare versions).
|
release tag (so the auto-updater, D18, can compare versions).
|
||||||
|
|
||||||
|
## [0.37.0] - 2026-05-22
|
||||||
|
### Added
|
||||||
|
- **Version footer** — a footer across the bottom of the window shows `RigDoctor v<version>` in
|
||||||
|
the bottom-right (moved out of the sidebar).
|
||||||
|
### Fixed
|
||||||
|
- **Pages scroll when content doesn't fit, and the window is no longer pinned to the tallest
|
||||||
|
page's height.** Long pages (Settings, Tuning, …) get a scrollbar when too tall — so controls
|
||||||
|
like Uninstall are always reachable — and the window can now be resized smaller than the screen
|
||||||
|
(min height dropped from "taller than the screen" to ~600px). Pages that manage their own
|
||||||
|
scroll/fill (Dashboard, System Health, Inventory, Share) are unchanged.
|
||||||
|
|
||||||
|
## [0.36.1] - 2026-05-22
|
||||||
|
### Fixed
|
||||||
|
- `rigdoctor gui` printed the wrong fix when PySide6 is missing — it suggested the non-existent
|
||||||
|
`python3-pyside6` package. Now it names the real split modules
|
||||||
|
(`python3-pyside6.qt{widgets,gui,websockets,svg}` + `python3-pyte`).
|
||||||
|
|
||||||
|
## [0.36.0] - 2026-05-22
|
||||||
|
### Fixed
|
||||||
|
- **`.deb` now installs all dependencies automatically — no manual tool install.** The previous
|
||||||
|
`Recommends: python3-pyside6` named a package that doesn't exist on Debian/Ubuntu (PySide6 is
|
||||||
|
split per module), so apt silently skipped it and the GUI wouldn't start. Now it Recommends the
|
||||||
|
actual modules the GUI imports — `python3-pyside6.qt{widgets,gui,websockets,svg}` + `python3-pyte`.
|
||||||
|
### Changed
|
||||||
|
- **`apt install rigdoctor` sets up the whole toolset.** The `.deb` also Recommends the optional
|
||||||
|
diagnostic/gaming tools (smartmontools, lm-sensors, dmidecode, pciutils, libnotify-bin,
|
||||||
|
libsecret-tools, gamemode, mangohud) so they install by default — users never hand-install
|
||||||
|
tools. `cpupower` is a Suggests (kernel-tied); `--no-install-recommends` still gives CLI-only.
|
||||||
|
|
||||||
## [0.35.0] - 2026-05-22
|
## [0.35.0] - 2026-05-22
|
||||||
### Added
|
### Added
|
||||||
- **`.deb` package (M9 / D8)** — `packaging/make_deb.py` builds a `rigdoctor_<version>_all.deb`
|
- **`.deb` package (M9 / D8)** — `packaging/make_deb.py` builds a `rigdoctor_<version>_all.deb`
|
||||||
|
|||||||
@@ -41,22 +41,29 @@ apt pulls the GUI dependencies (PySide6, pyte) automatically:
|
|||||||
sudo apt install ./rigdoctor_*_all.deb # CLI only: add --no-install-recommends
|
sudo apt install ./rigdoctor_*_all.deb # CLI only: add --no-install-recommends
|
||||||
```
|
```
|
||||||
|
|
||||||
**Or add the apt repository** for `apt install` + automatic updates:
|
**Or add the apt repository** for `apt install` + automatic updates. The registry is public and
|
||||||
|
GPG-signed — no token needed; just add the signing key and a deb822 source:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# the registry is private, so give apt a token (a Gitea PAT with read:package)
|
# signing key → dearmored into the keyring
|
||||||
echo "machine git.jesseyvanofferen.com login <user> password <token>" \
|
sudo install -d -m 0755 /etc/apt/keyrings
|
||||||
| sudo tee /etc/apt/auth.conf.d/rigdoctor.conf
|
curl -fsSL https://git.jesseyvanofferen.com/api/packages/jessey/debian/repository.key \
|
||||||
sudo chmod 600 /etc/apt/auth.conf.d/rigdoctor.conf
|
| sudo gpg --dearmor -o /etc/apt/keyrings/gitea-jessey.gpg
|
||||||
|
|
||||||
echo "deb [trusted=yes] https://git.jesseyvanofferen.com/api/packages/jessey/debian stable main" \
|
# the source (modern deb822 format, GPG-verified, all-arch)
|
||||||
| sudo tee /etc/apt/sources.list.d/rigdoctor.list
|
sudo tee /etc/apt/sources.list.d/rigdoctor.sources >/dev/null <<'EOF'
|
||||||
|
Types: deb
|
||||||
|
URIs: https://git.jesseyvanofferen.com/api/packages/jessey/debian
|
||||||
|
Suites: stable
|
||||||
|
Components: main
|
||||||
|
Architectures: all
|
||||||
|
Signed-By: /etc/apt/keyrings/gitea-jessey.gpg
|
||||||
|
EOF
|
||||||
|
|
||||||
sudo apt update && sudo apt install rigdoctor
|
sudo apt update && sudo apt install rigdoctor
|
||||||
```
|
```
|
||||||
|
|
||||||
Then `sudo apt upgrade` keeps it current. *(If your server serves a signed registry, drop the
|
Then `sudo apt upgrade` keeps it current.
|
||||||
`auth.conf.d` file and replace `[trusted=yes]` with `[signed-by=…]` + the `repository.key`.)*
|
|
||||||
|
|
||||||
### Any distro — self-extracting `.run` (no root)
|
### Any distro — self-extracting `.run` (no root)
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,13 @@
|
|||||||
|
|
||||||
Pure-Python app, so it's `Architecture: all`: we stage the package into dist-packages, drop the
|
Pure-Python app, so it's `Architecture: all`: we stage the package into dist-packages, drop the
|
||||||
two launchers in /usr/bin, install the desktop entry + icon, write a DEBIAN/control, and call
|
two launchers in /usr/bin, install the desktop entry + icon, write a DEBIAN/control, and call
|
||||||
`dpkg-deb`. The core is stdlib (`Depends: python3`); the GUI/tray deps are **Recommends**
|
`dpkg-deb`. The core is stdlib (`Depends: python3`); everything else is **Recommends** so a
|
||||||
(`python3-pyside6`, `python3-pyte`) so `apt install rigdoctor` gives the full app by default,
|
plain `apt install rigdoctor` sets up the whole toolset automatically (users never hand-install
|
||||||
while `--no-install-recommends` yields a CLI-only install.
|
deps) — the GUI modules (Debian/Ubuntu split PySide6 per module, so we name
|
||||||
|
`python3-pyside6.qt{widgets,gui,websockets,svg}`) + `python3-pyte`, plus the diagnostic/gaming
|
||||||
|
tools (smartmontools, lm-sensors, dmidecode, pciutils, libnotify-bin, libsecret-tools, gamemode,
|
||||||
|
mangohud). `--no-install-recommends` still yields a CLI-only install; `cpupower` is a Suggests
|
||||||
|
(kernel-tied/heavy).
|
||||||
|
|
||||||
Run: `python packaging/make_deb.py` → `dist/rigdoctor_<version>_all.deb`.
|
Run: `python packaging/make_deb.py` → `dist/rigdoctor_<version>_all.deb`.
|
||||||
"""
|
"""
|
||||||
@@ -57,7 +61,8 @@ Maintainer: {maintainer}
|
|||||||
Section: utils
|
Section: utils
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Depends: python3 (>= 3.11)
|
Depends: python3 (>= 3.11)
|
||||||
Recommends: python3-pyside6, python3-pyte
|
Recommends: python3-pyside6.qtwidgets, python3-pyside6.qtgui, python3-pyside6.qtwebsockets, python3-pyside6.qtsvg, python3-pyte, smartmontools, lm-sensors, dmidecode, pciutils, libnotify-bin, libsecret-tools, gamemode, mangohud
|
||||||
|
Suggests: linux-tools-generic
|
||||||
Homepage: {homepage}
|
Homepage: {homepage}
|
||||||
Description: Hardware monitoring & crash diagnostics for Linux gamers
|
Description: Hardware monitoring & crash diagnostics for Linux gamers
|
||||||
RigDoctor monitors GPU/CPU temperatures, load, and sensors, captures crash
|
RigDoctor monitors GPU/CPU temperatures, load, and sensors, captures crash
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "rigdoctor"
|
name = "rigdoctor"
|
||||||
version = "0.35.0"
|
version = "0.37.0"
|
||||||
description = "Modular hardware monitoring & crash diagnostics for Linux gamers."
|
description = "Modular hardware monitoring & crash diagnostics for Linux gamers."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
"""RigDoctor — modular hardware monitoring & crash diagnostics for Linux gamers."""
|
"""RigDoctor — modular hardware monitoring & crash diagnostics for Linux gamers."""
|
||||||
|
|
||||||
__version__ = "0.35.0"
|
__version__ = "0.37.0"
|
||||||
|
|||||||
@@ -55,8 +55,9 @@ def cmd_gui(args) -> int:
|
|||||||
from .gui.app import main as gui_main
|
from .gui.app import main as gui_main
|
||||||
except ImportError as exc:
|
except ImportError as exc:
|
||||||
print("The GUI needs PySide6, which isn't installed.")
|
print("The GUI needs PySide6, which isn't installed.")
|
||||||
print(" Install it with: pip install 'rigdoctor[gui]'")
|
print(" Ubuntu/Debian: sudo apt install python3-pyside6.qtwidgets "
|
||||||
print(" or on Ubuntu: sudo apt install python3-pyside6")
|
"python3-pyside6.qtgui python3-pyside6.qtwebsockets python3-pyside6.qtsvg python3-pyte")
|
||||||
|
print(" pip: pip install 'rigdoctor[gui]'")
|
||||||
print(f" ({exc})")
|
print(f" ({exc})")
|
||||||
return 2
|
return 2
|
||||||
return gui_main([sys.argv[0]])
|
return gui_main([sys.argv[0]])
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ from PySide6.QtWidgets import (
|
|||||||
QMainWindow,
|
QMainWindow,
|
||||||
QMessageBox,
|
QMessageBox,
|
||||||
QPushButton,
|
QPushButton,
|
||||||
|
QScrollArea,
|
||||||
QStackedWidget,
|
QStackedWidget,
|
||||||
QSystemTrayIcon,
|
QSystemTrayIcon,
|
||||||
QTextEdit,
|
QTextEdit,
|
||||||
@@ -51,6 +52,10 @@ _NAV = [
|
|||||||
("App", ["Settings", "Share"]),
|
("App", ["Settings", "Share"]),
|
||||||
]
|
]
|
||||||
_PAGES = [name for _section, names in _NAV for name in names]
|
_PAGES = [name for _section, names in _NAV for name in names]
|
||||||
|
# Pages that manage their own scrolling (pinned header + inner scroll) or must fill the
|
||||||
|
# viewport (the Share terminal) — these are added to the stack as-is; every other page is
|
||||||
|
# wrapped in a QScrollArea so it scrolls when too tall and doesn't pin the window's height.
|
||||||
|
_NO_WRAP = {"Dashboard", "System Health", "Inventory", "Share"}
|
||||||
_ICON = Path(__file__).parent / "assets" / "rigdoctor.svg"
|
_ICON = Path(__file__).parent / "assets" / "rigdoctor.svg"
|
||||||
|
|
||||||
|
|
||||||
@@ -68,7 +73,11 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
central = QWidget()
|
central = QWidget()
|
||||||
self.setCentralWidget(central)
|
self.setCentralWidget(central)
|
||||||
layout = QHBoxLayout(central)
|
outer = QVBoxLayout(central)
|
||||||
|
outer.setContentsMargins(0, 0, 0, 0)
|
||||||
|
outer.setSpacing(0)
|
||||||
|
body = QWidget()
|
||||||
|
layout = QHBoxLayout(body)
|
||||||
layout.setContentsMargins(0, 0, 0, 0)
|
layout.setContentsMargins(0, 0, 0, 0)
|
||||||
layout.setSpacing(0)
|
layout.setSpacing(0)
|
||||||
|
|
||||||
@@ -100,11 +109,14 @@ class MainWindow(QMainWindow):
|
|||||||
"Share": self.share_page,
|
"Share": self.share_page,
|
||||||
}
|
}
|
||||||
for name in _PAGES:
|
for name in _PAGES:
|
||||||
self._stack.addWidget(self._pages[name])
|
page = self._pages[name]
|
||||||
|
self._stack.addWidget(page if name in _NO_WRAP else self._scrollable(page))
|
||||||
content_layout.addWidget(self._stack)
|
content_layout.addWidget(self._stack)
|
||||||
|
|
||||||
layout.addWidget(self._build_sidebar())
|
layout.addWidget(self._build_sidebar())
|
||||||
layout.addWidget(content, 1)
|
layout.addWidget(content, 1)
|
||||||
|
outer.addWidget(body, 1)
|
||||||
|
outer.addWidget(self._build_footer())
|
||||||
|
|
||||||
self._worker = SamplerWorker(interval=interval)
|
self._worker = SamplerWorker(interval=interval)
|
||||||
self._worker.sampled.connect(self.dashboard.update_sample)
|
self._worker.sampled.connect(self.dashboard.update_sample)
|
||||||
@@ -216,9 +228,6 @@ class MainWindow(QMainWindow):
|
|||||||
v.addStretch(1)
|
v.addStretch(1)
|
||||||
live = QLabel(f'<span style="color:{ACCENT};">●</span> <span style="color:{MUTED};">Live</span>')
|
live = QLabel(f'<span style="color:{ACCENT};">●</span> <span style="color:{MUTED};">Live</span>')
|
||||||
v.addWidget(live)
|
v.addWidget(live)
|
||||||
version = QLabel(f"v{__version__}")
|
|
||||||
version.setObjectName("Muted")
|
|
||||||
v.addWidget(version)
|
|
||||||
changelog_btn = QPushButton("Changelog")
|
changelog_btn = QPushButton("Changelog")
|
||||||
changelog_btn.setObjectName("LinkButton")
|
changelog_btn.setObjectName("LinkButton")
|
||||||
changelog_btn.setCursor(Qt.CursorShape.PointingHandCursor)
|
changelog_btn.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||||
@@ -248,6 +257,27 @@ class MainWindow(QMainWindow):
|
|||||||
v.addWidget(self._restart_btn)
|
v.addWidget(self._restart_btn)
|
||||||
return bar
|
return bar
|
||||||
|
|
||||||
|
def _scrollable(self, page: QWidget) -> QScrollArea:
|
||||||
|
"""Wrap a page so it scrolls when taller than the window — and so the window can shrink
|
||||||
|
below the page's natural height instead of being pinned to it."""
|
||||||
|
area = QScrollArea()
|
||||||
|
area.setWidget(page)
|
||||||
|
area.setWidgetResizable(True)
|
||||||
|
area.setFrameShape(QFrame.Shape.NoFrame)
|
||||||
|
area.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
|
||||||
|
return area
|
||||||
|
|
||||||
|
def _build_footer(self) -> QFrame:
|
||||||
|
bar = QFrame()
|
||||||
|
bar.setObjectName("Footer")
|
||||||
|
h = QHBoxLayout(bar)
|
||||||
|
h.setContentsMargins(14, 5, 16, 5)
|
||||||
|
h.addStretch(1)
|
||||||
|
version = QLabel(f"RigDoctor v{__version__}")
|
||||||
|
version.setObjectName("Muted")
|
||||||
|
h.addWidget(version)
|
||||||
|
return bar
|
||||||
|
|
||||||
def _restart(self) -> None:
|
def _restart(self) -> None:
|
||||||
gui = os.path.join(os.path.dirname(sys.executable), "rigdoctor-gui")
|
gui = os.path.join(os.path.dirname(sys.executable), "rigdoctor-gui")
|
||||||
if os.path.exists(gui):
|
if os.path.exists(gui):
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ QMainWindow, #ContentArea, #Page {{ background: {BG}; }}
|
|||||||
QLabel {{ background: transparent; }}
|
QLabel {{ background: transparent; }}
|
||||||
|
|
||||||
#Sidebar {{ background: {SIDEBAR}; border-right: 1px solid {CARD_BORDER}; }}
|
#Sidebar {{ background: {SIDEBAR}; border-right: 1px solid {CARD_BORDER}; }}
|
||||||
|
#Footer {{ background: {SIDEBAR}; border-top: 1px solid {CARD_BORDER}; }}
|
||||||
|
#Footer QLabel {{ font-size: 11px; }}
|
||||||
#AppTitle {{ font-size: 17px; font-weight: 800; }}
|
#AppTitle {{ font-size: 17px; font-weight: 800; }}
|
||||||
#AppSubtitle {{ color: {MUTED}; font-size: 11px; }}
|
#AppSubtitle {{ color: {MUTED}; font-size: 11px; }}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user