From c9240fbb4a58e199cc7a1a40749a4491943d6e8b Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Fri, 4 Feb 2022 21:47:34 -0600 Subject: [PATCH] GUI: Add Python interface to create custom command --- src/Gui/Command.cpp | 23 ++++++++++++++ src/Gui/Command.h | 7 +++++ src/Gui/CommandPy.xml | 24 +++++++++++++++ src/Gui/CommandPyImp.cpp | 64 +++++++++++++++++++++++++++++++++++++++ src/Gui/DlgActionsImp.cpp | 30 +----------------- src/Gui/DlgActionsImp.h | 2 -- 6 files changed, 119 insertions(+), 31 deletions(-) diff --git a/src/Gui/Command.cpp b/src/Gui/Command.cpp index 3f44c28d87..d2d206cc62 100644 --- a/src/Gui/Command.cpp +++ b/src/Gui/Command.cpp @@ -1769,6 +1769,29 @@ void CommandManager::removeCommand(Command* pCom) } } +std::string CommandManager::newMacroName() const +{ + CommandManager& commandManager = Application::Instance->commandManager(); + std::vector 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::iterator it = _sCommands.begin(); it != _sCommands.end(); ++it ) diff --git a/src/Gui/Command.h b/src/Gui/Command.h index 59ac11416e..ead59c13d4 100644 --- a/src/Gui/Command.h +++ b/src/Gui/Command.h @@ -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(); diff --git a/src/Gui/CommandPy.xml b/src/Gui/CommandPy.xml index cd8a188438..a67df25b8f 100644 --- a/src/Gui/CommandPy.xml +++ b/src/Gui/CommandPy.xml @@ -93,5 +93,29 @@ Usage: menuText, tooltipText, whatsThisText, statustipText, pixmapText, shortcut getAction() -> list of QAction + + + 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. + + + + + + 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. + + + diff --git a/src/Gui/CommandPyImp.cpp b/src/Gui/CommandPyImp.cpp index 853c19bf5d..b223a5c8d2 100644 --- a/src/Gui/CommandPyImp.cpp +++ b/src/Gui/CommandPyImp.cpp @@ -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", ¯oFile, &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 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; } + diff --git a/src/Gui/DlgActionsImp.cpp b/src/Gui/DlgActionsImp.cpp index 7fb740cdce..1228b4629c 100644 --- a/src/Gui/DlgActionsImp.cpp +++ b/src/Gui/DlgActionsImp.cpp @@ -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 aclCurMacros = rclMan.getGroupCommands("Macros"); - - do - { - bUsed = false; - sName = QString::fromLatin1("Std_Macro_%1").arg( id++ ); - - std::vector::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) { diff --git a/src/Gui/DlgActionsImp.h b/src/Gui/DlgActionsImp.h index af9b14ced4..2168841567 100644 --- a/src/Gui/DlgActionsImp.h +++ b/src/Gui/DlgActionsImp.h @@ -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;