• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdeui
 

tdeui

  • tdeui
tdeshortcutdialog.cpp
1 /* This file is part of the KDE libraries
2  Copyright (C) 2002,2003 Ellis Whitehead <ellis@kde.org>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "tdeshortcutdialog.h"
21 
22 #include <tqvariant.h>
23 
24 #ifdef Q_WS_X11
25  #define XK_XKB_KEYS
26  #define XK_MISCELLANY
27  #include <X11/Xlib.h> // For x11Event()
28  #include <X11/keysymdef.h> // For XK_...
29 
30  #ifdef KeyPress
31  const int XKeyPress = KeyPress;
32  const int XKeyRelease = KeyRelease;
33  const int XFocusOut = FocusOut;
34  const int XFocusIn = FocusIn;
35  #undef KeyRelease
36  #undef KeyPress
37  #undef FocusOut
38  #undef FocusIn
39  #endif
40 #elif defined(Q_WS_WIN)
41 # include <kkeyserver.h>
42 #endif
43 
44 #include <tdeshortcutdialog_simple.h>
45 #include <tdeshortcutdialog_advanced.h>
46 
47 #include <tqbuttongroup.h>
48 #include <tqcheckbox.h>
49 #include <tqframe.h>
50 #include <tqlayout.h>
51 #include <tqradiobutton.h>
52 #include <tqtimer.h>
53 #include <tqvbox.h>
54 
55 #include <tdeapplication.h>
56 #include <tdeconfig.h>
57 #include <kdebug.h>
58 #include <tdeglobal.h>
59 #include <kiconloader.h>
60 #include <kkeynative.h>
61 #include <tdelocale.h>
62 #include <kstdguiitem.h>
63 #include <kpushbutton.h>
64 
65 bool TDEShortcutDialog::s_showMore = false;
66 
67 TDEShortcutDialog::TDEShortcutDialog( const TDEShortcut& shortcut, bool bQtShortcut, TQWidget* parent, const char* name )
68 : KDialogBase( parent, name, true, i18n("Configure Shortcut"),
69  KDialogBase::Details|KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Cancel, true )
70 {
71  setButtonText(Details, i18n("Advanced"));
72  m_stack = new TQVBox(this);
73  m_stack->setMinimumWidth(360);
74  m_stack->setSpacing(0);
75  m_stack->setMargin(0);
76  setMainWidget(m_stack);
77 
78  m_simple = new TDEShortcutDialogSimple(m_stack);
79 
80  m_adv = new TDEShortcutDialogAdvanced(m_stack);
81  m_adv->hide();
82 
83  m_bQtShortcut = bQtShortcut;
84 
85  m_bGrab = false;
86  m_iSeq = 0;
87  m_iKey = 0;
88  m_ptxtCurrent = 0;
89  m_bRecording = false;
90  m_mod = 0;
91 
92  m_simple->m_btnClearShortcut->setPixmap( SmallIcon( "locationbar_erase" ) );
93  m_adv->m_btnClearPrimary->setPixmap( SmallIcon( "locationbar_erase" ) );
94  m_adv->m_btnClearAlternate->setPixmap( SmallIcon( "locationbar_erase" ) );
95  connect(m_simple->m_btnClearShortcut, TQT_SIGNAL(clicked()),
96  this, TQT_SLOT(slotClearShortcut()));
97  connect(m_adv->m_btnClearPrimary, TQT_SIGNAL(clicked()),
98  this, TQT_SLOT(slotClearPrimary()));
99  connect(m_adv->m_btnClearAlternate, TQT_SIGNAL(clicked()),
100  this, TQT_SLOT(slotClearAlternate()));
101 
102  connect(m_adv->m_txtPrimary, TQT_SIGNAL(clicked()),
103  m_adv->m_btnPrimary, TQT_SLOT(animateClick()));
104  connect(m_adv->m_txtAlternate, TQT_SIGNAL(clicked()),
105  m_adv->m_btnAlternate, TQT_SLOT(animateClick()));
106  connect(m_adv->m_btnPrimary, TQT_SIGNAL(clicked()),
107  this, TQT_SLOT(slotSelectPrimary()));
108  connect(m_adv->m_btnAlternate, TQT_SIGNAL(clicked()),
109  this, TQT_SLOT(slotSelectAlternate()));
110 
111  KGuiItem ok = KStdGuiItem::ok();
112  ok.setText( i18n( "OK" ) );
113  setButtonOK( ok );
114 
115  KGuiItem cancel = KStdGuiItem::cancel();
116  cancel.setText( i18n( "Cancel" ) );
117  setButtonCancel( cancel );
118 
119  setShortcut( shortcut );
120  resize( 0, 0 );
121 
122  s_showMore = TDEConfigGroup(TDEGlobal::config(), "General").readBoolEntry("ShowAlternativeShortcutConfig", s_showMore);
123  updateDetails();
124 
125  #ifdef Q_WS_X11
126  kapp->installX11EventFilter( this ); // Allow button to capture X Key Events.
127  #endif
128 }
129 
130 TDEShortcutDialog::~TDEShortcutDialog()
131 {
132  TDEConfigGroup group(TDEGlobal::config(), "General");
133  group.writeEntry("ShowAlternativeShortcutConfig", s_showMore);
134 }
135 
136 void TDEShortcutDialog::setShortcut( const TDEShortcut & shortcut )
137 {
138  m_shortcut = shortcut;
139  updateShortcutDisplay();
140 }
141 
142 void TDEShortcutDialog::updateShortcutDisplay()
143 {
144  TQString s[2] = { m_shortcut.seq(0).toString(), m_shortcut.seq(1).toString() };
145 
146  if( m_bRecording ) {
147  m_ptxtCurrent->setDefault( true );
148  m_ptxtCurrent->setFocus();
149 
150  // Display modifiers for the first key in the KKeySequence
151  if( m_iKey == 0 ) {
152  if( m_mod ) {
153  TQString keyModStr;
154  if( m_mod & KKey::WIN ) keyModStr += KKey::modFlagLabel(KKey::WIN) + "+";
155  if( m_mod & KKey::ALT ) keyModStr += KKey::modFlagLabel(KKey::ALT) + "+";
156  if( m_mod & KKey::CTRL ) keyModStr += KKey::modFlagLabel(KKey::CTRL) + "+";
157  if( m_mod & KKey::SHIFT ) keyModStr += KKey::modFlagLabel(KKey::SHIFT) + "+";
158  s[m_iSeq] = keyModStr;
159  }
160  }
161  // When in the middle of entering multi-key shortcuts,
162  // add a "," to the end of the displayed shortcut.
163  else
164  s[m_iSeq] += ",";
165  }
166  else {
167  m_adv->m_txtPrimary->setDefault( false );
168  m_adv->m_txtAlternate->setDefault( false );
169  this->setFocus();
170  }
171 
172  s[0].replace('&', TQString::fromLatin1("&&"));
173  s[1].replace('&', TQString::fromLatin1("&&"));
174 
175  m_simple->m_txtShortcut->setText( s[0] );
176  m_adv->m_txtPrimary->setText( s[0] );
177  m_adv->m_txtAlternate->setText( s[1] );
178 
179  // Determine the enable state of the 'Less' button
180  bool bLessOk;
181  // If there is no shortcut defined,
182  if( m_shortcut.count() == 0 )
183  bLessOk = true;
184  // If there is a single shortcut defined, and it is not a multi-key shortcut,
185  else if( m_shortcut.count() == 1 && m_shortcut.seq(0).count() <= 1 )
186  bLessOk = true;
187  // Otherwise, we have an alternate shortcut or multi-key shortcut(s).
188  else
189  bLessOk = false;
190  enableButton(Details, bLessOk);
191 }
192 
193 void TDEShortcutDialog::slotDetails()
194 {
195  s_showMore = (m_adv->isHidden());
196  updateDetails();
197 }
198 
199 void TDEShortcutDialog::updateDetails()
200 {
201  bool showAdvanced = s_showMore || (m_shortcut.count() > 1);
202  setDetails(showAdvanced);
203  m_bRecording = false;
204  m_iSeq = 0;
205  m_iKey = 0;
206 
207  if (showAdvanced)
208  {
209  m_simple->hide();
210  m_adv->show();
211  m_adv->m_btnPrimary->setChecked( true );
212  slotSelectPrimary();
213  }
214  else
215  {
216  m_ptxtCurrent = m_simple->m_txtShortcut;
217  m_adv->hide();
218  m_simple->show();
219  m_simple->m_txtShortcut->setDefault( true );
220  m_simple->m_txtShortcut->setFocus();
221  m_adv->m_btnMultiKey->setChecked( false );
222  }
223  kapp->processEvents();
224  adjustSize();
225 }
226 
227 void TDEShortcutDialog::slotSelectPrimary()
228 {
229  m_bRecording = false;
230  m_iSeq = 0;
231  m_iKey = 0;
232  m_ptxtCurrent = m_adv->m_txtPrimary;
233  m_ptxtCurrent->setDefault(true);
234  m_ptxtCurrent->setFocus();
235  updateShortcutDisplay();
236 }
237 
238 void TDEShortcutDialog::slotSelectAlternate()
239 {
240  m_bRecording = false;
241  m_iSeq = 1;
242  m_iKey = 0;
243  m_ptxtCurrent = m_adv->m_txtAlternate;
244  m_ptxtCurrent->setDefault(true);
245  m_ptxtCurrent->setFocus();
246  updateShortcutDisplay();
247 }
248 
249 void TDEShortcutDialog::slotClearShortcut()
250 {
251  m_shortcut.setSeq( 0, KKeySequence() );
252  updateShortcutDisplay();
253 }
254 
255 void TDEShortcutDialog::slotClearPrimary()
256 {
257  m_shortcut.setSeq( 0, KKeySequence() );
258  m_adv->m_btnPrimary->setChecked( true );
259  slotSelectPrimary();
260 }
261 
262 void TDEShortcutDialog::slotClearAlternate()
263 {
264  if( m_shortcut.count() == 2 )
265  m_shortcut.init( m_shortcut.seq(0) );
266  m_adv->m_btnAlternate->setChecked( true );
267  slotSelectAlternate();
268 }
269 
270 void TDEShortcutDialog::slotMultiKeyMode( bool bOn )
271 {
272  // If turning off multi-key mode during a recording,
273  if( !bOn && m_bRecording ) {
274  m_bRecording = false;
275  m_iKey = 0;
276  updateShortcutDisplay();
277  }
278 }
279 
280 #ifdef Q_WS_X11
281 /* we don't use the generic Qt code on X11 because it allows us
282  to grab the keyboard so that all keypresses are seen
283  */
284 bool TDEShortcutDialog::x11Event( XEvent *pEvent )
285 {
286  switch( pEvent->type ) {
287  case XKeyPress:
288  x11KeyPressEvent( pEvent );
289  return true;
290  case XKeyRelease:
291  x11KeyReleaseEvent( pEvent );
292  return true;
293  case XFocusIn:
294  if (!m_bGrab) {
295  //kdDebug(125) << "FocusIn and Grab!" << endl;
296  grabKeyboard();
297  m_bGrab = true;
298  }
299  //else
300  // kdDebug(125) << "FocusIn" << endl;
301  break;
302  case XFocusOut:
303  if (m_bGrab) {
304  //kdDebug(125) << "FocusOut and Ungrab!" << endl;
305  releaseKeyboard();
306  m_bGrab = false;
307  }
308  //else
309  // kdDebug(125) << "FocusOut" << endl;
310  break;
311  default:
312  //kdDebug(125) << "x11Event->type = " << pEvent->type << endl;
313  break;
314  }
315  return KDialogBase::x11Event( pEvent );
316 }
317 
318 static uint getModsFromModX( uint keyModX )
319 {
320  uint mod = 0;
321  if( keyModX & KKeyNative::modX(KKey::SHIFT) ) mod += KKey::SHIFT;
322  if( keyModX & KKeyNative::modX(KKey::CTRL) ) mod += KKey::CTRL;
323  if( keyModX & KKeyNative::modX(KKey::ALT) ) mod += KKey::ALT;
324  if( keyModX & KKeyNative::modX(KKey::WIN) ) mod += KKey::WIN;
325  return mod;
326 }
327 
328 static bool convertSymXToMod( uint keySymX, uint* pmod )
329 {
330  switch( keySymX ) {
331  // Don't allow setting a modifier key as an accelerator.
332  // Also, don't release the focus yet. We'll wait until
333  // we get a 'normal' key.
334  case XK_Shift_L: case XK_Shift_R: *pmod = KKey::SHIFT; break;
335  case XK_Control_L: case XK_Control_R: *pmod = KKey::CTRL; break;
336  case XK_Alt_L: case XK_Alt_R: *pmod = KKey::ALT; break;
337  // FIXME: check whether the Meta or Super key are for the Win modifier
338  case XK_Meta_L: case XK_Meta_R:
339  case XK_Super_L: case XK_Super_R: *pmod = KKey::WIN; break;
340  case XK_Hyper_L: case XK_Hyper_R:
341  case XK_Mode_switch:
342  case XK_Num_Lock:
343  case XK_Caps_Lock:
344  break;
345  default:
346  return false;
347  }
348  return true;
349 }
350 
351 void TDEShortcutDialog::x11KeyPressEvent( XEvent* pEvent )
352 {
353  KKeyNative keyNative( pEvent );
354  uint keyModX = keyNative.mod();
355  uint keySymX = keyNative.sym();
356 
357  m_mod = getModsFromModX( keyModX );
358 
359  if( keySymX ) {
360  m_bRecording = true;
361 
362  uint mod = 0;
363  if( convertSymXToMod( keySymX, &mod ) ) {
364  if( mod )
365  m_mod |= mod;
366  }
367  else
368  keyPressed( KKey(keyNative) );
369  }
370  updateShortcutDisplay();
371 }
372 
373 void TDEShortcutDialog::x11KeyReleaseEvent( XEvent* pEvent )
374 {
375  // We're only interested in the release of modifier keys,
376  // and then only when it's for the first key in a sequence.
377  if( m_bRecording && m_iKey == 0 ) {
378  KKeyNative keyNative( pEvent );
379  uint keyModX = keyNative.mod();
380  uint keySymX = keyNative.sym();
381 
382  m_mod = getModsFromModX( keyModX );
383 
384  uint mod = 0;
385  if( convertSymXToMod( keySymX, &mod ) && mod ) {
386  m_mod &= ~mod;
387  if( !m_mod )
388  m_bRecording = false;
389  }
390  updateShortcutDisplay();
391  }
392 }
393 #elif defined(Q_WS_WIN)
394 void TDEShortcutDialog::keyPressEvent( TQKeyEvent * e )
395 {
396  kdDebug() << e->text() << " " << (int)e->text()[0].latin1()<< " " << (int)e->ascii() << endl;
397  //if key is a letter, it must be stored as lowercase
398  int keyQt = TQChar( e->key() & 0xff ).isLetter() ?
399  (TQChar( e->key() & 0xff ).lower().latin1() | (e->key() & 0xffff00) )
400  : e->key();
401  int modQt = KKeyServer::qtButtonStateToMod( e->state() );
402  KKeyNative keyNative( KKey(keyQt, modQt) );
403  m_mod = keyNative.mod();
404  uint keySym = keyNative.sym();
405 
406  switch( keySym ) {
407  case Key_Shift:
408  m_mod |= KKey::SHIFT;
409  m_bRecording = true;
410  break;
411  case Key_Control:
412  m_mod |= KKey::CTRL;
413  m_bRecording = true;
414  break;
415  case Key_Alt:
416  m_mod |= KKey::ALT;
417  m_bRecording = true;
418  break;
419  case Key_Menu:
420  case Key_Meta: //unused
421  break;
422  default:
423  if( keyNative.sym() == Key_Return && m_iKey > 0 ) {
424  accept();
425  return;
426  }
427  //accept
428  if (keyNative.sym()) {
429  KKey key = keyNative;
430  key.simplify();
431  KKeySequence seq;
432  if( m_iKey == 0 )
433  seq = key;
434  else {
435  seq = m_shortcut.seq( m_iSeq );
436  seq.setKey( m_iKey, key );
437  }
438  m_shortcut.setSeq( m_iSeq, seq );
439 
440  if(m_adv->m_btnMultiKey->isChecked())
441  m_iKey++;
442 
443  m_bRecording = true;
444 
445  updateShortcutDisplay();
446 
447  if( !m_adv->m_btnMultiKey->isChecked() )
448  TQTimer::singleShot(500, this, TQT_SLOT(accept()));
449  }
450  return;
451  }
452 
453  // If we are editing the first key in the sequence,
454  // display modifier keys which are held down
455  if( m_iKey == 0 ) {
456  updateShortcutDisplay();
457  }
458 }
459 
460 bool TDEShortcutDialog::event ( TQEvent * e )
461 {
462  if (e->type()==TQEvent::KeyRelease) {
463  int modQt = KKeyServer::qtButtonStateToMod( static_cast<TQKeyEvent*>(e)->state() );
464  KKeyNative keyNative( KKey(static_cast<TQKeyEvent*>(e)->key(), modQt) );
465  uint keySym = keyNative.sym();
466 
467  bool change = true;
468  switch( keySym ) {
469  case Key_Shift:
470  if (m_mod & KKey::SHIFT)
471  m_mod ^= KKey::SHIFT;
472  break;
473  case Key_Control:
474  if (m_mod & KKey::CTRL)
475  m_mod ^= KKey::CTRL;
476  break;
477  case Key_Alt:
478  if (m_mod & KKey::ALT)
479  m_mod ^= KKey::ALT;
480  break;
481  default:
482  change = false;
483  }
484  if (change)
485  updateShortcutDisplay();
486  }
487  return KDialogBase::event(e);
488 }
489 #endif
490 
491 void TDEShortcutDialog::keyPressed( KKey key )
492 {
493  kdDebug(125) << "keyPressed: " << key.toString() << endl;
494 
495  key.simplify();
496  if( m_bQtShortcut ) {
497  key = key.keyCodeQt();
498  if( key.isNull() ) {
499  // TODO: message box about key not able to be used as application shortcut
500  }
501  }
502 
503  KKeySequence seq;
504  if( m_iKey == 0 )
505  seq = key;
506  else {
507  // Remove modifiers
508  key.init( key.sym(), 0 );
509  seq = m_shortcut.seq( m_iSeq );
510  seq.setKey( m_iKey, key );
511  }
512 
513  m_shortcut.setSeq( m_iSeq, seq );
514 
515  m_mod = 0;
516  if( m_adv->m_btnMultiKey->isChecked() && m_iKey < KKeySequence::MAX_KEYS - 1 )
517  m_iKey++;
518  else {
519  m_iKey = 0;
520  m_bRecording = false;
521  }
522 
523  updateShortcutDisplay();
524 
525  if( !m_adv->m_btnMultiKey->isChecked() )
526  TQTimer::singleShot(500, this, TQT_SLOT(accept()));
527 }
528 
529 #include "tdeshortcutdialog.moc"

tdeui

Skip menu "tdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdeui

Skip menu "tdeui"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeui by doxygen 1.8.1.2
This website is maintained by Timothy Pearson.