File indexing completed on 2024-04-28 04:36:30

0001 /*
0002     SPDX-FileCopyrightText: 2002 Simon Hausmann <hausmann@kde.org>
0003     SPDX-FileCopyrightText: 2002 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
0004     SPDX-FileCopyrightText: 2002 Harald Fernengel <harry@kdevelop.org>
0005     SPDX-FileCopyrightText: 2002 Falk Brettschneider <falkbr@kdevelop.org>
0006     SPDX-FileCopyrightText: 2003 Julian Rockey <linux@jrockey.com>
0007     SPDX-FileCopyrightText: 2003 Roberto Raggi <roberto@kdevelop.org>
0008     SPDX-FileCopyrightText: 2003 Jens Dagerbo <jens.dagerbo@swipnet.se>
0009     SPDX-FileCopyrightText: 2003 Mario Scalas <mario.scalas@libero.it>
0010     SPDX-FileCopyrightText: 2003-2004, 2007 Alexander Dymo <adymo@kdevelop.org>
0011     SPDX-FileCopyrightText: 2006 Adam Treat <treat@kde.org>
0012     SPDX-FileCopyrightText: 2007 Andreas Pakulat <apaku@gmx.de>
0013 
0014     SPDX-License-Identifier: LGPL-2.0-or-later
0015 */
0016 
0017 #include "iplugin.h"
0018 
0019 #include <KActionCollection>
0020 #include <KMainWindow>
0021 #include <KXmlGuiWindow>
0022 #include <KXMLGUIFactory>
0023 
0024 #include "icore.h"
0025 #include "iplugincontroller.h"
0026 #include "iprojectcontroller.h"
0027 #include "iproject.h"
0028 #include "contextmenuextension.h"
0029 
0030 namespace KDevelop
0031 {
0032 
0033 class IPluginPrivate
0034 {
0035 public:
0036     explicit IPluginPrivate(IPlugin *q)
0037         : q(q)
0038     {}
0039 
0040     ~IPluginPrivate()
0041     {
0042     }
0043 
0044     void guiClientAdded(KXMLGUIClient *client)
0045     {
0046         if (client != q)
0047             return;
0048 
0049         q->initializeGuiState();
0050         updateState();
0051     }
0052 
0053     void updateState()
0054     {
0055         const int projectCount =
0056             ICore::self()->projectController()->projectCount();
0057 
0058         IPlugin::ReverseStateChange reverse = IPlugin::StateNoReverse;
0059         if (! projectCount)
0060             reverse = IPlugin::StateReverse;
0061 
0062         q->stateChanged(QStringLiteral("has_project"), reverse);
0063     }
0064 
0065     IPlugin *q;
0066     ICore *core;
0067     QString m_errorDescription;
0068 };
0069 
0070 IPlugin::IPlugin( const QString &componentName, QObject *parent )
0071     : QObject(parent)
0072     , KXMLGUIClient()
0073     , d_ptr(new IPluginPrivate(this))
0074 {
0075     Q_D(IPlugin);
0076 
0077     // The following cast is safe, there's no component in KDevPlatform that
0078     // creates plugins except the plugincontroller. The controller passes
0079     // Core::self() as parent to KServiceTypeTrader::createInstanceFromQuery
0080     // so we know the parent is always a Core* pointer.
0081     // This is the only way to pass the Core pointer to the plugin during its
0082     // creation so plugins have access to ICore during their creation.
0083     Q_ASSERT(qobject_cast<KDevelop::ICore*>(parent));
0084     d->core = static_cast<KDevelop::ICore*>(parent);
0085 
0086     auto metaData = core()->pluginController()->infoForPluginId(componentName);
0087     setComponentName(componentName, metaData.name());
0088 
0089     auto clientAdded = [this] (KXMLGUIClient* client) {
0090         Q_D(IPlugin);
0091         d->guiClientAdded(client);
0092     };
0093     const auto mainWindows = KMainWindow::memberList();
0094     for (KMainWindow* mw : mainWindows) {
0095         auto* guiWindow = qobject_cast<KXmlGuiWindow*>(mw);
0096         if (! guiWindow)
0097             continue;
0098 
0099         connect(guiWindow->guiFactory(), &KXMLGUIFactory::clientAdded,
0100                 this, clientAdded);
0101     }
0102 
0103     auto updateState = [this] {
0104         Q_D(IPlugin);
0105         d->updateState();
0106     };
0107     connect(ICore::self()->projectController(), &IProjectController::projectOpened,
0108             this, updateState);
0109     connect(ICore::self()->projectController(), &IProjectController::projectClosed,
0110             this, updateState);
0111 }
0112 
0113 IPlugin::~IPlugin() = default;
0114 
0115 void IPlugin::unload()
0116 {
0117 }
0118 
0119 ICore *IPlugin::core() const
0120 {
0121     Q_D(const IPlugin);
0122 
0123     return d->core;
0124 }
0125 
0126 }
0127 
0128 KDevelop::ContextMenuExtension KDevelop::IPlugin::contextMenuExtension(KDevelop::Context* context, QWidget* parent)
0129 {
0130     Q_UNUSED(context);
0131     Q_UNUSED(parent);
0132     return KDevelop::ContextMenuExtension();
0133 }
0134 
0135 void KDevelop::IPlugin::initializeGuiState()
0136 { }
0137 
0138 class CustomXmlGUIClient : public KXMLGUIClient
0139 {
0140 public:
0141     explicit CustomXmlGUIClient(const KDevelop::IPlugin* plugin)
0142     {
0143         // TODO KF5: Get rid off this
0144         setComponentName(plugin->componentName(), plugin->actionCollection()->componentDisplayName());
0145     }
0146     using KXMLGUIClient::setXMLFile;
0147 };
0148 
0149 KXMLGUIClient* KDevelop::IPlugin::createGUIForMainWindow(Sublime::MainWindow* window)
0150 {
0151     QScopedPointer<CustomXmlGUIClient> ret(new CustomXmlGUIClient(this));
0152 
0153     QString file;
0154     createActionsForMainWindow(window, file, *ret->actionCollection());
0155     if (ret->actionCollection()->isEmpty()) {
0156         return nullptr;
0157     }
0158 
0159     Q_ASSERT(!file.isEmpty()); //A file must have been set
0160     ret->setXMLFile(file);
0161     return ret.take();
0162 }
0163 
0164 void KDevelop::IPlugin::createActionsForMainWindow( Sublime::MainWindow* /*window*/, QString& /*xmlFile*/, KActionCollection& /*actions*/ )
0165 {
0166 }
0167 
0168 bool KDevelop::IPlugin::hasError() const
0169 {
0170     Q_D(const IPlugin);
0171 
0172     return !d->m_errorDescription.isEmpty();
0173 }
0174 
0175 void KDevelop::IPlugin::setErrorDescription(const QString& description)
0176 {
0177     Q_D(IPlugin);
0178 
0179     d->m_errorDescription = description;
0180 }
0181 
0182 
0183 QString KDevelop::IPlugin::errorDescription() const
0184 {
0185     Q_D(const IPlugin);
0186 
0187     return d->m_errorDescription;
0188 }
0189 
0190 int KDevelop::IPlugin::configPages() const
0191 {
0192     return 0;
0193 }
0194 
0195 KDevelop::ConfigPage* KDevelop::IPlugin::configPage (int, QWidget*)
0196 {
0197     return nullptr;
0198 }
0199 
0200 int KDevelop::IPlugin::perProjectConfigPages() const
0201 {
0202     return 0;
0203 }
0204 
0205 KDevelop::ConfigPage* KDevelop::IPlugin::perProjectConfigPage(int, const ProjectConfigOptions&, QWidget*)
0206 {
0207     return nullptr;
0208 }
0209 #include "moc_iplugin.cpp"