diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index a68a75b82b..4c30b6ac31 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -125,6 +125,7 @@ #include "ViewProviderLink.h" #include "LinkViewPy.h" #include "AxisOriginPy.h" +#include "CommandPy.h" #include "Language/Translator.h" #include "TaskView/TaskView.h" @@ -472,6 +473,7 @@ Application::Application(bool GUIenabled) Base::Interpreter().addType(&LinkViewPy::Type,module,"LinkView"); Base::Interpreter().addType(&AxisOriginPy::Type,module,"AxisOrigin"); + Base::Interpreter().addType(&CommandPy::Type,module, "Command"); } Base::PyGILStateLocker lock; diff --git a/src/Gui/Application.h b/src/Gui/Application.h index ae30bdc7c2..91b2909afc 100644 --- a/src/Gui/Application.h +++ b/src/Gui/Application.h @@ -258,12 +258,6 @@ public: static PyObject* sRunCommand (PyObject *self,PyObject *args); static PyObject* sAddCommand (PyObject *self,PyObject *args); - static PyObject* sGetCommandInfo (PyObject *self,PyObject *args); - static PyObject* sListCommands (PyObject *self,PyObject *args); - static PyObject* sGetCommandShortcut (PyObject *self,PyObject *args); - static PyObject* sSetCommandShortcut (PyObject *self,PyObject *args); - static PyObject* sIsCommandActive (PyObject *self,PyObject *args); - static PyObject* sUpdateCommands (PyObject *self,PyObject *args); static PyObject* sHide (PyObject *self,PyObject *args); // deprecated static PyObject* sShow (PyObject *self,PyObject *args); // deprecated diff --git a/src/Gui/ApplicationPy.cpp b/src/Gui/ApplicationPy.cpp index dd80a3ede9..d22bc29200 100644 --- a/src/Gui/ApplicationPy.cpp +++ b/src/Gui/ApplicationPy.cpp @@ -139,24 +139,6 @@ PyMethodDef Application::Methods[] = { {"runCommand", (PyCFunction) Application::sRunCommand, METH_VARARGS, "runCommand(string) -> None\n\n" "Run command with name"}, - {"isCommandActive", (PyCFunction) Application::sIsCommandActive, METH_VARARGS, - "isCommandActive(string) -> Bool\n\n" - "Test if a command is active"}, - {"listCommands", (PyCFunction) Application::sListCommands, METH_VARARGS, - "listCommands() -> list of strings\n\n" - "Returns a list of all commands known to FreeCAD."}, - {"getCommandInfo", (PyCFunction) Application::sGetCommandInfo, METH_VARARGS, - "getCommandInfo(string) -> list of strings\n\n" - "Usage: menuText,tooltipText,whatsThisText,statustipText,pixmapText,shortcutText = getCommandInfo(string)"}, - {"getCommandShortcut", (PyCFunction) Application::sGetCommandShortcut, METH_VARARGS, - "getCommandShortcut(string) -> string\n\n" - "Returns string representing shortcut key accelerator for command."}, - {"setCommandShortcut", (PyCFunction) Application::sSetCommandShortcut, METH_VARARGS, - "setCommandShortcut(string,string) > bool\n\n" - "Sets shortcut for given command, returns bool True for success"}, - {"updateCommands", (PyCFunction) Application::sUpdateCommands, METH_VARARGS, - "updateCommands\n\n" - "Update all command active status"}, {"SendMsgToActiveView", (PyCFunction) Application::sSendActiveView, METH_VARARGS, "deprecated -- use class View"}, {"sendMsgToFocusView", (PyCFunction) Application::sSendFocusView, METH_VARARGS, @@ -1258,159 +1240,6 @@ PyObject* Application::sRunCommand(PyObject * /*self*/, PyObject *args) } } -PyObject* Application::sIsCommandActive(PyObject * /*self*/, PyObject *args) -{ - char* pName; - if (!PyArg_ParseTuple(args, "s", &pName)) - return NULL; - - Command* cmd = Application::Instance->commandManager().getCommandByName(pName); - if (!cmd) { - PyErr_Format(Base::BaseExceptionFreeCADError, "No such command '%s'", pName); - return 0; - } - PY_TRY { - return Py::new_reference_to(Py::Boolean(cmd->isActive())); - }PY_CATCH; -} - -PyObject* Application::sUpdateCommands(PyObject * /*self*/, PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) - return NULL; - - getMainWindow()->updateActions(); - Py_Return; -} - -PyObject* Application::sGetCommandShortcut(PyObject * /*self*/, PyObject *args) -{ - char* pName; - if (!PyArg_ParseTuple(args, "s", &pName)) - return NULL; - - Command* cmd = Application::Instance->commandManager().getCommandByName(pName); - if (cmd) { - -#if PY_MAJOR_VERSION >= 3 - PyObject* str = PyUnicode_FromString(cmd->getAction() ? cmd->getAction()->shortcut().toString().toStdString().c_str() : ""); -#else - PyObject* str = PyString_FromString(cmd->getAction() ? cmd->getAction()->shortcut().toString().toStdString().c_str() : ""); -#endif - return str; - } - else { - PyErr_Format(Base::BaseExceptionFreeCADError, "No such command '%s'", pName); - return 0; - } -} - -PyObject* Application::sSetCommandShortcut(PyObject * /*self*/, PyObject *args) -{ - char* pName; - char* pShortcut; - if (!PyArg_ParseTuple(args, "ss", &pName, &pShortcut)) - return NULL; - - Command* cmd = Application::Instance->commandManager().getCommandByName(pName); - if (cmd) { - Action* action = cmd->getAction(); - if (action){ - QKeySequence shortcut = QString::fromLatin1(pShortcut); - QString nativeText = shortcut.toString(QKeySequence::NativeText); - action->setShortcut(nativeText); - bool success = action->shortcut() == nativeText; - /** - * avoid cluttering parameters unnecessarily by saving only - * when new shortcut is not the default shortcut - * remove spaces to handle cases such as shortcut = "C,L" or "C, L" - */ - QString default_shortcut = QString::fromLatin1(cmd->getAccel()); - QString spc = QString::fromLatin1(" "); - ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("Shortcut"); - if (success && default_shortcut.remove(spc).toUpper() != nativeText.remove(spc).toUpper()){ - hGrp->SetASCII(pName, pShortcut); - } else { - hGrp->RemoveASCII(pName); - } - return Py::new_reference_to(Py::Boolean(success)); - } else { - return Py::new_reference_to(Py::Boolean(false)); - } - } - else { - PyErr_Format(Base::BaseExceptionFreeCADError, "No such command '%s'", pName); - return NULL; - } -} - - -PyObject* Application::sGetCommandInfo(PyObject * /*self*/, PyObject *args) -{ - char* pName; - if (!PyArg_ParseTuple(args, "s", &pName)) - return NULL; - Command* cmd = Application::Instance->commandManager().getCommandByName(pName); - if (cmd) { - Action* action = cmd->getAction(); - PyObject* pyList = PyList_New(6); - const char* menuTxt = cmd->getMenuText(); - const char* tooltipTxt = cmd->getToolTipText(); - const char* whatsThisTxt = cmd->getWhatsThis(); - const char* statustipTxt = cmd->getStatusTip(); - const char* pixMapTxt = cmd->getPixmap(); - std::string shortcutTxt = ""; - if(action) - shortcutTxt = action->shortcut().toString().toStdString(); - -#if PY_MAJOR_VERSION >= 3 - PyObject* strMenuTxt = PyUnicode_FromString(menuTxt ? menuTxt : ""); - PyObject* strTooltipTxt = PyUnicode_FromString(tooltipTxt ? tooltipTxt : ""); - PyObject* strWhatsThisTxt = PyUnicode_FromString(whatsThisTxt ? whatsThisTxt : ""); - PyObject* strStatustipTxt = PyUnicode_FromString(statustipTxt ? statustipTxt : ""); - PyObject* strPixMapTxt = PyUnicode_FromString(pixMapTxt ? pixMapTxt : ""); - PyObject* strShortcutTxt = PyUnicode_FromString(!shortcutTxt.empty() ? shortcutTxt.c_str() : ""); -#else - PyObject* strMenuTxt = PyString_FromString(menuTxt ? menuTxt : ""); - PyObject* strTooltipTxt = PyString_FromString(tooltipTxt ? tooltipTxt : ""); - PyObject* strWhatsThisTxt = PyString_FromString(whatsThisTxt ? whatsThisTxt : ""); - PyObject* strStatustipTxt = PyString_FromString(statustipTxt ? statustipTxt : ""); - PyObject* strPixMapTxt = PyString_FromString(pixMapTxt ? pixMapTxt : ""); - PyObject* strShortcutTxt = PyString_FromString(!shortcutTxt.empty() ? shortcutTxt.c_str() : ""); -#endif - PyList_SetItem(pyList, 0, strMenuTxt); - PyList_SetItem(pyList, 1, strTooltipTxt); - PyList_SetItem(pyList, 2, strWhatsThisTxt); - PyList_SetItem(pyList, 3, strStatustipTxt); - PyList_SetItem(pyList, 4, strPixMapTxt); - PyList_SetItem(pyList, 5, strShortcutTxt); - return pyList; - } - else { - PyErr_Format(Base::BaseExceptionFreeCADError, "No such command '%s'", pName); - return 0; - } -} - -PyObject* Application::sListCommands(PyObject * /*self*/, PyObject *args) -{ - if (!PyArg_ParseTuple(args, "")) - return NULL; - - std::vector cmds = Application::Instance->commandManager().getAllCommands(); - PyObject* pyList = PyList_New(cmds.size()); - int i=0; - for ( std::vector::iterator it = cmds.begin(); it != cmds.end(); ++it ) { -#if PY_MAJOR_VERSION >= 3 - PyObject* str = PyUnicode_FromString((*it)->getName()); -#else - PyObject* str = PyString_FromString((*it)->getName()); -#endif - PyList_SetItem(pyList, i++, str); - } - return pyList; -} - PyObject* Application::sDoCommand(PyObject * /*self*/, PyObject *args) { char *sCmd=0; diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index b4fa291591..e680213efb 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -229,6 +229,7 @@ generate_from_xml(SelectionObjectPy) generate_from_xml(LinkViewPy) generate_from_xml(ViewProviderLinkPy) generate_from_xml(AxisOriginPy) +generate_from_xml(CommandPy) generate_from_py(FreeCADGuiInit GuiInitScript.h) @@ -243,6 +244,7 @@ SET(FreeCADGui_XML_SRCS LinkViewPy.xml ViewProviderLinkPy.xml AxisOriginPy.xml + CommandPy.xml ) SOURCE_GROUP("XML" FILES ${FreeCADApp_XML_SRCS}) @@ -498,6 +500,7 @@ SET(Command_CPP_SRCS CommandView.cpp CommandStructure.cpp CommandLink.cpp + CommandPyImp.cpp ) SET(Command_SRCS ${Command_CPP_SRCS} diff --git a/src/Gui/CommandPy.xml b/src/Gui/CommandPy.xml new file mode 100644 index 0000000000..44758591ca --- /dev/null +++ b/src/Gui/CommandPy.xml @@ -0,0 +1,81 @@ + + + + + + FreeCAD Python wrapper of Command functions + + + + get(string) -> Command + +Get a given command by name or None if it doesn't exist. + + + + + + update() -> None + +Update active status of all commands. + + + + + + listAll() -> list of strings + +Returns the name of all commands. + + + + + + run() -> None + +Runs the given command. + + + + + + isActive() -> bool + +Returns True if the command is active, False otherwise. + + + + + + getShortcut() -> string + +Returns string representing shortcut key accelerator for command. + + + + + + setShortcut(string) -> bool + +Sets shortcut for given command, returns bool True for success. + + + + + + getInfo() -> list of strings + +Usage: menuText, tooltipText, whatsThisText, statustipText, pixmapText, shortcutText. + + + + + diff --git a/src/Gui/CommandPyImp.cpp b/src/Gui/CommandPyImp.cpp new file mode 100644 index 0000000000..2643aa1f73 --- /dev/null +++ b/src/Gui/CommandPyImp.cpp @@ -0,0 +1,241 @@ +/*************************************************************************** + * Copyright (c) 2020 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + +#include "PreCompiled.h" + +#include "Command.h" +#include "Action.h" +#include "Application.h" +#include "MainWindow.h" +#include "Selection.h" +#include "Window.h" + +// inclusion of the generated files (generated out of AreaPy.xml) +#include "CommandPy.h" +#include "CommandPy.cpp" + + +// returns a string which represents the object e.g. when printed in python +std::string CommandPy::representation(void) const +{ + return std::string(""); +} + +PyObject* CommandPy::get(PyObject *args) +{ + char* pName; + if (!PyArg_ParseTuple(args, "s", &pName)) + return nullptr; + + Command* cmd = Application::Instance->commandManager().getCommandByName(pName); + if (cmd) { + CommandPy* cmdPy = new CommandPy(cmd); + return cmdPy; + } + + Py_Return; +} + +PyObject* CommandPy::update(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + getMainWindow()->updateActions(); + Py_Return; +} + +PyObject* CommandPy::listAll(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + std::vector cmds = Application::Instance->commandManager().getAllCommands(); + PyObject* pyList = PyList_New(cmds.size()); + int i=0; + for ( std::vector::iterator it = cmds.begin(); it != cmds.end(); ++it ) { +#if PY_MAJOR_VERSION >= 3 + PyObject* str = PyUnicode_FromString((*it)->getName()); +#else + PyObject* str = PyString_FromString((*it)->getName()); +#endif + PyList_SetItem(pyList, i++, str); + } + return pyList; +} + +PyObject* CommandPy::run(PyObject *args) +{ + int item = 0; + if (!PyArg_ParseTuple(args, "|i", &item)) + return nullptr; + + Gui::Command::LogDisabler d1; + Gui::SelectionLogDisabler d2; + + Command* cmd = this->getCommandPtr(); + if (cmd) { + cmd->invoke(item); + Py_Return; + } + else { + PyErr_Format(Base::BaseExceptionFreeCADError, "No such command"); + return nullptr; + } +} + +PyObject* CommandPy::isActive(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + Command* cmd = this->getCommandPtr(); + if (cmd) { + PY_TRY { + return Py::new_reference_to(Py::Boolean(cmd->isActive())); + } + PY_CATCH; + } + else { + PyErr_Format(Base::BaseExceptionFreeCADError, "No such command"); + return nullptr; + } +} + +PyObject* CommandPy::getShortcut(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + Command* cmd = this->getCommandPtr(); + if (cmd) { +#if PY_MAJOR_VERSION >= 3 + PyObject* str = PyUnicode_FromString(cmd->getAction() ? cmd->getAction()->shortcut().toString().toStdString().c_str() : ""); +#else + PyObject* str = PyString_FromString(cmd->getAction() ? cmd->getAction()->shortcut().toString().toStdString().c_str() : ""); +#endif + return str; + } + else { + PyErr_Format(Base::BaseExceptionFreeCADError, "No such command"); + return nullptr; + } +} + +PyObject* CommandPy::setShortcut(PyObject *args) +{ + char* pShortcut; + if (!PyArg_ParseTuple(args, "s", &pShortcut)) + return nullptr; + + Command* cmd = this->getCommandPtr(); + if (cmd) { + Action* action = cmd->getAction(); + if (action) { + QKeySequence shortcut = QString::fromLatin1(pShortcut); + QString nativeText = shortcut.toString(QKeySequence::NativeText); + action->setShortcut(nativeText); + bool success = action->shortcut() == nativeText; + /** + * avoid cluttering parameters unnecessarily by saving only + * when new shortcut is not the default shortcut + * remove spaces to handle cases such as shortcut = "C,L" or "C, L" + */ + QString default_shortcut = QString::fromLatin1(cmd->getAccel()); + QString spc = QString::fromLatin1(" "); + + ParameterGrp::handle hGrp = WindowParameter::getDefaultParameter()->GetGroup("Shortcut"); + const char* pName = cmd->getName(); + if (success && default_shortcut.remove(spc).toUpper() != nativeText.remove(spc).toUpper()) { + hGrp->SetASCII(pName, pShortcut); + } + else { + hGrp->RemoveASCII(pName); + } + return Py::new_reference_to(Py::Boolean(success)); + } + else { + return Py::new_reference_to(Py::Boolean(false)); + } + } + else { + PyErr_Format(Base::BaseExceptionFreeCADError, "No such command"); + return nullptr; + } +} + +PyObject* CommandPy::getInfo(PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return nullptr; + + Command* cmd = this->getCommandPtr(); + if (cmd) { + Action* action = cmd->getAction(); + PyObject* pyList = PyList_New(6); + const char* menuTxt = cmd->getMenuText(); + const char* tooltipTxt = cmd->getToolTipText(); + const char* whatsThisTxt = cmd->getWhatsThis(); + const char* statustipTxt = cmd->getStatusTip(); + const char* pixMapTxt = cmd->getPixmap(); + std::string shortcutTxt = ""; + if (action) + shortcutTxt = action->shortcut().toString().toStdString(); + +#if PY_MAJOR_VERSION >= 3 + PyObject* strMenuTxt = PyUnicode_FromString(menuTxt ? menuTxt : ""); + PyObject* strTooltipTxt = PyUnicode_FromString(tooltipTxt ? tooltipTxt : ""); + PyObject* strWhatsThisTxt = PyUnicode_FromString(whatsThisTxt ? whatsThisTxt : ""); + PyObject* strStatustipTxt = PyUnicode_FromString(statustipTxt ? statustipTxt : ""); + PyObject* strPixMapTxt = PyUnicode_FromString(pixMapTxt ? pixMapTxt : ""); + PyObject* strShortcutTxt = PyUnicode_FromString(!shortcutTxt.empty() ? shortcutTxt.c_str() : ""); +#else + PyObject* strMenuTxt = PyString_FromString(menuTxt ? menuTxt : ""); + PyObject* strTooltipTxt = PyString_FromString(tooltipTxt ? tooltipTxt : ""); + PyObject* strWhatsThisTxt = PyString_FromString(whatsThisTxt ? whatsThisTxt : ""); + PyObject* strStatustipTxt = PyString_FromString(statustipTxt ? statustipTxt : ""); + PyObject* strPixMapTxt = PyString_FromString(pixMapTxt ? pixMapTxt : ""); + PyObject* strShortcutTxt = PyString_FromString(!shortcutTxt.empty() ? shortcutTxt.c_str() : ""); +#endif + PyList_SetItem(pyList, 0, strMenuTxt); + PyList_SetItem(pyList, 1, strTooltipTxt); + PyList_SetItem(pyList, 2, strWhatsThisTxt); + PyList_SetItem(pyList, 3, strStatustipTxt); + PyList_SetItem(pyList, 4, strPixMapTxt); + PyList_SetItem(pyList, 5, strShortcutTxt); + return pyList; + } + else { + PyErr_Format(Base::BaseExceptionFreeCADError, "No such command"); + return nullptr; + } +} + +PyObject *CommandPy::getCustomAttributes(const char* /*attr*/) const +{ + return 0; +} + +int CommandPy::setCustomAttributes(const char* /*attr*/, PyObject* /*obj*/) +{ + return 0; +}