KontactInterface

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

KDE's Doxygen guidelines are available online.