• 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_iSeq = 0;
86  m_iKey = 0;
87  m_ptxtCurrent = 0;
88  m_bRecording = false;
89  m_mod = 0;
90 
91  m_simple->m_btnClearShortcut->setPixmap( SmallIcon( "locationbar_erase" ) );
92  m_adv->m_btnClearPrimary->setPixmap( SmallIcon( "locationbar_erase" ) );
93  m_adv->m_btnClearAlternate->setPixmap( SmallIcon( "locationbar_erase" ) );
94  connect(m_simple->m_btnClearShortcut, TQT_SIGNAL(clicked()),
95  this, TQT_SLOT(slotClearShortcut()));
96  connect(m_adv->m_btnClearPrimary, TQT_SIGNAL(clicked()),
97  this, TQT_SLOT(slotClearPrimary()));
98  connect(m_adv->m_btnClearAlternate, TQT_SIGNAL(clicked()),
99  this, TQT_SLOT(slotClearAlternate()));
100 
101  connect(m_adv->m_txtPrimary, TQT_SIGNAL(clicked()),
102  m_adv->m_btnPrimary, TQT_SLOT(animateClick()));
103  connect(m_adv->m_txtAlternate, TQT_SIGNAL(clicked()),
104  m_adv->m_btnAlternate, TQT_SLOT(animateClick()));
105  connect(m_adv->m_btnPrimary, TQT_SIGNAL(clicked()),
106  this, TQT_SLOT(slotSelectPrimary()));
107  connect(m_adv->m_btnAlternate, TQT_SIGNAL(clicked()),
108  this, TQT_SLOT(slotSelectAlternate()));
109 
110  KGuiItem ok = KStdGuiItem::ok();
111  ok.setText( i18n( "OK" ) );
112  setButtonOK( ok );
113 
114  KGuiItem cancel = KStdGuiItem::cancel();
115  cancel.setText( i18n( "Cancel" ) );
116  setButtonCancel( cancel );
117 
118  setShortcut( shortcut );
119  resize( 0, 0 );
120 
121  s_showMore = TDEConfigGroup(TDEGlobal::config(), "General").readBoolEntry("ShowAlternativeShortcutConfig", s_showMore);
122  updateDetails();
123 
124  #ifdef Q_WS_X11
125  kapp->installX11EventFilter( this ); // Allow button to capture X Key Events.
126  #endif
127 }
128 
129 TDEShortcutDialog::~TDEShortcutDialog()
130 {
131  TDEConfigGroup group(TDEGlobal::config(), "General");
132  group.writeEntry("ShowAlternativeShortcutConfig", s_showMore);
133 }
134 
135 void TDEShortcutDialog::setShortcut( const TDEShortcut & shortcut )
136 {
137  m_shortcut = shortcut;
138  updateShortcutDisplay();
139 }
140 
141 void TDEShortcutDialog::updateShortcutDisplay()
142 {
143  TQString s[2] = { m_shortcut.seq(0).toString(), m_shortcut.seq(1).toString() };
144 
145  if( m_bRecording ) {
146  m_ptxtCurrent->setDefault( true );
147  m_ptxtCurrent->setFocus();
148 
149  // Display modifiers for the first key in the KKeySequence
150  if( m_iKey == 0 ) {
151  if( m_mod ) {
152  TQString keyModStr;
153  if( m_mod & KKey::WIN ) keyModStr += KKey::modFlagLabel(KKey::WIN) + "+";
154  if( m_mod & KKey::ALT ) keyModStr += KKey::modFlagLabel(KKey::ALT) + "+";
155  if( m_mod & KKey::CTRL ) keyModStr += KKey::modFlagLabel(KKey::CTRL) + "+";
156  if( m_mod & KKey::SHIFT ) keyModStr += KKey::modFlagLabel(KKey::SHIFT) + "+";
157  s[m_iSeq] = keyModStr;
158  }
159  }
160  // When in the middle of entering multi-key shortcuts,
161  // add a "," to the end of the displayed shortcut.
162  else
163  s[m_iSeq] += ",";
164  }
165  else {
166  m_adv->m_txtPrimary->setDefault( false );
167  m_adv->m_txtAlternate->setDefault( false );
168  this->setFocus();
169  }
170 
171  s[0].replace('&', TQString::fromLatin1("&&"));
172  s[1].replace('&', TQString::fromLatin1("&&"));
173 
174  m_simple->m_txtShortcut->setText( s[0] );
175  m_adv->m_txtPrimary->setText( s[0] );
176  m_adv->m_txtAlternate->setText( s[1] );
177 
178  // Determine the enable state of the 'Less' button
179  bool bLessOk;
180  // If there is no shortcut defined,
181  if( m_shortcut.count() == 0 )
182  bLessOk = true;
183  // If there is a single shortcut defined, and it is not a multi-key shortcut,
184  else if( m_shortcut.count() == 1 && m_shortcut.seq(0).count() <= 1 )
185  bLessOk = true;
186  // Otherwise, we have an alternate shortcut or multi-key shortcut(s).
187  else
188  bLessOk = false;
189  enableButton(Details, bLessOk);
190 }
191 
192 void TDEShortcutDialog::slotDetails()
193 {
194  s_showMore = (m_adv->isHidden());
195  updateDetails();
196 }
197 
198 void TDEShortcutDialog::updateDetails()
199 {
200  bool showAdvanced = s_showMore || (m_shortcut.count() > 1);
201  setDetails(showAdvanced);
202  m_bRecording = false;
203  m_iSeq = 0;
204  m_iKey = 0;
205 
206  if (showAdvanced)
207  {
208  m_simple->hide();
209  m_adv->show();
210  m_adv->m_btnPrimary->setChecked( true );
211  slotSelectPrimary();
212  }
213  else
214  {
215  m_ptxtCurrent = m_simple->m_txtShortcut;
216  m_adv->hide();
217  m_simple->show();
218  m_simple->m_txtShortcut->setDefault( true );
219  m_simple->m_txtShortcut->setFocus();
220  m_adv->m_btnMultiKey->setChecked( false );
221  }
222  kapp->processEvents();
223  adjustSize();
224 }
225 
226 void TDEShortcutDialog::slotSelectPrimary()
227 {
228  m_bRecording = false;
229  m_iSeq = 0;
230  m_iKey = 0;
231  m_ptxtCurrent = m_adv->m_txtPrimary;
232  m_ptxtCurrent->setDefault(true);
233  m_ptxtCurrent->setFocus();
234  updateShortcutDisplay();
235 }
236 
237 void TDEShortcutDialog::slotSelectAlternate()
238 {
239  m_bRecording = false;
240  m_iSeq = 1;
241  m_iKey = 0;
242  m_ptxtCurrent = m_adv->m_txtAlternate;
243  m_ptxtCurrent->setDefault(true);
244  m_ptxtCurrent->setFocus();
245  updateShortcutDisplay();
246 }
247 
248 void TDEShortcutDialog::slotClearShortcut()
249 {
250  m_shortcut.setSeq( 0, KKeySequence() );
251  updateShortcutDisplay();
252 }
253 
254 void TDEShortcutDialog::slotClearPrimary()
255 {
256  m_shortcut.setSeq( 0, KKeySequence() );
257  m_adv->m_btnPrimary->setChecked( true );
258  slotSelectPrimary();
259 }
260 
261 void TDEShortcutDialog::slotClearAlternate()
262 {
263  if( m_shortcut.count() == 2 )
264  m_shortcut.init( m_shortcut.seq(0) );
265  m_adv->m_btnAlternate->setChecked( true );
266  slotSelectAlternate();
267 }
268 
269 void TDEShortcutDialog::slotMultiKeyMode( bool bOn )
270 {
271  // If turning off multi-key mode during a recording,
272  if( !bOn && m_bRecording ) {
273  m_bRecording = false;
274  m_iKey = 0;
275  updateShortcutDisplay();
276  }
277 }
278 
279 #ifdef Q_WS_X11
280 /* we don't use the generic Qt code on X11 because it allows us
281  to grab the keyboard so that all keypresses are seen
282  */
283 bool TDEShortcutDialog::x11Event( XEvent *pEvent )
284 {
285  switch( pEvent->type ) {
286  case XKeyPress:
287  x11KeyPressEvent( pEvent );
288  return true;
289  case XKeyRelease:
290  x11KeyReleaseEvent( pEvent );
291  return true;
292  case XFocusIn:
293  {
294  XFocusInEvent *fie = (XFocusInEvent*)pEvent;
295  if (fie->mode != NotifyGrab && fie->mode != NotifyUngrab) {
296  grabKeyboard();
297  }
298  }
299  break;
300  case XFocusOut:
301  {
302  XFocusOutEvent *foe = (XFocusOutEvent*)pEvent;
303  if (foe->mode != NotifyGrab && foe->mode != NotifyUngrab) {
304  releaseKeyboard();
305  }
306  }
307  break;
308  default:
309  //kdDebug(125) << "x11Event->type = " << pEvent->type << endl;
310  break;
311  }
312  return KDialogBase::x11Event( pEvent );
313 }
314 
315 static uint getModsFromModX( uint keyModX )
316 {
317  uint mod = 0;
318  if( keyModX & KKeyNative::modX(KKey::SHIFT) ) mod += KKey::SHIFT;
319  if( keyModX & KKeyNative::modX(KKey::CTRL) ) mod += KKey::CTRL;
320  if( keyModX & KKeyNative::modX(KKey::ALT) ) mod += KKey::ALT;
321  if( keyModX & KKeyNative::modX(KKey::WIN) ) mod += KKey::WIN;
322  return mod;
323 }
324 
325 static bool convertSymXToMod( uint keySymX, uint* pmod )
326 {
327  switch( keySymX ) {
328  // Don't allow setting a modifier key as an accelerator.
329  // Also, don't release the focus yet. We'll wait until
330  // we get a 'normal' key.
331  case XK_Shift_L: case XK_Shift_R: *pmod = KKey::SHIFT; break;
332  case XK_Control_L: case XK_Control_R: *pmod = KKey::CTRL; break;
333  case XK_Alt_L: case XK_Alt_R: *pmod = KKey::ALT; break;
334  // FIXME: check whether the Meta or Super key are for the Win modifier
335  case XK_Meta_L: case XK_Meta_R:
336  case XK_Super_L: case XK_Super_R: *pmod = KKey::WIN; break;
337  case XK_Hyper_L: case XK_Hyper_R:
338  case XK_Mode_switch:
339  case XK_Num_Lock:
340  case XK_Caps_Lock:
341  break;
342  default:
343  return false;
344  }
345  return true;
346 }
347 
348 void TDEShortcutDialog::x11KeyPressEvent( XEvent* pEvent )
349 {
350  KKeyNative keyNative( pEvent );
351  uint keyModX = keyNative.mod();
352  uint keySymX = keyNative.sym();
353 
354  m_mod = getModsFromModX( keyModX );
355 
356  if( keySymX ) {
357  m_bRecording = true;
358 
359  uint mod = 0;
360  if( convertSymXToMod( keySymX, &mod ) ) {
361  if( mod )
362  m_mod |= mod;
363  }
364  else
365  keyPressed( KKey(keyNative) );
366  }
367  updateShortcutDisplay();
368 }
369 
370 void TDEShortcutDialog::x11KeyReleaseEvent( XEvent* pEvent )
371 {
372  // We're only interested in the release of modifier keys,
373  // and then only when it's for the first key in a sequence.
374  if( m_bRecording && m_iKey == 0 ) {
375  KKeyNative keyNative( pEvent );
376  uint keyModX = keyNative.mod();
377  uint keySymX = keyNative.sym();
378 
379  m_mod = getModsFromModX( keyModX );
380 
381  uint mod = 0;
382  if( convertSymXToMod( keySymX, &mod ) && mod ) {
383  m_mod &= ~mod;
384  if( !m_mod )
385  m_bRecording = false;
386  }
387  updateShortcutDisplay();
388  }
389 }
390 #elif defined(Q_WS_WIN)
391 void TDEShortcutDialog::keyPressEvent( TQKeyEvent * e )
392 {
393  kdDebug() << e->text() << " " << (int)e->text()[0].latin1()<< " " << (int)e->ascii() << endl;
394  //if key is a letter, it must be stored as lowercase
395  int keyQt = TQChar( e->key() & 0xff ).isLetter() ?
396  (TQChar( e->key() & 0xff ).lower().latin1() | (e->key() & 0xffff00) )
397  : e->key();
398  int modQt = KKeyServer::qtButtonStateToMod( e->state() );
399  KKeyNative keyNative( KKey(keyQt, modQt) );
400  m_mod = keyNative.mod();
401  uint keySym = keyNative.sym();
402 
403  switch( keySym ) {
404  case Key_Shift:
405  m_mod |= KKey::SHIFT;
406  m_bRecording = true;
407  break;
408  case Key_Control:
409  m_mod |= KKey::CTRL;
410  m_bRecording = true;
411  break;
412  case Key_Alt:
413  m_mod |= KKey::ALT;
414  m_bRecording = true;
415  break;
416  case Key_Menu:
417  case Key_Meta: //unused
418  break;
419  default:
420  if( keyNative.sym() == Key_Return && m_iKey > 0 ) {
421  accept();
422  return;
423  }
424  //accept
425  if (keyNative.sym()) {
426  KKey key = keyNative;
427  key.simplify();
428  KKeySequence seq;
429  if( m_iKey == 0 )
430  seq = key;
431  else {
432  seq = m_shortcut.seq( m_iSeq );
433  seq.setKey( m_iKey, key );
434  }
435  m_shortcut.setSeq( m_iSeq, seq );
436 
437  if(m_adv->m_btnMultiKey->isChecked())
438  m_iKey++;
439 
440  m_bRecording = true;
441 
442  updateShortcutDisplay();
443 
444  if( !m_adv->m_btnMultiKey->isChecked() )
445  TQTimer::singleShot(500, this, TQT_SLOT(accept()));
446  }
447  return;
448  }
449 
450  // If we are editing the first key in the sequence,
451  // display modifier keys which are held down
452  if( m_iKey == 0 ) {
453  updateShortcutDisplay();
454  }
455 }
456 
457 bool TDEShortcutDialog::event ( TQEvent * e )
458 {
459  if (e->type()==TQEvent::KeyRelease) {
460  int modQt = KKeyServer::qtButtonStateToMod( static_cast<TQKeyEvent*>(e)->state() );
461  KKeyNative keyNative( KKey(static_cast<TQKeyEvent*>(e)->key(), modQt) );
462  uint keySym = keyNative.sym();
463 
464  bool change = true;
465  switch( keySym ) {
466  case Key_Shift:
467  if (m_mod & KKey::SHIFT)
468  m_mod ^= KKey::SHIFT;
469  break;
470  case Key_Control:
471  if (m_mod & KKey::CTRL)
472  m_mod ^= KKey::CTRL;
473  break;
474  case Key_Alt:
475  if (m_mod & KKey::ALT)
476  m_mod ^= KKey::ALT;
477  break;
478  default:
479  change = false;
480  }
481  if (change)
482  updateShortcutDisplay();
483  }
484  return KDialogBase::event(e);
485 }
486 #endif
487 
488 void TDEShortcutDialog::keyPressed( KKey key )
489 {
490  kdDebug(125) << "keyPressed: " << key.toString() << endl;
491 
492  key.simplify();
493  if( m_bQtShortcut ) {
494  key = key.keyCodeQt();
495  if( key.isNull() ) {
496  // TODO: message box about key not able to be used as application shortcut
497  }
498  }
499 
500  KKeySequence seq;
501  if( m_iKey == 0 )
502  seq = key;
503  else {
504  // Remove modifiers
505  key.init( key.sym(), 0 );
506  seq = m_shortcut.seq( m_iSeq );
507  seq.setKey( m_iKey, key );
508  }
509 
510  m_shortcut.setSeq( m_iSeq, seq );
511 
512  m_mod = 0;
513  if( m_adv->m_btnMultiKey->isChecked() && m_iKey < KKeySequence::MAX_KEYS - 1 )
514  m_iKey++;
515  else {
516  m_iKey = 0;
517  m_bRecording = false;
518  }
519 
520  updateShortcutDisplay();
521 
522  if( !m_adv->m_btnMultiKey->isChecked() )
523  TQTimer::singleShot(500, this, TQT_SLOT(accept()));
524 }
525 
526 #include "tdeshortcutdialog.moc"
KDialogBase::Details
Show Details button.
Definition: kdialogbase.h:211
TDEShortcut::seq
const KKeySequence & seq(uint i) const
TDEStdAccel::key
int key(StdAccel) KDE_DEPRECATED
KKeySequence::setKey
bool setKey(uint i, const KKey &key)
KDialogBase::enableButton
void enableButton(ButtonCode id, bool state)
Enable or disable (gray out) a general action button.
Definition: kdialogbase.cpp:838
TDEShortcut::count
uint count() const
kdDebug
kdbgstream kdDebug(int area=0)
KKey::toString
TQString toString() const
KDialogBase
A dialog base class with standard buttons and predefined layouts.
Definition: kdialogbase.h:191
KKey::isNull
bool isNull() const
KKey::init
bool init(int keyQt)
KKeySequence
TDEConfigGroup
tdelocale.h
KGuiItem
An abstract class for GUI data such as ToolTip and Icon.
Definition: kguiitem.h:38
KDialogBase::setDetails
void setDetails(bool showDetails)
Sets the status of the Details button.
Definition: kdialogbase.cpp:1127
KKeySequence::toString
TQString toString() const
KKeyServer::qtButtonStateToMod
int qtButtonStateToMod(TQ_ButtonState s)
KKeyNative
KDialogBase::keyPressEvent
virtual void keyPressEvent(TQKeyEvent *e)
Maps some keys to the actions buttons.
Definition: kdialogbase.cpp:1553
TDEShortcut::setSeq
bool setSeq(uint i, const KKeySequence &keySeq)
KKey
TDEShortcut
KKey::keyCodeQt
int keyCodeQt() const
KKey::modFlagLabel
static TQString modFlagLabel(ModFlag f)
TDEGlobal::config
static TDEConfig * config()
endl
kndbgstream & endl(kndbgstream &s)
TDEShortcut::init
bool init(int keyQt)
KDialogBase::adjustSize
virtual void adjustSize()
Adjust the size of the dialog to fit the contents just before TQDialog::exec() or TQDialog::show() is...
Definition: kdialogbase.cpp:427
KKeySequence::count
uint count() const

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdeui by doxygen 1.8.8
This website is maintained by Timothy Pearson.