00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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/QShortcutEvent>
00037
00038 #include <kdebug.h>
00039
00040 #include "kguiitem.h"
00041 #include "kicon.h"
00042
00043
00044
00045
00046
00047 void KActionPrivate::init(KAction *q_ptr)
00048 {
00049 q = q_ptr;
00050 globalShortcutEnabled = false;
00051 neverSetGlobalShortcut = true;
00052
00053 QObject::connect(q, SIGNAL(triggered(bool)), q, SLOT(slotTriggered()));
00054
00055 q->setProperty("isShortcutConfigurable", true);
00056 }
00057
00058 void KActionPrivate::setActiveGlobalShortcutNoEnable(const KShortcut &cut)
00059 {
00060 globalShortcut = cut;
00061 emit q->globalShortcutChanged(cut.primary());
00062 }
00063
00064
00065 void KActionPrivate::slotTriggered()
00066 {
00067 #ifdef KDE3_SUPPORT
00068 emit q->activated();
00069 #endif
00070 emit q->triggered(QApplication::mouseButtons(), QApplication::keyboardModifiers());
00071
00072 if (authAction) {
00073 KAuth::Action::AuthStatus s = authAction->authorize();
00074 switch(s) {
00075 case KAuth::Action::Denied:
00076 q->setEnabled(false);
00077 break;
00078 case KAuth::Action::Authorized:
00079 emit q->authorized(authAction);
00080 break;
00081 default:
00082 break;
00083 }
00084 }
00085 }
00086
00087 void KActionPrivate::authStatusChanged(int status)
00088 {
00089 KAuth::Action::AuthStatus s = (KAuth::Action::AuthStatus)status;
00090
00091 switch(s) {
00092 case KAuth::Action::Authorized:
00093 q->setEnabled(true);
00094 if(!oldIcon.isNull()) {
00095 q->setIcon(oldIcon);
00096 oldIcon = KIcon();
00097 }
00098 break;
00099 case KAuth::Action::AuthRequired:
00100 q->setEnabled(true);
00101 oldIcon = KIcon(q->icon());
00102 q->setIcon(KIcon("dialog-password"));
00103 break;
00104 default:
00105 q->setEnabled(false);
00106 if(!oldIcon.isNull()) {
00107 q->setIcon(oldIcon);
00108 oldIcon = KIcon();
00109 }
00110 }
00111 }
00112
00113 bool KAction::event(QEvent *event)
00114 {
00115 if (event->type() == QEvent::Shortcut) {
00116 QShortcutEvent *se = static_cast<QShortcutEvent*>(event);
00117 if(se->isAmbiguous()) {
00118 KMessageBox::information(
00119 NULL,
00120 i18n( "The key sequence '%1' is ambiguous. Use 'Configure Shortcuts'\n"
00121 "from the 'Settings' menu to solve the ambiguity.\n"
00122 "No action will be triggered.",
00123 se->key().toString()),
00124 i18n("Ambiguous shortcut detected"));
00125 return true;
00126 }
00127 }
00128
00129 return QAction::event(event);
00130 }
00131
00132
00133
00134
00135
00136
00137 KAction::KAction(QObject *parent)
00138 : QWidgetAction(parent), d(new KActionPrivate)
00139 {
00140 d->init(this);
00141 }
00142
00143 KAction::KAction(const QString &text, QObject *parent)
00144 : QWidgetAction(parent), d(new KActionPrivate)
00145 {
00146 d->init(this);
00147 setText(text);
00148 }
00149
00150 KAction::KAction(const KIcon &icon, const QString &text, QObject *parent)
00151 : QWidgetAction(parent), d(new KActionPrivate)
00152 {
00153 d->init(this);
00154 setIcon(icon);
00155 setText(text);
00156 }
00157
00158 KAction::~KAction()
00159 {
00160 if (d->globalShortcutEnabled) {
00161
00162 d->globalShortcutEnabled = false;
00163 KGlobalAccel::self()->d->remove(this, KGlobalAccelPrivate::SetInactive);
00164 }
00165
00166 KGestureMap::self()->removeGesture(d->shapeGesture, this);
00167 KGestureMap::self()->removeGesture(d->rockerGesture, this);
00168 delete d;
00169 }
00170
00171 bool KAction::isShortcutConfigurable() const
00172 {
00173 return property("isShortcutConfigurable").toBool();
00174 }
00175
00176 void KAction::setShortcutConfigurable( bool b )
00177 {
00178 setProperty("isShortcutConfigurable", b);
00179 }
00180
00181 KShortcut KAction::shortcut(ShortcutTypes type) const
00182 {
00183 Q_ASSERT(type);
00184
00185 if (type == DefaultShortcut) {
00186 QKeySequence primary = property("defaultPrimaryShortcut").value<QKeySequence>();
00187 QKeySequence secondary = property("defaultAlternateShortcut").value<QKeySequence>();
00188 return KShortcut(primary, secondary);
00189 }
00190
00191 QKeySequence primary = shortcuts().value(0);
00192 QKeySequence secondary = shortcuts().value(1);
00193 return KShortcut(primary, secondary);
00194 }
00195
00196 void KAction::setShortcut( const KShortcut & shortcut, ShortcutTypes type )
00197 {
00198 Q_ASSERT(type);
00199
00200 if (type & DefaultShortcut) {
00201 setProperty("defaultPrimaryShortcut", shortcut.primary());
00202 setProperty("defaultAlternateShortcut", shortcut.alternate());
00203 }
00204
00205 if (type & ActiveShortcut) {
00206 QAction::setShortcuts(shortcut);
00207 }
00208 }
00209
00210 void KAction::setShortcut( const QKeySequence & keySeq, ShortcutTypes type )
00211 {
00212 Q_ASSERT(type);
00213
00214 if (type & DefaultShortcut)
00215 setProperty("defaultPrimaryShortcut", keySeq);
00216
00217 if (type & ActiveShortcut) {
00218 QAction::setShortcut(keySeq);
00219 }
00220 }
00221
00222 void KAction::setShortcuts(const QList<QKeySequence>& shortcuts, ShortcutTypes type)
00223 {
00224 setShortcut(KShortcut(shortcuts), type);
00225 }
00226
00227 const KShortcut & KAction::globalShortcut(ShortcutTypes type) const
00228 {
00229 Q_ASSERT(type);
00230
00231 if (type == DefaultShortcut)
00232 return d->defaultGlobalShortcut;
00233
00234 return d->globalShortcut;
00235 }
00236
00237 void KAction::setGlobalShortcut( const KShortcut & shortcut, ShortcutTypes type,
00238 GlobalShortcutLoading load )
00239 {
00240 Q_ASSERT(type);
00241 bool changed = false;
00242
00243
00244
00245 int shortcutKeys[8];
00246 for (int i = 0; i < 4; i++) {
00247 shortcutKeys[i] = shortcut.primary()[i];
00248 shortcutKeys[i + 4] = shortcut.alternate()[i];
00249 }
00250 for (int i = 0; i < 8; i++) {
00251 if (shortcutKeys[i] == -1) {
00252 kWarning(283) << "Encountered garbage keycode (keycode = -1) in input, not doing anything.";
00253 return;
00254 }
00255 }
00256
00257 if (!d->globalShortcutEnabled) {
00258 changed = true;
00259 if (objectName().isEmpty() || objectName().startsWith(QLatin1String("unnamed-"))) {
00260 kWarning(283) << "Attempt to set global shortcut for action without objectName()."
00261 " Read the setGlobalShortcut() documentation.";
00262 return;
00263 }
00264 d->globalShortcutEnabled = true;
00265 KGlobalAccel::self()->d->doRegister(this);
00266 }
00267
00268 if ((type & DefaultShortcut) && d->defaultGlobalShortcut != shortcut) {
00269 d->defaultGlobalShortcut = shortcut;
00270 changed = true;
00271 }
00272
00273 if ((type & ActiveShortcut) && d->globalShortcut != shortcut) {
00274 d->globalShortcut = shortcut;
00275 changed = true;
00276 }
00277
00278
00279
00280
00281 if (changed || d->neverSetGlobalShortcut) {
00282 KGlobalAccel::self()->d->updateGlobalShortcut(this, type | load);
00283 d->neverSetGlobalShortcut = false;
00284 }
00285 }
00286
00287 bool KAction::globalShortcutAllowed() const
00288 {
00289 return d->globalShortcutEnabled;
00290 }
00291
00292 bool KAction::isGlobalShortcutEnabled() const
00293 {
00294 return d->globalShortcutEnabled;
00295 }
00296
00297 void KAction::setGlobalShortcutAllowed( bool allowed, GlobalShortcutLoading )
00298 {
00299 if (allowed) {
00300
00301 } else {
00302 forgetGlobalShortcut();
00303 }
00304 }
00305
00306 void KAction::forgetGlobalShortcut()
00307 {
00308 d->globalShortcut = KShortcut();
00309 d->defaultGlobalShortcut = KShortcut();
00310 if (d->globalShortcutEnabled) {
00311 d->globalShortcutEnabled = false;
00312 d->neverSetGlobalShortcut = true;
00313 KGlobalAccel::self()->d->remove(this, KGlobalAccelPrivate::UnRegister);
00314 }
00315 }
00316
00317 KShapeGesture KAction::shapeGesture( ShortcutTypes type ) const
00318 {
00319 Q_ASSERT(type);
00320 if ( type & DefaultShortcut )
00321 return d->defaultShapeGesture;
00322
00323 return d->shapeGesture;
00324 }
00325
00326 KRockerGesture KAction::rockerGesture( ShortcutTypes type ) const
00327 {
00328 Q_ASSERT(type);
00329 if ( type & DefaultShortcut )
00330 return d->defaultRockerGesture;
00331
00332 return d->rockerGesture;
00333 }
00334
00335 void KAction::setShapeGesture( const KShapeGesture& gest, ShortcutTypes type )
00336 {
00337 Q_ASSERT(type);
00338
00339 if( type & DefaultShortcut )
00340 d->defaultShapeGesture = gest;
00341
00342 if ( type & ActiveShortcut ) {
00343 if ( KGestureMap::self()->findAction( gest ) ) {
00344 kDebug(283) << "New mouse gesture already in use, won't change gesture.";
00345 return;
00346 }
00347 KGestureMap::self()->removeGesture( d->shapeGesture, this );
00348 KGestureMap::self()->addGesture( gest, this );
00349 d->shapeGesture = gest;
00350 }
00351 }
00352
00353 void KAction::setRockerGesture( const KRockerGesture& gest, ShortcutTypes type )
00354 {
00355 Q_ASSERT(type);
00356
00357 if( type & DefaultShortcut )
00358 d->defaultRockerGesture = gest;
00359
00360 if ( type & ActiveShortcut ) {
00361 if ( KGestureMap::self()->findAction( gest ) ) {
00362 kDebug(283) << "New mouse gesture already in use, won't change gesture.";
00363 return;
00364 }
00365 KGestureMap::self()->removeGesture( d->rockerGesture, this );
00366 KGestureMap::self()->addGesture( gest, this );
00367 d->rockerGesture = gest;
00368 }
00369 }
00370
00371 void KAction::setHelpText(const QString& text)
00372 {
00373 setStatusTip(text);
00374 setToolTip(text);
00375 if (whatsThis().isEmpty())
00376 setWhatsThis(text);
00377 }
00378
00379 KAuth::Action *KAction::authAction() const
00380 {
00381 return d->authAction;
00382 }
00383
00384 void KAction::setAuthAction(const QString &actionName)
00385 {
00386 if (actionName.isEmpty()) {
00387 setAuthAction(0);
00388 } else {
00389 setAuthAction(new KAuth::Action(actionName));
00390 }
00391 }
00392
00393 void KAction::setAuthAction(KAuth::Action *action)
00394 {
00395 if (d->authAction == action) {
00396 return;
00397 }
00398
00399 if (d->authAction) {
00400 disconnect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
00401 this, SLOT(authStatusChanged(int)));
00402
00403 d->authAction = 0;
00404 if (!d->oldIcon.isNull()) {
00405 setIcon(d->oldIcon);
00406 d->oldIcon = KIcon();
00407 }
00408 }
00409
00410 if (action != 0) {
00411 d->authAction = action;
00412 connect(d->authAction->watcher(), SIGNAL(statusChanged(int)),
00413 this, SLOT(authStatusChanged(int)));
00414 d->authStatusChanged(d->authAction->status());
00415 }
00416 }
00417
00418
00419
00420
00421 #include "kaction.moc"