• Skip to content
  • Skip to link menu
KDE 4.3 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     foreach (KXMLGUIClient *client, d->m_clients) {
00205         client->setFactory ( 0L );
00206     }
00207     delete d;
00208 }
00209 
00210 void KXMLGUIFactory::addClient( KXMLGUIClient *client )
00211 {
00212     //kDebug(260) << client;
00213     if ( client->factory() ) {
00214         if ( client->factory() == this )
00215             return;
00216         else
00217             client->factory()->removeClient( client ); //just in case someone does stupid things ;-)
00218     }
00219 
00220     if (d->emptyState())
00221         emit makingChanges(true);
00222     d->pushState();
00223 
00224 //    QTime dt; dt.start();
00225 
00226     d->guiClient = client;
00227 
00228     // add this client to our client list
00229     if ( !d->m_clients.contains( client ) )
00230         d->m_clients.append( client );
00231     else
00232         kDebug(260) << "XMLGUI client already added " << client;
00233 
00234     // Tell the client that plugging in is process and
00235     //  let it know what builder widget its mainwindow shortcuts
00236     //  should be attached to.
00237     client->beginXMLPlug( d->builder->widget() );
00238 
00239     // try to use the build document for building the client's GUI, as the build document
00240     // contains the correct container state information (like toolbar positions, sizes, etc.) .
00241     // if there is non available, then use the "real" document.
00242     QDomDocument doc = client->xmlguiBuildDocument();
00243     if ( doc.documentElement().isNull() )
00244         doc = client->domDocument();
00245 
00246     QDomElement docElement = doc.documentElement();
00247 
00248     d->m_rootNode->index = -1;
00249 
00250     // cache some variables
00251 
00252     d->clientName = docElement.attribute( d->attrName );
00253     d->clientBuilder = client->clientBuilder();
00254 
00255     if ( d->clientBuilder )
00256     {
00257         d->clientBuilderContainerTags = d->clientBuilder->containerTags();
00258         d->clientBuilderCustomTags = d->clientBuilder->customTags();
00259     }
00260     else
00261     {
00262         d->clientBuilderContainerTags.clear();
00263         d->clientBuilderCustomTags.clear();
00264     }
00265 
00266     // load shortcut schemes, user-defined shortcuts and other action properties
00267     d->saveDefaultActionProperties(client);
00268     d->refreshActionProperties(client, doc);
00269 
00270     BuildHelper( *d, d->m_rootNode ).build( docElement );
00271 
00272     // let the client know that we built its GUI.
00273     client->setFactory( this );
00274 
00275     // call the finalizeGUI method, to fix up the positions of toolbars for example.
00276     // ### FIXME : obey client builder
00277     // --- Well, toolbars have a bool "positioned", so it doesn't really matter,
00278     // if we call positionYourself on all of them each time. (David)
00279     d->builder->finalizeGUI( d->guiClient );
00280 
00281     // reset some variables, for safety
00282     d->BuildState::reset();
00283 
00284     client->endXMLPlug();
00285 
00286     d->popState();
00287 
00288     emit clientAdded( client );
00289 
00290     // build child clients
00291     foreach (KXMLGUIClient *child, client->childClients())
00292         addClient( child );
00293 
00294     if (d->emptyState())
00295         emit makingChanges(false);
00296 /*
00297     QString unaddedActions;
00298     foreach (KActionCollection* ac, KActionCollection::allCollections())
00299       foreach (QAction* action, ac->actions())
00300         if (action->associatedWidgets().isEmpty())
00301           unaddedActions += action->objectName() + ' ';
00302 
00303     if (!unaddedActions.isEmpty())
00304       kWarning() << "The following actions are not plugged into the gui (shortcuts will not work): " << unaddedActions;
00305 */
00306 
00307 //    kDebug() << "addClient took " << dt.elapsed();
00308 }
00309 
00310 void KXMLGUIFactory::refreshActionProperties()
00311 {
00312     foreach (KXMLGUIClient *client, d->m_clients)
00313     {
00314         d->guiClient = client;
00315         QDomDocument doc = client->xmlguiBuildDocument();
00316         if ( doc.documentElement().isNull() )
00317         {
00318             client->reloadXML();
00319             doc = client->domDocument();
00320         }
00321         d->refreshActionProperties(client, doc);
00322     }
00323     d->guiClient = 0;
00324 }
00325 
00326 void KXMLGUIFactoryPrivate::refreshActionProperties(KXMLGUIClient *client, QDomDocument doc)
00327 {
00328     // try to find and apply shortcuts schemes
00329     QDomDocument scheme = shortcutSchemeDoc(client);
00330     applyShortcutScheme(client, scheme);
00331 
00332     // try to find and apply user-defined shortcuts
00333     QDomElement actionPropElement = KXMLGUIFactory::actionPropertiesElement(doc);
00334     if (actionPropElement.childNodes().isEmpty())
00335         doc.documentElement().removeChild(actionPropElement);
00336 
00337     if ( !actionPropElement.isNull() )
00338         applyActionProperties( actionPropElement );
00339 }
00340 
00341 void KXMLGUIFactoryPrivate::saveDefaultActionProperties(KXMLGUIClient *client)
00342 {
00343     // This method is called every time the user activated a new
00344     // kxmlguiclient. We only want to execute the following code only once in
00345     // the lifetime of an action.
00346     foreach (QAction *action, client->actionCollection()->actions())
00347     {
00348         // Skip NULL actions or those we have seen already.
00349         if (!action || action->property("_k_DefaultShortcut").isValid()) continue;
00350 
00351         if (KAction* kaction = qobject_cast<KAction*>(action))
00352         {
00353             // Check if the default shortcut is set
00354             KShortcut defaultShortcut = kaction->shortcut(KAction::DefaultShortcut);
00355             KShortcut activeShortcut  = kaction->shortcut(KAction::ActiveShortcut);
00356 
00357             // Check if we have an empty default shortcut and an non empty
00358             // custom shortcut. This should only happen if a developer called
00359             // QAction::setShortcut on an KAction. Print out a warning and
00360             // correct the mistake
00361             if ((!activeShortcut.isEmpty()) && defaultShortcut.isEmpty())
00362             {
00363                 kError(240) << "Shortcut for KAction " << kaction->objectName() << kaction->text() << "set with QShortcut::setShortcut()! See KAction documentation.";
00364                 kaction->setProperty("_k_DefaultShortcut", activeShortcut);
00365             }
00366             else
00367             {
00368                 kaction->setProperty("_k_DefaultShortcut", defaultShortcut);
00369             }
00370         }
00371         else
00372         {
00373             // A QAction used with KXMLGUI? Set our property and ignore it.
00374             kError(240) << "Attempt to use QAction" << action->objectName() << "with KXMLGUIFactory!";
00375             action->setProperty("_k_DefaultShortcut", KShortcut());
00376         }
00377 
00378     }
00379 }
00380 
00381 void KXMLGUIFactory::changeShortcutScheme(const QString &scheme)
00382 {
00383     kDebug(260) << "Changing shortcut scheme to" << scheme;
00384     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00385     cg.writeEntry("Current Scheme", scheme);
00386 
00387     refreshActionProperties();
00388 }
00389 
00390 void KXMLGUIFactory::forgetClient( KXMLGUIClient *client )
00391 {
00392     d->m_clients.removeAll( client );
00393 }
00394 
00395 void KXMLGUIFactory::removeClient( KXMLGUIClient *client )
00396 {
00397     //kDebug(260) << client;
00398 
00399     // don't try to remove the client's GUI if we didn't build it
00400     if ( !client || client->factory() != this )
00401         return;
00402 
00403     if (d->emptyState())
00404         emit makingChanges(true);
00405 
00406     // remove this client from our client list
00407     d->m_clients.removeAll( client );
00408 
00409     // remove child clients first (create a copy of the list just in case the
00410     // original list is modified directly or indirectly in removeClient())
00411     const QList<KXMLGUIClient*> childClients(client->childClients());
00412     foreach (KXMLGUIClient *child, childClients)
00413         removeClient(child);
00414 
00415     //kDebug(260) << "calling removeRecursive";
00416 
00417     d->pushState();
00418 
00419     // cache some variables
00420 
00421     d->guiClient = client;
00422     d->clientName = client->domDocument().documentElement().attribute( d->attrName );
00423     d->clientBuilder = client->clientBuilder();
00424 
00425     client->setFactory( 0L );
00426 
00427     // if we don't have a build document for that client, yet, then create one by
00428     // cloning the original document, so that saving container information in the
00429     // DOM tree does not touch the original document.
00430     QDomDocument doc = client->xmlguiBuildDocument();
00431     if ( doc.documentElement().isNull() )
00432     {
00433         doc = client->domDocument().cloneNode( true ).toDocument();
00434         client->setXMLGUIBuildDocument( doc );
00435     }
00436 
00437     d->m_rootNode->destruct( doc.documentElement(), *d );
00438 
00439     // reset some variables
00440     d->BuildState::reset();
00441 
00442     // This will destruct the KAccel object built around the given widget.
00443     client->prepareXMLUnplug( d->builder->widget() );
00444 
00445     d->popState();
00446 
00447     if (d->emptyState())
00448         emit makingChanges(false);
00449 
00450     emit clientRemoved( client );
00451 }
00452 
00453 QList<KXMLGUIClient*> KXMLGUIFactory::clients() const
00454 {
00455     return d->m_clients;
00456 }
00457 
00458 QWidget *KXMLGUIFactory::container( const QString &containerName, KXMLGUIClient *client,
00459                                     bool useTagName )
00460 {
00461     d->pushState();
00462     d->m_containerName = containerName;
00463     d->guiClient = client;
00464 
00465     QWidget *result = d->findRecursive( d->m_rootNode, useTagName );
00466 
00467     d->guiClient = 0L;
00468     d->m_containerName.clear();
00469 
00470     d->popState();
00471 
00472     return result;
00473 }
00474 
00475 QList<QWidget*> KXMLGUIFactory::containers( const QString &tagName )
00476 {
00477     return d->findRecursive( d->m_rootNode, tagName );
00478 }
00479 
00480 void KXMLGUIFactory::reset()
00481 {
00482     d->m_rootNode->reset();
00483 
00484     d->m_rootNode->clearChildren();
00485 }
00486 
00487 void KXMLGUIFactory::resetContainer( const QString &containerName, bool useTagName )
00488 {
00489     if ( containerName.isEmpty() )
00490         return;
00491 
00492     ContainerNode *container = d->m_rootNode->findContainer( containerName, useTagName );
00493 
00494     if ( !container )
00495         return;
00496 
00497     ContainerNode *parent = container->parent;
00498     if ( !parent )
00499         return;
00500 
00501     //  resetInternal( container );
00502 
00503     parent->removeChild( container );
00504 }
00505 
00506 QWidget *KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node, bool tag )
00507 {
00508     if ( ( ( !tag && node->name == m_containerName ) ||
00509            ( tag && node->tagName == m_containerName ) ) &&
00510          ( !guiClient || node->client == guiClient ) )
00511         return node->container;
00512 
00513     foreach (ContainerNode* child, node->children)
00514     {
00515         QWidget *cont = findRecursive( child, tag );
00516         if ( cont )
00517             return cont;
00518     }
00519 
00520     return 0L;
00521 }
00522 
00523 // Case insensitive equality without calling toLower which allocates a new string
00524 static inline bool equals(const QString& str1, const char* str2)
00525 {
00526     return str1.compare(QLatin1String(str2), Qt::CaseInsensitive) == 0;
00527 }
00528 static inline bool equals(const QString& str1, const QString& str2)
00529 {
00530     return str1.compare(str2, Qt::CaseInsensitive) == 0;
00531 }
00532 
00533 
00534 QList<QWidget*> KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node,
00535                                                       const QString &tagName )
00536 {
00537     QList<QWidget*> res;
00538 
00539     if ( equals(node->tagName, tagName) )
00540         res.append( node->container );
00541 
00542     foreach (KXMLGUI::ContainerNode* child, node->children)
00543         res << findRecursive( child, tagName );
00544 
00545     return res;
00546 }
00547 
00548 void KXMLGUIFactory::plugActionList( KXMLGUIClient *client, const QString &name,
00549                                      const QList<QAction*> &actionList )
00550 {
00551     d->pushState();
00552     d->guiClient = client;
00553     d->actionListName = name;
00554     d->actionList = actionList;
00555     d->clientName = client->domDocument().documentElement().attribute( d->attrName );
00556 
00557     d->m_rootNode->plugActionList( *d );
00558 
00559     d->BuildState::reset();
00560     d->popState();
00561 }
00562 
00563 void KXMLGUIFactory::unplugActionList( KXMLGUIClient *client, const QString &name )
00564 {
00565     d->pushState();
00566     d->guiClient = client;
00567     d->actionListName = name;
00568     d->clientName = client->domDocument().documentElement().attribute( d->attrName );
00569 
00570     d->m_rootNode->unplugActionList( *d );
00571 
00572     d->BuildState::reset();
00573     d->popState();
00574 }
00575 
00576 void KXMLGUIFactoryPrivate::applyActionProperties( const QDomElement &actionPropElement,
00577         ShortcutOption shortcutOption )
00578 {
00579     for (QDomNode n = actionPropElement.firstChild();
00580          !n.isNull(); n = n.nextSibling() )
00581     {
00582         QDomElement e = n.toElement();
00583         if ( !equals(e.tagName(), "action") )
00584             continue;
00585 
00586         QAction *action = guiClient->action( e );
00587         if ( !action )
00588             continue;
00589 
00590         configureAction( action, e.attributes(), shortcutOption );
00591     }
00592 }
00593 
00594 void KXMLGUIFactoryPrivate::configureAction( QAction *action, const QDomNamedNodeMap &attributes,
00595         ShortcutOption shortcutOption )
00596 {
00597     for ( uint i = 0; i < attributes.length(); i++ )
00598     {
00599         QDomAttr attr = attributes.item( i ).toAttr();
00600         if ( attr.isNull() )
00601             continue;
00602 
00603         configureAction( action, attr, shortcutOption );
00604     }
00605 }
00606 
00607 void KXMLGUIFactoryPrivate::configureAction( QAction *action, const QDomAttr &attribute,
00608         ShortcutOption shortcutOption )
00609 {
00610     static const QString &attrShortcut = KGlobal::staticQString( "shortcut" );
00611 
00612     QString attrName = attribute.name();
00613     // If the attribute is a deprecated "accel", change to "shortcut".
00614     if ( equals(attrName, "accel") )
00615         attrName = attrShortcut;
00616 
00617     // No need to re-set name, particularly since it's "objectName" in Qt4
00618     if ( equals(attrName, "name") )
00619         return;
00620 
00621     if ( equals(attrName, "icon") ) {
00622         action->setIcon( KIcon( attribute.value() ) );
00623         return;
00624     }
00625 
00626     QVariant propertyValue;
00627 
00628     QVariant::Type propertyType = action->property( attrName.toLatin1() ).type();
00629 
00630     if ( propertyType == QVariant::Int ) {
00631         propertyValue = QVariant( attribute.value().toInt() );
00632     } else if ( propertyType == QVariant::UInt ) {
00633         propertyValue = QVariant( attribute.value().toUInt() );
00634     } else if ( propertyType == QVariant::UserType && action->property( attrName.toLatin1() ).userType() == qMetaTypeId<KShortcut>() ) {
00635         // Setting the shortcut by property also sets the default shortcut (which is incorrect), so we have to do it directly
00636         if (KAction* ka = qobject_cast<KAction*>(action)) {
00637             if (attrName=="globalShortcut") {
00638                 ka->setGlobalShortcut(KShortcut(attribute.value()), KAction::ActiveShortcut);
00639             } else {
00640                 ka->setShortcut(KShortcut(attribute.value()), KAction::ActiveShortcut);
00641             }
00642             if (shortcutOption & KXMLGUIFactoryPrivate::SetDefaultShortcut)
00643                 ka->setShortcut(KShortcut(attribute.value()), KAction::DefaultShortcut);
00644             return;
00645         }
00646         propertyValue = KShortcut( attribute.value() );
00647     } else {
00648         propertyValue = QVariant( attribute.value() );
00649     }
00650     if (!action->setProperty( attrName.toLatin1(), propertyValue )) {
00651         kWarning() << "Error: Unknown action property " << attrName << " will be ignored!";
00652     }
00653 }
00654 
00655 QDomDocument KXMLGUIFactoryPrivate::shortcutSchemeDoc(KXMLGUIClient *client)
00656 {
00657     // Get the name of the current shorcut scheme
00658     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00659     QString schemeName = cg.readEntry("Current Scheme", "Default");
00660 
00661     QDomDocument doc;
00662     if (schemeName != "Default")
00663     {
00664         // Find the document for the shortcut scheme using both current application path
00665         // and current xmlguiclient path but making a preference to app path
00666         QString schemeFileName = KStandardDirs::locateLocal("data",
00667             client->componentData().componentName() + '/' +
00668             client->componentData().componentName() + schemeName.toLower() + "shortcuts.rc" );
00669 
00670         QFile schemeFile(schemeFileName);
00671         if (schemeFile.open(QIODevice::ReadOnly))
00672         {
00673 //             kDebug(260) << "Found shortcut scheme" << schemeFileName;
00674             doc.setContent(&schemeFile);
00675             schemeFile.close();
00676         }
00677     }
00678     return doc;
00679 }
00680 
00681 void KXMLGUIFactoryPrivate::applyShortcutScheme(KXMLGUIClient *client, QDomDocument scheme)
00682 {
00683     static const QString &actionPropElementName = KGlobal::staticQString( "ActionProperties" );
00684 
00685     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00686     QString schemeName = cg.readEntry("Current Scheme", "Default");
00687 
00688     //First clear all existing shortcuts
00689     if (schemeName != "Default") {
00690         foreach (QAction *action, client->actionCollection()->actions())
00691         {
00692             if (KAction *kaction = qobject_cast<KAction*>(action))
00693             {
00694                 kaction->setShortcut(KShortcut(), KAction::ActiveShortcut);
00695                 // We clear the default shortcut as well because the shortcut scheme will set its own defaults
00696                 kaction->setShortcut(KShortcut(), KAction::DefaultShortcut);
00697             }
00698             else
00699                 action->setProperty("shortcut", KShortcut());
00700         }
00701     } else {
00702         // apply saved default shortcuts
00703         foreach (QAction *action, client->actionCollection()->actions())
00704         {
00705             if (KAction *kaction = qobject_cast<KAction*>(action))
00706             {
00707                 QVariant savedDefaultShortcut = kaction->property("_k_DefaultShortcut");
00708                 if (savedDefaultShortcut.isValid())
00709                 {
00710                     KShortcut shortcut = savedDefaultShortcut.value<KShortcut>();
00711                     kaction->setShortcut(shortcut, KAction::ActiveShortcut);
00712                     kaction->setShortcut(shortcut, KAction::DefaultShortcut);
00713                     continue;
00714                 }
00715             }
00716             action->setProperty("shortcut", KShortcut());
00717         }
00718     }
00719 
00720     if (scheme.isNull())
00721         return;
00722 
00723     QDomElement docElement = scheme.documentElement();
00724     QDomElement actionPropElement = docElement.namedItem( actionPropElementName ).toElement();
00725 
00726     //Check if we really have the shortcut configuration here
00727     if (!actionPropElement.isNull())
00728     {
00729         kDebug(260) << "Applying shortcut scheme for XMLGUI client" << client->componentData().componentName();
00730 
00731         //Apply all shortcuts we have
00732         applyActionProperties(actionPropElement, KXMLGUIFactoryPrivate::SetDefaultShortcut);
00733     }
00734     else
00735         kDebug(260) << "Invalid shortcut scheme file";
00736 }
00737 
00738 int KXMLGUIFactory::configureShortcuts(bool letterCutsOk , bool bSaveSettings )
00739 {
00740     KShortcutsDialog dlg(KShortcutsEditor::AllActions,
00741          letterCutsOk ? KShortcutsEditor::LetterShortcutsAllowed : KShortcutsEditor::LetterShortcutsDisallowed,
00742          qobject_cast<QWidget*>(parent()));
00743     foreach (KXMLGUIClient *client, d->m_clients)
00744     {
00745         if(client && !client->xmlFile().isEmpty())
00746             dlg.addCollection( client->actionCollection() );
00747     }
00748     return dlg.configure(bSaveSettings);
00749 }
00750 
00751 QDomElement KXMLGUIFactory::actionPropertiesElement( QDomDocument& doc )
00752 {
00753     KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
00754     QString schemeName = cg.readEntry("Current Scheme", "Default");
00755 
00756     const QString tagActionProp = QLatin1String("ActionProperties");
00757     // first, lets see if we have existing properties
00758     QDomElement elem;
00759     QDomNode it = doc.documentElement().firstChild();
00760     for( ; !it.isNull(); it = it.nextSibling() ) {
00761         QDomElement e = it.toElement();
00762         if( ((e.tagName() == tagActionProp) || (e.tagName() == tagActionProp.toLower()))
00763                 && (e.attribute("scheme", "Default") == schemeName) ) {
00764             elem = e;
00765             break;
00766         }
00767     }
00768 
00769     // if there was none, create one
00770     if( elem.isNull() ) {
00771         elem = doc.createElement( tagActionProp );
00772         elem.setAttribute( "scheme", schemeName );
00773         doc.documentElement().appendChild( elem );
00774     }
00775     return elem;
00776 }
00777 
00778 QDomElement KXMLGUIFactory::findActionByName( QDomElement& elem, const QString& sName, bool create )
00779 {
00780         static const QString& attrName = KGlobal::staticQString( "name" );
00781     static const QString& tagAction = KGlobal::staticQString( "Action" );
00782     for( QDomNode it = elem.firstChild(); !it.isNull(); it = it.nextSibling() ) {
00783         QDomElement e = it.toElement();
00784         if( e.attribute( attrName ) == sName )
00785             return e;
00786     }
00787 
00788     if( create ) {
00789         QDomElement act_elem = elem.ownerDocument().createElement( tagAction );
00790         act_elem.setAttribute( attrName, sName );
00791                 elem.appendChild( act_elem );
00792                 return act_elem;
00793     }
00794         return QDomElement();
00795 }
00796 
00797 #include "kxmlguifactory.moc"
00798 
00799 /* vim: et sw=4
00800  */

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
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
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