KontactInterface

plugin.cpp
1 /*
2  This file is part of the KDE Kontact Plugin Interface Library.
3 
4  SPDX-FileCopyrightText: 2001 Matthias Hoelzer-Kluepfel <[email protected]>
5  SPDX-FileCopyrightText: 2002-2003 Daniel Molkentin <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.0-or-later
8 */
9 
10 #include "plugin.h"
11 #include "core.h"
12 #include "processes.h"
13 #include "kontactinterface_debug.h"
14 
15 #include <KPluginLoader>
16 #include <KXMLGUIFactory>
17 #include <KAboutData>
18 #include <KLocalizedString>
19 #include <KIO/CommandLauncherJob>
20 
21 #include <QObject>
22 #include <QDBusConnection>
23 #include <QDomDocument>
24 #include <QFileInfo>
25 #include <QDir>
26 
27 #include <QStandardPaths>
28 #include <QCoreApplication>
29 
30 using namespace KontactInterface;
31 
36 //@cond PRIVATE
37 class Q_DECL_HIDDEN Plugin::Private
38 {
39 public:
40 
41  void partDestroyed();
42  void setXmlFiles();
43  void removeInvisibleToolbarActions(Plugin *plugin);
44 
45  Core *core = nullptr;
46  QList<QAction *> newActions;
47  QList<QAction *> syncActions;
48  QString identifier;
49  QString title;
50  QString icon;
51  QString executableName;
52  QString serviceName;
53  QByteArray partLibraryName;
54  QByteArray pluginName;
55  KParts::Part *part = nullptr;
56  bool hasPart;
57  bool disabled;
58 };
59 //@endcond
60 
61 Plugin::Plugin(Core *core, QObject *parent, const char *appName, const char *pluginName)
62  : KXMLGUIClient(core), QObject(parent), d(new Private)
63 {
64  setObjectName(QLatin1String(appName));
65  core->factory()->addClient(this);
66 
67  d->pluginName = pluginName ? pluginName : appName;
68  d->core = core;
69  d->hasPart = true;
70  d->part = nullptr;
71  d->disabled = false;
72 }
73 
75 {
76  delete d->part;
77  delete d;
78 }
79 
81 {
82  d->identifier = identifier;
83 }
84 
86 {
87  return d->identifier;
88 }
89 
91 {
92  d->title = title;
93 }
94 
96 {
97  return d->title;
98 }
99 
101 {
102  d->icon = icon;
103 }
104 
106 {
107  return d->icon;
108 }
109 
111 {
112  d->executableName = bin;
113 }
114 
116 {
117  return d->executableName;
118 }
119 
121 {
122  d->partLibraryName = libName;
123 }
124 
126 {
127  return false;
128 }
129 
131 {
132  return core()->createPart(d->partLibraryName.constData());
133 }
134 
136 {
137  return part()->componentData();
138 }
139 
141 {
142  if (!d->part) {
143  d->part = createPart();
144  if (d->part) {
145  connect(d->part, &KParts::Part::destroyed, this, [this]() { d->partDestroyed(); });
146  d->removeInvisibleToolbarActions(this);
147  core()->partLoaded(this, d->part);
148  }
149  }
150  return d->part;
151 }
152 
154 {
155  if (d->serviceName.isEmpty()) {
156  d->serviceName = QLatin1String("org.kde.") + QLatin1String(objectName().toLatin1());
157 #ifdef Q_OS_WIN
159  d->serviceName.append(QLatin1String(".unique-") + pid);
160 #endif
162  }
163  return d->serviceName;
164 }
165 
166 int Plugin::weight() const
167 {
168  return 0;
169 }
170 
172 {
173  d->newActions.append(action);
174 }
175 
177 {
178  d->syncActions.append(action);
179 }
180 
182 {
183  return d->newActions;
184 }
185 
187 {
188  return d->syncActions;
189 }
190 
192 {
193  return QStringList();
194 }
195 
196 bool Plugin::canDecodeMimeData(const QMimeData *data) const
197 {
198  Q_UNUSED(data);
199  return false;
200 }
201 
203 {
204 }
205 
207 {
208 }
209 
211 {
212 }
213 
215 {
216  return d->core;
217 }
218 
220 {
221  // Because the 3 korganizer plugins share the same part, we need to switch
222  // that part's XML files every time we are about to show its GUI...
223  d->setXmlFiles();
224 
225  select();
226 }
227 
229 {
230 }
231 
233 {
234 }
235 
236 //@cond PRIVATE
237 void Plugin::Private::partDestroyed()
238 {
239  part = nullptr;
240 }
241 
242 void Plugin::Private::removeInvisibleToolbarActions(Plugin *plugin)
243 {
244  if (pluginName.isEmpty()) {
245  return;
246  }
247 
248  // Hide unwanted toolbar action by modifying the XML before createGUI, rather
249  // than doing it by calling removeAction on the toolbar after createGUI. Both
250  // solutions work visually, but only modifying the XML ensures that the
251  // actions don't appear in "edit toolbars". #207296
252  const QStringList hideActions = plugin->invisibleToolbarActions();
253  //qCDebug(KONTACTINTERFACE_LOG) << "Hiding actions" << hideActions << "from" << pluginName << part;
254  QDomDocument doc = part->domDocument();
255  QDomElement docElem = doc.documentElement();
256  // 1. Iterate over containers
257  for (QDomElement containerElem = docElem.firstChildElement();
258  !containerElem.isNull(); containerElem = containerElem.nextSiblingElement()) {
259  if (QString::compare(containerElem.tagName(), QLatin1String("ToolBar"), Qt::CaseInsensitive) == 0) {
260  // 2. Iterate over actions in toolbars
261  QDomElement actionElem = containerElem.firstChildElement();
262  while (!actionElem.isNull()) {
263  QDomElement nextActionElem = actionElem.nextSiblingElement();
264  if (QString::compare(actionElem.tagName(), QLatin1String("Action"), Qt::CaseInsensitive) == 0) {
265  //qCDebug(KONTACTINTERFACE_LOG) << "Looking at action" << actionElem.attribute("name");
266  if (hideActions.contains(actionElem.attribute(QStringLiteral("name")))) {
267  //qCDebug(KONTACTINTERFACE_LOG) << "REMOVING";
268  containerElem.removeChild(actionElem);
269  }
270  }
271  actionElem = nextActionElem;
272  }
273  }
274  }
275 
276  // Possible optimization: we could do all the above and the writing below
277  // only when (newAppFile does not exist) or (version of domDocument > version of newAppFile) (*)
278  // This requires parsing newAppFile when it exists, though, and better use
279  // the fast kdeui code for that rather than a full QDomDocument.
280  // (*) or when invisibleToolbarActions() changes :)
281 
282  const QString newAppFile =
284  QFileInfo fileInfo(newAppFile);
285  QDir().mkpath(fileInfo.absolutePath());
286 
287  QFile file(newAppFile);
288  if (!file.open(QFile::WriteOnly)) {
289  qCWarning(KONTACTINTERFACE_LOG) << "error writing to" << newAppFile;
290  return;
291  }
292  file.write(doc.toString().toUtf8());
293  file.flush();
294 
295  setXmlFiles();
296 }
297 
298 void Plugin::Private::setXmlFiles()
299 {
300  if (pluginName.isEmpty()) {
301  return;
302  }
303  const QString newAppFile =
305  const QString localFile =
307  if (!localFile.isEmpty() && !newAppFile.isEmpty()) {
308  if (part->xmlFile() != newAppFile || part->localXMLFile() != localFile) {
309  part->replaceXMLFile(newAppFile, localFile);
310  }
311  }
312 }
313 //@endcond
314 
316 {
317  configUpdated();
318 }
319 
321 {
322  if (d->executableName.isEmpty()) {
323  return;
324  }
325 #ifdef Q_OS_WIN
326  activateWindowForProcess(d->executableName);
327 #else
328  KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(d->executableName);
329  job->start();
330 #endif
331 }
332 
334 {
335  Q_UNUSED(parent);
336  return nullptr;
337 }
338 
340 {
341  return d->hasPart;
342 }
343 
344 void Plugin::setShowInSideBar(bool hasPart)
345 {
346  d->hasPart = hasPart;
347 }
348 
349 bool Plugin::queryClose() const
350 {
351  return true;
352 }
353 
355 {
356  d->disabled = disabled;
357 }
358 
359 bool Plugin::disabled() const
360 {
361  return d->disabled;
362 }
363 
365 {
366 }
367 
368 void Plugin::virtual_hook(int, void *)
369 {
370  //BASE::virtual_hook( id, data );
371 }
372 
373 #include "moc_plugin.cpp"
374 
virtual void configUpdated()
This function is called whenever the config dialog has been closed successfully.
Definition: plugin.cpp:232
virtual bool showInSideBar() const
Returns whether the plugin provides a part that should be shown in the sidebar.
Definition: plugin.cpp:339
virtual void saveProperties(KConfigGroup &)
Session management: save properties.
Definition: plugin.cpp:210
QString writableLocation(QStandardPaths::StandardLocation type)
virtual bool canDecodeMimeData(const QMimeData *data) const
Returns whether the plugin can handle the drag object of the given mime type.
Definition: plugin.cpp:196
QString attribute(const QString &name, const QString &defValue) const const
void insertNewAction(QAction *action)
Inserts a custom "New" action.
Definition: plugin.cpp:171
bool flush()
void replaceXMLFile(const QString &xmlfile, const QString &localxmlfile, bool merge=false)
QString toString(int indent) const const
This file is part of the kpimutils library.
KParts::Part * part()
You can use this method if you need to access the current part.
Definition: plugin.cpp:140
void addClient(KXMLGUIClient *client)
QList< QAction * > newActions() const
Returns the list of custom "New" actions.
Definition: plugin.cpp:181
void setShowInSideBar(bool hasPart)
Set if the plugin provides a part that should be shown in the sidebar.
Definition: plugin.cpp:344
QString identifier() const
Returns the identifier of the plugin.
Definition: plugin.cpp:85
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QDomElement nextSiblingElement(const QString &tagName) const const
QString registerClient()
Registers the client at DBus and returns the dbus identifier.
Definition: plugin.cpp:153
virtual void shortcutChanged()
Definition: plugin.cpp:364
virtual const KAboutData aboutData()
Reimplement this method if you want to add your credits to the Kontact about dialog.
Definition: plugin.cpp:135
QDBusConnection sessionBus()
KXMLGUIFactory * factory() const
QDomElement documentElement() const const
virtual QString xmlFile() const
void start() override
void setDisabled(bool value)
Sets whether the plugin shall be disabled.
Definition: plugin.cpp:354
QString icon() const
Returns the icon name that is used for the plugin.
Definition: plugin.cpp:105
virtual void partLoaded(Plugin *plugin, KParts::Part *part)=0
void setIcon(const QString &icon)
Sets the icon name that is used for the plugin.
Definition: plugin.cpp:100
QString number(int n, int base)
Base class for summary widgets in Kontact.
Definition: summary.h:28
void insertSyncAction(QAction *action)
Inserts a custom "Sync" action.
Definition: plugin.cpp:176
virtual int weight() const
Return the weight of the plugin.
Definition: plugin.cpp:166
QList< QAction * > syncActions() const
Returns the list of custom "Sync" actions.
Definition: plugin.cpp:186
CaseInsensitive
void setObjectName(const QString &name)
bool isEmpty() const const
QString executableName() const
Returns the name of the executable (if existent).
Definition: plugin.cpp:115
QString title() const
Returns the localized title of the plugin.
Definition: plugin.cpp:95
qint64 applicationPid()
Core * core() const
Returns a pointer to the kontact core object.
Definition: plugin.cpp:214
virtual KParts::Part * createPart()=0
Reimplement and return the part here.
void setTitle(const QString &title)
Sets the localized title of the plugin.
Definition: plugin.cpp:90
virtual void readProperties(const KConfigGroup &)
Session management: read properties.
Definition: plugin.cpp:206
virtual bool open(QIODevice::OpenMode mode) override
virtual void processDropEvent(QDropEvent *)
Process drop event.
Definition: plugin.cpp:202
void virtual_hook(int id, void *data) override
Virtual hook for BC extension.
Definition: plugin.cpp:368
QDomNode removeChild(const QDomNode &oldChild)
bool isNull() const const
virtual QStringList invisibleToolbarActions() const
Returns a list of action names that shall be hidden in the main toolbar.
Definition: plugin.cpp:191
bool disabled() const
Returns whether the plugin is disabled.
Definition: plugin.cpp:359
~Plugin() override
Destroys the plugin.
Definition: plugin.cpp:74
QAction * action(const char *name) const
KParts::Part * createPart(const char *library)
Definition: core.cpp:59
void setIdentifier(const QString &identifier)
Sets the identifier of the plugin.
Definition: plugin.cpp:80
Plugin(Core *core, QObject *parent, const char *appName, const char *pluginName=nullptr)
Creates a new plugin.
Definition: plugin.cpp:61
QDomElement firstChildElement(const QString &tagName) const const
KParts::Part * loadPart()
Returns the loaded part.
Definition: plugin.cpp:130
virtual bool isRunningStandalone() const
Reimplement this method and return whether a standalone application is still running.
Definition: plugin.cpp:125
Base class for all Plugins in Kontact.
Definition: plugin.h:80
qint64 write(const char *data, qint64 maxSize)
void setPartLibraryName(const QByteArray &name)
Set name of library which contains the KPart used by this plugin.
Definition: plugin.cpp:120
virtual QDomDocument domDocument() const
The abstract interface that represents the Kontact core.
Definition: core.h:28
QString tagName() const const
void setExecutableName(const QString &name)
Sets the name of executable (if existent).
Definition: plugin.cpp:110
virtual Summary * createSummaryWidget(QWidget *parent)
Reimplement this method if you want to add a widget for your application to Kontact&#39;s summary page...
Definition: plugin.cpp:333
virtual void bringToForeground()
Reimplement this method if your application needs a different approach to be brought in the foregroun...
Definition: plugin.cpp:320
QString absolutePath() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
int compare(const QString &other, Qt::CaseSensitivity cs) const const
virtual bool queryClose() const
Reimplement this method if you want to add checks before closing the main kontact window...
Definition: plugin.cpp:349
void destroyed(QObject *obj)
virtual void select()
This function is called when the plugin is selected by the user before the widget of the KPart belong...
Definition: plugin.cpp:228
bool registerService(const QString &serviceName)
bool mkpath(const QString &dirPath) const const
void aboutToSelect()
Called by kontact when the plugin is selected by the user.
Definition: plugin.cpp:219
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue Sep 29 2020 23:20:57 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.