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