diff --git a/.github/workflows/build-rpm.yml b/.github/workflows/build-rpm.yml index f91d202..ce15de9 100644 --- a/.github/workflows/build-rpm.yml +++ b/.github/workflows/build-rpm.yml @@ -11,7 +11,7 @@ on: tags: - "v*" pull_request: - types: [opened, synchronize, reopened, labeled, unlabeled] + types: [opened, synchronize, reopened, labeled, unlabeled, ready_for_review] permissions: contents: write @@ -24,7 +24,7 @@ jobs: lint: name: Lint Python runs-on: ubuntu-latest - if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) + if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation') steps: - name: Checkout source @@ -44,7 +44,7 @@ jobs: shellcheck: name: ShellCheck polaris-helper runs-on: ubuntu-latest - if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) + if: github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation') steps: - name: Checkout source @@ -53,16 +53,16 @@ jobs: - name: Run ShellCheck uses: ludeeus/action-shellcheck@2.0.0 with: - additional_files: src/polaris-helper + additional_files: src/polaris-helper src/packaging/build-rpm.sh build: - name: Build (Fedora ${{ matrix.fedora }} KDE) + name: Build (Fedora ${{ matrix.fedora }}) runs-on: ubuntu-latest needs: [lint, shellcheck] - if: github.actor != 'dependabot[bot]' && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) + if: github.event.pull_request.draft != true && (github.event_name != 'pull_request' || !contains(github.event.pull_request.labels.*.name, 'documentation')) strategy: matrix: - fedora: [43] + fedora: [43, 44] container: image: fedora:${{ matrix.fedora }} @@ -91,8 +91,7 @@ jobs: # 1) workflow_dispatch explicit input wins if [ -n "${INPUT_VERSION}" ]; then - VERSION="${INPUT_VERSION}" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~-]/./g')" + VERSION="${INPUT_VERSION#v}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Resolved version from workflow input: ${VERSION}" exit 0 @@ -101,24 +100,23 @@ jobs: # 2) Tag pushes use tag name if [ "${GITHUB_REF#refs/tags/}" != "${GITHUB_REF}" ]; then VERSION="${GITHUB_REF#refs/tags/}" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~-]/./g')" + VERSION="${VERSION#v}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Resolved version from tag: ${VERSION}" exit 0 fi - # 3) PR builds create a clean beta version. - # RPM Version cannot include '-', so we use dots for prerelease label. + # 3) PR builds: semver prerelease string (dash separator so build-rpm.sh + # splits it into RPM Version + Release: 0.prerelease.1) if [ "${GITHUB_EVENT_NAME}" = "pull_request" ]; then BASE_TAG="$(git tag --list 'v*' --sort=-v:refname | head -n 1 || true)" - BASE_VERSION="${BASE_TAG}" + BASE_VERSION="${BASE_TAG#v}" if [ -z "${BASE_VERSION}" ]; then - BASE_VERSION="v0.0.0" + BASE_VERSION="0.0.0" fi SHORT_SHA="$(printf '%s' "$GITHUB_SHA" | cut -c1-8)" - VERSION="${BASE_VERSION}.beta.pr${{ github.event.pull_request.number }}.${SHORT_SHA}" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~]/./g')" + VERSION="${BASE_VERSION}-beta.pr${{ github.event.pull_request.number }}.${SHORT_SHA}" echo "version=${VERSION}" >> "$GITHUB_OUTPUT" echo "Resolved version for PR beta build: ${VERSION}" exit 0 @@ -126,7 +124,7 @@ jobs: # 4) Fallback for branch manual runs without input VERSION="$(git tag --list 'v*' --sort=-v:refname | head -n 1 || true)" - VERSION="$(printf '%s' "$VERSION" | sed 's/[^[:alnum:]._+~-]/./g')" + VERSION="${VERSION#v}" if [ -z "${VERSION}" ]; then echo "Could not resolve a version (no tags found)." exit 1 @@ -143,30 +141,22 @@ jobs: GIT_DISCOVERY_ACROSS_FILESYSTEM: 1 run: | mkdir -p "$TOPDIR" "$DISTDIR" - # Ensure rpmbuild writes inside the shared workspace (not ~) export HOME="${{ github.workspace }}" mkdir -p "$HOME"/rpmbuild - echo "GITHUB_REF=$GITHUB_REF" - echo "GITHUB_REF_NAME=$GITHUB_REF_NAME" - echo "GITHUB_REF_TYPE=$GITHUB_REF_TYPE" - echo "VERSION (env)=$VERSION" - - if [ -z "$VERSION" ]; then - echo "Resolved VERSION is empty; aborting." - exit 1 - fi + git config --global --add safe.directory "$GITHUB_WORKSPACE" chmod +x src/packaging/build-rpm.sh - ./src/packaging/build-rpm.sh "$VERSION" + ./src/packaging/build-rpm.sh - # Collect RPMs into dist/ - find "$HOME/rpmbuild/RPMS" -type f -name "*.rpm" -exec cp -v {} "$DISTDIR/" \; + find "$HOME/rpmbuild/RPMS" -type f -name "*.rpm" -exec cp -v {} "$DISTDIR/" \; + mkdir -p "$DISTDIR/srpms" + find "$HOME/rpmbuild/SRPMS" -type f -name "*.src.rpm" -exec cp -v {} "$DISTDIR/srpms/" \; - name: Smoke test — install RPM and verify files env: DISTDIR: ${{ github.workspace }}/dist run: | - dnf install -y --nogpgcheck "$DISTDIR"/*.rpm + dnf install -y --nogpgcheck "$DISTDIR"/*.noarch.rpm test -x /usr/bin/polaris || { echo "FAIL: /usr/bin/polaris missing"; exit 1; } test -x /usr/libexec/polaris-helper || { echo "FAIL: polaris-helper missing"; exit 1; } test -f /usr/share/applications/polaris.desktop || { echo "FAIL: .desktop file missing"; exit 1; } @@ -176,8 +166,15 @@ jobs: - name: Upload RPM artifacts uses: actions/upload-artifact@v7 with: - name: rpm-f${{ matrix.fedora }}-kde-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} - path: dist/*.rpm + name: rpm-f${{ matrix.fedora }}-${{ github.event_name == 'pull_request' && format('pr{0}', github.event.pull_request.number) || 'release' }} + path: dist/*.noarch.rpm + + - name: Upload SRPM artifact (f44 only, PRs only) + if: matrix.fedora == 44 && github.event_name == 'pull_request' + uses: actions/upload-artifact@v7 + with: + name: srpm-pr${{ github.event.pull_request.number }} + path: dist/srpms/*.src.rpm release: name: Release @@ -211,11 +208,12 @@ jobs: echo "do_release=false" >> "$GITHUB_OUTPUT" fi - - name: Download Fedora 43 KDE artifacts + - name: Download RPM artifacts if: steps.resolve_tag.outputs.do_release == 'true' uses: actions/download-artifact@v4 with: - name: rpm-f43-kde-release + pattern: rpm-f*-release + merge-multiple: true path: dist - name: List files (debug) @@ -253,29 +251,71 @@ jobs: > the package is not yet signed with a GPG key. ### Assets - - Fedora 43 KDE RPM + - Fedora 43 RPM + - Fedora 44 RPM + + copr-beta: + name: Submit to COPR Testing + needs: build + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'documentation') + + steps: + - name: Download SRPM + uses: actions/download-artifact@v4 + with: + name: srpm-pr${{ github.event.pull_request.number }} + path: dist + + - name: Install copr-cli + run: pip install copr-cli + + - name: Configure copr-cli + env: + COPR_LOGIN: ${{ secrets.COPR_LOGIN }} + COPR_TOKEN: ${{ secrets.COPR_TOKEN }} + run: | + mkdir -p ~/.config + cat > ~/.config/copr < The COPR build runs asynchronously — wait ~5 min after this comment before installing. + + **Option 2 — manual RPM download:** + https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}#artifacts - Artifact name: `rpm-f43-kde-pr${{ github.event.pull_request.number }}` + Artifact names: `rpm-f43-pr${{ github.event.pull_request.number }}`, `rpm-f44-pr${{ github.event.pull_request.number }}` diff --git a/README.md b/README.md index e0676b4..373f139 100644 --- a/README.md +++ b/README.md @@ -6,13 +6,13 @@ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](LICENSE) [![Python](https://img.shields.io/badge/Made%20with-Python-3776AB?logo=python&logoColor=white)](https://www.python.org/) [![Shell](https://img.shields.io/badge/Script-Shell-4EAA25?logo=gnu-bash&logoColor=white)](https://www.gnu.org/software/bash/) -[![Fedora](https://img.shields.io/badge/Platform-Fedora%2043%20KDE-51A2DA?logo=fedora&logoColor=white)](https://fedoraproject.org/) +[![Fedora](https://img.shields.io/badge/Platform-Fedora%2043%20%2F%2044-51A2DA?logo=fedora&logoColor=white)](https://fedoraproject.org/) [![Buy Me A Coffee](https://img.shields.io/badge/Support-Buy%20Me%20A%20Coffee-orange?logo=buy-me-a-coffee)](https://www.buymeacoffee.com/ttheroux) [![Stars](https://img.shields.io/github/stars/KernelChief/polaris?style=social)](https://github.com/KernelChief/polaris/stargazers) Setting up a Linux workstation shouldn’t be a chore. -**Polaris** is a **PySide6 (Qt6)** desktop application that simplifies setting up a fresh Fedora KDE installation. It wraps essential post-install tasks, such as enabling repositories, installing drivers, and deploying apps, into a clean, point-and-click interface. +**Polaris** is a **PySide6 (Qt6)** desktop application that simplifies setting up a fresh Fedora installation. It wraps essential post-install tasks, such as enabling repositories, installing drivers, and deploying apps, into a clean, point-and-click interface. **Why Polaris?** Polaris is the north star: always there, always reliable. It’s the first thing you find when you’re navigating a new install. @@ -44,7 +44,7 @@ sudo dnf install ./polaris-*.noarch.rpm ## 🧩 Supported Platform -Polaris is built specifically for **Fedora 43 KDE Workstation (Plasma 6)**. It leverages `dnf5`, Btrfs-specific tools, and KDE-native configurations to provide a seamless experience. +Polaris is built and tested on **Fedora 43 and 44** with KDE Plasma and GNOME (GDM). It leverages `dnf5` and Btrfs-specific tools to provide a seamless post-install experience. ## 🧰 Included Features @@ -62,12 +62,12 @@ The app auto-detects what is already on your system and organizes tools into ded * **AMD GPU Tools**: Monitoring (`radeontop`) and VA-API hardware acceleration. ### Security -* **Password Managers**: 1Password (official repo), Proton Pass (RPM). +* **Password Managers**: 1Password (official repo), Proton Pass (RPM), Bitwarden (Flatpak). * **VPN**: Tailscale mesh networking. ### Gaming -* **Launchers**: Steam, Lutris, Heroic (AppImage), CurseForge (AppImage), Prism Launcher (Flatpak). -* **Tools**: Wine, GameMode, Gamescope, MangoHud, GOverlay, ProtonUp-Qt. +* **Launchers**: Steam, Lutris, Heroic (AppImage), CurseForge (AppImage), Faugus Launcher, Prism Launcher (Flatpak). +* **Tools**: Wine, Bottles (Flatpak), GameMode, Gamescope, MangoHud, GOverlay, ProtonUp-Qt. * **Input**: Input Remapper for gamepads/mice. ### Containers @@ -77,13 +77,14 @@ The app auto-detects what is already on your system and organizes tools into ded ### System Tools * **Hardware**: LACT (AMD Control), CoolerControl, OpenRGB, Piper (Mice). * **Filesystem**: Btrfs Assistant & Snapper for snapshot management. -* **Utilities**: KDE Connect, Flatseal, Warehouse. +* **Utilities**: Flatseal, Warehouse. ### Media & Apps -* **Productivity**: VS Code, JetBrains Toolbox, LibreOffice. -* **Communication**: Discord (RPM), Vesktop, Slack, Signal, Telegram, Element, Mattermost. -* **Media**: OBS Studio, VLC, EasyEffects, Pulsemeeter, Flameshot. -* **Graphics**: GIMP, Kdenlive. +* **Productivity**: VS Code, JetBrains Toolbox, LibreOffice (Flatpak), Apache OpenOffice (Flatpak). +* **Communication**: Thunderbird (Flatpak), Discord (RPM), Vesktop, Slack, Signal, Telegram, Element, Mattermost. +* **Utilities**: Zoom, Google Chrome, LocalSend (Flatpak). +* **Media**: OBS Studio, VLC, HandBrake (Flatpak), EasyEffects, Pulsemeeter, Flameshot. +* **Graphics**: GIMP (Flatpak), Kdenlive (Flatpak). ## 🔐 Privilege & Security Model diff --git a/docs/index.html b/docs/index.html index 7563dd0..92c2564 100644 --- a/docs/index.html +++ b/docs/index.html @@ -3,10 +3,10 @@ - Polaris - One-Click Fedora KDE Setup Tool - + Polaris - One-Click Fedora Setup Tool + - + @@ -14,15 +14,15 @@ - - + + - - + + @@ -39,7 +39,7 @@ "name": "Polaris", "operatingSystem": "Linux", "applicationCategory": "UtilitiesApplication", - "description": "A PySide6 desktop application that simplifies post-install setup for Fedora KDE workstations. Install drivers, repositories, gaming tools, and apps with a single click.", + "description": "A PySide6 desktop application that simplifies post-install setup for Fedora workstations (43 and 44). Install drivers, repositories, gaming tools, and apps with a single click.", "url": "https://kernelchief.github.io/Polaris/", "downloadUrl": "https://github.com/KernelChief/Polaris/releases", "softwareVersion": "1.0.1", @@ -594,8 +594,8 @@

