KDEUI
kactioncollection.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-2007 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 "kactioncollection.h" 00028 #include "kactioncategory.h" 00029 #include <kauthorized.h> 00030 #include "kxmlguiclient.h" 00031 #include "kxmlguifactory.h" 00032 00033 #include "kdebug.h" 00034 #include "kglobal.h" 00035 #include "kaction.h" 00036 #include "kaction_p.h" 00037 00038 #include <QtXml/QDomDocument> 00039 #include <QtCore/QSet> 00040 #include <QtCore/QMap> 00041 #include <QtCore/QList> 00042 #include <QtGui/QAction> 00043 00044 #include <stdio.h> 00045 #include "kcomponentdata.h" 00046 #include "kconfiggroup.h" 00047 #include "klocale.h" 00048 00049 class KActionCollectionPrivate 00050 { 00051 public: 00052 KActionCollectionPrivate() 00053 { 00054 q = 0; 00055 m_parentGUIClient = 0L; 00056 00057 configIsGlobal = false; 00058 00059 connectHovered = connectTriggered = false; 00060 00061 configGroup = "Shortcuts"; 00062 } 00063 00064 void setComponentForAction(KAction *kaction) 00065 { kaction->d->maybeSetComponentData(m_componentData); } 00066 00067 static QList<KActionCollection*> s_allCollections; 00068 00069 void _k_associatedWidgetDestroyed(QObject *obj); 00070 void _k_actionDestroyed(QObject *obj); 00071 00072 bool writeKXMLGUIConfigFile(); 00073 00074 KComponentData m_componentData; 00075 00078 QAction *unlistAction(QAction*); 00079 00080 QMap<QString, QAction*> actionByName; 00081 QList<QAction*> actions; 00082 00083 const KXMLGUIClient *m_parentGUIClient; 00084 00085 QString configGroup; 00086 bool configIsGlobal : 1; 00087 00088 bool connectTriggered : 1; 00089 bool connectHovered : 1; 00090 00091 KActionCollection *q; 00092 00093 QList<QWidget*> associatedWidgets; 00094 }; 00095 00096 QList<KActionCollection*> KActionCollectionPrivate::s_allCollections; 00097 00098 KActionCollection::KActionCollection(QObject *parent, const KComponentData &cData) 00099 : QObject( parent ) 00100 , d(new KActionCollectionPrivate) 00101 { 00102 d->q = this; 00103 KActionCollectionPrivate::s_allCollections.append(this); 00104 00105 setComponentData(cData); 00106 } 00107 00108 KActionCollection::KActionCollection( const KXMLGUIClient *parent ) 00109 : QObject( 0 ) 00110 , d(new KActionCollectionPrivate) 00111 { 00112 d->q = this; 00113 KActionCollectionPrivate::s_allCollections.append(this); 00114 00115 d->m_parentGUIClient=parent; 00116 d->m_componentData = parent->componentData(); 00117 } 00118 00119 KActionCollection::~KActionCollection() 00120 { 00121 KActionCollectionPrivate::s_allCollections.removeAll(this); 00122 00123 delete d; 00124 } 00125 00126 void KActionCollection::clear() 00127 { 00128 d->actionByName.clear(); 00129 qDeleteAll(d->actions); 00130 d->actions.clear(); 00131 } 00132 00133 QAction* KActionCollection::action( const QString& name ) const 00134 { 00135 QAction* action = 0L; 00136 00137 if ( !name.isEmpty() ) 00138 action = d->actionByName.value (name); 00139 00140 return action; 00141 } 00142 00143 QAction* KActionCollection::action( int index ) const 00144 { 00145 // ### investigate if any apps use this at all 00146 return actions().value(index); 00147 } 00148 00149 int KActionCollection::count() const 00150 { 00151 return d->actions.count(); 00152 } 00153 00154 bool KActionCollection::isEmpty() const 00155 { 00156 return count() == 0; 00157 } 00158 00159 void KActionCollection::setComponentData(const KComponentData &cData) 00160 { 00161 if (count() > 0) { 00162 // Its component name is part of an action's signature in the context of 00163 // global shortcuts and the semantics of changing an existing action's 00164 // signature are, as it seems, impossible to get right. 00165 // As of now this only matters for global shortcuts. We could 00166 // thus relax the requirement and only refuse to change the component data 00167 // if we have actions with global shortcuts in this collection. 00168 kWarning(129) << "this does not work on a KActionCollection containing actions!"; 00169 } 00170 00171 if (cData.isValid()) { 00172 d->m_componentData = cData; 00173 } else { 00174 d->m_componentData = KGlobal::mainComponent(); 00175 } 00176 } 00177 00178 KComponentData KActionCollection::componentData() const 00179 { 00180 return d->m_componentData; 00181 } 00182 00183 const KXMLGUIClient *KActionCollection::parentGUIClient() const 00184 { 00185 return d->m_parentGUIClient; 00186 } 00187 00188 QList<QAction*> KActionCollection::actions() const 00189 { 00190 return d->actions; 00191 } 00192 00193 const QList< QAction* > KActionCollection::actionsWithoutGroup( ) const 00194 { 00195 QList<QAction*> ret; 00196 foreach (QAction* action, d->actions) 00197 if (!action->actionGroup()) 00198 ret.append(action); 00199 return ret; 00200 } 00201 00202 const QList< QActionGroup * > KActionCollection::actionGroups( ) const 00203 { 00204 QSet<QActionGroup*> set; 00205 foreach (QAction* action, d->actions) 00206 if (action->actionGroup()) 00207 set.insert(action->actionGroup()); 00208 return set.toList(); 00209 } 00210 00211 KAction *KActionCollection::addAction(const QString &name, KAction *action) 00212 { 00213 QAction* ret = addAction(name, static_cast<QAction*>(action)); 00214 Q_ASSERT(ret == action); 00215 Q_UNUSED(ret); // fix compiler warning in release mode 00216 return action; 00217 } 00218 00219 QAction *KActionCollection::addAction(const QString &name, QAction *action) 00220 { 00221 if (!action) 00222 return action; 00223 00224 const QString objectName = action->objectName(); 00225 QString indexName = name; 00226 00227 if (indexName.isEmpty()) { 00228 // No name provided. Use the objectName. 00229 indexName = objectName; 00230 00231 } else { 00232 00233 // A name was provided. Check against objectName. 00234 if ((!objectName.isEmpty()) && (objectName != indexName)) { 00235 // The user specified a new name and the action already has a 00236 // different one. The objectName is used for saving shortcut 00237 // settings to disk. Both for local and global shortcuts. 00238 KAction *kaction = qobject_cast<KAction*>(action); 00239 kDebug(125) << "Registering action " << objectName << " under new name " << indexName; 00240 // If there is a global shortcuts it's a very bad idea. 00241 if (kaction && kaction->isGlobalShortcutEnabled()) { 00242 // In debug mode assert 00243 Q_ASSERT(!kaction->isGlobalShortcutEnabled()); 00244 // In release mode keep the old name 00245 kError() << "Changing action name from " << objectName << " to " << indexName << "\nignored because of active global shortcut."; 00246 indexName = objectName; 00247 } 00248 } 00249 00250 // Set the new name 00251 action->setObjectName(indexName); 00252 } 00253 00254 // No name provided and the action had no name. Make one up. This will not 00255 // work when trying to save shortcuts. Both local and global shortcuts. 00256 if( indexName.isEmpty() ) { 00257 indexName = indexName.sprintf("unnamed-%p", (void*)action); 00258 action->setObjectName(indexName); 00259 } 00260 00261 // From now on the objectName has to have a value. Else we cannot safely 00262 // remove actions. 00263 Q_ASSERT(!action->objectName().isEmpty()); 00264 00265 // look if we already have THIS action under THIS name ;) 00266 if (d->actionByName.value(indexName, 0) == action ) { 00267 // This is not a multi map! 00268 Q_ASSERT( d->actionByName.count(indexName)==1); 00269 return action; 00270 } 00271 00272 if (!KAuthorized::authorizeKAction(indexName)) { 00273 // Disable this action 00274 action->setEnabled(false); 00275 action->setVisible(false); 00276 action->blockSignals(true); 00277 } 00278 00279 // Check if we have another action under this name 00280 if (QAction *oldAction = d->actionByName.value(indexName)) { 00281 takeAction(oldAction); 00282 } 00283 00284 // Check if we have this action under a different name. 00285 // Not using takeAction because we don't want to remove it from categories, 00286 // and because it has the new name already. 00287 const int oldIndex = d->actions.indexOf(action); 00288 if (oldIndex != -1) { 00289 d->actionByName.remove(d->actionByName.key(action)); 00290 d->actions.removeAt(oldIndex); 00291 } 00292 00293 // Add action to our lists. 00294 d->actionByName.insert(indexName, action); 00295 d->actions.append(action); 00296 00297 foreach (QWidget* widget, d->associatedWidgets) { 00298 widget->addAction(action); 00299 } 00300 00301 connect(action, SIGNAL(destroyed(QObject*)), SLOT(_k_actionDestroyed(QObject*))); 00302 00303 // only our private class is a friend of KAction 00304 if (KAction *kaction = dynamic_cast<KAction *>(action)) { 00305 d->setComponentForAction(kaction); 00306 } 00307 00308 if (d->connectHovered) 00309 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered())); 00310 00311 if (d->connectTriggered) 00312 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered())); 00313 00314 emit inserted( action ); 00315 return action; 00316 } 00317 00318 void KActionCollection::removeAction( QAction* action ) 00319 { 00320 delete takeAction( action ); 00321 } 00322 00323 QAction* KActionCollection::takeAction(QAction *action) 00324 { 00325 if (!d->unlistAction(action)) 00326 return NULL; 00327 00328 // Remove the action from all widgets 00329 foreach (QWidget* widget, d->associatedWidgets) { 00330 widget->removeAction(action); 00331 } 00332 00333 action->disconnect(this); 00334 00335 emit removed( action ); //deprecated 00336 return action; 00337 } 00338 00339 KAction *KActionCollection::addAction(KStandardAction::StandardAction actionType, const QObject *receiver, const char *member) 00340 { 00341 KAction *action = KStandardAction::create(actionType, receiver, member, this); 00342 return action; 00343 } 00344 00345 KAction *KActionCollection::addAction(KStandardAction::StandardAction actionType, const QString &name, 00346 const QObject *receiver, const char *member) 00347 { 00348 // pass 0 as parent, because if the parent is a KActionCollection KStandardAction::create automatically 00349 // adds the action to it under the default name. We would trigger the 00350 // warning about renaming the action then. 00351 KAction *action = KStandardAction::create(actionType, receiver, member, 0); 00352 // Give it a parent for gc. 00353 action->setParent(this); 00354 // Remove the name to get rid of the "rename action" warning above 00355 action->setObjectName(name); 00356 // And now add it with the desired name. 00357 return addAction(name, action); 00358 } 00359 00360 KAction *KActionCollection::addAction(const QString &name, const QObject *receiver, const char *member) 00361 { 00362 KAction *a = new KAction(this); 00363 if (receiver && member) 00364 connect(a, SIGNAL(triggered(bool)), receiver, member); 00365 return addAction(name, a); 00366 } 00367 00368 QString KActionCollection::configGroup( ) const 00369 { 00370 return d->configGroup; 00371 } 00372 00373 void KActionCollection::setConfigGroup( const QString & group ) 00374 { 00375 d->configGroup = group; 00376 } 00377 00378 bool KActionCollection::configIsGlobal() const 00379 { 00380 return d->configIsGlobal; 00381 } 00382 00383 void KActionCollection::setConfigGlobal( bool global ) 00384 { 00385 d->configIsGlobal = global; 00386 } 00387 00388 void KActionCollection::importGlobalShortcuts( KConfigGroup* config ) 00389 { 00390 Q_ASSERT(config); 00391 if( !config || !config->exists()) { 00392 return; 00393 } 00394 00395 for (QMap<QString, QAction *>::ConstIterator it = d->actionByName.constBegin(); 00396 it != d->actionByName.constEnd(); ++it) { 00397 KAction *kaction = qobject_cast<KAction*>(it.value()); 00398 if (!kaction) 00399 continue; 00400 00401 QString actionName = it.key(); 00402 00403 if( kaction->isShortcutConfigurable() ) { 00404 QString entry = config->readEntry(actionName, QString()); 00405 if( !entry.isEmpty() ) { 00406 kaction->setGlobalShortcut( KShortcut(entry), KAction::ActiveShortcut, KAction::NoAutoloading ); 00407 } else { 00408 kaction->setGlobalShortcut( kaction->shortcut(KAction::DefaultShortcut), KAction::ActiveShortcut, KAction::NoAutoloading ); 00409 } 00410 } 00411 } 00412 } 00413 00414 00415 void KActionCollection::readSettings( KConfigGroup* config ) 00416 { 00417 KConfigGroup cg( KGlobal::config(), configGroup() ); 00418 if( !config ) 00419 config = &cg; 00420 00421 if( !config->exists()) { 00422 return; 00423 } 00424 00425 for (QMap<QString, QAction *>::ConstIterator it = d->actionByName.constBegin(); 00426 it != d->actionByName.constEnd(); ++it) { 00427 KAction *kaction = qobject_cast<KAction*>(it.value()); 00428 if (!kaction) 00429 continue; 00430 00431 00432 if( kaction->isShortcutConfigurable() ) { 00433 QString actionName = it.key(); 00434 QString entry = config->readEntry(actionName, QString()); 00435 if( !entry.isEmpty() ) { 00436 kaction->setShortcut( KShortcut(entry), KAction::ActiveShortcut ); 00437 } else { 00438 kaction->setShortcut( kaction->shortcut(KAction::DefaultShortcut) ); 00439 } 00440 } 00441 } 00442 00443 //kDebug(125) << " done"; 00444 } 00445 00446 void KActionCollection::exportGlobalShortcuts( KConfigGroup* config, bool writeAll ) const 00447 { 00448 Q_ASSERT(config); 00449 if (!config) { 00450 return; 00451 } 00452 00453 QList<QAction*> writeActions = actions(); 00454 00455 for (QMap<QString, QAction *>::ConstIterator it = d->actionByName.constBegin(); 00456 it != d->actionByName.constEnd(); ++it) { 00457 00458 KAction *kaction = qobject_cast<KAction*>(it.value()); 00459 if (!kaction) 00460 continue; 00461 QString actionName = it.key(); 00462 00463 // If the action name starts with unnamed- spit out a warning. That name 00464 // will change at will and will break loading writing 00465 if (actionName.startsWith(QLatin1String("unnamed-"))) { 00466 kError() << "Skipped exporting Shortcut for action without name " << kaction->text() << "!"; 00467 continue; 00468 } 00469 00470 if( kaction->isShortcutConfigurable() && kaction->isGlobalShortcutEnabled() ) { 00471 bool bConfigHasAction = !config->readEntry( actionName, QString() ).isEmpty(); 00472 bool bSameAsDefault = (kaction->globalShortcut() == kaction->globalShortcut(KAction::DefaultShortcut)); 00473 // If we're using a global config or this setting 00474 // differs from the default, then we want to write. 00475 KConfigGroup::WriteConfigFlags flags = KConfigGroup::Persistent; 00476 if (configIsGlobal()) 00477 flags |= KConfigGroup::Global; 00478 if( writeAll || !bSameAsDefault ) { 00479 QString s = kaction->globalShortcut().toString(); 00480 if( s.isEmpty() ) 00481 s = "none"; 00482 kDebug(125) << "\twriting " << actionName << " = " << s; 00483 config->writeEntry( actionName, s, flags ); 00484 } 00485 // Otherwise, this key is the same as default 00486 // but exists in config file. Remove it. 00487 else if( bConfigHasAction ) { 00488 kDebug(125) << "\tremoving " << actionName << " because == default"; 00489 config->deleteEntry( actionName, flags ); 00490 } 00491 } 00492 } 00493 00494 config->sync(); 00495 } 00496 00497 00498 bool KActionCollectionPrivate::writeKXMLGUIConfigFile() 00499 { 00500 const KXMLGUIClient *kxmlguiClient = q->parentGUIClient(); 00501 // return false if there is no KXMLGUIClient 00502 if (!kxmlguiClient || kxmlguiClient->xmlFile().isEmpty()) { 00503 return false; 00504 } 00505 00506 kDebug(129) << "xmlFile=" << kxmlguiClient->xmlFile(); 00507 00508 QString attrShortcut = QLatin1String("shortcut"); 00509 00510 // Read XML file 00511 QString sXml(KXMLGUIFactory::readConfigFile(kxmlguiClient->xmlFile(), q->componentData())); 00512 QDomDocument doc; 00513 doc.setContent( sXml ); 00514 00515 // Process XML data 00516 00517 // Get hold of ActionProperties tag 00518 QDomElement elem = KXMLGUIFactory::actionPropertiesElement( doc ); 00519 00520 // now, iterate through our actions 00521 for (QMap<QString, QAction *>::ConstIterator it = actionByName.constBegin(); 00522 it != actionByName.constEnd(); ++it) { 00523 KAction *kaction = qobject_cast<KAction*>(it.value()); 00524 if (!kaction) { 00525 continue; 00526 } 00527 00528 QString actionName = it.key(); 00529 00530 // If the action name starts with unnamed- spit out a warning and ignore 00531 // it. That name will change at will and will break loading writing 00532 if (actionName.startsWith(QLatin1String("unnamed-"))) { 00533 kError() << "Skipped writing shortcut for action " << actionName << "(" << kaction->text() << ")!"; 00534 continue; 00535 } 00536 00537 bool bSameAsDefault = (kaction->shortcut() == kaction->shortcut(KAction::DefaultShortcut)); 00538 kDebug(129) << "name = " << actionName 00539 << " shortcut = " << kaction->shortcut(KAction::ActiveShortcut).toString() 00540 << " globalshortcut = " << kaction->globalShortcut(KAction::ActiveShortcut).toString() 00541 << " def = " << kaction->shortcut(KAction::DefaultShortcut).toString(); 00542 00543 // now see if this element already exists 00544 // and create it if necessary (unless bSameAsDefault) 00545 QDomElement act_elem = KXMLGUIFactory::findActionByName( elem, actionName, !bSameAsDefault ); 00546 if ( act_elem.isNull() ) 00547 continue; 00548 00549 if( bSameAsDefault ) { 00550 act_elem.removeAttribute( attrShortcut ); 00551 //kDebug(129) << "act_elem.attributes().count() = " << act_elem.attributes().count(); 00552 if( act_elem.attributes().count() == 1 ) 00553 elem.removeChild( act_elem ); 00554 } else { 00555 act_elem.setAttribute( attrShortcut, kaction->shortcut().toString() ); 00556 } 00557 } 00558 00559 // Write back to XML file 00560 KXMLGUIFactory::saveConfigFile(doc, kxmlguiClient->localXMLFile(), q->componentData()); 00561 return true; 00562 } 00563 00564 00565 void KActionCollection::writeSettings( KConfigGroup* config, bool writeAll, QAction* oneAction ) const 00566 { 00567 // If the caller didn't provide a config group we try to save the KXMLGUI 00568 // Configuration file. If that succeeds we are finished. 00569 if (config==0 && d->writeKXMLGUIConfigFile() ) { 00570 return; 00571 } 00572 00573 KConfigGroup cg(KGlobal::config() , configGroup() ); 00574 if (!config) { 00575 config = &cg; 00576 } 00577 00578 QList<QAction*> writeActions; 00579 if (oneAction) { 00580 writeActions.append(oneAction); 00581 } else { 00582 writeActions = actions(); 00583 } 00584 00585 00586 for (QMap<QString, QAction *>::ConstIterator it = d->actionByName.constBegin(); 00587 it != d->actionByName.constEnd(); ++it) { 00588 00589 // Get the action. We only handle KActions so skip QActions 00590 KAction *kaction = qobject_cast<KAction*>(it.value()); 00591 if (!kaction) { 00592 continue; 00593 } 00594 00595 QString actionName = it.key(); 00596 00597 // If the action name starts with unnamed- spit out a warning and ignore 00598 // it. That name will change at will and will break loading writing 00599 if (actionName.startsWith(QLatin1String("unnamed-"))) { 00600 kError() << "Skipped saving Shortcut for action without name " << kaction->text() << "!"; 00601 continue; 00602 } 00603 00604 // Write the shortcut 00605 if( kaction->isShortcutConfigurable() ) { 00606 bool bConfigHasAction = !config->readEntry( actionName, QString() ).isEmpty(); 00607 bool bSameAsDefault = (kaction->shortcut() == kaction->shortcut(KAction::DefaultShortcut)); 00608 // If we're using a global config or this setting 00609 // differs from the default, then we want to write. 00610 KConfigGroup::WriteConfigFlags flags = KConfigGroup::Persistent; 00611 00612 // Honor the configIsGlobal() setting 00613 if (configIsGlobal()) { 00614 flags |= KConfigGroup::Global; 00615 } 00616 00617 if( writeAll || !bSameAsDefault ) { 00618 // We are instructed to write all shortcuts or the shortcut is 00619 // not set to its default value. Write it 00620 QString s = kaction->shortcut().toString(); 00621 if( s.isEmpty() ) 00622 s = "none"; 00623 kDebug(125) << "\twriting " << actionName << " = " << s; 00624 config->writeEntry( actionName, s, flags ); 00625 00626 } else if( bConfigHasAction ) { 00627 // Otherwise, this key is the same as default but exists in 00628 // config file. Remove it. 00629 kDebug(125) << "\tremoving " << actionName << " because == default"; 00630 config->deleteEntry( actionName, flags ); 00631 } 00632 } 00633 } 00634 00635 config->sync(); 00636 } 00637 00638 void KActionCollection::slotActionTriggered( ) 00639 { 00640 QAction* action = qobject_cast<QAction*>(sender()); 00641 if (action) 00642 emit actionTriggered(action); 00643 } 00644 00645 void KActionCollection::slotActionHighlighted( ) 00646 { 00647 slotActionHovered(); 00648 } 00649 00650 void KActionCollection::slotActionHovered( ) 00651 { 00652 QAction* action = qobject_cast<QAction*>(sender()); 00653 if (action) { 00654 emit actionHighlighted(action); 00655 emit actionHovered(action); 00656 } 00657 } 00658 00659 00660 void KActionCollectionPrivate::_k_actionDestroyed( QObject *obj ) 00661 { 00662 // obj isn't really a QAction anymore. So make sure we don't do fancy stuff 00663 // with it. 00664 QAction *action = static_cast<QAction*>(obj); 00665 00666 if (!unlistAction(action)) 00667 return; 00668 00669 //HACK the object we emit is partly destroyed 00670 emit q->removed(action); //deprecated. remove in KDE5 00671 } 00672 00673 void KActionCollection::connectNotify ( const char * signal ) 00674 { 00675 if (d->connectHovered && d->connectTriggered) 00676 return; 00677 00678 if (QMetaObject::normalizedSignature(SIGNAL(actionHighlighted(QAction*))) == signal || 00679 QMetaObject::normalizedSignature(SIGNAL(actionHovered(QAction*))) == signal) { 00680 if (!d->connectHovered) { 00681 d->connectHovered = true; 00682 foreach (QAction* action, actions()) 00683 connect(action, SIGNAL(hovered()), SLOT(slotActionHovered())); 00684 } 00685 00686 } else if (QMetaObject::normalizedSignature(SIGNAL(actionTriggered(QAction*))) == signal) { 00687 if (!d->connectTriggered) { 00688 d->connectTriggered = true; 00689 foreach (QAction* action, actions()) 00690 connect(action, SIGNAL(triggered(bool)), SLOT(slotActionTriggered())); 00691 } 00692 } 00693 00694 QObject::connectNotify(signal); 00695 } 00696 00697 const QList< KActionCollection * >& KActionCollection::allCollections( ) 00698 { 00699 return KActionCollectionPrivate::s_allCollections; 00700 } 00701 00702 void KActionCollection::associateWidget(QWidget* widget) const 00703 { 00704 foreach (QAction* action, actions()) { 00705 if (!widget->actions().contains(action)) 00706 widget->addAction(action); 00707 } 00708 } 00709 00710 void KActionCollection::addAssociatedWidget(QWidget * widget) 00711 { 00712 if (!d->associatedWidgets.contains(widget)) { 00713 widget->addActions(actions()); 00714 00715 d->associatedWidgets.append(widget); 00716 connect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(_k_associatedWidgetDestroyed(QObject*))); 00717 } 00718 } 00719 00720 void KActionCollection::removeAssociatedWidget(QWidget * widget) 00721 { 00722 foreach (QAction* action, actions()) 00723 widget->removeAction(action); 00724 00725 d->associatedWidgets.removeAll(widget); 00726 disconnect(widget, SIGNAL(destroyed(QObject*)), this, SLOT(_k_associatedWidgetDestroyed(QObject*))); 00727 } 00728 00729 00730 QAction *KActionCollectionPrivate::unlistAction(QAction* action) 00731 { 00732 // ATTENTION: 00733 // This method is called with an QObject formerly known as a QAction 00734 // during _k_actionDestroyed(). So don't do fancy stuff here that needs a 00735 // real QAction! 00736 00737 // Get the index for the action 00738 int index = actions.indexOf(action); 00739 00740 // Action not found. 00741 if (index==-1) return NULL; 00742 00743 // An action collection can't have the same action twice. 00744 Q_ASSERT(actions.indexOf(action,index+1)==-1); 00745 00746 // Get the actions name 00747 const QString name = action->objectName(); 00748 00749 // Remove the action 00750 actionByName.remove(name); 00751 actions.removeAt(index); 00752 00753 // Remove the action from the categories. Should be only one 00754 QList<KActionCategory*> categories = q->findChildren<KActionCategory*>(); 00755 foreach (KActionCategory *category, categories) { 00756 category->unlistAction(action); 00757 } 00758 00759 return action; 00760 } 00761 00762 00763 QList< QWidget * > KActionCollection::associatedWidgets() const 00764 { 00765 return d->associatedWidgets; 00766 } 00767 00768 void KActionCollection::clearAssociatedWidgets() 00769 { 00770 foreach (QWidget* widget, d->associatedWidgets) 00771 foreach (QAction* action, actions()) 00772 widget->removeAction(action); 00773 00774 d->associatedWidgets.clear(); 00775 } 00776 00777 void KActionCollectionPrivate::_k_associatedWidgetDestroyed(QObject *obj) 00778 { 00779 associatedWidgets.removeAll(static_cast<QWidget*>(obj)); 00780 } 00781 00782 /* vim: et sw=2 ts=2 00783 */ 00784 00785 #include "kactioncollection.moc"
KDE 4.6 API Reference