GUI: Add Python interface to create custom command

This commit is contained in:
Chris Hennes
2022-02-04 21:47:34 -06:00
parent 58a70cbbe5
commit c9240fbb4a
6 changed files with 119 additions and 31 deletions

View File

@@ -1769,6 +1769,29 @@ void CommandManager::removeCommand(Command* pCom)
}
}
std::string CommandManager::newMacroName() const
{
CommandManager& commandManager = Application::Instance->commandManager();
std::vector<Command*> macros = commandManager.getGroupCommands("Macros");
bool used = true;
int id = 0;
std::ostringstream name;
while (used) {
used = false;
name << "Std_Macro_" << id++;
for (const auto& macro : macros) {
if (name.str() == std::string(macro->getName())) {
used = true;
break;
}
}
}
return name.str();
}
void CommandManager::clearCommands()
{
for ( std::map<std::string,Command*>::iterator it = _sCommands.begin(); it != _sCommands.end(); ++it )

View File

@@ -883,6 +883,13 @@ public:
*/
const Command* checkAcceleratorForConflicts(const char* accel, const Command *ignore = nullptr) const;
/**
* Returns the first available command name for a new macro (e.g. starting from 1,
* examines the existing user preferences for Std_Macro_%1 and returns the lowest
* available numbered string).
*/
std::string newMacroName() const;
private:
/// Destroys all commands in the manager and empties the list.
void clearCommands();

View File

@@ -93,5 +93,29 @@ Usage: menuText, tooltipText, whatsThisText, statustipText, pixmapText, shortcut
getAction() -> list of QAction</UserDocu>
</Documentation>
</Methode>
<Methode Name="createCustomCommand" Static='true'>
<Documentation>
<UserDocu>Create a custom command for a macro
createCustomCommand(macrofile, menuText, tooltipText, whatsThisText, statustipText, pixmapText, shortcutText) -> str
--
Only the macrofile argument is required, and should be the name of the macro file. All other arguments are
passed on to the command creation routines if they are provided. All arguments except the first accept None.
Returns the name of the created custom command.
</UserDocu>
</Documentation>
</Methode>
<Methode Name="removeCustomCommand" Static='true'>
<Documentation>
<UserDocu>Remove the custom command if it exists
removeCustomCommand(name) -> bool
--
Given the name of a custom command, this removes that command. It is not an error
to remove a non-existent command, the function simply does nothing in that case.
Returns True if something was removed, or False if not.
</UserDocu>
</Documentation>
</Methode>
</PythonExport>
</GenerateModel>

View File

@@ -321,6 +321,69 @@ PyObject* CommandPy::getAction(PyObject *args)
}
}
PyObject* CommandPy::createCustomCommand(PyObject* args)
{
const char* macroFile = nullptr;
const char* menuTxt = nullptr;
const char* tooltipTxt = nullptr;
const char* whatsthisTxt = nullptr;
const char* statustipTxt = nullptr;
const char* pixmapTxt = nullptr;
const char* shortcutTxt = nullptr;
if (!PyArg_ParseTuple(args, "s|zzzzzz", &macroFile, &menuTxt, &tooltipTxt, &whatsthisTxt, &statustipTxt, &pixmapTxt, &shortcutTxt))
return nullptr;
auto name = Application::Instance->commandManager().newMacroName();
CommandManager& commandManager = Application::Instance->commandManager();
MacroCommand* macro = new MacroCommand(name.c_str(), false);
commandManager.addCommand(macro);
macro->setScriptName(macroFile);
if (menuTxt)
macro->setMenuText(menuTxt);
if (tooltipTxt)
macro->setToolTipText(tooltipTxt);
if (whatsthisTxt)
macro->setWhatsThis(whatsthisTxt);
if (statustipTxt)
macro->setStatusTip(statustipTxt);
if (pixmapTxt)
macro->setPixmap(pixmapTxt);
if (shortcutTxt)
macro->setAccel(shortcutTxt);
return PyUnicode_FromString(name.c_str());
}
PyObject* CommandPy::removeCustomCommand(PyObject* args)
{
const char* actionName = nullptr;
if (!PyArg_ParseTuple(args, "s", &actionName))
return nullptr;
CommandManager& commandManager = Application::Instance->commandManager();
std::vector<Command*> macros = commandManager.getGroupCommands("Macros");
auto action = std::find_if(macros.begin(), macros.end(), [actionName](const Command* c) {
return std::string(c->getName()) == std::string(actionName);
});
if (action != macros.end()) {
commandManager.removeCommand(*action);
return Py::new_reference_to(Py::Boolean(true));
}
else {
return Py::new_reference_to(Py::Boolean(false));
}
}
PyObject *CommandPy::getCustomAttributes(const char* /*attr*/) const
{
return 0;
@@ -330,3 +393,4 @@ int CommandPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/)
{
return 0;
}

View File

@@ -223,8 +223,8 @@ void DlgCustomActionsImp::on_buttonAddAction_clicked()
}
// search for the command in the manager
QByteArray actionName = newActionName().toLatin1();
CommandManager& rclMan = Application::Instance->commandManager();
QByteArray actionName = QString::fromStdString(rclMan.newMacroName()).toLatin1();
MacroCommand* macro = new MacroCommand(actionName, ui->actionMacros->itemData(ui->actionMacros->currentIndex()).toBool());
rclMan.addCommand( macro );
@@ -496,34 +496,6 @@ void DlgCustomActionsImp::on_buttonChoosePixmap_clicked()
}
}
QString DlgCustomActionsImp::newActionName()
{
int id = 0;
QString sName;
bool bUsed;
CommandManager& rclMan = Application::Instance->commandManager();
std::vector<Command*> aclCurMacros = rclMan.getGroupCommands("Macros");
do
{
bUsed = false;
sName = QString::fromLatin1("Std_Macro_%1").arg( id++ );
std::vector<Command*>::iterator it;
for ( it = aclCurMacros.begin(); it!= aclCurMacros.end(); ++it )
{
if (sName == QLatin1String((*it)->getName()))
{
bUsed = true;
break;
}
}
} while ( bUsed );
return sName;
}
void DlgCustomActionsImp::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {

View File

@@ -84,8 +84,6 @@ protected Q_SLOTS:
private:
/** Shows all actions and their pixmaps if available */
void showActions();
/** Name for the new created action */
QString newActionName();
private:
std::unique_ptr<Ui_DlgCustomActions> ui;