Polaris

-

Your Ultimate Companion for Fedora KDE Setup

-

Transform your fresh Fedora KDE installation into a powerful daily rig with Polaris. This intuitive PySide6 (Qt6) desktop application streamlines post-install tasks, from essential drivers and repositories to your favorite apps, all through a simple point-and-click interface.

+

Your Ultimate Companion for Fedora Setup

+

Transform your fresh Fedora installation into a powerful daily rig with Polaris. This intuitive PySide6 (Qt6) desktop application streamlines post-install tasks, from essential drivers and repositories to your favorite apps, all through a simple point-and-click interface.

Get Polaris Now Explore on GitHub @@ -619,18 +619,18 @@

Polaris

Why Polaris?

-

Setting up a Linux workstation shouldn't be a chore. Polaris was born from the desire to make Fedora KDE accessible and powerful for everyone, from seasoned users to those just making the switch. It's your reliable guide, ensuring a smooth and optimized experience.

+

Setting up a Linux workstation shouldn't be a chore. Polaris was born from the desire to make Fedora accessible and powerful for everyone, from seasoned users to those just making the switch. It's your reliable guide, ensuring a smooth and optimized experience.

North Star Reliability

-

Polaris is the essential first tool for navigating a new Fedora KDE install, guiding you through configurations with ease and ensuring your setup starts on the right path.

