Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kcontrol / access / kcmaccess.cpp
blobb8b054d060079b0bd0a0eac3d6ce64118c444fc2
1 /**
2 * kcmaccess.cpp
4 * Copyright (c) 2000 Matthias H�zer-Klpfel
6 */
9 #include <stdlib.h>
10 #include <math.h>
13 #include <QTabWidget>
14 #include <QLabel>
15 #include <QCheckBox>
16 #include <QLineEdit>
17 #include <QRadioButton>
18 #include <QtGui/QX11Info>
19 #include <QtDBus/QtDBus>
21 //Added by qt3to4:
22 #include <QVBoxLayout>
23 #include <QHBoxLayout>
24 #include <QGroupBox>
25 #include <klocale.h>
27 #include <kcombobox.h>
28 #include <kstandarddirs.h>
29 #include <kcolorbutton.h>
30 #include <kfiledialog.h>
31 #include <kapplication.h>
32 #include <kaboutdata.h>
33 #include <kshortcut.h>
34 #include <knotifyconfigwidget.h>
35 #include <kkeyserver.h>
37 #include <X11/Xlib.h>
38 #include <X11/XKBlib.h>
39 #define XK_MISCELLANY
40 #define XK_XKB_KEYS
41 #include <X11/keysymdef.h>
42 #include <ktoolinvocation.h>
44 #include "kcmaccess.moc"
46 #include <kgenericfactory.h>
47 typedef KGenericFactory<KAccessConfig, QWidget> KAccessConfigFactory;
48 K_EXPORT_COMPONENT_FACTORY(kcm_access, KAccessConfigFactory("kcmaccess"))
50 ExtendedIntNumInput::ExtendedIntNumInput
51 (QWidget* parent)
52 : KIntNumInput(parent)
56 ExtendedIntNumInput::~ExtendedIntNumInput () {
59 void ExtendedIntNumInput::setRange(int min, int max, int step, bool withSlider) {
60 KIntNumInput::setRange (min, max, step, withSlider);
62 if (withSlider) {
63 disconnect(slider(), SIGNAL(valueChanged(int)),
64 spinBox(), SLOT(setValue(int)));
65 disconnect(spinBox(), SIGNAL(valueChanged(int)),
66 this, SLOT(spinValueChanged(int)));
68 this->min = min;
69 this->max = max;
70 sliderMax = (int)floor (0.5
71 + 2*(log((double)max)-log((double)min)) / (log((double)max)-log((double)max-1)));
72 slider()->setRange(0, sliderMax);
73 slider()->setSingleStep(step);
74 slider()->setPageStep(sliderMax/10);
75 slider()->setTickInterval(sliderMax/10);
77 double alpha = sliderMax / (log((double)max) - log((double)min));
78 double logVal = alpha * (log((double)value())-log((double)min));
79 slider()->setValue ((int)floor (0.5 + logVal));
81 connect(slider(), SIGNAL(valueChanged(int)),
82 this, SLOT(slotSliderValueChanged(int)));
83 connect(spinBox(), SIGNAL(valueChanged(int)),
84 this, SLOT(slotSpinValueChanged(int)));
88 // Basically the slider values are logarithmic whereas
89 // spinbox values are linear.
91 void ExtendedIntNumInput::slotSpinValueChanged(int val)
94 if(slider()) {
95 double alpha = sliderMax / (log((double)max) - log((double)min));
96 double logVal = alpha * (log((double)val)-log((double)min));
97 slider()->setValue ((int)floor (0.5 + logVal));
100 emit valueChanged(val);
103 void ExtendedIntNumInput::slotSliderValueChanged(int val)
105 double alpha = sliderMax / (log((double)max) - log((double)min));
106 double linearVal = exp (val/alpha + log((double)min));
107 spinBox()->setValue ((int)floor(0.5 + linearVal));
110 static bool needToRunKAccessDaemon( KConfig *config )
112 // We always start the KAccess Daemon, if it is not needed,
113 // it will terminate itself after configuring the AccessX
114 // features.
115 return true;
118 QString mouseKeysShortcut (Display *display) {
119 // Calculate the keycode
120 KeySym sym = XK_MouseKeys_Enable;
121 KeyCode code = XKeysymToKeycode(display, sym);
122 if (code == 0) {
123 sym = XK_Pointer_EnableKeys;
124 code = XKeysymToKeycode(display, sym);
125 if (code == 0)
126 return ""; // No shortcut available?
129 // Calculate the modifiers by searching the keysym in the X keyboard mapping
130 XkbDescPtr xkbdesc = XkbGetMap(display, XkbKeyTypesMask | XkbKeySymsMask, XkbUseCoreKbd);
131 if (!xkbdesc)
132 return ""; // Failed to obtain the mapping from server
134 bool found = false;
135 unsigned char modifiers = 0;
136 int groups = XkbKeyNumGroups(xkbdesc, code);
137 for (int grp = 0; grp < groups && !found; grp++)
139 int levels = XkbKeyGroupWidth(xkbdesc, code, grp);
140 for (int level = 0; level < levels && !found; level++)
142 if (sym == XkbKeySymEntry(xkbdesc, code, level, grp))
144 // keysym found => determine modifiers
145 int typeIdx = xkbdesc->map->key_sym_map[code].kt_index[grp];
146 XkbKeyTypePtr type = &(xkbdesc->map->types[typeIdx]);
147 for (int i = 0; i < type->map_count && !found; i++)
149 if (type->map[i].active && (type->map[i].level == level))
151 modifiers = type->map[i].mods.mask;
152 found = true;
158 XkbFreeClientMap (xkbdesc, 0, true);
160 if (!found)
161 return ""; // Somehow the keycode -> keysym mapping is flawed
163 XEvent ev;
164 ev.xkey.display = display;
165 ev.xkey.keycode = code;
166 ev.xkey.state = 0;
167 int key;
168 KKeyServer::xEventToQt(&ev, &key);
169 QString keyname = QKeySequence(key).toString();
171 unsigned int AltMask = KKeyServer::modXAlt();
172 unsigned int WinMask = KKeyServer::modXMeta();
173 unsigned int NumMask = KKeyServer::modXNumLock();
174 unsigned int ScrollMask= KKeyServer::modXScrollLock();
176 unsigned int MetaMask = XkbKeysymToModifiers (display, XK_Meta_L);
177 unsigned int SuperMask = XkbKeysymToModifiers (display, XK_Super_L);
178 unsigned int HyperMask = XkbKeysymToModifiers (display, XK_Hyper_L);
179 unsigned int AltGrMask = XkbKeysymToModifiers (display, XK_Mode_switch)
180 | XkbKeysymToModifiers (display, XK_ISO_Level3_Shift)
181 | XkbKeysymToModifiers (display, XK_ISO_Level3_Latch)
182 | XkbKeysymToModifiers (display, XK_ISO_Level3_Lock);
184 unsigned int mods = ShiftMask | ControlMask | AltMask | WinMask
185 | LockMask | NumMask | ScrollMask;
187 AltGrMask &= ~mods;
188 MetaMask &= ~(mods | AltGrMask);
189 SuperMask &= ~(mods | AltGrMask | MetaMask);
190 HyperMask &= ~(mods | AltGrMask | MetaMask | SuperMask);
192 if ((modifiers & AltGrMask) != 0)
193 keyname = i18n("AltGraph") + '+' + keyname;
194 if ((modifiers & HyperMask) != 0)
195 keyname = i18n("Hyper") + '+' + keyname;
196 if ((modifiers & SuperMask) != 0)
197 keyname = i18n("Super") + '+' + keyname;
198 if ((modifiers & WinMask) != 0)
199 keyname = QKeySequence(Qt::META).toString() + '+' + keyname;
200 if ((modifiers & AltMask) != 0)
201 keyname = QKeySequence(Qt::ALT).toString() + '+' + keyname;
202 if ((modifiers & ControlMask) != 0)
203 keyname = QKeySequence(Qt::CTRL).toString() + '+' + keyname;
204 if ((modifiers & ShiftMask) != 0)
205 keyname = QKeySequence(Qt::SHIFT).toString() + '+' + keyname;
207 QString result;
208 if ((modifiers & ScrollMask) != 0)
209 if ((modifiers & LockMask) != 0)
210 if ((modifiers & NumMask) != 0)
211 result = i18n("Press %1 while NumLock, CapsLock and ScrollLock are active", keyname);
212 else
213 result = i18n("Press %1 while CapsLock and ScrollLock are active", keyname);
214 else if ((modifiers & NumMask) != 0)
215 result = i18n("Press %1 while NumLock and ScrollLock are active", keyname);
216 else
217 result = i18n("Press %1 while ScrollLock is active", keyname);
218 else if ((modifiers & LockMask) != 0)
219 if ((modifiers & NumMask) != 0)
220 result = i18n("Press %1 while NumLock and CapsLock are active", keyname);
221 else
222 result = i18n("Press %1 while CapsLock is active", keyname);
223 else if ((modifiers & NumMask) != 0)
224 result = i18n("Press %1 while NumLock is active", keyname);
225 else
226 result = i18n("Press %1", keyname);
228 return result;
231 KAccessConfig::KAccessConfig(QWidget *parent, const QStringList& args)
232 : KCModule(KAccessConfigFactory::componentData(), parent, args)
235 KAboutData *about =
236 new KAboutData(I18N_NOOP("kaccess"), 0, ki18n("KDE Accessibility Tool"),
237 0, KLocalizedString(), KAboutData::License_GPL,
238 ki18n("(c) 2000, Matthias Hoelzer-Kluepfel"));
240 about->addAuthor(ki18n("Matthias Hoelzer-Kluepfel"), ki18n("Author") , "hoelzer@kde.org");
242 setAboutData( about );
244 QVBoxLayout *main = new QVBoxLayout(this);
245 main->setMargin(0);
246 main->setSpacing(KDialog::spacingHint());
247 QTabWidget *tab = new QTabWidget(this);
248 main->addWidget(tab);
250 // bell settings ---------------------------------------
251 QWidget *bell = new QWidget(this);
253 QVBoxLayout *vbox = new QVBoxLayout(bell);
254 vbox->setMargin(KDialog::marginHint());
255 vbox->setSpacing(KDialog::spacingHint());
257 QGroupBox *grp = new QGroupBox(i18n("Audible Bell"), bell);
258 QHBoxLayout *layout = new QHBoxLayout;
259 grp->setLayout(layout);
260 vbox->addWidget(grp);
262 QVBoxLayout *vvbox = new QVBoxLayout();
263 layout->addLayout( vvbox );
264 vvbox->setSpacing( KDialog::spacingHint() );
266 systemBell = new QCheckBox(i18n("Use &system bell"), grp);
267 vvbox->addWidget(systemBell);
268 customBell = new QCheckBox(i18n("Us&e customized bell"), grp);
269 vvbox->addWidget(customBell);
270 systemBell->setWhatsThis( i18n("If this option is checked, the default system bell will be used. See the"
271 " \"System Bell\" control module for how to customize the system bell."
272 " Normally, this is just a \"beep\".") );
273 customBell->setWhatsThis( i18n("<p>Check this option if you want to use a customized bell, playing"
274 " a sound file. If you do this, you will probably want to turn off the system bell.</p><p> Please note"
275 " that on slow machines this may cause a \"lag\" between the event causing the bell and the sound being played.</p>") );
277 QHBoxLayout *hbox = new QHBoxLayout();
278 vvbox->addItem( hbox );
279 hbox->setSpacing(KDialog::spacingHint());
280 hbox->addSpacing(24);
281 soundEdit = new QLineEdit(grp);
282 soundLabel = new QLabel(i18n("Sound &to play:"), grp);
283 soundLabel->setBuddy(soundEdit);
284 hbox->addWidget(soundLabel);
285 hbox->addWidget(soundEdit);
286 soundButton = new QPushButton(i18n("Browse..."), grp);
287 hbox->addWidget(soundButton);
288 QString wtstr = i18n("If the option \"Use customized bell\" is enabled, you can choose a sound file here."
289 " Click \"Browse...\" to choose a sound file using the file dialog.");
290 soundEdit->setWhatsThis( wtstr );
291 soundLabel->setWhatsThis( wtstr );
292 soundButton->setWhatsThis( wtstr );
294 connect(soundButton, SIGNAL(clicked()), this, SLOT(selectSound()));
296 connect(customBell, SIGNAL(clicked()), this, SLOT(checkAccess()));
298 connect(systemBell, SIGNAL(clicked()), this, SLOT(configChanged()));
299 connect(customBell, SIGNAL(clicked()), this, SLOT(configChanged()));
300 connect(soundEdit, SIGNAL(textChanged(const QString&)), this, SLOT(configChanged()));
302 // -----------------------------------------------------
304 // visible bell ----------------------------------------
305 grp = new QGroupBox(i18n("Visible Bell"), bell);
306 layout = new QHBoxLayout;
307 grp->setLayout(layout);
308 vbox->addWidget(grp);
310 vvbox = new QVBoxLayout();
311 layout->addLayout( vvbox );
312 vvbox->setSpacing(KDialog::spacingHint());
314 visibleBell = new QCheckBox(i18n("&Use visible bell"), grp);
315 vvbox->addWidget(visibleBell);
316 visibleBell->setWhatsThis( i18n("This option will turn on the \"visible bell\", i.e. a visible"
317 " notification shown every time that normally just a bell would occur. This is especially useful"
318 " for deaf people.") );
320 hbox = new QHBoxLayout();
321 vvbox->addItem(hbox);
322 hbox->setSpacing(KDialog::spacingHint());
323 hbox->addSpacing(24);
324 invertScreen = new QRadioButton(i18n("I&nvert screen"), grp);
325 hbox->addWidget(invertScreen);
326 hbox = new QHBoxLayout();
327 vvbox->addItem(hbox);
328 hbox->setSpacing(KDialog::spacingHint());
329 invertScreen->setWhatsThis( i18n("All screen colors will be inverted for the amount of time specified below.") );
330 hbox->addSpacing(24);
331 flashScreen = new QRadioButton(i18n("F&lash screen"), grp);
332 hbox->addWidget(flashScreen);
333 flashScreen->setWhatsThis( i18n("The screen will turn to a custom color for the amount of time specified below.") );
334 hbox->addSpacing(12);
335 colorButton = new KColorButton(grp);
336 colorButton->setFixedWidth(colorButton->sizeHint().height()*2);
337 hbox->addWidget(colorButton);
338 hbox->addStretch();
339 colorButton->setWhatsThis( i18n("Click here to choose the color used for the \"flash screen\" visible bell.") );
341 hbox = new QHBoxLayout();
342 vvbox->addItem(hbox);
343 hbox->setSpacing(KDialog::spacingHint());
344 hbox->addSpacing(24);
346 durationSlider = new ExtendedIntNumInput(grp);
347 durationSlider->setRange(100, 2000, 100);
348 durationSlider->setLabel(i18n("Duration:"));
349 durationSlider->setSuffix(i18n(" msec"));
350 hbox->addWidget(durationSlider);
351 durationSlider->setWhatsThis( i18n("Here you can customize the duration of the \"visible bell\" effect being shown.") );
353 connect(invertScreen, SIGNAL(clicked()), this, SLOT(configChanged()));
354 connect(flashScreen, SIGNAL(clicked()), this, SLOT(configChanged()));
355 connect(visibleBell, SIGNAL(clicked()), this, SLOT(configChanged()));
356 connect(visibleBell, SIGNAL(clicked()), this, SLOT(checkAccess()));
357 connect(colorButton, SIGNAL(clicked()), this, SLOT(changeFlashScreenColor()));
359 connect(invertScreen, SIGNAL(clicked()), this, SLOT(invertClicked()));
360 connect(flashScreen, SIGNAL(clicked()), this, SLOT(flashClicked()));
362 connect(durationSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
364 vbox->addStretch();
366 // -----------------------------------------------------
368 tab->addTab(bell, i18n("&Bell"));
371 // modifier key settings -------------------------------
372 QWidget *modifiers = new QWidget(this);
374 vbox = new QVBoxLayout(modifiers);
375 vbox->setMargin(KDialog::marginHint());
376 vbox->setSpacing(KDialog::spacingHint());
378 grp = new QGroupBox(i18n("S&ticky Keys"), modifiers);
379 layout = new QHBoxLayout;
380 grp->setLayout(layout);
381 vbox->addWidget(grp);
383 vvbox = new QVBoxLayout();
384 layout->addLayout(vvbox);
385 vvbox->setSpacing(KDialog::spacingHint());
387 stickyKeys = new QCheckBox(i18n("Use &sticky keys"), grp);
388 vvbox->addWidget(stickyKeys);
390 hbox = new QHBoxLayout();
391 vvbox->addItem(hbox);
392 hbox->setSpacing(KDialog::spacingHint());
393 hbox->addSpacing(24);
394 stickyKeysLock = new QCheckBox(i18n("&Lock sticky keys"), grp);
395 hbox->addWidget(stickyKeysLock);
397 hbox = new QHBoxLayout();
398 vvbox->addItem(hbox);
399 hbox->setSpacing(KDialog::spacingHint());
400 hbox->addSpacing(24);
401 stickyKeysAutoOff = new QCheckBox(i18n("Turn sticky keys off when two keys are pressed simultaneously"), grp);
402 hbox->addWidget(stickyKeysAutoOff);
404 hbox = new QHBoxLayout();
405 vvbox->addItem(hbox);
406 hbox->setSpacing(KDialog::spacingHint());
407 hbox->addSpacing(24);
408 stickyKeysBeep = new QCheckBox(i18n("Use system bell whenever a modifier gets latched, locked or unlocked"), grp);
409 hbox->addWidget(stickyKeysBeep);
411 grp = new QGroupBox(i18n("Locking Keys"), modifiers);
412 layout = new QHBoxLayout;
413 grp->setLayout(layout);
414 vbox->addWidget(grp);
416 vvbox = new QVBoxLayout();
417 layout->addLayout(vvbox);
418 vvbox->setSpacing(KDialog::spacingHint());
420 toggleKeysBeep = new QCheckBox(i18n("Use system bell whenever a locking key gets activated or deactivated"), grp);
421 vvbox->addWidget(toggleKeysBeep);
423 kNotifyModifiers = new QCheckBox(i18n("Use KDE's system notification mechanism whenever a modifier or locking key changes its state"), grp);
424 vvbox->addWidget(kNotifyModifiers);
426 hbox = new QHBoxLayout();
427 vvbox->addItem(hbox);
428 hbox->setSpacing(KDialog::spacingHint());
429 hbox->addStretch(1);
430 kNotifyModifiersButton = new QPushButton(i18n("Configure &Notifications..."), grp);
431 kNotifyModifiersButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
432 hbox->addWidget(kNotifyModifiersButton);
434 connect(stickyKeys, SIGNAL(clicked()), this, SLOT(configChanged()));
435 connect(stickyKeysLock, SIGNAL(clicked()), this, SLOT(configChanged()));
436 connect(stickyKeysAutoOff, SIGNAL(clicked()), this, SLOT(configChanged()));
437 connect(stickyKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
439 connect(stickyKeysBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
440 connect(toggleKeysBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
441 connect(kNotifyModifiers, SIGNAL(clicked()), this, SLOT(configChanged()));
442 connect(kNotifyModifiers, SIGNAL(clicked()), this, SLOT(checkAccess()));
443 connect(kNotifyModifiersButton, SIGNAL(clicked()), this, SLOT(configureKNotify()));
445 vbox->addStretch();
447 tab->addTab(modifiers, i18n("&Modifier Keys"));
449 // key filter settings ---------------------------------
450 QWidget *filters = new QWidget(this);
452 vbox = new QVBoxLayout(filters);
453 vbox->setMargin(KDialog::marginHint());
454 vbox->setSpacing(KDialog::spacingHint());
455 grp = new QGroupBox(i18n("Slo&w Keys"), filters);
456 layout = new QHBoxLayout;
457 grp->setLayout(layout);
458 vbox->addWidget(grp);
460 vvbox = new QVBoxLayout();
461 layout->addLayout(vvbox);
462 vvbox->setSpacing(KDialog::spacingHint());
464 slowKeys = new QCheckBox(i18n("&Use slow keys"), grp);
465 vvbox->addWidget(slowKeys);
467 hbox = new QHBoxLayout();
468 vvbox->addItem(hbox);
469 hbox->setSpacing(KDialog::spacingHint());
470 hbox->addSpacing(24);
471 slowKeysDelay = new ExtendedIntNumInput(grp);
472 slowKeysDelay->setSuffix(i18n(" msec"));
473 slowKeysDelay->setRange(50, 10000, 100);
474 slowKeysDelay->setLabel(i18n("Acceptance dela&y:"));
475 hbox->addWidget(slowKeysDelay);
477 hbox = new QHBoxLayout();
478 vvbox->addItem(hbox);
479 hbox->setSpacing(KDialog::spacingHint());
480 hbox->addSpacing(24);
481 slowKeysPressBeep = new QCheckBox(i18n("&Use system bell whenever a key is pressed"), grp);
482 hbox->addWidget(slowKeysPressBeep);
484 hbox = new QHBoxLayout();
485 vvbox->addItem(hbox);
486 hbox->setSpacing(KDialog::spacingHint());
487 hbox->addSpacing(24);
488 slowKeysAcceptBeep = new QCheckBox(i18n("&Use system bell whenever a key is accepted"), grp);
489 hbox->addWidget(slowKeysAcceptBeep);
491 hbox = new QHBoxLayout();
492 vvbox->addItem(hbox);
493 hbox->setSpacing(KDialog::spacingHint());
494 hbox->addSpacing(24);
495 slowKeysRejectBeep = new QCheckBox(i18n("&Use system bell whenever a key is rejected"), grp);
496 hbox->addWidget(slowKeysRejectBeep);
498 grp = new QGroupBox(i18n("Bounce Keys"), filters);
499 layout= new QHBoxLayout;
500 grp->setLayout(layout);
501 vbox->addWidget(grp);
503 vvbox = new QVBoxLayout();
504 layout->addLayout( vvbox );
505 vvbox->setSpacing(KDialog::spacingHint());
507 bounceKeys = new QCheckBox(i18n("Use bou&nce keys"), grp);
508 vvbox->addWidget(bounceKeys);
510 hbox = new QHBoxLayout();
511 vvbox->addItem(hbox);
512 hbox->setSpacing(KDialog::spacingHint());
513 hbox->addSpacing(24);
514 bounceKeysDelay = new ExtendedIntNumInput(grp);
515 bounceKeysDelay->setSuffix(i18n(" msec"));
516 bounceKeysDelay->setRange(100, 5000, 100);
517 bounceKeysDelay->setLabel(i18n("D&ebounce time:"));
518 hbox->addWidget(bounceKeysDelay);
520 hbox = new QHBoxLayout();
521 vvbox->addItem(hbox);
522 hbox->setSpacing(KDialog::spacingHint());
523 hbox->addSpacing(24);
524 bounceKeysRejectBeep = new QCheckBox(i18n("Use the system bell whenever a key is rejected"), grp);
525 hbox->addWidget(bounceKeysRejectBeep);
527 connect(slowKeysDelay, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
528 connect(slowKeys, SIGNAL(clicked()), this, SLOT(configChanged()));
529 connect(slowKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
531 connect(slowKeysPressBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
532 connect(slowKeysAcceptBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
533 connect(slowKeysRejectBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
535 connect(bounceKeysDelay, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
536 connect(bounceKeys, SIGNAL(clicked()), this, SLOT(configChanged()));
537 connect(bounceKeysRejectBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
538 connect(bounceKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
540 vbox->addStretch();
542 tab->addTab(filters, i18n("&Keyboard Filters"));
544 // gestures --------------------------------------------
545 QWidget *features = new QWidget(this);
547 vbox = new QVBoxLayout(features);
548 vbox->setMargin(KDialog::marginHint());
549 vbox->setSpacing(KDialog::spacingHint());
551 grp = new QGroupBox(i18n("Activation Gestures"), features);
552 layout = new QHBoxLayout;
553 grp->setLayout(layout);
554 vbox->addWidget(grp);
556 vvbox = new QVBoxLayout();
557 layout->addLayout( vvbox );
558 vvbox->setSpacing(KDialog::spacingHint());
560 gestures = new QCheckBox(i18n("Use gestures for activating sticky keys and slow keys"), grp);
561 vvbox->addWidget(gestures);
562 QString shortcut = mouseKeysShortcut(x11Info().display());
563 if (shortcut.isEmpty())
564 gestures->setWhatsThis( i18n("Here you can activate keyboard gestures that turn on the following features: \n"
565 "Sticky keys: Press Shift key 5 consecutive times\n"
566 "Slow keys: Hold down Shift for 8 seconds"));
567 else
568 gestures->setWhatsThis( i18n("Here you can activate keyboard gestures that turn on the following features: \n"
569 "Mouse Keys: %1\n"
570 "Sticky keys: Press Shift key 5 consecutive times\n"
571 "Slow keys: Hold down Shift for 8 seconds", shortcut));
573 timeout = new QCheckBox(i18n("Turn sticky keys and slow keys off after a certain time of inactivity"), grp);
574 vvbox->addWidget(timeout);
576 hbox = new QHBoxLayout();
577 vvbox->addItem(hbox);
578 hbox->setSpacing(KDialog::spacingHint());
579 hbox->addSpacing(24);
580 timeoutDelay = new KIntNumInput(grp);
581 timeoutDelay->setSuffix(i18n(" min"));
582 timeoutDelay->setRange(1, 30, 4);
583 timeoutDelay->setLabel(i18n("Timeout:"));
584 hbox->addWidget(timeoutDelay);
586 grp = new QGroupBox(i18n("Notification"), features);
587 layout = new QHBoxLayout;
588 grp->setLayout(layout);
589 vbox->addWidget(grp);
591 vvbox = new QVBoxLayout();
592 layout->addLayout(vvbox);
593 vvbox->setSpacing(KDialog::spacingHint());
595 accessxBeep = new QCheckBox(i18n("Use the system bell whenever a gesture is used to turn an accessibility feature on or off"), grp);
596 vvbox->addWidget(accessxBeep);
598 gestureConfirmation = new QCheckBox(i18n("Show a confirmation dialog whenever a keyboard accessibility feature is turned on or off"), grp);
599 vvbox->addWidget(gestureConfirmation);
600 gestureConfirmation->setWhatsThis( i18n("If this option is checked, KDE will show a confirmation dialog whenever a keyboard accessibility feature is turned on or off.\nBe carefull to know what you are doing if you uncheck it as then the keyboard accessibility settings will always be applied without confirmation.") );
602 kNotifyAccessX = new QCheckBox(i18n("Use KDE's system notification mechanism whenever a keyboard accessibility feature is turned on or off"), grp);
603 vvbox->addWidget(kNotifyAccessX);
605 hbox = new QHBoxLayout();
606 vvbox->addItem(hbox);
607 hbox->setSpacing(KDialog::spacingHint());
608 hbox->addStretch(1);
609 kNotifyAccessXButton = new QPushButton(i18n("Configure &Notifications..."), grp);
610 kNotifyAccessXButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
611 hbox->addWidget(kNotifyAccessXButton);
613 connect(gestures, SIGNAL(clicked()), this, SLOT(configChanged()));
614 connect(timeout, SIGNAL(clicked()), this, SLOT(configChanged()));
615 connect(timeout, SIGNAL(clicked()), this, SLOT(checkAccess()));
616 connect(timeoutDelay, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
617 connect(accessxBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
618 connect(gestureConfirmation, SIGNAL(clicked()), this, SLOT(configChanged()));
619 connect(kNotifyAccessX, SIGNAL(clicked()), this, SLOT(configChanged()));
620 connect(kNotifyAccessX, SIGNAL(clicked()), this, SLOT(checkAccess()));
621 connect(kNotifyAccessXButton, SIGNAL(clicked()), this, SLOT(configureKNotify()));
623 vbox->addStretch();
625 tab->addTab(features, i18n("Activation Gestures"));
627 load();
631 KAccessConfig::~KAccessConfig()
635 void KAccessConfig::configureKNotify()
637 KNotifyConfigWidget::configure (this, "kaccess");
640 void KAccessConfig::changeFlashScreenColor()
642 invertScreen->setChecked(false);
643 flashScreen->setChecked(true);
644 configChanged();
647 void KAccessConfig::selectSound()
649 QStringList list = KGlobal::dirs()->findDirs("sound", "");
650 QString start;
651 if (list.count()>0)
652 start = list[0];
653 // TODO: Why only wav's? How can I find out what artsd supports?
654 QString fname = KFileDialog::getOpenFileName(start, i18n("*.wav|WAV Files"));
655 if (!fname.isEmpty())
656 soundEdit->setText(fname);
660 void KAccessConfig::configChanged()
662 emit changed(true);
666 void KAccessConfig::load()
668 KConfigGroup cg(KSharedConfig::openConfig("kaccessrc"), "Bell");
670 systemBell->setChecked(cg.readEntry("SystemBell", true));
671 customBell->setChecked(cg.readEntry("ArtsBell", false));
672 soundEdit->setText(cg.readPathEntry("ArtsBellFile", QString()));
674 visibleBell->setChecked(cg.readEntry("VisibleBell", false));
675 invertScreen->setChecked(cg.readEntry("VisibleBellInvert", true));
676 flashScreen->setChecked(!invertScreen->isChecked());
677 colorButton->setColor(cg.readEntry("VisibleBellColor", QColor(Qt::red)));
679 durationSlider->setValue(cg.readEntry("VisibleBellPause", 500));
681 KConfigGroup keyboardGroup(KSharedConfig::openConfig("kaccessrc"),"Keyboard");
683 stickyKeys->setChecked(keyboardGroup.readEntry("StickyKeys", false));
684 stickyKeysLock->setChecked(keyboardGroup.readEntry("StickyKeysLatch", true));
685 stickyKeysAutoOff->setChecked(keyboardGroup.readEntry("StickyKeysAutoOff", false));
686 stickyKeysBeep->setChecked(keyboardGroup.readEntry("StickyKeysBeep", true));
687 toggleKeysBeep->setChecked(keyboardGroup.readEntry("ToggleKeysBeep", false));
688 kNotifyModifiers->setChecked(keyboardGroup.readEntry("kNotifyModifiers", false));
690 slowKeys->setChecked(keyboardGroup.readEntry("SlowKeys", false));
691 slowKeysDelay->setValue(keyboardGroup.readEntry("SlowKeysDelay", 500));
692 slowKeysPressBeep->setChecked(keyboardGroup.readEntry("SlowKeysPressBeep", true));
693 slowKeysAcceptBeep->setChecked(keyboardGroup.readEntry("SlowKeysAcceptBeep", true));
694 slowKeysRejectBeep->setChecked(keyboardGroup.readEntry("SlowKeysRejectBeep", true));
696 bounceKeys->setChecked(keyboardGroup.readEntry("BounceKeys", false));
697 bounceKeysDelay->setValue(keyboardGroup.readEntry("BounceKeysDelay", 500));
698 bounceKeysRejectBeep->setChecked(keyboardGroup.readEntry("BounceKeysRejectBeep", true));
700 gestures->setChecked(keyboardGroup.readEntry("Gestures", true));
701 timeout->setChecked(keyboardGroup.readEntry("AccessXTimeout", false));
702 timeoutDelay->setValue(keyboardGroup.readEntry("AccessXTimeoutDelay", 30));
704 accessxBeep->setChecked(keyboardGroup.readEntry("AccessXBeep", true));
705 gestureConfirmation->setChecked(keyboardGroup.readEntry("GestureConfirmation", false));
706 kNotifyAccessX->setChecked(keyboardGroup.readEntry("kNotifyAccessX", false));
708 checkAccess();
710 emit changed(false);
714 void KAccessConfig::save()
716 KConfigGroup cg(KSharedConfig::openConfig("kaccessrc"), "Bell");
718 cg.writeEntry("SystemBell", systemBell->isChecked());
719 cg.writeEntry("ArtsBell", customBell->isChecked());
720 cg.writePathEntry("ArtsBellFile", soundEdit->text());
722 cg.writeEntry("VisibleBell", visibleBell->isChecked());
723 cg.writeEntry("VisibleBellInvert", invertScreen->isChecked());
724 cg.writeEntry("VisibleBellColor", colorButton->color());
726 cg.writeEntry("VisibleBellPause", durationSlider->value());
728 KConfigGroup keyboardGroup(KSharedConfig::openConfig("kaccessrc"),"Keyboard");
730 keyboardGroup.writeEntry("StickyKeys", stickyKeys->isChecked());
731 keyboardGroup.writeEntry("StickyKeysLatch", stickyKeysLock->isChecked());
732 keyboardGroup.writeEntry("StickyKeysAutoOff", stickyKeysAutoOff->isChecked());
733 keyboardGroup.writeEntry("StickyKeysBeep", stickyKeysBeep->isChecked());
734 keyboardGroup.writeEntry("ToggleKeysBeep", toggleKeysBeep->isChecked());
735 keyboardGroup.writeEntry("kNotifyModifiers", kNotifyModifiers->isChecked());
737 keyboardGroup.writeEntry("SlowKeys", slowKeys->isChecked());
738 keyboardGroup.writeEntry("SlowKeysDelay", slowKeysDelay->value());
739 keyboardGroup.writeEntry("SlowKeysPressBeep", slowKeysPressBeep->isChecked());
740 keyboardGroup.writeEntry("SlowKeysAcceptBeep", slowKeysAcceptBeep->isChecked());
741 keyboardGroup.writeEntry("SlowKeysRejectBeep", slowKeysRejectBeep->isChecked());
744 keyboardGroup.writeEntry("BounceKeys", bounceKeys->isChecked());
745 keyboardGroup.writeEntry("BounceKeysDelay", bounceKeysDelay->value());
746 keyboardGroup.writeEntry("BounceKeysRejectBeep", bounceKeysRejectBeep->isChecked());
748 keyboardGroup.writeEntry("Gestures", gestures->isChecked());
749 keyboardGroup.writeEntry("AccessXTimeout", timeout->isChecked());
750 keyboardGroup.writeEntry("AccessXTimeoutDelay", timeoutDelay->value());
752 keyboardGroup.writeEntry("AccessXBeep", accessxBeep->isChecked());
753 keyboardGroup.writeEntry("GestureConfirmation", gestureConfirmation->isChecked());
754 keyboardGroup.writeEntry("kNotifyAccessX", kNotifyAccessX->isChecked());
757 cg.sync();
758 keyboardGroup.sync();
760 if (systemBell->isChecked() ||
761 customBell->isChecked() ||
762 visibleBell->isChecked())
764 KConfig _cfg("kdeglobals", KConfig::NoGlobals);
765 KConfigGroup cfg(&_cfg, "General");
766 cfg.writeEntry("UseSystemBell", true);
767 cfg.sync();
770 // make kaccess reread the configuration
771 // When turning things off, it needs to be done by kaccess,
772 // so don't actually kill it *shrug*.
773 if ( true /*needToRunKAccessDaemon( config )*/ )
774 KToolInvocation::startServiceByDesktopName("kaccess");
776 else // don't need it -> kill it
778 #ifdef __GNUC__
779 #warning "kde4: dbus port: need to test it"
780 #endif
781 QDBusInterface kaccess("org.kde.kaccess", "/KAccess", "org.kde.kaccess.KAccess");
782 kaccess.call("quit");
783 //DCOPRef kaccess( "kaccess", "qt/kaccess" );
784 //kaccess.send( "quit" );
787 emit changed(false);
791 void KAccessConfig::defaults()
793 systemBell->setChecked(true);
794 customBell->setChecked(false);
795 soundEdit->setText("");
797 visibleBell->setChecked(false);
798 invertScreen->setChecked(true);
799 flashScreen->setChecked(false);
800 colorButton->setColor(QColor(Qt::red));
802 durationSlider->setValue(500);
804 slowKeys->setChecked(false);
805 slowKeysDelay->setValue(500);
806 slowKeysPressBeep->setChecked(true);
807 slowKeysAcceptBeep->setChecked(true);
808 slowKeysRejectBeep->setChecked(true);
810 bounceKeys->setChecked(false);
811 bounceKeysDelay->setValue(500);
812 bounceKeysRejectBeep->setChecked(true);
814 stickyKeys->setChecked(false);
815 stickyKeysLock->setChecked(true);
816 stickyKeysAutoOff->setChecked(false);
817 stickyKeysBeep->setChecked(true);
818 toggleKeysBeep->setChecked(false);
819 kNotifyModifiers->setChecked(false);
821 gestures->setChecked(true);
822 timeout->setChecked(false);
823 timeoutDelay->setValue(30);
825 accessxBeep->setChecked(true);
826 gestureConfirmation->setChecked(true);
827 kNotifyAccessX->setChecked(false);
829 checkAccess();
831 emit changed(true);
835 void KAccessConfig::invertClicked()
837 flashScreen->setChecked(false);
841 void KAccessConfig::flashClicked()
843 invertScreen->setChecked(false);
847 void KAccessConfig::checkAccess()
849 bool custom = customBell->isChecked();
850 soundEdit->setEnabled(custom);
851 soundButton->setEnabled(custom);
852 soundLabel->setEnabled(custom);
854 bool visible = visibleBell->isChecked();
855 invertScreen->setEnabled(visible);
856 flashScreen->setEnabled(visible);
857 colorButton->setEnabled(visible);
858 durationSlider->setEnabled(visible);
860 bool sticky = stickyKeys->isChecked();
861 stickyKeysLock->setEnabled(sticky);
862 stickyKeysAutoOff->setEnabled(sticky);
863 stickyKeysBeep->setEnabled(sticky);
865 bool slow = slowKeys->isChecked();
866 slowKeysDelay->setEnabled(slow);
867 slowKeysPressBeep->setEnabled(slow);
868 slowKeysAcceptBeep->setEnabled(slow);
869 slowKeysRejectBeep->setEnabled(slow);
871 bool bounce = bounceKeys->isChecked();
872 bounceKeysDelay->setEnabled(bounce);
873 bounceKeysRejectBeep->setEnabled(bounce);
875 bool useTimeout = timeout->isChecked();
876 timeoutDelay->setEnabled(useTimeout);
879 extern "C"
881 /* This one gets called by kcminit
884 KDE_EXPORT void kcminit_access()
886 KConfig *config = new KConfig( "kaccessrc", KConfig::NoGlobals );
887 bool run = needToRunKAccessDaemon( config );
889 delete config;
890 if (run)
891 KToolInvocation::startServiceByDesktopName("kaccess");