• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kxmlguifactory.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 1999,2000 Simon Hausmann <hausmann@kde.org>
00003    Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "kxmlguifactory.h"
00022 #include "kxmlguifactory_p.h"
00023 #include "kxmlguiclient.h"
00024 #include "kxmlguibuilder.h"
00025 
00026 #include <assert.h>
00027 
00028 #include <QtCore/QDir>
00029 #include <QtXml/QDomDocument>
00030 #include <QtCore/QFile>
00031 #include <QtCore/QTextIStream>
00032 #include <QtGui/QWidget>
00033 #include <QtCore/QDate>
00034 #include <QtCore/QVariant>
00035 #include <QTextCodec>
00036 
00037 #include <kdebug.h>
00038 #include <kcomponentdata.h>
00039 #include <kglobal.h>
00040 #include <kshortcut.h>
00041 #include <kstandarddirs.h>
00042 
00043 #include "kaction.h"
00044 #include "kshortcutsdialog.h"
00045 #include "kactioncollection.h"
00046 
00047 using namespace KXMLGUI;
00048 
00049 class KXMLGUIFactoryPrivate : public BuildState
00050 {
00051 public:
00052     enum ShortcutOption { SetActiveShortcut = 1, SetDefaultShortcut = 2};
00053 
00054     KXMLGUIFactoryPrivate()
00055     {
00056         static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
00057         static const QString &actionList = KGlobal::staticQString( "actionlist" );
00058         static const QString &name = KGlobal::staticQString( "name" );
00059 
00060         m_rootNode = new ContainerNode( 0L, QString(), 0L );
00061         m_defaultMergingName = defaultMergingName;
00062         tagActionList = actionList;
00063         attrName = name;
00064     }
00065     ~KXMLGUIFactoryPrivate()
00066     {
00067         delete m_rootNode;
00068     }
00069 
00070     void pushState()
00071     {
00072         m_stateStack.push( *this );
00073     }
00074 
00075     void popState()
00076     {
00077         BuildState::operator=( m_stateStack.pop() );
00078     }
00079 
00080     bool emptyState() const { return m_stateStack.isEmpty(); }
00081 
00082     QWidget *findRecursive( KXMLGUI::ContainerNode *node, bool tag );
00083     QList<QWidget*> findRecursive( KXMLGUI::ContainerNode *node, const QString &tagName );
00084     void applyActionProperties( const QDomElement &element,
00085         ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut );
00086     void configureAction( QAction *action, const QDomNamedNodeMap &attributes,
00087         ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut );
00088     void configureAction( QAction *action, const QDomAttr &attribute,
00089         ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut );
00090 
00091     QDomDocument shortcutSchemeDoc(KXMLGUIClient *client);
00092     void applyShortcutScheme(KXMLGUIClient *client, QDomDocument scheme);
00093     void refreshActionProperties(KXMLGUIClient *client, QDomDocument doc);
00094     void saveDefaultActionProperties(KXMLGUIClient *client);
00095 
00096     ContainerNode *m_rootNode;
00097 
00098     QString m_defaultMergingName;
00099 
00100     /*
00101      * Contains the container which is searched for in ::container .
00102      */
00103     QString m_containerName;
00104 
00105     /*
00106      * List of all clients
00107      */
00108     QList<KXMLGUIClient*> m_clients;
00109 
00110     QString tagActionList;
00111 
00112     QString attrName;
00113 
00114     BuildStateStack m_stateStack;
00115 };
00116 
00117 QString KXMLGUIFactory::readConfigFile( const QString &filename, const KComponentData &_componentData )
00118 {
00119     KComponentData componentData = _componentData.isValid() ? _componentData : KGlobal::mainComponent();
00120     QString xml_file;
00121 
00122     if (!QDir::isRelativePath(filename))
00123         xml_file = filename;
00124     else
00125     {
00126         xml_file = KStandardDirs::locate("data", componentData.componentName() + '/' + filename);
00127         if ( !QFile::exists( xml_file ) )
00128           xml_file = KStandardDirs::locate( "data", filename );
00129     }
00130 
00131     QFile file( xml_file );
00132     if ( xml_file.isEmpty() || !file.open( QIODevice::ReadOnly ) )
00133     {
00134         kError(240) << "No such XML file" << filename;
00135         return QString();
00136     }
00137 
00138     QByteArray buffer(file.readAll());
00139     return QString::fromUtf8(buffer.constData(), buffer.size());
00140 }
00141 
00142 bool KXMLGUIFactory::saveConfigFile( const QDomDocument& doc,
00143                                      const QString& filename, const KComponentData &_componentData )
00144 {
00145     KComponentData componentData = _componentData.isValid() ? _componentData : KGlobal::mainComponent();
00146     QString xml_file(filename);
00147 
00148     if (QDir::isRelativePath(xml_file))
00149         xml_file = KStandardDirs::locateLocal("data", componentData.componentName() + '/' + filename);
00150 
00151     QFile file( xml_file );
00152     if ( xml_file.isEmpty() || !file.open( QIODevice::WriteOnly ) )
00153     {
00154         kError(240) << "Could not write to" << filename;
00155         return false;
00156     }
00157 
00158     // write out our document
00159     QTextStream ts(&file);
00160     ts.setCodec( QTextCodec::codecForName( "UTF-8" ) );
00161     ts << doc;
00162 
00163     file.close();
00164     return true;
00165 }
00166 
00170 static void removeDOMComments( QDomNode &node )
00171 {
00172     QDomNode n = node.firstChild();
00173     while ( !n.isNull() )
00174     {
00175         if ( n.nodeType() == QDomNode::CommentNode )
00176         {
00177             QDomNode tmp = n;
00178             n = n.nextSibling();
00179             node.removeChild( tmp );
00180         }
00181         else
00182         {
00183             QDomNode tmp = n;
00184             n = n.nextSibling();
00185             removeDOMComments( tmp );
00186         }
00187     }
00188 }
00189 
00190 KXMLGUIFactory::KXMLGUIFactory( KXMLGUIBuilder *builder, QObject *parent )
00191     : QObject( parent ),d(new KXMLGUIFactoryPrivate)
00192 {
00193     d->builder = builder;
00194     d->guiClient = 0;
00195     if ( d->builder )
00196     {
00197         d->builderContainerTags = d->builder->containerTags();
00198         d->builderCustomTags = d->builder->customTags();
00199     }
00200 }
00201 
00202 KXMLGUIFactory::~KXMLGUIFactory()
00203 {
00204     delete d;
00205 }
00206 
00207 void KXMLGUIFactory::addClient( KXMLGUIClient *client )
00208 {
00209     //kDebug(260) << client;
00210     if ( client->factory() ) {
00211         if ( client->factory() == this )
00212             return;
00213         else
00214             client->factory()->removeClient( client ); //just in case someone does stupid things ;-)
00215     }
00216 
00217     if (d->emptyState())
00218         emit makingChanges(true);
00219     d->pushState();
00220 
00221 //    QTime dt; dt.start();
00222 
00223     d->guiClient = client;
00224 
00225     // add this client to our client list
00226     if ( !d->m_clients.contains( client ) )
00227         d->m_clients.append( client );
00228     else
00229         kDebug(260) << "XMLGUI client already added " << client;
00230 
00231     // Tell the client that plugging in is process and
00232     //  let it know what builder widget its mainwindow shortcuts
00233     //  should be attached to.
00234     client->beginXMLPlug( d->builder->widget() );
00235 
00236     // try to use the build document for building the client's GUI, as the build document
00237     // contains the correct container state information (like toolbar positions, sizes, etc.) .
00238     // if there is non available, then use the "real" document.
00239     QDomDocument doc = client->xmlguiBuildDocument();
00240     if ( doc.documentElement().isNull() )
00241         doc = client->domDocument();
00242 
00243     QDomElement docElement = doc.documentElement();
00244 
00245     d->m_rootNode->index = -1;
00246 
00247     // cache some variables
00248 
00249     d->clientName = docElement.attribute( d->attrName );
00250     d->clientBuilder = client->clientBuilder();
00251 
00252     if ( d->clientBuilder )
00253     {
00254         d->clientBuilderContainerTags = d->clientBuilder->containerTags();
00255         d->clientBuilderCustomTags = d->clientBuilder->customTags();
00256     }
00257     else
00258     {
00259         d->clientBuilderContainerTags.clear();
00260         d->clientBuilderCustomTags.clear();
00261     }
00262 
00263     // load shortcut schemes, user-defined shortcuts and other action properties
00264     d->saveDefaultActionProperties(client);
00265     d->refreshActionProperties(client, doc);
00266 
00267     BuildHelper( *d, d->m_rootNode ).build( docElement );
00268 
00269     // let the client know that we built its GUI.
00270     client->setFactory( this );
00271 
00272     // call the finalizeGUI method, to fix up the positions of toolbars for example.
00273     // ### FIXME : obey client builder
00274     // --- Well, toolbars have a bool "positioned", so it doesn't really matter,
00275     // if we call positionYourself on all of them each time. (David)
00276     d->builder->finalizeGUI( d->guiClient );
00277 
00278     // reset some variables, for safety
00279     d->BuildState::reset();
00280 
00281     client->endXMLPlug();
00282 
00283     d->popState();
00284 
00285     emit clientAdded( client );
00286 
00287     // build child clients
00288     foreach (KXMLGUIClient *child, client->childClients())
00289         addClient( child );
00290 
00291     if (d->emptyState())
00292         emit makingChanges(false);
00293 /*
00294     QString unaddedActions;
00295     foreach (KActionCollection* ac, KActionCollection::allCollections())
00296       foreach (QAction* action, ac->actions())
00297         if (action->associatedWidgets().isEmpty())
00298           unaddedActions += action->objectName() + ' ';
00299 
00300     if (!unaddedActions.isEmpty())
00301       kWarning() << "The following actions are not plugged into the gui (shortcuts will not work): " << unaddedActions;
00302 */
00303 
00304 //    kDebug() << "addClient took " << dt.elapsed();
00305 }
00306 
00307 void KXMLGUIFactory::refreshActionProperties()
00308 {
00309     foreach (KXMLGUIClient *client, d->m_clients)
00310     {
00311         d->guiClient = client;
00312         QDomDocument doc = client->xmlguiBuildDocument();
00313         if ( doc.documentElement().isNull() )
00314         {
00315             client->reloadXML();
00316             doc = client->domDocument();
00317         }
00318         d->refreshActionProperties(client, doc);
00319     }
00320     d->guiClient = 0;
00321 }
00322 
00323 void KXMLGUIFactoryPrivate::refreshActionProperties(KXMLGUIClient *client, QDomDocument doc)
00324 {
00325     // try to find and apply shortcuts schemes
00326     QDomDocument scheme = shortcutSchemeDoc(client);
00327     applyShortcutScheme(client, scheme);
00328 
00329     // try to find and apply user-defined shortcuts
00330     QDomElement actionPropElement = KXMLGUIFactory::actionPropertiesElement(doc);
00331     if (actionPropElement.childNodes().isEmpty())
00332         doc.documentElement().removeChild(actionPropElement);
00333 
00334     if ( !actionPropElement.isNull() )
00335         applyActionProperties( actionPropElement );
00336 }
00337 
00338 void KXMLGUIFactoryPrivate::saveDefaultActionProperties(KXMLGUIClient *client)
00339 {
00340     // This method is called every time the user activated a new
00341     // kxmlguiclient. We only want to execute the following code only once in
00342     // the lifetime of an action.
00343     foreach (QAction *action, client->actionCollection()->actions())
00344     {
00345         // Skip actions we have seen already.
00346         if (action->property("_k_DefaultShortcut").isValid()) continue;
00347 
00348         if (KAction* kaction = qobject_cast<KAction*>(action))
00349         {
00350             // Check if the default shortcut is set
00351             KShortcut defaultShortcut = kaction->shortcut(KAction::DefaultShortcut);
00352             KShortcut activeShortcut  = kaction->shortcut(KAction::ActiveShortcut);
00353 
00354             // Check if we have an empty default shortcut and an non empty
00355             // custom shortcut. This should only happen if a developer called
00356             // QAction::setShortcut on an KAction. Print out a warning and
00357             // correct the mistake
00358             if ((!activeShortcut.isEmpty()) && defaultShortcut.isEmpty())
00359             {
00360                 kError() << "Shortcut for KAction " << kaction->objectName() << kaction->text() << "set with QShortcut::setShortcut()! See KAction documentation.";
00361                 kaction->setProperty("_k_DefaultShortcut", activeShortcut);
00362             }
00363             else
00364             {
00365                 kaction->setProperty("_k_DefaultShortcut", defaultShortcut);
00366             }
00367         }
00368         else
00369         {
00370             // A QAction used with KXMLGUI? Set our property and ignore it.
00371             kError() << "Attempt to use QAction" << action->objectName() << "with KXMLGUIFactory!";
00372             action->setProperty("_k_DefaultShortcut", KShortcut());
00373         }
00374 
00375     }
00376 }
00377 
00378 void KXMLGUIFactory::changeShortcutScheme(const QString &scheme)
00379 {
00380     kDebug(260) << "Changing shortcut scheme to" << scheme;
00381     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00382     cg.writeEntry("Current Scheme", scheme);
00383 
00384     refreshActionProperties();
00385 }
00386 
00387 void KXMLGUIFactory::removeClient( KXMLGUIClient *client )
00388 {
00389     //kDebug(260) << client;
00390 
00391     // don't try to remove the client's GUI if we didn't build it
00392     if ( !client || client->factory() != this )
00393         return;
00394 
00395     if (d->emptyState())
00396         emit makingChanges(true);
00397 
00398     // remove this client from our client list
00399     d->m_clients.removeAll( client );
00400 
00401     // remove child clients first (create a copy of the list just in case the
00402     // original list is modified directly or indirectly in removeClient())
00403     const QList<KXMLGUIClient*> childClients(client->childClients());
00404     foreach (KXMLGUIClient *child, childClients)
00405         removeClient(child);
00406 
00407     //kDebug(260) << "calling removeRecursive";
00408 
00409     d->pushState();
00410 
00411     // cache some variables
00412 
00413     d->guiClient = client;
00414     d->clientName = client->domDocument().documentElement().attribute( d->attrName );
00415     d->clientBuilder = client->clientBuilder();
00416 
00417     client->setFactory( 0L );
00418 
00419     // if we don't have a build document for that client, yet, then create one by
00420     // cloning the original document, so that saving container information in the
00421     // DOM tree does not touch the original document.
00422     QDomDocument doc = client->xmlguiBuildDocument();
00423     if ( doc.documentElement().isNull() )
00424     {
00425         doc = client->domDocument().cloneNode( true ).toDocument();
00426         client->setXMLGUIBuildDocument( doc );
00427     }
00428 
00429     d->m_rootNode->destruct( doc.documentElement(), *d );
00430 
00431     // reset some variables
00432     d->BuildState::reset();
00433 
00434     // This will destruct the KAccel object built around the given widget.
00435     client->prepareXMLUnplug( d->builder->widget() );
00436 
00437     d->popState();
00438 
00439     if (d->emptyState())
00440         emit makingChanges(false);
00441 
00442     emit clientRemoved( client );
00443 }
00444 
00445 QList<KXMLGUIClient*> KXMLGUIFactory::clients() const
00446 {
00447     return d->m_clients;
00448 }
00449 
00450 QWidget *KXMLGUIFactory::container( const QString &containerName, KXMLGUIClient *client,
00451                                     bool useTagName )
00452 {
00453     d->pushState();
00454     d->m_containerName = containerName;
00455     d->guiClient = client;
00456 
00457     QWidget *result = d->findRecursive( d->m_rootNode, useTagName );
00458 
00459     d->guiClient = 0L;
00460     d->m_containerName.clear();
00461 
00462     d->popState();
00463 
00464     return result;
00465 }
00466 
00467 QList<QWidget*> KXMLGUIFactory::containers( const QString &tagName )
00468 {
00469     return d->findRecursive( d->m_rootNode, tagName );
00470 }
00471 
00472 void KXMLGUIFactory::reset()
00473 {
00474     d->m_rootNode->reset();
00475 
00476     d->m_rootNode->clearChildren();
00477 }
00478 
00479 void KXMLGUIFactory::resetContainer( const QString &containerName, bool useTagName )
00480 {
00481     if ( containerName.isEmpty() )
00482         return;
00483 
00484     ContainerNode *container = d->m_rootNode->findContainer( containerName, useTagName );
00485 
00486     if ( !container )
00487         return;
00488 
00489     ContainerNode *parent = container->parent;
00490     if ( !parent )
00491         return;
00492 
00493     //  resetInternal( container );
00494 
00495     parent->removeChild( container );
00496 }
00497 
00498 QWidget *KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node, bool tag )
00499 {
00500     if ( ( ( !tag && node->name == m_containerName ) ||
00501            ( tag && node->tagName == m_containerName ) ) &&
00502          ( !guiClient || node->client == guiClient ) )
00503         return node->container;
00504 
00505     foreach (ContainerNode* child, node->children)
00506     {
00507         QWidget *cont = findRecursive( child, tag );
00508         if ( cont )
00509             return cont;
00510     }
00511 
00512     return 0L;
00513 }
00514 
00515 // Case insensitive equality without calling toLower which allocates a new string
00516 static inline bool equals(const QString& str1, const char* str2)
00517 {
00518     return str1.compare(QLatin1String(str2), Qt::CaseInsensitive) == 0;
00519 }
00520 static inline bool equals(const QString& str1, const QString& str2)
00521 {
00522     return str1.compare(str2, Qt::CaseInsensitive) == 0;
00523 }
00524 
00525 
00526 QList<QWidget*> KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node,
00527                                                       const QString &tagName )
00528 {
00529     QList<QWidget*> res;
00530 
00531     if ( equals(node->tagName, tagName) )
00532         res.append( node->container );
00533 
00534     foreach (KXMLGUI::ContainerNode* child, node->children)
00535         res << findRecursive( child, tagName );
00536 
00537     return res;
00538 }
00539 
00540 void KXMLGUIFactory::plugActionList( KXMLGUIClient *client, const QString &name,
00541                                      const QList<QAction*> &actionList )
00542 {
00543     d->pushState();
00544     d->guiClient = client;
00545     d->actionListName = name;
00546     d->actionList = actionList;
00547     d->clientName = client->domDocument().documentElement().attribute( d->attrName );
00548 
00549     d->m_rootNode->plugActionList( *d );
00550 
00551     d->BuildState::reset();
00552     d->popState();
00553 }
00554 
00555 void KXMLGUIFactory::unplugActionList( KXMLGUIClient *client, const QString &name )
00556 {
00557     d->pushState();
00558     d->guiClient = client;
00559     d->actionListName = name;
00560     d->clientName = client->domDocument().documentElement().attribute( d->attrName );
00561 
00562     d->m_rootNode->unplugActionList( *d );
00563 
00564     d->BuildState::reset();
00565     d->popState();
00566 }
00567 
00568 void KXMLGUIFactoryPrivate::applyActionProperties( const QDomElement &actionPropElement,
00569         ShortcutOption shortcutOption )
00570 {
00571     for (QDomNode n = actionPropElement.firstChild();
00572          !n.isNull(); n = n.nextSibling() )
00573     {
00574         QDomElement e = n.toElement();
00575         if ( !equals(e.tagName(), "action") )
00576             continue;
00577 
00578         QAction *action = guiClient->action( e );
00579         if ( !action )
00580             continue;
00581 
00582         configureAction( action, e.attributes(), shortcutOption );
00583     }
00584 }
00585 
00586 void KXMLGUIFactoryPrivate::configureAction( QAction *action, const QDomNamedNodeMap &attributes,
00587         ShortcutOption shortcutOption )
00588 {
00589     for ( uint i = 0; i < attributes.length(); i++ )
00590     {
00591         QDomAttr attr = attributes.item( i ).toAttr();
00592         if ( attr.isNull() )
00593             continue;
00594 
00595         configureAction( action, attr, shortcutOption );
00596     }
00597 }
00598 
00599 void KXMLGUIFactoryPrivate::configureAction( QAction *action, const QDomAttr &attribute,
00600         ShortcutOption shortcutOption )
00601 {
00602     static const QString &attrShortcut = KGlobal::staticQString( "shortcut" );
00603 
00604     QString attrName = attribute.name();
00605     // If the attribute is a deprecated "accel", change to "shortcut".
00606     if ( equals(attrName, "accel") )
00607         attrName = attrShortcut;
00608 
00609     // No need to re-set name, particularly since it's "objectName" in Qt4
00610     if ( equals(attrName, "name") )
00611         return;
00612 
00613     if ( equals(attrName, "icon") ) {
00614         action->setIcon( KIcon( attribute.value() ) );
00615         return;
00616     }
00617 
00618     QVariant propertyValue;
00619 
00620     QVariant::Type propertyType = action->property( attrName.toLatin1() ).type();
00621 
00622     if ( propertyType == QVariant::Int ) {
00623         propertyValue = QVariant( attribute.value().toInt() );
00624     } else if ( propertyType == QVariant::UInt ) {
00625         propertyValue = QVariant( attribute.value().toUInt() );
00626     } else if ( propertyType == QVariant::UserType && action->property( attrName.toLatin1() ).userType() == qMetaTypeId<KShortcut>() ) {
00627         // Setting the shortcut by property also sets the default shortcut (which is incorrect), so we have to do it directly
00628         if (KAction* ka = qobject_cast<KAction*>(action)) {
00629             if (attrName=="globalShortcut") {
00630                 ka->setGlobalShortcut(KShortcut(attribute.value()), KAction::ActiveShortcut);
00631             } else {
00632                 ka->setShortcut(KShortcut(attribute.value()), KAction::ActiveShortcut);
00633             }
00634             if (shortcutOption & KXMLGUIFactoryPrivate::SetDefaultShortcut)
00635                 ka->setShortcut(KShortcut(attribute.value()), KAction::DefaultShortcut);
00636             return;
00637         }
00638         propertyValue = KShortcut( attribute.value() );
00639     } else {
00640         propertyValue = QVariant( attribute.value() );
00641     }
00642     if (!action->setProperty( attrName.toLatin1(), propertyValue )) {
00643         kWarning() << "Error: Unknown action property " << attrName << " will be ignored!";
00644     }
00645 }
00646 
00647 QDomDocument KXMLGUIFactoryPrivate::shortcutSchemeDoc(KXMLGUIClient *client)
00648 {
00649     // Get the name of the current shorcut scheme
00650     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00651     QString schemeName = cg.readEntry("Current Scheme", "Default");
00652 
00653     QDomDocument doc;
00654     if (schemeName != "Default")
00655     {
00656         // Find the document for the shortcut scheme using both current application path
00657         // and current xmlguiclient path but making a preference to app path
00658         QString schemeFileName = KStandardDirs::locateLocal("data",
00659             client->componentData().componentName() + '/' +
00660             client->componentData().componentName() + schemeName.toLower() + "shortcuts.rc" );
00661 
00662         QFile schemeFile(schemeFileName);
00663         if (schemeFile.open(QIODevice::ReadOnly))
00664         {
00665 //             kDebug(260) << "Found shortcut scheme" << schemeFileName;
00666             doc.setContent(&schemeFile);
00667             schemeFile.close();
00668         }
00669     }
00670     return doc;
00671 }
00672 
00673 void KXMLGUIFactoryPrivate::applyShortcutScheme(KXMLGUIClient *client, QDomDocument scheme)
00674 {
00675     static const QString &actionPropElementName = KGlobal::staticQString( "ActionProperties" );
00676 
00677     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00678     QString schemeName = cg.readEntry("Current Scheme", "Default");
00679 
00680     //First clear all existing shortcuts
00681     if (schemeName != "Default") {
00682         foreach (QAction *action, client->actionCollection()->actions())
00683         {
00684             if (KAction *kaction = qobject_cast<KAction*>(action))
00685             {
00686                 kaction->setShortcut(KShortcut(), KAction::ActiveShortcut);
00687                 // We clear the default shortcut as well because the shortcut scheme will set its own defaults
00688                 kaction->setShortcut(KShortcut(), KAction::DefaultShortcut);
00689             }
00690             else
00691                 action->setProperty("shortcut", KShortcut());
00692         }
00693     } else {
00694         // apply saved default shortcuts
00695         foreach (QAction *action, client->actionCollection()->actions())
00696         {
00697             if (KAction *kaction = qobject_cast<KAction*>(action))
00698             {
00699                 QVariant savedDefaultShortcut = kaction->property("_k_DefaultShortcut");
00700                 if (savedDefaultShortcut.isValid())
00701                 {
00702                     KShortcut shortcut = savedDefaultShortcut.value<KShortcut>();
00703                     kaction->setShortcut(shortcut, KAction::ActiveShortcut);
00704                     kaction->setShortcut(shortcut, KAction::DefaultShortcut);
00705                     continue;
00706                 }
00707             }
00708             action->setProperty("shortcut", KShortcut());
00709         }
00710     }
00711 
00712     if (scheme.isNull())
00713         return;
00714 
00715     QDomElement docElement = scheme.documentElement();
00716     QDomElement actionPropElement = docElement.namedItem( actionPropElementName ).toElement();
00717 
00718     //Check if we really have the shortcut configuration here
00719     if (!actionPropElement.isNull())
00720     {
00721         kDebug(260) << "Applying shortcut scheme for XMLGUI client" << client->componentData().componentName();
00722 
00723         //Apply all shortcuts we have
00724         applyActionProperties(actionPropElement, KXMLGUIFactoryPrivate::SetDefaultShortcut);
00725     }
00726     else
00727         kDebug(260) << "Invalid shortcut scheme file";
00728 }
00729 
00730 int KXMLGUIFactory::configureShortcuts(bool letterCutsOk , bool bSaveSettings )
00731 {
00732     KShortcutsDialog dlg(KShortcutsEditor::AllActions,
00733          letterCutsOk ? KShortcutsEditor::LetterShortcutsAllowed : KShortcutsEditor::LetterShortcutsDisallowed,
00734          qobject_cast<QWidget*>(parent()));
00735     foreach (KXMLGUIClient *client, d->m_clients)
00736     {
00737         if(client && !client->xmlFile().isEmpty())
00738             dlg.addCollection( client->actionCollection() );
00739     }
00740     return dlg.configure(bSaveSettings);
00741 }
00742 
00743 QDomElement KXMLGUIFactory::actionPropertiesElement( QDomDocument& doc )
00744 {
00745     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00746     QString schemeName = cg.readEntry("Current Scheme", "Default");
00747 
00748     const QString tagActionProp = QLatin1String("ActionProperties");
00749     // first, lets see if we have existing properties
00750     QDomElement elem;
00751     QDomNode it = doc.documentElement().firstChild();
00752     for( ; !it.isNull(); it = it.nextSibling() ) {
00753         QDomElement e = it.toElement();
00754         if( ((e.tagName() == tagActionProp) || (e.tagName() == tagActionProp.toLower()))
00755                 && (e.attribute("scheme", "Default") == schemeName) ) {
00756             elem = e;
00757             break;
00758         }
00759     }
00760 
00761     // if there was none, create one
00762     if( elem.isNull() ) {
00763         elem = doc.createElement( tagActionProp );
00764         elem.setAttribute( "scheme", schemeName );
00765         doc.documentElement().appendChild( elem );
00766     }
00767     return elem;
00768 }
00769 
00770 QDomElement KXMLGUIFactory::findActionByName( QDomElement& elem, const QString& sName, bool create )
00771 {
00772         static const QString& attrName = KGlobal::staticQString( "name" );
00773     static const QString& tagAction = KGlobal::staticQString( "Action" );
00774     for( QDomNode it = elem.firstChild(); !it.isNull(); it = it.nextSibling() ) {
00775         QDomElement e = it.toElement();
00776         if( e.attribute( attrName ) == sName )
00777             return e;
00778     }
00779 
00780     if( create ) {
00781         QDomElement act_elem = elem.ownerDocument().createElement( tagAction );
00782         act_elem.setAttribute( attrName, sName );
00783                 elem.appendChild( act_elem );
00784                 return act_elem;
00785     }
00786         return QDomElement();
00787 }
00788 
00789 #include "kxmlguifactory.moc"
00790 
00791 /* vim: et sw=4
00792  */

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal