Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73f995636b | ||
|
|
14119442e7 | ||
|
|
af72762508 | ||
|
|
6e796705d8 | ||
|
|
01aa5dbc74 | ||
|
|
3e0084ae1d | ||
|
|
4bb15d9e8f | ||
|
|
49a1a23a31 | ||
|
|
91dbb6f049 | ||
|
|
31dae6098f | ||
|
|
080c1cd0af | ||
|
|
bcbaaf74bc | ||
|
|
4db3bcef9c | ||
|
|
e371fff7fd | ||
|
|
10b4d91eec |
No files matched your search
@@ -1,15 +1 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: Felitendo
|
|
||||||
patreon: # Replace with a single Patreon username
|
|
||||||
open_collective: # Replace with a single Open Collective username
|
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
liberapay: # Replace with a single Liberapay username
|
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
|
||||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
||||||
polar: # Replace with a single Polar username
|
|
||||||
buy_me_a_coffee: felitendo
|
buy_me_a_coffee: felitendo
|
||||||
thanks_dev: # Replace with a single thanks.dev username
|
|
||||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
||||||
Executable
+135
@@ -0,0 +1,135 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Builds the GitHub release notes for a tag, the way big projects such as
|
||||||
|
# Immich lay them out: the hand-written entry from CHANGELOG.md (a welcome,
|
||||||
|
# the highlights), a support section, then every commit since the last
|
||||||
|
# release, sorted by kind, and a link to the full changelog.
|
||||||
|
#
|
||||||
|
# .github/release-notes.sh v1.2.0 the notes
|
||||||
|
# .github/release-notes.sh --title v1.2.0 the title (checks the entry exists)
|
||||||
|
#
|
||||||
|
# Commit authors come from the GitHub API through gh. Without it the list
|
||||||
|
# goes without them.
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.."
|
||||||
|
|
||||||
|
title=0
|
||||||
|
if [[ ${1:-} == --title ]]; then
|
||||||
|
title=1
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
tag="${1:?usage: release-notes.sh [--title] vX.Y.Z}"
|
||||||
|
|
||||||
|
if ! grep -qx "## $tag" CHANGELOG.md; then
|
||||||
|
echo "CHANGELOG.md has no entry for $tag. Add \"## $tag\" first." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if (( title )); then
|
||||||
|
printf '%s\n' "$tag"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
repo="${GITHUB_REPOSITORY:-$(git remote get-url origin | sed -E 's#^.*github\.com[:/]##; s#\.git$##')}"
|
||||||
|
name="${repo#*/}"
|
||||||
|
|
||||||
|
# The entry: up to the next one, without the date line (GitHub shows the
|
||||||
|
# date), one heading level up, outside code blocks.
|
||||||
|
entry="$(awk -v h="## $tag" '
|
||||||
|
$0 == h { on = 1; next }
|
||||||
|
on && /^## / { exit }
|
||||||
|
!on { next }
|
||||||
|
/^```/ { code = !code }
|
||||||
|
!code && /^_[0-9]{4}-[0-9]{2}-[0-9]{2}_$/ { next }
|
||||||
|
!code && /^###/ { sub(/^#/, "") }
|
||||||
|
{ print }
|
||||||
|
' CHANGELOG.md | sed -e '/./,$!d')"
|
||||||
|
|
||||||
|
# The commits: from the last release, or from the start. A tag that does not
|
||||||
|
# exist yet is a preview of what HEAD would become.
|
||||||
|
if git rev-parse -q --verify "refs/tags/$tag" > /dev/null; then
|
||||||
|
target="$tag"
|
||||||
|
prev="$(git describe --tags --abbrev=0 --match 'v[0-9]*' "$tag^" 2>/dev/null || true)"
|
||||||
|
else
|
||||||
|
target="$(git rev-parse HEAD)"
|
||||||
|
prev="$(git describe --tags --abbrev=0 --match 'v[0-9]*' HEAD 2>/dev/null || true)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
declare -A login=()
|
||||||
|
if command -v gh > /dev/null; then
|
||||||
|
if [[ -n $prev ]]; then
|
||||||
|
api=(api "repos/$repo/compare/$prev...$target" --jq '.commits[] | [.sha, (.author.login // "")] | @tsv')
|
||||||
|
else
|
||||||
|
api=(api --paginate "repos/$repo/commits?sha=$target&per_page=100" --jq '.[] | [.sha, (.author.login // "")] | @tsv')
|
||||||
|
fi
|
||||||
|
while IFS=$'\t' read -r sha who; do
|
||||||
|
[[ -n $who ]] && login[$sha]="$who"
|
||||||
|
done < <(gh "${api[@]}" 2>/dev/null || true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
declare -A list=()
|
||||||
|
count_maint=0
|
||||||
|
while IFS=$'\t' read -r sha subject body; do
|
||||||
|
# Version bumps say nothing a reader needs.
|
||||||
|
[[ $subject =~ ^(chore:\ )?($name\ )?v?[0-9]+\.[0-9]+\.[0-9]+$ ]] && continue
|
||||||
|
|
||||||
|
case "$subject" in
|
||||||
|
*!:*) kind=breaking ;;
|
||||||
|
feat:* | feat\(*) kind=feat ;;
|
||||||
|
fix:* | fix\(*) kind=fix ;;
|
||||||
|
perf:* | perf\(*) kind=enh ;;
|
||||||
|
docs:* | docs\(*) kind=docs ;;
|
||||||
|
chore* | ci:* | ci\(* | build* | refactor* | test* | style*) kind=maint ;;
|
||||||
|
# Older commits without a prefix, sorted by their first word.
|
||||||
|
Add\ * | Put\ * | Introduce\ *) kind=feat ;;
|
||||||
|
Fix\ * | Repair\ * | Recover\ * | Stop\ *) kind=fix ;;
|
||||||
|
*\ *) kind=enh ;;
|
||||||
|
*) kind=maint ;;
|
||||||
|
esac
|
||||||
|
[[ $body == *"BREAKING CHANGE"* ]] && kind=breaking
|
||||||
|
[[ $subject == "Initial commit" ]] && kind=maint
|
||||||
|
|
||||||
|
line="* $subject"
|
||||||
|
[[ -n ${login[$sha]:-} ]] && line+=" by @${login[$sha]}"
|
||||||
|
line+=" in https://github.com/$repo/commit/$sha"
|
||||||
|
list[$kind]+="$line"$'\n'
|
||||||
|
[[ $kind == maint ]] && count_maint=$((count_maint + 1))
|
||||||
|
done < <(git log --reverse --no-merges --format='%H%x09%s%x09%b%x1e' "${prev:+$prev..}$target" | tr '\n\036' ' \n' | sed 's/^ //')
|
||||||
|
|
||||||
|
changes=''
|
||||||
|
for pair in "breaking:🚨 Breaking Changes" "feat:🚀 Features" "enh:🌟 Enhancements" "fix:🐛 Bug fixes" "docs:📚 Documentation"; do
|
||||||
|
kind="${pair%%:*}"
|
||||||
|
[[ -n ${list[$kind]:-} ]] || continue
|
||||||
|
changes+="### ${pair#*:}"$'\n'"${list[$kind]}"
|
||||||
|
done
|
||||||
|
if [[ -n ${list[maint]:-} ]]; then
|
||||||
|
changes+=$'\n'"<details><summary>🧰 Maintenance ($count_maint)</summary>"$'\n\n'"${list[maint]}"$'\n'"</details>"$'\n'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n $prev ]]; then
|
||||||
|
full="**Full Changelog**: https://github.com/$repo/compare/$prev...$tag"
|
||||||
|
else
|
||||||
|
full="**Full Changelog**: https://github.com/$repo/commits/$tag"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# A release with highlights is a big one: it gets a heading and the support
|
||||||
|
# section, as in Immich. A patch is a sentence or two and the list.
|
||||||
|
if grep -q '^## Highlights$' <<< "$entry"; then
|
||||||
|
cat <<EOF
|
||||||
|
# 🚀 $name $tag
|
||||||
|
|
||||||
|
$entry
|
||||||
|
|
||||||
|
## ☕ Support $name
|
||||||
|
|
||||||
|
If $name is useful to you, you can buy me a coffee. It keeps these tools going. Found a bug or have an idea? Tell me in the [issues](https://github.com/$repo/issues).
|
||||||
|
|
||||||
|
<a href="https://buymeacoffee.com/felitendo"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" height="48"></a>
|
||||||
|
|
||||||
|
----
|
||||||
|
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
printf '%s\n\n' "$entry"
|
||||||
|
fi
|
||||||
|
printf "## What's Changed\n%s\n\n%s\n" "$changes" "$full"
|
||||||
@@ -55,6 +55,10 @@ jobs:
|
|||||||
- name: Check the tag against the Makefile
|
- name: Check the tag against the Makefile
|
||||||
run: packaging/check-version.sh "${{ github.ref_name }}"
|
run: packaging/check-version.sh "${{ github.ref_name }}"
|
||||||
|
|
||||||
|
- name: Check CHANGELOG.md has this release
|
||||||
|
if: startsWith(github.ref, 'refs/tags/v')
|
||||||
|
run: .github/release-notes.sh --title "${{ github.ref_name }}"
|
||||||
|
|
||||||
- run: packaging/build-deb.sh
|
- run: packaging/build-deb.sh
|
||||||
env:
|
env:
|
||||||
DEB_SUFFIX: ${{ matrix.suffix }}
|
DEB_SUFFIX: ${{ matrix.suffix }}
|
||||||
@@ -130,6 +134,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v7
|
- uses: actions/checkout@v7
|
||||||
|
with:
|
||||||
|
# All tags, for the link to the changes since the last release.
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: actions/download-artifact@v8
|
- uses: actions/download-artifact@v8
|
||||||
with:
|
with:
|
||||||
@@ -141,9 +148,10 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ github.token }}
|
GH_TOKEN: ${{ github.token }}
|
||||||
run: |
|
run: |
|
||||||
|
.github/release-notes.sh "${{ github.ref_name }}" > notes.md
|
||||||
gh release create "${{ github.ref_name }}" \
|
gh release create "${{ github.ref_name }}" \
|
||||||
--title "${{ github.ref_name }}" \
|
--title "$(.github/release-notes.sh --title "${{ github.ref_name }}")" \
|
||||||
--generate-notes \
|
--notes-file notes.md \
|
||||||
incoming/*.deb incoming/*.rpm \
|
incoming/*.deb incoming/*.rpm \
|
||||||
|| gh release upload "${{ github.ref_name }}" \
|
|| gh release upload "${{ github.ref_name }}" \
|
||||||
incoming/*.deb incoming/*.rpm --clobber
|
incoming/*.deb incoming/*.rpm --clobber
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# Changelog
|
||||||
|
|
||||||
|
What each release brings, newest first. The [GitHub releases](https://github.com/LoonixTools/plasma-face-unlock/releases) add every commit that went into it.
|
||||||
|
|
||||||
|
## v1.0.1
|
||||||
|
|
||||||
|
_2026-09-24_
|
||||||
|
|
||||||
|
A small update that makes everyday use smoother. You no longer have to blink: the basic photo check is now the default, and it still stops a photo on a phone, a tablet or glossy paper. If you want the blink back, set **Photo check** to `strict` in the settings.
|
||||||
|
|
||||||
|
The settings are now grouped and explain the selected one, the animations are a little calmer, and the lock screen unlocks as soon as your face matches.
|
||||||
|
|
||||||
|
## v1.0.0
|
||||||
|
|
||||||
|
_2026-09-23_
|
||||||
|
|
||||||
|
Welcome to the very first release of plasma-face-unlock! It brings Face ID to KDE Plasma: look at the screen and it unlocks. The lock screen, sudo and admin prompts can all take your face instead of a password.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="480" alt="The bubble drops down over the lock screen, finds the face and shows a green tick" src="https://raw.githubusercontent.com/LoonixTools/plasma-face-unlock/v1.0.0/res/screenshots/unlock.webp">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- Unlock the lock screen with your face
|
||||||
|
- sudo and admin prompts
|
||||||
|
- A bubble like Face ID
|
||||||
|
- Photos do not get in
|
||||||
|
- Packages for Arch, Fedora, Debian and Kubuntu
|
||||||
@@ -24,6 +24,56 @@
|
|||||||
- `src/pam`: the PAM module for sudo and admin prompts.
|
- `src/pam`: the PAM module for sudo and admin prompts.
|
||||||
- `src/ctl`: the client the bash code talks to the daemon with.
|
- `src/ctl`: the client the bash code talks to the daemon with.
|
||||||
|
|
||||||
|
## Releases
|
||||||
|
|
||||||
|
Releases look like the ones of big projects such as Immich. `.github/release-notes.sh <tag>` builds
|
||||||
|
the notes: the entry from `CHANGELOG.md` (welcome and highlights), a support section, every commit
|
||||||
|
since the last release sorted by its prefix (`feat`, `fix`, `docs`, ...) with author and link, and
|
||||||
|
the full changelog link. So commit subjects end up in public: keep them clear.
|
||||||
|
|
||||||
|
1. Read `git log <last tag>..HEAD` and pick the version: only fixes → patch, something new → minor,
|
||||||
|
something that breaks or needs the user to act → major.
|
||||||
|
2. Bump the version and add the entry at the top of `CHANGELOG.md`, in one commit (`chore: 1.4.0`).
|
||||||
|
3. Push, then push the tag: `git tag v1.4.0 && git push origin main v1.4.0`. The `release` workflow
|
||||||
|
builds the packages and creates the release. It stops before building when the entry is missing.
|
||||||
|
4. PKGBUILDS picks up the new release for the AUR on its own.
|
||||||
|
|
||||||
|
A minor or major release (has `### Highlights`, gets a heading and the support section):
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
## v1.4.0
|
||||||
|
|
||||||
|
_2026-09-24_
|
||||||
|
|
||||||
|
Welcome to plasma-face-unlock `v1.4.0`! One or two sentences on what this release is about.
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img width="480" alt="What the picture shows" src="https://raw.githubusercontent.com/LoonixTools/plasma-face-unlock/v1.4.0/<path>">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
### 🚨 Breaking changes
|
||||||
|
|
||||||
|
- Only if there are any: what changed, and what the user has to do.
|
||||||
|
|
||||||
|
### Highlights
|
||||||
|
|
||||||
|
- First highlight, a few words
|
||||||
|
- Second highlight
|
||||||
|
```
|
||||||
|
|
||||||
|
A picture under the welcome is optional. To show the menu or another screen of the program, use a
|
||||||
|
real screenshot of it running in Konsole, in English. Never a text copy of the screen. The same goes
|
||||||
|
for the README. The highlights stay a plain list: no heading or text per highlight, the list of
|
||||||
|
commits explains the rest.
|
||||||
|
|
||||||
|
A patch release is just a sentence or two, for example: "A small patch. The menu no longer closes
|
||||||
|
when you press Enter." The list of commits follows on its own.
|
||||||
|
|
||||||
|
- Write for users: what they notice, not how the code does it. Friendly and simple.
|
||||||
|
- Commands and settings they type go in backticks, buttons and labels in bold.
|
||||||
|
- To change an old release: edit its entry, commit, then
|
||||||
|
`gh release edit <tag> --title <tag> --notes "$(.github/release-notes.sh <tag>)"`.
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
Never test against the real setup: enrolling and the PAM files belong to the user's machine.
|
Never test against the real setup: enrolling and the PAM files belong to the user's machine.
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
# installed by the Makefile, which is where the paths come from.
|
# installed by the Makefile, which is where the paths come from.
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.22)
|
cmake_minimum_required(VERSION 3.22)
|
||||||
project(plasma-face-unlock VERSION 1.0.0 LANGUAGES C CXX)
|
project(plasma-face-unlock VERSION 1.0.1 LANGUAGES C CXX)
|
||||||
|
|
||||||
set(PFU_VERSION "${PROJECT_VERSION}" CACHE STRING "Version reported by every binary")
|
set(PFU_VERSION "${PROJECT_VERSION}" CACHE STRING "Version reported by every binary")
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
# Overridable so a packager can pass the version it is actually building
|
# Overridable so a packager can pass the version it is actually building
|
||||||
# (`make VERSION=$pkgver`). The literal below is the fallback for builds
|
# (`make VERSION=$pkgver`). The literal below is the fallback for builds
|
||||||
# straight from a checkout, and is what a release tag has to carry.
|
# straight from a checkout, and is what a release tag has to carry.
|
||||||
VERSION ?= 1.0.0
|
VERSION ?= 1.0.1
|
||||||
|
|
||||||
PREFIX ?= /usr
|
PREFIX ?= /usr
|
||||||
DESTDIR ?=
|
DESTDIR ?=
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<h3 align="center">Face ID for KDE Plasma.</h3>
|
<h3 align="center">Face ID for KDE Plasma.</h3>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Look at the screen and it unlocks: the lock screen, sudo and admin prompts. A photo of you is not enough.
|
Look at the screen and it unlocks: the lock screen, sudo and admin prompts. A photo on a phone does not fool it.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h5 align="center">
|
<h5 align="center">
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="res/screenshots/unlock.webp" alt="The bubble drops down over the lock screen, the face in it looks around, asks for a blink, and two green rings spin and land around a tick" width="480">
|
<img src="res/screenshots/unlock.webp" alt="The bubble drops down over the lock screen, the face in it looks around, and two green rings spin and land around a tick" width="480">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -41,7 +41,7 @@ your computer, and your face is saved as numbers, never as a picture.
|
|||||||
yay -S plasma-face-unlock
|
yay -S plasma-face-unlock
|
||||||
```
|
```
|
||||||
|
|
||||||
**Fedora 44**
|
**Fedora**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \
|
sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \
|
||||||
@@ -49,29 +49,20 @@ sudo curl -fsSL -o /etc/yum.repos.d/plasma-face-unlock.repo \
|
|||||||
sudo dnf install plasma-face-unlock
|
sudo dnf install plasma-face-unlock
|
||||||
```
|
```
|
||||||
|
|
||||||
**Debian 13**
|
**Debian, Kubuntu**
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
codename="$(sed -n 's/^VERSION_CODENAME=//p' /etc/os-release)"
|
||||||
sudo install -d -m 0755 /etc/apt/keyrings
|
sudo install -d -m 0755 /etc/apt/keyrings
|
||||||
curl -fsSL https://loonixtools.github.io/plasma-face-unlock/KEY.gpg \
|
curl -fsSL https://loonixtools.github.io/plasma-face-unlock/KEY.gpg \
|
||||||
| sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
|
| sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] https://loonixtools.github.io/plasma-face-unlock/deb/trixie ./" \
|
echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] https://loonixtools.github.io/plasma-face-unlock/deb/$codename ./" \
|
||||||
| sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
|
| sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
|
||||||
sudo apt update && sudo apt install plasma-face-unlock
|
sudo apt update && sudo apt install plasma-face-unlock
|
||||||
```
|
```
|
||||||
|
|
||||||
**Kubuntu 26.04**
|
The packages are built for the current release of each. Updates then come with your normal system
|
||||||
|
updates.
|
||||||
```bash
|
|
||||||
sudo install -d -m 0755 /etc/apt/keyrings
|
|
||||||
curl -fsSL https://loonixtools.github.io/plasma-face-unlock/KEY.gpg \
|
|
||||||
| sudo gpg --dearmor -o /etc/apt/keyrings/plasma-face-unlock.gpg
|
|
||||||
echo "deb [signed-by=/etc/apt/keyrings/plasma-face-unlock.gpg] https://loonixtools.github.io/plasma-face-unlock/deb/resolute ./" \
|
|
||||||
| sudo tee /etc/apt/sources.list.d/plasma-face-unlock.list
|
|
||||||
sudo apt update && sudo apt install plasma-face-unlock
|
|
||||||
```
|
|
||||||
|
|
||||||
Updates then come with your normal system updates.
|
|
||||||
|
|
||||||
You need Plasma 6 on Wayland and a camera. Infrared cameras (the Windows Hello kind) work too.
|
You need Plasma 6 on Wayland and a camera. Infrared cameras (the Windows Hello kind) work too.
|
||||||
|
|
||||||
@@ -81,16 +72,22 @@ You need Plasma 6 on Wayland and a camera. Infrared cameras (the Windows Hello k
|
|||||||
plasma-face-unlock
|
plasma-face-unlock
|
||||||
```
|
```
|
||||||
|
|
||||||
This opens a menu. Press **1** and follow the setup window: look at the camera, then turn your head
|
This opens a menu:
|
||||||
slowly in a circle until the ring is full. Then lock the screen and look at it.
|
|
||||||
|
|
||||||
| Key | |
|
<p align="center">
|
||||||
|---|---|
|
<img src="res/screenshots/menu.png" alt="The plasma-face-unlock menu in Konsole: face unlock on, one face, lock screen, sudo and admin prompts on" width="560">
|
||||||
| **1** | Turn face unlock on or off |
|
</p>
|
||||||
| **2** | Add another face, for example with glasses |
|
|
||||||
| **3** | Rename, turn off or delete faces |
|
Press **1** and follow the setup window: look at the camera, then turn your head slowly in a circle
|
||||||
| **4** | Settings: sudo, admin prompts, photo check, camera, bubble style, animation speed and more |
|
until the ring is full. Then lock the screen and look at it. **2** adds another face, for example
|
||||||
| **5** | One test scan that shows what the camera sees. Try this first when something does not work. |
|
with glasses, and **5** runs one test scan that shows what the camera sees. Try that first when
|
||||||
|
something does not work.
|
||||||
|
|
||||||
|
**4** opens the settings. The text at the bottom says what the selected one does:
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="res/screenshots/settings.png" alt="The settings in Konsole, grouped into lock screen, password prompts, recognition and bubble, with the photo check explained at the bottom" width="680">
|
||||||
|
</p>
|
||||||
|
|
||||||
Without the menu: `plasma-face-unlock enable`, `disable`, `setup [NAME]`, `faces`, `remove ID`,
|
Without the menu: `plasma-face-unlock enable`, `disable`, `setup [NAME]`, `faces`, `remove ID`,
|
||||||
`test` and `status`.
|
`test` and `status`.
|
||||||
@@ -100,8 +97,10 @@ Without the menu: `plasma-face-unlock enable`, `disable`, `setup [NAME]`, `faces
|
|||||||
It is a convenience, not a security upgrade. Face ID on a phone sees your face in 3D. A webcam only
|
It is a convenience, not a security upgrade. Face ID on a phone sees your face in 3D. A webcam only
|
||||||
sees a flat picture.
|
sees a flat picture.
|
||||||
|
|
||||||
- A photo does not get in: the face has to blink or turn a little, and a photo can do neither.
|
- You do not have to blink. A photo on a phone or tablet, or a glossy print, is still refused:
|
||||||
- A phone or tablet held up to the camera is caught by its reflection and its straight edges.
|
it gives itself away by its reflection and its straight edges.
|
||||||
|
- A matte printed photo can get past that. Set the photo check to *strict* in the settings: then
|
||||||
|
the face has to blink or turn a little, and a photo can do neither.
|
||||||
- A video of you can still get in.
|
- A video of you can still get in.
|
||||||
- Five failed tries in a row pause it for 15 minutes, or until you use your password.
|
- Five failed tries in a row pause it for 15 minutes, or until you use your password.
|
||||||
- Only root can read your face data. Adding or deleting a face always needs your password.
|
- Only root can read your face data. Adding or deleting a face always needs your password.
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ plasma-face-unlock - face unlock for KDE Plasma
|
|||||||
|
|
||||||
Look at the screen and it unlocks, the way a phone does. The lock screen, sudo
|
Look at the screen and it unlocks, the way a phone does. The lock screen, sudo
|
||||||
in a terminal and the admin password prompts of Plasma can all take a face
|
in a terminal and the admin password prompts of Plasma can all take a face
|
||||||
instead of a password. Before a face counts, it has to show a sign of life, so
|
instead of a password. A photo of somebody on a phone or tablet does not get
|
||||||
holding up a photo of somebody is not enough.
|
in, and with the strict photo check a printed one does not either.
|
||||||
|
|
||||||
A bubble at the top of the screen shows what is going on: it drops down when
|
A bubble at the top of the screen shows what is going on: it drops down when
|
||||||
the camera starts looking, the face in it looks around, and when it recognises
|
the camera starts looking, the face in it looks around, and when it recognises
|
||||||
@@ -100,7 +100,7 @@ threshold count, so the samples cannot drift towards somebody else one
|
|||||||
borderline unlock at a time.
|
borderline unlock at a time.
|
||||||
|
|
||||||
A match has to hold for two frames. The face has to look at the screen with
|
A match has to hold for two frames. The face has to look at the screen with
|
||||||
its eyes open (*Only while looking at the screen*), and it has to be the same
|
its eyes open (*Only when you look at the screen*), and it has to be the same
|
||||||
face that shows the sign of life: a face that jumps in the picture, disappears
|
face that shows the sign of life: a face that jumps in the picture, disappears
|
||||||
or stops matching starts the whole check again.
|
or stops matching starts the whole check again.
|
||||||
|
|
||||||
@@ -128,14 +128,18 @@ Confirm cues are evidence of a real head. *strict* needs one of them:
|
|||||||
real turn, measured without the nose's own jitter, and the face has to
|
real turn, measured without the nose's own jitter, and the face has to
|
||||||
narrow no more than a head that turned that far would.
|
narrow no more than a head that turned that far would.
|
||||||
|
|
||||||
*basic* uses the deny cues only. *off* checks nothing and is only for trying
|
*basic*, the default, uses the deny cues only: nobody has to blink, and a
|
||||||
out a camera.
|
phone, a tablet or a glossy print held up is still refused. A matte printed
|
||||||
|
photo is not, so *strict* is the one to pick when that matters. *off* checks
|
||||||
|
nothing and is only for trying out a camera.
|
||||||
|
|
||||||
# HOW SAFE IS THIS
|
# HOW SAFE IS THIS
|
||||||
|
|
||||||
A webcam sees a flat picture. A phone's face unlock builds a depth map with a
|
A webcam sees a flat picture. A phone's face unlock builds a depth map with a
|
||||||
projector and an infrared camera; this cannot. What the photo check does:
|
projector and an infrared camera; this cannot. What the photo check does:
|
||||||
|
|
||||||
|
- a photo on a phone or tablet, or a glossy print, is refused by *basic*, the
|
||||||
|
default. A matte printed photo can get past *basic*;
|
||||||
- a photo, printed or on a screen, held up and turned any way, is refused by
|
- a photo, printed or on a screen, held up and turned any way, is refused by
|
||||||
*strict*;
|
*strict*;
|
||||||
- a photo curled strongly and turned a lot can pass the head turn cue some of
|
- a photo curled strongly and turned a lot can pass the head turn cue some of
|
||||||
@@ -176,7 +180,7 @@ scans when somebody comes back:
|
|||||||
field is a key like any other. This works while a video or an app keeps the
|
field is a key like any other. This works while a video or an app keeps the
|
||||||
screen on, too (ext_idle_notifier_v1, input notification);
|
screen on, too (ext_idle_notifier_v1, input notification);
|
||||||
- when the machine wakes from sleep;
|
- when the machine wakes from sleep;
|
||||||
- right after locking, if *Look right after the screen locks* is on. Off by
|
- right after locking, if *Scan right after locking* is on. Off by
|
||||||
default: whoever locks their screen on purpose is usually still in front of
|
default: whoever locks their screen on purpose is usually still in front of
|
||||||
it.
|
it.
|
||||||
|
|
||||||
@@ -224,7 +228,7 @@ emitter has to be switched on with a tool such as linux-enable-ir-emitter.
|
|||||||
In infrared a phone screen shows up black, which makes the photo check's job
|
In infrared a phone screen shows up black, which makes the photo check's job
|
||||||
easier. A face set up with one camera should be set up again for another.
|
easier. A face set up with one camera should be set up again for another.
|
||||||
|
|
||||||
A laptop with its lid shut is not scanned (*Not while the lid is closed*).
|
A laptop with its lid shut is not scanned (*Not when the lid is closed*).
|
||||||
|
|
||||||
# FILES
|
# FILES
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -8,12 +8,14 @@ description of the layout, and two descriptions drift.
|
|||||||
|---|---|
|
|---|---|
|
||||||
| `deb/control`, `deb/copyright` | metadata for the Debian binary package |
|
| `deb/control`, `deb/copyright` | metadata for the Debian binary package |
|
||||||
| `rpm/plasma-face-unlock.spec` | the RPM spec |
|
| `rpm/plasma-face-unlock.spec` | the RPM spec |
|
||||||
| `aur/PKGBUILD`, `aur/plasma-face-unlock.install` | the AUR package |
|
|
||||||
| `build-deb.sh`, `build-rpm.sh` | build one package into `dist/` |
|
| `build-deb.sh`, `build-rpm.sh` | build one package into `dist/` |
|
||||||
| `check-version.sh` | refuses a tag that disagrees with the Makefile |
|
| `check-version.sh` | refuses a tag that disagrees with the Makefile |
|
||||||
| `publish-repos.sh` | regenerates the APT and RPM repositories |
|
| `publish-repos.sh` | regenerates the APT and RPM repositories |
|
||||||
| `pages/` | the landing page and the `.repo` file served from GitHub Pages |
|
| `pages/` | the landing page and the `.repo` file served from GitHub Pages |
|
||||||
|
|
||||||
|
The AUR package lives in [Felitendo/PKGBUILDS](https://github.com/Felitendo/PKGBUILDS/tree/main/plasma-face-unlock).
|
||||||
|
Its CI notices a new GitHub release, updates the checksum and pushes to the AUR.
|
||||||
|
|
||||||
Unlike the shell-only LoonixTools, this one is compiled. The packages are per
|
Unlike the shell-only LoonixTools, this one is compiled. The packages are per
|
||||||
architecture (amd64 and x86_64), and they need the Plasma 6 and Qt 6
|
architecture (amd64 and x86_64), and they need the Plasma 6 and Qt 6
|
||||||
development packages to build: Debian 13 (trixie) and current Fedora have
|
development packages to build: Debian 13 (trixie) and current Fedora have
|
||||||
@@ -51,12 +53,13 @@ argument.
|
|||||||
|
|
||||||
1. Bump `VERSION` in the Makefile. The compiled programs get it from there
|
1. Bump `VERSION` in the Makefile. The compiled programs get it from there
|
||||||
too (`-DPFU_VERSION`).
|
too (`-DPFU_VERSION`).
|
||||||
2. Commit, then `git tag vX.Y.Z && git push --tags`.
|
2. Add the release to `CHANGELOG.md`, in the format CLAUDE.md describes.
|
||||||
|
3. Commit, then `git tag vX.Y.Z && git push --tags`.
|
||||||
|
|
||||||
The `release` workflow builds both packages in a Debian and a Fedora container,
|
The `release` workflow builds both packages in a Debian and a Fedora container,
|
||||||
refuses the tag if it disagrees with the Makefile, attaches the packages to a
|
refuses the tag if it disagrees with the Makefile or has no changelog entry,
|
||||||
GitHub release, and adds them to the APT and RPM repositories on the `gh-pages`
|
attaches the packages to a GitHub release with the entry as its notes, and adds
|
||||||
branch.
|
them to the APT and RPM repositories on the `gh-pages` branch.
|
||||||
|
|
||||||
## Trying the release path first
|
## Trying the release path first
|
||||||
|
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
# Maintainer: Felitendo
|
|
||||||
#
|
|
||||||
# The PKGBUILD for the AUR, kept here next to the code it builds. The copy in
|
|
||||||
# github.com/Felitendo/PKGBUILDS is the one CI bumps and pushes.
|
|
||||||
|
|
||||||
pkgname=plasma-face-unlock
|
|
||||||
pkgver=1.0.0
|
|
||||||
pkgrel=1
|
|
||||||
pkgdesc="Face ID for KDE Plasma: the lock screen, sudo and admin prompts by face, with a photo check"
|
|
||||||
arch=('x86_64' 'aarch64')
|
|
||||||
url="https://github.com/LoonixTools/plasma-face-unlock"
|
|
||||||
license=('GPL-3.0-or-later' 'MIT' 'Apache-2.0')
|
|
||||||
depends=('bash' 'coreutils' 'gawk' 'grep' 'sed' 'gettext' 'systemd' 'systemd-libs' 'pam' 'polkit'
|
|
||||||
'opencv' 'qt6-base' 'qt6-declarative' 'layer-shell-qt' 'ki18n' 'kscreenlocker')
|
|
||||||
makedepends=('cmake' 'scdoc')
|
|
||||||
install="${pkgname}.install"
|
|
||||||
source=("${pkgname}-${pkgver}.tar.gz::${url}/archive/refs/tags/v${pkgver}.tar.gz"
|
|
||||||
"face_detection_yunet_2023mar.onnx::https://github.com/opencv/opencv_zoo/raw/main/models/face_detection_yunet/face_detection_yunet_2023mar.onnx"
|
|
||||||
"face_recognition_sface_2021dec.onnx::https://github.com/opencv/opencv_zoo/raw/main/models/face_recognition_sface/face_recognition_sface_2021dec.onnx")
|
|
||||||
noextract=('face_detection_yunet_2023mar.onnx' 'face_recognition_sface_2021dec.onnx')
|
|
||||||
sha256sums=('SKIP'
|
|
||||||
'8f2383e4dd3cfbb4553ea8718107fc0423210dc964f9f4280604804ed2552fa4'
|
|
||||||
'0ba9fbfa01b5270c96627c4ef784da859931e02f04419c829e83484087c34e79')
|
|
||||||
|
|
||||||
build() {
|
|
||||||
make -C "${pkgname}-${pkgver}" VERSION="$pkgver"
|
|
||||||
}
|
|
||||||
|
|
||||||
check() {
|
|
||||||
make -C "${pkgname}-${pkgver}" VERSION="$pkgver" test
|
|
||||||
}
|
|
||||||
|
|
||||||
package() {
|
|
||||||
make -C "${pkgname}-${pkgver}" VERSION="$pkgver" MODELS_SRC="$srcdir" DESTDIR="$pkgdir" install
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
post_install() {
|
|
||||||
cat <<'MSG'
|
|
||||||
|
|
||||||
plasma-face-unlock is installed but not active yet.
|
|
||||||
|
|
||||||
plasma-face-unlock interactive menu
|
|
||||||
plasma-face-unlock enable set up your face and turn it on
|
|
||||||
|
|
||||||
Run it as your own user, not with sudo. It asks for your password when it
|
|
||||||
needs to, and sudo and admin prompts stay with the password until you switch
|
|
||||||
them on under Settings.
|
|
||||||
|
|
||||||
MSG
|
|
||||||
}
|
|
||||||
|
|
||||||
pre_remove() {
|
|
||||||
cat <<'MSG'
|
|
||||||
|
|
||||||
Before removing this package, run
|
|
||||||
|
|
||||||
plasma-face-unlock disable
|
|
||||||
|
|
||||||
as each user that turned it on. That takes face unlock back out of sudo and
|
|
||||||
polkit. (Removing it without that is safe too: the PAM line is written so
|
|
||||||
that a missing module is skipped, and sudo keeps asking for the password.)
|
|
||||||
|
|
||||||
MSG
|
|
||||||
systemctl disable --now plasma-face-unlockd.socket plasma-face-unlockd.service >/dev/null 2>&1 || true
|
|
||||||
}
|
|
||||||
@@ -13,10 +13,12 @@ Description: face unlock for KDE Plasma
|
|||||||
instead of a password. A bubble at the top of the screen, above the lock
|
instead of a password. A bubble at the top of the screen, above the lock
|
||||||
screen too, shows the face being looked for, recognised or refused.
|
screen too, shows the face being looked for, recognised or refused.
|
||||||
.
|
.
|
||||||
Before a face counts it has to show a sign of life (a blink, or the nose
|
A photo on a phone, a tablet or a glossy print is refused by its
|
||||||
moving the way a real nose does when the head turns), so a photo held up to
|
reflection and its straight edges. The strict photo check also wants a sign
|
||||||
the camera is not enough. It is a convenience, not a security upgrade: a
|
of life (a blink, or the nose moving the way a real nose does when the head
|
||||||
webcam sees a flat picture, and a video of the person can get through.
|
turns), which stops a printed photo too. It is a convenience, not a security
|
||||||
|
upgrade: a webcam sees a flat picture, and a video of the person can get
|
||||||
|
through.
|
||||||
.
|
.
|
||||||
Everything runs on the machine. Faces are stored as numbers readable only by
|
Everything runs on the machine. Faces are stored as numbers readable only by
|
||||||
root, never as pictures. Run "plasma-face-unlock disable" before removing
|
root, never as pictures. Run "plasma-face-unlock disable" before removing
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Built with `packaging/build-rpm.sh`, which passes the version in rather than
|
# Built with `packaging/build-rpm.sh`, which passes the version in rather than
|
||||||
# editing this file: the Makefile is where the version is written down.
|
# editing this file: the Makefile is where the version is written down.
|
||||||
%global upstream_version %{?_version}%{!?_version:1.0.0}
|
%global upstream_version %{?_version}%{!?_version:1.0.1}
|
||||||
|
|
||||||
Name: plasma-face-unlock
|
Name: plasma-face-unlock
|
||||||
Version: %{upstream_version}
|
Version: %{upstream_version}
|
||||||
@@ -53,9 +53,10 @@ in a terminal and the admin password prompts of Plasma can take a face instead
|
|||||||
of a password. A bubble at the top of the screen, above the lock screen too,
|
of a password. A bubble at the top of the screen, above the lock screen too,
|
||||||
shows the face being looked for, recognised or refused.
|
shows the face being looked for, recognised or refused.
|
||||||
|
|
||||||
Before a face counts it has to show a sign of life (a blink, or the nose moving
|
A photo on a phone, a tablet or a glossy print is refused by its reflection and
|
||||||
the way a real nose does when the head turns), so a photo held up to the camera
|
its straight edges. The strict photo check also wants a sign of life (a blink,
|
||||||
is not enough. It is a convenience, not a security upgrade: a webcam sees a
|
or the nose moving the way a real nose does when the head turns), which stops a
|
||||||
|
printed photo too. It is a convenience, not a security upgrade: a webcam sees a
|
||||||
flat picture, and a video of the person can get through.
|
flat picture, and a video of the person can get through.
|
||||||
|
|
||||||
Run "plasma-face-unlock disable" before removing this package, so that sudo
|
Run "plasma-face-unlock disable" before removing this package, so that sudo
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ msgstr ""
|
|||||||
"Project-Id-Version: plasma-face-unlock 1.0.0\n"
|
"Project-Id-Version: plasma-face-unlock 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/"
|
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/"
|
||||||
"issues\n"
|
"issues\n"
|
||||||
"POT-Creation-Date: 2026-09-22 18:45+0200\n"
|
"POT-Creation-Date: 2026-09-24 01:31+0200\n"
|
||||||
"PO-Revision-Date: 2026-09-22 18:45+0200\n"
|
"PO-Revision-Date: 2026-09-23 22:32+0200\n"
|
||||||
"Last-Translator: Felitendo\n"
|
"Last-Translator: Felitendo\n"
|
||||||
"Language-Team: German\n"
|
"Language-Team: German\n"
|
||||||
"Language: de\n"
|
"Language: de\n"
|
||||||
@@ -20,7 +20,9 @@ msgstr ""
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Face unlock's service has to be switched on once for this computer. That "
|
"Face unlock's service has to be switched on once for this computer. That "
|
||||||
"needs your password."
|
"needs your password."
|
||||||
msgstr "Der Dienst für die Gesichtsentsperrung muss auf diesem Computer einmal eingeschaltet werden. Dafür wird dein Passwort gebraucht."
|
msgstr ""
|
||||||
|
"Der Dienst für die Gesichtsentsperrung muss auf diesem Computer einmal "
|
||||||
|
"eingeschaltet werden. Dafür wird dein Passwort gebraucht."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:57
|
#: src/plasma-face-unlock:57
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
@@ -31,7 +33,9 @@ msgstr "Prüfen mit: systemctl status %s"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Setting up a face needs the camera picture on screen. Run this inside your "
|
"Setting up a face needs the camera picture on screen. Run this inside your "
|
||||||
"Plasma session."
|
"Plasma session."
|
||||||
msgstr "Zum Einrichten eines Gesichts muss das Kamerabild auf dem Bildschirm zu sehen sein. Starte das in deiner Plasma-Sitzung."
|
msgstr ""
|
||||||
|
"Zum Einrichten eines Gesichts muss das Kamerabild auf dem Bildschirm zu "
|
||||||
|
"sehen sein. Starte das in deiner Plasma-Sitzung."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:71
|
#: src/plasma-face-unlock:71
|
||||||
msgid "The setup window is open. Follow it there."
|
msgid "The setup window is open. Follow it there."
|
||||||
@@ -44,7 +48,9 @@ msgstr "Das Gesicht ist eingerichtet."
|
|||||||
#: src/plasma-face-unlock:83
|
#: src/plasma-face-unlock:83
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
msgid "Face unlock is still off. Turn it on with [1] or `%s enable`."
|
||||||
msgstr "Die Gesichtsentsperrung ist noch aus. Schalte sie mit [1] oder `%s enable` ein."
|
msgstr ""
|
||||||
|
"Die Gesichtsentsperrung ist noch aus. Schalte sie mit [1] oder `%s enable` "
|
||||||
|
"ein."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:87
|
#: src/plasma-face-unlock:87
|
||||||
msgid "No face was added."
|
msgid "No face was added."
|
||||||
@@ -54,7 +60,8 @@ msgstr "Es wurde kein Gesicht hinzugefügt."
|
|||||||
msgid "First, set up your face."
|
msgid "First, set up your face."
|
||||||
msgstr "Richte zuerst dein Gesicht ein."
|
msgstr "Richte zuerst dein Gesicht ein."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:338
|
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:406
|
||||||
|
#: src/lib/menu.sh:410 src/lib/menu.sh:416 src/lib/menu.sh:418
|
||||||
msgid "Could not save the setting."
|
msgid "Could not save the setting."
|
||||||
msgstr "Einstellung konnte nicht gespeichert werden."
|
msgstr "Einstellung konnte nicht gespeichert werden."
|
||||||
|
|
||||||
@@ -64,11 +71,15 @@ msgstr "Der Sperrbildschirm-Dienst konnte nicht gestartet werden."
|
|||||||
|
|
||||||
#: src/plasma-face-unlock:106
|
#: src/plasma-face-unlock:106
|
||||||
msgid "No systemd user session, so the lock screen agent was not started."
|
msgid "No systemd user session, so the lock screen agent was not started."
|
||||||
msgstr "Keine systemd-Benutzersitzung, daher wurde der Sperrbildschirm-Dienst nicht gestartet."
|
msgstr ""
|
||||||
|
"Keine systemd-Benutzersitzung, daher wurde der Sperrbildschirm-Dienst nicht "
|
||||||
|
"gestartet."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:113
|
#: src/plasma-face-unlock:113
|
||||||
msgid "Face unlock is on. Lock the screen and look at it to try."
|
msgid "Face unlock is on. Lock the screen and look at it to try."
|
||||||
msgstr "Die Gesichtsentsperrung ist an. Sperre den Bildschirm und schau ihn an, um es auszuprobieren."
|
msgstr ""
|
||||||
|
"Die Gesichtsentsperrung ist an. Sperre den Bildschirm und schau ihn an, um "
|
||||||
|
"es auszuprobieren."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:115
|
#: src/plasma-face-unlock:115
|
||||||
msgid "It can do sudo and admin prompts too. See Settings."
|
msgid "It can do sudo and admin prompts too. See Settings."
|
||||||
@@ -76,22 +87,24 @@ msgstr "Sie kann auch sudo und Admin-Abfragen übernehmen. Siehe Einstellungen."
|
|||||||
|
|
||||||
#: src/plasma-face-unlock:130
|
#: src/plasma-face-unlock:130
|
||||||
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
msgid "Face unlock is off. Your faces are kept; delete them under Faces."
|
||||||
msgstr "Die Gesichtsentsperrung ist aus. Deine Gesichter bleiben erhalten; löschen kannst du sie unter Gesichter."
|
msgstr ""
|
||||||
|
"Die Gesichtsentsperrung ist aus. Deine Gesichter bleiben erhalten; löschen "
|
||||||
|
"kannst du sie unter Gesichter."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
#: src/plasma-face-unlock:144 src/lib/daemon.sh:109
|
||||||
msgid "No face is set up yet."
|
msgid "No face is set up yet."
|
||||||
msgstr "Es ist noch kein Gesicht eingerichtet."
|
msgstr "Es ist noch kein Gesicht eingerichtet."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:157 src/lib/menu.sh:460
|
#: src/plasma-face-unlock:148 src/lib/menu.sh:167 src/lib/menu.sh:563
|
||||||
msgid "on"
|
msgid "on"
|
||||||
msgstr "an"
|
msgstr "an"
|
||||||
|
|
||||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:159 src/lib/menu.sh:169
|
#: src/plasma-face-unlock:148 src/lib/menu.sh:169 src/lib/menu.sh:179
|
||||||
#: src/lib/menu.sh:461
|
#: src/lib/menu.sh:564
|
||||||
msgid "off"
|
msgid "off"
|
||||||
msgstr "aus"
|
msgstr "aus"
|
||||||
|
|
||||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:478
|
#: src/plasma-face-unlock:150 src/lib/menu.sh:581
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%s samples, %s learned"
|
msgid "%s samples, %s learned"
|
||||||
msgstr "%s Aufnahmen, %s dazugelernt"
|
msgstr "%s Aufnahmen, %s dazugelernt"
|
||||||
@@ -121,7 +134,7 @@ msgstr "Gesichtsentsperrung einschalten"
|
|||||||
msgid "Turn it off (faces are kept)"
|
msgid "Turn it off (faces are kept)"
|
||||||
msgstr "Ausschalten (Gesichter bleiben erhalten)"
|
msgstr "Ausschalten (Gesichter bleiben erhalten)"
|
||||||
|
|
||||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:540
|
#: src/plasma-face-unlock:176 src/lib/menu.sh:646
|
||||||
msgid "Add a face"
|
msgid "Add a face"
|
||||||
msgstr "Gesicht hinzufügen"
|
msgstr "Gesicht hinzufügen"
|
||||||
|
|
||||||
@@ -157,7 +170,9 @@ msgstr "Ohne Befehl wird ein interaktives Menü angezeigt."
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Run this as your own user, not as root. It asks for your password when it "
|
"Run this as your own user, not as root. It asks for your password when it "
|
||||||
"needs to."
|
"needs to."
|
||||||
msgstr "Starte das als dein eigener Benutzer, nicht als root. Wenn nötig, wird nach deinem Passwort gefragt."
|
msgstr ""
|
||||||
|
"Starte das als dein eigener Benutzer, nicht als root. Wenn nötig, wird nach "
|
||||||
|
"deinem Passwort gefragt."
|
||||||
|
|
||||||
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
#: src/plasma-face-unlock:221 src/lib/system.sh:89
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
@@ -172,17 +187,29 @@ msgstr "nie"
|
|||||||
msgid "just now"
|
msgid "just now"
|
||||||
msgstr "gerade eben"
|
msgstr "gerade eben"
|
||||||
|
|
||||||
#: src/lib/common.sh:173
|
#: src/lib/common.sh:172
|
||||||
|
msgid "1 minute ago"
|
||||||
|
msgstr "vor 1 Minute"
|
||||||
|
|
||||||
|
#: src/lib/common.sh:175
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%d minutes ago"
|
msgid "%d minutes ago"
|
||||||
msgstr "vor %d Minuten"
|
msgstr "vor %d Minuten"
|
||||||
|
|
||||||
#: src/lib/common.sh:176
|
#: src/lib/common.sh:177
|
||||||
|
msgid "1 hour ago"
|
||||||
|
msgstr "vor 1 Stunde"
|
||||||
|
|
||||||
|
#: src/lib/common.sh:180
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%d hours ago"
|
msgid "%d hours ago"
|
||||||
msgstr "vor %d Stunden"
|
msgstr "vor %d Stunden"
|
||||||
|
|
||||||
#: src/lib/common.sh:179
|
#: src/lib/common.sh:182
|
||||||
|
msgid "1 day ago"
|
||||||
|
msgstr "vor 1 Tag"
|
||||||
|
|
||||||
|
#: src/lib/common.sh:185
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%d days ago"
|
msgid "%d days ago"
|
||||||
msgstr "vor %d Tagen"
|
msgstr "vor %d Tagen"
|
||||||
@@ -214,13 +241,15 @@ msgstr "Kein Gesicht zu sehen."
|
|||||||
#: src/lib/daemon.sh:108
|
#: src/lib/daemon.sh:108
|
||||||
msgid ""
|
msgid ""
|
||||||
"Face unlock is paused after too many tries. Unlock once with your password."
|
"Face unlock is paused after too many tries. Unlock once with your password."
|
||||||
msgstr "Die Gesichtsentsperrung ist nach zu vielen Versuchen pausiert. Entsperre einmal mit deinem Passwort."
|
msgstr ""
|
||||||
|
"Die Gesichtsentsperrung ist nach zu vielen Versuchen pausiert. Entsperre "
|
||||||
|
"einmal mit deinem Passwort."
|
||||||
|
|
||||||
#: src/lib/daemon.sh:110
|
#: src/lib/daemon.sh:110
|
||||||
msgid "The camera could not be used."
|
msgid "The camera could not be used."
|
||||||
msgstr "Die Kamera konnte nicht benutzt werden."
|
msgstr "Die Kamera konnte nicht benutzt werden."
|
||||||
|
|
||||||
#: src/lib/daemon.sh:111 src/lib/menu.sh:233
|
#: src/lib/daemon.sh:111 src/lib/menu.sh:246
|
||||||
msgid "The recognition models are missing. Reinstall the package."
|
msgid "The recognition models are missing. Reinstall the package."
|
||||||
msgstr "Die Erkennungsmodelle fehlen. Installiere das Paket neu."
|
msgstr "Die Erkennungsmodelle fehlen. Installiere das Paket neu."
|
||||||
|
|
||||||
@@ -315,175 +344,315 @@ msgstr "Lebenszeichen: %s"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"That was too many tries. Face unlock is paused until you unlock with your "
|
"That was too many tries. Face unlock is paused until you unlock with your "
|
||||||
"password."
|
"password."
|
||||||
msgstr "Das waren zu viele Versuche. Die Gesichtsentsperrung ist pausiert, bis du mit deinem Passwort entsperrst."
|
msgstr ""
|
||||||
|
"Das waren zu viele Versuche. Die Gesichtsentsperrung ist pausiert, bis du "
|
||||||
|
"mit deinem Passwort entsperrst."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:140
|
||||||
#: src/lib/menu.sh:130
|
|
||||||
msgid "[y/N]"
|
msgid "[y/N]"
|
||||||
msgstr "[j/N]"
|
msgstr "[j/N]"
|
||||||
|
|
||||||
#: src/lib/menu.sh:149 src/lib/menu.sh:382
|
#: src/lib/menu.sh:159 src/lib/menu.sh:467
|
||||||
msgid "ON"
|
msgid "ON"
|
||||||
msgstr "AN"
|
msgstr "AN"
|
||||||
|
|
||||||
#: src/lib/menu.sh:151 src/lib/menu.sh:383
|
#: src/lib/menu.sh:161 src/lib/menu.sh:468
|
||||||
msgid "OFF"
|
msgid "OFF"
|
||||||
msgstr "AUS"
|
msgstr "AUS"
|
||||||
|
|
||||||
#: src/lib/menu.sh:167
|
#: src/lib/menu.sh:177 src/lib/menu.sh:181
|
||||||
msgid "strict (blink or turn your head)"
|
|
||||||
msgstr "streng (blinzeln oder Kopf drehen)"
|
|
||||||
|
|
||||||
#: src/lib/menu.sh:168
|
|
||||||
msgid "basic (screens and phone edges)"
|
|
||||||
msgstr "einfach (Bildschirme und Handyränder)"
|
|
||||||
|
|
||||||
#: src/lib/menu.sh:170
|
|
||||||
msgid "normal"
|
|
||||||
msgstr "normal"
|
|
||||||
|
|
||||||
#: src/lib/menu.sh:171
|
|
||||||
msgid "strict"
|
msgid "strict"
|
||||||
msgstr "streng"
|
msgstr "streng"
|
||||||
|
|
||||||
#: src/lib/menu.sh:172
|
#: src/lib/menu.sh:178
|
||||||
|
msgid "basic"
|
||||||
|
msgstr "einfach"
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:180 src/lib/menu.sh:185
|
||||||
|
msgid "normal"
|
||||||
|
msgstr "normal"
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:182
|
||||||
msgid "relaxed"
|
msgid "relaxed"
|
||||||
msgstr "locker"
|
msgstr "locker"
|
||||||
|
|
||||||
#: src/lib/menu.sh:173
|
#: src/lib/menu.sh:183
|
||||||
msgid "island with the face"
|
msgid "island with the face"
|
||||||
msgstr "Insel mit Gesicht"
|
msgstr "Insel mit Gesicht"
|
||||||
|
|
||||||
#: src/lib/menu.sh:174
|
#: src/lib/menu.sh:184
|
||||||
msgid "small pill with a lock"
|
msgid "small pill with a lock"
|
||||||
msgstr "kleine Pille mit Schloss"
|
msgstr "kleine Pille mit Schloss"
|
||||||
|
|
||||||
#: src/lib/menu.sh:175
|
#: src/lib/menu.sh:186
|
||||||
|
msgid "fast"
|
||||||
|
msgstr "schnell"
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:187
|
||||||
|
msgid "slow"
|
||||||
|
msgstr "langsam"
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:188
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%s seconds"
|
msgid "%s seconds"
|
||||||
msgstr "%s Sekunden"
|
msgstr "%s Sekunden"
|
||||||
|
|
||||||
#: src/lib/menu.sh:176 src/lib/menu.sh:313
|
#: src/lib/menu.sh:189 src/lib/menu.sh:381
|
||||||
msgid "automatic"
|
msgid "automatic"
|
||||||
msgstr "automatisch"
|
msgstr "automatisch"
|
||||||
|
|
||||||
#: src/lib/menu.sh:193
|
#: src/lib/menu.sh:206
|
||||||
msgid "Face unlock"
|
msgid "Face unlock"
|
||||||
msgstr "Gesichtsentsperrung"
|
msgstr "Gesichtsentsperrung"
|
||||||
|
|
||||||
#: src/lib/menu.sh:197
|
#: src/lib/menu.sh:210
|
||||||
msgid "Service"
|
msgid "Service"
|
||||||
msgstr "Dienst"
|
msgstr "Dienst"
|
||||||
|
|
||||||
#: src/lib/menu.sh:197
|
#: src/lib/menu.sh:210
|
||||||
msgid "not running"
|
msgid "not running"
|
||||||
msgstr "läuft nicht"
|
msgstr "läuft nicht"
|
||||||
|
|
||||||
#: src/lib/menu.sh:199
|
#: src/lib/menu.sh:212
|
||||||
msgid "Turning face unlock on again starts it."
|
msgid "Turning face unlock on again starts it."
|
||||||
msgstr "Die Gesichtsentsperrung erneut einzuschalten startet ihn."
|
msgstr "Die Gesichtsentsperrung erneut einzuschalten startet ihn."
|
||||||
|
|
||||||
#: src/lib/menu.sh:210 src/lib/menu.sh:212 src/lib/menu.sh:457
|
#: src/lib/menu.sh:223 src/lib/menu.sh:225 src/lib/menu.sh:560
|
||||||
#: src/lib/menu.sh:541
|
#: src/lib/menu.sh:647
|
||||||
msgid "Faces"
|
msgid "Faces"
|
||||||
msgstr "Gesichter"
|
msgstr "Gesichter"
|
||||||
|
|
||||||
#: src/lib/menu.sh:210
|
#: src/lib/menu.sh:223
|
||||||
msgid "none set up yet"
|
msgid "none set up yet"
|
||||||
msgstr "noch keins eingerichtet"
|
msgstr "noch keins eingerichtet"
|
||||||
|
|
||||||
#: src/lib/menu.sh:212
|
#: src/lib/menu.sh:225
|
||||||
msgid "all turned off"
|
msgid "all turned off"
|
||||||
msgstr "alle ausgeschaltet"
|
msgstr "alle ausgeschaltet"
|
||||||
|
|
||||||
#: src/lib/menu.sh:218
|
#: src/lib/menu.sh:231
|
||||||
msgid "none found"
|
msgid "none found"
|
||||||
msgstr "keine gefunden"
|
msgstr "keine gefunden"
|
||||||
|
|
||||||
#: src/lib/menu.sh:220 /tmp/tmp.q9gMIu3Tjj/settings.sh:9
|
#: src/lib/menu.sh:233 /tmp/tmp.3ElRvSMg8S/settings.sh:12
|
||||||
msgid "Camera"
|
msgid "Camera"
|
||||||
msgstr "Kamera"
|
msgstr "Kamera"
|
||||||
|
|
||||||
#: src/lib/menu.sh:222
|
#: src/lib/menu.sh:235 /tmp/tmp.3ElRvSMg8S/settings.sh:1
|
||||||
msgid "Lock screen"
|
msgid "Lock screen"
|
||||||
msgstr "Sperrbildschirm"
|
msgstr "Sperrbildschirm"
|
||||||
|
|
||||||
#: src/lib/menu.sh:223
|
#: src/lib/menu.sh:236
|
||||||
msgid "sudo"
|
msgid "sudo"
|
||||||
msgstr "sudo"
|
msgstr "sudo"
|
||||||
|
|
||||||
#: src/lib/menu.sh:224
|
#: src/lib/menu.sh:237 /tmp/tmp.3ElRvSMg8S/settings.sh:7
|
||||||
msgid "Admin prompts"
|
msgid "Admin prompts"
|
||||||
msgstr "Admin-Abfragen"
|
msgstr "Admin-Abfragen"
|
||||||
|
|
||||||
#: src/lib/menu.sh:225 /tmp/tmp.q9gMIu3Tjj/settings.sh:6
|
#: src/lib/menu.sh:238 /tmp/tmp.3ElRvSMg8S/settings.sh:9
|
||||||
msgid "Photo check"
|
msgid "Photo check"
|
||||||
msgstr "Foto-Prüfung"
|
msgstr "Foto-Prüfung"
|
||||||
|
|
||||||
#: src/lib/menu.sh:228
|
#: src/lib/menu.sh:241
|
||||||
msgid "Paused"
|
msgid "Paused"
|
||||||
msgstr "Pausiert"
|
msgstr "Pausiert"
|
||||||
|
|
||||||
#: src/lib/menu.sh:228
|
#: src/lib/menu.sh:241
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "for %d more minutes, or until the password is used"
|
msgid "for %d more minutes, or until the password is used"
|
||||||
msgstr "noch %d Minuten, oder bis das Passwort benutzt wird"
|
msgstr "noch %d Minuten, oder bis das Passwort benutzt wird"
|
||||||
|
|
||||||
#: src/lib/menu.sh:230
|
#: src/lib/menu.sh:243
|
||||||
msgid "Last unlock"
|
msgid "Last unlock"
|
||||||
msgstr "Letzte Entsperrung"
|
msgstr "Letzte Entsperrung"
|
||||||
|
|
||||||
#: src/lib/menu.sh:309
|
#: src/lib/menu.sh:287
|
||||||
|
msgid ""
|
||||||
|
"Unlocks the lock screen when it sees your face. Off: only your password "
|
||||||
|
"works there."
|
||||||
|
msgstr ""
|
||||||
|
"Entsperrt den Sperrbildschirm, wenn er dein Gesicht sieht. Aus: Dort geht "
|
||||||
|
"nur dein Passwort."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:288
|
||||||
|
msgid ""
|
||||||
|
"Scans when you press a key or move the mouse on the lock screen, and when "
|
||||||
|
"the computer wakes up."
|
||||||
|
msgstr ""
|
||||||
|
"Scannt, wenn du auf dem Sperrbildschirm eine Taste drückst oder die Maus "
|
||||||
|
"bewegst, und wenn der Computer aufwacht."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:289
|
||||||
|
msgid ""
|
||||||
|
"Scans as soon as the screen locks. Off by default: if you lock it yourself, "
|
||||||
|
"it would unlock again right away."
|
||||||
|
msgstr ""
|
||||||
|
"Scannt, sobald der Bildschirm gesperrt wird. Normalerweise aus: Sperrst du "
|
||||||
|
"selbst, würde er gleich wieder entsperren."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:290
|
||||||
|
msgid ""
|
||||||
|
"sudo takes your face instead of the password. No match: you type the "
|
||||||
|
"password as usual."
|
||||||
|
msgstr ""
|
||||||
|
"sudo nimmt dein Gesicht statt des Passworts. Passt es nicht, tippst du wie "
|
||||||
|
"gewohnt dein Passwort."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:291
|
||||||
|
msgid ""
|
||||||
|
"The password windows of Plasma and apps, for example when you install "
|
||||||
|
"software. No match: you type the password."
|
||||||
|
msgstr ""
|
||||||
|
"Die Passwort-Fenster von Plasma und Apps, zum Beispiel beim Installieren. "
|
||||||
|
"Passt das Gesicht nicht, tippst du dein Passwort."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:292
|
||||||
|
msgid ""
|
||||||
|
"You have to blink or turn your head a little. This also stops printed photos."
|
||||||
|
msgstr ""
|
||||||
|
"Du musst blinzeln oder den Kopf leicht drehen. Das hält auch ausgedruckte "
|
||||||
|
"Fotos auf."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:293
|
||||||
|
msgid "No check at all. Only for trying out a camera."
|
||||||
|
msgstr "Keine Prüfung. Nur zum Ausprobieren einer Kamera."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:294
|
||||||
|
msgid ""
|
||||||
|
"Stops photos on a phone, a tablet or glossy paper. You do not have to blink. "
|
||||||
|
"A matte printed photo can get through."
|
||||||
|
msgstr ""
|
||||||
|
"Hält Fotos auf Handy, Tablet oder Hochglanzpapier auf. Blinzeln ist nicht "
|
||||||
|
"nötig. Ein matter Ausdruck kann durchkommen."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:295
|
||||||
|
msgid ""
|
||||||
|
"Fewer wrong matches, but it may not know you with glasses or in bad light."
|
||||||
|
msgstr ""
|
||||||
|
"Seltener Verwechslungen, aber mit Brille oder bei schlechtem Licht erkennt "
|
||||||
|
"es dich vielleicht nicht."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:296
|
||||||
|
msgid "Knows you more easily, but also somebody who looks a lot like you."
|
||||||
|
msgstr "Erkennt dich leichter, aber auch jemanden, der dir sehr ähnlich sieht."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:297
|
||||||
|
msgid "The default. Right for most people."
|
||||||
|
msgstr "Der Standard. Passt für die meisten."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:298
|
||||||
|
msgid ""
|
||||||
|
"Your eyes have to be open and on the screen. So it does not unlock while you "
|
||||||
|
"look away or sleep."
|
||||||
|
msgstr ""
|
||||||
|
"Deine Augen müssen offen sein und auf den Bildschirm schauen. So entsperrt "
|
||||||
|
"es nicht, wenn du wegschaust oder schläfst."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:299
|
||||||
|
msgid ""
|
||||||
|
"Automatic takes the first normal camera. After a change, set up your face "
|
||||||
|
"again. An infrared camera needs its light on (linux-enable-ir-emitter)."
|
||||||
|
msgstr ""
|
||||||
|
"Automatisch nimmt die erste normale Kamera. Nach einem Wechsel dein Gesicht "
|
||||||
|
"neu einrichten. Eine Infrarot-Kamera braucht ihr Licht (linux-enable-ir-"
|
||||||
|
"emitter)."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:300
|
||||||
|
msgid "How long the camera looks for your face before it gives up."
|
||||||
|
msgstr "Wie lange die Kamera nach deinem Gesicht sucht, bevor sie aufgibt."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:301
|
||||||
|
msgid ""
|
||||||
|
"After a sure match it keeps how you look now. So a new haircut or glasses "
|
||||||
|
"need no new setup."
|
||||||
|
msgstr ""
|
||||||
|
"Nach einem sicheren Treffer merkt es sich, wie du gerade aussiehst. So musst "
|
||||||
|
"du nach neuer Frisur oder Brille nichts neu einrichten."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:302
|
||||||
|
msgid ""
|
||||||
|
"No scan while the laptop is closed, for example at a desk with an external "
|
||||||
|
"screen."
|
||||||
|
msgstr ""
|
||||||
|
"Kein Scan bei zugeklapptem Laptop, zum Beispiel am Schreibtisch mit externem "
|
||||||
|
"Bildschirm."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:303
|
||||||
|
msgid "The bubble at the top of the screen shows what the camera is doing."
|
||||||
|
msgstr "Die Bubble oben am Bildschirm zeigt, was die Kamera gerade macht."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:304
|
||||||
|
msgid "A small pill with a lock that opens."
|
||||||
|
msgstr "Eine kleine Pille mit einem Schloss, das aufgeht."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:305
|
||||||
|
msgid "An island with a face that looks around, then rings and a tick."
|
||||||
|
msgstr ""
|
||||||
|
"Eine Insel mit einem Gesicht, das sich umschaut, danach Ringe und ein Haken."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:306
|
||||||
|
msgid "How fast the bubble moves."
|
||||||
|
msgstr "Wie schnell sich die Bubble bewegt."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:307
|
||||||
|
msgid "Shows the bubble when sudo or an admin prompt scans your face, too."
|
||||||
|
msgstr ""
|
||||||
|
"Zeigt die Bubble auch, wenn sudo oder eine Admin-Abfrage dein Gesicht scannt."
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:377
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "automatic (%s)"
|
msgid "automatic (%s)"
|
||||||
msgstr "automatisch (%s)"
|
msgstr "automatisch (%s)"
|
||||||
|
|
||||||
#: src/lib/menu.sh:319
|
#: src/lib/menu.sh:387
|
||||||
msgid "(infrared)"
|
msgid "(infrared)"
|
||||||
msgstr "(Infrarot)"
|
msgstr "(Infrarot)"
|
||||||
|
|
||||||
#: src/lib/menu.sh:323
|
#: src/lib/menu.sh:391
|
||||||
msgid "(not connected)"
|
msgid "(not connected)"
|
||||||
msgstr "(nicht angeschlossen)"
|
msgstr "(nicht angeschlossen)"
|
||||||
|
|
||||||
#: src/lib/menu.sh:379 src/lib/menu.sh:542
|
#: src/lib/menu.sh:464 src/lib/menu.sh:648
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr "Einstellungen"
|
msgstr "Einstellungen"
|
||||||
|
|
||||||
#: src/lib/menu.sh:380
|
#: src/lib/menu.sh:465
|
||||||
msgid "Up/Down: select, Space or Right: change, q: back"
|
msgid "↑↓ select ←→ or Space: change q: back"
|
||||||
msgstr "Hoch/Runter: wählen, Leertaste oder Rechts: ändern, q: zurück"
|
msgstr "↑↓ auswählen ←→ oder Leertaste: ändern q: zurück"
|
||||||
|
|
||||||
#: src/lib/menu.sh:381
|
#: src/lib/menu.sh:466
|
||||||
msgid "Settings marked * are for the whole computer and ask for your password."
|
msgid "for all users, asks for your password"
|
||||||
msgstr "Mit * markierte Einstellungen gelten für den ganzen Computer und fragen nach deinem Passwort."
|
msgstr "für alle Nutzer, fragt nach deinem Passwort"
|
||||||
|
|
||||||
#: src/lib/menu.sh:458
|
#: src/lib/menu.sh:561
|
||||||
msgid "Up/Down: select, Space: on/off, r: rename, d: delete, a: add, q: back"
|
msgid "Up/Down: select, Space: on/off, r: rename, d: delete, a: add, q: back"
|
||||||
msgstr "Hoch/Runter: wählen, Leertaste: an/aus, r: umbenennen, d: löschen, a: hinzufügen, q: zurück"
|
msgstr ""
|
||||||
|
"Hoch/Runter: wählen, Leertaste: an/aus, r: umbenennen, d: löschen, a: "
|
||||||
|
"hinzufügen, q: zurück"
|
||||||
|
|
||||||
#: src/lib/menu.sh:459
|
#: src/lib/menu.sh:562
|
||||||
msgid "No face is set up yet. Press a to add one."
|
msgid "No face is set up yet. Press a to add one."
|
||||||
msgstr "Es ist noch kein Gesicht eingerichtet. Drück a, um eins hinzuzufügen."
|
msgstr "Es ist noch kein Gesicht eingerichtet. Drück a, um eins hinzuzufügen."
|
||||||
|
|
||||||
#: src/lib/menu.sh:502
|
#: src/lib/menu.sh:607
|
||||||
msgid "New name:"
|
msgid "New name:"
|
||||||
msgstr "Neuer Name:"
|
msgstr "Neuer Name:"
|
||||||
|
|
||||||
#: src/lib/menu.sh:509
|
#: src/lib/menu.sh:614
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "Delete \"%s\"?"
|
msgid "Delete \"%s\"?"
|
||||||
msgstr "„%s“ löschen?"
|
msgstr "„%s“ löschen?"
|
||||||
|
|
||||||
#: src/lib/menu.sh:539
|
#: src/lib/menu.sh:645
|
||||||
msgid "Turn face unlock on or off"
|
msgid "Turn face unlock on or off"
|
||||||
msgstr "Gesichtsentsperrung ein- oder ausschalten"
|
msgstr "Gesichtsentsperrung ein- oder ausschalten"
|
||||||
|
|
||||||
#: src/lib/menu.sh:543
|
#: src/lib/menu.sh:649
|
||||||
msgid "Try it"
|
msgid "Try it"
|
||||||
msgstr "Ausprobieren"
|
msgstr "Ausprobieren"
|
||||||
|
|
||||||
#: src/lib/menu.sh:544
|
#: src/lib/menu.sh:650
|
||||||
msgid "Quit"
|
msgid "Quit"
|
||||||
msgstr "Beenden"
|
msgstr "Beenden"
|
||||||
|
|
||||||
@@ -499,7 +668,8 @@ msgstr "Auf diesem System gibt es keine PAM-Konfiguration für %s."
|
|||||||
|
|
||||||
#: src/lib/system.sh:47
|
#: src/lib/system.sh:47
|
||||||
msgid "This needs root, and neither sudo, run0 nor doas is installed."
|
msgid "This needs root, and neither sudo, run0 nor doas is installed."
|
||||||
msgstr "Dafür braucht es root, aber weder sudo noch run0 noch doas ist installiert."
|
msgstr ""
|
||||||
|
"Dafür braucht es root, aber weder sudo noch run0 noch doas ist installiert."
|
||||||
|
|
||||||
#: src/lib/system.sh:56
|
#: src/lib/system.sh:56
|
||||||
msgid "This command has to run as root."
|
msgid "This command has to run as root."
|
||||||
@@ -516,86 +686,98 @@ msgid "Not a service this can be used for: %s"
|
|||||||
msgstr "Dafür kann es nicht verwendet werden: %s"
|
msgstr "Dafür kann es nicht verwendet werden: %s"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Unlock the lock screen"
|
msgid "Unlock with your face"
|
||||||
msgstr "Sperrbildschirm entsperren"
|
msgstr "Mit dem Gesicht entsperren"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Look when somebody comes back to the screen"
|
msgid "Scan when you come back"
|
||||||
msgstr "Schauen, wenn jemand zum Bildschirm zurückkommt"
|
msgstr "Scannen, wenn du zurückkommst"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Look right after the screen locks"
|
msgid "Scan right after locking"
|
||||||
msgstr "Gleich nach dem Sperren schauen"
|
msgstr "Gleich nach dem Sperren scannen"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Use for sudo in a terminal"
|
msgid "Password prompts"
|
||||||
msgstr "Für sudo im Terminal verwenden"
|
msgstr "Passwort-Abfragen"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Use for admin prompts"
|
msgid "sudo in a terminal"
|
||||||
msgstr "Für Admin-Abfragen verwenden"
|
msgstr "sudo im Terminal"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "How closely a face has to match"
|
msgid "Recognition"
|
||||||
msgstr "Wie genau ein Gesicht passen muss"
|
msgstr "Erkennung"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Only while looking at the screen"
|
msgid "How closely the face has to match"
|
||||||
msgstr "Nur beim Blick auf den Bildschirm"
|
msgstr "Wie genau das Gesicht passen muss"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "How long one look lasts"
|
msgid "Only when you look at the screen"
|
||||||
msgstr "Wie lange ein Blick dauert"
|
msgstr "Nur wenn du auf den Bildschirm schaust"
|
||||||
|
|
||||||
|
#: src/lib/menu.sh
|
||||||
|
msgid "How long a scan lasts"
|
||||||
|
msgstr "Wie lange ein Scan dauert"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Learn from every unlock"
|
msgid "Learn from every unlock"
|
||||||
msgstr "Bei jeder Entsperrung dazulernen"
|
msgstr "Bei jeder Entsperrung dazulernen"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Not while the lid is closed"
|
msgid "Not when the lid is closed"
|
||||||
msgstr "Nicht bei geschlossenem Deckel"
|
msgstr "Nicht bei zugeklapptem Laptop"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Show the bubble at the top"
|
msgid "Bubble"
|
||||||
msgstr "Die Bubble oben anzeigen"
|
msgstr "Bubble"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Bubble style"
|
msgid "Show the bubble"
|
||||||
msgstr "Bubble-Stil"
|
msgstr "Bubble anzeigen"
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Bubble for sudo and admin prompts too"
|
msgid "Style"
|
||||||
msgstr "Bubble auch für sudo und Admin-Abfragen"
|
msgstr "Stil"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:91
|
#: src/lib/menu.sh
|
||||||
|
msgid "Animation speed"
|
||||||
|
msgstr "Animationsgeschwindigkeit"
|
||||||
|
|
||||||
|
#: src/lib/menu.sh
|
||||||
|
msgid "Also for sudo and admin prompts"
|
||||||
|
msgstr "Auch bei sudo und Admin-Abfragen"
|
||||||
|
|
||||||
|
#: src/agent/bubblecontroller.cpp:98
|
||||||
msgid "Blink once"
|
msgid "Blink once"
|
||||||
msgstr "Einmal blinzeln"
|
msgstr "Einmal blinzeln"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:93
|
#: src/agent/bubblecontroller.cpp:100
|
||||||
msgid "Look at the screen"
|
msgid "Look at the screen"
|
||||||
msgstr "Auf den Bildschirm schauen"
|
msgstr "Auf den Bildschirm schauen"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:95
|
#: src/agent/bubblecontroller.cpp:102
|
||||||
msgid "Move closer"
|
msgid "Move closer"
|
||||||
msgstr "Näher kommen"
|
msgstr "Näher kommen"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:97
|
#: src/agent/bubblecontroller.cpp:104
|
||||||
msgid "Too dark"
|
msgid "Too dark"
|
||||||
msgstr "Zu dunkel"
|
msgstr "Zu dunkel"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:117
|
#: src/agent/bubblecontroller.cpp:124
|
||||||
msgid "Use your password"
|
msgid "Use your password"
|
||||||
msgstr "Nutze dein Passwort"
|
msgstr "Nutze dein Passwort"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:123
|
#: src/agent/bubblecontroller.cpp:130
|
||||||
msgid "Not recognized"
|
msgid "Not recognized"
|
||||||
msgstr "Nicht erkannt"
|
msgstr "Nicht erkannt"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:125
|
#: src/agent/bubblecontroller.cpp:132
|
||||||
msgid "Try again and blink"
|
msgid "Try again and blink"
|
||||||
msgstr "Nochmal, und blinzeln"
|
msgstr "Nochmal, und blinzeln"
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:127
|
#: src/agent/bubblecontroller.cpp:134
|
||||||
msgid "Camera unavailable"
|
msgid "Camera unavailable"
|
||||||
msgstr "Kamera nicht verfügbar"
|
msgstr "Kamera nicht verfügbar"
|
||||||
|
|
||||||
@@ -653,7 +835,8 @@ msgstr "Die Kamera konnte nicht benutzt werden: %1"
|
|||||||
|
|
||||||
#: src/agent/enrollcontroller.cpp:197
|
#: src/agent/enrollcontroller.cpp:197
|
||||||
msgid "The face recognition models are missing. Reinstall the package."
|
msgid "The face recognition models are missing. Reinstall the package."
|
||||||
msgstr "Die Modelle für die Gesichtserkennung fehlen. Installiere das Paket neu."
|
msgstr ""
|
||||||
|
"Die Modelle für die Gesichtserkennung fehlen. Installiere das Paket neu."
|
||||||
|
|
||||||
#: src/agent/enrollcontroller.cpp:199
|
#: src/agent/enrollcontroller.cpp:199
|
||||||
msgid "That took too long. Try again, in good light."
|
msgid "That took too long. Try again, in good light."
|
||||||
@@ -661,11 +844,15 @@ msgstr "Das hat zu lange gedauert. Versuch es nochmal, bei gutem Licht."
|
|||||||
|
|
||||||
#: src/agent/enrollcontroller.cpp:201
|
#: src/agent/enrollcontroller.cpp:201
|
||||||
msgid "The face unlock service is not running. Turn face unlock on first."
|
msgid "The face unlock service is not running. Turn face unlock on first."
|
||||||
msgstr "Der Dienst für die Gesichtsentsperrung läuft nicht. Schalte die Gesichtsentsperrung zuerst ein."
|
msgstr ""
|
||||||
|
"Der Dienst für die Gesichtsentsperrung läuft nicht. Schalte die "
|
||||||
|
"Gesichtsentsperrung zuerst ein."
|
||||||
|
|
||||||
#: src/agent/enrollcontroller.cpp:203
|
#: src/agent/enrollcontroller.cpp:203
|
||||||
msgid "The camera is busy with another scan. Try again in a moment."
|
msgid "The camera is busy with another scan. Try again in a moment."
|
||||||
msgstr "Die Kamera ist gerade mit einem anderen Scan beschäftigt. Versuch es gleich nochmal."
|
msgstr ""
|
||||||
|
"Die Kamera ist gerade mit einem anderen Scan beschäftigt. Versuch es gleich "
|
||||||
|
"nochmal."
|
||||||
|
|
||||||
#: src/agent/enrollcontroller.cpp:205
|
#: src/agent/enrollcontroller.cpp:205
|
||||||
msgid "The face could not be added (%1)."
|
msgid "The face could not be added (%1)."
|
||||||
@@ -701,7 +888,9 @@ msgstr "Blinzle oder dreh den Kopf ein wenig."
|
|||||||
|
|
||||||
#: src/pam/pam_plasma_face_unlock.c:312
|
#: src/pam/pam_plasma_face_unlock.c:312
|
||||||
msgid "Face unlock is paused after too many tries. Use your password."
|
msgid "Face unlock is paused after too many tries. Use your password."
|
||||||
msgstr "Die Gesichtsentsperrung ist nach zu vielen Versuchen pausiert. Nutze dein Passwort."
|
msgstr ""
|
||||||
|
"Die Gesichtsentsperrung ist nach zu vielen Versuchen pausiert. Nutze dein "
|
||||||
|
"Passwort."
|
||||||
|
|
||||||
#: src/pam/pam_plasma_face_unlock.c:316
|
#: src/pam/pam_plasma_face_unlock.c:316
|
||||||
msgid "Face not recognised."
|
msgid "Face not recognised."
|
||||||
@@ -731,47 +920,38 @@ msgstr "Die Einrichtung wurde nicht abgeschlossen"
|
|||||||
msgid ""
|
msgid ""
|
||||||
"Look at the camera, then move your head slowly in a circle. Your face is "
|
"Look at the camera, then move your head slowly in a circle. Your face is "
|
||||||
"turned into numbers on this computer and never stored as a picture."
|
"turned into numbers on this computer and never stored as a picture."
|
||||||
msgstr "Schau in die Kamera und beweg dann den Kopf langsam im Kreis. Dein Gesicht wird auf diesem Computer in Zahlen umgewandelt und nie als Bild gespeichert."
|
msgstr ""
|
||||||
|
"Schau in die Kamera und beweg dann den Kopf langsam im Kreis. Dein Gesicht "
|
||||||
|
"wird auf diesem Computer in Zahlen umgewandelt und nie als Bild gespeichert."
|
||||||
|
|
||||||
#: src/agent/qml/Enroll.qml:123
|
#: src/agent/qml/Enroll.qml:123
|
||||||
msgid ""
|
msgid ""
|
||||||
"Lock the screen and look at it to try it out. You can add a second look, "
|
"Lock the screen and look at it to try it out. You can add a second look, "
|
||||||
"with glasses for example, from the menu."
|
"with glasses for example, from the menu."
|
||||||
msgstr "Sperre den Bildschirm und schau ihn an, um es auszuprobieren. Einen zweiten Look, zum Beispiel mit Brille, kannst du im Menü hinzufügen."
|
msgstr ""
|
||||||
|
"Sperre den Bildschirm und schau ihn an, um es auszuprobieren. Einen zweiten "
|
||||||
|
"Look, zum Beispiel mit Brille, kannst du im Menü hinzufügen."
|
||||||
|
|
||||||
#: src/agent/qml/Enroll.qml:156
|
#: src/agent/qml/Enroll.qml:157
|
||||||
msgid "Name (optional)"
|
msgid "Name (optional)"
|
||||||
msgstr "Name (optional)"
|
msgstr "Name (optional)"
|
||||||
|
|
||||||
#: src/agent/qml/Enroll.qml:171
|
#: src/agent/qml/Enroll.qml:172
|
||||||
msgid "Cancel"
|
msgid "Cancel"
|
||||||
msgstr "Abbrechen"
|
msgstr "Abbrechen"
|
||||||
|
|
||||||
#: src/agent/qml/Enroll.qml:177
|
#: src/agent/qml/Enroll.qml:178
|
||||||
msgid "Finish now"
|
msgid "Finish now"
|
||||||
msgstr "Jetzt abschließen"
|
msgstr "Jetzt abschließen"
|
||||||
|
|
||||||
#: src/agent/qml/Enroll.qml:182
|
#: src/agent/qml/Enroll.qml:183
|
||||||
msgid "Try again"
|
msgid "Try again"
|
||||||
msgstr "Nochmal versuchen"
|
msgstr "Nochmal versuchen"
|
||||||
|
|
||||||
#: src/agent/qml/Enroll.qml:182
|
#: src/agent/qml/Enroll.qml:183
|
||||||
msgid "Get started"
|
msgid "Get started"
|
||||||
msgstr "Los geht's"
|
msgstr "Los geht's"
|
||||||
|
|
||||||
#: src/agent/qml/Enroll.qml:187
|
#: src/agent/qml/Enroll.qml:188
|
||||||
msgid "Done"
|
msgid "Done"
|
||||||
msgstr "Fertig"
|
msgstr "Fertig"
|
||||||
|
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
|
||||||
msgid "Animation speed"
|
|
||||||
msgstr "Animationsgeschwindigkeit"
|
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
|
||||||
msgid "fast"
|
|
||||||
msgstr "schnell"
|
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
|
||||||
msgid "slow"
|
|
||||||
msgstr "langsam"
|
|
||||||
+175
-53
@@ -8,7 +8,7 @@ msgstr ""
|
|||||||
"Project-Id-Version: plasma-face-unlock 1.0.0\n"
|
"Project-Id-Version: plasma-face-unlock 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/"
|
"Report-Msgid-Bugs-To: https://github.com/LoonixTools/plasma-face-unlock/"
|
||||||
"issues\n"
|
"issues\n"
|
||||||
"POT-Creation-Date: 2026-09-22 23:12+0200\n"
|
"POT-Creation-Date: 2026-09-24 01:31+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -55,8 +55,8 @@ msgstr ""
|
|||||||
msgid "First, set up your face."
|
msgid "First, set up your face."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:352
|
#: src/plasma-face-unlock:100 src/plasma-face-unlock:120 src/lib/menu.sh:406
|
||||||
#: src/lib/menu.sh:356 src/lib/menu.sh:362 src/lib/menu.sh:364
|
#: src/lib/menu.sh:410 src/lib/menu.sh:416 src/lib/menu.sh:418
|
||||||
msgid "Could not save the setting."
|
msgid "Could not save the setting."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -84,16 +84,16 @@ msgstr ""
|
|||||||
msgid "No face is set up yet."
|
msgid "No face is set up yet."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:167 src/lib/menu.sh:476
|
#: src/plasma-face-unlock:148 src/lib/menu.sh:167 src/lib/menu.sh:563
|
||||||
msgid "on"
|
msgid "on"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/plasma-face-unlock:148 src/lib/menu.sh:169 src/lib/menu.sh:179
|
#: src/plasma-face-unlock:148 src/lib/menu.sh:169 src/lib/menu.sh:179
|
||||||
#: src/lib/menu.sh:477
|
#: src/lib/menu.sh:564
|
||||||
msgid "off"
|
msgid "off"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/plasma-face-unlock:150 src/lib/menu.sh:494
|
#: src/plasma-face-unlock:150 src/lib/menu.sh:581
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%s samples, %s learned"
|
msgid "%s samples, %s learned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -123,7 +123,7 @@ msgstr ""
|
|||||||
msgid "Turn it off (faces are kept)"
|
msgid "Turn it off (faces are kept)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/plasma-face-unlock:176 src/lib/menu.sh:559
|
#: src/plasma-face-unlock:176 src/lib/menu.sh:646
|
||||||
msgid "Add a face"
|
msgid "Add a face"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -174,17 +174,29 @@ msgstr ""
|
|||||||
msgid "just now"
|
msgid "just now"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/common.sh:173
|
#: src/lib/common.sh:172
|
||||||
|
msgid "1 minute ago"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/common.sh:175
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%d minutes ago"
|
msgid "%d minutes ago"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/common.sh:176
|
#: src/lib/common.sh:177
|
||||||
|
msgid "1 hour ago"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/common.sh:180
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%d hours ago"
|
msgid "%d hours ago"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/common.sh:179
|
#: src/lib/common.sh:182
|
||||||
|
msgid "1 day ago"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/common.sh:185
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "%d days ago"
|
msgid "%d days ago"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -323,30 +335,26 @@ msgstr ""
|
|||||||
msgid "[y/N]"
|
msgid "[y/N]"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:159 src/lib/menu.sh:396
|
#: src/lib/menu.sh:159 src/lib/menu.sh:467
|
||||||
msgid "ON"
|
msgid "ON"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:161 src/lib/menu.sh:397
|
#: src/lib/menu.sh:161 src/lib/menu.sh:468
|
||||||
msgid "OFF"
|
msgid "OFF"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:177
|
#: src/lib/menu.sh:177 src/lib/menu.sh:181
|
||||||
msgid "strict (blink or turn your head)"
|
msgid "strict"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:178
|
#: src/lib/menu.sh:178
|
||||||
msgid "basic (screens and phone edges)"
|
msgid "basic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:180 src/lib/menu.sh:185
|
#: src/lib/menu.sh:180 src/lib/menu.sh:185
|
||||||
msgid "normal"
|
msgid "normal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:181
|
|
||||||
msgid "strict"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/lib/menu.sh:182
|
#: src/lib/menu.sh:182
|
||||||
msgid "relaxed"
|
msgid "relaxed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -372,7 +380,7 @@ msgstr ""
|
|||||||
msgid "%s seconds"
|
msgid "%s seconds"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:189 src/lib/menu.sh:327
|
#: src/lib/menu.sh:189 src/lib/menu.sh:381
|
||||||
msgid "automatic"
|
msgid "automatic"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -392,8 +400,8 @@ msgstr ""
|
|||||||
msgid "Turning face unlock on again starts it."
|
msgid "Turning face unlock on again starts it."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:223 src/lib/menu.sh:225 src/lib/menu.sh:473
|
#: src/lib/menu.sh:223 src/lib/menu.sh:225 src/lib/menu.sh:560
|
||||||
#: src/lib/menu.sh:560
|
#: src/lib/menu.sh:647
|
||||||
msgid "Faces"
|
msgid "Faces"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -409,11 +417,11 @@ msgstr ""
|
|||||||
msgid "none found"
|
msgid "none found"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:233 /tmp/tmp.PgsbSPb4Sv/settings.sh:9
|
#: src/lib/menu.sh:233 /tmp/tmp.3ElRvSMg8S/settings.sh:12
|
||||||
msgid "Camera"
|
msgid "Camera"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:235
|
#: src/lib/menu.sh:235 /tmp/tmp.3ElRvSMg8S/settings.sh:1
|
||||||
msgid "Lock screen"
|
msgid "Lock screen"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -421,11 +429,11 @@ msgstr ""
|
|||||||
msgid "sudo"
|
msgid "sudo"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:237
|
#: src/lib/menu.sh:237 /tmp/tmp.3ElRvSMg8S/settings.sh:7
|
||||||
msgid "Admin prompts"
|
msgid "Admin prompts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:238 /tmp/tmp.PgsbSPb4Sv/settings.sh:6
|
#: src/lib/menu.sh:238 /tmp/tmp.3ElRvSMg8S/settings.sh:9
|
||||||
msgid "Photo check"
|
msgid "Photo check"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -442,57 +450,163 @@ msgstr ""
|
|||||||
msgid "Last unlock"
|
msgid "Last unlock"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:323
|
#: src/lib/menu.sh:287
|
||||||
|
msgid ""
|
||||||
|
"Unlocks the lock screen when it sees your face. Off: only your password "
|
||||||
|
"works there."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:288
|
||||||
|
msgid ""
|
||||||
|
"Scans when you press a key or move the mouse on the lock screen, and when "
|
||||||
|
"the computer wakes up."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:289
|
||||||
|
msgid ""
|
||||||
|
"Scans as soon as the screen locks. Off by default: if you lock it yourself, "
|
||||||
|
"it would unlock again right away."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:290
|
||||||
|
msgid ""
|
||||||
|
"sudo takes your face instead of the password. No match: you type the "
|
||||||
|
"password as usual."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:291
|
||||||
|
msgid ""
|
||||||
|
"The password windows of Plasma and apps, for example when you install "
|
||||||
|
"software. No match: you type the password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:292
|
||||||
|
msgid ""
|
||||||
|
"You have to blink or turn your head a little. This also stops printed photos."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:293
|
||||||
|
msgid "No check at all. Only for trying out a camera."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:294
|
||||||
|
msgid ""
|
||||||
|
"Stops photos on a phone, a tablet or glossy paper. You do not have to blink. "
|
||||||
|
"A matte printed photo can get through."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:295
|
||||||
|
msgid ""
|
||||||
|
"Fewer wrong matches, but it may not know you with glasses or in bad light."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:296
|
||||||
|
msgid "Knows you more easily, but also somebody who looks a lot like you."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:297
|
||||||
|
msgid "The default. Right for most people."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:298
|
||||||
|
msgid ""
|
||||||
|
"Your eyes have to be open and on the screen. So it does not unlock while you "
|
||||||
|
"look away or sleep."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:299
|
||||||
|
msgid ""
|
||||||
|
"Automatic takes the first normal camera. After a change, set up your face "
|
||||||
|
"again. An infrared camera needs its light on (linux-enable-ir-emitter)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:300
|
||||||
|
msgid "How long the camera looks for your face before it gives up."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:301
|
||||||
|
msgid ""
|
||||||
|
"After a sure match it keeps how you look now. So a new haircut or glasses "
|
||||||
|
"need no new setup."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:302
|
||||||
|
msgid ""
|
||||||
|
"No scan while the laptop is closed, for example at a desk with an external "
|
||||||
|
"screen."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:303
|
||||||
|
msgid "The bubble at the top of the screen shows what the camera is doing."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:304
|
||||||
|
msgid "A small pill with a lock that opens."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:305
|
||||||
|
msgid "An island with a face that looks around, then rings and a tick."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:306
|
||||||
|
msgid "How fast the bubble moves."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:307
|
||||||
|
msgid "Shows the bubble when sudo or an admin prompt scans your face, too."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh:377
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "automatic (%s)"
|
msgid "automatic (%s)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:333
|
#: src/lib/menu.sh:387
|
||||||
msgid "(infrared)"
|
msgid "(infrared)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:337
|
#: src/lib/menu.sh:391
|
||||||
msgid "(not connected)"
|
msgid "(not connected)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:393 src/lib/menu.sh:561
|
#: src/lib/menu.sh:464 src/lib/menu.sh:648
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:394
|
#: src/lib/menu.sh:465
|
||||||
msgid "Up/Down: select, Space or Right: change, q: back"
|
msgid "↑↓ select ←→ or Space: change q: back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:395
|
#: src/lib/menu.sh:466
|
||||||
msgid "Settings marked * are for the whole computer and ask for your password."
|
msgid "for all users, asks for your password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:474
|
#: src/lib/menu.sh:561
|
||||||
msgid "Up/Down: select, Space: on/off, r: rename, d: delete, a: add, q: back"
|
msgid "Up/Down: select, Space: on/off, r: rename, d: delete, a: add, q: back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:475
|
#: src/lib/menu.sh:562
|
||||||
msgid "No face is set up yet. Press a to add one."
|
msgid "No face is set up yet. Press a to add one."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:520
|
#: src/lib/menu.sh:607
|
||||||
msgid "New name:"
|
msgid "New name:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:527
|
#: src/lib/menu.sh:614
|
||||||
#, sh-printf-format
|
#, sh-printf-format
|
||||||
msgid "Delete \"%s\"?"
|
msgid "Delete \"%s\"?"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:558
|
#: src/lib/menu.sh:645
|
||||||
msgid "Turn face unlock on or off"
|
msgid "Turn face unlock on or off"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:562
|
#: src/lib/menu.sh:649
|
||||||
msgid "Try it"
|
msgid "Try it"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh:563
|
#: src/lib/menu.sh:650
|
||||||
msgid "Quit"
|
msgid "Quit"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -525,35 +639,39 @@ msgid "Not a service this can be used for: %s"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Unlock the lock screen"
|
msgid "Unlock with your face"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Look when somebody comes back to the screen"
|
msgid "Scan when you come back"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Look right after the screen locks"
|
msgid "Scan right after locking"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Use for sudo in a terminal"
|
msgid "Password prompts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Use for admin prompts"
|
msgid "sudo in a terminal"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "How closely a face has to match"
|
msgid "Recognition"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Only while looking at the screen"
|
msgid "How closely the face has to match"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "How long one look lasts"
|
msgid "Only when you look at the screen"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh
|
||||||
|
msgid "How long a scan lasts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
@@ -561,15 +679,19 @@ msgid "Learn from every unlock"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Not while the lid is closed"
|
msgid "Not when the lid is closed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Show the bubble at the top"
|
msgid "Bubble"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Bubble style"
|
msgid "Show the bubble"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/lib/menu.sh
|
||||||
|
msgid "Style"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
@@ -577,7 +699,7 @@ msgid "Animation speed"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/lib/menu.sh
|
#: src/lib/menu.sh
|
||||||
msgid "Bubble for sudo and admin prompts too"
|
msgid "Also for sudo and admin prompts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: src/agent/bubblecontroller.cpp:98
|
#: src/agent/bubblecontroller.cpp:98
|
||||||
|
|||||||
+5
-3
@@ -5,8 +5,9 @@
|
|||||||
# the shell code (pfu_msg), the agent (i18n in C++ and QML) and the PAM module
|
# the shell code (pfu_msg), the agent (i18n in C++ and QML) and the PAM module
|
||||||
# (dgettext), so a word is translated once wherever it shows up.
|
# (dgettext), so a word is translated once wherever it shows up.
|
||||||
#
|
#
|
||||||
# The settings labels live in an array in menu.sh and reach gettext at run
|
# The settings labels and headings live in an array in menu.sh and reach
|
||||||
# time, so xgettext cannot see them; they are pulled out here first.
|
# gettext at run time, so xgettext cannot see them; they are pulled out here
|
||||||
|
# first.
|
||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
@@ -17,7 +18,8 @@ trap 'rm -rf -- "$tmp"' EXIT
|
|||||||
version="$(make -s version)"
|
version="$(make -s version)"
|
||||||
|
|
||||||
# The labels, as calls xgettext understands, pointing back at menu.sh.
|
# The labels, as calls xgettext understands, pointing back at menu.sh.
|
||||||
awk -F'|' '/^\t"(user|sys|pam)\|/ { sub(/"$/, "", $5); print "pfu_msg \"" $5 "\"" }' src/lib/menu.sh > "$tmp/settings.sh"
|
awk -F'|' '/^\t"(user|sys|pam)\|/ { sub(/"$/, "", $5); print "pfu_msg \"" $5 "\"" }
|
||||||
|
/^\t"group\|/ { sub(/"$/, "", $2); print "pfu_msg \"" $2 "\"" }' src/lib/menu.sh > "$tmp/settings.sh"
|
||||||
|
|
||||||
common=(--from-code=UTF-8 --add-comments=TRANSLATORS --package-name=plasma-face-unlock --package-version="$version"
|
common=(--from-code=UTF-8 --add-comments=TRANSLATORS --package-name=plasma-face-unlock --package-version="$version"
|
||||||
--msgid-bugs-address=https://github.com/LoonixTools/plasma-face-unlock/issues)
|
--msgid-bugs-address=https://github.com/LoonixTools/plasma-face-unlock/issues)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 223 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 111 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 275 KiB After Width: | Height: | Size: 2.3 MiB |
@@ -10,10 +10,10 @@
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
// How long a result stays up before the bubble closes: long enough to read
|
// How long a result stays up before the bubble closes: long enough to read,
|
||||||
// (on success after the face has resolved, about a second), short enough not
|
// short enough not to be in the way. On success the tick is drawn after
|
||||||
// to be in the way.
|
// about 730 ms and only gets a short moment on its own.
|
||||||
constexpr int SuccessHoldMs = 1500;
|
constexpr int SuccessHoldMs = 1100;
|
||||||
constexpr int FailureHoldMs = 1700;
|
constexpr int FailureHoldMs = 1700;
|
||||||
constexpr int LockoutHoldMs = 3000;
|
constexpr int LockoutHoldMs = 3000;
|
||||||
// A scan that never reports back (the daemon went away half way) must not
|
// A scan that never reports back (the daemon went away half way) must not
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ constexpr int GraceAfterLockMs = 1500;
|
|||||||
// person has kept still for this long and then touched something again. That
|
// person has kept still for this long and then touched something again. That
|
||||||
// way typing the password does not start a scan with every key.
|
// way typing the password does not start a scan with every key.
|
||||||
constexpr int CalmBeforeRetryMs = 2000;
|
constexpr int CalmBeforeRetryMs = 2000;
|
||||||
// Show the tick before the screen goes: long enough to see, short enough
|
|
||||||
// not to feel like waiting.
|
|
||||||
constexpr int UnlockAfterSuccessMs = 450;
|
|
||||||
// A camera needs a moment after the machine wakes before it delivers frames.
|
// A camera needs a moment after the machine wakes before it delivers frames.
|
||||||
constexpr int ScanAfterWakeMs = 1000;
|
constexpr int ScanAfterWakeMs = 1000;
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -188,8 +185,11 @@ void LockController::onScanFinished(const QJsonObject &result)
|
|||||||
|
|
||||||
const QString reason = result.value(u"reason").toString();
|
const QString reason = result.value(u"reason").toString();
|
||||||
if (result.value(u"ok").toBool()) {
|
if (result.value(u"ok").toBool()) {
|
||||||
|
// Straight away, the way a phone does it: the lock screen takes a
|
||||||
|
// moment to go, and the bubble stays above the desktop, so the rings
|
||||||
|
// and the tick play on over it.
|
||||||
m_bubble->succeeded();
|
m_bubble->succeeded();
|
||||||
QTimer::singleShot(int(UnlockAfterSuccessMs * m_config->pace()), this, &LockController::unlock);
|
unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,9 @@ void UserConfig::load()
|
|||||||
m_bubbleStyle = kv.value(QStringLiteral("BubbleStyle"), QStringLiteral("full")) == u"minimal" ? QStringLiteral("minimal") : QStringLiteral("full");
|
m_bubbleStyle = kv.value(QStringLiteral("BubbleStyle"), QStringLiteral("full")) == u"minimal" ? QStringLiteral("minimal") : QStringLiteral("full");
|
||||||
m_bubbleForPrompts = kv.boolean(QStringLiteral("BubbleForPrompts"), true);
|
m_bubbleForPrompts = kv.boolean(QStringLiteral("BubbleForPrompts"), true);
|
||||||
const QString speed = kv.value(QStringLiteral("AnimationSpeed"), QStringLiteral("normal"));
|
const QString speed = kv.value(QStringLiteral("AnimationSpeed"), QStringLiteral("normal"));
|
||||||
m_pace = speed == u"fast" ? 0.6 : speed == u"slow" ? 1.5 : 1.0;
|
// The durations in the code are brisk, like on a phone. On a big screen
|
||||||
|
// they read better a little longer, so normal stretches them.
|
||||||
|
m_pace = speed == u"fast" ? 1.0 : speed == u"slow" ? 2.0 : 1.3;
|
||||||
|
|
||||||
if (QFileInfo::exists(path()) && !m_watcher.files().contains(path())) {
|
if (QFileInfo::exists(path()) && !m_watcher.files().contains(path())) {
|
||||||
m_watcher.addPath(path());
|
m_watcher.addPath(path());
|
||||||
|
|||||||
@@ -55,8 +55,9 @@ public:
|
|||||||
{
|
{
|
||||||
return m_bubbleForPrompts;
|
return m_bubbleForPrompts;
|
||||||
}
|
}
|
||||||
// How long the bubble's animations take, as a multiple of normal: the
|
// How long the bubble's animations take, as a multiple of the durations
|
||||||
// animation speed setting (fast 0.6, normal 1, slow 1.5).
|
// in the code: the animation speed setting (fast 1, normal 1.3,
|
||||||
|
// slow 2).
|
||||||
qreal pace() const
|
qreal pace() const
|
||||||
{
|
{
|
||||||
return m_pace;
|
return m_pace;
|
||||||
@@ -77,6 +78,6 @@ private:
|
|||||||
bool m_bubble = true;
|
bool m_bubble = true;
|
||||||
QString m_bubbleStyle = QStringLiteral("full");
|
QString m_bubbleStyle = QStringLiteral("full");
|
||||||
bool m_bubbleForPrompts = true;
|
bool m_bubbleForPrompts = true;
|
||||||
qreal m_pace = 1;
|
qreal m_pace = 1.3;
|
||||||
QString m_styleOverride;
|
QString m_styleOverride;
|
||||||
};
|
};
|
||||||
@@ -37,6 +37,21 @@ QString sysName(const QString &device)
|
|||||||
return QString::fromUtf8(file.readAll()).trimmed();
|
return QString::fromUtf8(file.readAll()).trimmed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UVC names a node "<device>: <function>", often twice the same or with the
|
||||||
|
// second cut short ("HP HD Camera: HP HD Camera"). The function tells a
|
||||||
|
// laptop's two cameras apart ("HP HD Camera: HP IR Camera"), so that part is
|
||||||
|
// kept unless it only repeats the first.
|
||||||
|
QString shortName(const QString &name)
|
||||||
|
{
|
||||||
|
const qsizetype colon = name.indexOf(u": ");
|
||||||
|
if (colon < 0) {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
const QString device = name.left(colon);
|
||||||
|
const QString function = name.mid(colon + 2).trimmed();
|
||||||
|
return function.isEmpty() || device.startsWith(function) ? device : function;
|
||||||
|
}
|
||||||
|
|
||||||
// Opens the node just long enough to ask what it is. Neither this nor the
|
// Opens the node just long enough to ask what it is. Neither this nor the
|
||||||
// format list below starts streaming, so it does not switch the light on.
|
// format list below starts streaming, so it does not switch the light on.
|
||||||
bool probe(const QString &path, CameraInfo *info)
|
bool probe(const QString &path, CameraInfo *info)
|
||||||
@@ -85,6 +100,7 @@ bool probe(const QString &path, CameraInfo *info)
|
|||||||
if (info->name.isEmpty()) {
|
if (info->name.isEmpty()) {
|
||||||
info->name = QString::fromUtf8(reinterpret_cast<const char *>(cap.card));
|
info->name = QString::fromUtf8(reinterpret_cast<const char *>(cap.card));
|
||||||
}
|
}
|
||||||
|
info->name = shortName(info->name);
|
||||||
info->infrared = grey && !colour;
|
info->infrared = grey && !colour;
|
||||||
}
|
}
|
||||||
return ok;
|
return ok;
|
||||||
|
|||||||
+3
-1
@@ -30,7 +30,9 @@ struct Settings {
|
|||||||
// A /dev/video path, "auto", or for testing "file:<video>" and
|
// A /dev/video path, "auto", or for testing "file:<video>" and
|
||||||
// "images:<directory>".
|
// "images:<directory>".
|
||||||
QString camera = QStringLiteral("auto");
|
QString camera = QStringLiteral("auto");
|
||||||
LivenessMode liveness = LivenessMode::Heavy;
|
// Basic by default: screens and phones are caught without asking for a
|
||||||
|
// blink. Strict adds the blink or head turn that stops a printed photo.
|
||||||
|
LivenessMode liveness = LivenessMode::Light;
|
||||||
Strictness strictness = Strictness::Normal;
|
Strictness strictness = Strictness::Normal;
|
||||||
// Only a face that looks at the screen with its eyes open counts.
|
// Only a face that looks at the screen with its eyes open counts.
|
||||||
bool attention = true;
|
bool attention = true;
|
||||||
|
|||||||
@@ -168,12 +168,18 @@ pfu_time_ago() {
|
|||||||
|
|
||||||
if [[ $delta -lt 60 ]]; then
|
if [[ $delta -lt 60 ]]; then
|
||||||
pfu_msg "just now"
|
pfu_msg "just now"
|
||||||
|
elif [[ $delta -lt 120 ]]; then
|
||||||
|
pfu_msg "1 minute ago"
|
||||||
elif [[ $delta -lt 3600 ]]; then
|
elif [[ $delta -lt 3600 ]]; then
|
||||||
n=$(( delta / 60 ))
|
n=$(( delta / 60 ))
|
||||||
pfu_msg "%d minutes ago" "$n"
|
pfu_msg "%d minutes ago" "$n"
|
||||||
|
elif [[ $delta -lt 7200 ]]; then
|
||||||
|
pfu_msg "1 hour ago"
|
||||||
elif [[ $delta -lt 86400 ]]; then
|
elif [[ $delta -lt 86400 ]]; then
|
||||||
n=$(( delta / 3600 ))
|
n=$(( delta / 3600 ))
|
||||||
pfu_msg "%d hours ago" "$n"
|
pfu_msg "%d hours ago" "$n"
|
||||||
|
elif [[ $delta -lt 172800 ]]; then
|
||||||
|
pfu_msg "1 day ago"
|
||||||
else
|
else
|
||||||
n=$(( delta / 86400 ))
|
n=$(( delta / 86400 ))
|
||||||
pfu_msg "%d days ago" "$n"
|
pfu_msg "%d days ago" "$n"
|
||||||
|
|||||||
+1
-1
@@ -126,7 +126,7 @@ pfu_config_load() {
|
|||||||
_pfu_kv_lookup "$PFU_CONFIG" Sudo no; CFG_SUDO=no; pfu_is_true "$PFU_KV_VALUE" && CFG_SUDO=yes
|
_pfu_kv_lookup "$PFU_CONFIG" Sudo no; CFG_SUDO=no; pfu_is_true "$PFU_KV_VALUE" && CFG_SUDO=yes
|
||||||
_pfu_kv_lookup "$PFU_CONFIG" Polkit no; CFG_POLKIT=no; pfu_is_true "$PFU_KV_VALUE" && CFG_POLKIT=yes
|
_pfu_kv_lookup "$PFU_CONFIG" Polkit no; CFG_POLKIT=no; pfu_is_true "$PFU_KV_VALUE" && CFG_POLKIT=yes
|
||||||
|
|
||||||
_pfu_kv_lookup "$PFU_SYSCONFIG" Liveness heavy; CFG_LIVENESS="$PFU_KV_VALUE"
|
_pfu_kv_lookup "$PFU_SYSCONFIG" Liveness light; CFG_LIVENESS="$PFU_KV_VALUE"
|
||||||
_pfu_kv_lookup "$PFU_SYSCONFIG" Camera auto; CFG_CAMERA="$PFU_KV_VALUE"
|
_pfu_kv_lookup "$PFU_SYSCONFIG" Camera auto; CFG_CAMERA="$PFU_KV_VALUE"
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
+162
-75
@@ -174,8 +174,8 @@ _pfu_small_onoff() {
|
|||||||
# How a setting's value reads in the menu.
|
# How a setting's value reads in the menu.
|
||||||
pfu_value_label() {
|
pfu_value_label() {
|
||||||
case "$1:$2" in
|
case "$1:$2" in
|
||||||
Liveness:heavy) pfu_msg "strict (blink or turn your head)" ;;
|
Liveness:heavy) pfu_msg "strict" ;;
|
||||||
Liveness:light) pfu_msg "basic (screens and phone edges)" ;;
|
Liveness:light) pfu_msg "basic" ;;
|
||||||
Liveness:off) pfu_msg "off" ;;
|
Liveness:off) pfu_msg "off" ;;
|
||||||
Strictness:normal) pfu_msg "normal" ;;
|
Strictness:normal) pfu_msg "normal" ;;
|
||||||
Strictness:strict) pfu_msg "strict" ;;
|
Strictness:strict) pfu_msg "strict" ;;
|
||||||
@@ -250,29 +250,85 @@ pfu_ui_status() {
|
|||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Settings
|
# Settings
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Format: scope|Key|type|default|label-msgid|choices
|
# Format: scope|Key|type|default|label-msgid|choices|needs
|
||||||
# scope user (this user's file), sys (the system file, through sudo) or
|
# scope user (this user's file), sys (the system file, through sudo),
|
||||||
# pam (the service of that name, through sudo)
|
# pam (the service of that name, through sudo), or group for a
|
||||||
# type bool, choice (cycles through the choices) or camera
|
# heading, with only the label after it
|
||||||
|
# type bool, choice (steps through the choices) or camera
|
||||||
|
# needs a bool setting this one does nothing without; it is dimmed while
|
||||||
|
# that is off
|
||||||
PFU_SETTINGS=(
|
PFU_SETTINGS=(
|
||||||
"user|LockScreen|bool|yes|Unlock the lock screen"
|
"group|Lock screen"
|
||||||
"user|ScanOnWake|bool|yes|Look when somebody comes back to the screen"
|
"user|LockScreen|bool|yes|Unlock with your face"
|
||||||
"user|ScanOnLock|bool|no|Look right after the screen locks"
|
"user|ScanOnWake|bool|yes|Scan when you come back||LockScreen"
|
||||||
"pam|sudo|bool|no|Use for sudo in a terminal"
|
"user|ScanOnLock|bool|no|Scan right after locking||LockScreen"
|
||||||
"pam|polkit-1|bool|no|Use for admin prompts"
|
"group|Password prompts"
|
||||||
"sys|Liveness|choice|heavy|Photo check|heavy,light,off"
|
"pam|sudo|bool|no|sudo in a terminal"
|
||||||
"sys|Strictness|choice|normal|How closely a face has to match|normal,strict,relaxed"
|
"pam|polkit-1|bool|no|Admin prompts"
|
||||||
"sys|Attention|bool|yes|Only while looking at the screen"
|
"group|Recognition"
|
||||||
|
"sys|Liveness|choice|light|Photo check|off,light,heavy"
|
||||||
|
"sys|Strictness|choice|normal|How closely the face has to match|relaxed,normal,strict"
|
||||||
|
"sys|Attention|bool|yes|Only when you look at the screen"
|
||||||
"sys|Camera|camera|auto|Camera"
|
"sys|Camera|camera|auto|Camera"
|
||||||
"sys|ScanSeconds|choice|5|How long one look lasts|3,4,5,6,8,10"
|
"sys|ScanSeconds|choice|5|How long a scan lasts|3,4,5,6,8,10"
|
||||||
"sys|Adapt|bool|yes|Learn from every unlock"
|
"sys|Adapt|bool|yes|Learn from every unlock"
|
||||||
"sys|SkipLidClosed|bool|yes|Not while the lid is closed"
|
"sys|SkipLidClosed|bool|yes|Not when the lid is closed"
|
||||||
"user|Bubble|bool|yes|Show the bubble at the top"
|
"group|Bubble"
|
||||||
"user|BubbleStyle|choice|full|Bubble style|full,minimal"
|
"user|Bubble|bool|yes|Show the bubble"
|
||||||
"user|AnimationSpeed|choice|normal|Animation speed|normal,fast,slow"
|
"user|BubbleStyle|choice|full|Style|full,minimal|Bubble"
|
||||||
"user|BubbleForPrompts|bool|yes|Bubble for sudo and admin prompts too"
|
"user|AnimationSpeed|choice|normal|Animation speed|slow,normal,fast|Bubble"
|
||||||
|
"user|BubbleForPrompts|bool|yes|Also for sudo and admin prompts||Bubble"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# pfu_setting_help <Key> <value>
|
||||||
|
# What a setting does, shown under the list for the selected one.
|
||||||
|
pfu_setting_help() {
|
||||||
|
case "$1:$2" in
|
||||||
|
LockScreen:*) pfu_msg "Unlocks the lock screen when it sees your face. Off: only your password works there." ;;
|
||||||
|
ScanOnWake:*) pfu_msg "Scans when you press a key or move the mouse on the lock screen, and when the computer wakes up." ;;
|
||||||
|
ScanOnLock:*) pfu_msg "Scans as soon as the screen locks. Off by default: if you lock it yourself, it would unlock again right away." ;;
|
||||||
|
sudo:*) pfu_msg "sudo takes your face instead of the password. No match: you type the password as usual." ;;
|
||||||
|
polkit-1:*) pfu_msg "The password windows of Plasma and apps, for example when you install software. No match: you type the password." ;;
|
||||||
|
Liveness:heavy) pfu_msg "You have to blink or turn your head a little. This also stops printed photos." ;;
|
||||||
|
Liveness:off) pfu_msg "No check at all. Only for trying out a camera." ;;
|
||||||
|
Liveness:*) pfu_msg "Stops photos on a phone, a tablet or glossy paper. You do not have to blink. A matte printed photo can get through." ;;
|
||||||
|
Strictness:strict) pfu_msg "Fewer wrong matches, but it may not know you with glasses or in bad light." ;;
|
||||||
|
Strictness:relaxed) pfu_msg "Knows you more easily, but also somebody who looks a lot like you." ;;
|
||||||
|
Strictness:*) pfu_msg "The default. Right for most people." ;;
|
||||||
|
Attention:*) pfu_msg "Your eyes have to be open and on the screen. So it does not unlock while you look away or sleep." ;;
|
||||||
|
Camera:*) pfu_msg "Automatic takes the first normal camera. After a change, set up your face again. An infrared camera needs its light on (linux-enable-ir-emitter)." ;;
|
||||||
|
ScanSeconds:*) pfu_msg "How long the camera looks for your face before it gives up." ;;
|
||||||
|
Adapt:*) pfu_msg "After a sure match it keeps how you look now. So a new haircut or glasses need no new setup." ;;
|
||||||
|
SkipLidClosed:*) pfu_msg "No scan while the laptop is closed, for example at a desk with an external screen." ;;
|
||||||
|
Bubble:*) pfu_msg "The bubble at the top of the screen shows what the camera is doing." ;;
|
||||||
|
BubbleStyle:minimal) pfu_msg "A small pill with a lock that opens." ;;
|
||||||
|
BubbleStyle:*) pfu_msg "An island with a face that looks around, then rings and a tick." ;;
|
||||||
|
AnimationSpeed:*) pfu_msg "How fast the bubble moves." ;;
|
||||||
|
BubbleForPrompts:*) pfu_msg "Shows the bubble when sudo or an admin prompt scans your face, too." ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# _pfu_wrap <width> <text>
|
||||||
|
# Word wrap, into PFU_WRAP_LINES.
|
||||||
|
PFU_WRAP_LINES=()
|
||||||
|
|
||||||
|
_pfu_wrap() {
|
||||||
|
local width="$1" word line=''
|
||||||
|
local -a words
|
||||||
|
PFU_WRAP_LINES=()
|
||||||
|
read -r -a words <<< "$2"
|
||||||
|
for word in "${words[@]}"; do
|
||||||
|
if [[ -n $line ]] && (( ${#line} + 1 + ${#word} > width )); then
|
||||||
|
PFU_WRAP_LINES+=("$line")
|
||||||
|
line="$word"
|
||||||
|
else
|
||||||
|
line="${line:+$line }$word"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
[[ -n $line ]] && PFU_WRAP_LINES+=("$line")
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
# _pfu_setting_value <scope> <Key> <default>
|
# _pfu_setting_value <scope> <Key> <default>
|
||||||
# The current value, in PFU_SETTING_VALUE.
|
# The current value, in PFU_SETTING_VALUE.
|
||||||
PFU_SETTING_VALUE=''
|
PFU_SETTING_VALUE=''
|
||||||
@@ -285,34 +341,32 @@ _pfu_setting_value() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# _pfu_next_choice <current> <a,b,c>
|
# _pfu_step <current> <step> <choice>...
|
||||||
_pfu_next_choice() {
|
# The choice <step> (1 or -1) away from the current one, round at the ends.
|
||||||
local current="$1" list="$2" first='' found=0 c
|
_pfu_step() {
|
||||||
local -a choices
|
local current="$1" step="$2" i
|
||||||
IFS=',' read -r -a choices <<< "$list"
|
shift 2
|
||||||
for c in "${choices[@]}"; do
|
local -a all=("$@")
|
||||||
[[ -z $first ]] && first="$c"
|
|
||||||
if (( found )); then
|
|
||||||
printf '%s\n' "$c"
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
[[ $c == "$current" ]] && found=1
|
|
||||||
done
|
|
||||||
printf '%s\n' "$first"
|
|
||||||
}
|
|
||||||
|
|
||||||
# _pfu_next_camera <current>
|
|
||||||
_pfu_next_camera() {
|
|
||||||
local current="$1" i
|
|
||||||
pfu_cameras_load
|
|
||||||
local -a all=(auto "${PFU_CAM_PATHS[@]}")
|
|
||||||
for i in "${!all[@]}"; do
|
for i in "${!all[@]}"; do
|
||||||
if [[ ${all[i]} == "$current" ]]; then
|
if [[ ${all[i]} == "$current" ]]; then
|
||||||
printf '%s\n' "${all[(i + 1) % ${#all[@]}]}"
|
printf '%s\n' "${all[(i + step + ${#all[@]}) % ${#all[@]}]}"
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
printf 'auto\n'
|
printf '%s\n' "${all[0]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# _pfu_next_choice <current> <a,b,c> <step>
|
||||||
|
_pfu_next_choice() {
|
||||||
|
local -a choices
|
||||||
|
IFS=',' read -r -a choices <<< "$2"
|
||||||
|
_pfu_step "$1" "$3" "${choices[@]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# _pfu_next_camera <current> <step>
|
||||||
|
_pfu_next_camera() {
|
||||||
|
pfu_cameras_load
|
||||||
|
_pfu_step "$1" "$2" auto "${PFU_CAM_PATHS[@]}"
|
||||||
}
|
}
|
||||||
|
|
||||||
_pfu_camera_label() {
|
_pfu_camera_label() {
|
||||||
@@ -337,14 +391,14 @@ _pfu_camera_label() {
|
|||||||
printf '%s %s' "$value" "$(pfu_msg "(not connected)")"
|
printf '%s %s' "$value" "$(pfu_msg "(not connected)")"
|
||||||
}
|
}
|
||||||
|
|
||||||
# _pfu_setting_change <scope> <Key> <type> <current> <choices>
|
# _pfu_setting_change <scope> <Key> <type> <current> <choices> <step>
|
||||||
_pfu_setting_change() {
|
_pfu_setting_change() {
|
||||||
local scope="$1" key="$2" type="$3" current="$4" choices="$5" next
|
local scope="$1" key="$2" type="$3" current="$4" choices="$5" step="$6" next
|
||||||
|
|
||||||
case "$type" in
|
case "$type" in
|
||||||
bool) if pfu_is_true "$current"; then next=no; else next=yes; fi ;;
|
bool) if pfu_is_true "$current"; then next=no; else next=yes; fi ;;
|
||||||
choice) next="$(_pfu_next_choice "$current" "$choices")" ;;
|
choice) next="$(_pfu_next_choice "$current" "$choices" "$step")" ;;
|
||||||
camera) next="$(_pfu_next_camera "$current")" ;;
|
camera) next="$(_pfu_next_camera "$current" "$step")" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
case "$scope" in
|
case "$scope" in
|
||||||
@@ -374,25 +428,42 @@ _pfu_setting_change() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# pfu_ui_settings
|
# pfu_ui_settings
|
||||||
# A cursor list rather than a numbered menu. The frame is assembled in memory
|
# A cursor list in groups, with what the selected setting does under it. The
|
||||||
# and written once, and everything constant is resolved before the loop.
|
# frame is assembled in memory and written once, and everything constant is
|
||||||
|
# resolved before the loop.
|
||||||
pfu_ui_settings() {
|
pfu_ui_settings() {
|
||||||
local count=${#PFU_SETTINGS[@]}
|
local -a scopes=() keys=() types=() defaults=() labels=() choices=() needs=() values=() rows=()
|
||||||
local -a scopes=() keys=() types=() defaults=() labels=() choices=() values=()
|
local spec scope key type default label choice need locale i j frame row pad dirty=1 cursor=0 shown
|
||||||
local spec scope key type default label choice locale i frame row pad dirty=1 cursor=0 shown
|
local width=0 wrap cols
|
||||||
|
|
||||||
locale="$(pfu_ui_locale)"
|
locale="$(pfu_ui_locale)"
|
||||||
for spec in "${PFU_SETTINGS[@]}"; do
|
for spec in "${PFU_SETTINGS[@]}"; do
|
||||||
IFS='|' read -r scope key type default label choice <<< "$spec"
|
IFS='|' read -r scope key type default label choice need <<< "$spec"
|
||||||
scopes+=("$scope"); keys+=("$key"); types+=("$type"); defaults+=("$default"); choices+=("$choice")
|
# A heading has its label where the key would be.
|
||||||
|
[[ $scope == group ]] && label="$key" key=''
|
||||||
|
scopes+=("$scope"); keys+=("$key"); types+=("$type"); defaults+=("$default")
|
||||||
|
choices+=("$choice"); needs+=("$need")
|
||||||
pfu_msg_into "$locale" "$label"
|
pfu_msg_into "$locale" "$label"
|
||||||
labels+=("$PFU_MSG_RESULT")
|
labels+=("$PFU_MSG_RESULT")
|
||||||
|
if [[ $scope != group ]]; then
|
||||||
|
rows+=($(( ${#keys[@]} - 1 )))
|
||||||
|
(( ${#PFU_MSG_RESULT} > width )) && width=${#PFU_MSG_RESULT}
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
local count=${#rows[@]}
|
||||||
|
|
||||||
local title hint legend l_on l_off
|
cols="$(tput cols 2>/dev/null)" || cols=80
|
||||||
|
[[ $cols =~ ^[0-9]+$ ]] || cols=80
|
||||||
|
wrap=$(( cols - 4 ))
|
||||||
|
(( wrap > 72 )) && wrap=72
|
||||||
|
local rule
|
||||||
|
printf -v rule '%*s' "$wrap" ''
|
||||||
|
rule="${rule// /─}"
|
||||||
|
|
||||||
|
local title hint shared l_on l_off
|
||||||
pfu_msg_into "$locale" "Settings"; title="$PFU_MSG_RESULT"
|
pfu_msg_into "$locale" "Settings"; title="$PFU_MSG_RESULT"
|
||||||
pfu_msg_into "$locale" "Up/Down: select, Space or Right: change, q: back"; hint="$PFU_MSG_RESULT"
|
pfu_msg_into "$locale" "↑↓ select ←→ or Space: change q: back"; hint="$PFU_MSG_RESULT"
|
||||||
pfu_msg_into "$locale" "Settings marked * are for the whole computer and ask for your password."; legend="$PFU_MSG_RESULT"
|
pfu_msg_into "$locale" "for all users, asks for your password"; shared="$PFU_MSG_RESULT"
|
||||||
pfu_msg_into "$locale" "ON"; l_on="$PFU_MSG_RESULT"
|
pfu_msg_into "$locale" "ON"; l_on="$PFU_MSG_RESULT"
|
||||||
pfu_msg_into "$locale" "OFF"; l_off="$PFU_MSG_RESULT"
|
pfu_msg_into "$locale" "OFF"; l_off="$PFU_MSG_RESULT"
|
||||||
|
|
||||||
@@ -404,17 +475,26 @@ pfu_ui_settings() {
|
|||||||
while true; do
|
while true; do
|
||||||
if (( dirty )); then
|
if (( dirty )); then
|
||||||
PFU_KV_CACHE=()
|
PFU_KV_CACHE=()
|
||||||
for i in "${!keys[@]}"; do
|
declare -A current=()
|
||||||
|
for i in "${rows[@]}"; do
|
||||||
_pfu_setting_value "${scopes[i]}" "${keys[i]}" "${defaults[i]}"
|
_pfu_setting_value "${scopes[i]}" "${keys[i]}" "${defaults[i]}"
|
||||||
values[i]="$PFU_SETTING_VALUE"
|
values[i]="$PFU_SETTING_VALUE"
|
||||||
|
current[${keys[i]}]="$PFU_SETTING_VALUE"
|
||||||
done
|
done
|
||||||
dirty=0
|
dirty=0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
frame="$clearseq"$'\n'"${PFU_C_BOLD}${PFU_C_BLUE} ${title}${PFU_C_RESET}"$'\n\n'
|
frame="$clearseq"$'\n'"${PFU_C_BOLD}${PFU_C_BLUE} ${title}${PFU_C_RESET}"$'\n'
|
||||||
|
|
||||||
local marker selected="${PFU_C_BLUE}▸${PFU_C_RESET} " star
|
local selected=${rows[cursor]} marker before after dim
|
||||||
for i in "${!keys[@]}"; do
|
for i in "${!keys[@]}"; do
|
||||||
|
if [[ ${scopes[i]} == group ]]; then
|
||||||
|
frame+=$'\n'" ${PFU_C_BOLD}${labels[i]}${PFU_C_RESET}"
|
||||||
|
# The next row says whose settings these are.
|
||||||
|
[[ ${scopes[i + 1]} != user ]] && frame+=" ${PFU_C_DIM}${shared}${PFU_C_RESET}"
|
||||||
|
frame+=$'\n'
|
||||||
|
continue
|
||||||
|
fi
|
||||||
case "${types[i]}" in
|
case "${types[i]}" in
|
||||||
bool)
|
bool)
|
||||||
if pfu_is_true "${values[i]}"; then
|
if pfu_is_true "${values[i]}"; then
|
||||||
@@ -426,22 +506,27 @@ pfu_ui_settings() {
|
|||||||
camera) shown="$(_pfu_camera_label "${values[i]}")" ;;
|
camera) shown="$(_pfu_camera_label "${values[i]}")" ;;
|
||||||
*) shown="$(pfu_value_label "${keys[i]}" "${values[i]}")" ;;
|
*) shown="$(pfu_value_label "${keys[i]}" "${values[i]}")" ;;
|
||||||
esac
|
esac
|
||||||
star=' '
|
# Arrows on the selected choice: left and right step through it.
|
||||||
[[ ${scopes[i]} != user ]] && star='*'
|
before=' ' after=''
|
||||||
pad=$(( 44 - ${#labels[i]} ))
|
if (( i == selected )) && [[ ${types[i]} != bool ]]; then
|
||||||
(( pad < 0 )) && pad=0
|
before="${PFU_C_BLUE}◂${PFU_C_RESET} " after=" ${PFU_C_BLUE}▸${PFU_C_RESET}"
|
||||||
if (( i == cursor )); then marker="$selected"; else marker=' '; fi
|
fi
|
||||||
printf -v row ' %s%s%s%*s %s' "$marker" "${labels[i]}" "${PFU_C_DIM}${star}${PFU_C_RESET}" "$pad" '' "$shown"
|
dim=''
|
||||||
|
[[ -n ${needs[i]} ]] && ! pfu_is_true "${current[${needs[i]}]}" && dim="$PFU_C_DIM"
|
||||||
|
pad=$(( width + 2 - ${#labels[i]} ))
|
||||||
|
if (( i == selected )); then marker="${PFU_C_BLUE}▸${PFU_C_RESET} "; else marker=' '; fi
|
||||||
|
printf -v row ' %s%s%s%s%*s%s%s%s' "$marker" "$dim" "${labels[i]}" "$PFU_C_RESET" "$pad" '' "$before" "$dim$shown$PFU_C_RESET" "$after"
|
||||||
frame+="$row"$'\n'
|
frame+="$row"$'\n'
|
||||||
# A gap between the groups: the lock screen, other prompts, how it
|
|
||||||
# checks, the bubble.
|
|
||||||
case "${keys[i]}" in
|
|
||||||
ScanOnLock|polkit-1|SkipLidClosed) frame+=$'\n' ;;
|
|
||||||
esac
|
|
||||||
done
|
done
|
||||||
|
|
||||||
frame+=$'\n'" ${PFU_C_DIM}${legend}${PFU_C_RESET}"$'\n'
|
# What the selected setting does, in a box of fixed height so the
|
||||||
frame+=" ${PFU_C_DIM}${hint}${PFU_C_RESET}"$'\n'
|
# screen does not jump while moving through the list.
|
||||||
|
_pfu_wrap "$wrap" "$(pfu_setting_help "${keys[selected]}" "${values[selected]}")"
|
||||||
|
frame+=$'\n'" ${PFU_C_DIM}${rule}${PFU_C_RESET}"$'\n'
|
||||||
|
for j in 0 1 2; do
|
||||||
|
frame+=" ${PFU_WRAP_LINES[j]:-}"$'\n'
|
||||||
|
done
|
||||||
|
frame+=$'\n'" ${PFU_C_DIM}${hint}${PFU_C_RESET}"$'\n'
|
||||||
_pfu_ui_take_notices
|
_pfu_ui_take_notices
|
||||||
frame+="$PFU_UI_NOTICE_TEXT"
|
frame+="$PFU_UI_NOTICE_TEXT"
|
||||||
printf '%s' "$frame"
|
printf '%s' "$frame"
|
||||||
@@ -451,8 +536,10 @@ pfu_ui_settings() {
|
|||||||
case "$key" in
|
case "$key" in
|
||||||
up|k) cursor=$(( (cursor - 1 + count) % count )) ;;
|
up|k) cursor=$(( (cursor - 1 + count) % count )) ;;
|
||||||
down|j) cursor=$(( (cursor + 1) % count )) ;;
|
down|j) cursor=$(( (cursor + 1) % count )) ;;
|
||||||
space|enter|right|l)
|
space|enter|right|l|left|h)
|
||||||
_pfu_setting_change "${scopes[cursor]}" "${keys[cursor]}" "${types[cursor]}" "${values[cursor]}" "${choices[cursor]}"
|
local step=1
|
||||||
|
[[ $key == left || $key == h ]] && step=-1
|
||||||
|
_pfu_setting_change "${scopes[selected]}" "${keys[selected]}" "${types[selected]}" "${values[selected]}" "${choices[selected]}" "$step"
|
||||||
dirty=1
|
dirty=1
|
||||||
;;
|
;;
|
||||||
q|Q|escape) return 0 ;;
|
q|Q|escape) return 0 ;;
|
||||||
|
|||||||
Reference in new issue
Block a user