• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegraphics API Reference
  • KDE Home
  • Contact Us
 

libs/libkipi/libkipi

  • sources
  • kde-4.14
  • kdegraphics
  • libs
  • libkipi
  • libkipi
plugin.cpp
Go to the documentation of this file.
1 
34 #include "plugin.moc"
35 
36 // Qt includes
37 
38 #include <QWidget>
39 #include <QFile>
40 
41 // KDE includes
42 
43 #include <kaction.h>
44 #include <kactioncollection.h>
45 #include <kcomponentdata.h>
46 #include <kstandarddirs.h>
47 #include <kdebug.h>
48 
49 // Local includes
50 
51 #include "version.h"
52 #include "interface.h"
53 #include "pluginloader.h"
54 
55 namespace KIPI
56 {
57 
58 class Plugin::Private
59 {
60 public:
61 
62  Private() :
63  uiBaseName(QString())
64  {
65  defaultWidget = 0;
66  defaultCategory = InvalidCategory;
67  }
68 
69  KComponentData instance;
70  ActionCategoryMap actionsCat;
71  QWidget* defaultWidget;
72  QString uiBaseName;
73  Category defaultCategory;
74 
75 public:
76 
77  class XMLParser
78  {
79 
80  public:
81 
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);
86 
87  private:
88 
89  XMLParser();
90  static void buildPaths(const QDomElement& original, const QDomNodeList& localNodes, QHashPath& paths, QDomElemList& stack);
91  };
92 };
93 
94 QDomElement Plugin::Private::XMLParser::makeElement(QDomDocument& domDoc, const QDomElement& from)
95 {
96  if (domDoc.isNull() || from.isNull())
97  return QDomElement();
98 
99  QDomElement elem = domDoc.createElement(from.tagName());
100  QDomNamedNodeMap attributes = from.attributes();
101 
102  for (int i = 0; i < attributes.size(); ++i)
103  {
104  QDomAttr attr = attributes.item(i).toAttr();
105 
106  if (attr.name() != "alreadyVisited")
107  elem.setAttributeNode(attr);
108  }
109 
110  return elem;
111 }
112 
113 void Plugin::Private::XMLParser::buildPaths(const QDomElement& original, const QDomNodeList& localNodes, QHashPath& paths)
114 {
115  /*
116  * For each child element of "local", we will construct the path from the
117  * "original" element to first appearance of the respective child in the
118  * subtree.
119  */
120  QDomElemList stack;
121  buildPaths(original, localNodes, paths, stack);
122 }
123 
124 int Plugin::Private::XMLParser::findByNameAttr(const QDomNodeList& list, const QDomElement& node)
125 {
126  const QString nodeName = node.toElement().attribute("name");
127  const QString nodeTag = node.toElement().tagName();
128 
129  for (int i = 0; i < list.size(); ++i)
130  {
131  QDomElement e = list.at(i).toElement();
132 
133  if (e.tagName() == nodeTag && e.attribute("name") == nodeName)
134  return i;
135  }
136 
137  return -1;
138 }
139 
140 void Plugin::Private::XMLParser::removeDisabledActions(QDomElement& elem)
141 {
142  QDomNodeList actionList = elem.elementsByTagName("Action");
143  QStringList disabledActions = PluginLoader::instance()->disabledPluginActions();
144  QDomElemList disabledElements;
145 
146  for(int i = 0; i < actionList.size(); ++i)
147  {
148  QDomElement el = actionList.item(i).toElement();
149 
150  if (el.isNull())
151  continue;
152 
153  if (disabledActions.contains(el.attribute("name")))
154  {
155  disabledElements << el;
156  }
157  }
158 
159  foreach(QDomElement element, disabledElements)
160  {
161  kDebug() << "Plugin action '" << element.attribute("name") << "' is disabled.";
162  QDomElement parent = element.parentNode().toElement();
163  parent.removeChild(element);
164  }
165 }
166 
167 void Plugin::Private::XMLParser::buildPaths(const QDomElement& original, const QDomNodeList& localNodes,
168  QHashPath& paths, QDomElemList& stack)
169 {
170  stack.push_back(original.cloneNode(true).toElement());
171 
172  int idx;
173 
174  if ((idx = findByNameAttr(localNodes, original)) != -1)
175  {
176  paths[localNodes.item(idx).toElement().attribute("name")] = stack;
177  }
178 
179  if (!original.hasChildNodes())
180  {
181  stack.pop_back();
182  return;
183  }
184 
185  for (QDomNode n = original.firstChild(); !n.isNull(); n = n.nextSibling())
186  {
187  QDomElement e = n.toElement();
188 
189  if (e.tagName() == "Menu" && e.hasChildNodes())
190  {
191  buildPaths(e, localNodes, paths, stack);
192  }
193  }
194 
195  stack.pop_back();
196 }
197 
198 // --------------------------------------------------------------------------------------------------------------
199 
200 Plugin::Plugin(const KComponentData& instance, QObject* const parent, const char* name)
201  : QObject(parent), d(new Private)
202 {
203  d->instance = instance;
204  setObjectName(name);
205 }
206 
207 Plugin::~Plugin()
208 {
209  clearActions();
210  delete d;
211 }
212 
213 QList<KAction*> Plugin::actions(QWidget* const widget) const
214 {
215  QWidget* w = !widget ? d->defaultWidget : widget;
216 
217  if (!d->actionsCat.contains(w))
218  {
219  kWarning() << "Error in plugin. It needs to call Plugin::setup(QWidget*) "
220  << "as the very first line when overriding the setup method.";
221  }
222 
223  return d->actionsCat[w].keys();
224 }
225 
226 void Plugin::addAction(const QString& name, KAction* const action)
227 {
228  if (!action || name.isEmpty())
229  return;
230 
231  if (!PluginLoader::instance()->disabledPluginActions().contains(name))
232  {
233  actionCollection()->addAction(name, action);
234  addAction(action);
235  }
236  else
237  {
238  kDebug() << "Action '" << name << "' is disabled.";
239  }
240 }
241 
242 void Plugin::addAction(KAction* const action)
243 {
244  addAction(action, d->defaultCategory);
245 }
246 
247 void Plugin::addAction(const QString& name, KAction* const action, Category cat)
248 {
249  if (!action || name.isEmpty())
250  return;
251 
252  if (!PluginLoader::instance()->disabledPluginActions().contains(name))
253  {
254  actionCollection()->addAction(name, action);
255  addAction(action, cat);
256  }
257  else
258  {
259  kDebug() << "Action '" << name << "' is disabled.";
260  }
261 }
262 
263 void Plugin::addAction(KAction* const action, Category cat)
264 {
265  if (cat == InvalidCategory)
266  {
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";
270  }
271 
272  d->actionsCat[d->defaultWidget].insert(action, cat);
273 }
274 
275 void Plugin::setup(QWidget* const widget)
276 {
277  clearActions();
278  d->defaultWidget = widget;
279  d->actionsCat.insert(widget, QMap<KAction*, Category>());
280 }
281 
282 Category Plugin::category(KAction* const action) const
283 {
284  QMap<KAction*, Category>::const_iterator it = d->actionsCat[d->defaultWidget].constFind(action);
285 
286  if (it != d->actionsCat[d->defaultWidget].constEnd())
287  {
288  return it.value();
289  }
290  else
291  {
292  if (d->defaultCategory == InvalidCategory)
293  {
294  kWarning() << "Error in plugin. Invalid category. "
295  "You must set default plugin category.";
296  }
297 
298  return d->defaultCategory;
299  }
300 }
301 
302 Interface* Plugin::interface() const
303 {
304  return (dynamic_cast<Interface*>(parent()));
305 }
306 
307 void Plugin::setUiBaseName(const char* name)
308 {
309  if (name && *name)
310  d->uiBaseName = QString(name);
311 }
312 
313 QString Plugin::uiBaseName() const
314 {
315  return d->uiBaseName;
316 }
317 
318 void Plugin::mergeXMLFile(KXMLGUIClient *const host)
319 {
320  if (!host)
321  {
322  // Should we display this message?
323  //kError() << "Host KXMLGUIClient is null!";
324  return;
325  }
326 
327  if (d->uiBaseName.isEmpty())
328  {
329  kError() << "UI file basename is not set! You must first call setUiBaseName.";
330  return;
331  }
332 
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);
336 
337  QFile defaultUIFile(defaultUI);
338  QDomDocument defaultDomDoc;
339 
340  if (!defaultUIFile.open(QFile::ReadOnly) || !defaultDomDoc.setContent(&defaultUIFile))
341  {
342  kError() << "Could not open default ui file: " << defaultUI;
343  return;
344  }
345 
346  defaultUIFile.close();
347  const QDomDocument hostDoc = host->domDocument();
348 
349  if (hostDoc.isNull() || defaultDomDoc.isNull())
350  {
351  kError() << "Cannot merge the XML files, at least one is null!";
352  return;
353  }
354 
355  QDomElement hostGuiElem = hostDoc.firstChildElement("kpartgui");
356  QDomElement hostMenuBarElem = hostGuiElem.firstChildElement("MenuBar");
357 
358  QDomDocument newPluginDoc(defaultDomDoc.doctype());
359  QDomElement defGuiElem = defaultDomDoc.firstChildElement("gui");
360 
361  Private::XMLParser::removeDisabledActions(defGuiElem);
362 
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");
368 
369  QHashPath paths;
370  Private::XMLParser::buildPaths(hostMenuBarElem, defMenuBarElem.childNodes(), paths);
371 
372  for (QDomNode n = defMenuBarElem.firstChild(); !n.isNull(); n = n.nextSibling())
373  {
374  QDomElemList path = paths[n.toElement().attribute("name")];
375  QDomElement current = newMenuBarElem;
376  QDomElement origCurr = defMenuBarElem;
377 
378  if (path.empty())
379  {
380  newMenuBarElem.appendChild(n.cloneNode());
381  }
382  else
383  {
384  for (int i = 1; i < path.size() - 1; ++i)
385  {
386  int idx = Private::XMLParser::findByNameAttr(current.childNodes(), path[i]);
387  origCurr = path[i];
388 
389  if (idx == -1)
390  {
391  if (!path[i].isNull())
392  {
393  QDomElement newChild = Private::XMLParser::makeElement(newPluginDoc, path[i]);
394  QDomElement textElem = origCurr.firstChildElement("text");
395 
396  if (!textElem.isNull())
397  {
398  newChild.appendChild(textElem.cloneNode());
399  }
400 
401  current.appendChild(newChild);
402  current = newChild;
403  }
404  }
405  else
406  {
407  current = current.childNodes().item(idx).toElement();
408  }
409  }
410  }
411 
412  if (!current.isNull())
413  current.appendChild(n.cloneNode());
414  }
415 
416  newGuiElem.appendChild(newMenuBarElem);
417  QFile localUIFile(localUI);
418  QDomDocument localDomDoc;
419 
420  if (!localUIFile.exists() || !localUIFile.open(QFile::ReadOnly) || !localDomDoc.setContent(&localUIFile))
421  {
422  newGuiElem.appendChild(defToolBarElem.cloneNode());
423  newGuiElem.appendChild(defActionPropElem.cloneNode());
424  }
425  else
426  {
427  QDomElement localGuiElem = localDomDoc.firstChildElement("gui");
428 
429  Private::XMLParser::removeDisabledActions(localGuiElem);
430 
431  QDomElement localToolBarElem = localGuiElem.firstChildElement("ToolBar");
432  QDomElement localActionPropElem = localGuiElem.firstChildElement("ActionProperties");
433 
434  newGuiElem.appendChild(localToolBarElem.cloneNode());
435  newGuiElem.appendChild(localActionPropElem.cloneNode());
436  }
437 
438  localUIFile.close();
439  QFile writeFile(localUI);
440 
441  if (!writeFile.open(QFile::WriteOnly | QFile::Truncate))
442  {
443  kError() << "Could not open " << localUI << " for writing!";
444  return;
445  }
446 
447  newPluginDoc.appendChild(newGuiElem);
448 
449  writeFile.write(newPluginDoc.toString().toUtf8());
450  writeFile.close();
451 
452  setXMLFile(d->uiBaseName);
453 }
454 
455 void Plugin::clearActions()
456 {
457  QList<QAction*> actions = actionCollection()->actions();
458 
459  foreach (QAction* const action, actions)
460  {
461  actionCollection()->removeAction(action);
462  }
463 }
464 
465 void Plugin::setupXML()
466 {
467  mergeXMLFile(dynamic_cast<KXMLGUIClient*>(interface()->parent()));
468 }
469 
470 void Plugin::rebuild()
471 {
472  QString file = xmlFile();
473 
474  if (!file.isEmpty())
475  {
476  setXMLGUIBuildDocument(QDomDocument());
477  setXMLFile(file, false);
478  }
479 }
480 
481 void Plugin::setDefaultCategory(Category cat)
482 {
483  d->defaultCategory = cat;
484 }
485 
486 Category Plugin::defaultCategory() const
487 {
488  return d->defaultCategory;
489 }
490 
491 } // namespace KIPI
KIPI::Plugin::uiBaseName
QString uiBaseName() const
Return the base name of the xml file associated with this KXMLGUIClient.
Definition: plugin.cpp:313
KIPI::Plugin::setupXML
void setupXML()
Adapt the xml file of the plugin with the one of the KXmlGuiWindow main window.
Definition: plugin.cpp:465
QDomElement::elementsByTagName
QDomNodeList elementsByTagName(const QString &tagname) const
QWidget
QDomNodeList::item
QDomNode item(int index) const
KIPI::Plugin::rebuild
void rebuild()
Force the plugin to reread and to reload its xml file.
Definition: plugin.cpp:470
KXMLGUIClient
KIPI::Plugin::~Plugin
virtual ~Plugin()
Standard destructor.
Definition: plugin.cpp:207
QDomAttr::name
QString name() const
QDomNode::appendChild
QDomNode appendChild(const QDomNode &newChild)
pluginloader.h
===========================================================This file is a part of digiKam project htt...
QDomElement::attribute
QString attribute(const QString &name, const QString &defValue) const
KIPI::InvalidCategory
Definition: plugin.h:65
KIPI::Plugin::setUiBaseName
void setUiBaseName(const char *name)
Sets the name of the xml file associated with this KXMLGUIClient.
Definition: plugin.cpp:307
QDomNodeList
QMap
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
KIPI::Plugin::defaultCategory
Category defaultCategory() const
Returns the default category of the plugin actions.
Definition: plugin.cpp:486
QDomNode
KIPI::Interface
Definition: interface.h:158
QDomDocument::doctype
QDomDocumentType doctype() const
QDomNode::childNodes
QDomNodeList childNodes() const
QFile
QDomNode::toElement
QDomElement toElement() const
QDomNamedNodeMap
KIPI::PluginLoader::instance
static PluginLoader * instance()
Returns plugin loader instance.
Definition: pluginloader.cpp:374
KIPI::Plugin::setup
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...
Definition: plugin.cpp:275
QDomAttr
interface.h
===========================================================This file is a part of digiKam project htt...
QObject
KIPI::Plugin::addAction
void addAction(const QString &name, KAction *const action)
Register an action to the plugin instance and add it to the action collection.
Definition: plugin.cpp:226
QObject::setObjectName
void setObjectName(const QString &name)
QString::isEmpty
bool isEmpty() const
QMap::const_iterator
KIPI::Plugin::Plugin
Plugin(const KComponentData &instance, QObject *const parent, const char *name)
Constructs a plugin.
Definition: plugin.cpp:200
QString
QList
QDomNode::hasChildNodes
bool hasChildNodes() const
QStringList
QDomNode::removeChild
QDomNode removeChild(const QDomNode &oldChild)
QDomDocument
QDomNode::isNull
bool isNull() const
KIPI::Plugin::actions
QList< KAction * > actions(QWidget *const widget=0) const
Returns the plugin actions associated with the widget passed as argument, or with the default widget...
Definition: plugin.cpp:213
KIPI::Plugin::interface
Interface * interface() const
Returns the KIPI::Interface.
Definition: plugin.cpp:302
QDomNode::firstChild
QDomNode firstChild() const
KIPI::Plugin::setDefaultCategory
void setDefaultCategory(Category cat)
Sets the default category of the plugin actions.
Definition: plugin.cpp:481
QDomNode::parentNode
QDomNode parentNode() const
QDomNode::cloneNode
QDomNode cloneNode(bool deep) const
QDomElement::setAttributeNode
QDomAttr setAttributeNode(const QDomAttr &newAttr)
QDomNode::firstChildElement
QDomElement firstChildElement(const QString &tagName) const
QAction
QDomNode::toAttr
QDomAttr toAttr() const
KIPI::Category
Category
Definition: plugin.h:63
KIPI::Plugin::category
Category category(KAction *const action) const
Returns the category of the specified plugin action, or InvalidCategory if the action is not recognis...
Definition: plugin.cpp:282
QDomElement::tagName
QString tagName() const
QDomNodeList::size
int size() const
QDomDocument::createElement
QDomElement createElement(const QString &tagName)
KIPI::PluginLoader::disabledPluginActions
QStringList disabledPluginActions() const
Return the list of disabled plugin actions.
Definition: pluginloader.cpp:283
QDomNamedNodeMap::item
QDomNode item(int index) const
QObject::parent
QObject * parent() const
QDomElement
QDomNamedNodeMap::size
int size() const
QDomDocument::setContent
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QDomNodeList::at
QDomNode at(int index) const
QDomElement::attributes
QDomNamedNodeMap attributes() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:19:43 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libs/libkipi/libkipi

Skip menu "libs/libkipi/libkipi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdegraphics API Reference

Skip menu "kdegraphics API Reference"
  •     libkdcraw
  •     libkexiv2
  •     libkipi
  •     libksane
  • okular

Search



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