Add api for context menu extensions (#2029)

This commit is contained in:
yossizap 2020-01-24 11:49:52 +02:00 committed by Florian Märkl
parent e3f7036de7
commit 409102afa7
9 changed files with 87 additions and 6 deletions

View File

@ -6,7 +6,9 @@
<primitive-type name="bool"/>
<object-type name="CutterCore" />
<object-type name="CutterCore">
<enum-type name="ContextMenuType" />
</object-type>
<object-type name="Configuration" />
<object-type name="MainWindow" >
<enum-type name="MenuType" />

View File

@ -207,6 +207,13 @@ void CutterCore::initialize()
// Initialize Async tasks manager
asyncTaskManager = new AsyncTaskManager(this);
// Initialize context menu extensions for plugins
disassemblyContextMenuExtensions = new QMenu(tr("Plugins"));
disassemblyContextMenuExtensions->menuAction()->setVisible(false);
disassemblyContextMenuExtensions->setEnabled(false);
addressableContextMenuExtensions = new QMenu(tr("Plugins"));
addressableContextMenuExtensions->menuAction()->setVisible(false);
}
CutterCore::~CutterCore()
@ -2232,6 +2239,39 @@ QStringList CutterCore::getAnalPluginNames()
return ret;
}
QMenu *CutterCore::getContextMenuExtensions(ContextMenuType type)
{
switch (type) {
case ContextMenuType::Disassembly:
return disassemblyContextMenuExtensions;
case ContextMenuType::Addressable:
return addressableContextMenuExtensions;
default:
return nullptr;
}
}
void CutterCore::addContextMenuExtensionAction(ContextMenuType type, QAction *action)
{
QMenu *menu = getContextMenuExtensions(type);
if (menu) {
// The submenu should be invisible and disabled while it's empty
if (menu->isEmpty()) {
menu->menuAction()->setVisible(true);
menu->setEnabled(true);
}
menu->addAction(action);
}
}
void CutterCore::addContextMenuExtensionSeparator(ContextMenuType type)
{
QMenu *menu = getContextMenuExtensions(type);
if (menu) {
menu->addSeparator();
}
}
QStringList CutterCore::getProjectNames()
{
CORE_LOCK();

View File

@ -6,6 +6,7 @@
#include "common/BasicInstructionHighlighter.h"
#include <QMap>
#include <QMenu>
#include <QDebug>
#include <QObject>
#include <QStringList>
@ -419,6 +420,17 @@ public:
QStringList getAsmPluginNames();
QStringList getAnalPluginNames();
/* Context menu plugins */
enum class ContextMenuType { Disassembly, Addressable };
/**
* @brief Fetches the pointer to a context menu extension of type
* @param type - the type of the context menu
* @return plugins submenu of the selected context menu
*/
QMenu *getContextMenuExtensions(ContextMenuType type);
void addContextMenuExtensionAction(ContextMenuType type, QAction *action);
void addContextMenuExtensionSeparator(ContextMenuType type);
/* Projects */
QStringList getProjectNames();
void openProject(const QString &name);
@ -628,6 +640,9 @@ private:
QSharedPointer<R2Task> debugTask;
R2TaskDialog *debugTaskDialog;
QMenu *disassemblyContextMenuExtensions = nullptr;
QMenu *addressableContextMenuExtensions = nullptr;
};
class RCoreLocked

View File

@ -408,11 +408,6 @@ void MainWindow::addExtraWidget(CutterDockWidget *extraDock)
restoreExtraDock.restoreWidth(extraDock->widget());
}
/**
* @brief Getter for MainWindow's different menus
* @param type The type which represents the desired menu
* @return The requested menu or nullptr if "type" is invalid
**/
QMenu *MainWindow::getMenuByType(MenuType type)
{
switch (type) {

View File

@ -101,6 +101,11 @@ public:
void addPluginDockWidget(QDockWidget *dockWidget, QAction *action);
enum class MenuType { File, Edit, View, Windows, Debug, Help, Plugins };
/**
* @brief Getter for MainWindow's different menus
* @param type The type which represents the desired menu
* @return The requested menu or nullptr if "type" is invalid
*/
QMenu *getMenuByType(MenuType type);
void addMenuFileAction(QAction *action);

View File

@ -39,7 +39,13 @@ AddressableItemContextMenu::AddressableItemContextMenu(QWidget *parent, MainWind
addSeparator();
addAction(&actionAddcomment);
addSeparator();
pluginMenu = Core()->getContextMenuExtensions(CutterCore::ContextMenuType::Addressable);
addMenu(pluginMenu);
addSeparator();
setHasTarget(hasTarget);
connect(this, &QMenu::aboutToShow, this, &AddressableItemContextMenu::aboutToShowSlot);
}
@ -98,6 +104,10 @@ void AddressableItemContextMenu::aboutToShowSlot()
actionShowInMenu.menu()->deleteLater();
}
actionShowInMenu.setMenu(mainWindow->createShowInMenu(this, offset));
for (QAction *pluginAction : pluginMenu->actions()) {
pluginAction->setData(QVariant::fromValue(offset));
}
}
void AddressableItemContextMenu::setHasTarget(bool hasTarget)

View File

@ -31,6 +31,7 @@ private:
virtual void aboutToShowSlot();
QMenu *pluginMenu;
MainWindow *mainWindow;
RVA offset;

View File

@ -153,6 +153,13 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
addDebugMenu();
addSeparator();
pluginMenu = Core()->getContextMenuExtensions(CutterCore::ContextMenuType::Disassembly);
addMenu(pluginMenu);
addSeparator();
connect(this, &DisassemblyContextMenu::aboutToShow,
this, &DisassemblyContextMenu::aboutToShowSlot);
}
@ -515,6 +522,10 @@ void DisassemblyContextMenu::aboutToShowSlot()
tr("Edit breakpoint") : tr("Advanced breakpoint"));
QString progCounterName = Core()->getRegisterName("PC").toUpper();
actionSetPC.setText("Set " + progCounterName + " here");
for (QAction *pluginAction : pluginMenu->actions()) {
pluginAction->setData(QVariant::fromValue(offset));
}
}
QKeySequence DisassemblyContextMenu::getCopySequence() const

View File

@ -161,6 +161,8 @@ private:
QAction actionAdvancedBreakpoint;
QAction actionSetPC;
QMenu *pluginMenu;
QAction actionSetToCode;
QAction actionSetAsStringAuto;