22 #include "kxmlguifactory_p.h"
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>
47 using namespace KXMLGUI;
49 class KXMLGUIFactoryPrivate :
public BuildState
52 enum ShortcutOption { SetActiveShortcut = 1, SetDefaultShortcut = 2};
54 KXMLGUIFactoryPrivate()
60 m_rootNode =
new ContainerNode( 0L,
QString(), 0L );
61 m_defaultMergingName = defaultMergingName;
62 tagActionList = actionList;
65 ~KXMLGUIFactoryPrivate()
72 m_stateStack.push( *
this );
77 BuildState::operator=( m_stateStack.pop() );
80 bool emptyState()
const {
return m_stateStack.isEmpty(); }
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 );
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);
96 ContainerNode *m_rootNode;
108 QList<KXMLGUIClient*> m_clients;
114 BuildStateStack m_stateStack;
121 if (!QDir::isRelativePath(filename))
127 if ( !QFile::exists( xml_file ) )
131 QFile file( xml_file );
132 if ( xml_file.isEmpty() || !file.open( QIODevice::ReadOnly ) )
134 kError(240) <<
"No such XML file" << filename;
138 QByteArray buffer(file.readAll());
139 return QString::fromUtf8(buffer.constData(), buffer.size());
148 if (QDir::isRelativePath(xml_file))
151 QFile file( xml_file );
152 if ( xml_file.isEmpty() || !file.open( QIODevice::WriteOnly ) )
154 kError(240) <<
"Could not write to" << filename;
159 QTextStream ts(&file);
160 ts.setCodec( QTextCodec::codecForName(
"UTF-8" ) );
172 QDomNode n = node.firstChild();
173 while ( !n.isNull() )
175 if ( n.nodeType() == QDomNode::CommentNode )
179 node.removeChild( tmp );
191 :
QObject( parent ),d(new KXMLGUIFactoryPrivate)
193 d->builder = builder;
197 d->builderContainerTags = d->builder->containerTags();
198 d->builderCustomTags = d->builder->customTags();
214 if ( client->
factory() == this )
226 d->guiClient = client;
229 if ( !d->m_clients.contains( client ) )
230 d->m_clients.append( client );
232 kDebug(260) <<
"XMLGUI client already added " << client;
243 if ( doc.documentElement().isNull() )
246 QDomElement docElement = doc.documentElement();
248 d->m_rootNode->index = -1;
252 d->clientName = docElement.attribute( d->attrName );
255 if ( d->clientBuilder )
257 d->clientBuilderContainerTags = d->clientBuilder->containerTags();
258 d->clientBuilderCustomTags = d->clientBuilder->customTags();
262 d->clientBuilderContainerTags.clear();
263 d->clientBuilderCustomTags.clear();
271 BuildHelper( *d, d->m_rootNode ).build( docElement );
280 d->builder->finalizeGUI( d->guiClient );
283 d->BuildState::reset();
315 d->guiClient = client;
317 if ( doc.documentElement().isNull() )
330 return cg.
readEntry(
"Current Scheme",
"Default");
336 const QLatin1String tagActionProp(
"ActionProperties");
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) ) {
345 return QDomElement();
348 void KXMLGUIFactoryPrivate::refreshActionProperties(
KXMLGUIClient *client,
const QList<QAction*>& actions,
const QDomDocument& doc)
351 QDomDocument scheme = shortcutSchemeDoc(client);
352 applyShortcutScheme(client, actions, scheme);
356 if ( !actionPropElement.isNull() )
357 applyActionProperties( actionPropElement );
360 void KXMLGUIFactoryPrivate::saveDefaultActionProperties(
const QList<QAction *>& actions)
365 foreach (
QAction *action, actions) {
367 if (!action || action->property(
"_k_DefaultShortcut").isValid())
continue;
369 if (
KAction* kaction = qobject_cast<KAction*>(action)) {
380 kError(240) <<
"Shortcut for KAction " << kaction->objectName() << kaction->text() <<
"set with QShortcut::setShortcut()! See KAction documentation.";
381 kaction->setProperty(
"_k_DefaultShortcut", activeShortcut);
383 kaction->setProperty(
"_k_DefaultShortcut", defaultShortcut);
389 kError(240) <<
"Attempt to use QAction" << action->objectName() <<
"with KXMLGUIFactory!";
390 action->setProperty(
"_k_DefaultShortcut",
KShortcut());
398 kDebug(260) <<
"Changing shortcut scheme to" << scheme;
407 d->m_clients.removeAll( client );
415 if ( !client || client->
factory() != this )
422 d->m_clients.removeAll( client );
426 const QList<KXMLGUIClient*> childClients(client->
childClients());
436 d->guiClient = client;
437 d->clientName = client->
domDocument().documentElement().attribute( d->attrName );
446 if ( doc.documentElement().isNull() )
448 doc = client->
domDocument().cloneNode(
true ).toDocument();
452 d->m_rootNode->destruct( doc.documentElement(), *d );
455 d->BuildState::reset();
477 d->m_containerName = containerName;
478 d->guiClient = client;
480 QWidget *result = d->findRecursive( d->m_rootNode, useTagName );
483 d->m_containerName.clear();
492 return d->findRecursive( d->m_rootNode, tagName );
497 d->m_rootNode->reset();
499 d->m_rootNode->clearChildren();
504 if ( containerName.isEmpty() )
507 ContainerNode *
container = d->m_rootNode->findContainer( containerName, useTagName );
512 ContainerNode *parent = container->parent;
518 parent->removeChild( container );
521 QWidget *KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node,
bool tag )
523 if ( ( ( !tag && node->name == m_containerName ) ||
524 ( tag && node->tagName == m_containerName ) ) &&
525 ( !guiClient || node->client == guiClient ) )
526 return node->container;
528 foreach (ContainerNode* child, node->children)
541 return str1.compare(QLatin1String(str2), Qt::CaseInsensitive) == 0;
545 return str1.compare(str2, Qt::CaseInsensitive) == 0;
549 QList<QWidget*> KXMLGUIFactoryPrivate::findRecursive( KXMLGUI::ContainerNode *node,
554 if (
equals(node->tagName, tagName) )
555 res.append( node->container );
557 foreach (KXMLGUI::ContainerNode* child, node->children)
558 res << findRecursive( child, tagName );
564 const QList<QAction*> &actionList )
567 d->guiClient = client;
568 d->actionListName =
name;
569 d->actionList = actionList;
570 d->clientName = client->
domDocument().documentElement().attribute( d->attrName );
572 d->m_rootNode->plugActionList( *d );
575 d->saveDefaultActionProperties(actionList);
576 d->refreshActionProperties(client, actionList, client->
domDocument());
578 d->BuildState::reset();
585 d->guiClient = client;
586 d->actionListName =
name;
587 d->clientName = client->
domDocument().documentElement().attribute( d->attrName );
589 d->m_rootNode->unplugActionList( *d );
591 d->BuildState::reset();
595 void KXMLGUIFactoryPrivate::applyActionProperties(
const QDomElement &actionPropElement,
596 ShortcutOption shortcutOption )
598 for (QDomElement e = actionPropElement.firstChildElement();
599 !e.isNull(); e = e.nextSiblingElement()) {
600 if ( !
equals(e.tagName(),
"action") )
603 QAction *action = guiClient->action( e );
607 configureAction( action, e.attributes(), shortcutOption );
611 void KXMLGUIFactoryPrivate::configureAction(
QAction *action,
const QDomNamedNodeMap &attributes,
612 ShortcutOption shortcutOption )
614 for ( uint i = 0; i < attributes.length(); i++ )
616 QDomAttr attr = attributes.item( i ).toAttr();
620 configureAction( action, attr, shortcutOption );
624 void KXMLGUIFactoryPrivate::configureAction(
QAction *action,
const QDomAttr &attribute,
625 ShortcutOption shortcutOption )
629 QString attrName = attribute.name();
631 if (
equals(attrName,
"accel") )
632 attrName = attrShortcut;
635 if (
equals(attrName,
"name") )
638 if (
equals(attrName,
"icon") ) {
639 action->setIcon(
KIcon( attribute.value() ) );
645 QVariant::Type propertyType = action->property( attrName.toLatin1() ).type();
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>() ) {
653 if (
KAction* ka = qobject_cast<KAction*>(action)) {
654 if (attrName==
"globalShortcut") {
659 if (shortcutOption & KXMLGUIFactoryPrivate::SetDefaultShortcut)
663 propertyValue =
KShortcut( attribute.value() );
665 propertyValue =
QVariant( attribute.value() );
667 if (!action->setProperty( attrName.toLatin1(), propertyValue )) {
668 kWarning() <<
"Error: Unknown action property " << attrName <<
" will be ignored!";
672 QDomDocument KXMLGUIFactoryPrivate::shortcutSchemeDoc(
KXMLGUIClient *client)
679 if (schemeName !=
"Default")
687 QFile schemeFile(schemeFileName);
688 if (schemeFile.open(QIODevice::ReadOnly))
691 doc.setContent(&schemeFile);
698 void KXMLGUIFactoryPrivate::applyShortcutScheme(
KXMLGUIClient *client,
const QList<QAction*> &actions,
const QDomDocument& scheme)
706 if (schemeName !=
"Default") {
707 foreach (
QAction *action, actions) {
708 if (
KAction *kaction = qobject_cast<KAction*>(action)) {
715 action->setProperty(
"shortcut",
KShortcut());
720 foreach (
QAction *action, actions) {
721 if (
KAction *kaction = qobject_cast<KAction*>(action)) {
722 QVariant savedDefaultShortcut = kaction->property(
"_k_DefaultShortcut");
723 if (savedDefaultShortcut.isValid()) {
732 action->setProperty(
"shortcut",
KShortcut());
740 QDomElement docElement = scheme.documentElement();
741 QDomElement actionPropElement = docElement.namedItem( actionPropElementName ).toElement();
744 if (!actionPropElement.isNull()) {
748 applyActionProperties(actionPropElement, KXMLGUIFactoryPrivate::SetDefaultShortcut);
750 kDebug(260) <<
"Invalid shortcut scheme file";
758 qobject_cast<QWidget*>(parent()));
775 elem = doc.createElement(QLatin1String(
"ActionProperties"));
777 doc.documentElement().appendChild( elem );
786 for( QDomNode it = elem.firstChild(); !it.isNull(); it = it.nextSibling() ) {
787 QDomElement e = it.toElement();
788 if( e.attribute( attrName ) == sName )
793 QDomElement act_elem = elem.ownerDocument().createElement( tagAction );
794 act_elem.setAttribute( attrName, sName );
795 elem.appendChild( act_elem );
798 return QDomElement();
801 #include "kxmlguifactory.moc"