presentation/SettingsCatalog.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "SettingsCatalog.h" | ||
| 2 | #include <QCoreApplication> | ||
| 3 | #include <QHash> | ||
| 4 | #include <QRegularExpression> | ||
| 5 | #include <QSet> | ||
| 6 | #include <algorithm> | ||
| 7 | |||
| 8 | namespace { | ||
| 9 | using K = SettingKind; | ||
| 10 | using S = SettingScope; | ||
| 11 | |||
| 12 | // The page list of §6.1 (D-5): three blocks, the areas in the order of the | ||
| 13 | // area tabs. | ||
| 14 | 25 | QList<SettingsPageSpec> pageTable() { | |
| 15 | return { | ||
| 16 | {.id = "accounts", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Accounts"), | ||
| 17 | .keywords = "konten konto | accounts account", .glyph = 0xF0B55, .block = "main"}, | ||
| 18 | {.id = "general", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "General"), | ||
| 19 | .keywords = "allgemein start | general startup", .glyph = 0xF1542, .block = "main"}, | ||
| 20 | {.id = "appearance", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Appearance"), | ||
| 21 | .keywords = "aussehen darstellung design | appearance look", .glyph = 0xF0E0C, .block = "main"}, | ||
| 22 | {.id = "mail", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Mail"), | ||
| 23 | .keywords = "e-mail nachrichten post | mail messages email", .glyph = 0xF01F0, .block = "areas"}, | ||
| 24 | {.id = "calendar", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Calendar"), | ||
| 25 | .keywords = "kalender termine | calendar appointments events", .glyph = 0xF0E18, .block = "areas"}, | ||
| 26 | {.id = "tasks", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Tasks"), .keywords = "aufgaben | tasks todo", | ||
| 27 | .glyph = 0xF0134, .block = "areas"}, | ||
| 28 | {.id = "contacts", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Contacts"), | ||
| 29 | .keywords = "kontakte adressbuch | contacts address book", .glyph = 0xF0007, .block = "areas"}, | ||
| 30 | {.id = "rules", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Rules"), | ||
| 31 | .keywords = "regeln filter serverregeln spam | rules filters sieve spam", .glyph = 0xF0233, .block = "areas"}, | ||
| 32 | {.id = "sync", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Sync"), | ||
| 33 | .keywords = "abgleich synchronisieren synchronisation | sync synchronization", .glyph = 0xF04E6, | ||
| 34 | .block = "system"}, | ||
| 35 | {.id = "privacy", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Privacy"), | ||
| 36 | .keywords = "datenschutz privatsphäre | privacy", .glyph = 0xF0CCC, .block = "system"}, | ||
| 37 | {.id = "about", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "About"), | ||
| 38 | .keywords = "über version lizenz | about version license", .glyph = 0xF02FD, .block = "system"}, | ||
| 39 | 25 | }; | |
| 40 | } | ||
| 41 | |||
| 42 | 15 | QList<SettingsGroupSpec> groupTable() { | |
| 43 | return { | ||
| 44 | {.page = "accounts", .id = "overview", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "All accounts"), | ||
| 45 | .keywords = "übersicht status | overview status"}, | ||
| 46 | {.page = "accounts", .id = "mail", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Mail"), | ||
| 47 | .keywords = "posteingang postausgang | incoming outgoing"}, | ||
| 48 | {.page = "accounts", .id = "rules", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Server rules"), | ||
| 49 | .keywords = "sieve regelserver | sieve rule server"}, | ||
| 50 | // Sprint 108 S108.5.4 (D-15, D-16): the addresses an account writes from. | ||
| 51 | {.page = "accounts", .id = "identities", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Addresses and signatures"), | ||
| 52 | .keywords = "absender identität alias signatur unterschrift | sender identity alias signature"}, | ||
| 53 | {.page = "accounts", .id = "calendars", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Calendars and contacts"), | ||
| 54 | .keywords = "kalender adressbücher dav | calendars address books dav"}, | ||
| 55 | {.page = "general", .id = "regional", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Language"), | ||
| 56 | .keywords = "sprache | language"}, | ||
| 57 | {.page = "general", .id = "startup", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Startup and tray"), | ||
| 58 | .keywords = "start systemleiste | startup tray"}, | ||
| 59 | {.page = "general", .id = "alerts", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Notifications"), | ||
| 60 | .keywords = "benachrichtigungen mitteilungen | notifications"}, | ||
| 61 | // Sprint 105 S105.8.7: the place Sprint 100 reserved for the keyboard. | ||
| 62 | {.page = "general", .id = "keyboard", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Keyboard"), | ||
| 63 | .keywords = "tastatur tasten kürzel | keyboard keys shortcuts"}, | ||
| 64 | {.page = "appearance", .id = "colors", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Theme and colors"), | ||
| 65 | .keywords = "farben design | colors theme"}, | ||
| 66 | {.page = "appearance", .id = "display", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Layout and text"), | ||
| 67 | .keywords = "anordnung schrift | layout text"}, | ||
| 68 | {.page = "mail", .id = "message-list", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Message list"), | ||
| 69 | .keywords = "nachrichtenliste liste | message list"}, | ||
| 70 | {.page = "mail", .id = "reading", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Reading"), | ||
| 71 | .keywords = "lesen leseansicht | reading reader"}, | ||
| 72 | {.page = "mail", .id = "writing", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Writing"), | ||
| 73 | .keywords = "schreiben verfassen | writing compose"}, | ||
| 74 | {.page = "mail", .id = "downloads", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Downloads"), | ||
| 75 | .keywords = "herunterladen | downloads"}, // F100-44: one setting, no "Advanced" disclosure | ||
| 76 | {.page = "calendar", .id = "working-time", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Working time"), | ||
| 77 | .keywords = "arbeitszeit arbeitstag arbeitsbeginn feierabend wochenbeginn | working hours workday business hours"}, | ||
| 78 | {.page = "calendar", .id = "reminders", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Reminders"), | ||
| 79 | .keywords = "erinnerungen alarm | reminders alarms"}, | ||
| 80 | {.page = "calendar", .id = "invitations", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Invitations"), | ||
| 81 | .keywords = "einladungen zusage absage | invitations rsvp"}, | ||
| 82 | {.page = "calendar", .id = "show", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Show in the calendar"), | ||
| 83 | .keywords = "anzeigen einblenden | show display"}, | ||
| 84 | {.page = "calendar", .id = "mail-view", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "In the mail view"), | ||
| 85 | .keywords = "statusleiste | status bar"}, | ||
| 86 | {.page = "calendar", .id = "subscriptions", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Subscribed calendars"), | ||
| 87 | .keywords = "abonnements abonniert ics webcal feiertage | subscriptions ics webcal holidays"}, | ||
| 88 | {.page = "tasks", .id = "reminders", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Reminders"), | ||
| 89 | .keywords = "erinnerungen | reminders"}, | ||
| 90 | {.page = "contacts", .id = "me", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Me"), | ||
| 91 | .keywords = "ich meine karte das bin ich | me my card this is me"}, | ||
| 92 | {.page = "contacts", .id = "names", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Names"), | ||
| 93 | .keywords = "namen | names"}, | ||
| 94 | {.page = "contacts", .id = "completion", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Address completion"), | ||
| 95 | .keywords = "vervollständigung autovervollständigung | completion autocomplete"}, | ||
| 96 | {.page = "contacts", .id = "books", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Address books"), | ||
| 97 | .keywords = "adressbücher synchronisation | address books sync"}, | ||
| 98 | {.page = "rules", .id = "accounts", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Rules per account"), | ||
| 99 | .keywords = "konten | accounts"}, | ||
| 100 | {.page = "rules", .id = "behavior", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Behavior"), | ||
| 101 | .keywords = "verhalten | behavior"}, | ||
| 102 | {.page = "sync", .id = "status", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Status"), | ||
| 103 | .keywords = "status zustand | status"}, | ||
| 104 | {.page = "sync", .id = "background", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Background sync"), | ||
| 105 | .keywords = "intervall hintergrund minuten automatisch | interval background minutes automatic", | ||
| 106 | .lead = QT_TRANSLATE_NOOP("SettingsCatalog", "How often MailJD asks the servers for changes.")}, | ||
| 107 | {.page = "sync", .id = "push", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Push"), | ||
| 108 | .keywords = "push sofort ntfy unifiedpush | push instant ntfy"}, | ||
| 109 | {.page = "sync", .id = "installations", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Between installations"), | ||
| 110 | .keywords = "einstellungen geräte installationen | settings devices installations", | ||
| 111 | .lead = QT_TRANSLATE_NOOP("SettingsCatalog", "Keeps chosen settings equal on your other MailJD installations.")}, | ||
| 112 | {.page = "privacy", .id = "remote-content", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Remote content"), | ||
| 113 | .keywords = "externe inhalte bilder tracking | remote content images tracking"}, | ||
| 114 | {.page = "privacy", .id = "collected-addresses", | ||
| 115 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Collected addresses"), | ||
| 116 | .keywords = "gesammelte adressen | collected addresses"}, | ||
| 117 | {.page = "privacy", .id = "address-lookup", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Address lookup"), | ||
| 118 | .keywords = "adressen nachschlagen position | address lookup position"}, | ||
| 119 | {.page = "privacy", .id = "relationship-suggestions", | ||
| 120 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Suggested relationships"), | ||
| 121 | .keywords = "beziehungsvorschläge beziehungen graph | suggested relationships graph"}, | ||
| 122 | {.page = "privacy", .id = "contact-map", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Contact map"), | ||
| 123 | .keywords = "karte weltkarte kacheln openstreetmap | map world map tiles openstreetmap"}, | ||
| 124 | {.page = "privacy", .id = "command-history", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Command history"), | ||
| 125 | .keywords = "befehlsverlauf verlauf | command history"}, | ||
| 126 | {.page = "about", .id = "mailjd", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "MailJD"), | ||
| 127 | .keywords = "version programm | version program"}, | ||
| 128 | 15 | }; | |
| 129 | } | ||
| 130 | |||
| 131 | 12 | QList<SettingSpec> accountSettings() { | |
| 132 | return { | ||
| 133 | {.id = "accounts/add", .group = "overview", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Add account"), | ||
| 134 | .keywords = "konto hinzufügen einrichten neu anlegen | add account new set up", .kind = K::Action, | ||
| 135 | .owner = "openSettings(\"accounts/new\")", .store = "account file", .scope = S::Profile}, | ||
| 136 | {.id = "accounts/status", .group = "overview", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Account status"), | ||
| 137 | .keywords = "status verbindung fehler funktioniert | status connection error working", .kind = K::Info, | ||
| 138 | .owner = "backend.settings.accountOverview", .scope = S::Profile, .availability = "backend"}, | ||
| 139 | {.id = "accounts/servers", .group = "mail", | ||
| 140 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Incoming and outgoing mail"), | ||
| 141 | .keywords = "imap smtp server posteingang postausgang port verschlüsselung | imap smtp server incoming outgoing port encryption", | ||
| 142 | .kind = K::Editor, .owner = "backend.settings.saveAccountAsync", .store = "account file + keyring", | ||
| 143 | .scope = S::Account, | ||
| 144 | .availability = "backend"}, | ||
| 145 | {.id = "accounts/sender-name", .group = "mail", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Your name"), | ||
| 146 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Shown to the people you write to."), | ||
| 147 | .keywords = "absender name anzeigename | sender name display name", .kind = K::Editor, | ||
| 148 | .owner = "backend.settings.saveAccountAsync", .store = "account file", .scope = S::Account, | ||
| 149 | .availability = "backend"}, | ||
| 150 | {.id = "accounts/addresses", .group = "identities", | ||
| 151 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Addresses and signatures"), | ||
| 152 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "The names, addresses and signatures you write with."), | ||
| 153 | .keywords = "absender alias signatur unterschrift identität | sender alias signature identity", .kind = K::Editor, | ||
| 154 | .owner = "backend.compose.saveIdentity", .store = "identities.json", .scope = S::Account, | ||
| 155 | .availability = "backend"}, | ||
| 156 | {.id = "accounts/password", .group = "mail", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Change password"), | ||
| 157 | .keywords = "passwort kennwort ändern anmeldung zugangsdaten | password change login credentials", | ||
| 158 | .kind = K::Editor, | ||
| 159 | .owner = "backend.settings.changePassword", .store = "keyring", .scope = S::Account, .availability = "backend"}, | ||
| 160 | {.id = "accounts/server-rules", .group = "rules", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Rule server"), | ||
| 161 | .keywords = "sieve managesieve regelserver | sieve managesieve rule server", .kind = K::Editor, | ||
| 162 | .owner = "backend.settings.saveAccountAsync", .store = "account file", .scope = S::Account, | ||
| 163 | .availability = "backend"}, | ||
| 164 | {.id = "accounts/collections", .group = "calendars", | ||
| 165 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Calendars, task lists, address books"), | ||
| 166 | .keywords = "caldav carddav nextcloud kalenderauswahl adressbücher | caldav carddav nextcloud choose calendars", | ||
| 167 | .kind = K::Editor, .owner = "backend.settings.davAccounts", .key = "carddav/accounts, caldav/configs", | ||
| 168 | .store = "QSettings + keyring", .scope = S::Account, .syncCategory = "davAccounts", .availability = "backend"}, | ||
| 169 | {.id = "accounts/remove", .group = "overview", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Remove account"), | ||
| 170 | .keywords = "konto entfernen löschen | remove delete account", .kind = K::Action, | ||
| 171 | .owner = "backend.settings.removeAccount", .store = "account file + keyring", .scope = S::Account, | ||
| 172 | .availability = "backend"}, | ||
| 173 | 12 | }; | |
| 174 | } | ||
| 175 | |||
| 176 | 12 | QList<SettingSpec> preferenceSettings() { | |
| 177 | return { | ||
| 178 | // General | ||
| 179 | {.id = "general/language", .group = "regional", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Language"), | ||
| 180 | .keywords = "sprache deutsch englisch | language german english locale", .kind = K::Choice, | ||
| 181 | .owner = "backend.preferences.language", .key = "i18n/language", .store = "QSettings", .defaultValue = "auto", | ||
| 182 | .values = "auto|en|de", .syncCategory = "general", .availability = "backend"}, | ||
| 183 | {.id = "general/start-minimized", .group = "startup", | ||
| 184 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Start minimized"), | ||
| 185 | .keywords = "minimiert starten autostart versteckt | start minimized hidden", .kind = K::Toggle, | ||
| 186 | .owner = "backend.preferences.startMinimized", .key = "tray/startMinimized", .store = "QSettings", | ||
| 187 | .defaultValue = "false", .availability = "backend"}, | ||
| 188 | {.id = "general/close-to-tray", .group = "startup", | ||
| 189 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Keep in the tray when closing"), | ||
| 190 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Closing the window keeps MailJD running."), | ||
| 191 | .keywords = "systemleiste tray schließen hintergrund | tray close background", .kind = K::Toggle, | ||
| 192 | .owner = "tray.closeToTray", .key = "ui/closeToTray", .store = "UiStateStore", .defaultValue = "true", | ||
| 193 | .availability = "tray"}, | ||
| 194 | {.id = "general/notifications", .group = "alerts", | ||
| 195 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Notify me about new mail"), | ||
| 196 | .keywords = "benachrichtigungen mitteilungen nicht stören | notifications new mail alerts", .kind = K::Toggle, | ||
| 197 | .owner = "backend.preferences.notifications", .key = "notifications/enabled", .store = "QSettings", | ||
| 198 | .defaultValue = "true", .availability = "backend"}, | ||
| 199 | // Sprint 105 S105.8.7 (D-12, D-17): the keys overlay. | ||
| 200 | {.id = "general/hold-alt", .group = "keyboard", | ||
| 201 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Hold Alt to show the keys"), | ||
| 202 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Ctrl+? shows them without holding."), | ||
| 203 | .keywords = "alt halten tastenübersicht tasten | hold alt keys overlay", .kind = K::Toggle, | ||
| 204 | .owner = "commands.overlay.holdEnabled", .key = "keys/holdAlt", .store = "QSettings", .defaultValue = "true"}, | ||
| 205 | {.id = "general/hold-delay", .group = "keyboard", | ||
| 206 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Delay before the keys appear"), | ||
| 207 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "In milliseconds; 0 shows them at once."), | ||
| 208 | .keywords = "verzögerung millisekunden | delay milliseconds", .kind = K::Number, | ||
| 209 | .owner = "commands.overlay.holdDelay", .key = "keys/holdDelay", .store = "QSettings", .defaultValue = "300", | ||
| 210 | .values = "0…1000"}, | ||
| 211 | {.id = "general/key-explanations", .group = "keyboard", | ||
| 212 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Explanations"), | ||
| 213 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Short texts at the keys whose effect is not obvious."), | ||
| 214 | .keywords = "erklärungen hilfe texte | explanations help", .kind = K::Choice, | ||
| 215 | .owner = "commands.overlay.explanations", .key = "keys/explanations", .store = "QSettings", | ||
| 216 | .defaultValue = "after", .values = "after|atOnce|never"}, | ||
| 217 | // Appearance | ||
| 218 | {.id = "appearance/theme", .group = "colors", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Theme"), | ||
| 219 | .keywords = "dunkel hell dunkelmodus farbschema | dark light dark mode", .kind = K::Choice, | ||
| 220 | .owner = "tokens.theme", | ||
| 221 | .key = "appearance/theme", .store = "UiStateStore", .defaultValue = "system", .values = "light|dark|system"}, | ||
| 222 | {.id = "appearance/accent", .group = "colors", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Accent color"), | ||
| 223 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Shades adapt to the theme to keep text readable."), | ||
| 224 | .keywords = "akzentfarbe farbe hervorhebung | accent color highlight", .kind = K::Text, | ||
| 225 | .owner = "tokens.applyAccentColor", .key = "appearance/accentColor", .store = "UiStateStore", .values = "#RRGGBB"}, | ||
| 226 | {.id = "appearance/layout", .group = "display", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Layout"), | ||
| 227 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Wide puts the reader beside the list."), | ||
| 228 | .keywords = "anordnung breit klassisch lesebereich | layout wide classic reading pane", .kind = K::Choice, | ||
| 229 | .owner = "workspace.layout", .key = "ui/layout", .store = "UiStateStore", .defaultValue = "classic", | ||
| 230 | .values = "classic|wide"}, | ||
| 231 | {.id = "appearance/text-size", .group = "display", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Text size"), | ||
| 232 | .keywords = "schriftgröße schrift zoom größer | font size text zoom larger", .kind = K::Choice, | ||
| 233 | .owner = "tokens.fontScale", .key = "ui/fontScale", .store = "UiStateStore", .defaultValue = "1", | ||
| 234 | .values = "1|1.5|2"}, | ||
| 235 | {.id = "appearance/motion", .group = "display", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Motion"), | ||
| 236 | .keywords = "animation bewegung reduziert | animation motion reduce", .kind = K::Choice, | ||
| 237 | .owner = "tokens.applyMotionPolicy", .key = "ui/motion", .store = "UiStateStore", .defaultValue = "system", | ||
| 238 | .values = "system|reduced|full"}, | ||
| 239 | |||
| 240 | {.id = "mail/threads", .group = "message-list", | ||
| 241 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Group messages by thread"), | ||
| 242 | .keywords = "unterhaltungen konversation verlauf | threads conversations", .kind = K::Toggle, | ||
| 243 | .owner = "backend.threaded", .key = "view/threaded", .store = "UiStateStore", .defaultValue = "false", | ||
| 244 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "View menu"), .availability = "backend"}, | ||
| 245 | {.id = "mail/suggestions", .group = "message-list", | ||
| 246 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Folder suggestions for all mails"), | ||
| 247 | .keywords = "ordnervorschläge vorschläge verschieben | folder suggestions move", .kind = K::Toggle, | ||
| 248 | .owner = "backend.suggestionsVisible", .key = "view/suggestions", .store = "UiStateStore", .defaultValue = "false", | ||
| 249 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "View menu"), .availability = "backend"}, | ||
| 250 | {.id = "mail/reading-mode", .group = "reading", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Open messages as"), | ||
| 251 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "A mode you pick in the reader stays for that session."), | ||
| 252 | .keywords = "lesemodus anzeige text html | reading mode text html", .kind = K::Choice, | ||
| 253 | .owner = "backend.settings.defaultReadingMode", .key = "view/defaultMode", .store = "QSettings", | ||
| 254 | .defaultValue = "text", .values = "text|light|html", .syncCategory = "general", .availability = "backend"}, | ||
| 255 | // F100-56; "spam" alone keeps finding the Rules page first (G4). | ||
| 256 | {.id = "mail/spam-score", .group = "reading", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Show the server filter's rating"), | ||
| 257 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "How SpamAssassin or Rspamd on the server rated it, beside the date."), | ||
| 258 | .keywords = "spamassassin rspamd bewertung punkte | spamassassin rspamd rating score", .kind = K::Toggle, | ||
| 259 | .owner = "backend.preferences.showSpamScore", .key = "reader/showSpamScore", .store = "QSettings", | ||
| 260 | .defaultValue = "true", .syncCategory = "general", .availability = "backend"}, | ||
| 261 | // Sprint 108 D-20: how long a sent message waits for Undo. | ||
| 262 | {.id = "mail/undo-send", .group = "writing", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Undo sending"), | ||
| 263 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "How long a sent message waits before it leaves."), | ||
| 264 | .keywords = "rückgängig senden verzögerung zurückholen | undo send delay", .kind = K::Choice, | ||
| 265 | .owner = "backend.compose.undoDelaySeconds", .key = "compose/undoDelaySeconds", .store = "QSettings", | ||
| 266 | .defaultValue = "10", .values = "0|5|10|20|30", .availability = "backend"}, | ||
| 267 | // Sprint 108 D-7: **bold**, - lists and # headings while typing. | ||
| 268 | {.id = "mail/markdown-typing", .group = "writing", | ||
| 269 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Format while typing"), | ||
| 270 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "**bold**, _italic_, - lists and # headings in formatted mails."), | ||
| 271 | .keywords = "markdown formatierung tippen fett liste | markdown formatting typing bold list", .kind = K::Toggle, | ||
| 272 | .owner = "backend.compose.markdownTyping", .key = "compose/markdownTyping", .store = "QSettings", | ||
| 273 | .defaultValue = "true", .availability = "backend"}, | ||
| 274 | // Sprint 108 D-26: the one-line reply field above the shown message. | ||
| 275 | {.id = "mail/quick-reply", .group = "writing", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Quick reply"), | ||
| 276 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Q shows a reply field above the message; typing opens the reply."), | ||
| 277 | .keywords = "schnellantwort antworten feld | quick reply field", .kind = K::Toggle, | ||
| 278 | .owner = "backend.compose.quickReply", .key = "compose/quickReply", .store = "QSettings", | ||
| 279 | .defaultValue = "true", .availability = "backend"}, | ||
| 280 | // Sprint 108 S108.9.5 (D-27): saved message texts (⋯ › Templates… in the composer). | ||
| 281 | {.id = "mail/templates", .group = "writing", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Templates"), | ||
| 282 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Saved texts to insert into a message. Save one in the composer: ⋯ › Templates…."), | ||
| 283 | .keywords = "vorlage vorlagen textbaustein | template templates snippet", .kind = K::Editor, | ||
| 284 | .owner = "backend.compose.templates", .store = "templates.json", .availability = "backend"}, | ||
| 285 | {.id = "mail/compose-window", .group = "writing", | ||
| 286 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Write in a separate window"), | ||
| 287 | .keywords = "eigenes fenster verfassen abdocken | separate window compose detach", .kind = K::Toggle, | ||
| 288 | .owner = "backend.compose.composeWindowed", .key = "ui/composeWindowed", .store = "UiStateStore", | ||
| 289 | .defaultValue = "false", .availability = "backend"}, | ||
| 290 | {.id = "mail/max-message-size", .group = "downloads", | ||
| 291 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Largest message to download"), | ||
| 292 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", | ||
| 293 | "Larger messages are not downloaded. In MiB; matches the composer."), | ||
| 294 | .keywords = "maximale größe nachrichtengröße limit | maximum size limit", .kind = K::Number, | ||
| 295 | .owner = "backend.preferences.maximumMessageMiB", .key = "network/maxMessageSizeMiB", .store = "QSettings", | ||
| 296 | .defaultValue = "100", .values = "1…100", .availability = "backend"}, | ||
| 297 | // Calendar | ||
| 298 | {.id = "calendar/workday-start", .group = "working-time", | ||
| 299 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Working day starts at"), | ||
| 300 | .keywords = "beginn | start", .kind = K::Choice, .owner = "backend.pim.calendarWorkdayStart", | ||
| 301 | .key = "calendar/workdayStart", .store = "UiStateStore", .defaultValue = "8", .values = "0…22", | ||
| 302 | .availability = "backend"}, | ||
| 303 | {.id = "calendar/workday-end", .group = "working-time", | ||
| 304 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Working day ends at"), | ||
| 305 | .keywords = "ende feierabend | end", .kind = K::Choice, .owner = "backend.pim.calendarWorkdayEnd", | ||
| 306 | .key = "calendar/workdayEnd", .store = "UiStateStore", .defaultValue = "18", .values = "1…24", | ||
| 307 | .availability = "backend"}, | ||
| 308 | // Sprint 108 D-22: the days *Suggest times* offers. | ||
| 309 | {.id = "calendar/working-days", .group = "working-time", | ||
| 310 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Working days"), | ||
| 311 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "The days the composer suggests meeting times on."), | ||
| 312 | .keywords = "arbeitstage werktage wochentage | working days weekdays", .kind = K::Choice, | ||
| 313 | .owner = "backend.pim.calendarWorkdays", .key = "calendar/workdays", .store = "UiStateStore", | ||
| 314 | .defaultValue = "1,2,3,4,5", .values = "1…7", .availability = "backend"}, | ||
| 315 | {.id = "calendar/first-day", .group = "working-time", | ||
| 316 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Week starts on"), | ||
| 317 | .keywords = "wochenbeginn montag sonntag | first day monday sunday", .kind = K::Choice, | ||
| 318 | .owner = "backend.pim.calendarFirstDayOfWeek", .key = "calendar/firstDayOfWeek", .store = "UiStateStore", | ||
| 319 | .defaultValue = "0", .values = "0|1|7|6", .availability = "backend"}, | ||
| 320 | {.id = "calendar/remind", .group = "reminders", | ||
| 321 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Remind me of appointments"), | ||
| 322 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Also covers tasks with a reminder."), | ||
| 323 | .keywords = "erinnern benachrichtigung doppelt | remind notify twice", .kind = K::Toggle, | ||
| 324 | .owner = "backend.pim.remindersEnabled", .key = "calendar/remindersEnabled", .store = "QSettings", | ||
| 325 | .defaultValue = "true", .availability = "backend"}, | ||
| 326 | {.id = "calendar/default-reminder", .group = "reminders", | ||
| 327 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Default reminder"), | ||
| 328 | .keywords = "standarderinnerung vorlauf | default reminder lead time", .kind = K::Choice, | ||
| 329 | .owner = "backend.pim.defaultReminder", .key = "calendar/defaultReminder", .store = "QSettings", | ||
| 330 | .defaultValue = "15", .values = "-1|0|5|10|15|30|60|1440", .availability = "backend"}, | ||
| 331 | {.id = "calendar/invitation-replies", .group = "invitations", | ||
| 332 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Invitations and replies"), | ||
| 333 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", | ||
| 334 | "Automatic: a scheduling calendar server sends them, otherwise MailJD mails them."), | ||
| 335 | .keywords = "antworten itip imip planung | replies itip imip scheduling", .kind = K::Choice, | ||
| 336 | .owner = "backend.invitation.replyMode", .key = "calendar/imipReplies", .store = "QSettings", | ||
| 337 | .defaultValue = "auto", .values = "auto|client|server", .availability = "backend"}, | ||
| 338 | {.id = "calendar/show-tasks", .group = "show", | ||
| 339 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Tasks with a due date"), | ||
| 340 | .keywords = "aufgaben fällig | tasks due", .kind = K::Toggle, .owner = "backend.pim.calendar.showTasks", | ||
| 341 | .key = "calendar/showTasks", .store = "QSettings", .defaultValue = "false", | ||
| 342 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "View menu"), .availability = "backend"}, | ||
| 343 | {.id = "calendar/show-birthdays", .group = "show", | ||
| 344 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Birthdays of contacts"), | ||
| 345 | .keywords = "geburtstage | birthdays", .kind = K::Toggle, .owner = "backend.pim.calendar.showBirthdays", | ||
| 346 | .key = "calendar/showBirthdays", .store = "QSettings", .defaultValue = "false", | ||
| 347 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "View menu"), .availability = "backend"}, | ||
| 348 | {.id = "calendar/next-up", .group = "mail-view", | ||
| 349 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Next appointment in status bar"), | ||
| 350 | .keywords = "nächster termin | next appointment", .kind = K::Toggle, .owner = "backend.pim.nextUp.enabled", | ||
| 351 | .key = "calendar/nextUpInStatusBar", .store = "QSettings", .defaultValue = "true", | ||
| 352 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "View menu"), .availability = "backend"}, | ||
| 353 | {.id = "calendar/subscription-list", .group = "subscriptions", | ||
| 354 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Calendar subscriptions"), | ||
| 355 | .keywords = "abonnieren aktualisierung | subscribe update", .kind = K::List, | ||
| 356 | .owner = "backend.pim.subscriptionList", .key = "calendar/subscriptions", .store = "QSettings", | ||
| 357 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "calendar sidebar"), .availability = "backend"}, | ||
| 358 | // Tasks | ||
| 359 | {.id = "tasks/default-reminder", .group = "reminders", | ||
| 360 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Default reminder for new tasks"), | ||
| 361 | .keywords = "aufgabenerinnerung fälligkeit | task reminder due", .kind = K::Choice, | ||
| 362 | .owner = "backend.pim.taskActions.defaultReminder", .key = "calendar/taskDefaultReminder", .store = "UiStateStore", | ||
| 363 | .defaultValue = "0", .values = "0|1", .availability = "backend"}, | ||
| 364 | // Contacts | ||
| 365 | {.id = "contacts/name-order", .group = "names", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Sort names by"), | ||
| 366 | .keywords = "namensreihenfolge nachname vorname sortieren | name order surname first name sort", .kind = K::Choice, | ||
| 367 | .owner = "backend.pim.contacts.sortByFamilyName", .key = "contacts/sortByFamilyName", .store = "QSettings", | ||
| 368 | .defaultValue = "given", .values = "given|family", | ||
| 369 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "contacts View menu"), | ||
| 370 | .availability = "backend"}, | ||
| 371 | // Sprint 103 D-6, F103-29: the card that is the user (per profile, never synced). | ||
| 372 | {.id = "contacts/my-card", .group = "me", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "My card"), | ||
| 373 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Relationships are seen from it; the graph starts there."), | ||
| 374 | .keywords = "ich meine karte das bin ich eigene | me my card this is me own", .kind = K::Action, | ||
| 375 | .owner = "backend.pim.contactActions.setMe", .key = "contacts/meCard", .store = "QSettings", | ||
| 376 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "a contact's menu"), .availability = "backend"}, | ||
| 377 | // S97.5.11, kept by S100.5.7: every CardDAV address book with its state. | ||
| 378 | {.id = "contacts/book-states", .group = "books", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Synchronization"), | ||
| 379 | .keywords = "nicht synchronisiert fehler jetzt abgleichen | not synchronized error sync now", .kind = K::List, | ||
| 380 | .owner = "backend.pim.contactNavigation.books", .key = "carddav/accounts", .store = "QSettings", | ||
| 381 | .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "contacts sidebar"), .availability = "backend"}, | ||
| 382 | {.id = "contacts/collected", .group = "completion", | ||
| 383 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Remembered addresses"), | ||
| 384 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Set on the Privacy page."), | ||
| 385 | .keywords = "gesammelte adressen merken | collected addresses remember", .kind = K::Link, | ||
| 386 | .target = "privacy/collect-addresses"}, | ||
| 387 | // Rules | ||
| 388 | {.id = "rules/manage", .group = "accounts", | ||
| 389 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Rules and out of office"), | ||
| 390 | .keywords = "abwesenheit abwesend urlaub abwesenheitsnotiz verwalten | out of office vacation autoreply manage", | ||
| 391 | .kind = K::List, .owner = "backend.rules", .store = "server", .scope = S::Account, .availability = "backend"}, | ||
| 392 | {.id = "rules/apply-to-existing", .group = "behavior", | ||
| 393 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "New rules sort existing mail"), | ||
| 394 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Matching messages already in the folder move too."), | ||
| 395 | .keywords = "bestehende nachrichten anwenden | existing mail apply", .kind = K::Toggle, | ||
| 396 | .owner = "backend.preferences.applyRulesToExisting", .key = "rules/applyToExisting", .store = "QSettings", | ||
| 397 | .defaultValue = "false", .availability = "backend"}, | ||
| 398 | {.id = "rules/suggestions", .group = "behavior", | ||
| 399 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Suggest rules from my moves"), | ||
| 400 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "After three messages from one sender go to one folder."), | ||
| 401 | .keywords = "regelvorschläge vorschlagen | rule suggestions suggest", .kind = K::Toggle, | ||
| 402 | .owner = "backend.preferences.ruleSuggestions", .key = "rules/suggestions", .store = "QSettings", | ||
| 403 | .defaultValue = "true", .availability = "backend"}, | ||
| 404 | 12 | }; | |
| 405 | } | ||
| 406 | |||
| 407 | 12 | QList<SettingSpec> systemSettings() { | |
| 408 | return { | ||
| 409 | // Sync | ||
| 410 | {.id = "sync/now", .group = "status", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Sync now"), | ||
| 411 | .keywords = "jetzt abgleichen aktualisieren | sync now refresh", .kind = K::Action, | ||
| 412 | .owner = "backend.pim.sync.syncNow", .scope = S::Profile, .availability = "backend"}, | ||
| 413 | {.id = "sync/calendar-interval", .group = "background", | ||
| 414 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Calendars and tasks"), | ||
| 415 | .keywords = "kalenderintervall | calendar interval", .kind = K::Choice, | ||
| 416 | .owner = "backend.settings.caldavSyncIntervalMinutes", .key = "caldav/syncIntervalMin", .store = "QSettings", | ||
| 417 | .defaultValue = "15", .values = "0|5|15|30|60|240", .syncCategory = "general", .availability = "backend"}, | ||
| 418 | {.id = "sync/contact-interval", .group = "background", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Contacts"), | ||
| 419 | .keywords = "kontaktintervall adressbücher | contact interval address books", .kind = K::Choice, | ||
| 420 | .owner = "backend.preferences.contactIntervalMinutes", .key = "carddav/syncIntervalMin", .store = "QSettings", | ||
| 421 | .defaultValue = "0", .values = "0|5|15|30|60|240", .syncCategory = "general", .availability = "backend"}, | ||
| 422 | {.id = "sync/use-push", .group = "push", | ||
| 423 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Push when the server offers it"), | ||
| 424 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Changes arrive at once; the interval stays as a safety net."), | ||
| 425 | .keywords = "sofort echtzeit | instant real time", .kind = K::Toggle, .owner = "backend.pim.push.enabled", | ||
| 426 | .key = "davpush/enabled", .store = "QSettings", .defaultValue = "true", .availability = "backend"}, | ||
| 427 | {.id = "sync/push-system", .group = "push", | ||
| 428 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Use the system push service"), | ||
| 429 | .keywords = "kunifiedpush systemdienst | kunifiedpush system service", .kind = K::Toggle, | ||
| 430 | .owner = "backend.pim.push.useSystemService", .key = "davpush/useSystemService", .store = "QSettings", | ||
| 431 | .defaultValue = "true", .availability = "backend"}, | ||
| 432 | {.id = "sync/push-service", .group = "push", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Push service"), | ||
| 433 | .keywords = "ntfy dienst server zugangstoken | ntfy service server token", .kind = K::Editor, | ||
| 434 | .owner = "backend.pim.push.saveService", .key = "davpush/receiver", .store = "QSettings + keyring", | ||
| 435 | .availability = "backend"}, | ||
| 436 | {.id = "sync/push-collections", .group = "push", | ||
| 437 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Push per collection"), | ||
| 438 | .keywords = "pro kalender adressbuch einzeln | per calendar address book", .kind = K::List, | ||
| 439 | .owner = "backend.pim.push.calendars", .key = "davpush/policy", .store = "QSettings", .scope = S::Account, | ||
| 440 | .availability = "backend"}, | ||
| 441 | {.id = "sync/settings-sync", .group = "installations", | ||
| 442 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Share settings via a mail folder"), | ||
| 443 | .keywords = "einstellungen synchronisieren geräte | settings sync devices", .kind = K::Editor, | ||
| 444 | .owner = "backend.settings.settingsSync", .key = "sync/enabled, sync/accountId, sync/folder, sync/categories", | ||
| 445 | .store = "QSettings", .scope = S::Profile, .availability = "backend"}, | ||
| 446 | // Privacy | ||
| 447 | {.id = "privacy/remote-images", .group = "remote-content", | ||
| 448 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Images from the internet"), | ||
| 449 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Blocked images can be loaded per message."), | ||
| 450 | .keywords = "bilder externe inhalte nachladen verfolgung | images remote content load tracking", .kind = K::Choice, | ||
| 451 | .owner = "backend.settings.imagePolicyMode", .key = "view/externalContent", .store = "QSettings", | ||
| 452 | .defaultValue = "block", .values = "block|load", .syncCategory = "general", .availability = "backend"}, | ||
| 453 | {.id = "privacy/allowed-domains", .group = "remote-content", | ||
| 454 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Always load from these domains"), | ||
| 455 | .keywords = "erlaubte domains ausnahmen whitelist | allowed domains exceptions whitelist", .kind = K::List, | ||
| 456 | .owner = "backend.settings.imageWhitelist", .key = "external whitelist", .store = "mail cache", | ||
| 457 | .scope = S::Profile, | ||
| 458 | .availability = "backend"}, | ||
| 459 | {.id = "privacy/collect-addresses", .group = "collected-addresses", | ||
| 460 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Remember addresses I write to"), | ||
| 461 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "For the address completion; they stay on this computer."), | ||
| 462 | .keywords = "adressen merken sammeln | remember addresses collect", .kind = K::Toggle, | ||
| 463 | .owner = "backend.pim.contactActions.collectAddresses", .key = "contacts/collectAddresses", .store = "QSettings", | ||
| 464 | .defaultValue = "true", .availability = "backend"}, | ||
| 465 | {.id = "privacy/forget-collected", .group = "collected-addresses", | ||
| 466 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Forget collected addresses"), | ||
| 467 | .keywords = "vergessen löschen | forget delete", .kind = K::Action, | ||
| 468 | .owner = "backend.pim.contactActions.forgetCollected", | ||
| 469 | .store = "contact store", .scope = S::Profile, .availability = "backend"}, | ||
| 470 | // Sprint 103 S103.1.9 (D-10): online address lookup, off by default. | ||
| 471 | {.id = "privacy/place-lookup", .group = "address-lookup", | ||
| 472 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Look up street addresses online"), | ||
| 473 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Exact map positions; only the address is sent, never names."), | ||
| 474 | .keywords = "adresse nachschlagen geocoding nominatim position | address lookup geocoding nominatim position", | ||
| 475 | .kind = K::Toggle, .owner = "backend.pim.contactMap.onlineLookup", .key = "contacts/placeLookup", | ||
| 476 | .store = "QSettings", .defaultValue = "false", .availability = "backend"}, | ||
| 477 | {.id = "privacy/lookup-server", .group = "address-lookup", | ||
| 478 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Lookup server"), | ||
| 479 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "A Nominatim server (https); empty is OpenStreetMap."), | ||
| 480 | .keywords = "nominatim server adresse | nominatim server address", .kind = K::Text, | ||
| 481 | .owner = "backend.pim.contactMap.lookupServer", .key = "contacts/placeLookupServer", .store = "QSettings", | ||
| 482 | .values = "https://…", .availability = "backend"}, | ||
| 483 | // Sprint 103 S103.5.8 (I-8): suggestions from local data, off by default. | ||
| 484 | {.id = "privacy/graph-suggestions", .group = "relationship-suggestions", | ||
| 485 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Suggest relationships"), | ||
| 486 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "From mails and appointments you share; worked out here."), | ||
| 487 | .keywords = "beziehungsvorschläge beziehungen graph zusammen | suggested relationships graph together", .kind = K::Toggle, | ||
| 488 | .owner = "backend.pim.contactGraph.suggestions", .key = "contacts/graphSuggestions", .store = "QSettings", | ||
| 489 | .defaultValue = "false", .alsoIn = QT_TRANSLATE_NOOP("SettingsCatalog", "the graph's legend"), | ||
| 490 | .availability = "backend"}, | ||
| 491 | {.id = "privacy/forget-dismissed", .group = "relationship-suggestions", | ||
| 492 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Forget dismissed suggestions"), | ||
| 493 | .keywords = "beziehungsvorschläge abgelehnt vergessen | suggested dismissed forget", .kind = K::Action, | ||
| 494 | .owner = "backend.pim.contactGraph.forgetDismissedSuggestions", .store = "contact store", | ||
| 495 | .availability = "backend"}, | ||
| 496 | // Sprint 103 S103.4.10 (D-11): online map tiles, off by default. | ||
| 497 | {.id = "privacy/map-tiles", .group = "contact-map", | ||
| 498 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Map tiles from the internet"), | ||
| 499 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Streets on the contact map; the server sees the areas you view."), | ||
| 500 | .keywords = "kartenkacheln strassen online openstreetmap | map tiles streets online openstreetmap", .kind = K::Toggle, | ||
| 501 | .owner = "backend.pim.contactMap.onlineTiles", .key = "contacts/mapTiles", .store = "QSettings", | ||
| 502 | .defaultValue = "false", .availability = "backend"}, | ||
| 503 | // F103-24: the public styles of resources/contacts/map-styles.json, or an own server. | ||
| 504 | {.id = "privacy/map-tile-provider", .group = "contact-map", | ||
| 505 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Map provider"), | ||
| 506 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Community servers need no key; the others need a free API key."), | ||
| 507 | .keywords = "kartenanbieter anbieter carto thunderforest stadia maptiler | map provider carto thunderforest stadia maptiler", | ||
| 508 | .kind = K::Choice, .owner = "backend.pim.contactMap.tileProvider", .key = "contacts/mapTileStyle", | ||
| 509 | .store = "QSettings (the style's provider)", | ||
| 510 | .defaultValue = "osm", .values = "osm|carto|thunderforest|stadia|maptiler|custom", .availability = "backend"}, | ||
| 511 | {.id = "privacy/map-tile-style", .group = "contact-map", | ||
| 512 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Map style"), | ||
| 513 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Each provider sees the areas you view."), | ||
| 514 | .keywords = "kartenstil design aussehen topografie dunkel hell satellit | map style design look topographic dark light satellite", | ||
| 515 | .kind = K::Choice, .owner = "backend.pim.contactMap.tileStyle", .key = "contacts/mapTileStyle", .store = "QSettings", | ||
| 516 | .defaultValue = "osm", | ||
| 517 | // The style ids of resources/contacts/map-styles.json. | ||
| 518 | .values = "osm|osm-de|osm-fr|osm-humanitarian|cyclosm|opentopomap|opnvkarte|carto-voyager|" | ||
| 519 | "carto-light|carto-dark|thunderforest-cycle|thunderforest-transport|" | ||
| 520 | "thunderforest-transport-dark|thunderforest-landscape|thunderforest-outdoors|" | ||
| 521 | "thunderforest-atlas|stadia-smooth|stadia-smooth-dark|stadia-outdoors|stadia-osm-bright|" | ||
| 522 | "stadia-toner|stadia-terrain|stadia-watercolor|maptiler-streets|maptiler-outdoor|" | ||
| 523 | "maptiler-topo|maptiler-winter|maptiler-satellite|maptiler-hybrid|custom", | ||
| 524 | .availability = "backend"}, | ||
| 525 | {.id = "privacy/map-tile-key", .group = "contact-map", | ||
| 526 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "API key"), | ||
| 527 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "Kept on this computer only and sent with every map tile request."), | ||
| 528 | .keywords = "api schlüssel key zugangsschlüssel token | api key token", .kind = K::Text, | ||
| 529 | .owner = "backend.pim.contactMap.setTileKey", .key = "contacts/mapTileKeys/<provider>", .store = "QSettings", | ||
| 530 | .availability = "backend"}, | ||
| 531 | {.id = "privacy/map-tile-server", .group = "contact-map", | ||
| 532 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Tile server"), | ||
| 533 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "https with {z}, {x} and {y}; empty is OpenStreetMap."), | ||
| 534 | .keywords = "kachelserver server adresse | tile server address", .kind = K::Text, | ||
| 535 | .owner = "backend.pim.contactMap.tileServer", .key = "contacts/mapTileServer", .store = "QSettings", | ||
| 536 | .values = "https://…/{z}/{x}/{y}.png", .availability = "backend"}, | ||
| 537 | {.id = "privacy/clear-map-tiles", .group = "contact-map", | ||
| 538 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Clear map tile cache"), | ||
| 539 | .keywords = "kachel cache leeren löschen | tile cache clear delete", .kind = K::Action, | ||
| 540 | .owner = "backend.pim.contactMap.clearTileCache", .store = "tile cache", .availability = "backend"}, | ||
| 541 | {.id = "privacy/clear-command-history", .group = "command-history", | ||
| 542 | .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Clear command history"), | ||
| 543 | .description = QT_TRANSLATE_NOOP("SettingsCatalog", "The last 50 commands; searches and texts are never kept."), | ||
| 544 | .keywords = "befehlsverlauf befehlsleiste löschen | command bar history clear", .kind = K::Action, | ||
| 545 | .owner = "commands.clearHistory", .key = "commandbar/history", .store = "UiStateStore"}, | ||
| 546 | // About | ||
| 547 | {.id = "about/version", .group = "mailjd", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Version"), | ||
| 548 | .keywords = "versionsnummer commit | version number commit", .kind = K::Info, .owner = "about.version"}, | ||
| 549 | {.id = "about/license", .group = "mailjd", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "License"), | ||
| 550 | .keywords = "lizenz gpl freie software | license gpl free software", .kind = K::Info, .owner = "about"}, | ||
| 551 | {.id = "about/notices", .group = "mailjd", .label = QT_TRANSLATE_NOOP("SettingsCatalog", "Third-party notices"), | ||
| 552 | .keywords = "drittanbieter hinweise bibliotheken | third party notices libraries", .kind = K::Action, | ||
| 553 | .owner = "about.thirdPartyNotices"}, | ||
| 554 | 12 | }; | |
| 555 | } | ||
| 556 | |||
| 557 | 2854 | const char *kindName(SettingKind kind) { | |
| 558 |
9/10✓ Branch 2 → 3 taken 926 times.
✓ Branch 2 → 4 taken 895 times.
✓ Branch 2 → 5 taken 88 times.
✓ Branch 2 → 6 taken 152 times.
✓ Branch 2 → 7 taken 69 times.
✓ Branch 2 → 8 taken 233 times.
✓ Branch 2 → 9 taken 401 times.
✓ Branch 2 → 10 taken 31 times.
✓ Branch 2 → 11 taken 59 times.
✗ Branch 2 → 12 not taken.
|
2854 | switch (kind) { |
| 559 | 926 | case K::Toggle: return "toggle"; | |
| 560 | 895 | case K::Choice: return "choice"; | |
| 561 | 88 | case K::Number: return "number"; | |
| 562 | 152 | case K::Text: return "text"; | |
| 563 | 69 | case K::List: return "list"; | |
| 564 | 233 | case K::Action: return "action"; | |
| 565 | 401 | case K::Editor: return "editor"; | |
| 566 | 31 | case K::Link: return "link"; | |
| 567 | 59 | case K::Info: return "info"; | |
| 568 | } | ||
| 569 | ✗ | return ""; | |
| 570 | } | ||
| 571 | |||
| 572 | 3 | const char *scopeName(SettingScope scope) { | |
| 573 |
3/4✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 1 time.
✓ Branch 2 → 5 taken 1 time.
✗ Branch 2 → 6 not taken.
|
3 | switch (scope) { |
| 574 | 1 | case S::Application: return "application"; | |
| 575 | 1 | case S::Profile: return "profile"; | |
| 576 | 1 | case S::Account: return "account"; | |
| 577 | } | ||
| 578 | ✗ | return ""; | |
| 579 | } | ||
| 580 | |||
| 581 | // Words of a folded text, split at everything that is not a letter or digit. | ||
| 582 | 111331 | QStringList words(const QString &folded) { | |
| 583 |
4/7✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 15 taken 111329 times.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 15 not taken.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
|
111333 | static const QRegularExpression separator(QStringLiteral("[^\\p{L}\\p{N}]+")); |
| 584 |
1/1✓ Branch 16 → 17 taken 111331 times.
|
111331 | return folded.split(separator, Qt::SkipEmptyParts); |
| 585 | } | ||
| 586 | |||
| 587 | 54445 | bool anyWordStartsWith(const QStringList &candidates, const QString &prefix) { | |
| 588 | 54445 | return std::any_of(candidates.cbegin(), candidates.cend(), | |
| 589 | 305101 | [&](const QString &candidate) { return candidate.startsWith(prefix); }); | |
| 590 | } | ||
| 591 | |||
| 592 | // One searchable place: its own label/keywords/description and the names | ||
| 593 | // of the places around it. | ||
| 594 | struct Candidate { | ||
| 595 | QString place, kind, label, path; | ||
| 596 | QStringList labels; // folded labels (translated and English) | ||
| 597 | QStringList labelWords; | ||
| 598 | QStringList keywordWords; | ||
| 599 | QStringList contextWords; // group and page names | ||
| 600 | QStringList descriptionWords; | ||
| 601 | int order = 0; | ||
| 602 | int kindRank = 0; // ties: page, then group, then setting (the broader place first) | ||
| 603 | }; | ||
| 604 | |||
| 605 | 13796 | int wordScore(const Candidate &candidate, const QString &word) { | |
| 606 |
2/2✓ Branch 5 → 6 taken 61 times.
✓ Branch 5 → 7 taken 13735 times.
|
13796 | if (std::any_of(candidate.labels.cbegin(), candidate.labels.cend(), |
| 607 | 14272 | [&](const QString &label) { return label.startsWith(word); })) | |
| 608 | 61 | return 100; | |
| 609 |
2/2✓ Branch 8 → 9 taken 50 times.
✓ Branch 8 → 10 taken 13685 times.
|
13735 | if (anyWordStartsWith(candidate.labelWords, word)) return 80; |
| 610 |
2/2✓ Branch 11 → 12 taken 153 times.
✓ Branch 11 → 13 taken 13532 times.
|
13685 | if (anyWordStartsWith(candidate.keywordWords, word)) return 60; |
| 611 |
2/2✓ Branch 14 → 15 taken 39 times.
✓ Branch 14 → 16 taken 13493 times.
|
13532 | if (anyWordStartsWith(candidate.contextWords, word)) return 40; |
| 612 |
2/2✓ Branch 17 → 18 taken 9 times.
✓ Branch 17 → 19 taken 13484 times.
|
13493 | if (anyWordStartsWith(candidate.descriptionWords, word)) return 30; |
| 613 | 13484 | return 0; | |
| 614 | } | ||
| 615 | |||
| 616 | 13734 | void addLabel(Candidate &candidate, const char *source) { | |
| 617 | 41202 | for (const QString &label : {SettingsCatalog::fold(SettingsCatalog::text(source)), | |
| 618 |
6/10✓ Branch 2 → 3 taken 13734 times.
✓ Branch 3 → 4 taken 13734 times.
✓ Branch 5 → 6 taken 13734 times.
✓ Branch 6 → 7 taken 13734 times.
✓ Branch 21 → 12 taken 27468 times.
✓ Branch 21 → 22 taken 13734 times.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 40 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 40 not taken.
|
82404 | SettingsCatalog::fold(QString::fromUtf8(source))}) { |
| 619 |
2/2✓ Branch 13 → 14 taken 13258 times.
✓ Branch 13 → 15 taken 14210 times.
|
27468 | if (candidate.labels.contains(label)) continue; |
| 620 |
1/1✓ Branch 15 → 16 taken 14210 times.
|
14210 | candidate.labels << label; |
| 621 |
2/2✓ Branch 16 → 17 taken 14210 times.
✓ Branch 17 → 18 taken 14210 times.
|
14210 | candidate.labelWords << words(label); |
| 622 | 41202 | } | |
| 623 | 13734 | } | |
| 624 | |||
| 625 | 41638 | void addWords(QStringList &target, const char *source, bool translate) { | |
| 626 |
4/4✓ Branch 3 → 4 taken 41638 times.
✓ Branch 4 → 5 taken 41638 times.
✓ Branch 5 → 6 taken 41638 times.
✓ Branch 6 → 7 taken 41638 times.
|
41638 | target << words(SettingsCatalog::fold(QString::fromUtf8(source))); |
| 627 |
5/6✓ Branch 10 → 11 taken 41638 times.
✗ Branch 10 → 19 not taken.
✓ Branch 11 → 12 taken 41638 times.
✓ Branch 12 → 13 taken 41638 times.
✓ Branch 13 → 14 taken 41638 times.
✓ Branch 14 → 15 taken 41638 times.
|
41638 | if (translate) target << words(SettingsCatalog::fold(SettingsCatalog::text(source))); |
| 628 | 41638 | } | |
| 629 | |||
| 630 | 109 | QList<Candidate> candidates() { | |
| 631 | 109 | QList<Candidate> result; | |
| 632 | 109 | int order = 0; | |
| 633 |
3/3✓ Branch 2 → 3 taken 109 times.
✓ Branch 22 → 5 taken 1199 times.
✓ Branch 22 → 23 taken 109 times.
|
1308 | for (const auto &page : SettingsCatalog::pages()) { |
| 634 | 1199 | Candidate candidate{.place = QString::fromLatin1(page.id), .kind = QStringLiteral("page"), | |
| 635 |
3/9✓ Branch 7 → 8 taken 1199 times.
✓ Branch 11 → 12 taken 1199 times.
✓ Branch 12 → 13 taken 1199 times.
✗ Branch 127 → 128 not taken.
✗ Branch 127 → 129 not taken.
✗ Branch 130 → 131 not taken.
✗ Branch 130 → 132 not taken.
✗ Branch 136 → 137 not taken.
✗ Branch 136 → 138 not taken.
|
2398 | .label = SettingsCatalog::text(page.label), .path = SettingsCatalog::text(page.label)}; |
| 636 |
1/1✓ Branch 14 → 15 taken 1199 times.
|
1199 | addLabel(candidate, page.label); |
| 637 |
1/1✓ Branch 15 → 16 taken 1199 times.
|
1199 | candidate.keywordWords = SettingsCatalog::keywordWords(page.keywords); |
| 638 | 1199 | candidate.order = order++; | |
| 639 | 1199 | candidate.kindRank = 0; | |
| 640 |
1/1✓ Branch 18 → 19 taken 1199 times.
|
1199 | result << candidate; |
| 641 | 1199 | } | |
| 642 |
3/3✓ Branch 23 → 24 taken 109 times.
✓ Branch 68 → 26 taken 4251 times.
✓ Branch 68 → 69 taken 109 times.
|
4360 | for (const auto &group : SettingsCatalog::groups()) { |
| 643 |
2/2✓ Branch 28 → 29 taken 4251 times.
✓ Branch 29 → 30 taken 4251 times.
|
4251 | const auto *page = SettingsCatalog::findPage(QString::fromLatin1(group.page)); |
| 644 |
3/3✓ Branch 32 → 33 taken 4251 times.
✓ Branch 35 → 36 taken 4251 times.
✓ Branch 36 → 37 taken 4251 times.
|
8502 | Candidate candidate{.place = QString::fromLatin1(group.page) + '/' + QString::fromLatin1(group.id), |
| 645 | 4251 | .kind = QStringLiteral("group"), .label = SettingsCatalog::text(group.label), | |
| 646 |
6/12✓ Branch 37 → 38 taken 4251 times.
✓ Branch 41 → 42 taken 4251 times.
✓ Branch 42 → 43 taken 4251 times.
✓ Branch 46 → 47 taken 4251 times.
✓ Branch 47 → 48 taken 4251 times.
✓ Branch 48 → 49 taken 4251 times.
✗ Branch 164 → 165 not taken.
✗ Branch 164 → 166 not taken.
✗ Branch 167 → 168 not taken.
✗ Branch 167 → 169 not taken.
✗ Branch 173 → 174 not taken.
✗ Branch 173 → 175 not taken.
|
12753 | .path = SettingsCatalog::text(page->label) + QStringLiteral(" › ") + SettingsCatalog::text(group.label)}; |
| 647 |
1/1✓ Branch 58 → 59 taken 4251 times.
|
4251 | addLabel(candidate, group.label); |
| 648 |
1/1✓ Branch 59 → 60 taken 4251 times.
|
4251 | candidate.keywordWords = SettingsCatalog::keywordWords(group.keywords); |
| 649 |
1/1✓ Branch 62 → 63 taken 4251 times.
|
4251 | addWords(candidate.contextWords, page->label, true); |
| 650 |
1/1✓ Branch 63 → 64 taken 4251 times.
|
4251 | addWords(candidate.descriptionWords, group.lead, true); |
| 651 | 4251 | candidate.order = order++; | |
| 652 | 4251 | candidate.kindRank = 1; | |
| 653 |
1/1✓ Branch 64 → 65 taken 4251 times.
|
4251 | result << candidate; |
| 654 | 4251 | } | |
| 655 |
3/3✓ Branch 69 → 70 taken 109 times.
✓ Branch 124 → 72 taken 8284 times.
✓ Branch 124 → 125 taken 109 times.
|
8393 | for (const auto &setting : SettingsCatalog::settings()) { |
| 656 |
1/1✓ Branch 74 → 75 taken 8284 times.
|
8284 | const QString id = QString::fromLatin1(setting.id); |
| 657 |
2/2✓ Branch 77 → 78 taken 8284 times.
✓ Branch 78 → 79 taken 8284 times.
|
8284 | const auto *page = SettingsCatalog::findPage(id.section('/', 0, 0)); |
| 658 |
5/5✓ Branch 81 → 82 taken 8284 times.
✓ Branch 85 → 86 taken 8284 times.
✓ Branch 86 → 87 taken 8284 times.
✓ Branch 87 → 88 taken 8284 times.
✓ Branch 88 → 89 taken 8284 times.
|
16568 | const auto *group = SettingsCatalog::findGroup(id.section('/', 0, 0) + '/' + QString::fromLatin1(setting.group)); |
| 659 | ✗ | Candidate candidate{.place = id, .kind = QStringLiteral("setting"), .label = SettingsCatalog::text(setting.label), | |
| 660 |
5/11✓ Branch 97 → 98 taken 8284 times.
✓ Branch 98 → 99 taken 8284 times.
✓ Branch 102 → 103 taken 8284 times.
✓ Branch 103 → 104 taken 8284 times.
✓ Branch 104 → 105 taken 8284 times.
✗ Branch 230 → 231 not taken.
✗ Branch 230 → 232 not taken.
✗ Branch 233 → 234 not taken.
✗ Branch 233 → 235 not taken.
✗ Branch 239 → 240 not taken.
✗ Branch 239 → 241 not taken.
|
24852 | .path = SettingsCatalog::text(page->label) + QStringLiteral(" › ") + SettingsCatalog::text(group->label)}; |
| 661 |
1/1✓ Branch 111 → 112 taken 8284 times.
|
8284 | addLabel(candidate, setting.label); |
| 662 |
1/1✓ Branch 112 → 113 taken 8284 times.
|
8284 | candidate.keywordWords = SettingsCatalog::keywordWords(setting.keywords); |
| 663 |
1/1✓ Branch 115 → 116 taken 8284 times.
|
8284 | addWords(candidate.contextWords, page->label, true); |
| 664 |
1/1✓ Branch 116 → 117 taken 8284 times.
|
8284 | addWords(candidate.contextWords, group->label, true); |
| 665 |
1/1✓ Branch 117 → 118 taken 8284 times.
|
8284 | addWords(candidate.descriptionWords, setting.description, true); |
| 666 |
1/1✓ Branch 118 → 119 taken 8284 times.
|
8284 | addWords(candidate.descriptionWords, setting.alsoIn, true); |
| 667 | 8284 | candidate.order = order++; | |
| 668 | 8284 | candidate.kindRank = 2; | |
| 669 |
1/1✓ Branch 119 → 120 taken 8284 times.
|
8284 | result << candidate; |
| 670 | 8284 | } | |
| 671 | 109 | return result; | |
| 672 | ✗ | } | |
| 673 | } // namespace | ||
| 674 | |||
| 675 | 18460 | const QList<SettingsPageSpec> &SettingsCatalog::pages() { | |
| 676 |
4/7✓ Branch 2 → 3 taken 25 times.
✓ Branch 2 → 8 taken 18435 times.
✓ Branch 4 → 5 taken 25 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 25 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
18460 | static const QList<SettingsPageSpec> table = pageTable(); |
| 677 | 18460 | return table; | |
| 678 | } | ||
| 679 | |||
| 680 | 13558 | const QList<SettingsGroupSpec> &SettingsCatalog::groups() { | |
| 681 |
4/7✓ Branch 2 → 3 taken 15 times.
✓ Branch 2 → 8 taken 13543 times.
✓ Branch 4 → 5 taken 15 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 15 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
13558 | static const QList<SettingsGroupSpec> table = groupTable(); |
| 682 | 13558 | return table; | |
| 683 | } | ||
| 684 | |||
| 685 | 5770 | const QList<SettingSpec> &SettingsCatalog::settings() { | |
| 686 |
8/11✓ Branch 2 → 3 taken 12 times.
✓ Branch 2 → 17 taken 5758 times.
✓ Branch 4 → 5 taken 12 times.
✗ Branch 4 → 17 not taken.
✓ Branch 5 → 6 taken 12 times.
✓ Branch 6 → 7 taken 12 times.
✓ Branch 7 → 8 taken 12 times.
✓ Branch 8 → 9 taken 12 times.
✓ Branch 9 → 10 taken 12 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
5770 | static const QList<SettingSpec> table = accountSettings() + preferenceSettings() + systemSettings(); |
| 687 | 5770 | return table; | |
| 688 | } | ||
| 689 | |||
| 690 | 17516 | const SettingsPageSpec *SettingsCatalog::findPage(const QString &id) { | |
| 691 |
3/3✓ Branch 2 → 3 taken 17516 times.
✓ Branch 12 → 5 taken 112215 times.
✓ Branch 12 → 13 taken 2129 times.
|
114344 | for (const auto &page : pages()) |
| 692 |
2/2✓ Branch 8 → 9 taken 15387 times.
✓ Branch 8 → 10 taken 96828 times.
|
112215 | if (id == QLatin1String(page.id)) return &page; |
| 693 | 2129 | return nullptr; | |
| 694 | } | ||
| 695 | |||
| 696 | 12611 | const SettingsGroupSpec *SettingsCatalog::findGroup(const QString &place) { | |
| 697 |
2/2✓ Branch 4 → 5 taken 12611 times.
✓ Branch 7 → 8 taken 12611 times.
|
12611 | const QString page = place.section('/', 0, 0), id = place.section('/', 1); |
| 698 |
3/3✓ Branch 8 → 9 taken 12611 times.
✓ Branch 24 → 11 taken 298686 times.
✓ Branch 24 → 25 taken 2180 times.
|
300866 | for (const auto &group : groups()) |
| 699 |
6/6✓ Branch 14 → 15 taken 36713 times.
✓ Branch 14 → 19 taken 261973 times.
✓ Branch 17 → 18 taken 10431 times.
✓ Branch 17 → 19 taken 26282 times.
✓ Branch 20 → 21 taken 10431 times.
✓ Branch 20 → 22 taken 288255 times.
|
298686 | if (page == QLatin1String(group.page) && id == QLatin1String(group.id)) return &group; |
| 700 | 2180 | return nullptr; | |
| 701 | 12611 | } | |
| 702 | |||
| 703 | 5614 | const SettingSpec *SettingsCatalog::findSetting(const QString &id) { | |
| 704 |
3/3✓ Branch 2 → 3 taken 5614 times.
✓ Branch 12 → 5 taken 218336 times.
✓ Branch 12 → 13 taken 135 times.
|
218471 | for (const auto &setting : settings()) |
| 705 |
2/2✓ Branch 8 → 9 taken 5479 times.
✓ Branch 8 → 10 taken 212857 times.
|
218336 | if (id == QLatin1String(setting.id)) return &setting; |
| 706 | 135 | return nullptr; | |
| 707 | } | ||
| 708 | |||
| 709 | 127715 | QString SettingsCatalog::text(const char *source) { | |
| 710 |
3/4✓ Branch 2 → 3 taken 127715 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 104215 times.
✓ Branch 3 → 5 taken 23500 times.
|
127715 | return source && *source ? QCoreApplication::translate("SettingsCatalog", source) : QString{}; |
| 711 | } | ||
| 712 | |||
| 713 | 13735 | QStringList SettingsCatalog::keywordWords(const char *keywords) { | |
| 714 |
3/3✓ Branch 3 → 4 taken 13735 times.
✓ Branch 4 → 5 taken 13735 times.
✓ Branch 5 → 6 taken 13735 times.
|
13735 | return words(fold(QString::fromUtf8(keywords))); |
| 715 | } | ||
| 716 | |||
| 717 | 124590 | QString SettingsCatalog::fold(const QString &text) { | |
| 718 |
3/3✓ Branch 2 → 3 taken 124590 times.
✓ Branch 7 → 8 taken 124590 times.
✓ Branch 8 → 9 taken 124590 times.
|
249180 | QString decomposed = text.toLower().replace(QChar(0x00DF), QStringLiteral("ss")).normalized(QString::NormalizationForm_D); |
| 719 | 124590 | QString result; | |
| 720 |
1/1✓ Branch 13 → 14 taken 124590 times.
|
124590 | result.reserve(decomposed.size()); |
| 721 |
4/4✓ Branch 14 → 15 taken 124590 times.
✓ Branch 15 → 16 taken 124590 times.
✓ Branch 21 → 17 taken 1985341 times.
✓ Branch 21 → 22 taken 124590 times.
|
2109931 | for (const QChar c : decomposed) |
| 722 |
3/3✓ Branch 18 → 19 taken 1980327 times.
✓ Branch 18 → 20 taken 5014 times.
✓ Branch 19 → 20 taken 1980327 times.
|
1985341 | if (c.category() != QChar::Mark_NonSpacing) result += c; |
| 723 | 124590 | return result; | |
| 724 | 124590 | } | |
| 725 | |||
| 726 | 110 | QList<SettingsCatalog::SearchHit> SettingsCatalog::search(const QString &query, int limit) { | |
| 727 |
2/2✓ Branch 2 → 3 taken 110 times.
✓ Branch 3 → 4 taken 110 times.
|
110 | const QStringList queryWords = words(fold(query)); |
| 728 |
2/2✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 109 times.
|
110 | if (queryWords.isEmpty()) return {}; |
| 729 | struct Scored { int score; const Candidate *candidate; }; | ||
| 730 |
1/1✓ Branch 8 → 9 taken 109 times.
|
109 | const QList<Candidate> all = candidates(); // translations follow the current language |
| 731 | 109 | QList<Scored> scored; | |
| 732 |
2/2✓ Branch 26 → 11 taken 13734 times.
✓ Branch 26 → 27 taken 109 times.
|
13843 | for (const auto &candidate : all) { |
| 733 | 13734 | int total = 0; | |
| 734 | 13734 | bool every = true; | |
| 735 |
2/2✓ Branch 20 → 14 taken 13796 times.
✓ Branch 20 → 21 taken 250 times.
|
14046 | for (const auto &word : queryWords) { |
| 736 |
1/1✓ Branch 15 → 16 taken 13796 times.
|
13796 | const int score = wordScore(candidate, word); |
| 737 |
2/2✓ Branch 16 → 17 taken 13484 times.
✓ Branch 16 → 18 taken 312 times.
|
13796 | if (score == 0) { every = false; break; } |
| 738 | 312 | total += score; | |
| 739 | } | ||
| 740 |
3/3✓ Branch 21 → 22 taken 250 times.
✓ Branch 21 → 24 taken 13484 times.
✓ Branch 22 → 23 taken 250 times.
|
13734 | if (every) scored.append({total, &candidate}); |
| 741 | } | ||
| 742 |
3/3✓ Branch 27 → 28 taken 109 times.
✓ Branch 28 → 29 taken 109 times.
✓ Branch 29 → 30 taken 109 times.
|
109 | std::stable_sort(scored.begin(), scored.end(), [](const Scored &a, const Scored &b) { |
| 743 |
2/2✓ Branch 2 → 3 taken 102 times.
✓ Branch 2 → 4 taken 187 times.
|
289 | if (a.score != b.score) return a.score > b.score; |
| 744 |
2/2✓ Branch 4 → 5 taken 71 times.
✓ Branch 4 → 6 taken 116 times.
|
187 | if (a.candidate->kindRank != b.candidate->kindRank) return a.candidate->kindRank < b.candidate->kindRank; |
| 745 | 116 | return a.candidate->order < b.candidate->order; | |
| 746 | }); | ||
| 747 | 109 | QList<SearchHit> hits; | |
| 748 |
4/4✓ Branch 30 → 31 taken 109 times.
✓ Branch 31 → 32 taken 109 times.
✓ Branch 45 → 33 taken 233 times.
✓ Branch 45 → 46 taken 108 times.
|
341 | for (const auto &entry : scored) { |
| 749 |
2/2✓ Branch 35 → 36 taken 1 time.
✓ Branch 35 → 37 taken 232 times.
|
233 | if (hits.size() >= limit) break; |
| 750 | 232 | hits.append({entry.candidate->place, entry.candidate->kind, entry.candidate->label, entry.candidate->path, entry.score}); | |
| 751 | } | ||
| 752 | 109 | return hits; | |
| 753 | 342 | } | |
| 754 | |||
| 755 | 1 | QStringList SettingsCatalog::lint() { | |
| 756 |
3/7✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 15 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 15 not taken.
✓ Branch 9 → 10 taken 1 time.
✗ Branch 319 → 320 not taken.
✗ Branch 319 → 321 not taken.
|
2 | static const QRegularExpression idPattern(QStringLiteral("^[a-z]+(-[a-z]+)*$")); |
| 757 | 1 | QStringList problems; | |
| 758 | 1 | QSet<QString> places; | |
| 759 | 126 | const auto keywordsBothLanguages = [](const char *keywords) { | |
| 760 |
1/1✓ Branch 3 → 4 taken 126 times.
|
126 | const QString text = QString::fromUtf8(keywords); |
| 761 |
1/1✓ Branch 7 → 8 taken 126 times.
|
126 | const int bar = text.indexOf(QStringLiteral(" | ")); |
| 762 |
11/26✓ Branch 10 → 11 taken 126 times.
✗ Branch 10 → 20 not taken.
✓ Branch 11 → 12 taken 126 times.
✓ Branch 12 → 13 taken 126 times.
✓ Branch 14 → 15 taken 126 times.
✗ Branch 14 → 20 not taken.
✓ Branch 15 → 16 taken 126 times.
✓ Branch 16 → 17 taken 126 times.
✓ Branch 18 → 19 taken 126 times.
✗ Branch 18 → 20 not taken.
✓ Branch 22 → 23 taken 126 times.
✗ Branch 22 → 24 not taken.
✓ Branch 24 → 25 taken 126 times.
✗ Branch 24 → 26 not taken.
✓ Branch 26 → 27 taken 126 times.
✗ Branch 26 → 28 not taken.
✓ Branch 28 → 29 taken 126 times.
✗ Branch 28 → 30 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 42 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 46 not taken.
✗ Branch 48 → 49 not taken.
✗ Branch 48 → 50 not taken.
✗ Branch 52 → 53 not taken.
✗ Branch 52 → 54 not taken.
|
252 | return bar > 0 && !text.left(bar).trimmed().isEmpty() && !text.mid(bar + 3).trimmed().isEmpty(); |
| 763 | 126 | }; | |
| 764 |
3/3✓ Branch 16 → 17 taken 1 time.
✓ Branch 78 → 19 taken 11 times.
✓ Branch 78 → 79 taken 1 time.
|
12 | for (const auto &page : pages()) { |
| 765 |
1/1✓ Branch 21 → 22 taken 11 times.
|
11 | const QString id = QString::fromLatin1(page.id); |
| 766 |
3/6✓ Branch 23 → 24 taken 11 times.
✓ Branch 24 → 25 taken 11 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 31 taken 11 times.
✗ Branch 27 → 28 not taken.
✗ Branch 28 → 29 not taken.
|
11 | if (!idPattern.match(id).hasMatch()) problems << id + ": page ids are lowercase words joined by '-'"; |
| 767 |
1/4✗ Branch 32 → 33 not taken.
✓ Branch 32 → 37 taken 11 times.
✗ Branch 33 → 34 not taken.
✗ Branch 34 → 35 not taken.
|
11 | if (places.contains(id)) problems << id + ": duplicate place"; |
| 768 |
1/1✓ Branch 37 → 38 taken 11 times.
|
11 | places.insert(id); |
| 769 |
2/6✓ Branch 38 → 39 taken 11 times.
✗ Branch 38 → 40 not taken.
✗ Branch 39 → 40 not taken.
✓ Branch 39 → 44 taken 11 times.
✗ Branch 40 → 41 not taken.
✗ Branch 41 → 42 not taken.
|
11 | if (!*page.label || !page.glyph) problems << id + ": a page needs a label and a glyph"; |
| 770 |
2/5✓ Branch 44 → 45 taken 11 times.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 50 taken 11 times.
✗ Branch 46 → 47 not taken.
✗ Branch 47 → 48 not taken.
|
11 | if (!keywordsBothLanguages(page.keywords)) problems << id + ": keywords need German and English words"; |
| 771 |
8/14✓ Branch 51 → 52 taken 11 times.
✓ Branch 53 → 54 taken 8 times.
✓ Branch 53 → 63 taken 3 times.
✓ Branch 55 → 56 taken 8 times.
✓ Branch 57 → 58 taken 3 times.
✓ Branch 57 → 63 taken 5 times.
✓ Branch 68 → 69 taken 11 times.
✗ Branch 68 → 70 not taken.
✗ Branch 70 → 71 not taken.
✓ Branch 70 → 75 taken 11 times.
✗ Branch 346 → 347 not taken.
✗ Branch 346 → 348 not taken.
✗ Branch 352 → 353 not taken.
✗ Branch 352 → 354 not taken.
|
25 | if (QString::fromLatin1(page.block) != "main" && QString::fromLatin1(page.block) != "areas" && |
| 772 |
6/9✓ Branch 59 → 60 taken 3 times.
✗ Branch 61 → 62 not taken.
✓ Branch 61 → 63 taken 3 times.
✓ Branch 64 → 65 taken 3 times.
✓ Branch 64 → 66 taken 8 times.
✓ Branch 66 → 67 taken 8 times.
✓ Branch 66 → 68 taken 3 times.
✗ Branch 340 → 341 not taken.
✗ Branch 340 → 342 not taken.
|
14 | QString::fromLatin1(page.block) != "system") |
| 773 | ✗ | problems << id + ": unknown block"; | |
| 774 | 11 | } | |
| 775 | 1 | int leads = 0; | |
| 776 |
3/3✓ Branch 79 → 80 taken 1 time.
✓ Branch 137 → 82 taken 39 times.
✓ Branch 137 → 138 taken 1 time.
|
40 | for (const auto &group : groups()) { |
| 777 |
4/4✓ Branch 84 → 85 taken 39 times.
✓ Branch 87 → 88 taken 39 times.
✓ Branch 88 → 89 taken 39 times.
✓ Branch 89 → 90 taken 39 times.
|
39 | const QString place = QString::fromLatin1(group.page) + '/' + QString::fromLatin1(group.id); |
| 778 |
3/6✓ Branch 94 → 95 taken 39 times.
✓ Branch 95 → 96 taken 39 times.
✗ Branch 97 → 98 not taken.
✓ Branch 97 → 102 taken 39 times.
✗ Branch 98 → 99 not taken.
✗ Branch 99 → 100 not taken.
|
39 | if (!findPage(QString::fromLatin1(group.page))) problems << place + ": unknown page"; |
| 779 |
4/7✓ Branch 104 → 105 taken 39 times.
✓ Branch 105 → 106 taken 39 times.
✓ Branch 106 → 107 taken 39 times.
✗ Branch 109 → 110 not taken.
✓ Branch 109 → 114 taken 39 times.
✗ Branch 110 → 111 not taken.
✗ Branch 111 → 112 not taken.
|
39 | if (!idPattern.match(QString::fromLatin1(group.id)).hasMatch()) problems << place + ": bad group id"; |
| 780 |
1/4✗ Branch 115 → 116 not taken.
✓ Branch 115 → 120 taken 39 times.
✗ Branch 116 → 117 not taken.
✗ Branch 117 → 118 not taken.
|
39 | if (places.contains(place)) problems << place + ": duplicate place"; |
| 781 |
1/1✓ Branch 120 → 121 taken 39 times.
|
39 | places.insert(place); |
| 782 |
1/4✗ Branch 121 → 122 not taken.
✓ Branch 121 → 126 taken 39 times.
✗ Branch 122 → 123 not taken.
✗ Branch 123 → 124 not taken.
|
39 | if (!*group.label) problems << place + ": a group needs a label"; |
| 783 |
2/5✓ Branch 126 → 127 taken 39 times.
✗ Branch 127 → 128 not taken.
✓ Branch 127 → 132 taken 39 times.
✗ Branch 128 → 129 not taken.
✗ Branch 129 → 130 not taken.
|
39 | if (!keywordsBothLanguages(group.keywords)) problems << place + ": keywords need German and English words"; |
| 784 |
2/2✓ Branch 132 → 133 taken 2 times.
✓ Branch 132 → 134 taken 37 times.
|
39 | if (*group.lead) ++leads; |
| 785 | 39 | } | |
| 786 |
1/3✗ Branch 138 → 139 not taken.
✓ Branch 138 → 146 taken 1 time.
✗ Branch 142 → 143 not taken.
|
1 | if (leads > 6) problems << QStringLiteral("more than six group leads (§6.3)"); |
| 787 | 1 | QHash<QString, QSet<QString>> labelsPerPage; | |
| 788 |
3/3✓ Branch 146 → 147 taken 1 time.
✓ Branch 307 → 149 taken 76 times.
✓ Branch 307 → 308 taken 1 time.
|
77 | for (const auto &setting : settings()) { |
| 789 |
1/1✓ Branch 151 → 152 taken 76 times.
|
76 | const QString id = QString::fromLatin1(setting.id); |
| 790 |
1/1✓ Branch 154 → 155 taken 76 times.
|
76 | const QString page = id.section('/', 0, 0); |
| 791 |
2/5✓ Branch 155 → 156 taken 76 times.
✗ Branch 156 → 157 not taken.
✓ Branch 156 → 161 taken 76 times.
✗ Branch 157 → 158 not taken.
✗ Branch 158 → 159 not taken.
|
76 | if (!findPage(page)) problems << id + ": unknown page"; |
| 792 |
9/18✓ Branch 164 → 165 taken 76 times.
✓ Branch 165 → 166 taken 76 times.
✓ Branch 166 → 167 taken 76 times.
✓ Branch 167 → 168 taken 76 times.
✗ Branch 167 → 171 not taken.
✓ Branch 169 → 170 taken 76 times.
✗ Branch 170 → 171 not taken.
✓ Branch 170 → 172 taken 76 times.
✓ Branch 173 → 174 taken 76 times.
✗ Branch 173 → 175 not taken.
✓ Branch 175 → 176 taken 76 times.
✗ Branch 175 → 177 not taken.
✗ Branch 177 → 178 not taken.
✓ Branch 177 → 182 taken 76 times.
✗ Branch 422 → 423 not taken.
✗ Branch 422 → 424 not taken.
✗ Branch 426 → 427 not taken.
✗ Branch 426 → 428 not taken.
|
152 | if (!idPattern.match(id.section('/', 1)).hasMatch() || id.count('/') != 1) |
| 793 | ✗ | problems << id + ": a setting id is <page>/<lowercase-words>"; | |
| 794 |
5/8✓ Branch 183 → 184 taken 76 times.
✓ Branch 185 → 186 taken 76 times.
✓ Branch 186 → 187 taken 76 times.
✓ Branch 187 → 188 taken 76 times.
✗ Branch 191 → 192 not taken.
✓ Branch 191 → 196 taken 76 times.
✗ Branch 192 → 193 not taken.
✗ Branch 193 → 194 not taken.
|
76 | if (!findGroup(page + '/' + QString::fromLatin1(setting.group))) problems << id + ": unknown group"; |
| 795 |
1/4✗ Branch 197 → 198 not taken.
✓ Branch 197 → 202 taken 76 times.
✗ Branch 198 → 199 not taken.
✗ Branch 199 → 200 not taken.
|
76 | if (places.contains(id)) problems << id + ": duplicate place"; |
| 796 |
1/1✓ Branch 202 → 203 taken 76 times.
|
76 | places.insert(id); |
| 797 |
1/1✓ Branch 204 → 205 taken 76 times.
|
76 | const QString label = QString::fromUtf8(setting.label); |
| 798 |
1/4✗ Branch 206 → 207 not taken.
✓ Branch 206 → 211 taken 76 times.
✗ Branch 207 → 208 not taken.
✗ Branch 208 → 209 not taken.
|
76 | if (label.isEmpty()) problems << id + ": a setting needs a label"; |
| 799 |
1/4✗ Branch 212 → 213 not taken.
✓ Branch 212 → 217 taken 76 times.
✗ Branch 213 → 214 not taken.
✗ Branch 214 → 215 not taken.
|
76 | if (label.size() > 40) problems << id + ": label longer than 40 characters"; |
| 800 |
2/5✓ Branch 218 → 219 taken 76 times.
✗ Branch 221 → 222 not taken.
✓ Branch 221 → 226 taken 76 times.
✗ Branch 222 → 223 not taken.
✗ Branch 223 → 224 not taken.
|
76 | if (QString::fromUtf8(setting.description).size() > 90) problems << id + ": description longer than 90 characters"; |
| 801 |
2/5✓ Branch 226 → 227 taken 76 times.
✗ Branch 228 → 229 not taken.
✓ Branch 228 → 233 taken 76 times.
✗ Branch 229 → 230 not taken.
✗ Branch 230 → 231 not taken.
|
76 | if (labelsPerPage[page].contains(label)) problems << id + ": two settings with the same label on one page"; |
| 802 |
2/2✓ Branch 233 → 234 taken 76 times.
✓ Branch 234 → 235 taken 76 times.
|
76 | labelsPerPage[page].insert(label); |
| 803 |
2/5✓ Branch 235 → 236 taken 76 times.
✗ Branch 236 → 237 not taken.
✓ Branch 236 → 241 taken 76 times.
✗ Branch 237 → 238 not taken.
✗ Branch 238 → 239 not taken.
|
76 | if (!keywordsBothLanguages(setting.keywords)) problems << id + ": keywords need German and English words"; |
| 804 |
6/6✓ Branch 241 → 242 taken 54 times.
✓ Branch 241 → 245 taken 22 times.
✓ Branch 242 → 243 taken 33 times.
✓ Branch 242 → 245 taken 21 times.
✓ Branch 243 → 244 taken 31 times.
✓ Branch 243 → 245 taken 2 times.
|
107 | const bool stored = setting.kind == K::Toggle || setting.kind == K::Choice || setting.kind == K::Number || |
| 805 |
2/2✓ Branch 244 → 245 taken 4 times.
✓ Branch 244 → 246 taken 27 times.
|
31 | setting.kind == K::Text; |
| 806 |
5/8✓ Branch 247 → 248 taken 49 times.
✓ Branch 247 → 255 taken 27 times.
✓ Branch 248 → 249 taken 49 times.
✗ Branch 248 → 251 not taken.
✓ Branch 249 → 250 taken 49 times.
✗ Branch 249 → 251 not taken.
✗ Branch 250 → 251 not taken.
✓ Branch 250 → 255 taken 49 times.
|
76 | if (stored && (!*setting.key || !*setting.store || !*setting.owner)) |
| 807 | ✗ | problems << id + ": a stored setting names its owner, key and store"; | |
| 808 |
5/6✓ Branch 255 → 256 taken 55 times.
✓ Branch 255 → 257 taken 21 times.
✓ Branch 256 → 257 taken 2 times.
✓ Branch 256 → 262 taken 53 times.
✗ Branch 257 → 258 not taken.
✓ Branch 257 → 262 taken 23 times.
|
76 | if ((setting.kind == K::Choice || setting.kind == K::Number) && !*setting.values) |
| 809 | ✗ | problems << id + ": choices and numbers name their values"; | |
| 810 |
6/9✓ Branch 262 → 263 taken 22 times.
✓ Branch 262 → 272 taken 54 times.
✓ Branch 264 → 265 taken 22 times.
✓ Branch 266 → 267 taken 10 times.
✓ Branch 266 → 272 taken 12 times.
✗ Branch 277 → 278 not taken.
✓ Branch 277 → 282 taken 76 times.
✗ Branch 485 → 486 not taken.
✗ Branch 485 → 487 not taken.
|
162 | if (setting.kind == K::Toggle && QString::fromLatin1(setting.defaultValue) != "true" && |
| 811 |
6/9✓ Branch 268 → 269 taken 10 times.
✗ Branch 270 → 271 not taken.
✓ Branch 270 → 272 taken 10 times.
✓ Branch 273 → 274 taken 10 times.
✓ Branch 273 → 275 taken 66 times.
✓ Branch 275 → 276 taken 22 times.
✓ Branch 275 → 277 taken 54 times.
✗ Branch 479 → 480 not taken.
✗ Branch 479 → 481 not taken.
|
86 | QString::fromLatin1(setting.defaultValue) != "false") |
| 812 | ✗ | problems << id + ": a toggle defaults to true or false"; | |
| 813 |
8/12✓ Branch 282 → 283 taken 1 time.
✓ Branch 282 → 288 taken 75 times.
✓ Branch 284 → 285 taken 1 time.
✓ Branch 285 → 286 taken 1 time.
✗ Branch 286 → 287 not taken.
✓ Branch 286 → 288 taken 1 time.
✓ Branch 289 → 290 taken 1 time.
✓ Branch 289 → 291 taken 75 times.
✗ Branch 291 → 292 not taken.
✓ Branch 291 → 296 taken 76 times.
✗ Branch 494 → 495 not taken.
✗ Branch 494 → 496 not taken.
|
76 | if (setting.kind == K::Link && !findSetting(QString::fromLatin1(setting.target))) |
| 814 | ✗ | problems << id + ": a link names an existing setting"; | |
| 815 |
3/6✓ Branch 296 → 297 taken 75 times.
✓ Branch 296 → 302 taken 1 time.
✗ Branch 297 → 298 not taken.
✓ Branch 297 → 302 taken 75 times.
✗ Branch 298 → 299 not taken.
✗ Branch 299 → 300 not taken.
|
76 | if (setting.kind != K::Link && *setting.target) problems << id + ": only links have a target"; |
| 816 | 76 | } | |
| 817 | 1 | return problems; | |
| 818 | 1 | } | |
| 819 | |||
| 820 | 1 | QString SettingsCatalog::referenceSnapshot() { | |
| 821 | 1 | QString result = QStringLiteral( | |
| 822 | "# Settings reference\n\n" | ||
| 823 | "Generated from `SettingsCatalog::referenceSnapshot()` (`src/presentation/SettingsCatalog.cpp`);\n" | ||
| 824 | "`test_settings_catalog` fails when this file is stale. Every setting has one home\n" | ||
| 825 | "(page › group); *Also in* lists other places that change the same value; *Synchronised*\n" | ||
| 826 | "names the category of settings sync between installations (empty = this computer only).\n" | ||
| 827 | "The place (`page/name`) opens the setting: `settings <place>` in the command bar.\n" | ||
| 828 | "How to open, search and leave the settings: [user guide](user/CONFIGURATION.md#settings).\n"); | ||
| 829 |
3/3✓ Branch 6 → 7 taken 1 time.
✓ Branch 183 → 9 taken 11 times.
✓ Branch 183 → 184 taken 1 time.
|
12 | for (const auto &page : pages()) { |
| 830 |
4/4✓ Branch 14 → 15 taken 11 times.
✓ Branch 16 → 17 taken 11 times.
✓ Branch 17 → 18 taken 11 times.
✓ Branch 18 → 19 taken 11 times.
|
11 | result += QStringLiteral("\n## %1 (`%2`)\n").arg(QString::fromUtf8(page.label), QString::fromLatin1(page.id)); |
| 831 |
3/3✓ Branch 24 → 25 taken 11 times.
✓ Branch 180 → 27 taken 429 times.
✓ Branch 180 → 181 taken 11 times.
|
440 | for (const auto &group : groups()) { |
| 832 |
2/2✓ Branch 31 → 32 taken 390 times.
✓ Branch 31 → 33 taken 39 times.
|
429 | if (QLatin1String(group.page) != QLatin1String(page.id)) continue; |
| 833 |
2/2✓ Branch 42 → 43 taken 39 times.
✓ Branch 43 → 44 taken 39 times.
|
156 | result += QStringLiteral("\n### %1%2\n\n").arg(QString::fromUtf8(group.label), |
| 834 |
3/7✗ Branch 36 → 37 not taken.
✓ Branch 36 → 40 taken 39 times.
✓ Branch 44 → 45 taken 39 times.
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 39 times.
✗ Branch 262 → 263 not taken.
✗ Branch 262 → 264 not taken.
|
117 | group.advanced ? QStringLiteral(" (Advanced)") : QString{}); |
| 835 |
5/5✓ Branch 52 → 53 taken 2 times.
✓ Branch 52 → 65 taken 37 times.
✓ Branch 57 → 58 taken 2 times.
✓ Branch 58 → 59 taken 2 times.
✓ Branch 59 → 60 taken 2 times.
|
41 | if (*group.lead) result += QString::fromUtf8(group.lead) + QStringLiteral("\n\n"); |
| 836 |
1/1✓ Branch 68 → 69 taken 39 times.
|
39 | result += QStringLiteral("| Place | Setting | Kind | Default | Values | Stored in | Also in | Synchronised |\n" |
| 837 | "|---|---|---|---|---|---|---|---|\n"); | ||
| 838 |
3/3✓ Branch 71 → 72 taken 39 times.
✓ Branch 176 → 74 taken 2964 times.
✓ Branch 176 → 177 taken 39 times.
|
3003 | for (const auto &setting : settings()) { |
| 839 |
1/1✓ Branch 76 → 77 taken 2964 times.
|
2964 | const QString id = QString::fromLatin1(setting.id); |
| 840 |
8/11✓ Branch 80 → 81 taken 2964 times.
✓ Branch 82 → 83 taken 337 times.
✓ Branch 82 → 87 taken 2627 times.
✓ Branch 86 → 87 taken 261 times.
✓ Branch 86 → 88 taken 76 times.
✓ Branch 89 → 90 taken 2964 times.
✗ Branch 89 → 91 not taken.
✓ Branch 91 → 92 taken 2888 times.
✓ Branch 91 → 93 taken 76 times.
✗ Branch 296 → 297 not taken.
✗ Branch 296 → 298 not taken.
|
5928 | if (id.section('/', 0, 0) != QLatin1String(page.id) || QLatin1String(setting.group) != QLatin1String(group.id)) |
| 841 | 2888 | continue; | |
| 842 |
1/1✓ Branch 94 → 95 taken 76 times.
|
76 | QString label = QString::fromUtf8(setting.label); |
| 843 |
5/5✓ Branch 95 → 96 taken 34 times.
✓ Branch 95 → 108 taken 42 times.
✓ Branch 97 → 98 taken 34 times.
✓ Branch 101 → 102 taken 34 times.
✓ Branch 102 → 103 taken 34 times.
|
110 | if (*setting.description) label += QStringLiteral(" — ") + QString::fromUtf8(setting.description); |
| 844 |
8/16✓ Branch 113 → 114 taken 58 times.
✓ Branch 115 → 116 taken 58 times.
✓ Branch 121 → 122 taken 58 times.
✓ Branch 121 → 123 taken 18 times.
✓ Branch 123 → 124 taken 58 times.
✓ Branch 123 → 125 taken 18 times.
✓ Branch 125 → 126 taken 58 times.
✓ Branch 125 → 127 taken 18 times.
✗ Branch 318 → 319 not taken.
✗ Branch 318 → 320 not taken.
✗ Branch 323 → 324 not taken.
✗ Branch 323 → 325 not taken.
✗ Branch 328 → 329 not taken.
✗ Branch 328 → 330 not taken.
✗ Branch 332 → 333 not taken.
✗ Branch 332 → 334 not taken.
|
250 | const QString key = *setting.key ? QStringLiteral("`%1` (%2)").arg(QString::fromUtf8(setting.key), QString::fromUtf8(setting.store)) |
| 845 |
6/6✓ Branch 108 → 109 taken 58 times.
✓ Branch 108 → 117 taken 18 times.
✓ Branch 116 → 119 taken 58 times.
✓ Branch 118 → 119 taken 18 times.
✓ Branch 119 → 120 taken 58 times.
✓ Branch 119 → 121 taken 18 times.
|
250 | : QString::fromUtf8(setting.store); |
| 846 | 152 | result += QStringLiteral("| `%1` | %2 | %3 | %4 | %5 | %6 | %7 | %8 |\n") | |
| 847 |
3/3✓ Branch 140 → 141 taken 76 times.
✓ Branch 149 → 150 taken 76 times.
✓ Branch 150 → 151 taken 76 times.
|
228 | .arg(id, label, QString::fromLatin1(kindName(setting.kind)), |
| 848 |
9/13✓ Branch 141 → 142 taken 45 times.
✓ Branch 141 → 146 taken 31 times.
✓ Branch 143 → 144 taken 45 times.
✓ Branch 144 → 145 taken 45 times.
✓ Branch 145 → 147 taken 45 times.
✓ Branch 155 → 156 taken 45 times.
✓ Branch 155 → 157 taken 31 times.
✓ Branch 157 → 158 taken 45 times.
✓ Branch 157 → 159 taken 31 times.
✗ Branch 345 → 346 not taken.
✗ Branch 345 → 347 not taken.
✗ Branch 349 → 350 not taken.
✗ Branch 349 → 351 not taken.
|
152 | *setting.defaultValue ? "`" + QString::fromUtf8(setting.defaultValue) + "`" : QString{}, |
| 849 |
1/1✓ Branch 135 → 136 taken 76 times.
|
228 | QString::fromUtf8(setting.values).replace('|', QStringLiteral(" ∣ ")), key, |
| 850 |
3/3✓ Branch 131 → 132 taken 76 times.
✓ Branch 133 → 134 taken 76 times.
✓ Branch 151 → 152 taken 76 times.
|
228 | QString::fromUtf8(setting.alsoIn), QString::fromLatin1(setting.syncCategory)); |
| 851 | 2964 | } | |
| 852 | } | ||
| 853 | } | ||
| 854 |
1/1✓ Branch 187 → 188 taken 1 time.
|
1 | result += QStringLiteral("\n## Scopes\n\n"); |
| 855 |
2/2✓ Branch 234 → 192 taken 3 times.
✓ Branch 234 → 235 taken 1 time.
|
4 | for (const auto scope : {S::Application, S::Profile, S::Account}) { |
| 856 | 3 | QStringList ids; | |
| 857 |
3/3✓ Branch 192 → 193 taken 3 times.
✓ Branch 212 → 195 taken 228 times.
✓ Branch 212 → 213 taken 3 times.
|
231 | for (const auto &setting : settings()) |
| 858 |
5/5✓ Branch 196 → 197 taken 76 times.
✓ Branch 196 → 210 taken 152 times.
✓ Branch 202 → 203 taken 76 times.
✓ Branch 203 → 204 taken 76 times.
✓ Branch 204 → 205 taken 76 times.
|
380 | if (setting.scope == scope) ids << QStringLiteral("`%1`").arg(QString::fromLatin1(setting.id)); |
| 859 |
4/4✓ Branch 219 → 220 taken 3 times.
✓ Branch 222 → 223 taken 3 times.
✓ Branch 223 → 224 taken 3 times.
✓ Branch 224 → 225 taken 3 times.
|
6 | result += QStringLiteral("- **%1**: %2\n").arg(QString::fromLatin1(scopeName(scope)), ids.join(QStringLiteral(", "))); |
| 860 | 3 | } | |
| 861 | 1 | return result; | |
| 862 | ✗ | } | |
| 863 | |||
| 864 | 831 | QVariantList SettingsCatalog::pageList() const { | |
| 865 | 831 | QVariantList result; | |
| 866 |
3/3✓ Branch 2 → 3 taken 831 times.
✓ Branch 28 → 5 taken 9141 times.
✓ Branch 28 → 29 taken 831 times.
|
9972 | for (const auto &page : pages()) |
| 867 |
1/1✓ Branch 7 → 8 taken 9141 times.
|
27423 | result << QVariantMap{{"id", QString::fromLatin1(page.id)}, {"label", text(page.label)}, |
| 868 |
4/6✓ Branch 13 → 14 taken 9141 times.
✓ Branch 17 → 18 taken 9141 times.
✓ Branch 21 → 22 taken 36564 times.
✓ Branch 21 → 23 taken 9141 times.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 38 not taken.
|
73128 | {"glyph", page.glyph}, {"block", QString::fromLatin1(page.block)}}; |
| 869 | 831 | return result; | |
| 870 | 27423 | } | |
| 871 | |||
| 872 | 825 | QVariantList SettingsCatalog::groupList(const QString &page) const { | |
| 873 | 825 | QVariantList result; | |
| 874 |
3/3✓ Branch 2 → 3 taken 825 times.
✓ Branch 40 → 5 taken 32175 times.
✓ Branch 40 → 41 taken 825 times.
|
33000 | for (const auto &group : groups()) |
| 875 |
2/2✓ Branch 8 → 9 taken 3639 times.
✓ Branch 8 → 38 taken 28536 times.
|
32175 | if (page == QLatin1String(group.page)) |
| 876 |
4/4✓ Branch 10 → 11 taken 3639 times.
✓ Branch 13 → 14 taken 3639 times.
✓ Branch 15 → 16 taken 3639 times.
✓ Branch 16 → 17 taken 3639 times.
|
14556 | result << QVariantMap{{"id", QString::fromLatin1(group.id)}, {"place", page + '/' + QString::fromLatin1(group.id)}, |
| 877 |
3/5✓ Branch 25 → 26 taken 3639 times.
✓ Branch 29 → 30 taken 18195 times.
✓ Branch 29 → 31 taken 3639 times.
✗ Branch 48 → 49 not taken.
✗ Branch 48 → 50 not taken.
|
29112 | {"label", text(group.label)}, {"lead", text(group.lead)}, {"advanced", group.advanced}}; |
| 878 | 825 | return result; | |
| 879 | 10917 | } | |
| 880 | |||
| 881 | 2778 | QVariantMap SettingsCatalog::setting(const QString &id) const { | |
| 882 | 2778 | const auto *spec = findSetting(id); | |
| 883 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2778 times.
|
2778 | if (!spec) return {}; |
| 884 |
1/1✓ Branch 7 → 8 taken 2778 times.
|
5556 | return {{"id", id}, {"group", QString::fromLatin1(spec->group)}, {"label", text(spec->label)}, |
| 885 |
1/1✓ Branch 15 → 16 taken 2778 times.
|
5556 | {"description", text(spec->description)}, {"kind", QString::fromLatin1(kindName(spec->kind))}, |
| 886 |
1/1✓ Branch 18 → 19 taken 2778 times.
|
5556 | {"syncCategory", QString::fromLatin1(spec->syncCategory)}, {"alsoIn", text(spec->alsoIn)}, |
| 887 |
2/2✓ Branch 23 → 24 taken 2778 times.
✓ Branch 26 → 27 taken 2778 times.
|
8334 | {"availability", QString::fromLatin1(spec->availability)}, {"target", QString::fromLatin1(spec->target)}, |
| 888 |
3/5✓ Branch 29 → 30 taken 2778 times.
✓ Branch 33 → 34 taken 27780 times.
✓ Branch 33 → 35 taken 2778 times.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 49 not taken.
|
36114 | {"defaultValue", QString::fromUtf8(spec->defaultValue)}}; |
| 889 | 19446 | } | |
| 890 | |||
| 891 | 2376 | QVariantMap SettingsCatalog::place(const QString &id) const { | |
| 892 |
2/2✓ Branch 3 → 4 taken 249 times.
✓ Branch 3 → 21 taken 2127 times.
|
2376 | if (const auto *page = findPage(id)) |
| 893 | 249 | return {{"id", id}, {"kind", "page"}, {"page", id}, {"group", QString()}, {"label", text(page->label)}, | |
| 894 |
2/4✓ Branch 15 → 16 taken 1494 times.
✓ Branch 15 → 17 taken 249 times.
✗ Branch 109 → 110 not taken.
✗ Branch 109 → 111 not taken.
|
1992 | {"path", text(page->label)}}; |
| 895 |
1/2✗ Branch 22 → 23 not taken.
✓ Branch 22 → 56 taken 2127 times.
|
2127 | if (const auto *group = findGroup(id)) { |
| 896 | ✗ | const auto *page = findPage(QString::fromLatin1(group->page)); | |
| 897 | ✗ | return {{"id", id}, {"kind", "group"}, {"page", QString::fromLatin1(group->page)}, {"group", id}, | |
| 898 | ✗ | {"label", text(group->label)}, {"path", text(page->label) + QStringLiteral(" › ") + text(group->label)}}; | |
| 899 | } | ||
| 900 |
2/2✓ Branch 57 → 58 taken 2061 times.
✓ Branch 57 → 106 taken 66 times.
|
2127 | if (const auto *setting = findSetting(id)) { |
| 901 |
1/1✓ Branch 60 → 61 taken 2061 times.
|
2061 | const QString page = id.section('/', 0, 0); |
| 902 |
4/4✓ Branch 62 → 63 taken 2061 times.
✓ Branch 64 → 65 taken 2061 times.
✓ Branch 65 → 66 taken 2061 times.
✓ Branch 66 → 67 taken 2061 times.
|
2061 | const auto *group = findGroup(page + '/' + QString::fromLatin1(setting->group)); |
| 903 |
3/3✓ Branch 74 → 75 taken 2061 times.
✓ Branch 76 → 77 taken 2061 times.
✓ Branch 77 → 78 taken 2061 times.
|
4122 | return {{"id", id}, {"kind", "setting"}, {"page", page}, {"group", page + '/' + QString::fromLatin1(setting->group)}, |
| 904 | 2061 | {"label", text(setting->label)}, | |
| 905 |
6/8✓ Branch 85 → 86 taken 2061 times.
✓ Branch 86 → 87 taken 2061 times.
✓ Branch 87 → 88 taken 2061 times.
✓ Branch 88 → 89 taken 2061 times.
✓ Branch 92 → 93 taken 12366 times.
✓ Branch 92 → 94 taken 2061 times.
✗ Branch 180 → 181 not taken.
✗ Branch 180 → 182 not taken.
|
16488 | {"path", text(findPage(page)->label) + QStringLiteral(" › ") + text(group->label)}}; |
| 906 | 2061 | } | |
| 907 | 66 | return {}; | |
| 908 | 6432 | } | |
| 909 | |||
| 910 | 4 | QVariantList SettingsCatalog::searchPlaces(const QString &query) const { | |
| 911 | 4 | QVariantList result; | |
| 912 |
5/5✓ Branch 2 → 3 taken 4 times.
✓ Branch 3 → 4 taken 4 times.
✓ Branch 4 → 5 taken 4 times.
✓ Branch 21 → 6 taken 12 times.
✓ Branch 21 → 22 taken 4 times.
|
16 | for (const auto &hit : search(query)) |
| 913 |
3/5✓ Branch 13 → 14 taken 12 times.
✓ Branch 17 → 18 taken 48 times.
✓ Branch 17 → 19 taken 12 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
|
64 | result << QVariantMap{{"place", hit.place}, {"kind", hit.kind}, {"label", hit.label}, {"path", hit.path}}; |
| 914 | 4 | return result; | |
| 915 | 12 | } | |
| 916 | |||
| 917 |
4/4✓ Branch 2 → 3 taken 2288 times.
✓ Branch 4 → 5 taken 2288 times.
✓ Branch 5 → 6 taken 2288 times.
✓ Branch 6 → 7 taken 2288 times.
|
2288 | QString SettingsCatalog::label(const QString &id) const { return place(id).value("label").toString(); } |
| 918 | |||
| 919 | 655 | QString SettingsCatalog::description(const QString &id) const { | |
| 920 | 655 | const auto *spec = findSetting(id); | |
| 921 |
2/2✓ Branch 3 → 4 taken 628 times.
✓ Branch 3 → 5 taken 27 times.
|
655 | return spec ? text(spec->description) : QString{}; |
| 922 | } | ||
| 923 |