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"/> <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="Configuration" />
<object-type name="MainWindow" > <object-type name="MainWindow" >
<enum-type name="MenuType" /> <enum-type name="MenuType" />

View File

@ -207,6 +207,13 @@ void CutterCore::initialize()
// Initialize Async tasks manager // Initialize Async tasks manager
asyncTaskManager = new AsyncTaskManager(this); 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() CutterCore::~CutterCore()
@ -2232,6 +2239,39 @@ QStringList CutterCore::getAnalPluginNames()
return ret; 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() QStringList CutterCore::getProjectNames()
{ {
CORE_LOCK(); CORE_LOCK();

View File

@ -6,6 +6,7 @@
#include "common/BasicInstructionHighlighter.h" #include "common/BasicInstructionHighlighter.h"
#include <QMap> #include <QMap>
#include <QMenu>
#include <QDebug> #include <QDebug>
#include <QObject> #include <QObject>
#include <QStringList> #include <QStringList>
@ -419,6 +420,17 @@ public:
QStringList getAsmPluginNames(); QStringList getAsmPluginNames();
QStringList getAnalPluginNames(); 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 */ /* Projects */
QStringList getProjectNames(); QStringList getProjectNames();
void openProject(const QString &name); void openProject(const QString &name);
@ -628,6 +640,9 @@ private:
QSharedPointer<R2Task> debugTask; QSharedPointer<R2Task> debugTask;
R2TaskDialog *debugTaskDialog; R2TaskDialog *debugTaskDialog;
QMenu *disassemblyContextMenuExtensions = nullptr;
QMenu *addressableContextMenuExtensions = nullptr;
}; };
class RCoreLocked class RCoreLocked

View File

@ -408,11 +408,6 @@ void MainWindow::addExtraWidget(CutterDockWidget *extraDock)
restoreExtraDock.restoreWidth(extraDock->widget()); 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) QMenu *MainWindow::getMenuByType(MenuType type)
{ {
switch (type) { switch (type) {

View File

@ -101,6 +101,11 @@ public:
void addPluginDockWidget(QDockWidget *dockWidget, QAction *action); void addPluginDockWidget(QDockWidget *dockWidget, QAction *action);
enum class MenuType { File, Edit, View, Windows, Debug, Help, Plugins }; 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); QMenu *getMenuByType(MenuType type);
void addMenuFileAction(QAction *action); void addMenuFileAction(QAction *action);

View File

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

View File

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

View File

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

View File

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