44 #include <kactioncollection.h>
45 #include <kcomponentdata.h>
46 #include <kstandarddirs.h>
69 KComponentData instance;
70 ActionCategoryMap actionsCat;
82 static QDomElement makeElement(QDomDocument& domDoc,
const QDomElement& from);
83 static void buildPaths(
const QDomElement& original,
const QDomNodeList& localNodes, QHashPath& paths);
84 static int findByNameAttr(
const QDomNodeList& list,
const QDomElement& node);
85 static void removeDisabledActions(QDomElement& elem);
90 static void buildPaths(
const QDomElement& original,
const QDomNodeList& localNodes, QHashPath& paths, QDomElemList& stack);
94 QDomElement Plugin::Private::XMLParser::makeElement(QDomDocument& domDoc,
const QDomElement& from)
96 if (domDoc.isNull() || from.isNull())
99 QDomElement elem = domDoc.createElement(from.tagName());
100 QDomNamedNodeMap attributes = from.attributes();
102 for (
int i = 0; i < attributes.size(); ++i)
104 QDomAttr attr = attributes.item(i).toAttr();
106 if (attr.name() !=
"alreadyVisited")
107 elem.setAttributeNode(attr);
113 void Plugin::Private::XMLParser::buildPaths(
const QDomElement& original,
const QDomNodeList& localNodes, QHashPath& paths)
121 buildPaths(original, localNodes, paths, stack);
124 int Plugin::Private::XMLParser::findByNameAttr(
const QDomNodeList& list,
const QDomElement& node)
126 const QString nodeName = node.toElement().attribute(
"name");
127 const QString nodeTag = node.toElement().tagName();
129 for (
int i = 0; i < list.size(); ++i)
131 QDomElement e = list.at(i).toElement();
133 if (e.tagName() == nodeTag && e.attribute(
"name") == nodeName)
140 void Plugin::Private::XMLParser::removeDisabledActions(QDomElement& elem)
142 QDomNodeList actionList = elem.elementsByTagName(
"Action");
144 QDomElemList disabledElements;
146 for(
int i = 0; i < actionList.size(); ++i)
148 QDomElement el = actionList.item(i).toElement();
153 if (disabledActions.contains(el.attribute(
"name")))
155 disabledElements << el;
159 foreach(QDomElement element, disabledElements)
161 kDebug() <<
"Plugin action '" << element.attribute(
"name") <<
"' is disabled.";
162 QDomElement parent = element.parentNode().toElement();
163 parent.removeChild(element);
167 void Plugin::Private::XMLParser::buildPaths(
const QDomElement& original,
const QDomNodeList& localNodes,
168 QHashPath& paths, QDomElemList& stack)
170 stack.push_back(original.cloneNode(
true).toElement());
174 if ((idx = findByNameAttr(localNodes, original)) != -1)
176 paths[localNodes.item(idx).toElement().attribute(
"name")] = stack;
179 if (!original.hasChildNodes())
185 for (QDomNode n = original.firstChild(); !n.isNull(); n = n.nextSibling())
187 QDomElement e = n.toElement();
189 if (e.tagName() ==
"Menu" && e.hasChildNodes())
191 buildPaths(e, localNodes, paths, stack);
201 :
QObject(parent), d(new Private)
203 d->instance = instance;
215 QWidget* w = !widget ? d->defaultWidget : widget;
217 if (!d->actionsCat.contains(w))
219 kWarning() <<
"Error in plugin. It needs to call Plugin::setup(QWidget*) "
220 <<
"as the very first line when overriding the setup method.";
223 return d->actionsCat[w].keys();
228 if (!action || name.isEmpty())
233 actionCollection()->addAction(name, action);
238 kDebug() <<
"Action '" << name <<
"' is disabled.";
249 if (!action || name.isEmpty())
254 actionCollection()->addAction(name, action);
259 kDebug() <<
"Action '" << name <<
"' is disabled.";
267 kWarning() <<
"Error in plugin. Action '" << action->objectName() <<
"has "
268 "invalid category. You must set default plugin category or "
269 "to use a valid Category";
272 d->actionsCat[d->defaultWidget].insert(action, cat);
278 d->defaultWidget = widget;
279 d->actionsCat.insert(widget, QMap<KAction*, Category>());
284 QMap<KAction*, Category>::const_iterator it = d->actionsCat[d->defaultWidget].constFind(action);
286 if (it != d->actionsCat[d->defaultWidget].constEnd())
294 kWarning() <<
"Error in plugin. Invalid category. "
295 "You must set default plugin category.";
298 return d->defaultCategory;
304 return (dynamic_cast<Interface*>(parent()));
310 d->uiBaseName = QString(name);
315 return d->uiBaseName;
327 if (d->uiBaseName.isEmpty())
329 kError() <<
"UI file basename is not set! You must first call setUiBaseName.";
333 const QString componentName = KGlobal::mainComponent().componentName();
334 const QString defaultUI = KGlobal::dirs()->locate(
"data", QString(
"kipi/") + d->uiBaseName);
335 const QString localUI = KGlobal::dirs()->locateLocal(
"data", componentName +
"/" + d->uiBaseName);
337 QFile defaultUIFile(defaultUI);
338 QDomDocument defaultDomDoc;
340 if (!defaultUIFile.open(QFile::ReadOnly) || !defaultDomDoc.setContent(&defaultUIFile))
342 kError() <<
"Could not open default ui file: " << defaultUI;
346 defaultUIFile.close();
347 const QDomDocument hostDoc = host->domDocument();
349 if (hostDoc.isNull() || defaultDomDoc.isNull())
351 kError() <<
"Cannot merge the XML files, at least one is null!";
355 QDomElement hostGuiElem = hostDoc.firstChildElement(
"kpartgui");
356 QDomElement hostMenuBarElem = hostGuiElem.firstChildElement(
"MenuBar");
358 QDomDocument newPluginDoc(defaultDomDoc.doctype());
359 QDomElement defGuiElem = defaultDomDoc.firstChildElement(
"gui");
361 Private::XMLParser::removeDisabledActions(defGuiElem);
363 QDomElement newGuiElem = Private::XMLParser::makeElement(newPluginDoc, defGuiElem);
364 QDomElement defMenuBarElem = defGuiElem.firstChildElement(
"MenuBar");
365 QDomElement newMenuBarElem = Private::XMLParser::makeElement(newPluginDoc, defMenuBarElem);
366 QDomElement defToolBarElem = defGuiElem.firstChildElement(
"ToolBar");
367 QDomElement defActionPropElem = defGuiElem.firstChildElement(
"ActionProperties");
370 Private::XMLParser::buildPaths(hostMenuBarElem, defMenuBarElem.childNodes(), paths);
372 for (QDomNode n = defMenuBarElem.firstChild(); !n.isNull(); n = n.nextSibling())
374 QDomElemList path = paths[n.toElement().attribute(
"name")];
375 QDomElement current = newMenuBarElem;
376 QDomElement origCurr = defMenuBarElem;
380 newMenuBarElem.appendChild(n.cloneNode());
384 for (
int i = 1; i < path.size() - 1; ++i)
386 int idx = Private::XMLParser::findByNameAttr(current.childNodes(), path[i]);
391 if (!path[i].isNull())
393 QDomElement newChild = Private::XMLParser::makeElement(newPluginDoc, path[i]);
394 QDomElement textElem = origCurr.firstChildElement(
"text");
396 if (!textElem.isNull())
398 newChild.appendChild(textElem.cloneNode());
401 current.appendChild(newChild);
407 current = current.childNodes().item(idx).toElement();
412 if (!current.isNull())
413 current.appendChild(n.cloneNode());
416 newGuiElem.appendChild(newMenuBarElem);
417 QFile localUIFile(localUI);
418 QDomDocument localDomDoc;
420 if (!localUIFile.exists() || !localUIFile.open(QFile::ReadOnly) || !localDomDoc.setContent(&localUIFile))
422 newGuiElem.appendChild(defToolBarElem.cloneNode());
423 newGuiElem.appendChild(defActionPropElem.cloneNode());
427 QDomElement localGuiElem = localDomDoc.firstChildElement(
"gui");
429 Private::XMLParser::removeDisabledActions(localGuiElem);
431 QDomElement localToolBarElem = localGuiElem.firstChildElement(
"ToolBar");
432 QDomElement localActionPropElem = localGuiElem.firstChildElement(
"ActionProperties");
434 newGuiElem.appendChild(localToolBarElem.cloneNode());
435 newGuiElem.appendChild(localActionPropElem.cloneNode());
439 QFile writeFile(localUI);
441 if (!writeFile.open(QFile::WriteOnly | QFile::Truncate))
443 kError() <<
"Could not open " << localUI <<
" for writing!";
447 newPluginDoc.appendChild(newGuiElem);
449 writeFile.write(newPluginDoc.toString().toUtf8());
452 setXMLFile(d->uiBaseName);
455 void Plugin::clearActions()
457 QList<QAction*>
actions = actionCollection()->actions();
459 foreach (QAction*
const action, actions)
461 actionCollection()->removeAction(action);
467 mergeXMLFile(dynamic_cast<KXMLGUIClient*>(
interface()->parent()));
472 QString file = xmlFile();
476 setXMLGUIBuildDocument(QDomDocument());
477 setXMLFile(file,
false);
483 d->defaultCategory = cat;
488 return d->defaultCategory;
QString uiBaseName() const
Return the base name of the xml file associated with this KXMLGUIClient.
void setupXML()
Adapt the xml file of the plugin with the one of the KXmlGuiWindow main window.
void rebuild()
Force the plugin to reread and to reload its xml file.
virtual ~Plugin()
Standard destructor.
===========================================================This file is a part of digiKam project htt...
void setUiBaseName(const char *name)
Sets the name of the xml file associated with this KXMLGUIClient.
Category defaultCategory() const
Returns the default category of the plugin actions.
static PluginLoader * instance()
Returns plugin loader instance.
virtual void setup(QWidget *const widget)=0
Virtual method that must be overrided by the non abstract descendants and must be called before any a...
===========================================================This file is a part of digiKam project htt...
void addAction(const QString &name, KAction *const action)
Register an action to the plugin instance and add it to the action collection.
Plugin(const KComponentData &instance, QObject *const parent, const char *name)
Constructs a plugin.
QList< KAction * > actions(QWidget *const widget=0) const
Returns the plugin actions associated with the widget passed as argument, or with the default widget...
Interface * interface() const
Returns the KIPI::Interface.
void setDefaultCategory(Category cat)
Sets the default category of the plugin actions.
Category category(KAction *const action) const
Returns the category of the specified plugin action, or InvalidCategory if the action is not recognis...
QStringList disabledPluginActions() const
Return the list of disabled plugin actions.