• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • xmlgui
kxmlguifactory.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 1999,2000 Simon Hausmann <hausmann@kde.org>
3  Copyright (C) 2000 Kurt Granroth <granroth@kde.org>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Library General Public License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to
17  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kxmlguifactory.h"
22 #include "kxmlguifactory_p.h"
23 #include "kxmlguiclient.h"
24 #include "kxmlguibuilder.h"
25 
26 #include <assert.h>
27 
28 #include <QtCore/QDir>
29 #include <QtXml/QDomDocument>
30 #include <QtCore/QFile>
31 #include <QtCore/QTextIStream>
32 #include <QtGui/QWidget>
33 #include <QtCore/QDate>
34 #include <QtCore/QVariant>
35 #include <QTextCodec>
36 
37 #include <kdebug.h>
38 #include <kcomponentdata.h>
39 #include <kglobal.h>
40 #include <kshortcut.h>
41 #include <kstandarddirs.h>
42 
43 #include "kaction.h"
44 #include "kshortcutsdialog.h"
45 #include "kactioncollection.h"
46 
47 using namespace KXMLGUI;
48 
49 class KXMLGUIFactoryPrivate : public BuildState
50 {
51 public:
52  enum ShortcutOption { SetActiveShortcut = 1, SetDefaultShortcut = 2};
53 
54  KXMLGUIFactoryPrivate()
55  {
56  static const QString &defaultMergingName = KGlobal::staticQString( "<default>" );
57  static const QString &actionList = KGlobal::staticQString( "actionlist" );
58  static const QString &name = KGlobal::staticQString( "name" );
59 
60  m_rootNode = new ContainerNode( 0L, QString(), 0L );
61  m_defaultMergingName = defaultMergingName;
62  tagActionList = actionList;
63  attrName = name;
64  }
65  ~KXMLGUIFactoryPrivate()
66  {
67  delete m_rootNode;
68  }
69 
70  void pushState()
71  {
72  m_stateStack.push( *this );
73  }
74 
75  void popState()
76  {
77  BuildState::operator=( m_stateStack.pop() );
78  }
79 
80  bool emptyState() const { return m_stateStack.isEmpty(); }
81 
82  QWidget *findRecursive( KXMLGUI::ContainerNode *node, bool tag );
83  QList<QWidget*> findRecursive( KXMLGUI::ContainerNode *node, const QString &tagName );
84  void applyActionProperties( const QDomElement &element,
85  ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut );
86  void configureAction( QAction *action, const QDomNamedNodeMap &attributes,
87  ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut );
88  void configureAction( QAction *action, const QDomAttr &attribute,
89  ShortcutOption shortcutOption = KXMLGUIFactoryPrivate::SetActiveShortcut );
90 
91  QDomDocument shortcutSchemeDoc(KXMLGUIClient *client);
92  void applyShortcutScheme(KXMLGUIClient *client, const QList<QAction*>& actions, const QDomDocument& scheme);
93  void refreshActionProperties(KXMLGUIClient *client, const QList<QAction*>& actions, const QDomDocument& doc);
94  void saveDefaultActionProperties(const QList<QAction*>& actions);
95 
96  ContainerNode *m_rootNode;
97 
98  QString m_defaultMergingName;
99 
100  /*
101  * Contains the container which is searched for in ::container .
102  */
103  QString m_containerName;
104 
105  /*
106  * List of all clients
107  */
108  QList<KXMLGUIClient*> m_clients;
109 
110  QString tagActionList;
111 
112  QString attrName;
113 
114  BuildStateStack m_stateStack;
115 };
116 
117 QString KXMLGUIFactory::readConfigFile( const QString &filename, const KComponentData &_componentData )
118 {
119  QString xml_file;
120 
121  if (!QDir::isRelativePath(filename))
122  xml_file = filename;
123  else
124  {
125  KComponentData componentData = _componentData.isValid() ? _componentData : KGlobal::mainComponent();
126  xml_file = KStandardDirs::locate("data", componentData.componentName() + '/' + filename);
127  if ( !QFile::exists( xml_file ) )
128  xml_file = KStandardDirs::locate( "data", filename );
129  }
130 
131  QFile file( xml_file );
132  if ( xml_file.isEmpty() || !file.open( QIODevice::ReadOnly ) )
133  {
134  kError(240) << "No such XML file" << filename;
135  return QString();
136  }
137 
138  QByteArray buffer(file.readAll());
139  return QString::fromUtf8(buffer.constData(), buffer.size());
140 }
141 
142 bool KXMLGUIFactory::saveConfigFile( const QDomDocument& doc,
143  const QString& filename, const KComponentData &_componentData )
144 {
145  KComponentData componentData = _componentData.isValid() ? _componentData : KGlobal::mainComponent();
146  QString xml_file(filename);
147 
148  if (QDir::isRelativePath(xml_file))
149  xml_file = KStandardDirs::locateLocal("data", componentData.componentName() + '/' + filename);
150 
151  QFile file( xml_file );
152  if ( xml_file.isEmpty() || !file.open( QIODevice::WriteOnly ) )
153  {
154  kError(240) << "Could not write to" << filename;
155  return false;
156  }
157 
158  // write out our document
159  QTextStream ts(&file);
160  ts.setCodec( QTextCodec::codecForName( "UTF-8" ) );
161  ts << doc;
162 
163  file.close();
164  return true;
165 }
166 
170 static void removeDOMComments( QDomNode &node )
171 {
172  QDomNode n = node.firstChild();
173  while ( !n.isNull() )
174  {
175  if ( n.nodeType() == QDomNode::CommentNode )
176  {
177  QDomNode tmp = n;
178  n = n.nextSibling();
179  node.removeChild( tmp );
180  }
181  else
182  {
183  QDomNode tmp = n;
184  n = n.nextSibling();
185  removeDOMComments( tmp );
186  }
187  }
188 }
189 
190 KXMLGUIFactory::KXMLGUIFactory( KXMLGUIBuilder *builder, QObject *parent )
191  : QObject( parent ),d(new KXMLGUIFactoryPrivate)
192 {
193  d->builder = builder;
194  d->guiClient = 0;
195  if ( d->builder )
196  {
197  d->builderContainerTags = d->builder->containerTags();
198  d->builderCustomTags = d->builder->customTags();
199  }
200 }
201 
202 KXMLGUIFactory::~KXMLGUIFactory()
203 {
204  foreach (KXMLGUIClient *client, d->m_clients) {
205  client->setFactory ( 0L );
206  }
207  delete d;
208 }
209 
210 void KXMLGUIFactory::addClient( KXMLGUIClient *client )
211 {
212  //kDebug(260) << client;
213  if ( client->factory() ) {
214  if ( client->factory() == this )
215  return;
216  else
217  client->factory()->removeClient( client ); //just in case someone does stupid things ;-)
218  }
219 
220  if (d->emptyState())
221  emit makingChanges(true);
222  d->pushState();
223 
224 // QTime dt; dt.start();
225 
226  d->guiClient = client;
227 
228  // add this client to our client list
229  if ( !d->m_clients.contains( client ) )
230  d->m_clients.append( client );
231  else
232  kDebug(260) << "XMLGUI client already added " << client;
233 
234  // Tell the client that plugging in is process and
235  // let it know what builder widget its mainwindow shortcuts
236  // should be attached to.
237  client->beginXMLPlug( d->builder->widget() );
238 
239  // try to use the build document for building the client's GUI, as the build document
240  // contains the correct container state information (like toolbar positions, sizes, etc.) .
241  // if there is non available, then use the "real" document.
242  QDomDocument doc = client->xmlguiBuildDocument();
243  if ( doc.documentElement().isNull() )
244  doc = client->domDocument();
245 
246  QDomElement docElement = doc.documentElement();
247 
248  d->m_rootNode->index = -1;
249 
250  // cache some variables
251 
252  d->clientName = docElement.attribute( d->attrName );
253  d->clientBuilder = client->clientBuilder();
254 
255  if ( d->clientBuilder )
256  {
257  d->clientBuilderContainerTags = d->clientBuilder->containerTags();
258  d->clientBuilderCustomTags = d->clientBuilder->customTags();
259  }
260  else
261  {
262  d->clientBuilderContainerTags.clear();
263  d->clientBuilderCustomTags.clear();
264  }
265 
266  // load shortcut schemes, user-defined shortcuts and other action properties
267  d->saveDefaultActionProperties(client->actionCollection()->actions());
268  if (!doc.isNull())
269  d->refreshActionProperties(client, client->actionCollection()->actions(), doc);
270 
271  BuildHelper( *d, d->m_rootNode ).build( docElement );
272 
273  // let the client know that we built its GUI.
274  client->setFactory( this );
275 
276  // call the finalizeGUI method, to fix up the positions of toolbars for example.
277  // ### FIXME : obey client builder
278  // --- Well, toolbars have a bool "positioned", so it doesn't really matter,
279  // if we call positionYourself on all of them each time. (David)
280  d->builder->finalizeGUI( d->guiClient );
281 
282  // reset some variables, for safety
283  d->BuildState::reset();
284 
285  client->endXMLPlug();
286 
287  d->popState();
288 
289  emit clientAdded( client );
290 
291  // build child clients
292  foreach (KXMLGUIClient *child, client->childClients())
293  addClient( child );
294 
295  if (d->emptyState())
296  emit makingChanges(false);
297 /*
298  QString unaddedActions;
299  foreach (KActionCollection* ac, KActionCollection::allCollections())
300  foreach (QAction* action, ac->actions())
301  if (action->associatedWidgets().isEmpty())
302  unaddedActions += action->objectName() + ' ';
303 
304  if (!unaddedActions.isEmpty())
305  kWarning() << "The following actions are not plugged into the gui (shortcuts will not work): " << unaddedActions;
306 */
307 
308 // kDebug() << "addClient took " << dt.elapsed();
309 }
310 
311 void KXMLGUIFactory::refreshActionProperties()
312 {
313  foreach (KXMLGUIClient *client, d->m_clients)
314  {
315  d->guiClient = client;
316  QDomDocument doc = client->xmlguiBuildDocument();
317  if ( doc.documentElement().isNull() )
318  {
319  client->reloadXML();
320  doc = client->domDocument();
321  }
322  d->refreshActionProperties(client, client->actionCollection()->actions(), doc);
323  }
324  d->guiClient = 0;
325 }
326 
327 static QString currentShortcutScheme()
328 {
329  const KConfigGroup cg = KGlobal::config()->group("Shortcut Schemes");
330  return cg.readEntry("Current Scheme", "Default");
331 }
332 
333 // Find the right ActionProperties element, otherwise return null element
334 static QDomElement findActionPropertiesElement(const QDomDocument& doc)
335 {
336  const QLatin1String tagActionProp("ActionProperties");
337  const QString schemeName = currentShortcutScheme();
338  QDomElement e = doc.documentElement().firstChildElement();
339  for( ; !e.isNull(); e = e.nextSiblingElement() ) {
340  if (QString::compare(e.tagName(), tagActionProp, Qt::CaseInsensitive) == 0
341  && (e.attribute("scheme", "Default") == schemeName) ) {
342  return e;
343  }
344  }
345  return QDomElement();
346 }
347 
348 void KXMLGUIFactoryPrivate::refreshActionProperties(KXMLGUIClient *client, const QList<QAction*>& actions, const QDomDocument& doc)
349 {
350  // try to find and apply shortcuts schemes
351  QDomDocument scheme = shortcutSchemeDoc(client);
352  applyShortcutScheme(client, actions, scheme);
353 
354  // try to find and apply user-defined shortcuts
355  const QDomElement actionPropElement = findActionPropertiesElement(doc);
356  if ( !actionPropElement.isNull() )
357  applyActionProperties( actionPropElement );
358 }
359 
360 void KXMLGUIFactoryPrivate::saveDefaultActionProperties(const QList<QAction *>& actions)
361 {
362  // This method is called every time the user activated a new
363  // kxmlguiclient. We only want to execute the following code only once in
364  // the lifetime of an action.
365  foreach (QAction *action, actions) {
366  // Skip NULL actions or those we have seen already.
367  if (!action || action->property("_k_DefaultShortcut").isValid()) continue;
368 
369  if (KAction* kaction = qobject_cast<KAction*>(action)) {
370  // Check if the default shortcut is set
371  KShortcut defaultShortcut = kaction->shortcut(KAction::DefaultShortcut);
372  KShortcut activeShortcut = kaction->shortcut(KAction::ActiveShortcut);
373  //kDebug() << kaction->objectName() << "default=" << defaultShortcut.toString() << "active=" << activeShortcut.toString();
374 
375  // Check if we have an empty default shortcut and an non empty
376  // custom shortcut. This should only happen if a developer called
377  // QAction::setShortcut on an KAction. Print out a warning and
378  // correct the mistake
379  if ((!activeShortcut.isEmpty()) && defaultShortcut.isEmpty()) {
380  kError(240) << "Shortcut for KAction " << kaction->objectName() << kaction->text() << "set with QShortcut::setShortcut()! See KAction documentation.";
381  kaction->setProperty("_k_DefaultShortcut", activeShortcut);
382  } else {
383  kaction->setProperty("_k_DefaultShortcut", defaultShortcut);
384  }
385  }
386  else
387  {
388  // A QAction used with KXMLGUI? Set our property and ignore it.
389  kError(240) << "Attempt to use QAction" << action->objectName() << "with KXMLGUIFactory!";
390  action->setProperty("_k_DefaultShortcut", KShortcut());
391  }
392 
393  }
394 }
395 
396 void KXMLGUIFactory::changeShortcutScheme(const QString &scheme)
397 {
398  kDebug(260) << "Changing shortcut scheme to" << scheme;
399  KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
400  cg.writeEntry("Current Scheme", scheme);
401 
402  refreshActionProperties();
403 }
404 
405 void KXMLGUIFactory::forgetClient( KXMLGUIClient *client )
406 {
407  d->m_clients.removeAll( client );
408 }
409 
410 void KXMLGUIFactory::removeClient( KXMLGUIClient *client )
411 {
412  //kDebug(260) << client;
413 
414  // don't try to remove the client's GUI if we didn't build it
415  if ( !client || client->factory() != this )
416  return;
417 
418  if (d->emptyState())
419  emit makingChanges(true);
420 
421  // remove this client from our client list
422  d->m_clients.removeAll( client );
423 
424  // remove child clients first (create a copy of the list just in case the
425  // original list is modified directly or indirectly in removeClient())
426  const QList<KXMLGUIClient*> childClients(client->childClients());
427  foreach (KXMLGUIClient *child, childClients)
428  removeClient(child);
429 
430  //kDebug(260) << "calling removeRecursive";
431 
432  d->pushState();
433 
434  // cache some variables
435 
436  d->guiClient = client;
437  d->clientName = client->domDocument().documentElement().attribute( d->attrName );
438  d->clientBuilder = client->clientBuilder();
439 
440  client->setFactory( 0L );
441 
442  // if we don't have a build document for that client, yet, then create one by
443  // cloning the original document, so that saving container information in the
444  // DOM tree does not touch the original document.
445  QDomDocument doc = client->xmlguiBuildDocument();
446  if ( doc.documentElement().isNull() )
447  {
448  doc = client->domDocument().cloneNode( true ).toDocument();
449  client->setXMLGUIBuildDocument( doc );
450  }
451 
452  d->m_rootNode->destruct( doc.documentElement(), *d );
453 
454  // reset some variables
455  d->BuildState::reset();
456 
457  // This will destruct the KAccel object built around the given widget.
458  client->prepareXMLUnplug( d->builder->widget() );
459 
460  d->popState();
461 
462  if (d->emptyState())
463  emit makingChanges(false);
464 
465  emit clientRemoved( client );
466 }
467 
468 QList<KXMLGUIClient*> KXMLGUIFactory::clients() const
469 {
470  return d->m_clients;
471 }
472 
473 QWidget *KXMLGUIFactory::container( const QString &containerName, KXMLGUIClient *client,
474  bool useTagName )
475 {
476  d->pushState();
477  d->m_containerName = containerName;
478  d->guiClient = client;
479 
480  QWidget *result = d->findRecursive( d->m_rootNode, useTagName );
481 
482  d->guiClient = 0L;
483  d->m_containerName.clear();
484 
485  d->popState();
486 
487  return result;
488 }
489 
490 QList<QWidget*> KXMLGUIFactory::containers( const QString &tagName )
491 {
492  return d->findRecursive( d->m_rootNode, tagName );
493 }
494 
495 void KXMLGUIFactory::reset()
496 {
497  d->m_rootNode->reset();
498 
499  d->m_rootNode->clearChildren();
500 }
501 
502 void KXMLGUIFactory::resetContainer( const QString &containerName, bool useTagName )
503 {
504  if ( containerName.isEmpty() )
505  return;
506 
507  ContainerNode *container = d->m_rootNode->findContainer( containerName, useTagName );
508 
509  if ( !container )
510  return;
511 
512  ContainerNode *parent = container->parent;
513  if ( !parent )
514  return;
515 
516  // resetInternal( container );
517 
518  parent->removeChild( container );
519 }
520 
521 QWidget *KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node, bool tag )
522 {
523  if ( ( ( !tag && node->name == m_containerName ) ||
524  ( tag && node->tagName == m_containerName ) ) &&
525  ( !guiClient || node->client == guiClient ) )
526  return node->container;
527 
528  foreach (ContainerNode* child, node->children)
529  {
530  QWidget *cont = findRecursive( child, tag );
531  if ( cont )
532  return cont;
533  }
534 
535  return 0L;
536 }
537 
538 // Case insensitive equality without calling toLower which allocates a new string
539 static inline bool equals(const QString& str1, const char* str2)
540 {
541  return str1.compare(QLatin1String(str2), Qt::CaseInsensitive) == 0;
542 }
543 static inline bool equals(const QString& str1, const QString& str2)
544 {
545  return str1.compare(str2, Qt::CaseInsensitive) == 0;
546 }
547 
548 
549 QList<QWidget*> KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node,
550  const QString &tagName )
551 {
552  QList<QWidget*> res;
553 
554  if ( equals(node->tagName, tagName) )
555  res.append( node->container );
556 
557  foreach (KXMLGUI::ContainerNode* child, node->children)
558  res << findRecursive( child, tagName );
559 
560  return res;
561 }
562 
563 void KXMLGUIFactory::plugActionList( KXMLGUIClient *client, const QString &name,
564  const QList<QAction*> &actionList )
565 {
566  d->pushState();
567  d->guiClient = client;
568  d->actionListName = name;
569  d->actionList = actionList;
570  d->clientName = client->domDocument().documentElement().attribute( d->attrName );
571 
572  d->m_rootNode->plugActionList( *d );
573 
574  // Load shortcuts for these new actions
575  d->saveDefaultActionProperties(actionList);
576  d->refreshActionProperties(client, actionList, client->domDocument());
577 
578  d->BuildState::reset();
579  d->popState();
580 }
581 
582 void KXMLGUIFactory::unplugActionList( KXMLGUIClient *client, const QString &name )
583 {
584  d->pushState();
585  d->guiClient = client;
586  d->actionListName = name;
587  d->clientName = client->domDocument().documentElement().attribute( d->attrName );
588 
589  d->m_rootNode->unplugActionList( *d );
590 
591  d->BuildState::reset();
592  d->popState();
593 }
594 
595 void KXMLGUIFactoryPrivate::applyActionProperties( const QDomElement &actionPropElement,
596  ShortcutOption shortcutOption )
597 {
598  for (QDomElement e = actionPropElement.firstChildElement();
599  !e.isNull(); e = e.nextSiblingElement()) {
600  if ( !equals(e.tagName(), "action") )
601  continue;
602 
603  QAction *action = guiClient->action( e );
604  if ( !action )
605  continue;
606 
607  configureAction( action, e.attributes(), shortcutOption );
608  }
609 }
610 
611 void KXMLGUIFactoryPrivate::configureAction( QAction *action, const QDomNamedNodeMap &attributes,
612  ShortcutOption shortcutOption )
613 {
614  for ( uint i = 0; i < attributes.length(); i++ )
615  {
616  QDomAttr attr = attributes.item( i ).toAttr();
617  if ( attr.isNull() )
618  continue;
619 
620  configureAction( action, attr, shortcutOption );
621  }
622 }
623 
624 void KXMLGUIFactoryPrivate::configureAction( QAction *action, const QDomAttr &attribute,
625  ShortcutOption shortcutOption )
626 {
627  static const QString &attrShortcut = KGlobal::staticQString( "shortcut" );
628 
629  QString attrName = attribute.name();
630  // If the attribute is a deprecated "accel", change to "shortcut".
631  if ( equals(attrName, "accel") )
632  attrName = attrShortcut;
633 
634  // No need to re-set name, particularly since it's "objectName" in Qt4
635  if ( equals(attrName, "name") )
636  return;
637 
638  if ( equals(attrName, "icon") ) {
639  action->setIcon( KIcon( attribute.value() ) );
640  return;
641  }
642 
643  QVariant propertyValue;
644 
645  QVariant::Type propertyType = action->property( attrName.toLatin1() ).type();
646 
647  if ( propertyType == QVariant::Int ) {
648  propertyValue = QVariant( attribute.value().toInt() );
649  } else if ( propertyType == QVariant::UInt ) {
650  propertyValue = QVariant( attribute.value().toUInt() );
651  } else if ( propertyType == QVariant::UserType && action->property( attrName.toLatin1() ).userType() == qMetaTypeId<KShortcut>() ) {
652  // Setting the shortcut by property also sets the default shortcut (which is incorrect), so we have to do it directly
653  if (KAction* ka = qobject_cast<KAction*>(action)) {
654  if (attrName=="globalShortcut") {
655  ka->setGlobalShortcut(KShortcut(attribute.value()), KAction::ActiveShortcut);
656  } else {
657  ka->setShortcut(KShortcut(attribute.value()), KAction::ActiveShortcut);
658  }
659  if (shortcutOption & KXMLGUIFactoryPrivate::SetDefaultShortcut)
660  ka->setShortcut(KShortcut(attribute.value()), KAction::DefaultShortcut);
661  return;
662  }
663  propertyValue = KShortcut( attribute.value() );
664  } else {
665  propertyValue = QVariant( attribute.value() );
666  }
667  if (!action->setProperty( attrName.toLatin1(), propertyValue )) {
668  kWarning() << "Error: Unknown action property " << attrName << " will be ignored!";
669  }
670 }
671 
672 QDomDocument KXMLGUIFactoryPrivate::shortcutSchemeDoc(KXMLGUIClient *client)
673 {
674  // Get the name of the current shorcut scheme
675  KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
676  QString schemeName = cg.readEntry("Current Scheme", "Default");
677 
678  QDomDocument doc;
679  if (schemeName != "Default")
680  {
681  // Find the document for the shortcut scheme using both current application path
682  // and current xmlguiclient path but making a preference to app path
683  QString schemeFileName = KStandardDirs::locateLocal("data",
684  client->componentData().componentName() + '/' +
685  client->componentData().componentName() + schemeName.toLower() + "shortcuts.rc" );
686 
687  QFile schemeFile(schemeFileName);
688  if (schemeFile.open(QIODevice::ReadOnly))
689  {
690 // kDebug(260) << "Found shortcut scheme" << schemeFileName;
691  doc.setContent(&schemeFile);
692  schemeFile.close();
693  }
694  }
695  return doc;
696 }
697 
698 void KXMLGUIFactoryPrivate::applyShortcutScheme(KXMLGUIClient *client, const QList<QAction*> &actions, const QDomDocument& scheme)
699 {
700  static const QString &actionPropElementName = KGlobal::staticQString( "ActionProperties" );
701 
702  KConfigGroup cg = KGlobal::config()->group( "Shortcut Schemes" );
703  QString schemeName = cg.readEntry("Current Scheme", "Default");
704 
705  //First clear all existing shortcuts
706  if (schemeName != "Default") {
707  foreach (QAction *action, actions) {
708  if (KAction *kaction = qobject_cast<KAction*>(action)) {
709  kaction->setShortcut(KShortcut(), KAction::ActiveShortcut);
710  // We clear the default shortcut as well because the shortcut scheme will set its own defaults
711  kaction->setShortcut(KShortcut(), KAction::DefaultShortcut);
712  continue;
713  }
714  if (action) {
715  action->setProperty("shortcut", KShortcut());
716  }
717  }
718  } else {
719  // apply saved default shortcuts
720  foreach (QAction *action, actions) {
721  if (KAction *kaction = qobject_cast<KAction*>(action)) {
722  QVariant savedDefaultShortcut = kaction->property("_k_DefaultShortcut");
723  if (savedDefaultShortcut.isValid()) {
724  KShortcut shortcut = savedDefaultShortcut.value<KShortcut>();
725  //kDebug() << "scheme said" << shortcut.toString() << "for action" << kaction->objectName();
726  kaction->setShortcut(shortcut, KAction::ActiveShortcut);
727  kaction->setShortcut(shortcut, KAction::DefaultShortcut);
728  continue;
729  }
730  }
731  if (action) {
732  action->setProperty("shortcut", KShortcut());
733  }
734  }
735  }
736 
737  if (scheme.isNull())
738  return;
739 
740  QDomElement docElement = scheme.documentElement();
741  QDomElement actionPropElement = docElement.namedItem( actionPropElementName ).toElement();
742 
743  //Check if we really have the shortcut configuration here
744  if (!actionPropElement.isNull()) {
745  kDebug(260) << "Applying shortcut scheme for XMLGUI client" << client->componentData().componentName();
746 
747  //Apply all shortcuts we have
748  applyActionProperties(actionPropElement, KXMLGUIFactoryPrivate::SetDefaultShortcut);
749  } else {
750  kDebug(260) << "Invalid shortcut scheme file";
751  }
752 }
753 
754 int KXMLGUIFactory::configureShortcuts(bool letterCutsOk , bool bSaveSettings )
755 {
756  KShortcutsDialog dlg(KShortcutsEditor::AllActions,
757  letterCutsOk ? KShortcutsEditor::LetterShortcutsAllowed : KShortcutsEditor::LetterShortcutsDisallowed,
758  qobject_cast<QWidget*>(parent()));
759  foreach (KXMLGUIClient *client, d->m_clients) {
760  if(client) {
761  dlg.addCollection(client->actionCollection());
762  }
763  }
764  return dlg.configure(bSaveSettings);
765 }
766 
767 // Find or create
768 QDomElement KXMLGUIFactory::actionPropertiesElement( QDomDocument& doc )
769 {
770  // first, lets see if we have existing properties
771  QDomElement elem = findActionPropertiesElement(doc);
772 
773  // if there was none, create one
774  if(elem.isNull()) {
775  elem = doc.createElement(QLatin1String("ActionProperties"));
776  elem.setAttribute("scheme", currentShortcutScheme());
777  doc.documentElement().appendChild( elem );
778  }
779  return elem;
780 }
781 
782 QDomElement KXMLGUIFactory::findActionByName( QDomElement& elem, const QString& sName, bool create )
783 {
784  static const QString& attrName = KGlobal::staticQString( "name" );
785  static const QString& tagAction = KGlobal::staticQString( "Action" );
786  for( QDomNode it = elem.firstChild(); !it.isNull(); it = it.nextSibling() ) {
787  QDomElement e = it.toElement();
788  if( e.attribute( attrName ) == sName )
789  return e;
790  }
791 
792  if( create ) {
793  QDomElement act_elem = elem.ownerDocument().createElement( tagAction );
794  act_elem.setAttribute( attrName, sName );
795  elem.appendChild( act_elem );
796  return act_elem;
797  }
798  return QDomElement();
799 }
800 
801 #include "kxmlguifactory.moc"
802 
803 /* vim: et sw=4
804  */
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Fri Dec 7 2012 16:04:48 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal