# User details in the drawer ## Goal Edit the user's own details from the drawer and write them where other applications already look for them, so LibreOffice, KDE apps, SDDM and git pick them up without being told. ## Where the details live Measured on this machine: - **AccountsService** (`org.freedesktop.Accounts`, D-Bus activated, not a running daemon until called): `RealName`, `Email`, `IconFile`, `Language`, `Location`. Read by KDE's Users settings, GNOME and SDDM. `SetRealName` also rewrites the GECOS field of `/etc/passwd`. - **GECOS** is what LibreOffice's `libdesktopbe1lo.so` reads to prefill its user data (`givenname`). Name only, never email. - **`~/.config/emaildefaults`** (KEMailSettings, `[PROFILE_Default]`): `FullName`, `EmailAddress`. Read by KDE mail apps. - **git** global config (`~/.gitconfig`): `user.name`, `user.email`, `user.signingkey`. Polkit's `org.freedesktop.accounts.change-own-user-data` is implicit `yes` for any, inactive and active sessions, so no write prompts for a password. ## Drawer row A row at the top of the drawer's grid view, above the notification list: the avatar in a circle, `Hello ` (the login name, `$USER`, which is fixed and not editable), and the real name as a smaller sub-line under it. Clicking it opens the user page; Escape and the mouse back button step out as on every page. ## Module: `desktop/modules/user/` - `UserModule.qml`: name `user`, label `User`, a `page`. It sets `tiled: false`, a new `Module` property (default `true`) that the drawer's tile grid filters on, so the module has a page and no tile. - `UserRow.qml`: the drawer row. `Drawer.qml` places it above `NotificationList` and calls `show("user")` on click. - `UserPage.qml`: the form. Avatar (click to choose a file with `QtQuick.Dialogs.FileDialog`, as the KDE Connect module already does; shown cropped to a circle, no cropping tool), name, email, language (a combo from `locale -a`, UTF-8 entries only), location (free text), signing key (a combo of the secret keys gpg holds, plus None), and a line previewing what git will carry: `git: Jane D. `. A Save button sends only the fields that changed. - `userctl`: bash, the only writer, like `statusctl`. The page reads values when it opens. The row reads them when the drawer opens. ## `userctl` userctl get # key=value lines: name, email, avatar, language, location, signingkey userctl keys # fpruid per secret key, from gpg --list-secret-keys --with-colons userctl set # writes one field everywhere it lives | Field | Writes | | --- | --- | | name | AccountsService `SetRealName`, emaildefaults `FullName`, git `user.name` (shortened) | | email | AccountsService `SetEmail`, emaildefaults `EmailAddress`, git `user.email` | | avatar | AccountsService `SetIconFile` (the daemon copies the file in) | | language | AccountsService `SetLanguage` | | location | AccountsService `SetLocation` | | signingkey | git `user.signingkey` (the fingerprint); None unsets it | AccountsService is called with `busctl --system`, emaildefaults with `kwriteconfig6 --file emaildefaults --group PROFILE_Default`, git with `git config --global`. Keys on a smartcard are listed as stubs by gpg and appear like any other; `commit.gpgsign` is not touched. **Git name shortening.** The last whitespace-separated word becomes its first character and a dot: `Jane Doèr` becomes `Jane D.`. A single-word name is unchanged. The first character is taken by character, not byte, so an accented initial survives. `set` exits non-zero on the first failing write and prints the failing command's stderr. The page shows that text under the field, and leaves the field marked changed so Save retries it. ## Extending A new detail is one entry in the field list in `UserPage.qml` and one `case` in `userctl`. No settings framework. ## Testing `test-userctl.sh`: stub `busctl`, `kwriteconfig6`, `git` and `gpg` on `PATH` that log their arguments. Checks the shortening (two words, three words, one word, accented initial), the `keys` parsing of a colon listing with two keys, that an empty signing key unsets it, that each field reaches exactly its stores, and that a failing stub makes `set` exit non-zero. It never calls the real AccountsService or touches the real git config. ## Ceilings - Values are read on open; a change made elsewhere while the page is open is not seen until it reopens. - No `~/.face.icon`: SDDM reads the AccountsService icon. - No password. `passwd` in a terminal already does it safely, and AccountsService's `SetPassword` needs admin rights and a pre-hashed value. Changing it also leaves the gnome-keyring unlocked at login on the old password, since the `passwd` PAM stack does not re-key it. - No vCard, no social links: nothing on the desktop reads them. The field list is where they would go.