Changeset View
Standalone View
kcms/access/kcmaccess.cpp
Show All 23 Lines | |||||
24 | #include <stdlib.h> | 24 | #include <stdlib.h> | ||
25 | #include <math.h> | 25 | #include <math.h> | ||
26 | 26 | | |||
27 | #include <QFileDialog> | 27 | #include <QFileDialog> | ||
28 | #include <QStandardPaths> | 28 | #include <QStandardPaths> | ||
29 | #include <QProcess> | 29 | #include <QProcess> | ||
30 | #include <QX11Info> | 30 | #include <QX11Info> | ||
31 | 31 | | |||
32 | #include <kaboutdata.h> | 32 | #include <KAboutData> | ||
33 | #include <KConfigGroup> | 33 | #include <KConfigGroup> | ||
34 | #include <KSharedConfig> | 34 | #include <KSharedConfig> | ||
35 | #include <kkeyserver.h> | 35 | #include <KKeyServer> | ||
36 | #include <knotifyconfigwidget.h> | 36 | #include <KNotifyConfigWidget> | ||
37 | #include <KPluginFactory> | 37 | #include <KPluginFactory> | ||
38 | #include <ktoolinvocation.h> | 38 | #include <KToolInvocation> | ||
39 | #include <KLocalizedString> | ||||
40 | #include <QFileDialog> | ||||
41 | #include <QWindow> | ||||
42 | #include <QQuickItem> | ||||
43 | #include <QQuickRenderControl> | ||||
39 | 44 | | |||
40 | #include <X11/Xlib.h> | 45 | #include <X11/Xlib.h> | ||
41 | #include <X11/XKBlib.h> | 46 | #include <X11/XKBlib.h> | ||
42 | #define XK_MISCELLANY | 47 | #define XK_MISCELLANY | ||
43 | #define XK_XKB_KEYS | 48 | #define XK_XKB_KEYS | ||
44 | #include <X11/keysymdef.h> | 49 | #include <X11/keysymdef.h> | ||
45 | 50 | | |||
46 | K_PLUGIN_FACTORY(KAccessConfigFactory, registerPlugin<KAccessConfig>();) | 51 | #include "kcmaccessibilitybell.h" | ||
52 | #include "kcmaccessibilitykeyboard.h" | ||||
53 | #include "kcmaccessibilitymouse.h" | ||||
54 | #include "kcmaccessibilityscreenreader.h" | ||||
55 | | ||||
56 | K_PLUGIN_FACTORY_WITH_JSON(KCMAccessFactory, "kcmaccess.json", registerPlugin<KAccessConfig>();) | ||||
47 | 57 | | |||
48 | QString mouseKeysShortcut(Display *display) | 58 | QString mouseKeysShortcut(Display *display) | ||
49 | { | 59 | { | ||
50 | // Calculate the keycode | 60 | // Calculate the keycode | ||
51 | KeySym sym = XK_MouseKeys_Enable; | 61 | KeySym sym = XK_MouseKeys_Enable; | ||
52 | KeyCode code = XKeysymToKeycode(display, sym); | 62 | KeyCode code = XKeysymToKeycode(display, sym); | ||
53 | if (code == 0) { | 63 | if (code == 0) { | ||
54 | sym = XK_Pointer_EnableKeys; | 64 | sym = XK_Pointer_EnableKeys; | ||
▲ Show 20 Lines • Show All 71 Lines • ▼ Show 20 Line(s) | 135 | if ((modifiers & WinMask) != 0) | |||
126 | keyname = QKeySequence(Qt::META).toString() + QLatin1Char('+') + keyname; | 136 | keyname = QKeySequence(Qt::META).toString() + QLatin1Char('+') + keyname; | ||
127 | if ((modifiers & AltMask) != 0) | 137 | if ((modifiers & AltMask) != 0) | ||
128 | keyname = QKeySequence(Qt::ALT).toString() + QLatin1Char('+') + keyname; | 138 | keyname = QKeySequence(Qt::ALT).toString() + QLatin1Char('+') + keyname; | ||
129 | if ((modifiers & ControlMask) != 0) | 139 | if ((modifiers & ControlMask) != 0) | ||
130 | keyname = QKeySequence(Qt::CTRL).toString() + QLatin1Char('+') + keyname; | 140 | keyname = QKeySequence(Qt::CTRL).toString() + QLatin1Char('+') + keyname; | ||
131 | if ((modifiers & ShiftMask) != 0) | 141 | if ((modifiers & ShiftMask) != 0) | ||
132 | keyname = QKeySequence(Qt::SHIFT).toString() + QLatin1Char('+') + keyname; | 142 | keyname = QKeySequence(Qt::SHIFT).toString() + QLatin1Char('+') + keyname; | ||
133 | 143 | | |||
134 | QString result; | 144 | return modifiers & (ScrollMask | LockMask | NumMask) ? i18n("Press %1 while NumLock, CapsLock and ScrollLock are active", keyname) | ||
135 | if ((modifiers & ScrollMask) != 0) | 145 | : modifiers & (ScrollMask | LockMask) ? i18n("Press %1 while CapsLock and ScrollLock are active", keyname) | ||
136 | if ((modifiers & LockMask) != 0) | 146 | : modifiers & (ScrollMask | NumMask) ? i18n("Press %1 while NumLock and ScrollLock are active", keyname) | ||
137 | if ((modifiers & NumMask) != 0) | 147 | : modifiers & (LockMask | NumMask) ? i18n("Press %1 while NumLock and CapsLock are active", keyname) | ||
138 | result = i18n("Press %1 while NumLock, CapsLock and ScrollLock are active", keyname); | 148 | : modifiers & ScrollMask ? i18n("Press %1 while ScrollLock is active", keyname) | ||
139 | else | 149 | : modifiers & LockMask ? i18n("Press %1 while CapsLock is active", keyname) | ||
140 | result = i18n("Press %1 while CapsLock and ScrollLock are active", keyname); | 150 | : modifiers & NumMask ? i18n("Press %1 while NumLock is active", keyname) | ||
141 | else if ((modifiers & NumMask) != 0) | 151 | : i18n("Press %1", keyname); | ||
broulik: Are you sure this shouldn't be something like
```
modifiers & (ScrollMask | LockMask | NumMask)… | |||||
tcanabrava: good catch. | |||||
142 | result = i18n("Press %1 while NumLock and ScrollLock are active", keyname); | 152 | } | ||
143 | else | 153 | | ||
144 | result = i18n("Press %1 while ScrollLock is active", keyname); | 154 | KAccessConfig::KAccessConfig(QObject *parent, const QVariantList& args) | ||
145 | else if ((modifiers & LockMask) != 0) | 155 | : KQuickAddons::ManagedConfigModule(parent, args) | ||
146 | if ((modifiers & NumMask) != 0) | 156 | , m_mouseSettings(new MouseSettings(this)) | ||
147 | result = i18n("Press %1 while NumLock and CapsLock are active", keyname); | 157 | , m_bellSettings(new BellSettings(this)) | ||
148 | else | 158 | , m_keyboardSettings(new KeyboardSettings(this)) | ||
149 | result = i18n("Press %1 while CapsLock is active", keyname); | 159 | , m_screenReaderSettings(new ScreenReaderSettings(this)) | ||
150 | else if ((modifiers & NumMask) != 0) | 160 | , m_desktopShortcutInfo(mouseKeysShortcut(QX11Info::display())) | ||
151 | result = i18n("Press %1 while NumLock is active", keyname); | 161 | { | ||
152 | else | 162 | qmlRegisterAnonymousType<MouseSettings>("kcm.kde.org", 1); | ||
153 | result = i18n("Press %1", keyname); | 163 | qmlRegisterAnonymousType<BellSettings>("kcm.kde.org", 1); | ||
164 | qmlRegisterAnonymousType<KeyboardSettings>("kcm.kde.org", 1); | ||||
165 | qmlRegisterAnonymousType<ScreenReaderSettings>("kcm.kde.org", 1); | ||||
154 | 166 | | |||
155 | return result; | | |||
156 | } | | |||
157 | | ||||
158 | KAccessConfig::KAccessConfig(QWidget *parent, const QVariantList& args) | | |||
159 | : KCModule(parent, args) | | |||
160 | { | | |||
161 | KAboutData *about = | 167 | KAboutData *about = | ||
162 | new KAboutData(QStringLiteral("kcmaccess"), i18n("KDE Accessibility Tool"), QStringLiteral("1.0"), | 168 | new KAboutData(QStringLiteral("kcmaccess"), i18n("KDE Accessibility Tool"), QStringLiteral("1.0"), | ||
163 | QString(), KAboutLicense::GPL, i18n("(c) 2000, Matthias Hoelzer-Kluepfel")); | 169 | QString(), KAboutLicense::GPL, i18n("(c) 2000, Matthias Hoelzer-Kluepfel")); | ||
164 | 170 | | |||
165 | about->addAuthor(i18n("Matthias Hoelzer-Kluepfel"), i18n("Author") , QStringLiteral("hoelzer@kde.org")); | 171 | about->addAuthor(i18n("Matthias Hoelzer-Kluepfel"), i18n("Author") , QStringLiteral("hoelzer@kde.org")); | ||
166 | setAboutData(about); | | |||
167 | | ||||
168 | ui.setupUi(this); | | |||
169 | 172 | | |||
170 | connect(ui.soundButton, &QPushButton::clicked, this, &KAccessConfig::selectSound); | 173 | setButtons(ConfigModule::Apply | ConfigModule::Default | ConfigModule::Help); | ||
171 | connect(ui.customBell, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | 174 | setAboutData(about); | ||
172 | connect(ui.systemBell, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
173 | connect(ui.customBell, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
174 | connect(ui.soundEdit, &QLineEdit::textChanged, this, &KAccessConfig::configChanged); | | |||
175 | | ||||
176 | connect(ui.invertScreen, &QRadioButton::clicked, this, &KAccessConfig::configChanged); | | |||
177 | connect(ui.flashScreen, &QRadioButton::clicked, this, &KAccessConfig::configChanged); | | |||
178 | connect(ui.visibleBell, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
179 | connect(ui.visibleBell, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | | |||
180 | connect(ui.colorButton, &KColorButton::clicked, this, &KAccessConfig::changeFlashScreenColor); | | |||
181 | | ||||
182 | connect(ui.invertScreen, &QRadioButton::clicked, this, &KAccessConfig::invertClicked); | | |||
183 | connect(ui.flashScreen, &QRadioButton::clicked, this, &KAccessConfig::flashClicked); | | |||
184 | | ||||
185 | connect(ui.duration, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
186 | | ||||
187 | | ||||
188 | // modifier key settings ------------------------------- | | |||
189 | | ||||
190 | connect(ui.stickyKeys, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
191 | connect(ui.stickyKeysLock, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
192 | connect(ui.stickyKeysAutoOff, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
193 | connect(ui.stickyKeys, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | | |||
194 | | ||||
195 | connect(ui.stickyKeysBeep, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
196 | connect(ui.toggleKeysBeep, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
197 | connect(ui.kNotifyModifiers, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
198 | connect(ui.kNotifyModifiers, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | | |||
199 | connect(ui.kNotifyModifiersButton, &QPushButton::clicked, this, &KAccessConfig::configureKNotify); | | |||
200 | | ||||
201 | // key filter settings --------------------------------- | | |||
202 | | ||||
203 | connect(ui.slowKeysDelay, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
204 | connect(ui.slowKeys, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
205 | connect(ui.slowKeys, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | | |||
206 | | ||||
207 | connect(ui.slowKeysPressBeep, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
208 | connect(ui.slowKeysAcceptBeep, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
209 | connect(ui.slowKeysRejectBeep, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
210 | | ||||
211 | connect(ui.bounceKeysDelay, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
212 | connect(ui.bounceKeys, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
213 | connect(ui.bounceKeysRejectBeep, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
214 | connect(ui.bounceKeys, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | | |||
215 | | ||||
216 | // gestures -------------------------------------------- | | |||
217 | | ||||
218 | QString shortcut = mouseKeysShortcut(QX11Info::display()); | | |||
219 | if (shortcut.isEmpty()) | | |||
220 | ui.gestures->setToolTip(i18n("Here you can activate keyboard gestures that turn on the following features: \n" | | |||
221 | "Sticky keys: Press Shift key 5 consecutive times\n" | | |||
222 | "Slow keys: Hold down Shift for 8 seconds")); | | |||
223 | else | | |||
224 | ui.gestures->setToolTip(i18n("Here you can activate keyboard gestures that turn on the following features: \n" | | |||
225 | "Mouse Keys: %1\n" | | |||
226 | "Sticky keys: Press Shift key 5 consecutive times\n" | | |||
227 | "Slow keys: Hold down Shift for 8 seconds", shortcut)); | | |||
228 | | ||||
229 | connect(ui.gestures, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
230 | connect(ui.timeout, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
231 | connect(ui.timeout, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | | |||
232 | connect(ui.timeoutDelay, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
233 | connect(ui.accessxBeep, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
234 | connect(ui.gestureConfirmation, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
235 | connect(ui.kNotifyAccess, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
236 | connect(ui.kNotifyAccess, &QCheckBox::clicked, this, &KAccessConfig::checkAccess); | | |||
237 | connect(ui.kNotifyAccessButton, &QPushButton::clicked, this, &KAccessConfig::configureKNotify); | | |||
238 | | ||||
239 | // keynboard navigation | | |||
240 | connect(ui.mouseKeys, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
241 | connect(ui.mk_delay, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
242 | connect(ui.mk_interval, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
243 | connect(ui.mk_time_to_max, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
244 | connect(ui.mk_max_speed, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
245 | connect(ui.mk_curve, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &KAccessConfig::configChanged); | | |||
246 | | ||||
247 | // screen reader | | |||
248 | connect(ui.screenReaderEnabled, &QCheckBox::clicked, this, &KAccessConfig::configChanged); | | |||
249 | connect(ui.launchOrcaConfiguration, &QPushButton::clicked, this, &KAccessConfig::launchOrcaConfiguration); | | |||
250 | } | 175 | } | ||
This call takes 250ms on my machine, perhaps it's better to do that asynchronously, and/or only when actually entering the screen reader page. Also document the magic number, please broulik: This call takes 250ms on my machine, perhaps it's better to do that asynchronously, and/or only… | |||||
251 | 176 | | |||
252 | | ||||
253 | KAccessConfig::~KAccessConfig() | 177 | KAccessConfig::~KAccessConfig() | ||
254 | { | 178 | { | ||
255 | } | 179 | } | ||
256 | 180 | | |||
257 | void KAccessConfig::configureKNotify() | 181 | void KAccessConfig::configureKNotify(QQuickItem *parent) | ||
258 | { | 182 | { | ||
259 | KNotifyConfigWidget::configure(this, QStringLiteral("kaccess")); | 183 | auto dialog = KNotifyConfigWidget::configure(nullptr, QStringLiteral("kaccess")); | ||
184 | if (parent && parent->window()) { | ||||
185 | dialog->winId(); | ||||
186 | dialog->windowHandle()->setTransientParent(QQuickRenderControl::renderWindowFor(parent->window())); | ||||
187 | } | ||||
This dialog doesn't have a transient parent now. broulik: This dialog doesn't have a transient parent now.
In notifications KCM I had to create the… | |||||
260 | } | 188 | } | ||
261 | 189 | | |||
262 | void KAccessConfig::launchOrcaConfiguration() | 190 | void KAccessConfig::launchOrcaConfiguration() | ||
263 | { | 191 | { | ||
264 | const QStringList gsettingArgs = { QStringLiteral("set"), QStringLiteral("org.gnome.desktop.a11y.applications"), QStringLiteral("screen-reader-enabled"), QStringLiteral("true") }; | 192 | const QStringList gsettingArgs = { | ||
193 | QStringLiteral("set"), | ||||
194 | QStringLiteral("org.gnome.desktop.a11y.applications"), | ||||
195 | QStringLiteral("screen-reader-enabled"), | ||||
196 | QStringLiteral("true") | ||||
197 | }; | ||||
198 | | ||||
265 | int ret = QProcess::execute(QStringLiteral("gsettings"), gsettingArgs); | 199 | int ret = QProcess::execute(QStringLiteral("gsettings"), gsettingArgs); | ||
You could consider using glib for a stable ABI instead of invoking a command line that could change at any time. Also would reduce dependencies for most distros, as glib's command line tools are often packaged separately from glib itself. cblack: You could consider using glib for a stable ABI instead of invoking a command line that could… | |||||
tcanabrava: care to elaborate? This is old code and I haven't touched it. | |||||
In that case, I can submit a separate patch to use glib instead of the gsettings command line interface. cblack: In that case, I can submit a separate patch to use glib instead of the gsettings command line… | |||||
266 | if (ret) { | 200 | if (ret) { | ||
267 | const QString errorStr = QLatin1String("gsettings ") + gsettingArgs.join(QLatin1Char(' ')); | 201 | const QString errorStr = QLatin1String("gsettings ") + gsettingArgs.join(QLatin1Char(' ')); | ||
268 | ui.orcaLaunchFeedbackLabel->setText(i18n("Could not set gsettings for Orca: \"%1\" failed", errorStr)); | 202 | setOrcaLaunchFeedback(i18n("Could not set gsettings for Orca: \"%1\" failed", errorStr)); | ||
269 | return; | 203 | return; | ||
270 | } | 204 | } | ||
271 | 205 | | |||
272 | qint64 pid = 0; | 206 | qint64 pid = 0; | ||
273 | bool started = QProcess::startDetached(QStringLiteral("orca"), {QStringLiteral("--setup")}, QString(), &pid); | 207 | bool started = QProcess::startDetached(QStringLiteral("orca"), {QStringLiteral("--setup")}, QString(), &pid); | ||
274 | if (!started) { | 208 | if (!started) { | ||
275 | ui.orcaLaunchFeedbackLabel->setText(i18n("Error: Could not launch \"orca --setup\"")); | 209 | setOrcaLaunchFeedback(i18n("Error: Could not launch \"orca --setup\"")); | ||
276 | } | | |||
277 | } | | |||
278 | | ||||
279 | void KAccessConfig::changeFlashScreenColor() | | |||
280 | { | | |||
281 | ui.invertScreen->setChecked(false); | | |||
282 | ui.flashScreen->setChecked(true); | | |||
283 | configChanged(); | | |||
284 | } | | |||
285 | | ||||
286 | void KAccessConfig::selectSound() | | |||
287 | { | | |||
288 | const QStringList list = QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("sound/")); | | |||
289 | QString start; | | |||
290 | if (!list.isEmpty()) | | |||
291 | start = list[0]; | | |||
292 | const QString fname = QFileDialog::getOpenFileName(this, QString(), start); | | |||
293 | if (!fname.isEmpty()) | | |||
294 | ui.soundEdit->setText(fname); | | |||
295 | } | 210 | } | ||
296 | | ||||
297 | | ||||
298 | void KAccessConfig::configChanged() | | |||
299 | { | | |||
300 | emit changed(true); | | |||
301 | } | 211 | } | ||
302 | 212 | | |||
303 | | ||||
304 | void KAccessConfig::load() | | |||
305 | { | | |||
306 | KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "Bell"); | | |||
307 | | ||||
308 | ui.systemBell->setChecked(cg.readEntry("SystemBell", true)); | | |||
309 | ui.customBell->setChecked(cg.readEntry("ArtsBell", false)); | | |||
310 | ui.soundEdit->setText(cg.readPathEntry("ArtsBellFile", QString())); | | |||
311 | | ||||
312 | ui.visibleBell->setChecked(cg.readEntry("VisibleBell", false)); | | |||
313 | ui.invertScreen->setChecked(cg.readEntry("VisibleBellInvert", true)); | | |||
314 | ui.flashScreen->setChecked(!ui.invertScreen->isChecked()); | | |||
315 | ui.colorButton->setColor(cg.readEntry("VisibleBellColor", QColor(Qt::red))); | | |||
316 | | ||||
317 | ui.duration->setValue(cg.readEntry("VisibleBellPause", 500)); | | |||
318 | | ||||
319 | KConfigGroup keyboardGroup(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "Keyboard"); | | |||
320 | | ||||
321 | ui.stickyKeys->setChecked(keyboardGroup.readEntry("StickyKeys", false)); | | |||
322 | ui.stickyKeysLock->setChecked(keyboardGroup.readEntry("StickyKeysLatch", true)); | | |||
323 | ui.stickyKeysAutoOff->setChecked(keyboardGroup.readEntry("StickyKeysAutoOff", false)); | | |||
324 | ui.stickyKeysBeep->setChecked(keyboardGroup.readEntry("StickyKeysBeep", true)); | | |||
325 | ui.toggleKeysBeep->setChecked(keyboardGroup.readEntry("ToggleKeysBeep", false)); | | |||
326 | ui.kNotifyModifiers->setChecked(keyboardGroup.readEntry("kNotifyModifiers", false)); | | |||
327 | | ||||
328 | ui.slowKeys->setChecked(keyboardGroup.readEntry("SlowKeys", false)); | | |||
329 | ui.slowKeysDelay->setValue(keyboardGroup.readEntry("SlowKeysDelay", 500)); | | |||
330 | ui.slowKeysPressBeep->setChecked(keyboardGroup.readEntry("SlowKeysPressBeep", true)); | | |||
331 | ui.slowKeysAcceptBeep->setChecked(keyboardGroup.readEntry("SlowKeysAcceptBeep", true)); | | |||
332 | ui.slowKeysRejectBeep->setChecked(keyboardGroup.readEntry("SlowKeysRejectBeep", true)); | | |||
333 | | ||||
334 | ui.bounceKeys->setChecked(keyboardGroup.readEntry("BounceKeys", false)); | | |||
335 | ui.bounceKeysDelay->setValue(keyboardGroup.readEntry("BounceKeysDelay", 500)); | | |||
336 | ui.bounceKeysRejectBeep->setChecked(keyboardGroup.readEntry("BounceKeysRejectBeep", true)); | | |||
337 | | ||||
338 | ui.gestures->setChecked(keyboardGroup.readEntry("Gestures", false)); | | |||
339 | ui.timeout->setChecked(keyboardGroup.readEntry("AccessXTimeout", false)); | | |||
340 | ui.timeoutDelay->setValue(keyboardGroup.readEntry("AccessXTimeoutDelay", 30)); | | |||
341 | | ||||
342 | ui.accessxBeep->setChecked(keyboardGroup.readEntry("AccessXBeep", true)); | | |||
343 | ui.gestureConfirmation->setChecked(keyboardGroup.readEntry("GestureConfirmation", false)); | | |||
344 | ui.kNotifyAccess->setChecked(keyboardGroup.readEntry("kNotifyAccess", false)); | | |||
345 | | ||||
346 | KConfigGroup mouseGroup(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "Mouse"); | | |||
347 | ui.mouseKeys->setChecked(mouseGroup.readEntry("MouseKeys", false)); | | |||
348 | ui.mk_delay->setValue(mouseGroup.readEntry("MKDelay", 160)); | | |||
349 | | ||||
350 | const int interval = mouseGroup.readEntry("MKInterval", 5); | | |||
351 | ui.mk_interval->setValue(interval); | | |||
352 | | ||||
353 | // Default time to reach maximum speed: 5000 msec | | |||
354 | int time_to_max = mouseGroup.readEntry("MKTimeToMax", (5000+interval/2)/interval); | | |||
355 | time_to_max = mouseGroup.readEntry("MK-TimeToMax", time_to_max*interval); | | |||
356 | ui.mk_time_to_max->setValue(time_to_max); | | |||
357 | | ||||
358 | // Default maximum speed: 1000 pixels/sec | | |||
359 | // (The old default maximum speed from KDE <= 3.4 | | |||
360 | // (100000 pixels/sec) was way too fast) | | |||
361 | long max_speed = mouseGroup.readEntry("MKMaxSpeed", interval); | | |||
362 | max_speed = max_speed * 1000 / interval; | | |||
363 | if (max_speed > 2000) { | | |||
364 | max_speed = 2000; | | |||
365 | } | | |||
366 | max_speed = mouseGroup.readEntry("MK-MaxSpeed", int(max_speed)); | | |||
367 | ui.mk_max_speed->setValue(max_speed); | | |||
368 | | ||||
369 | ui.mk_curve->setValue(mouseGroup.readEntry("MKCurve", 0)); | | |||
370 | | ||||
371 | KConfigGroup screenReaderGroup(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "ScreenReader"); | | |||
372 | ui.screenReaderEnabled->setChecked(screenReaderGroup.readEntry("Enabled", false)); | | |||
373 | | ||||
374 | checkAccess(); | | |||
375 | | ||||
376 | emit changed(false); | | |||
377 | } | | |||
378 | | ||||
379 | | ||||
380 | void KAccessConfig::save() | 213 | void KAccessConfig::save() | ||
381 | { | 214 | { | ||
382 | KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "Bell"); | 215 | ManagedConfigModule::save(); | ||
383 | 216 | | |||
384 | cg.writeEntry("SystemBell", ui.systemBell->isChecked()); | 217 | if (m_bellSettings->systemBell() || m_bellSettings->customBell() || m_bellSettings->visibleBell()) { | ||
385 | cg.writeEntry("ArtsBell", ui.customBell->isChecked()); | | |||
386 | cg.writePathEntry("ArtsBellFile", ui.soundEdit->text()); | | |||
387 | | ||||
388 | cg.writeEntry("VisibleBell", ui.visibleBell->isChecked()); | | |||
389 | cg.writeEntry("VisibleBellInvert", ui.invertScreen->isChecked()); | | |||
390 | cg.writeEntry("VisibleBellColor", ui.colorButton->color()); | | |||
391 | | ||||
392 | cg.writeEntry("VisibleBellPause", ui.duration->value()); | | |||
393 | cg.sync(); | | |||
394 | | ||||
395 | KConfigGroup keyboardGroup(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "Keyboard"); | | |||
396 | | ||||
397 | keyboardGroup.writeEntry("StickyKeys", ui.stickyKeys->isChecked()); | | |||
398 | keyboardGroup.writeEntry("StickyKeysLatch", ui.stickyKeysLock->isChecked()); | | |||
399 | keyboardGroup.writeEntry("StickyKeysAutoOff", ui.stickyKeysAutoOff->isChecked()); | | |||
400 | keyboardGroup.writeEntry("StickyKeysBeep", ui.stickyKeysBeep->isChecked()); | | |||
401 | keyboardGroup.writeEntry("ToggleKeysBeep", ui.toggleKeysBeep->isChecked()); | | |||
402 | keyboardGroup.writeEntry("kNotifyModifiers", ui.kNotifyModifiers->isChecked()); | | |||
403 | | ||||
404 | keyboardGroup.writeEntry("SlowKeys", ui.slowKeys->isChecked()); | | |||
405 | keyboardGroup.writeEntry("SlowKeysDelay", ui.slowKeysDelay->value()); | | |||
406 | keyboardGroup.writeEntry("SlowKeysPressBeep", ui.slowKeysPressBeep->isChecked()); | | |||
407 | keyboardGroup.writeEntry("SlowKeysAcceptBeep", ui.slowKeysAcceptBeep->isChecked()); | | |||
408 | keyboardGroup.writeEntry("SlowKeysRejectBeep", ui.slowKeysRejectBeep->isChecked()); | | |||
409 | | ||||
410 | | ||||
411 | keyboardGroup.writeEntry("BounceKeys", ui.bounceKeys->isChecked()); | | |||
412 | keyboardGroup.writeEntry("BounceKeysDelay", ui.bounceKeysDelay->value()); | | |||
413 | keyboardGroup.writeEntry("BounceKeysRejectBeep", ui.bounceKeysRejectBeep->isChecked()); | | |||
414 | | ||||
415 | keyboardGroup.writeEntry("Gestures", ui.gestures->isChecked()); | | |||
416 | keyboardGroup.writeEntry("AccessXTimeout", ui.timeout->isChecked()); | | |||
417 | keyboardGroup.writeEntry("AccessXTimeoutDelay", ui.timeoutDelay->value()); | | |||
418 | | ||||
419 | keyboardGroup.writeEntry("AccessXBeep", ui.accessxBeep->isChecked()); | | |||
420 | keyboardGroup.writeEntry("GestureConfirmation", ui.gestureConfirmation->isChecked()); | | |||
421 | keyboardGroup.writeEntry("kNotifyAccess", ui.kNotifyAccess->isChecked()); | | |||
422 | | ||||
423 | | ||||
424 | keyboardGroup.sync(); | | |||
425 | | ||||
426 | KConfigGroup mouseGroup(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "Mouse"); | | |||
427 | const int interval = ui.mk_interval->value(); | | |||
428 | mouseGroup.writeEntry("MouseKeys", ui.mouseKeys->isChecked()); | | |||
429 | mouseGroup.writeEntry("MKDelay", ui.mk_delay->value()); | | |||
430 | mouseGroup.writeEntry("MKInterval", interval); | | |||
431 | mouseGroup.writeEntry("MK-TimeToMax", ui.mk_time_to_max->value()); | | |||
432 | mouseGroup.writeEntry("MKTimeToMax", (ui.mk_time_to_max->value() + interval/2)/interval); | | |||
433 | mouseGroup.writeEntry("MK-MaxSpeed", ui.mk_max_speed->value()); | | |||
434 | mouseGroup.writeEntry("MKMaxSpeed", (ui.mk_max_speed->value()*interval + 500)/1000); | | |||
435 | mouseGroup.writeEntry("MKCurve", ui.mk_curve->value()); | | |||
436 | mouseGroup.sync(); | | |||
437 | | ||||
438 | KConfigGroup screenReaderGroup(KSharedConfig::openConfig(QStringLiteral("kaccessrc")), "ScreenReader"); | | |||
439 | screenReaderGroup.writeEntry("Enabled", ui.screenReaderEnabled->isChecked()); | | |||
440 | | ||||
441 | if (ui.systemBell->isChecked() || | | |||
442 | ui.customBell->isChecked() || | | |||
443 | ui.visibleBell->isChecked()) { | | |||
444 | KConfig _cfg(QStringLiteral("kdeglobals"), KConfig::NoGlobals); | 218 | KConfig _cfg(QStringLiteral("kdeglobals"), KConfig::NoGlobals); | ||
445 | KConfigGroup cfg(&_cfg, "General"); | 219 | KConfigGroup cfg(&_cfg, "General"); | ||
446 | cfg.writeEntry("UseSystemBell", true); | 220 | cfg.writeEntry("UseSystemBell", true); | ||
447 | cfg.sync(); | 221 | cfg.sync(); | ||
448 | } | 222 | } | ||
449 | 223 | | |||
450 | // make kaccess reread the configuration | 224 | // make kaccess reread the configuration | ||
451 | // turning a11y features off needs to be done by kaccess | 225 | // turning a11y features off needs to be done by kaccess | ||
452 | // so run it to clear any enabled features and it will exit if it should | 226 | // so run it to clear any enabled features and it will exit if it should | ||
453 | KToolInvocation::startServiceByDesktopName(QStringLiteral("kaccess")); | 227 | KToolInvocation::startServiceByDesktopName(QStringLiteral("kaccess")); | ||
454 | | ||||
455 | emit changed(false); | | |||
456 | } | 228 | } | ||
457 | 229 | | |||
458 | 230 | QString KAccessConfig::orcaLaunchFeedback() const | |||
459 | void KAccessConfig::defaults() | | |||
460 | { | 231 | { | ||
461 | ui.systemBell->setChecked(true); | 232 | return m_orcaLaunchFeedback; | ||
462 | ui.customBell->setChecked(false); | | |||
463 | ui.soundEdit->setText(QString()); | | |||
464 | | ||||
465 | ui.visibleBell->setChecked(false); | | |||
466 | ui.invertScreen->setChecked(true); | | |||
467 | ui.flashScreen->setChecked(false); | | |||
468 | ui.colorButton->setColor(QColor(Qt::red)); | | |||
469 | | ||||
470 | ui.duration->setValue(500); | | |||
471 | | ||||
472 | ui.slowKeys->setChecked(false); | | |||
473 | ui.slowKeysDelay->setValue(500); | | |||
474 | ui.slowKeysPressBeep->setChecked(true); | | |||
475 | ui.slowKeysAcceptBeep->setChecked(true); | | |||
476 | ui.slowKeysRejectBeep->setChecked(true); | | |||
477 | | ||||
478 | ui.bounceKeys->setChecked(false); | | |||
479 | ui.bounceKeysDelay->setValue(500); | | |||
480 | ui.bounceKeysRejectBeep->setChecked(true); | | |||
481 | | ||||
482 | ui.stickyKeys->setChecked(false); | | |||
483 | ui.stickyKeysLock->setChecked(true); | | |||
484 | ui.stickyKeysAutoOff->setChecked(false); | | |||
485 | ui.stickyKeysBeep->setChecked(true); | | |||
486 | ui.toggleKeysBeep->setChecked(false); | | |||
487 | ui.kNotifyModifiers->setChecked(false); | | |||
488 | | ||||
489 | ui.gestures->setChecked(false); | | |||
490 | ui.timeout->setChecked(false); | | |||
491 | ui.timeoutDelay->setValue(30); | | |||
492 | | ||||
493 | ui.accessxBeep->setChecked(true); | | |||
494 | ui.gestureConfirmation->setChecked(true); | | |||
495 | ui.kNotifyAccess->setChecked(false); | | |||
496 | | ||||
497 | ui.mouseKeys->setChecked(false); | | |||
498 | ui.mk_delay->setValue(160); | | |||
499 | ui.mk_interval->setValue(5); | | |||
500 | ui.mk_time_to_max->setValue(5000); | | |||
501 | ui.mk_max_speed->setValue(1000); | | |||
502 | ui.mk_curve->setValue(0); | | |||
503 | | ||||
504 | ui.screenReaderEnabled->setChecked(false); | | |||
505 | | ||||
506 | checkAccess(); | | |||
507 | | ||||
508 | emit changed(true); | | |||
509 | } | 233 | } | ||
510 | 234 | | |||
511 | 235 | void KAccessConfig::setOrcaLaunchFeedback(const QString& value) | |||
512 | void KAccessConfig::invertClicked() | | |||
513 | { | 236 | { | ||
514 | ui.flashScreen->setChecked(false); | 237 | if (m_orcaLaunchFeedback != value) { | ||
238 | m_orcaLaunchFeedback = value; | ||||
239 | emit orcaLaunchFeedbackChanged(); | ||||
515 | } | 240 | } | ||
516 | | ||||
517 | | ||||
518 | void KAccessConfig::flashClicked() | | |||
519 | { | | |||
520 | ui.invertScreen->setChecked(false); | | |||
521 | } | 241 | } | ||
522 | 242 | | |||
523 | 243 | bool KAccessConfig::orcaInstalled() | |||
524 | void KAccessConfig::checkAccess() | | |||
525 | { | 244 | { | ||
526 | bool custom = ui.customBell->isChecked(); | 245 | int tryOrcaRun = QProcess::execute(QStringLiteral("orca"), {QStringLiteral("--version")}); | ||
527 | ui.soundEdit->setEnabled(custom); | | |||
528 | ui.soundButton->setEnabled(custom); | | |||
529 | ui.soundLabel->setEnabled(custom); | | |||
530 | | ||||
531 | bool visible = ui.visibleBell->isChecked(); | | |||
532 | ui.invertScreen->setEnabled(visible); | | |||
533 | ui.flashScreen->setEnabled(visible); | | |||
534 | ui.colorButton->setEnabled(visible); | | |||
535 | ui.duration->setEnabled(visible); | | |||
536 | 246 | | |||
537 | bool sticky = ui.stickyKeys->isChecked(); | 247 | // If the process cannot be started, -2 is returned. | ||
538 | ui.stickyKeysLock->setEnabled(sticky); | 248 | return tryOrcaRun != -2; | ||
Don't ever use nested event loops in QML. You can use QtQuick.Dialogs FileDialog for that. broulik: Don't ever use nested event loops in QML. You can use `QtQuick.Dialogs` `FileDialog` for that.
| |||||
539 | ui.stickyKeysAutoOff->setEnabled(sticky); | | |||
540 | ui.stickyKeysBeep->setEnabled(sticky); | | |||
541 | | ||||
542 | bool slow = ui.slowKeys->isChecked(); | | |||
543 | ui.slowKeysDelay->setEnabled(slow); | | |||
544 | ui.slowKeysPressBeep->setEnabled(slow); | | |||
545 | ui.slowKeysAcceptBeep->setEnabled(slow); | | |||
546 | ui.slowKeysRejectBeep->setEnabled(slow); | | |||
547 | | ||||
548 | bool bounce = ui.bounceKeys->isChecked(); | | |||
549 | ui.bounceKeysDelay->setEnabled(bounce); | | |||
550 | ui.bounceKeysRejectBeep->setEnabled(bounce); | | |||
551 | | ||||
552 | bool useTimeout = ui.timeout->isChecked(); | | |||
553 | ui.timeoutDelay->setEnabled(useTimeout); | | |||
554 | } | 249 | } | ||
555 | 250 | | |||
556 | extern "C" | 251 | extern "C" | ||
557 | { | 252 | { | ||
558 | /* This one gets called by kcminit | 253 | /* This one gets called by kcminit | ||
559 | 254 | | |||
560 | */ | 255 | */ | ||
561 | Q_DECL_EXPORT void kcminit_access() | 256 | Q_DECL_EXPORT void kcminit_access() | ||
562 | { | 257 | { | ||
563 | KToolInvocation::startServiceByDesktopName(QStringLiteral("kaccess")); | 258 | KToolInvocation::startServiceByDesktopName(QStringLiteral("kaccess")); | ||
564 | } | 259 | } | ||
565 | } | 260 | } | ||
566 | 261 | | |||
567 | #include "kcmaccess.moc" | 262 | #include "kcmaccess.moc" | ||
568 | |
Are you sure this shouldn't be something like