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

0001 /*
0002     SPDX-FileCopyrightText: 2008 Andreas Pakulat <apaku@gmx.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "contextmenuextension.h"
0008 
0009 #include <QMap>
0010 
0011 #include <QMenu>
0012 #include <QAction>
0013 #include <QActionGroup>
0014 
0015 #include <KLocalizedString>
0016 
0017 namespace KDevelop
0018 {
0019 
0020 const QString ContextMenuExtension::FileGroup     = QStringLiteral("FileGroup");
0021 const QString ContextMenuExtension::RefactorGroup = QStringLiteral("RefactorGroup");
0022 const QString ContextMenuExtension::BuildGroup    = QStringLiteral("BuildGroup");
0023 const QString ContextMenuExtension::RunGroup      = QStringLiteral("RunGroup");
0024 const QString ContextMenuExtension::DebugGroup    = QStringLiteral("DebugGroup");
0025 const QString ContextMenuExtension::EditGroup     = QStringLiteral("EditGroup");
0026 const QString ContextMenuExtension::VcsGroup      = QStringLiteral("VcsGroup");
0027 const QString ContextMenuExtension::ProjectGroup  = QStringLiteral("ProjectGroup");
0028 const QString ContextMenuExtension::OpenEmbeddedGroup  = QStringLiteral("OpenEmbeddedGroup");
0029 const QString ContextMenuExtension::OpenExternalGroup  = QStringLiteral("OpenExternalGroup");
0030 const QString ContextMenuExtension::AnalyzeFileGroup = QStringLiteral("AnalyzeFileGroup");
0031 const QString ContextMenuExtension::AnalyzeProjectGroup = QStringLiteral("AnalyzeProjectGroup");
0032 const QString ContextMenuExtension::NavigationGroup = QStringLiteral("NavigationGroup");
0033 const QString ContextMenuExtension::ExtensionGroup  = QStringLiteral("ExtensionGroup");
0034 
0035 class ContextMenuExtensionPrivate
0036 {
0037 public:
0038     QMap<QString,QList<QAction*> > extensions;
0039 };
0040 
0041 ContextMenuExtension::ContextMenuExtension()
0042     : d_ptr(new ContextMenuExtensionPrivate)
0043 {
0044 }
0045 
0046 ContextMenuExtension::~ContextMenuExtension() = default;
0047 
0048 
0049 ContextMenuExtension::ContextMenuExtension( const ContextMenuExtension& rhs )
0050     : d_ptr(new ContextMenuExtensionPrivate)
0051 {
0052     Q_D(ContextMenuExtension);
0053 
0054     d->extensions = rhs.d_func()->extensions;
0055 }
0056 
0057 ContextMenuExtension& ContextMenuExtension::operator=( const ContextMenuExtension& rhs )
0058 {
0059     Q_D(ContextMenuExtension);
0060 
0061     if( this == &rhs )
0062         return *this;
0063 
0064     d->extensions = rhs.d_func()->extensions;
0065     return *this;
0066 }
0067 
0068 QList<QAction*> ContextMenuExtension::actions( const QString& group ) const
0069 {
0070     Q_D(const ContextMenuExtension);
0071 
0072     return d->extensions.value( group, QList<QAction*>() );
0073 }
0074 
0075 void ContextMenuExtension::addAction( const QString& group, QAction* action )
0076 {
0077     Q_D(ContextMenuExtension);
0078 
0079     auto actionGroupIt = d->extensions.find(group);
0080     if (actionGroupIt == d->extensions.end()) {
0081         d->extensions.insert( group, QList<QAction*>() << action );
0082     } else
0083     {
0084         actionGroupIt->append(action);
0085     }
0086 }
0087 
0088 static
0089 void populateMenuWithGroup(
0090     QMenu* menu,
0091     const QList<ContextMenuExtension>& extensions,
0092     const QString& groupName,
0093     const QString& groupDisplayName = QString(),
0094     const QString& groupIconName = QString(),
0095     bool forceAddMenu = false,
0096     bool addSeparator = true)
0097 {
0098     QList<QAction*> groupActions;
0099     for (const ContextMenuExtension& extension : extensions) {
0100         groupActions += extension.actions(groupName);
0101     }
0102     // remove NULL QActions, if any. Those can end up in groupActions if plugins
0103     // like the debugger plugins are not loaded.
0104     groupActions.removeAll(nullptr);
0105 
0106     if (groupActions.isEmpty()) {
0107         return;
0108     }
0109 
0110     QMenu* groupMenu = menu;
0111     if ((groupActions.count() > 1 && !groupDisplayName.isEmpty()) ||
0112         (!groupDisplayName.isEmpty() && forceAddMenu)) {
0113         groupMenu = menu->addMenu(groupDisplayName);
0114         if (!groupIconName.isEmpty()) {
0115             groupMenu->setIcon(QIcon::fromTheme(groupIconName));
0116         }
0117     }
0118 
0119     for (QAction* action : qAsConst(groupActions)) {
0120         groupMenu->addAction(action);
0121     }
0122 
0123     if (addSeparator) {
0124         menu->addSeparator();
0125     }
0126 }
0127 
0128 void ContextMenuExtension::populateMenu(QMenu* menu, const QList<ContextMenuExtension>& extensions)
0129 {
0130     populateMenuWithGroup(menu, extensions, BuildGroup);
0131     populateMenuWithGroup(menu, extensions, FileGroup);
0132     populateMenuWithGroup(menu, extensions, EditGroup);
0133     populateMenuWithGroup(menu, extensions, DebugGroup, i18nc("@title:menu", "Debug"));
0134     populateMenuWithGroup(menu, extensions, RefactorGroup, i18nc("@title:menu", "Refactor"));
0135     populateMenuWithGroup(menu, extensions, NavigationGroup);
0136     populateMenuWithGroup(menu, extensions, AnalyzeFileGroup, i18nc("@title:menu", "Analyze Current File With"), QStringLiteral("dialog-ok"), true, false);
0137     populateMenuWithGroup(menu, extensions, AnalyzeProjectGroup, i18nc("@title:menu", "Analyze Current Project With"), QStringLiteral("dialog-ok"), true);
0138     populateMenuWithGroup(menu, extensions, VcsGroup);
0139     populateMenuWithGroup(menu, extensions, ExtensionGroup);
0140 }
0141 
0142 }