not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / access / kcmaccess.cpp
blob7178d1dfc3a4a1a9f386f6a1442d085422104b6c
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);
61 KIntNumInput::setSliderEnabled (withSlider);
63 if (withSlider) {
64 disconnect(slider(), SIGNAL(valueChanged(int)),
65 spinBox(), SLOT(setValue(int)));
66 disconnect(spinBox(), SIGNAL(valueChanged(int)),
67 this, SLOT(spinValueChanged(int)));
69 this->min = min;
70 this->max = max;
71 sliderMax = (int)floor (0.5
72 + 2*(log((double)max)-log((double)min)) / (log((double)max)-log((double)max-1)));
73 slider()->setRange(0, sliderMax);
74 slider()->setSingleStep(step);
75 slider()->setPageStep(sliderMax/10);
76 slider()->setTickInterval(sliderMax/10);
78 double alpha = sliderMax / (log((double)max) - log((double)min));
79 double logVal = alpha * (log((double)value())-log((double)min));
80 slider()->setValue ((int)floor (0.5 + logVal));
82 connect(slider(), SIGNAL(valueChanged(int)),
83 this, SLOT(slotSliderValueChanged(int)));
84 connect(spinBox(), SIGNAL(valueChanged(int)),
85 this, SLOT(slotSpinValueChanged(int)));
89 // Basically the slider values are logarithmic whereas
90 // spinbox values are linear.
92 void ExtendedIntNumInput::slotSpinValueChanged(int val)
95 if(slider()) {
96 double alpha = sliderMax / (log((double)max) - log((double)min));
97 double logVal = alpha * (log((double)val)-log((double)min));
98 slider()->setValue ((int)floor (0.5 + logVal));
101 emit valueChanged(val);
104 void ExtendedIntNumInput::slotSliderValueChanged(int val)
106 double alpha = sliderMax / (log((double)max) - log((double)min));
107 double linearVal = exp (val/alpha + log((double)min));
108 spinBox()->setValue ((int)floor(0.5 + linearVal));
111 static bool needToRunKAccessDaemon( KConfig *config )
113 // We always start the KAccess Daemon, if it is not needed,
114 // it will terminate itself after configuring the AccessX
115 // features.
116 return true;
119 QString mouseKeysShortcut (Display *display) {
120 // Calculate the keycode
121 KeySym sym = XK_MouseKeys_Enable;
122 KeyCode code = XKeysymToKeycode(display, sym);
123 if (code == 0) {
124 sym = XK_Pointer_EnableKeys;
125 code = XKeysymToKeycode(display, sym);
126 if (code == 0)
127 return ""; // No shortcut available?
130 // Calculate the modifiers by searching the keysym in the X keyboard mapping
131 XkbDescPtr xkbdesc = XkbGetMap(display, XkbKeyTypesMask | XkbKeySymsMask, XkbUseCoreKbd);
132 if (!xkbdesc)
133 return ""; // Failed to obtain the mapping from server
135 bool found = false;
136 unsigned char modifiers = 0;
137 int groups = XkbKeyNumGroups(xkbdesc, code);
138 for (int grp = 0; grp < groups && !found; grp++)
140 int levels = XkbKeyGroupWidth(xkbdesc, code, grp);
141 for (int level = 0; level < levels && !found; level++)
143 if (sym == XkbKeySymEntry(xkbdesc, code, level, grp))
145 // keysym found => determine modifiers
146 int typeIdx = xkbdesc->map->key_sym_map[code].kt_index[grp];
147 XkbKeyTypePtr type = &(xkbdesc->map->types[typeIdx]);
148 for (int i = 0; i < type->map_count && !found; i++)
150 if (type->map[i].active && (type->map[i].level == level))
152 modifiers = type->map[i].mods.mask;
153 found = true;
159 XkbFreeClientMap (xkbdesc, 0, true);
161 if (!found)
162 return ""; // Somehow the keycode -> keysym mapping is flawed
164 XEvent ev;
165 ev.xkey.display = display;
166 ev.xkey.keycode = code;
167 ev.xkey.state = 0;
168 int key;
169 KKeyServer::xEventToQt(&ev, &key);
170 QString keyname = QKeySequence(key).toString();
172 unsigned int AltMask = KKeyServer::modXAlt();
173 unsigned int WinMask = KKeyServer::modXMeta();
174 unsigned int NumMask = KKeyServer::modXNumLock();
175 unsigned int ScrollMask= KKeyServer::modXScrollLock();
177 unsigned int MetaMask = XkbKeysymToModifiers (display, XK_Meta_L);
178 unsigned int SuperMask = XkbKeysymToModifiers (display, XK_Super_L);
179 unsigned int HyperMask = XkbKeysymToModifiers (display, XK_Hyper_L);
180 unsigned int AltGrMask = XkbKeysymToModifiers (display, XK_Mode_switch)
181 | XkbKeysymToModifiers (display, XK_ISO_Level3_Shift)
182 | XkbKeysymToModifiers (display, XK_ISO_Level3_Latch)
183 | XkbKeysymToModifiers (display, XK_ISO_Level3_Lock);
185 unsigned int mods = ShiftMask | ControlMask | AltMask | WinMask
186 | LockMask | NumMask | ScrollMask;
188 AltGrMask &= ~mods;
189 MetaMask &= ~(mods | AltGrMask);
190 SuperMask &= ~(mods | AltGrMask | MetaMask);
191 HyperMask &= ~(mods | AltGrMask | MetaMask | SuperMask);
193 if ((modifiers & AltGrMask) != 0)
194 keyname = i18n("AltGraph") + '+' + keyname;
195 if ((modifiers & HyperMask) != 0)
196 keyname = i18n("Hyper") + '+' + keyname;
197 if ((modifiers & SuperMask) != 0)
198 keyname = i18n("Super") + '+' + keyname;
199 if ((modifiers & WinMask) != 0)
200 keyname = QKeySequence(Qt::META).toString() + '+' + keyname;
201 if ((modifiers & AltMask) != 0)
202 keyname = QKeySequence(Qt::ALT).toString() + '+' + keyname;
203 if ((modifiers & ControlMask) != 0)
204 keyname = QKeySequence(Qt::CTRL).toString() + '+' + keyname;
205 if ((modifiers & ShiftMask) != 0)
206 keyname = QKeySequence(Qt::SHIFT).toString() + '+' + keyname;
208 QString result;
209 if ((modifiers & ScrollMask) != 0)
210 if ((modifiers & LockMask) != 0)
211 if ((modifiers & NumMask) != 0)
212 result = i18n("Press %1 while NumLock, CapsLock and ScrollLock are active", keyname);
213 else
214 result = i18n("Press %1 while CapsLock and ScrollLock are active", keyname);
215 else if ((modifiers & NumMask) != 0)
216 result = i18n("Press %1 while NumLock and ScrollLock are active", keyname);
217 else
218 result = i18n("Press %1 while ScrollLock is active", keyname);
219 else if ((modifiers & LockMask) != 0)
220 if ((modifiers & NumMask) != 0)
221 result = i18n("Press %1 while NumLock and CapsLock are active", keyname);
222 else
223 result = i18n("Press %1 while CapsLock is active", keyname);
224 else if ((modifiers & NumMask) != 0)
225 result = i18n("Press %1 while NumLock is active", keyname);
226 else
227 result = i18n("Press %1", keyname);
229 return result;
232 KAccessConfig::KAccessConfig(QWidget *parent, const QStringList& args)
233 : KCModule(KAccessConfigFactory::componentData(), parent, args)
236 KAboutData *about =
237 new KAboutData(I18N_NOOP("kaccess"), 0, ki18n("KDE Accessibility Tool"),
238 0, KLocalizedString(), KAboutData::License_GPL,
239 ki18n("(c) 2000, Matthias Hoelzer-Kluepfel"));
241 about->addAuthor(ki18n("Matthias Hoelzer-Kluepfel"), ki18n("Author") , "hoelzer@kde.org");
243 setAboutData( about );
245 QVBoxLayout *main = new QVBoxLayout(this);
246 main->setMargin(0);
247 main->setSpacing(KDialog::spacingHint());
248 QTabWidget *tab = new QTabWidget(this);
249 main->addWidget(tab);
251 // bell settings ---------------------------------------
252 QWidget *bell = new QWidget(this);
254 QVBoxLayout *vbox = new QVBoxLayout(bell);
255 vbox->setMargin(KDialog::marginHint());
256 vbox->setSpacing(KDialog::spacingHint());
258 QGroupBox *grp = new QGroupBox(i18n("Audible Bell"), bell);
259 QHBoxLayout *layout = new QHBoxLayout;
260 grp->setLayout(layout);
261 vbox->addWidget(grp);
263 QVBoxLayout *vvbox = new QVBoxLayout();
264 layout->addLayout( vvbox );
265 vvbox->setSpacing( KDialog::spacingHint() );
267 systemBell = new QCheckBox(i18n("Use &system bell"), grp);
268 vvbox->addWidget(systemBell);
269 customBell = new QCheckBox(i18n("Us&e customized bell"), grp);
270 vvbox->addWidget(customBell);
271 systemBell->setWhatsThis( i18n("If this option is checked, the default system bell will be used. See the"
272 " \"System Bell\" control module for how to customize the system bell."
273 " Normally, this is just a \"beep\".") );
274 customBell->setWhatsThis( i18n("<p>Check this option if you want to use a customized bell, playing"
275 " a sound file. If you do this, you will probably want to turn off the system bell.</p><p> Please note"
276 " that on slow machines this may cause a \"lag\" between the event causing the bell and the sound being played.</p>") );
278 QHBoxLayout *hbox = new QHBoxLayout();
279 vvbox->addItem( hbox );
280 hbox->setSpacing(KDialog::spacingHint());
281 hbox->addSpacing(24);
282 soundEdit = new QLineEdit(grp);
283 soundLabel = new QLabel(i18n("Sound &to play:"), grp);
284 soundLabel->setBuddy(soundEdit);
285 hbox->addWidget(soundLabel);
286 hbox->addWidget(soundEdit);
287 soundButton = new QPushButton(i18n("Browse..."), grp);
288 hbox->addWidget(soundButton);
289 QString wtstr = i18n("If the option \"Use customized bell\" is enabled, you can choose a sound file here."
290 " Click \"Browse...\" to choose a sound file using the file dialog.");
291 soundEdit->setWhatsThis( wtstr );
292 soundLabel->setWhatsThis( wtstr );
293 soundButton->setWhatsThis( wtstr );
295 connect(soundButton, SIGNAL(clicked()), this, SLOT(selectSound()));
297 connect(customBell, SIGNAL(clicked()), this, SLOT(checkAccess()));
299 connect(systemBell, SIGNAL(clicked()), this, SLOT(configChanged()));
300 connect(customBell, SIGNAL(clicked()), this, SLOT(configChanged()));
301 connect(soundEdit, SIGNAL(textChanged(const QString&)), this, SLOT(configChanged()));
303 // -----------------------------------------------------
305 // visible bell ----------------------------------------
306 grp = new QGroupBox(i18n("Visible Bell"), bell);
307 layout = new QHBoxLayout;
308 grp->setLayout(layout);
309 vbox->addWidget(grp);
311 vvbox = new QVBoxLayout();
312 layout->addLayout( vvbox );
313 vvbox->setSpacing(KDialog::spacingHint());
315 visibleBell = new QCheckBox(i18n("&Use visible bell"), grp);
316 vvbox->addWidget(visibleBell);
317 visibleBell->setWhatsThis( i18n("This option will turn on the \"visible bell\", i.e. a visible"
318 " notification shown every time that normally just a bell would occur. This is especially useful"
319 " for deaf people.") );
321 hbox = new QHBoxLayout();
322 vvbox->addItem(hbox);
323 hbox->setSpacing(KDialog::spacingHint());
324 hbox->addSpacing(24);
325 invertScreen = new QRadioButton(i18n("I&nvert screen"), grp);
326 hbox->addWidget(invertScreen);
327 hbox = new QHBoxLayout();
328 vvbox->addItem(hbox);
329 hbox->setSpacing(KDialog::spacingHint());
330 invertScreen->setWhatsThis( i18n("All screen colors will be inverted for the amount of time specified below.") );
331 hbox->addSpacing(24);
332 flashScreen = new QRadioButton(i18n("F&lash screen"), grp);
333 hbox->addWidget(flashScreen);
334 flashScreen->setWhatsThis( i18n("The screen will turn to a custom color for the amount of time specified below.") );
335 hbox->addSpacing(12);
336 colorButton = new KColorButton(grp);
337 colorButton->setFixedWidth(colorButton->sizeHint().height()*2);
338 hbox->addWidget(colorButton);
339 hbox->addStretch();
340 colorButton->setWhatsThis( i18n("Click here to choose the color used for the \"flash screen\" visible bell.") );
342 hbox = new QHBoxLayout();
343 vvbox->addItem(hbox);
344 hbox->setSpacing(KDialog::spacingHint());
345 hbox->addSpacing(24);
347 durationSlider = new ExtendedIntNumInput(grp);
348 durationSlider->setRange(100, 2000, 100);
349 durationSlider->setLabel(i18n("Duration:"));
350 durationSlider->setSuffix(i18n(" msec"));
351 hbox->addWidget(durationSlider);
352 durationSlider->setWhatsThis( i18n("Here you can customize the duration of the \"visible bell\" effect being shown.") );
354 connect(invertScreen, SIGNAL(clicked()), this, SLOT(configChanged()));
355 connect(flashScreen, SIGNAL(clicked()), this, SLOT(configChanged()));
356 connect(visibleBell, SIGNAL(clicked()), this, SLOT(configChanged()));
357 connect(visibleBell, SIGNAL(clicked()), this, SLOT(checkAccess()));
358 connect(colorButton, SIGNAL(clicked()), this, SLOT(changeFlashScreenColor()));
360 connect(invertScreen, SIGNAL(clicked()), this, SLOT(invertClicked()));
361 connect(flashScreen, SIGNAL(clicked()), this, SLOT(flashClicked()));
363 connect(durationSlider, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
365 vbox->addStretch();
367 // -----------------------------------------------------
369 tab->addTab(bell, i18n("&Bell"));
372 // modifier key settings -------------------------------
373 QWidget *modifiers = new QWidget(this);
375 vbox = new QVBoxLayout(modifiers);
376 vbox->setMargin(KDialog::marginHint());
377 vbox->setSpacing(KDialog::spacingHint());
379 grp = new QGroupBox(i18n("S&ticky Keys"), modifiers);
380 layout = new QHBoxLayout;
381 grp->setLayout(layout);
382 vbox->addWidget(grp);
384 vvbox = new QVBoxLayout();
385 layout->addLayout(vvbox);
386 vvbox->setSpacing(KDialog::spacingHint());
388 stickyKeys = new QCheckBox(i18n("Use &sticky keys"), grp);
389 vvbox->addWidget(stickyKeys);
391 hbox = new QHBoxLayout();
392 vvbox->addItem(hbox);
393 hbox->setSpacing(KDialog::spacingHint());
394 hbox->addSpacing(24);
395 stickyKeysLock = new QCheckBox(i18n("&Lock sticky keys"), grp);
396 hbox->addWidget(stickyKeysLock);
398 hbox = new QHBoxLayout();
399 vvbox->addItem(hbox);
400 hbox->setSpacing(KDialog::spacingHint());
401 hbox->addSpacing(24);
402 stickyKeysAutoOff = new QCheckBox(i18n("Turn sticky keys off when two keys are pressed simultaneously"), grp);
403 hbox->addWidget(stickyKeysAutoOff);
405 hbox = new QHBoxLayout();
406 vvbox->addItem(hbox);
407 hbox->setSpacing(KDialog::spacingHint());
408 hbox->addSpacing(24);
409 stickyKeysBeep = new QCheckBox(i18n("Use system bell whenever a modifier gets latched, locked or unlocked"), grp);
410 hbox->addWidget(stickyKeysBeep);
412 grp = new QGroupBox(i18n("Locking Keys"), modifiers);
413 layout = new QHBoxLayout;
414 grp->setLayout(layout);
415 vbox->addWidget(grp);
417 vvbox = new QVBoxLayout();
418 layout->addLayout(vvbox);
419 vvbox->setSpacing(KDialog::spacingHint());
421 toggleKeysBeep = new QCheckBox(i18n("Use system bell whenever a locking key gets activated or deactivated"), grp);
422 vvbox->addWidget(toggleKeysBeep);
424 kNotifyModifiers = new QCheckBox(i18n("Use KDE's system notification mechanism whenever a modifier or locking key changes its state"), grp);
425 vvbox->addWidget(kNotifyModifiers);
427 hbox = new QHBoxLayout();
428 vvbox->addItem(hbox);
429 hbox->setSpacing(KDialog::spacingHint());
430 hbox->addStretch(1);
431 kNotifyModifiersButton = new QPushButton(i18n("Configure &Notifications..."), grp);
432 kNotifyModifiersButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
433 hbox->addWidget(kNotifyModifiersButton);
435 connect(stickyKeys, SIGNAL(clicked()), this, SLOT(configChanged()));
436 connect(stickyKeysLock, SIGNAL(clicked()), this, SLOT(configChanged()));
437 connect(stickyKeysAutoOff, SIGNAL(clicked()), this, SLOT(configChanged()));
438 connect(stickyKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
440 connect(stickyKeysBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
441 connect(toggleKeysBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
442 connect(kNotifyModifiers, SIGNAL(clicked()), this, SLOT(configChanged()));
443 connect(kNotifyModifiers, SIGNAL(clicked()), this, SLOT(checkAccess()));
444 connect(kNotifyModifiersButton, SIGNAL(clicked()), this, SLOT(configureKNotify()));
446 vbox->addStretch();
448 tab->addTab(modifiers, i18n("&Modifier Keys"));
450 // key filter settings ---------------------------------
451 QWidget *filters = new QWidget(this);
453 vbox = new QVBoxLayout(filters);
454 vbox->setMargin(KDialog::marginHint());
455 vbox->setSpacing(KDialog::spacingHint());
456 grp = new QGroupBox(i18n("Slo&w Keys"), filters);
457 layout = new QHBoxLayout;
458 grp->setLayout(layout);
459 vbox->addWidget(grp);
461 vvbox = new QVBoxLayout();
462 layout->addLayout(vvbox);
463 vvbox->setSpacing(KDialog::spacingHint());
465 slowKeys = new QCheckBox(i18n("&Use slow keys"), grp);
466 vvbox->addWidget(slowKeys);
468 hbox = new QHBoxLayout();
469 vvbox->addItem(hbox);
470 hbox->setSpacing(KDialog::spacingHint());
471 hbox->addSpacing(24);
472 slowKeysDelay = new ExtendedIntNumInput(grp);
473 slowKeysDelay->setSuffix(i18n(" msec"));
474 slowKeysDelay->setRange(50, 10000, 100);
475 slowKeysDelay->setLabel(i18n("Acceptance dela&y:"), Qt::AlignVCenter|Qt::AlignLeft);
476 hbox->addWidget(slowKeysDelay);
478 hbox = new QHBoxLayout();
479 vvbox->addItem(hbox);
480 hbox->setSpacing(KDialog::spacingHint());
481 hbox->addSpacing(24);
482 slowKeysPressBeep = new QCheckBox(i18n("&Use system bell whenever a key is pressed"), grp);
483 hbox->addWidget(slowKeysPressBeep);
485 hbox = new QHBoxLayout();
486 vvbox->addItem(hbox);
487 hbox->setSpacing(KDialog::spacingHint());
488 hbox->addSpacing(24);
489 slowKeysAcceptBeep = new QCheckBox(i18n("&Use system bell whenever a key is accepted"), grp);
490 hbox->addWidget(slowKeysAcceptBeep);
492 hbox = new QHBoxLayout();
493 vvbox->addItem(hbox);
494 hbox->setSpacing(KDialog::spacingHint());
495 hbox->addSpacing(24);
496 slowKeysRejectBeep = new QCheckBox(i18n("&Use system bell whenever a key is rejected"), grp);
497 hbox->addWidget(slowKeysRejectBeep);
499 grp = new QGroupBox(i18n("Bounce Keys"), filters);
500 layout= new QHBoxLayout;
501 grp->setLayout(layout);
502 vbox->addWidget(grp);
504 vvbox = new QVBoxLayout();
505 layout->addLayout( vvbox );
506 vvbox->setSpacing(KDialog::spacingHint());
508 bounceKeys = new QCheckBox(i18n("Use bou&nce keys"), grp);
509 vvbox->addWidget(bounceKeys);
511 hbox = new QHBoxLayout();
512 vvbox->addItem(hbox);
513 hbox->setSpacing(KDialog::spacingHint());
514 hbox->addSpacing(24);
515 bounceKeysDelay = new ExtendedIntNumInput(grp);
516 bounceKeysDelay->setSuffix(i18n(" msec"));
517 bounceKeysDelay->setRange(100, 5000, 100);
518 bounceKeysDelay->setLabel(i18n("D&ebounce time:"), Qt::AlignVCenter|Qt::AlignLeft);;
519 hbox->addWidget(bounceKeysDelay);
521 hbox = new QHBoxLayout();
522 vvbox->addItem(hbox);
523 hbox->setSpacing(KDialog::spacingHint());
524 hbox->addSpacing(24);
525 bounceKeysRejectBeep = new QCheckBox(i18n("Use the system bell whenever a key is rejected"), grp);
526 hbox->addWidget(bounceKeysRejectBeep);
528 connect(slowKeysDelay, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
529 connect(slowKeys, SIGNAL(clicked()), this, SLOT(configChanged()));
530 connect(slowKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
532 connect(slowKeysPressBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
533 connect(slowKeysAcceptBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
534 connect(slowKeysRejectBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
536 connect(bounceKeysDelay, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
537 connect(bounceKeys, SIGNAL(clicked()), this, SLOT(configChanged()));
538 connect(bounceKeysRejectBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
539 connect(bounceKeys, SIGNAL(clicked()), this, SLOT(checkAccess()));
541 vbox->addStretch();
543 tab->addTab(filters, i18n("&Keyboard Filters"));
545 // gestures --------------------------------------------
546 QWidget *features = new QWidget(this);
548 vbox = new QVBoxLayout(features);
549 vbox->setMargin(KDialog::marginHint());
550 vbox->setSpacing(KDialog::spacingHint());
552 grp = new QGroupBox(i18n("Activation Gestures"), features);
553 layout = new QHBoxLayout;
554 grp->setLayout(layout);
555 vbox->addWidget(grp);
557 vvbox = new QVBoxLayout();
558 layout->addLayout( vvbox );
559 vvbox->setSpacing(KDialog::spacingHint());
561 gestures = new QCheckBox(i18n("Use gestures for activating sticky keys and slow keys"), grp);
562 vvbox->addWidget(gestures);
563 QString shortcut = mouseKeysShortcut(x11Info().display());
564 if (shortcut.isEmpty())
565 gestures->setWhatsThis( i18n("Here you can activate keyboard gestures that turn on the following features: \n"
566 "Sticky keys: Press Shift key 5 consecutive times\n"
567 "Slow keys: Hold down Shift for 8 seconds"));
568 else
569 gestures->setWhatsThis( i18n("Here you can activate keyboard gestures that turn on the following features: \n"
570 "Mouse Keys: %1\n"
571 "Sticky keys: Press Shift key 5 consecutive times\n"
572 "Slow keys: Hold down Shift for 8 seconds", shortcut));
574 timeout = new QCheckBox(i18n("Turn sticky keys and slow keys off after a certain period of inactivity."), grp);
575 vvbox->addWidget(timeout);
577 hbox = new QHBoxLayout();
578 vvbox->addItem(hbox);
579 hbox->setSpacing(KDialog::spacingHint());
580 hbox->addSpacing(24);
581 timeoutDelay = new KIntNumInput(grp);
582 timeoutDelay->setSuffix(i18n(" min"));
583 timeoutDelay->setRange(1, 30, 4);
584 timeoutDelay->setLabel(i18n("Timeout:"), Qt::AlignVCenter|Qt::AlignLeft);;
585 hbox->addWidget(timeoutDelay);
587 grp = new QGroupBox(i18n("Notification"), features);
588 layout = new QHBoxLayout;
589 grp->setLayout(layout);
590 vbox->addWidget(grp);
592 vvbox = new QVBoxLayout();
593 layout->addLayout(vvbox);
594 vvbox->setSpacing(KDialog::spacingHint());
596 accessxBeep = new QCheckBox(i18n("Use the system bell whenever a gesture is used to turn an accessibility feature on or off"), grp);
597 vvbox->addWidget(accessxBeep);
599 gestureConfirmation = new QCheckBox(i18n("Show a confirmation dialog whenever a keyboard accessibility feature is turned on or off"), grp);
600 vvbox->addWidget(gestureConfirmation);
601 gestureConfirmation->setWhatsThis( i18n("If this option is checked, KDE will show a confirmation dialog whenever a keyboard accessibility feature is turned on or off.\nEnsure you know what you are doing if you uncheck it, as the keyboard accessibility settings will then always be applied without confirmation.") );
603 kNotifyAccessX = new QCheckBox(i18n("Use KDE's system notification mechanism whenever a keyboard accessibility feature is turned on or off"), grp);
604 vvbox->addWidget(kNotifyAccessX);
606 hbox = new QHBoxLayout();
607 vvbox->addItem(hbox);
608 hbox->setSpacing(KDialog::spacingHint());
609 hbox->addStretch(1);
610 kNotifyAccessXButton = new QPushButton(i18n("Configure &Notifications..."), grp);
611 kNotifyAccessXButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
612 hbox->addWidget(kNotifyAccessXButton);
614 connect(gestures, SIGNAL(clicked()), this, SLOT(configChanged()));
615 connect(timeout, SIGNAL(clicked()), this, SLOT(configChanged()));
616 connect(timeout, SIGNAL(clicked()), this, SLOT(checkAccess()));
617 connect(timeoutDelay, SIGNAL(valueChanged(int)), this, SLOT(configChanged()));
618 connect(accessxBeep, SIGNAL(clicked()), this, SLOT(configChanged()));
619 connect(gestureConfirmation, SIGNAL(clicked()), this, SLOT(configChanged()));
620 connect(kNotifyAccessX, SIGNAL(clicked()), this, SLOT(configChanged()));
621 connect(kNotifyAccessX, SIGNAL(clicked()), this, SLOT(checkAccess()));
622 connect(kNotifyAccessXButton, SIGNAL(clicked()), this, SLOT(configureKNotify()));
624 vbox->addStretch();
626 tab->addTab(features, i18n("Activation Gestures"));
630 KAccessConfig::~KAccessConfig()
634 void KAccessConfig::configureKNotify()
636 KNotifyConfigWidget::configure (this, "kaccess");
639 void KAccessConfig::changeFlashScreenColor()
641 invertScreen->setChecked(false);
642 flashScreen->setChecked(true);
643 configChanged();
646 void KAccessConfig::selectSound()
648 QStringList list = KGlobal::dirs()->findDirs("sound", "");
649 QString start;
650 if (list.count()>0)
651 start = list[0];
652 // TODO: Why only wav's? How can I find out what artsd supports?
653 QString fname = KFileDialog::getOpenFileName(start, i18n("*.wav|WAV Files"));
654 if (!fname.isEmpty())
655 soundEdit->setText(fname);
659 void KAccessConfig::configChanged()
661 emit changed(true);
665 void KAccessConfig::load()
667 KConfigGroup cg(KSharedConfig::openConfig("kaccessrc"), "Bell");
669 systemBell->setChecked(cg.readEntry("SystemBell", true));
670 customBell->setChecked(cg.readEntry("ArtsBell", false));
671 soundEdit->setText(cg.readPathEntry("ArtsBellFile", QString()));
673 visibleBell->setChecked(cg.readEntry("VisibleBell", false));
674 invertScreen->setChecked(cg.readEntry("VisibleBellInvert", true));
675 flashScreen->setChecked(!invertScreen->isChecked());
676 colorButton->setColor(cg.readEntry("VisibleBellColor", QColor(Qt::red)));
678 durationSlider->setValue(cg.readEntry("VisibleBellPause", 500));
680 KConfigGroup keyboardGroup(KSharedConfig::openConfig("kaccessrc"),"Keyboard");
682 stickyKeys->setChecked(keyboardGroup.readEntry("StickyKeys", false));
683 stickyKeysLock->setChecked(keyboardGroup.readEntry("StickyKeysLatch", true));
684 stickyKeysAutoOff->setChecked(keyboardGroup.readEntry("StickyKeysAutoOff", false));
685 stickyKeysBeep->setChecked(keyboardGroup.readEntry("StickyKeysBeep", true));
686 toggleKeysBeep->setChecked(keyboardGroup.readEntry("ToggleKeysBeep", false));
687 kNotifyModifiers->setChecked(keyboardGroup.readEntry("kNotifyModifiers", false));
689 slowKeys->setChecked(keyboardGroup.readEntry("SlowKeys", false));
690 slowKeysDelay->setValue(keyboardGroup.readEntry("SlowKeysDelay", 500));
691 slowKeysPressBeep->setChecked(keyboardGroup.readEntry("SlowKeysPressBeep", true));
692 slowKeysAcceptBeep->setChecked(keyboardGroup.readEntry("SlowKeysAcceptBeep", true));
693 slowKeysRejectBeep->setChecked(keyboardGroup.readEntry("SlowKeysRejectBeep", true));
695 bounceKeys->setChecked(keyboardGroup.readEntry("BounceKeys", false));
696 bounceKeysDelay->setValue(keyboardGroup.readEntry("BounceKeysDelay", 500));
697 bounceKeysRejectBeep->setChecked(keyboardGroup.readEntry("BounceKeysRejectBeep", true));
699 gestures->setChecked(keyboardGroup.readEntry("Gestures", true));
700 timeout->setChecked(keyboardGroup.readEntry("AccessXTimeout", false));
701 timeoutDelay->setValue(keyboardGroup.readEntry("AccessXTimeoutDelay", 30));
703 accessxBeep->setChecked(keyboardGroup.readEntry("AccessXBeep", true));
704 gestureConfirmation->setChecked(keyboardGroup.readEntry("GestureConfirmation", false));
705 kNotifyAccessX->setChecked(keyboardGroup.readEntry("kNotifyAccessX", false));
707 checkAccess();
709 emit changed(false);
713 void KAccessConfig::save()
715 KConfigGroup cg(KSharedConfig::openConfig("kaccessrc"), "Bell");
717 cg.writeEntry("SystemBell", systemBell->isChecked());
718 cg.writeEntry("ArtsBell", customBell->isChecked());
719 cg.writePathEntry("ArtsBellFile", soundEdit->text());
721 cg.writeEntry("VisibleBell", visibleBell->isChecked());
722 cg.writeEntry("VisibleBellInvert", invertScreen->isChecked());
723 cg.writeEntry("VisibleBellColor", colorButton->color());
725 cg.writeEntry("VisibleBellPause", durationSlider->value());
727 KConfigGroup keyboardGroup(KSharedConfig::openConfig("kaccessrc"),"Keyboard");
729 keyboardGroup.writeEntry("StickyKeys", stickyKeys->isChecked());
730 keyboardGroup.writeEntry("StickyKeysLatch", stickyKeysLock->isChecked());
731 keyboardGroup.writeEntry("StickyKeysAutoOff", stickyKeysAutoOff->isChecked());
732 keyboardGroup.writeEntry("StickyKeysBeep", stickyKeysBeep->isChecked());
733 keyboardGroup.writeEntry("ToggleKeysBeep", toggleKeysBeep->isChecked());
734 keyboardGroup.writeEntry("kNotifyModifiers", kNotifyModifiers->isChecked());
736 keyboardGroup.writeEntry("SlowKeys", slowKeys->isChecked());
737 keyboardGroup.writeEntry("SlowKeysDelay", slowKeysDelay->value());
738 keyboardGroup.writeEntry("SlowKeysPressBeep", slowKeysPressBeep->isChecked());
739 keyboardGroup.writeEntry("SlowKeysAcceptBeep", slowKeysAcceptBeep->isChecked());
740 keyboardGroup.writeEntry("SlowKeysRejectBeep", slowKeysRejectBeep->isChecked());
743 keyboardGroup.writeEntry("BounceKeys", bounceKeys->isChecked());
744 keyboardGroup.writeEntry("BounceKeysDelay", bounceKeysDelay->value());
745 keyboardGroup.writeEntry("BounceKeysRejectBeep", bounceKeysRejectBeep->isChecked());
747 keyboardGroup.writeEntry("Gestures", gestures->isChecked());
748 keyboardGroup.writeEntry("AccessXTimeout", timeout->isChecked());
749 keyboardGroup.writeEntry("AccessXTimeoutDelay", timeoutDelay->value());
751 keyboardGroup.writeEntry("AccessXBeep", accessxBeep->isChecked());
752 keyboardGroup.writeEntry("GestureConfirmation", gestureConfirmation->isChecked());
753 keyboardGroup.writeEntry("kNotifyAccessX", kNotifyAccessX->isChecked());
756 cg.sync();
757 keyboardGroup.sync();
759 if (systemBell->isChecked() ||
760 customBell->isChecked() ||
761 visibleBell->isChecked())
763 KConfig _cfg("kdeglobals", KConfig::NoGlobals);
764 KConfigGroup cfg(&_cfg, "General");
765 cfg.writeEntry("UseSystemBell", true);
766 cfg.sync();
769 // make kaccess reread the configuration
770 // When turning things off, it needs to be done by kaccess,
771 // so don't actually kill it *shrug*.
772 if ( true /*needToRunKAccessDaemon( config )*/ )
773 KToolInvocation::startServiceByDesktopName("kaccess");
775 else // don't need it -> kill it
777 #ifdef __GNUC__
778 #warning "kde4: dbus port: need to test it"
779 #endif
780 QDBusInterface kaccess("org.kde.kaccess", "/KAccess", "org.kde.kaccess.KAccess");
781 kaccess.call("quit");
782 //DCOPRef kaccess( "kaccess", "qt/kaccess" );
783 //kaccess.send( "quit" );
786 emit changed(false);
790 void KAccessConfig::defaults()
792 systemBell->setChecked(true);
793 customBell->setChecked(false);
794 soundEdit->setText("");
796 visibleBell->setChecked(false);
797 invertScreen->setChecked(true);
798 flashScreen->setChecked(false);
799 colorButton->setColor(QColor(Qt::red));
801 durationSlider->setValue(500);
803 slowKeys->setChecked(false);
804 slowKeysDelay->setValue(500);
805 slowKeysPressBeep->setChecked(true);
806 slowKeysAcceptBeep->setChecked(true);
807 slowKeysRejectBeep->setChecked(true);
809 bounceKeys->setChecked(false);
810 bounceKeysDelay->setValue(500);
811 bounceKeysRejectBeep->setChecked(true);
813 stickyKeys->setChecked(false);
814 stickyKeysLock->setChecked(true);
815 stickyKeysAutoOff->setChecked(false);
816 stickyKeysBeep->setChecked(true);
817 toggleKeysBeep->setChecked(false);
818 kNotifyModifiers->setChecked(false);
820 gestures->setChecked(true);
821 timeout->setChecked(false);
822 timeoutDelay->setValue(30);
824 accessxBeep->setChecked(true);
825 gestureConfirmation->setChecked(true);
826 kNotifyAccessX->setChecked(false);
828 checkAccess();
830 emit changed(true);
834 void KAccessConfig::invertClicked()
836 flashScreen->setChecked(false);
840 void KAccessConfig::flashClicked()
842 invertScreen->setChecked(false);
846 void KAccessConfig::checkAccess()
848 bool custom = customBell->isChecked();
849 soundEdit->setEnabled(custom);
850 soundButton->setEnabled(custom);
851 soundLabel->setEnabled(custom);
853 bool visible = visibleBell->isChecked();
854 invertScreen->setEnabled(visible);
855 flashScreen->setEnabled(visible);
856 colorButton->setEnabled(visible);
857 durationSlider->setEnabled(visible);
859 bool sticky = stickyKeys->isChecked();
860 stickyKeysLock->setEnabled(sticky);
861 stickyKeysAutoOff->setEnabled(sticky);
862 stickyKeysBeep->setEnabled(sticky);
864 bool slow = slowKeys->isChecked();
865 slowKeysDelay->setEnabled(slow);
866 slowKeysPressBeep->setEnabled(slow);
867 slowKeysAcceptBeep->setEnabled(slow);
868 slowKeysRejectBeep->setEnabled(slow);
870 bool bounce = bounceKeys->isChecked();
871 bounceKeysDelay->setEnabled(bounce);
872 bounceKeysRejectBeep->setEnabled(bounce);
874 bool useTimeout = timeout->isChecked();
875 timeoutDelay->setEnabled(useTimeout);
878 extern "C"
880 /* This one gets called by kcminit
883 KDE_EXPORT void kcminit_access()
885 KConfig *config = new KConfig( "kaccessrc", KConfig::NoGlobals );
886 bool run = needToRunKAccessDaemon( config );
888 delete config;
889 if (run)
890 KToolInvocation::startServiceByDesktopName("kaccess");