Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package vermouth for openSUSE:Factory checked in at 2026-04-22 16:58:13 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/vermouth (Old) and /work/SRC/openSUSE:Factory/.vermouth.new.11940 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "vermouth" Wed Apr 22 16:58:13 2026 rev:3 rq:1348611 version:1.3.4 Changes: -------- --- /work/SRC/openSUSE:Factory/vermouth/vermouth.changes 2026-04-20 16:12:00.758920118 +0200 +++ /work/SRC/openSUSE:Factory/.vermouth.new.11940/vermouth.changes 2026-04-22 16:59:02.782635386 +0200 @@ -1,0 +2,16 @@ +Tue Apr 21 16:37:59 UTC 2026 - Jehu Marcos Herrera Puentes <[email protected]> + +- Added proper lang subpackage for SUSE builds +- Bump to version 1.3.4 +- Upstream changes: + * fix: HDR enablement fix + * fix: When deleting the prefix path while editing, return to defaults +- For version 1.3.3: + * Add the translation files to the spec + * feat: Translations! + * Stop button + HDR disable + * Tidy up the grid + * Run known exe, env vars + * Update PKGBUILD + +------------------------------------------------------------------- Old: ---- vermouth-1.3.2.tar.xz New: ---- vermouth-1.3.4.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ vermouth.spec ++++++ --- /var/tmp/diff_new_pack.e3mTQX/_old 2026-04-22 16:59:03.642670974 +0200 +++ /var/tmp/diff_new_pack.e3mTQX/_new 2026-04-22 16:59:03.642670974 +0200 @@ -17,7 +17,7 @@ Name: vermouth -Version: 1.3.2 +Version: 1.3.4 Release: 0 Summary: A Wine/Proton game launcher for KDE License: MIT @@ -76,6 +76,9 @@ It works like Lutris, Heroic, Faugus or Bottles, but is KDE first (written in Qt/QML and using Kirigami). +# Lang subpackage +%lang_package + %prep %autosetup -p1 @@ -89,6 +92,9 @@ # Remove duplicated files %fdupes %{buildroot}%{_datadir} +# Lang files +%find_lang vermouth %{name}.lang + %check # Checks for desktop files and appstream metadata desktop-file-validate %{buildroot}%{_datadir}/applications/*.desktop @@ -109,3 +115,6 @@ # Application data %{_datadir}/metainfo/com.dekomote.vermouth.metainfo.xml +# Language files for the subpackage +%files lang -f %{name}.lang + ++++++ _service ++++++ --- /var/tmp/diff_new_pack.e3mTQX/_old 2026-04-22 16:59:03.726674450 +0200 +++ /var/tmp/diff_new_pack.e3mTQX/_new 2026-04-22 16:59:03.738674947 +0200 @@ -3,7 +3,7 @@ <service name="tar_scm" mode="manual"> <param name="scm">git</param> <param name="url">https://github.com/dekomote/vermouth.git</param> - <param name="revision">v1.3.2</param> + <param name="revision">v1.3.4</param> <param name="match-tag">v[0-9]*</param> <param name="filename">vermouth</param> <param name="changesgenerate">enable</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.e3mTQX/_old 2026-04-22 16:59:03.774676436 +0200 +++ /var/tmp/diff_new_pack.e3mTQX/_new 2026-04-22 16:59:03.778676602 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/dekomote/vermouth.git</param> - <param name="changesrevision">a71963b74a4b0f7a23745263633e845eef816b36</param></service></servicedata> + <param name="changesrevision">5d3bee6fe69f1dce4ae12f650991538a87744bc8</param></service></servicedata> (No newline at EOF) ++++++ vermouth-1.3.2.tar.xz -> vermouth-1.3.4.tar.xz ++++++ ++++ 2049 lines of diff (skipped) ++++ retrying with extended exclude list diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/CMakeLists.txt new/vermouth-1.3.4/CMakeLists.txt --- old/vermouth-1.3.2/CMakeLists.txt 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/CMakeLists.txt 2026-04-21 17:18:28.000000000 +0200 @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.20) -project(vermouth VERSION 1.3.2 LANGUAGES CXX) +project(vermouth VERSION 1.3.4 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -90,6 +90,8 @@ APP_ID="${APP_ID}" ) +ki18n_install(po) + install(TARGETS vermouth ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES assets/${APP_ID}.desktop DESTINATION ${KDE_INSTALL_APPDIR}) install(FILES assets/${APP_ID}.svg DESTINATION ${KDE_INSTALL_FULL_ICONDIR}/hicolor/scalable/apps) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/README.md new/vermouth-1.3.4/README.md --- old/vermouth-1.3.2/README.md 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/README.md 2026-04-21 17:18:28.000000000 +0200 @@ -204,6 +204,32 @@ Games are stored in `~/.config/vermouth/apps.json`. When umu-launcher is available, Proton is launched through it with `PROTONPATH` and `STEAM_COMPAT_DATA_PATH` set. Without umu, Vermouth calls the `proton run` script directly, the same way Steam does. Wine games get `WINEPREFIX` set and the binary called directly. +## Contributing + +Contributions are welcome. Please open a pull request on [GitHub](https://github.com/dekomote/vermouth). + +### Code + +Build from source (see [Building from source](#building-from-source)), make your changes, and open a pull request. Keep changes focused - one feature or fix per PR. + +### Translations + +Vermouth uses the KDE i18n system (gettext `.po` files). To add or update a translation: + +1. Create a folder `po/<language_code>/` (e.g. `po/fr/` for French, `po/pt_BR/` for Brazilian Portuguese). +2. Copy `po/vermouth.pot` into it as `vermouth.po` (e.g. `po/fr/vermouth.po`). +3. Fill in the `msgstr` fields with your translations. +4. Open a pull request with your new folder. + +To update an existing translation after new strings have been added: + +```bash +sh po/Messages.sh # regenerate vermouth.pot from source +sh po/update-po.sh # merge new strings into all .po files +``` + +Then fill in any new empty `msgstr ""` entries in your `.po` file. + ## AI Disclaimer The code has been developed, reviewed and tested by a human. However, development included assistance of AI tools, so keep that in mind. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/com.dekomote.vermouth.flathub.yml new/vermouth-1.3.4/com.dekomote.vermouth.flathub.yml --- old/vermouth-1.3.2/com.dekomote.vermouth.flathub.yml 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/com.dekomote.vermouth.flathub.yml 2026-04-21 17:18:28.000000000 +0200 @@ -20,4 +20,4 @@ sources: - type: git url: https://github.com/dekomote/vermouth.git - tag: v1.3.2 + tag: v1.3.4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/packaging/.SRCINFO new/vermouth-1.3.4/packaging/.SRCINFO --- old/vermouth-1.3.2/packaging/.SRCINFO 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/packaging/.SRCINFO 2026-04-21 17:18:28.000000000 +0200 @@ -1,6 +1,6 @@ pkgbase = vermouth pkgdesc = A no-frills Wine/Proton game launcher for Linux - pkgver = 1.3.1 + pkgver = 1.3.4 pkgrel = 1 url = https://github.com/dekomote/vermouth arch = x86_64 @@ -15,7 +15,7 @@ depends = kcoreaddons depends = qqc2-desktop-style optdepends = icoutils: Windows icon extraction - source = vermouth-1.3.1.tar.gz::https://github.com/dekomote/vermouth/archive/refs/tags/v1.3.1.tar.gz - sha256sums = e6cb0ee4616d6c7485d5fb73f6c1f25b7563747bcd731be045c148391b51a730 + source = vermouth-1.3.4.tar.gz::https://github.com/dekomote/vermouth/archive/refs/tags/v1.3.4.tar.gz + sha256sums = c69c0884225867130d3f09fbcb55bf8cbb578f9a9b9fecb4993890aab9d366b5 pkgname = vermouth diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/packaging/PKGBUILD new/vermouth-1.3.4/packaging/PKGBUILD --- old/vermouth-1.3.2/packaging/PKGBUILD 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/packaging/PKGBUILD 2026-04-21 17:18:28.000000000 +0200 @@ -1,6 +1,6 @@ # Maintainer: Dejan Noveski <[email protected]> pkgname=vermouth -pkgver=1.3.2 +pkgver=1.3.4 pkgrel=1 pkgdesc="A no-frills Wine/Proton game launcher for Linux" arch=('x86_64') @@ -21,7 +21,7 @@ ) optdepends=('icoutils: Windows icon extraction') source=("${pkgname}-${pkgver}.tar.gz::https://github.com/dekomote/vermouth/archive/refs/tags/v${pkgver}.tar.gz") -sha256sums=('e6cb0ee4616d6c7485d5fb73f6c1f25b7563747bcd731be045c148391b51a730') +sha256sums=('c69c0884225867130d3f09fbcb55bf8cbb578f9a9b9fecb4993890aab9d366b5') build() { cd "${pkgname}-${pkgver}" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/packaging/vermouth.spec new/vermouth-1.3.4/packaging/vermouth.spec --- old/vermouth-1.3.2/packaging/vermouth.spec 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/packaging/vermouth.spec 2026-04-21 17:18:28.000000000 +0200 @@ -1,5 +1,5 @@ Name: vermouth -Version: 1.3.2 +Version: 1.3.4 Release: 1%{?dist} Summary: A no-frills Wine/Proton game launcher for KDE License: MIT @@ -67,8 +67,13 @@ %{_datadir}/applications/com.dekomote.vermouth.desktop %{_datadir}/icons/hicolor/scalable/apps/com.dekomote.vermouth.svg %{_datadir}/metainfo/com.dekomote.vermouth.metainfo.xml +%{_datadir}/locale/*/LC_MESSAGES/vermouth.mo %changelog +* Tue Apr 21 2026 Dejan Noveski <[email protected]> - 1.3.4-1 +- Single prefix fix, HDR Enable fix for full gamut monitors +* Mon Apr 20 2026 Dejan Noveski <[email protected]> - 1.3.3-1 +- Single prefix support, known exe launch, Stop button, HDR disable, translations * Fri Apr 17 2026 Dejan Noveski <[email protected]> - 1.3.2-1 - UMU prefix fixed, added single instance support * Fri Apr 17 2026 Dejan Noveski <[email protected]> - 1.3.1-1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/po/messages.sh new/vermouth-1.3.4/po/messages.sh --- old/vermouth-1.3.2/po/messages.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/vermouth-1.3.4/po/messages.sh 2026-04-21 17:18:28.000000000 +0200 @@ -0,0 +1,30 @@ +#!/bin/sh +# Extracts translatable strings from C++ and QML sources into vermouth.pot + +BASEDIR=$(dirname "$0")/.. +POTFILE="$BASEDIR/po/vermouth.pot" + +find "$BASEDIR/src" -name "*.cpp" -o -name "*.h" | sort | \ +xgettext --files-from=- \ + --language=C++ \ + --keyword=i18n \ + --keyword=i18nc:1c,2 \ + --keyword=i18np:1,2 \ + --keyword=i18ncp:1c,2,3 \ + --from-code=UTF-8 \ + --output="$POTFILE" \ + --package-name=vermouth \ + +find "$BASEDIR/qml" -name "*.qml" | sort | \ +xgettext --files-from=- \ + --language=JavaScript \ + --keyword=i18n \ + --keyword=i18nc:1c,2 \ + --keyword=i18np:1,2 \ + --keyword=i18ncp:1c,2,3 \ + --from-code=UTF-8 \ + --join-existing \ + --output="$POTFILE" \ + --package-name=vermouth \ + +echo "Updated $POTFILE" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/po/mk/vermouth.po new/vermouth-1.3.4/po/mk/vermouth.po --- old/vermouth-1.3.2/po/mk/vermouth.po 1970-01-01 01:00:00.000000000 +0100 +++ new/vermouth-1.3.4/po/mk/vermouth.po 2026-04-21 17:18:28.000000000 +0200 @@ -0,0 +1,550 @@ +# Vermouth in Macedonian. +# Copyright (C) 2026 DEJAN NOVESKI +# This file is distributed under the same license as the PACKAGE package. +# DEJAN NOVESKI <[email protected]>, 2026. +# +msgid "" +msgstr "" +"Project-Id-Version: 1.3.3\n" +"Report-Msgid-Bugs-To: [email protected]\n" +"POT-Creation-Date: 2026-04-20 12:28+0200\n" +"PO-Revision-Date: 2026-04-20 11:37+0200\n" +"Last-Translator: DEJAN NOVESKI <[email protected]>\n" +"Language-Team: Macedonian\n" +"Language: mk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n % 10 == 1 && n % 100 != 11) ? 0 : 1;\n" + +#: po/../src/main.cpp:27 +msgid "Vermouth" +msgstr "Vermouth" + +#: po/../src/main.cpp:32 +msgid "Lead Developer" +msgstr "Главен програмер" + +#: po/../src/main.cpp:47 +msgid "Launch app by its config ID" +msgstr "Стартувaj апликација по нејзиниот конфигурациски ID" + +#: po/../src/main.cpp:48 +msgid "Launch exe with Proton" +msgstr "Стартувaj exe со Proton" + +#: po/../src/main.cpp:49 +msgid "Launch exe with Wine" +msgstr "Стартуваj exe со Wine" + +#: po/../src/main.cpp:50 +msgid "Proton path" +msgstr "Патека до Proton" + +#: po/../src/main.cpp:51 +msgid "Wine binary path" +msgstr "Патека до Wine бинарна датотека" + +#: po/../src/main.cpp:52 +msgid "Prefix path" +msgstr "Патека до префикс" + +#: po/../src/main.cpp:53 +#, c-format +msgid "Launch options (use %command% as placeholder)" +msgstr "Опции за стартување (користете %command% како замена)" + +#: po/../src/main.cpp:54 +msgid "Enable logging to file" +msgstr "Овозможи запишување во датотека" + +#: po/../src/main.cpp:64 +msgid "File or URI to open" +msgstr "Датотека или URI за отворање" + +#: po/../qml/AddAppDialog.qml:9 +msgid "Edit App/Game" +msgstr "Уреди апликација/игра" + +#: po/../qml/AddAppDialog.qml:9 +msgid "Add App/Game" +msgstr "Додади апликација/игра" + +#: po/../qml/AddAppDialog.qml:17 +msgid "OK" +msgstr "Во ред" + +#: po/../qml/AddAppDialog.qml:27 po/../qml/RunExeStandaloneDialog.qml:27 +msgid "Cancel" +msgstr "Откажи" + +#: po/../qml/AddAppDialog.qml:97 +msgid "Name is required." +msgstr "Името е задолжително." + +#: po/../qml/AddAppDialog.qml:101 po/../qml/RunExeStandaloneDialog.qml:44 +msgid "Executable path is required." +msgstr "Патеката до извршната датотека е задолжителна." + +#: po/../qml/AddAppDialog.qml:140 +msgid "Game" +msgstr "Игра" + +#: po/../qml/AddAppDialog.qml:146 +msgid "Name:" +msgstr "Име:" + +#: po/../qml/AddAppDialog.qml:147 +msgid "My Game" +msgstr "Моја игра" + +#: po/../qml/AddAppDialog.qml:151 po/../qml/RunExeDialog.qml:37 +#: po/../qml/RunExeStandaloneDialog.qml:92 +msgid "Executable (.exe):" +msgstr "Извршна датотека (.exe):" + +#: po/../qml/AddAppDialog.qml:164 +msgid "Icon (optional):" +msgstr "Икона (незадолжително):" + +#: po/../qml/AddAppDialog.qml:188 +msgid "Proton Prefix (optional):" +msgstr "Протон Префикс (незадолжително):" + +#: po/../qml/AddAppDialog.qml:202 +msgid "Wine Prefix (WINEPREFIX):" +msgstr "Wine Префикс (WINEPREFIX):" + +#: po/../qml/AddAppDialog.qml:216 po/../qml/RunExeStandaloneDialog.qml:116 +msgid "Options" +msgstr "Опции" + +#: po/../qml/AddAppDialog.qml:221 po/../qml/RunExeStandaloneDialog.qml:121 +msgid "Launch Options (optional):" +msgstr "Опции за стартување (незадолжително):" + +#: po/../qml/AddAppDialog.qml:222 +msgid "e.g. mangohud %command%" +msgstr "пр. mangohud %command%" + +#: po/../qml/AddAppDialog.qml:227 +msgid "Write output to log file" +msgstr "Запиши излез во датотека за дневник" + +#: po/../qml/AddAppDialog.qml:233 +msgid "Global Env Vars:" +msgstr "Глобални env променливи:" + +#: po/../qml/AddAppDialog.qml:244 po/../qml/RunExeDialog.qml:53 +#: po/../qml/RunExeStandaloneDialog.qml:129 +msgid "Select Executable" +msgstr "Изберете извршна датотека" + +#: po/../qml/AddAppDialog.qml:246 po/../qml/RunExeDialog.qml:55 +#: po/../qml/RunExeStandaloneDialog.qml:131 +msgid "Executables (*.exe)" +msgstr "Извршни датотеки (*.exe)" + +#: po/../qml/AddAppDialog.qml:246 po/../qml/AddAppDialog.qml:257 +#: po/../qml/RunExeDialog.qml:55 po/../qml/RunExeStandaloneDialog.qml:131 +msgid "All files (*)" +msgstr "Сите датотеки (*)" + +#: po/../qml/AddAppDialog.qml:255 +msgid "Select Icon" +msgstr "Изберете икона" + +#: po/../qml/AddAppDialog.qml:257 +msgid "Images (*.png *.svg *.ico *.jpg)" +msgstr "Слики (*.png *.svg *.ico *.jpg)" + +#: po/../qml/AddAppDialog.qml:263 +msgid "Select Proton Prefix Folder" +msgstr "Изберете папка за Proton Префикс" + +#: po/../qml/AddAppDialog.qml:270 +msgid "Select Wine Prefix Folder" +msgstr "Изберете папка за Wine Префикс" + +#: po/../qml/AppGridView.qml:226 +msgid "Stop" +msgstr "Запри" + +#: po/../qml/AppGridView.qml:226 +msgid "Launch" +msgstr "Стартувај" + +#: po/../qml/AppGridView.qml:240 +msgid "Launch with logging" +msgstr "Стартувај со запишување" + +#: po/../qml/AppGridView.qml:253 +msgid "Run another EXE in this prefix" +msgstr "Стартувај друг EXE во овој префикс" + +#: po/../qml/AppGridView.qml:262 +msgid "Create start menu entry" +msgstr "Создај ставка во стартното мени" + +#: po/../qml/AppGridView.qml:270 +msgid "Create desktop shortcut" +msgstr "Создај кратенка на работната површина" + +#: po/../qml/AppGridView.qml:278 +msgid "&Wine Utilities" +msgstr "&Wine алатки" + +#: po/../qml/AppGridView.qml:282 +msgid "Run Winecfg" +msgstr "Стартувај Winecfg" + +#: po/../qml/AppGridView.qml:290 +msgid "Run Regedit" +msgstr "Стартувај Regedit" + +#: po/../qml/AppGridView.qml:298 +msgid "Run Winetricks" +msgstr "Стартувај Winetricks" + +#: po/../qml/AppGridView.qml:312 +msgid "Open log folder" +msgstr "Отвори папка за дневник" + +#: po/../qml/AppGridView.qml:317 +msgid "Open prefix folder" +msgstr "Отвори папка за prefix" + +#: po/../qml/AppGridView.qml:328 +msgid "Edit" +msgstr "Уреди" + +#: po/../qml/AppGridView.qml:333 +msgid "Remove" +msgstr "Отстрани" + +#: po/../qml/AppGridView.qml:341 +msgid "Remove and Delete Prefix" +msgstr "Отстрани и избриши префикс" + +#: po/../qml/AppGridView.qml:354 +msgid "Delete both app and prefix?" +msgstr "Да се избришат и апликацијата и prefix-от?" + +#: po/../qml/AppGridView.qml:355 +msgid "This will delete both the app and the prefix?" +msgstr "Ова ќе ги избрише и апликацијата и префиксот." + +#: po/../qml/AppGridView.qml:363 +msgid "Delete the app?" +msgstr "Да се избрише апликацијата?" + +#: po/../qml/AppGridView.qml:364 +msgid "This will delete the app but preserve the prefix folder." +msgstr "Ова ќе ја избрише апликацијата, но ќе ја зачува папката со префиксот." + +#: po/../qml/AppGridView.qml:371 +msgid "Winetricks not found" +msgstr "Winetricks не е пронајден" + +#: po/../qml/AppGridView.qml:372 +msgid "" +"Winetricks is not installed on your system. Please install it using your " +"package manager." +msgstr "" +"Winetricks не е инсталиран на вашиот систем. Инсталирајте го преку вашиот " +"менаџер на пакети." + +#: po/../qml/AppGridView.qml:380 +msgid "No apps or games added yet" +msgstr "Сè уште нема додадено апликации или игри" + +#: po/../qml/AppGridView.qml:381 +msgid "Click \"Add App/Game\" to get started" +msgstr "Кликнете „Додади апликација/игра“ за да започнете" + +#: po/../qml/Main.qml:28 +msgid "Unpin sidebar" +msgstr "Откачи странична лента" + +#: po/../qml/Main.qml:28 +msgid "Pin sidebar" +msgstr "Закачи странична лента" + +#: po/../qml/Main.qml:36 po/../qml/Main.qml:90 +msgid "Add &App/Game" +msgstr "Додади &апликација/игра" + +#: po/../qml/Main.qml:41 +msgid "Run &Standalone EXE" +msgstr "Стартување на &самостоен EXE" + +#: po/../qml/Main.qml:46 po/../qml/Main.qml:132 +msgid "Allow Sleep" +msgstr "Дозволи спиење" + +#: po/../qml/Main.qml:46 po/../qml/Main.qml:132 +msgid "Prevent Sleep" +msgstr "Спречи спиење" + +#: po/../qml/Main.qml:53 po/../qml/Main.qml:142 +msgid "Disable HDR" +msgstr "Оневозможи HDR" + +#: po/../qml/Main.qml:53 po/../qml/Main.qml:142 +msgid "Enable HDR" +msgstr "Овозможи HDR" + +#: po/../qml/Main.qml:61 +msgid "&Settings" +msgstr "&Поставки" + +#: po/../qml/Main.qml:66 +msgid "&About Vermouth" +msgstr "&За Vermouth" + +#: po/../qml/Main.qml:71 +msgid "Quit" +msgstr "Излез" + +#: po/../qml/Main.qml:122 +msgid "%1 - %2" +msgstr "%1 — %2" + +#: po/../qml/Main.qml:185 +msgid "Open Executable" +msgstr "Отвори извршна датотека" + +#: po/../qml/Main.qml:190 +msgid "Run Standalone" +msgstr "Стартување самостојно" + +#: po/../qml/Main.qml:198 +msgid "Add to Library" +msgstr "Додади во библиотека" + +#: po/../qml/Main.qml:215 +msgid "Prefix not ready" +msgstr "Prefix не е подготвен" + +#: po/../qml/Main.qml:216 +msgid "" +"The prefix for \"%1\" has not been created yet. Please launch the game at " +"least once first." +msgstr "" +"Префикс за \"%1\" сè уште не е создаден. Ве молиме стартувајте ја играта " +"барем еднаш прво." + +#: po/../qml/Main.qml:270 +msgid "Launched: %1" +msgstr "Стартувано: %1" + +#: po/../qml/Main.qml:273 +msgid "Error: %1" +msgstr "Грешка: %1" + +#: po/../qml/RunExeDialog.qml:9 +msgid "Run EXE in Prefix" +msgstr "Стартување на EXE во префикс" + +#: po/../qml/RunExeDialog.qml:29 +msgid "Run an executable using the same prefix as \"%1\"" +msgstr "Стартување на извршна датотека со истиот префикс како \"%1\"" + +#: po/../qml/RunExeStandaloneDialog.qml:9 +msgid "Run Standalone EXE" +msgstr "Стартување на самостоен EXE" + +#: po/../qml/RunExeStandaloneDialog.qml:17 +msgid "Run" +msgstr "Стартувај" + +#: po/../qml/RunExeStandaloneDialog.qml:122 +msgid "e.g ENV_VAR1=2" +msgstr "пр. ENV_VAR1=2" + +#: po/../qml/RuntimePicker.qml:14 +msgid "Runtime" +msgstr "Извршно опкружување" + +#: po/../qml/RuntimePicker.qml:64 +msgid "Please select a Proton version." +msgstr "Изберете верзија на Proton." + +#: po/../qml/RuntimePicker.qml:67 +msgid "Wine binary path is required." +msgstr "Патеката до Wine бинарна датотека е задолжителна." + +#: po/../qml/RuntimePicker.qml:106 +msgid "Runtime:" +msgstr "Извршно опкружување:" + +#: po/../qml/RuntimePicker.qml:112 +msgid "Proton Version:" +msgstr "Верзија на Proton:" + +#: po/../qml/RuntimePicker.qml:118 po/../qml/RuntimePicker.qml:120 +msgid "" +"No Proton versions found. Download GE Proton to get started - no Steam or " +"manual setup needed." +msgstr "" +"Не се пронајдени верзии на Proton. Преземете GE Proton за да започнете - не " +"е потребен Steam или рачно поставување." + +#: po/../qml/RuntimePicker.qml:125 +msgid "Open Vermouth Proton folder (%1)" +msgstr "Отвори папка за Vermouth Proton (%1)" + +#: po/../qml/RuntimePicker.qml:131 +msgid "Refresh Proton versions" +msgstr "Освежи листа на верзии на Proton" + +#: po/../qml/RuntimePicker.qml:138 po/../qml/SettingsDialog.qml:184 +msgid "Download latest GE Proton" +msgstr "Преземи ја најновата GE Proton" + +#: po/../qml/RuntimePicker.qml:145 +msgid "Wine Binary:" +msgstr "Wine бинарна датотека:" + +#: po/../qml/RuntimePicker.qml:160 +msgid "Select Wine Binary" +msgstr "Изберете Wine бинарна датотека" + +#: po/../qml/SettingsDialog.qml:9 +msgid "Settings" +msgstr "Поставки" + +#: po/../qml/SettingsDialog.qml:66 +msgid "Default Runtime" +msgstr "Стандардно извршно опкружување" + +#: po/../qml/SettingsDialog.qml:74 +msgid "umu-launcher" +msgstr "umu-launcher" + +#: po/../qml/SettingsDialog.qml:79 +msgid "" +"umu-launcher runs Proton through the Steam Runtime (pressure-vessel), which " +"significantly improves game compatibility - especially for games with video " +"cutscenes or anti-cheat. Strongly recommended." +msgstr "" +"umu-launcher го извршува Proton преку Steam Runtime (pressure-vessel), што " +"значително ја подобрува компатибилноста на игрите — особено за игри со видео-" +"сцени или анти-чит. Силно препорачано." + +#: po/../qml/SettingsDialog.qml:88 +msgid "umu-run path:" +msgstr "Патека до umu-run:" + +#: po/../qml/SettingsDialog.qml:92 +msgid "Auto-detect (umu-run in PATH)" +msgstr "Автоматско откривање (umu-run во PATH)" + +#: po/../qml/SettingsDialog.qml:102 +msgid "Download latest umu-launcher" +msgstr "Преземи ја најновата umu-launcher" + +#: po/../qml/SettingsDialog.qml:116 +msgid "Prefixes" +msgstr "Префикси" + +#: po/../qml/SettingsDialog.qml:120 +msgid "Default Prefix Parent Folder:" +msgstr "Стандардна папка за префикси:" + +#: po/../qml/SettingsDialog.qml:134 +msgid "" +"This is the folder where Vermouth stores all the created prefixes by default." +msgstr "" +"Ова е папката каде Vermouth ги складира сите создадени префикси стандардно." + +#: po/../qml/SettingsDialog.qml:143 +msgid "Default App/Game Prefix:" +msgstr "Стандарден префикс за апликација/игра:" + +#: po/../qml/SettingsDialog.qml:147 +msgid "Auto-generate per app/game" +msgstr "Автоматско генерирање за секоја апликација/игра" + +#: po/../qml/SettingsDialog.qml:157 +msgid "" +"Set this if you want all apps and games to share a single prefix (e.g. one " +"Wine/Proton environment for everything). Leave empty to auto-generate a " +"separate prefix per game. You can still use separate prefixe per game, but " +"you have to set it explicitly." +msgstr "" +"Поставете го ова ако сакате сите апликации и игри да споделуваат еден префикс " +"(пр. едно Wine/Proton опкружување за сè). Оставете празно за автоматско " +"генерирање на посебен префикс за секоја игра. Сепак може да користите посебен " +"префикс по игра, но мора да го поставите рачно." + +#: po/../qml/SettingsDialog.qml:167 +msgid "Vermouth Proton Folder" +msgstr "Папка за Vermouth Proton" + +#: po/../qml/SettingsDialog.qml:171 +msgid "" +"Download GE Proton to run most games and apps - no Steam or manual setup " +"needed." +msgstr "" +"Преземете GE Proton за да стартувате повеќето игри и апликации - не е " +"потребен Steam или рачно поставување." + +#: po/../qml/SettingsDialog.qml:174 +msgid "Open Vermouth Proton folder" +msgstr "Отвори папка за Vermouth Proton" + +#: po/../qml/SettingsDialog.qml:180 +msgid "Download Latest GE Proton" +msgstr "Преземи ја најновата GE Proton" + +#: po/../qml/SettingsDialog.qml:191 +msgid "Extra Proton Scan Paths" +msgstr "Дополнителни патеки за скенирање на Proton" + +#: po/../qml/SettingsDialog.qml:195 +msgid "" +"Folders to scan for Proton installations (in addition to Steam and local " +"paths)." +msgstr "" +"Папки за скенирање на Proton инсталации (покрај Steam и локалните патеки)." + +#: po/../qml/SettingsDialog.qml:217 +msgid "Add Path..." +msgstr "Додади патека..." + +#: po/../qml/SettingsDialog.qml:225 +msgid "Global Environment Variables" +msgstr "Глобални променливи на опкружувањето" + +#: po/../qml/SettingsDialog.qml:229 +msgid "Applied to every game. Per-game launch options can override these." +msgstr "Се применуваат на секоја игра. Опциите за секоја игра можат да ги заменат." + +#: po/../qml/SettingsDialog.qml:237 +msgid "KEY" +msgstr "КЛУЧ" + +#: po/../qml/SettingsDialog.qml:246 +msgid "value" +msgstr "вредност" + +#: po/../qml/SettingsDialog.qml:259 +msgid "Add Variable" +msgstr "Додади променлива" + +#: po/../qml/SettingsDialog.qml:272 +msgid "Select umu-run binary" +msgstr "Изберете umu-run бинарна датотека" + +#: po/../qml/SettingsDialog.qml:279 +msgid "Select Default Prefix Folder" +msgstr "Изберете стандардна папка за prefix" + +#: po/../qml/SettingsDialog.qml:286 +msgid "Select Default App/Game Prefix" +msgstr "Изберете стандарден prefix за апликација/игра" + +#: po/../qml/SettingsDialog.qml:293 +msgid "Select Proton Scan Folder" +msgstr "Изберете папка за скенирање на Proton" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/po/update-po.sh new/vermouth-1.3.4/po/update-po.sh --- old/vermouth-1.3.2/po/update-po.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/vermouth-1.3.4/po/update-po.sh 2026-04-21 17:18:28.000000000 +0200 @@ -0,0 +1,12 @@ +#!/bin/sh +# Merges updated vermouth.pot into all language .po files + +BASEDIR=$(dirname "$0") +POTFILE="$BASEDIR/vermouth.pot" + +for po in "$BASEDIR"/*/vermouth.po; do + echo "Updating $po..." + msgmerge --update --backup=none "$po" "$POTFILE" +done + +echo "Done." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/qml/AddAppDialog.qml new/vermouth-1.3.4/qml/AddAppDialog.qml --- old/vermouth-1.3.2/qml/AddAppDialog.qml 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/qml/AddAppDialog.qml 2026-04-21 17:18:28.000000000 +0200 @@ -61,12 +61,12 @@ var filename = parts[parts.length - 1]; nameField.text = filename.replace(/\.exe$/i, ""); } - var safeName = nameField.text.replace(/[^a-zA-Z0-9_-]/g, "_").toLowerCase(); - var prefixBase = dialog.prefixBasePath + "/" + safeName; + var defaultPrefix = settingsManager.defaultGamePrefix; + var resolvedPrefix = defaultPrefix !== "" ? defaultPrefix : dialog.prefixBasePath + "/" + nameField.text.replace(/[^a-zA-Z0-9_-]/g, "_").toLowerCase(); if (protonPrefixField.text === "") - protonPrefixField.text = prefixBase; + protonPrefixField.text = resolvedPrefix; if (winePrefixField.text === "") - winePrefixField.text = prefixBase; + winePrefixField.text = resolvedPrefix; } function openForNewWithExe(exePath) { @@ -110,14 +110,21 @@ return true; } + function resolvePrefix() { + var defaultPrefix = settingsManager.defaultGamePrefix; + return defaultPrefix !== "" ? defaultPrefix : dialog.prefixBasePath + "/" + nameField.text.replace(/[^a-zA-Z0-9_-]/g, "_").toLowerCase(); + } + function doSave() { var rt = runtimePicker.runtimeType; var protonPath = runtimePicker.protonPath; + var protonPrefix = protonPrefixField.text.trim() !== "" ? protonPrefixField.text : resolvePrefix(); + var winePrefix = winePrefixField.text.trim() !== "" ? winePrefixField.text : resolvePrefix(); if (editMode) { - appModel.editApp(editIndex, nameField.text, exeField.text, rt, protonPath, protonPrefixField.text, runtimePicker.wineBinary, winePrefixField.text, iconField.text, launchOptionsField.text, enableLoggingCheck.checked); + appModel.editApp(editIndex, nameField.text, exeField.text, rt, protonPath, protonPrefix, runtimePicker.wineBinary, winePrefix, iconField.text, launchOptionsField.text, enableLoggingCheck.checked); } else { - appModel.addApp(nameField.text, exeField.text, rt, protonPath, protonPrefixField.text, runtimePicker.wineBinary, winePrefixField.text, iconField.text, launchOptionsField.text, enableLoggingCheck.checked); + appModel.addApp(nameField.text, exeField.text, rt, protonPath, protonPrefix, runtimePicker.wineBinary, winePrefix, iconField.text, launchOptionsField.text, enableLoggingCheck.checked); } } @@ -189,7 +196,7 @@ QQC2.TextField { id: protonPrefixField Layout.fillWidth: true - placeholderText: dialog.prefixBasePath + "/mygame" + placeholderText: settingsManager.defaultGamePrefix !== "" ? settingsManager.defaultGamePrefix : dialog.prefixBasePath + "/mygame" } QQC2.Button { icon.name: "document-open" @@ -203,7 +210,7 @@ QQC2.TextField { id: winePrefixField Layout.fillWidth: true - placeholderText: "~/.wine" + placeholderText: settingsManager.defaultGamePrefix !== "" ? settingsManager.defaultGamePrefix : "~/.wine" } QQC2.Button { icon.name: "document-open" @@ -226,6 +233,16 @@ id: enableLoggingCheck text: i18n("Write output to log file") } + + Repeater { + model: settingsManager.globalEnvVars + delegate: QQC2.Label { + Kirigami.FormData.label: index === 0 ? i18n("Global Env Vars:") : "" + text: modelData + font.family: "monospace" + opacity: 0.7 + } + } } } @@ -251,14 +268,14 @@ FolderDialog { id: prefixFolderDialog title: i18n("Select Proton Prefix Folder") - currentFolder: "file://" + protonScanner.homePath() + currentFolder: "file://" + dialog.prefixBasePath onAccepted: protonPrefixField.text = decodeURIComponent(selectedFolder.toString().replace("file://", "")) } FolderDialog { id: winePrefixFolderDialog title: i18n("Select Wine Prefix Folder") - currentFolder: "file://" + protonScanner.homePath() + currentFolder: "file://" + dialog.prefixBasePath onAccepted: winePrefixField.text = decodeURIComponent(selectedFolder.toString().replace("file://", "")) } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/qml/AppGridView.qml new/vermouth-1.3.4/qml/AppGridView.qml --- old/vermouth-1.3.2/qml/AppGridView.qml 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/qml/AppGridView.qml 2026-04-21 17:18:28.000000000 +0200 @@ -15,7 +15,7 @@ property alias scaleFactor: gridView.scaleFactor } cellWidth: 140 * scaleFactor - cellHeight: 170 * scaleFactor + cellHeight: 160 * scaleFactor clip: true focus: true keyNavigationEnabled: true @@ -152,12 +152,12 @@ Layout.preferredWidth: 80 * gridView.scaleFactor Layout.preferredHeight: 80 * gridView.scaleFactor radius: Kirigami.Units.cornerRadius - color: Kirigami.Theme.alternateBackgroundColor + color: delegateRoot.iconPath === "" ? Kirigami.Theme.alternateBackgroundColor : Kirigami.Theme.backgroundColor Image { anchors.centerIn: parent - width: 64 * gridView.scaleFactor - height: 64 * gridView.scaleFactor + width: 70 * gridView.scaleFactor + height: 70 * gridView.scaleFactor source: delegateRoot.iconPath !== "" ? "file://" + delegateRoot.iconPath : "" visible: delegateRoot.iconPath !== "" fillMode: Image.PreserveAspectFit @@ -182,27 +182,10 @@ horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter Layout.fillWidth: true - Layout.maximumHeight: 50 * gridView.scaleFactor + Layout.fillHeight: true wrapMode: Text.Wrap maximumLineCount: 2 } - - QQC2.Label { - text: { - if (delegateRoot.runtimeType === "proton") { - var parts = delegateRoot.protonPath.split("/"); - return parts[parts.length - 1]; - } - return i18n("Wine"); - } - font.pixelSize: 10 * gridView.scaleFactor - color: Kirigami.Theme.disabledTextColor - elide: Text.ElideRight - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignBottom - Layout.fillWidth: true - maximumLineCount: 1 - } } MouseArea { @@ -239,13 +222,18 @@ QQC2.Menu { id: contextMenu QQC2.MenuItem { - text: i18n("Launch") - icon.name: "media-playback-start" + property bool isRunning: launcher.runningExePaths.indexOf(delegateRoot.exePath) >= 0 + text: isRunning ? i18n("Stop") : i18n("Launch") + icon.name: isRunning ? "media-playback-stop" : "media-playback-start" onTriggered: { - launchAnim.start(); - flashAnim.start(); var app = appModel.getApp(delegateRoot.index); - launcher.launchEntry(app); + if (isRunning) { + launcher.stopEntry(app); + } else { + launchAnim.start(); + flashAnim.start(); + launcher.launchEntry(app); + } } } QQC2.MenuItem { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/qml/Main.qml new/vermouth-1.3.4/qml/Main.qml --- old/vermouth-1.3.2/qml/Main.qml 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/qml/Main.qml 2026-04-21 17:18:28.000000000 +0200 @@ -92,11 +92,15 @@ onClicked: addDialog.openForNew() } QQC2.Button { - icon.name: "media-playback-start" + property bool isRunning: gridView.selectedIndex >= 0 && launcher.runningExePaths.indexOf(appModel.getApp(gridView.selectedIndex).exePath) >= 0 + icon.name: isRunning ? "media-playback-stop" : "media-playback-start" enabled: gridView.selectedIndex >= 0 onClicked: { var app = appModel.getApp(gridView.selectedIndex); - launcher.launchEntry(app); + if (isRunning) + launcher.stopEntry(app); + else + launcher.launchEntry(app); } } } @@ -220,6 +224,16 @@ } } + function openExe(path) { + var existing = appModel.getAppByExePath(path); + if (existing && existing.exePath !== undefined) { + launcher.launchEntry(existing); + } else { + openExeChoiceDialog.exePath = path; + openExeChoiceDialog.open(); + } + } + DropArea { anchors.fill: parent onDropped: function (drop) { @@ -229,25 +243,20 @@ } else if (drop.hasText) { path = decodeURIComponent(drop.text.trim().replace("file://", "")); } - if (path !== "") { - openExeChoiceDialog.exePath = path; - openExeChoiceDialog.open(); - } + if (path !== "") + root.openExe(path); } } Component.onCompleted: { - if (typeof openExePath !== "undefined" && openExePath !== "") { - openExeChoiceDialog.exePath = openExePath; - openExeChoiceDialog.open(); - } + if (typeof openExePath !== "undefined" && openExePath !== "") + root.openExe(openExePath); } Connections { target: singleInstance function onOpenExeRequested(path) { - openExeChoiceDialog.exePath = path; - openExeChoiceDialog.open(); + root.openExe(path); } function onRaiseRequested() { root.raise(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/qml/SettingsDialog.qml new/vermouth-1.3.4/qml/SettingsDialog.qml --- old/vermouth-1.3.2/qml/SettingsDialog.qml 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/qml/SettingsDialog.qml 2026-04-21 17:18:28.000000000 +0200 @@ -13,12 +13,22 @@ onAccepted: { settingsManager.setUmuPath(umuPathField.text); settingsManager.setDefaultPrefixDir(prefixDirField.text); + settingsManager.setDefaultGamePrefix(gamePrefixField.text); defaultRuntimePicker.saveToSettings(); + var vars = []; + for (var i = 0; i < envModel.count; i++) { + var k = envModel.get(i).key.trim(); + var v = envModel.get(i).value.trim(); + if (k !== "") + vars.push(k + "=" + v); + } + settingsManager.setGlobalEnvVars(vars); } function openDialog() { umuPathField.text = settingsManager.umuPath; prefixDirField.text = settingsManager.defaultPrefixDir; + gamePrefixField.text = settingsManager.defaultGamePrefix; pathsModel.clear(); var paths = settingsManager.extraProtonPaths; for (var i = 0; i < paths.length; i++) { @@ -26,6 +36,15 @@ "path": paths[i] }); } + envModel.clear(); + var vars = settingsManager.globalEnvVars; + for (var j = 0; j < vars.length; j++) { + var sep = vars[j].indexOf("="); + envModel.append({ + "key": sep > 0 ? vars[j].substring(0, sep) : vars[j], + "value": sep > 0 ? vars[j].substring(sep + 1) : "" + }); + } defaultRuntimePicker.reset(); dialog.open(); } @@ -34,6 +53,10 @@ id: pathsModel } + ListModel { + id: envModel + } + ColumnLayout { spacing: Kirigami.Units.smallSpacing @@ -94,7 +117,7 @@ } RowLayout { - Kirigami.FormData.label: i18n("Default Prefix Folder:") + Kirigami.FormData.label: i18n("Default Prefix Parent Folder:") QQC2.TextField { id: prefixDirField Layout.fillWidth: true @@ -106,6 +129,39 @@ } } + QQC2.Label { + Kirigami.FormData.label: "" + text: i18n("This is the folder where Vermouth stores all the created prefixes by default.") + wrapMode: Text.WordWrap + Layout.fillWidth: true + Layout.maximumWidth: Kirigami.Units.gridUnit * 26 + font.italic: true + opacity: 0.8 + } + + RowLayout { + Kirigami.FormData.label: i18n("Default App/Game Prefix:") + QQC2.TextField { + id: gamePrefixField + Layout.fillWidth: true + placeholderText: i18n("Auto-generate per app/game") + } + QQC2.Button { + icon.name: "document-open" + onClicked: gamePrefixFolderDialog.open() + } + } + + QQC2.Label { + Kirigami.FormData.label: "" + text: i18n("Set this if you want all apps and games to share a single prefix (e.g. one Wine/Proton environment for everything). Leave empty to auto-generate a separate prefix per game. You can still use separate prefixe per game, but you have to set it explicitly.") + wrapMode: Text.WordWrap + Layout.fillWidth: true + Layout.maximumWidth: Kirigami.Units.gridUnit * 26 + font.italic: true + opacity: 0.8 + } + Kirigami.Separator { Kirigami.FormData.isSection: true Kirigami.FormData.label: i18n("Vermouth Proton Folder") @@ -163,6 +219,51 @@ onClicked: protonPathFolderDialog.open() } } + + Kirigami.Separator { + Kirigami.FormData.isSection: true + Kirigami.FormData.label: i18n("Global Environment Variables") + } + + ColumnLayout { + Kirigami.FormData.label: i18n("Applied to every game. Per-game launch options can override these.") + Layout.fillWidth: true + + Repeater { + model: envModel + delegate: RowLayout { + Layout.fillWidth: true + QQC2.TextField { + placeholderText: i18n("KEY") + text: model.key + implicitWidth: Kirigami.Units.gridUnit * 9 + onTextChanged: envModel.setProperty(index, "key", text) + } + QQC2.Label { + text: "=" + } + QQC2.TextField { + placeholderText: i18n("value") + text: model.value + Layout.fillWidth: true + onTextChanged: envModel.setProperty(index, "value", text) + } + QQC2.Button { + icon.name: "list-remove" + onClicked: envModel.remove(index) + } + } + } + + QQC2.Button { + text: i18n("Add Variable") + icon.name: "list-add" + onClicked: envModel.append({ + "key": "", + "value": "" + }) + } + } } } @@ -181,6 +282,13 @@ } FolderDialog { + id: gamePrefixFolderDialog + title: i18n("Select Default App/Game Prefix") + currentFolder: "file://" + protonScanner.prefixBasePath() + onAccepted: gamePrefixField.text = decodeURIComponent(selectedFolder.toString().replace("file://", "")) + } + + FolderDialog { id: protonPathFolderDialog title: i18n("Select Proton Scan Folder") currentFolder: "file://" + protonScanner.homePath() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/scripts/update-pkgbuild.sh new/vermouth-1.3.4/scripts/update-pkgbuild.sh --- old/vermouth-1.3.2/scripts/update-pkgbuild.sh 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/scripts/update-pkgbuild.sh 2026-04-21 17:18:28.000000000 +0200 @@ -21,8 +21,11 @@ pacman -Syu --noconfirm --quiet pacman -S --noconfirm --needed --quiet pacman-contrib useradd -m builder - chown -R builder:builder /pkg - su builder -c 'cd /pkg && updpkgsums && makepkg --printsrcinfo > .SRCINFO' + cp -r /pkg /tmp/pkg + chown -R builder:builder /tmp/pkg + su builder -c 'cd /tmp/pkg && updpkgsums && makepkg --printsrcinfo > .SRCINFO' + cp /tmp/pkg/PKGBUILD /pkg/PKGBUILD + cp /tmp/pkg/.SRCINFO /pkg/.SRCINFO " echo "Done." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/src/appmodel.cpp new/vermouth-1.3.4/src/appmodel.cpp --- old/vermouth-1.3.2/src/appmodel.cpp 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/src/appmodel.cpp 2026-04-21 17:18:28.000000000 +0200 @@ -251,6 +251,30 @@ return {}; } +QVariantMap AppModel::getAppByExePath(const QString &exePath) const +{ + for (int i = 0; i < m_entries.size(); ++i) { + if (m_entries[i].exePath == exePath) { + // Return via getApp using a filtered index isn't safe here; build map directly. + const auto &e = m_entries[i]; + return { + {QStringLiteral("id"), e.id}, + {QStringLiteral("name"), e.name}, + {QStringLiteral("exePath"), e.exePath}, + {QStringLiteral("runtimeType"), (e.runtimeType == AppEntry::Proton) ? QStringLiteral("proton") : QStringLiteral("wine")}, + {QStringLiteral("protonPath"), e.protonPath}, + {QStringLiteral("protonPrefix"), e.protonPrefix}, + {QStringLiteral("wineBinary"), e.wineBinary}, + {QStringLiteral("winePrefix"), e.winePrefix}, + {QStringLiteral("iconPath"), e.iconPath}, + {QStringLiteral("launchOptions"), e.launchOptions}, + {QStringLiteral("enableLogging"), e.enableLogging}, + }; + } + } + return {}; +} + void AppModel::load() { QFile f(configPath()); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/src/appmodel.h new/vermouth-1.3.4/src/appmodel.h --- old/vermouth-1.3.2/src/appmodel.h 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/src/appmodel.h 2026-04-21 17:18:28.000000000 +0200 @@ -60,6 +60,7 @@ bool enableLogging = false); Q_INVOKABLE QVariantMap getApp(int index) const; Q_INVOKABLE QVariantMap getAppById(const QString &id) const; + Q_INVOKABLE QVariantMap getAppByExePath(const QString &exePath) const; Q_INVOKABLE void setFilterString(const QString &filter); void load(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/src/launcher.cpp new/vermouth-1.3.4/src/launcher.cpp --- old/vermouth-1.3.2/src/launcher.cpp 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/src/launcher.cpp 2026-04-21 17:18:28.000000000 +0200 @@ -61,6 +61,11 @@ m_umuPath = path; } +void Launcher::setGlobalEnvVars(const QStringList &vars) +{ + m_globalEnvVars = vars; +} + QString Launcher::logDir() const { return m_logDir; @@ -82,8 +87,14 @@ const QString &logName) { auto *proc = new QProcess(this); - connect(proc, &QProcess::finished, proc, &QProcess::deleteLater); - connect(proc, &QProcess::finished, this, &Launcher::processFinished); + m_runningProcesses.insert(exePath, proc); + Q_EMIT runningExePathsChanged(); + connect(proc, &QProcess::finished, this, [this, exePath, proc](int exitCode) { + m_runningProcesses.remove(exePath); + Q_EMIT runningExePathsChanged(); + Q_EMIT processFinished(exitCode); + proc->deleteLater(); + }); proc->setProcessEnvironment(env); proc->setWorkingDirectory(QFileInfo(exePath).absolutePath()); @@ -111,6 +122,8 @@ } if (!proc->waitForStarted(5000)) { + m_runningProcesses.remove(exePath); + Q_EMIT runningExePathsChanged(); Q_EMIT launchError(exePath, proc->errorString()); proc->deleteLater(); } else { @@ -127,6 +140,12 @@ QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + for (const QString &kv : std::as_const(m_globalEnvVars)) { + int sep = kv.indexOf(QLatin1Char('=')); + if (sep > 0) + env.insert(kv.left(sep), kv.mid(sep + 1)); + } + if (m_hdrEnabled) { env.insert(QStringLiteral("PROTON_ENABLE_HDR"), QStringLiteral("1")); env.insert(QStringLiteral("PROTON_ENABLE_WAYLAND"), QStringLiteral("1")); @@ -163,6 +182,13 @@ } } +void Launcher::stopEntry(const QVariantMap &app) +{ + QProcess *proc = m_runningProcesses.value(app[QStringLiteral("exePath")].toString(), nullptr); + if (proc) + proc->terminate(); +} + void Launcher::runInPrefix(const QVariantMap &app, const QString &exePath) { QVariantMap copy = app; @@ -272,7 +298,8 @@ void Launcher::refreshHdrState() { bool supported = false; - bool enabled = false; + bool hdrEnabled = false; + bool wcgEnabled = false; if (isKde()) { QString screenName = currentScreenName(); @@ -284,7 +311,8 @@ QJsonObject out = val.toObject(); if (out[QStringLiteral("name")].toString() == screenName && out[QStringLiteral("connected")].toBool() && out.contains(QStringLiteral("hdr"))) { supported = true; - enabled = out[QStringLiteral("hdr")].toBool(); + hdrEnabled = out[QStringLiteral("hdr")].toBool(); + wcgEnabled = out[QStringLiteral("wcg")].toBool(); break; } } @@ -294,21 +322,43 @@ m_hdrSupported = supported; Q_EMIT hdrSupportedChanged(); } - if (m_hdrEnabled != enabled) { - m_hdrEnabled = enabled; + if (m_hdrEnabled != hdrEnabled) { + m_hdrEnabled = hdrEnabled; Q_EMIT hdrEnabledChanged(); } + m_wcgEnabled = wcgEnabled; } void Launcher::toggleHdr() { bool enable = !m_hdrEnabled; QString screenName = currentScreenName(); - QString action = enable ? QStringLiteral("hdr.enable") : QStringLiteral("hdr.disable"); - QProcess::execute(kscreenDoctorBin(), kscreenDoctorArgs({QStringLiteral("output.") + screenName + QLatin1Char('.') + action})); + + if (enable) { + m_wcgEnabledBeforeHdr = m_wcgEnabled; + QProcess::execute(kscreenDoctorBin(), kscreenDoctorArgs({QStringLiteral("output.") + screenName + QStringLiteral(".hdr.enable")})); + QProcess::execute(kscreenDoctorBin(), kscreenDoctorArgs({QStringLiteral("output.") + screenName + QStringLiteral(".wcg.enable")})); + m_hdrEnabledByUs = true; + } else { + QProcess::execute(kscreenDoctorBin(), kscreenDoctorArgs({QStringLiteral("output.") + screenName + QStringLiteral(".hdr.disable")})); + QString wcgAction = m_wcgEnabledBeforeHdr ? QStringLiteral("wcg.enable") : QStringLiteral("wcg.disable"); + QProcess::execute(kscreenDoctorBin(), kscreenDoctorArgs({QStringLiteral("output.") + screenName + QLatin1Char('.') + wcgAction})); + m_hdrEnabledByUs = false; + } + refreshHdrState(); } +void Launcher::restoreHdrState() +{ + if (!m_hdrEnabledByUs) + return; + QString screenName = currentScreenName(); + QProcess::execute(kscreenDoctorBin(), kscreenDoctorArgs({QStringLiteral("output.") + screenName + QStringLiteral(".hdr.disable")})); + QString wcgAction = m_wcgEnabledBeforeHdr ? QStringLiteral("wcg.enable") : QStringLiteral("wcg.disable"); + QProcess::execute(kscreenDoctorBin(), kscreenDoctorArgs({QStringLiteral("output.") + screenName + QLatin1Char('.') + wcgAction})); +} + void Launcher::setupLogging(QProcess *proc, const QString &name) { QString safeName = name; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/src/launcher.h new/vermouth-1.3.4/src/launcher.h --- old/vermouth-1.3.2/src/launcher.h 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/src/launcher.h 2026-04-21 17:18:28.000000000 +0200 @@ -1,9 +1,11 @@ #pragma once #include <QDBusUnixFileDescriptor> +#include <QHash> #include <QObject> #include <QProcess> #include <QProcessEnvironment> +#include <QStringList> class Launcher : public QObject { @@ -13,8 +15,16 @@ explicit Launcher(QObject *parent = nullptr); void setUmuPath(const QString &path); + void setGlobalEnvVars(const QStringList &vars); + + Q_PROPERTY(QStringList runningExePaths READ runningExePaths NOTIFY runningExePathsChanged) + QStringList runningExePaths() const + { + return m_runningProcesses.keys(); + } Q_INVOKABLE void launchEntry(const QVariantMap &app); + Q_INVOKABLE void stopEntry(const QVariantMap &app); Q_INVOKABLE void runInPrefix(const QVariantMap &app, const QString &exePath); Q_INVOKABLE void runWinecfg(const QVariantMap &app); Q_INVOKABLE void runRegedit(const QVariantMap &app); @@ -29,6 +39,7 @@ Q_PROPERTY(bool hdrEnabled READ hdrEnabled NOTIFY hdrEnabledChanged) Q_PROPERTY(bool hdrSupported READ hdrSupported NOTIFY hdrSupportedChanged) Q_INVOKABLE void toggleHdr(); + void restoreHdrState(); bool hdrEnabled() const; bool hdrSupported() const; @@ -37,6 +48,7 @@ void launchError(const QString &name, const QString &error); void prefixNotReady(const QString &name); void processFinished(int exitCode); + void runningExePathsChanged(); void sleepInhibitedChanged(); void hdrEnabledChanged(); void hdrSupportedChanged(); @@ -53,7 +65,12 @@ void refreshHdrState(); QString m_logDir; QString m_umuPath; + QStringList m_globalEnvVars; + QHash<QString, QProcess *> m_runningProcesses; int m_inhibitFd = -1; bool m_hdrEnabled = false; bool m_hdrSupported = false; + bool m_hdrEnabledByUs = false; + bool m_wcgEnabled = false; + bool m_wcgEnabledBeforeHdr = false; }; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/src/main.cpp new/vermouth-1.3.4/src/main.cpp --- old/vermouth-1.3.2/src/main.cpp 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/src/main.cpp 2026-04-21 17:18:28.000000000 +0200 @@ -141,6 +141,15 @@ QObject::connect(&settingsManager, &SettingsManager::umuPathChanged, [&]() { launcher.setUmuPath(settingsManager.umuPath()); }); + + launcher.setGlobalEnvVars(settingsManager.globalEnvVars()); + QObject::connect(&settingsManager, &SettingsManager::globalEnvVarsChanged, [&]() { + launcher.setGlobalEnvVars(settingsManager.globalEnvVars()); + }); + + QObject::connect(&app, &QApplication::aboutToQuit, [&]() { + launcher.restoreHdrState(); + }); QObject::connect(&umuDownloader, &UmuDownloader::finished, [&](const QString &binPath) { settingsManager.setUmuPath(binPath); }); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/src/settingsmanager.cpp new/vermouth-1.3.4/src/settingsmanager.cpp --- old/vermouth-1.3.2/src/settingsmanager.cpp 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/src/settingsmanager.cpp 2026-04-21 17:18:28.000000000 +0200 @@ -18,6 +18,19 @@ Q_EMIT defaultPrefixDirChanged(); } +QString SettingsManager::defaultGamePrefix() const +{ + return m_settings.value(QStringLiteral("defaultGamePrefix")).toString(); +} + +void SettingsManager::setDefaultGamePrefix(const QString &path) +{ + if (defaultGamePrefix() == path) + return; + m_settings.setValue(QStringLiteral("defaultGamePrefix"), path); + Q_EMIT defaultGamePrefixChanged(); +} + QStringList SettingsManager::extraProtonPaths() const { return m_settings.value(QStringLiteral("extraProtonPaths")).toStringList(); @@ -99,6 +112,17 @@ Q_EMIT umuPathChanged(); } +QStringList SettingsManager::globalEnvVars() const +{ + return m_settings.value(QStringLiteral("globalEnvVars")).toStringList(); +} + +void SettingsManager::setGlobalEnvVars(const QStringList &vars) +{ + m_settings.setValue(QStringLiteral("globalEnvVars"), vars); + Q_EMIT globalEnvVarsChanged(); +} + bool SettingsManager::drawerPinned() const { return m_settings.value(QStringLiteral("drawerPinned"), false).toBool(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' --exclude Makefile.in --exclude configure --exclude config.guess --exclude '*.pot' --exclude mkinstalldirs --exclude aclocal.m4 --exclude config.sub --exclude depcomp --exclude install-sh --exclude ltmain.sh old/vermouth-1.3.2/src/settingsmanager.h new/vermouth-1.3.4/src/settingsmanager.h --- old/vermouth-1.3.2/src/settingsmanager.h 2026-04-19 13:13:48.000000000 +0200 +++ new/vermouth-1.3.4/src/settingsmanager.h 2026-04-21 17:18:28.000000000 +0200 @@ -8,12 +8,14 @@ { Q_OBJECT Q_PROPERTY(QString defaultPrefixDir READ defaultPrefixDir WRITE setDefaultPrefixDir NOTIFY defaultPrefixDirChanged) + Q_PROPERTY(QString defaultGamePrefix READ defaultGamePrefix WRITE setDefaultGamePrefix NOTIFY defaultGamePrefixChanged) Q_PROPERTY(QStringList extraProtonPaths READ extraProtonPaths WRITE setExtraProtonPaths NOTIFY extraProtonPathsChanged) Q_PROPERTY(QString defaultRuntimeType READ defaultRuntimeType WRITE setDefaultRuntimeType NOTIFY defaultRuntimeChanged) Q_PROPERTY(QString defaultProtonPath READ defaultProtonPath WRITE setDefaultProtonPath NOTIFY defaultRuntimeChanged) Q_PROPERTY(QString defaultWineBinary READ defaultWineBinary WRITE setDefaultWineBinary NOTIFY defaultRuntimeChanged) Q_PROPERTY(bool drawerPinned READ drawerPinned WRITE setDrawerPinned NOTIFY drawerPinnedChanged) Q_PROPERTY(QString umuPath READ umuPath WRITE setUmuPath NOTIFY umuPathChanged) + Q_PROPERTY(QStringList globalEnvVars READ globalEnvVars WRITE setGlobalEnvVars NOTIFY globalEnvVarsChanged) public: explicit SettingsManager(QObject *parent = nullptr); @@ -21,6 +23,9 @@ QString defaultPrefixDir() const; Q_INVOKABLE void setDefaultPrefixDir(const QString &path); + QString defaultGamePrefix() const; + Q_INVOKABLE void setDefaultGamePrefix(const QString &path); + QStringList extraProtonPaths() const; void setExtraProtonPaths(const QStringList &paths); @@ -42,12 +47,17 @@ QString umuPath() const; Q_INVOKABLE void setUmuPath(const QString &path); + QStringList globalEnvVars() const; + Q_INVOKABLE void setGlobalEnvVars(const QStringList &vars); + Q_SIGNALS: void defaultPrefixDirChanged(); + void defaultGamePrefixChanged(); void extraProtonPathsChanged(); void defaultRuntimeChanged(); void drawerPinnedChanged(); void umuPathChanged(); + void globalEnvVarsChanged(); private: QSettings m_settings;