+

Polaris is the essential first tool for navigating a new Fedora install, guiding you through configurations with ease and ensuring your setup starts on the right path.

-

KDE-Native Experience

-

Built with PySide6 (Qt6), Polaris integrates seamlessly into your KDE Plasma desktop. Enjoy a native look and feel that respects your system's aesthetics and performance.

+

Qt-Native Experience

+

Built with PySide6 (Qt6), Polaris integrates seamlessly into your desktop — whether you're running KDE Plasma or GNOME. Enjoy a native look and feel that respects your system's aesthetics and performance.

@@ -712,7 +712,7 @@

Creativity & Communication

Get Started with Polaris

-

The easiest way to install and keep Polaris updated is via our official COPR repository. Follow these simple steps to begin your optimized Fedora KDE experience.

+

The easiest way to install and keep Polaris updated is via our official COPR repository. Follow these simple steps to begin your optimized Fedora experience.

@@ -736,7 +736,7 @@

3. Launch the Application

-

Important Note: Polaris is specifically built and optimized for Fedora 43 KDE Workstation (Plasma 6). While it might function on other Fedora versions, optimal performance and full feature compatibility are guaranteed only on the target platform.

+

Supported Platforms: Polaris is built and tested on Fedora 43 and 44 with both KDE Plasma and GNOME (GDM). It is a Fedora-only project — other distributions are not supported.

