KDEUI
kaction.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org> 00003 (C) 1999 Simon Hausmann <hausmann@kde.org> 00004 (C) 2000 Nicolas Hadacek <haadcek@kde.org> 00005 (C) 2000 Kurt Granroth <granroth@kde.org> 00006 (C) 2000 Michael Koch <koch@kde.org> 00007 (C) 2001 Holger Freyther <freyther@kde.org> 00008 (C) 2002 Ellis Whitehead <ellis@kde.org> 00009 (C) 2002 Joseph Wenninger <jowenn@kde.org> 00010 (C) 2005-2006 Hamish Rodda <rodda@kde.org> 00011 00012 This library is free software; you can redistribute it and/or 00013 modify it under the terms of the GNU Library General Public 00014 License version 2 as published by the Free Software Foundation. 00015 00016 This library is distributed in the hope that it will be useful, 00017 but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 Library General Public License for more details. 00020 00021 You should have received a copy of the GNU Library General Public License 00022 along with this library; see the file COPYING.LIB. If not, write to 00023 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00024 Boston, MA 02110-1301, USA. 00025 */ 00026 00027 #include "kaction.h" 00028 #include "kaction_p.h" 00029 #include "kglobalaccel_p.h" 00030 #include "klocale.h" 00031 #include "kmessagebox.h" 00032 #include "kauthaction.h" 00033 #include "kauthactionwatcher.h" 00034 00035 #include <QtGui/QApplication> 00036 #include <QtGui/QHBoxLayout> 00037 #include <QtGui/QShortcutEvent> 00038 #include <QtGui/QToolBar> 00039 00040 #include <kdebug.h> 00041 00042 #include "kguiitem.h" 00043 #include "kicon.h" 00044 00045 //--------------------------------------------------------------------- 00046 // KActionPrivate 00047 //--------------------------------------------------------------------- 00048 00049 void KActionPrivate::init(KAction *q_ptr) 00050 { 00051 q = q_ptr; 00052 globalShortcutEnabled = false; 00053 neverSetGlobalShortcut = true; 00054 00055 QObject::connect(q, SIGNAL(triggered(bool)), q, SLOT(slotTriggered())); 00056 00057 q->setProperty("isShortcutConfigurable", true); 00058 } 00059 00060 void KActionPrivate::setActiveGlobalShortcutNoEnable(const KShortcut &cut) 00061 { 00062 globalShortcut = cut; 00063 emit q->globalShortcutChanged(cut.primary()); 00064 } 00065 00066 00067 void KActionPrivate::slotTriggered() 00068 { 00069 #ifdef KDE3_SUPPORT 00070 emit q->activated(); 00071 #endif 00072 emit q->triggered(QApplication::mouseButtons(), QApplication::keyboardModifiers()); 00073 00074 if (authAction) { 00075 KAuth::Action::AuthStatus s = authAction->earlyAuthorize(); 00076 switch(s) { 00077 case KAuth::Action::Denied: 00078 q->setEnabled(false); 00079 break; 00080 case KAuth::Action::Authorized: 00081 emit q->authorized(authAction); 00082 break; 00083 default: 00084 break; 00085 } 00086 } 00087 } 00088 00089 void KActionPrivate::authStatusChanged(int status) 00090 { 00091 KAuth::Action::AuthStatus s = (KAuth::Action::AuthStatus)status; 00092 00093 switch(s) { 00094 case KAuth::Action::Authorized: 00095 q->setEnabled(true); 00096 if(!oldIcon.isNull()) { 00097 q->setIcon(oldIcon); 00098 oldIcon = KIcon(); 00099 } 00100 break; 00101 case KAuth::Action::AuthRequired: 00102 q->setEnabled(true); 00103 oldIcon = KIcon(q->icon()); 00104 q->setIcon(KIcon("dialog-password")); 00105 break; 00106 default: 00107 q->setEnabled(false); 00108 if(!oldIcon.isNull()) { 00109 q->setIcon(oldIcon); 00110 oldIcon = KIcon(); 00111 } 00112 } 00113 } 00114 00115 bool KAction::event(QEvent *event) 00116 { 00117 if (event->type() == QEvent::Shortcut) { 00118 QShortcutEvent *se = static_cast<QShortcutEvent*>(event); 00119 if(se->isAmbiguous()) { 00120 KMessageBox::information( 00121 NULL, // No widget to be seen around here 00122 i18n( "The key sequence '%1' is ambiguous. Use 'Configure Shortcuts'\n" 00123 "from the 'Settings' menu to solve the ambiguity.\n" 00124 "No action will be triggered.", 00125 se->key().toString()), 00126 i18n("Ambiguous shortcut detected")); 00127 return true; 00128 } 00129 } 00130 00131 return QAction::event(event); 00132 } 00133 00134 00135 //--------------------------------------------------------------------- 00136 // KAction 00137 //--------------------------------------------------------------------- 00138 00139 KAction::KAction(QObject *parent) 00140 : QWidgetAction(parent), d(new KActionPrivate) 00141 { 00142 d->init(this); 00143 } 00144 00145 KAction::KAction(const QString &text, QObject *parent) 00146 : QWidgetAction(parent), d(new KActionPrivate) 00147 { 00148 d->init(this); 00149 setText(text); 00150 } 00151 00152 KAction::KAction(const KIcon &icon, const QString &text, QObject *parent) 00153 : QWidgetAction(parent), d(new KActionPrivate) 00154 { 00155 d->init(this); 00156 setIcon(icon); 00157 setText(text); 00158 } 00159 00160 KAction::~KAction() 00161 { 00162 if (d->globalShortcutEnabled) { 00163 // - remove the action from KGlobalAccel 00164 d->globalShortcutEnabled = false; 00165 KGlobalAccel::self()->d->remove(this, KGlobalAccelPrivate::SetInactive); 00166 } 00167 00168 KGestureMap::self()->removeGesture(d->shapeGesture, this); 00169 KGestureMap::self()->removeGesture(d->rockerGesture, this); 00170 delete d; 00171 } 00172 00173 bool KAction::isShortcutConfigurable() const 00174 { 00175 return property("isShortcutConfigurable").toBool(); 00176 } 00177 00178 void KAction::setShortcutConfigurable( bool b ) 00179 { 00180 setProperty("isShortcutConfigurable", b); 00181 } 00182 00183 KShortcut KAction::shortcut(ShortcutTypes type) const 00184 { 00185 Q_ASSERT(type); 00186 00187 if (type == DefaultShortcut) { 00188 QKeySequence primary = property("defaultPrimaryShortcut").value<QKeySequence>(); 00189 QKeySequence secondary = property("defaultAlternateShortcut").value<QKeySequence>(); 00190 return KShortcut(primary, secondary); 00191 } 00192 00193 QKeySequence primary = shortcuts().value(0); 00194 QKeySequence secondary = shortcuts().value(1); 00195 return KShortcut(primary, secondary); 00196 } 00197 00198 void KAction::setShortcut( const KShortcut & shortcut, ShortcutTypes type ) 00199 { 00200 Q_ASSERT(type); 00201 00202 if (type & DefaultShortcut) { 00203 setProperty("defaultPrimaryShortcut", shortcut.primary()); 00204 setProperty("defaultAlternateShortcut", shortcut.alternate()); 00205 } 00206 00207 if (type & ActiveShortcut) { 00208 QAction::setShortcuts(shortcut); 00209 } 00210 } 00211 00212 void KAction::setShortcut( const QKeySequence & keySeq, ShortcutTypes type ) 00213 { 00214 Q_ASSERT(type); 00215 00216 if (type & DefaultShortcut) 00217 setProperty("defaultPrimaryShortcut", keySeq); 00218 00219 if (type & ActiveShortcut) { 00220 QAction::setShortcut(keySeq); 00221 } 00222 } 00223 00224 void KAction::setShortcuts(const QList<QKeySequence>& shortcuts, ShortcutTypes type) 00225 { 00226 setShortcut(KShortcut(shortcuts), type); 00227 } 00228 00229 const KShortcut & KAction::globalShortcut(ShortcutTypes type) const 00230 { 00231 Q_ASSERT(type); 00232 00233 if (type == DefaultShortcut) 00234 return d->defaultGlobalShortcut; 00235 00236 return d->globalShortcut; 00237 } 00238 00239 void KAction::setGlobalShortcut( const KShortcut & shortcut, ShortcutTypes type, 00240 GlobalShortcutLoading load ) 00241 { 00242 Q_ASSERT(type); 00243 bool changed = false; 00244 00245 // protect against garbage keycode -1 that Qt sometimes produces for exotic keys; 00246 // at the moment (~mid 2008) Multimedia PlayPause is one of those keys. 00247 int shortcutKeys[8]; 00248 for (int i = 0; i < 4; i++) { 00249 shortcutKeys[i] = shortcut.primary()[i]; 00250 shortcutKeys[i + 4] = shortcut.alternate()[i]; 00251 } 00252 for (int i = 0; i < 8; i++) { 00253 if (shortcutKeys[i] == -1) { 00254 kWarning(283) << "Encountered garbage keycode (keycode = -1) in input, not doing anything."; 00255 return; 00256 } 00257 } 00258 00259 if (!d->globalShortcutEnabled) { 00260 changed = true; 00261 if (objectName().isEmpty() || objectName().startsWith(QLatin1String("unnamed-"))) { 00262 kWarning(283) << "Attempt to set global shortcut for action without objectName()." 00263 " Read the setGlobalShortcut() documentation."; 00264 return; 00265 } 00266 d->globalShortcutEnabled = true; 00267 KGlobalAccel::self()->d->doRegister(this); 00268 } 00269 00270 if ((type & DefaultShortcut) && d->defaultGlobalShortcut != shortcut) { 00271 d->defaultGlobalShortcut = shortcut; 00272 changed = true; 00273 } 00274 00275 if ((type & ActiveShortcut) && d->globalShortcut != shortcut) { 00276 d->globalShortcut = shortcut; 00277 changed = true; 00278 } 00279 00280 //We want to have updateGlobalShortcuts called on a new action in any case so that 00281 //it will be registered properly. In the case of the first setShortcut() call getting an 00282 //empty shortcut parameter this would not happen... 00283 if (changed || d->neverSetGlobalShortcut) { 00284 KGlobalAccel::self()->d->updateGlobalShortcut(this, type | load); 00285 d->neverSetGlobalShortcut = false; 00286 } 00287 } 00288 00289 #ifndef KDE_NO_DEPRECATED 00290 bool KAction::globalShortcutAllowed() const 00291 { 00292 return d->globalShortcutEnabled; 00293 } 00294 #endif 00295 00296 bool KAction::isGlobalShortcutEnabled() const 00297 { 00298 return d->globalShortcutEnabled; 00299 } 00300 00301 #ifndef KDE_NO_DEPRECATED 00302 void KAction::setGlobalShortcutAllowed( bool allowed, GlobalShortcutLoading /* load */ ) 00303 { 00304 if (allowed) { 00305 //### no-op 00306 } else { 00307 forgetGlobalShortcut(); 00308 } 00309 } 00310 #endif 00311 00312 void KAction::forgetGlobalShortcut() 00313 { 00314 d->globalShortcut = KShortcut(); 00315 d->defaultGlobalShortcut = KShortcut(); 00316 if (d->globalShortcutEnabled) { 00317 d->globalShortcutEnabled = false; 00318 d->neverSetGlobalShortcut = true; //it's a fresh start :) 00319 KGlobalAccel::self()->d->remove(this, KGlobalAccelPrivate::UnRegister); 00320 } 00321 } 00322 00323 KShapeGesture KAction::shapeGesture( ShortcutTypes type ) const 00324 { 00325 Q_ASSERT(type); 00326 if ( type & DefaultShortcut ) 00327 return d->defaultShapeGesture; 00328 00329 return d->shapeGesture; 00330 } 00331 00332 KRockerGesture KAction::rockerGesture( ShortcutTypes type ) const 00333 { 00334 Q_ASSERT(type); 00335 if ( type & DefaultShortcut ) 00336 return d->defaultRockerGesture; 00337 00338 return d->rockerGesture; 00339 } 00340 00341 void KAction::setShapeGesture( const KShapeGesture& gest, ShortcutTypes type ) 00342 { 00343 Q_ASSERT(type); 00344 00345 if( type & DefaultShortcut ) 00346 d->defaultShapeGesture = gest; 00347 00348 if ( type & ActiveShortcut ) { 00349 if ( KGestureMap::self()->findAction( gest ) ) { 00350 kDebug(283) << "New mouse gesture already in use, won't change gesture."; 00351 return; 00352 } 00353 KGestureMap::self()->removeGesture( d->shapeGesture, this ); 00354 KGestureMap::self()->addGesture( gest, this ); 00355 d->shapeGesture = gest; 00356 } 00357 } 00358 00359 void KAction::setRockerGesture( const KRockerGesture& gest, ShortcutTypes type ) 00360 { 00361 Q_ASSERT(type); 00362 00363 if( type & DefaultShortcut ) 00364 d->defaultRockerGesture = gest; 00365 00366 if ( type & ActiveShortcut ) { 00367 if ( KGestureMap::self()->findAction( gest ) ) { 00368 kDebug(283) << "New mouse gesture already in use, won't change gesture."; 00369 return; 00370 } 00371 KGestureMap::self()->removeGesture( d->rockerGesture, this ); 00372 KGestureMap::self()->addGesture( gest, this ); 00373 d->rockerGesture = gest; 00374 } 00375 } 00376 00377 void KAction::setHelpText(const QString& text) 00378 { 00379 setStatusTip(text); 00380 setToolTip(text); 00381 if (whatsThis().isEmpty()) 00382 setWhatsThis(text); 00383 } 00384 00385 KAuth::Action *KAction::authAction() const 00386 { 00387 return d->authAction; 00388 } 00389 00390 void KAction::setAuthAction(const QString &actionName) 00391 { 00392 if (actionName.isEmpty()) { 00393 setAuthAction(0); 00394 } else { 00395 setAuthAction(new KAuth::Action(actionName)); 00396 } 00397 } 00398 00399 void KAction::setAuthAction(KAuth::Action *action) 00400 { 00401 if (d->authAction == action) { 00402 return; 00403 } 00404 00405 if (d->authAction) { 00406 disconnect(d->authAction->watcher(), SIGNAL(statusChanged(int)), 00407 this, SLOT(authStatusChanged(int))); 00408 //delete d->authAction; 00409 d->authAction = 0; 00410 if (!d->oldIcon.isNull()) { 00411 setIcon(d->oldIcon); 00412 d->oldIcon = KIcon(); 00413 } 00414 } 00415 00416 if (action != 0) { 00417 d->authAction = action; 00418 00419 // Set the parent widget 00420 d->authAction->setParentWidget(parentWidget()); 00421 00422 connect(d->authAction->watcher(), SIGNAL(statusChanged(int)), 00423 this, SLOT(authStatusChanged(int))); 00424 d->authStatusChanged(d->authAction->status()); 00425 } 00426 } 00427 00428 /* vim: et sw=2 ts=2 00429 */ 00430 00431 #include "kaction.moc"
KDE 4.6 API Reference