Alternative: Manual RPM Installation

diff --git a/src/packaging/build-rpm.sh b/src/packaging/build-rpm.sh index fbd1db7..2159f6e 100755 --- a/src/packaging/build-rpm.sh +++ b/src/packaging/build-rpm.sh @@ -2,38 +2,61 @@ # SPDX-License-Identifier: GPL-3.0-or-later set -euo pipefail -NAME="polaris" -VERSION="${1:-1.0}" -VERSION="${VERSION#v}" # strip leading 'v' — RPM Version field must not start with it +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" +SPEC="${ROOT_DIR}/src/packaging/polaris.spec" -# Ensure rpmbuild tree exists command -v rpmdev-setuptree >/dev/null 2>&1 || { echo "ERROR: rpmdevtools not installed. Install: sudo dnf install rpmdevtools" >&2 exit 1 } -rpmdev-setuptree >/dev/null 2>&1 || true - -ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)" -SPEC="${ROOT_DIR}/src/packaging/${NAME}.spec" if [[ ! -f "${SPEC}" ]]; then echo "ERROR: Spec not found: ${SPEC}" >&2 exit 2 fi +NAME="polaris" + +VERSION="${VERSION:-}" +if [[ -z "${VERSION}" && "${GITHUB_REF_TYPE:-}" == "tag" && -n "${GITHUB_REF_NAME:-}" ]]; then + VERSION="${GITHUB_REF_NAME#v}" +fi +if [[ -z "${VERSION}" && -n "${GITHUB_REF:-}" && "${GITHUB_REF}" == refs/tags/* ]]; then + VERSION="${GITHUB_REF#refs/tags/}" + VERSION="${VERSION#v}" +fi +VERSION="${VERSION#v}" + +RPM_VERSION="${VERSION}" +RPM_PRERELEASE="" + +# Convert semver prerelease tags like 1.0.5-rc1 into RPM-friendly fields: +# Version: 1.0.5 +# Release: 0.rc1.1%{?dist} +if [[ "${VERSION}" == *-* ]]; then + RPM_VERSION="${VERSION%%-*}" + RPM_PRERELEASE="${VERSION#*-}" + RPM_PRERELEASE="${RPM_PRERELEASE//-/.}" +fi + +if [[ -z "${NAME}" || -z "${VERSION}" || -z "${RPM_VERSION}" ]]; then + echo "ERROR: Could not determine Name/Version. Set VERSION or run on a tag (e.g., v1.0.4)." >&2 + exit 3 +fi + +rpmdev-setuptree >/dev/null 2>&1 || true + TMPDIR="$(mktemp -d)" trap 'rm -rf "$TMPDIR"' EXIT # Directory name must match %setup -n Polaris-%{version} in the spec -# Tarball name must match the Source0 URL basename: v%{version}.tar.gz -SRC_DIR="${TMPDIR}/Polaris-${VERSION}" +SRC_DIR="${TMPDIR}/Polaris-${RPM_VERSION}" mkdir -p "${SRC_DIR}" -# Copy repo contents into tarball staging directory -# Exclude git + common junk rsync -a \ --exclude ".git" \ --exclude ".github" \ + --exclude ".idea" \ --exclude "*/__pycache__" \ --exclude "*.pyc" \ --exclude "*.pyo" \ @@ -41,12 +64,26 @@ rsync -a \ --exclude "rpmbuild" \ "${ROOT_DIR}/" "${SRC_DIR}/" -TARBALL="${HOME}/rpmbuild/SOURCES/v${VERSION}.tar.gz" -tar -C "${TMPDIR}" -czf "${TARBALL}" "Polaris-${VERSION}" +TARBALL="${HOME}/rpmbuild/SOURCES/Polaris-${RPM_VERSION}.tar.gz" +tar -C "${TMPDIR}" -czf "${TARBALL}" "Polaris-${RPM_VERSION}" echo "Created source tarball: ${TARBALL}" +echo "Building ${NAME} version ${VERSION} using spec: ${SPEC}" + +RPM_RELEASE="1" +if [[ -n "${RPM_PRERELEASE}" ]]; then + RPM_RELEASE="0.${RPM_PRERELEASE}.1" +fi + +# Bake version/release into a temp copy of the spec so the SRPM is +# self-contained: COPR rebuilds from the SRPM without --define flags. +BUILD_SPEC="${TMPDIR}/polaris.spec" +sed \ + -e "s|%{!?app_version:%global app_version [^}]*}|%global app_version ${RPM_VERSION}|" \ + -e "s|%{!?app_release:%global app_release [^}]*}|%global app_release ${RPM_RELEASE}|" \ + "${SPEC}" > "${BUILD_SPEC}" -rpmbuild -ba "${SPEC}" --define "app_version ${VERSION}" +rpmbuild -ba "${BUILD_SPEC}" echo "Done." echo "RPMs are in: ${HOME}/rpmbuild/RPMS/" diff --git a/src/packaging/polaris.spec b/src/packaging/polaris.spec index ba77c9d..73db420 100644 --- a/src/packaging/polaris.spec +++ b/src/packaging/polaris.spec @@ -1,10 +1,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later Name: polaris -%{!?app_version:%global app_version 1.0.2} +%{!?app_version:%global app_version 1.0.3} +%{!?app_release:%global app_release 1} Version: %{app_version} -Release: 1%{?dist} -Summary: One-click workstation setup assistant for Fedora KDE +Release: %{app_release}%{?dist} +Summary: One-click workstation setup assistant for Fedora License: GPL-3.0-or-later URL: https://github.com/KernelChief/polaris BuildArch: noarch @@ -18,10 +19,10 @@ Requires: systemd Requires: dnf5 # Use the GitHub-generated tarball URL -Source0: https://github.com/KernelChief/Polaris/archive/refs/tags/v%{version}.tar.gz +Source0: https://github.com/KernelChief/Polaris/archive/v%{version}.tar.gz#/Polaris-%{version}.tar.gz %description -Polaris is a Qt-based graphical utility for Fedora 43 KDE workstations. +Polaris is a Qt-based graphical utility for Fedora workstations (43 and 44). It provides one-click install/remove actions for common workstation packages, drivers, and Flatpak apps using a PolicyKit-protected helper. @@ -52,6 +53,12 @@ install -D -m 0644 LICENSE \ %{_datadir}/licenses/%{name}/LICENSE %changelog +* Sat May 03 2026 KernelChief - 1.0.3-1 +- Add Fedora 44 support and GNOME/GDM compatibility +- Replace JetBrains Toolbox with PyCharm Community Edition +- Add OpenOffice (Flatpak), fix Element Flatpak ID +- Remove KDE Connect, add AppImage reboot warning dialog +- Fix dark-theme subtext, scrollbar over-scroll, Pulsemeeter detection * Sat May 03 2026 KernelChief - 1.0.2-1 - Update to v1.0.2: Add Polaris branding and logo * Sun Apr 26 2026 KernelChief - 1.0.1-1 diff --git a/src/polaris b/src/polaris index d8c9574..3557dea 100644 --- a/src/polaris +++ b/src/polaris @@ -137,7 +137,7 @@ def _load_logo(size: int) -> QPixmap: Qt.TransformationMode.SmoothTransformation) PROTON_PASS_URL = "https://proton.me/download/pass/linux/proton-pass-1.34.2-1.x86_64.rpm" -JETBRAINS_TOOLBOX_URL = "https://data.services.jetbrains.com/products/download?platform=linux&code=TBA" +PYCHARM_CE_URL = "https://data.services.jetbrains.com/products/download?platform=linux&code=PCC" APPIMAGELAUNCHER_URL = "https://github.com/TheAssassin/AppImageLauncher/releases/download/v3.0.0-beta-3/appimagelauncher_3.0.0-beta-2-gha287.96cb937_x86_64.rpm" HEROIC_URL = "https://github.com/Heroic-Games-Launcher/HeroicGamesLauncher/releases/download/v2.19.1/Heroic-2.19.1-linux-x86_64.AppImage" CURSEFORGE_URL = "https://curseforge.overwolf.com/downloads/curseforge-latest-linux.AppImage" @@ -251,6 +251,8 @@ FEATURES = [ "remove": [["remove_pkg", "proton-pass"]], "check": {"kind": "rpm", "pkg": "proton-pass"}, }, + {"id": "flatpak_bitwarden", "name": "🔐 Bitwarden (Flatpak)", "desc": "Free, open-source password manager", + "check": {"kind": "flatpak", "appid": "com.bitwarden.desktop"}}, { "id": "tailscale", "name": "🌐 Tailscale", @@ -295,6 +297,11 @@ FEATURES = [ "install": [["install_url_rpm", APPIMAGELAUNCHER_URL]], "remove": [["remove_pkg", "appimagelauncher"]], "check": {"kind": "rpm", "pkg": "appimagelauncher"}, + "post_install_note": ( + "AppImageLauncher is installed.\n\n" + "⚠️ A reboot (or log out and back in) is required for AppImages to be " + "integrated into your application menu." + ), }, { "id": "heroic_appimage", @@ -304,6 +311,11 @@ FEATURES = [ ["install_appimage", HEROIC_URL, "Heroic-2.19.1-linux-x86_64.AppImage"]], "remove": [["remove_appimage_glob", "*Heroic*.AppImage"]], "check": {"kind": "appimage_glob", "pattern": "*Heroic*.AppImage"}, + "post_install_note": ( + "Heroic Games Launcher has been downloaded.\n\n" + "⚠️ A reboot (or log out and back in) is required for it to appear " + "in your application menu." + ), }, { "id": "curseforge_appimage", @@ -314,10 +326,17 @@ FEATURES = [ "remove": [["remove_appimage_glob", "*curse*forge*.AppImage"]], "check": {"kind": "appimage_glob_any", "patterns": ["*curse*forge*.AppImage", "*Curse*Forge*.AppImage"]}, + "post_install_note": ( + "CurseForge has been downloaded.\n\n" + "⚠️ A reboot (or log out and back in) is required for it to appear " + "in your application menu." + ), }, {"id": "input_remapper", "name": "🕹️ Input Remapper", "desc": "Remap keyboard, mouse and gamepad inputs", "install": [["install_pkg", "input-remapper"]], "remove": [["remove_pkg", "input-remapper"]], "check": {"kind": "rpm", "pkg": "input-remapper"}}, + {"id": "flatpak_bottles", "name": "🍾 Bottles (Flatpak)", "desc": "Run Windows apps and games in isolated Wine environments", + "check": {"kind": "flatpak", "appid": "com.usebottles.bottles"}}, {"id": "flatpak_protonupqt", "name": "⬆️ ProtonUp-Qt (Flatpak)", "desc": "Install and manage Proton-GE and Wine-GE versions", "check": {"kind": "flatpak", "appid": "net.davidotek.pupgui2"}}, {"id": "flatpak_prismlauncher", "name": "⛏️ Prism Launcher (Flatpak)", "desc": "Mod-friendly Minecraft launcher", @@ -347,9 +366,7 @@ FEATURES = [ {"id": "btrfs_assistant", "name": "🗂️ Btrfs Assistant", "desc": "GUI tools for Btrfs snapshot management", "install": [["install_pkg", "btrfs-assistant"]], "remove": [["remove_pkg", "btrfs-assistant"]], "check": {"kind": "rpm", "pkg": "btrfs-assistant"}}, - {"id": "kdeconnect", "name": "📱 KDE Connect", "desc": "Link your Android or iOS phone to your KDE desktop", - "install": [["install_pkg", "kdeconnect"]], "remove": [["remove_pkg", "kdeconnect"]], - "check": {"kind": "rpm", "pkg": "kdeconnect"}}, + {"id": "piper", "name": "🖱️ Piper", "desc": "GUI for configuring gaming mice via libratbag", "install": [["install_pkg", "piper"]], "remove": [["remove_pkg", "piper"]], "check": {"kind": "rpm", "pkg": "piper"}}, @@ -361,6 +378,8 @@ FEATURES = [ {"id": "flatpak_warehouse", "name": "🏪 Warehouse (Flatpak)", "desc": "Browse and manage all installed Flatpaks", "check": {"kind": "flatpak", "appid": "io.github.flattool.Warehouse"}}, # ── MEDIA & UTILITIES ─────────────────────────────────────────────────── + {"id": "flatpak_handbrake", "name": "🎞️ HandBrake (Flatpak)", "desc": "Video transcoder — convert and compress video files", + "check": {"kind": "flatpak", "appid": "fr.handbrake.ghb"}}, {"id": "obs_studio", "name": "📺 OBS Studio", "desc": "Recording and streaming studio", "install": [["install_pkg", "obs-studio"]], "remove": [["remove_pkg", "obs-studio"]], "check": {"kind": "rpm", "pkg": "obs-studio"}}, @@ -372,7 +391,7 @@ FEATURES = [ "check": {"kind": "rpm", "pkg": "easyeffects"}}, {"id": "pulsemeeter_audio", "name": "🔊 Pulsemeeter", "desc": "Advanced audio routing controls", "install": [["install_pulsemeeter"]], "remove": [["remove_pulsemeeter"]], - "check": {"kind": "rpm", "pkg": "pulsemeeter"}}, + "check": {"kind": "python_module", "module": "pulsemeeter"}}, {"id": "flameshot", "name": "📸 Flameshot", "desc": "Screenshot tool with annotation support", "install": [["install_pkg", "flameshot"]], "remove": [["remove_pkg", "flameshot"]], "check": {"kind": "rpm", "pkg": "flameshot"}}, @@ -392,6 +411,10 @@ FEATURES = [ "check": {"kind": "repo_and_pkg", "repo_prefix": "code", "repo_file": "/etc/yum.repos.d/vscode.repo", "pkg": "code"}, }, + {"id": "flatpak_thunderbird", "name": "🦅 Thunderbird (Flatpak)", "desc": "Mozilla email and calendar client", + "check": {"kind": "flatpak", "appid": "org.mozilla.Thunderbird"}}, + {"id": "flatpak_localsend", "name": "📡 LocalSend (Flatpak)", "desc": "Open-source AirDrop alternative for local network file sharing", + "check": {"kind": "flatpak", "appid": "org.localsend.localsend_app"}}, {"id": "flatpak_spotify", "name": "🎵 Spotify (Flatpak)", "desc": "Music streaming app", "check": {"kind": "flatpak", "appid": "com.spotify.Client"}}, {"id": "discord", "name": "💬 Discord", "desc": "Voice and chat — ⚠️ RPM Fusion Non-Free must be installed first", @@ -404,8 +427,10 @@ FEATURES = [ "check": {"kind": "flatpak", "appid": "com.slack.Slack"}}, {"id": "flatpak_mattermost", "name": "🗨️ Mattermost (Flatpak)", "desc": "Self-hosted team chat", "check": {"kind": "flatpak", "appid": "com.mattermost.Desktop"}}, - {"id": "flatpak_libreoffice", "name": "📄 LibreOffice (Flatpak)", "desc": "Full office suite", + {"id": "flatpak_libreoffice", "name": "📄 LibreOffice (Flatpak)", "desc": "Full office suite", "check": {"kind": "flatpak", "appid": "org.libreoffice.LibreOffice"}}, + {"id": "flatpak_openoffice", "name": "📄 Apache OpenOffice (Flatpak)", "desc": "Classic office suite — Writer, Calc, Impress and more", + "check": {"kind": "flatpak", "appid": "org.openoffice.OpenOffice"}}, {"id": "flatpak_gimp", "name": "🖌️ GIMP (Flatpak)", "desc": "GNU Image Manipulation Program", "check": {"kind": "flatpak", "appid": "org.gimp.GIMP"}}, {"id": "flatpak_kdenlive", "name": "🎬 Kdenlive (Flatpak)", "desc": "Open-source video editor", @@ -413,16 +438,16 @@ FEATURES = [ {"id": "flatpak_signal", "name": "🔒 Signal (Flatpak)", "desc": "Secure end-to-end encrypted messaging", "check": {"kind": "flatpak", "appid": "org.signal.Signal"}}, {"id": "flatpak_element", "name": "💬 Element (Flatpak)", "desc": "Matrix / Element chat client (self-hostable)", - "check": {"kind": "flatpak", "appid": "io.element.Element"}}, + "check": {"kind": "flatpak", "appid": "im.riot.Riot"}}, {"id": "flatpak_telegram", "name": "✈️ Telegram (Flatpak)", "desc": "Telegram desktop messaging app", "check": {"kind": "flatpak", "appid": "org.telegram.desktop"}}, { - "id": "jetbrains_toolbox", - "name": "🧰 JetBrains Toolbox", - "desc": "Manage all JetBrains IDEs (PyCharm, IntelliJ, Rider…) from one launcher", - "install": [["install_jetbrains_toolbox"]], - "remove": [["remove_jetbrains_toolbox"]], - "check": {"kind": "file", "path": "/usr/local/bin/jetbrains-toolbox"}, + "id": "pycharm_ce", + "name": "🐍 PyCharm Community Edition", + "desc": "Free Python IDE by JetBrains — full-featured, no subscription required", + "install": [["install_pycharm_ce"]], + "remove": [["remove_pycharm_ce"]], + "check": {"kind": "file", "path": "/usr/local/bin/pycharm"}, }, ] @@ -441,19 +466,19 @@ GAMING_BUNDLE = [ TABS = [ ("🚀 Get Started", ["rpmfusion", "flathub", "essential", "monitoring", "zram_profile"]), ("🔌 Drivers", ["nvidia_drivers", "amd_tools"]), - ("🔐 Security", ["onepassword", "proton_pass", "tailscale"]), + ("🔐 Security", ["onepassword", "proton_pass", "flatpak_bitwarden", "tailscale"]), ("🎮 Gaming", ["steam", "lutris", "wine", "gamemode", "gamescope", "mangohud", "goverlay", "faugus_launcher", "appimagelauncher", "heroic_appimage", "curseforge_appimage", - "input_remapper", "flatpak_protonupqt", + "input_remapper", "flatpak_bottles", "flatpak_protonupqt", "flatpak_prismlauncher"]), ("📦 Containers", ["podman", "distrobox", "flatpak_boxbuddy", "flatpak_podman_desktop"]), ("🛠️ Tools", ["lact", "coolercontrol", "openrgbtool", "btrfs_assistant", "kdeconnect", "piper", "snapper", "flatpak_flatseal", "flatpak_warehouse"]), - ("🎬 Media", ["obs_studio", "vlc", "easyeffects", "pulsemeeter_audio", "flameshot"]), + ("🎬 Media", ["obs_studio", "vlc", "flatpak_handbrake", "easyeffects", "pulsemeeter_audio", "flameshot"]), ("💻 Apps", ["chrome", "zoom_rpm", "vscode", "jetbrains_toolbox", - "flatpak_spotify", "discord", + "flatpak_thunderbird", "flatpak_localsend", "flatpak_spotify", "discord", "flatpak_vesktop", "flatpak_slack", "flatpak_mattermost", - "flatpak_libreoffice", "flatpak_gimp", "flatpak_kdenlive", + "flatpak_libreoffice", "flatpak_openoffice", "flatpak_gimp", "flatpak_kdenlive", "flatpak_signal", "flatpak_element", "flatpak_telegram"]), ] @@ -565,7 +590,8 @@ class Polaris(QMainWindow): vbox.addLayout(title_row) subtitle = QLabel( - "Set up your Fedora 43 KDE workstation in a few clicks. " + "Set up your Fedora 43 / 44 workstation in a few clicks. " + "Primarily tested on KDE Plasma — most features work on GNOME and other spins too. " "New here? Hit Recommended Setup — it handles the essentials automatically. " "Then explore the tabs for more." ) @@ -643,9 +669,9 @@ class Polaris(QMainWindow): all_rows_layout = QVBoxLayout(all_inner) all_rows_layout.setContentsMargins(4, 4, 4, 4) all_rows_layout.setSpacing(4) - all_rows_layout.setAlignment(Qt.AlignmentFlag.AlignTop) for f in FEATURES: self._add_row(f, all_rows_layout, target_store=self.all_rows) + all_rows_layout.addStretch(1) all_scroll.setWidget(all_inner) all_layout.addWidget(all_scroll) tabs.addTab(all_widget, "🔍 All") @@ -664,12 +690,12 @@ class Polaris(QMainWindow): rows_layout = QVBoxLayout(scroll_inner) rows_layout.setContentsMargins(4, 4, 4, 4) rows_layout.setSpacing(4) - rows_layout.setAlignment(Qt.AlignmentFlag.AlignTop) for fid in feature_ids: f = FEATURE_BY_ID.get(fid) if f: self._add_row(f, rows_layout) + rows_layout.addStretch(1) scroll.setWidget(scroll_inner) tab_layout.addWidget(scroll) @@ -712,7 +738,6 @@ class Polaris(QMainWindow): name_lbl = QLabel(f["name"]) name_lbl.setStyleSheet("font-weight: bold;") desc_lbl = QLabel(f["desc"]) - desc_lbl.setStyleSheet("color: palette(mid);") desc_lbl.setWordWrap(True) info_vbox.addWidget(name_lbl) info_vbox.addWidget(desc_lbl) @@ -874,6 +899,11 @@ class Polaris(QMainWindow): return False if kind == "file": return Path(check["path"]).exists() + if kind == "python_module": + return subprocess.run( + [sys.executable, "-c", f"import {check['module']}"], + stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, + ).returncode == 0 return False # ── State refresh ────────────────────────────────────────────────────── @@ -1012,7 +1042,20 @@ class Polaris(QMainWindow): label = "Removing…" if d["applied"] else "Installing…" self._set_busy(fid, True, label) - self._run_action_sequence(actions, on_done=lambda: self._done(fid), on_abort=lambda: self._done(fid)) + + is_install = not d["applied"] + note = d["feature"].get("post_install_note") if is_install else None + + def on_install_done(): + self._done(fid) + if note: + QMessageBox.information(self, "Reboot Required", note) + + self._run_action_sequence( + actions, + on_done=on_install_done if note else lambda: self._done(fid), + on_abort=lambda: self._done(fid), + ) # ── Busy state ───────────────────────────────────────────────────────── diff --git a/src/polaris-helper b/src/polaris-helper index f0372d8..4eacdee 100644 --- a/src/polaris-helper +++ b/src/polaris-helper @@ -306,26 +306,45 @@ remove_flathub() { flatpak remote-delete --system flathub 2>/dev/null || true } -JETBRAINS_TOOLBOX_URL="https://data.services.jetbrains.com/products/download?platform=linux&code=TBA" +PYCHARM_CE_URL="https://data.services.jetbrains.com/products/download?platform=linux&code=PCC" -install_jetbrains_toolbox() { +install_pycharm_ce() { local tmpdir tmpdir="$(mktemp -d)" trap 'rm -rf "${tmpdir}"' EXIT - log "Downloading JetBrains Toolbox..." - curl -fsSL -o "${tmpdir}/toolbox.tar.gz" "${JETBRAINS_TOOLBOX_URL}" - tar -xzf "${tmpdir}/toolbox.tar.gz" -C "${tmpdir}" + log "Downloading PyCharm Community Edition..." + curl -fsSL -o "${tmpdir}/pycharm-ce.tar.gz" "${PYCHARM_CE_URL}" + tar -xzf "${tmpdir}/pycharm-ce.tar.gz" -C "${tmpdir}" - local binary - binary="$(find "${tmpdir}" -name "jetbrains-toolbox" -type f | head -1)" - [[ -n "${binary}" ]] || { echo "ERROR: jetbrains-toolbox binary not found in archive" >&2; exit 2; } + local extracted + extracted="$(find "${tmpdir}" -maxdepth 1 -type d -name "pycharm-*" | head -1)" + [[ -n "${extracted}" ]] || { echo "ERROR: PyCharm directory not found in archive" >&2; exit 2; } - install -D -m 0755 "${binary}" /usr/local/bin/jetbrains-toolbox + rm -rf /opt/pycharm-ce + mv "${extracted}" /opt/pycharm-ce + ln -sf /opt/pycharm-ce/bin/pycharm /usr/local/bin/pycharm + + install -D -m 0644 /opt/pycharm-ce/bin/pycharm.png /usr/share/pixmaps/pycharm-ce.png 2>/dev/null || true + cat >/usr/share/applications/pycharm-ce.desktop <<'DESKTOP' +[Desktop Entry] +Name=PyCharm Community Edition +Comment=Python IDE for Professional Developers +Exec=/opt/pycharm-ce/bin/pycharm +Icon=pycharm-ce +Terminal=false +Type=Application +Categories=Development;IDE; +StartupWMClass=jetbrains-pycharm-ce +DESKTOP + chmod 0644 /usr/share/applications/pycharm-ce.desktop } -remove_jetbrains_toolbox() { - rm -f /usr/local/bin/jetbrains-toolbox +remove_pycharm_ce() { + rm -f /usr/local/bin/pycharm + rm -rf /opt/pycharm-ce + rm -f /usr/share/applications/pycharm-ce.desktop + rm -f /usr/share/pixmaps/pycharm-ce.png } install_flatpak_app() { @@ -400,8 +419,8 @@ case "${action}" in remove_appimage_glob) remove_appimage_glob "${2:-}" ;; setup_flathub) setup_flathub ;; remove_flathub) remove_flathub ;; - install_jetbrains_toolbox) install_jetbrains_toolbox ;; - remove_jetbrains_toolbox) remove_jetbrains_toolbox ;; + install_pycharm_ce) install_pycharm_ce ;; + remove_pycharm_ce) remove_pycharm_ce ;; install_flatpak_app) install_flatpak_app "${2:-}" "${3:-system}" ;; remove_flatpak_app) remove_flatpak_app "${2:-}" ;; *)