+ implement class PythonGroupCommand
This commit is contained in:
parent
38fffd8218
commit
882ecd3ce3
|
@ -812,37 +812,16 @@ PyObject* Application::sAddCommand(PyObject * /*self*/, PyObject *args,PyObject
|
|||
PyObject* pcCmdObj;
|
||||
if (!PyArg_ParseTuple(args, "sO|s", &pName,&pcCmdObj,&pSource)) // convert args: Python->C
|
||||
return NULL; // NULL triggers exception
|
||||
#if 0
|
||||
std::string source = (pSource ? pSource : "");
|
||||
|
||||
if (source.empty()) {
|
||||
try {
|
||||
Py::Module module(PyImport_ImportModule("inspect"),true);
|
||||
Py::Dict dict = module.getDict();
|
||||
Py::Callable call(dict.getItem("getsourcelines"));
|
||||
Py::Tuple arg(1);
|
||||
arg.setItem(0, Py::Object(pcCmdObj).getAttr("Activated"));
|
||||
Py::Tuple tuple(call.apply(arg));
|
||||
Py::List lines(tuple[0]);
|
||||
|
||||
int pos=0;
|
||||
std::string code = (std::string)(Py::String(lines[1]));
|
||||
while (code[pos] == ' ' || code[pos] == '\t')
|
||||
pos++;
|
||||
for (Py::List::iterator it = lines.begin()+1; it != lines.end(); ++it) {
|
||||
Py::String str(*it);
|
||||
source += ((std::string)str).substr(pos);
|
||||
}
|
||||
}
|
||||
catch (Py::Exception& e) {
|
||||
e.clear();
|
||||
}
|
||||
}
|
||||
|
||||
Application::Instance->commandManager().addCommand(new PythonCommand(pName,pcCmdObj,source.c_str()));
|
||||
#else
|
||||
try {
|
||||
Application::Instance->commandManager().addCommand(new PythonCommand(pName,pcCmdObj,pSource));
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Object cmd(pcCmdObj);
|
||||
if (cmd.hasAttr("GetCommands")) {
|
||||
Application::Instance->commandManager().addCommand(new PythonGroupCommand(pName, pcCmdObj));
|
||||
}
|
||||
else {
|
||||
Application::Instance->commandManager().addCommand(new PythonCommand(pName, pcCmdObj, pSource));
|
||||
}
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
PyErr_SetString(Base::BaseExceptionFreeCADError, e.what());
|
||||
|
@ -852,7 +831,7 @@ PyObject* Application::sAddCommand(PyObject * /*self*/, PyObject *args,PyObject
|
|||
PyErr_SetString(Base::BaseExceptionFreeCADError, "Unknown C++ exception raised in Application::sAddCommand()");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
|
|
@ -793,7 +793,7 @@ void MacroCommand::save()
|
|||
// PythonCommand
|
||||
//===========================================================================
|
||||
|
||||
PythonCommand::PythonCommand(const char* name,PyObject * pcPyCommand, const char* pActivationString)
|
||||
PythonCommand::PythonCommand(const char* name, PyObject * pcPyCommand, const char* pActivationString)
|
||||
: Command(name),_pcPyCommand(pcPyCommand)
|
||||
{
|
||||
if (pActivationString)
|
||||
|
@ -945,6 +945,238 @@ const char* PythonCommand::getAccel() const
|
|||
return getResource("Accel");
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// PythonGroupCommand
|
||||
//===========================================================================
|
||||
|
||||
PythonGroupCommand::PythonGroupCommand(const char* name, PyObject * pcPyCommand)
|
||||
: Command(name),_pcPyCommand(pcPyCommand)
|
||||
{
|
||||
sGroup = "Python";
|
||||
|
||||
Py_INCREF(_pcPyCommand);
|
||||
|
||||
// call the method "GetResources()" of the command object
|
||||
_pcPyResource = Interpreter().runMethodObject(_pcPyCommand, "GetResources");
|
||||
// check if the "GetResources()" method returns a Dict object
|
||||
if (!PyDict_Check(_pcPyResource)) {
|
||||
throw Base::TypeError("PythonGroupCommand::PythonGroupCommand(): Method GetResources() of the Python "
|
||||
"command object returns the wrong type (has to be Py Dictonary)");
|
||||
}
|
||||
|
||||
// check for command type
|
||||
std::string cmdType = getResource("CmdType");
|
||||
if (!cmdType.empty()) {
|
||||
int type = 0;
|
||||
if (cmdType.find("AlterDoc") != std::string::npos)
|
||||
type += int(AlterDoc);
|
||||
if (cmdType.find("Alter3DView") != std::string::npos)
|
||||
type += int(Alter3DView);
|
||||
if (cmdType.find("AlterSelection") != std::string::npos)
|
||||
type += int(AlterSelection);
|
||||
if (cmdType.find("ForEdit") != std::string::npos)
|
||||
type += int(ForEdit);
|
||||
eType = type;
|
||||
}
|
||||
}
|
||||
|
||||
PythonGroupCommand::~PythonGroupCommand()
|
||||
{
|
||||
Base::PyGILStateLocker lock;
|
||||
Py_DECREF(_pcPyCommand);
|
||||
}
|
||||
|
||||
void PythonGroupCommand::activated(int iMsg)
|
||||
{
|
||||
try {
|
||||
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
|
||||
QList<QAction*> a = pcAction->actions();
|
||||
assert(iMsg < a.size());
|
||||
QAction* act = a[iMsg];
|
||||
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Object cmd(_pcPyCommand);
|
||||
if (cmd.hasAttr("Activated")) {
|
||||
Py::Callable call(cmd.getAttr("Activated"));
|
||||
Py::Tuple args(1);
|
||||
args.setItem(0, Py::Int(iMsg));
|
||||
Py::Object ret = call.apply(args);
|
||||
}
|
||||
// If the command group doesn't implement the 'Activated' method then invoke the command directly
|
||||
else {
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
rcCmdMgr.runCommandByName(act->property("CommandName").toByteArray());
|
||||
}
|
||||
|
||||
// Since the default icon is reset when enabing/disabling the command we have
|
||||
// to explicitly set the icon of the used command.
|
||||
pcAction->setIcon(a[iMsg]->icon());
|
||||
}
|
||||
catch(Py::Exception&) {
|
||||
Base::PyGILStateLocker lock;
|
||||
Base::PyException e;
|
||||
Base::Console().Error("Running the Python command '%s' failed:\n%s\n%s",
|
||||
sName, e.getStackTrace().c_str(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool PythonGroupCommand::isActive(void)
|
||||
{
|
||||
try {
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Object cmd(_pcPyCommand);
|
||||
if (cmd.hasAttr("IsActive")) {
|
||||
Py::Callable call(cmd.getAttr("IsActive"));
|
||||
Py::Tuple args;
|
||||
Py::Object ret = call.apply(args);
|
||||
// if return type is not boolean or not true
|
||||
if (!PyBool_Check(ret.ptr()) || ret.ptr() != Py_True)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch(Py::Exception& e) {
|
||||
Base::PyGILStateLocker lock;
|
||||
e.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Action * PythonGroupCommand::createAction(void)
|
||||
{
|
||||
Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
|
||||
pcAction->setDropDownMenu(true);
|
||||
|
||||
applyCommandData(this->getName(), pcAction);
|
||||
|
||||
int defaultId = 0;
|
||||
|
||||
try {
|
||||
Base::PyGILStateLocker lock;
|
||||
Py::Object cmd(_pcPyCommand);
|
||||
|
||||
Py::Callable call(cmd.getAttr("GetCommands"));
|
||||
Py::Tuple args;
|
||||
Py::Tuple ret(call.apply(args));
|
||||
for (Py::Tuple::iterator it = ret.begin(); it != ret.end(); ++it) {
|
||||
Py::String str(*it);
|
||||
QAction* cmd = pcAction->addAction(QString());
|
||||
cmd->setProperty("CommandName", QByteArray(static_cast<std::string>(str).c_str()));
|
||||
}
|
||||
|
||||
if (cmd.hasAttr("GetDefaultCommand")) {
|
||||
Py::Callable call2(cmd.getAttr("GetDefaultCommand"));
|
||||
Py::Int def(call2.apply(args));
|
||||
defaultId = static_cast<int>(def);
|
||||
}
|
||||
}
|
||||
catch(Py::Exception&) {
|
||||
Base::PyGILStateLocker lock;
|
||||
Base::PyException e;
|
||||
Base::Console().Error("createAction() of the Python command '%s' failed:\n%s\n%s",
|
||||
sName, e.getStackTrace().c_str(), e.what());
|
||||
}
|
||||
|
||||
_pcAction = pcAction;
|
||||
languageChange();
|
||||
|
||||
if (strcmp(getResource("Pixmap"),"") != 0) {
|
||||
pcAction->setIcon(Gui::BitmapFactory().pixmap(getResource("Pixmap")));
|
||||
}
|
||||
else {
|
||||
QList<QAction*> a = pcAction->actions();
|
||||
if (a.size() > defaultId)
|
||||
pcAction->setIcon(a[defaultId]->icon());
|
||||
}
|
||||
|
||||
pcAction->setProperty("defaultAction", QVariant(defaultId));
|
||||
|
||||
return pcAction;
|
||||
}
|
||||
|
||||
void PythonGroupCommand::languageChange()
|
||||
{
|
||||
if (!_pcAction)
|
||||
return;
|
||||
|
||||
applyCommandData(this->getName(), _pcAction);
|
||||
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
|
||||
QList<QAction*> a = pcAction->actions();
|
||||
for (QList<QAction*>::iterator it = a.begin(); it != a.end(); ++it) {
|
||||
Gui::Command* cmd = rcCmdMgr.getCommandByName((*it)->property("CommandName").toByteArray());
|
||||
// Python command use getName as context
|
||||
if (dynamic_cast<PythonCommand*>(cmd)) {
|
||||
(*it)->setIcon(Gui::BitmapFactory().pixmap(cmd->getPixmap()));
|
||||
(*it)->setText(QApplication::translate(cmd->getName(), cmd->getMenuText()));
|
||||
(*it)->setToolTip(QApplication::translate(cmd->getName(), cmd->getToolTipText()));
|
||||
(*it)->setStatusTip(QApplication::translate(cmd->getName(), cmd->getStatusTip()));
|
||||
}
|
||||
else if (cmd) {
|
||||
(*it)->setIcon(Gui::BitmapFactory().pixmap(cmd->getPixmap()));
|
||||
(*it)->setText(QApplication::translate(cmd->className(), cmd->getMenuText()));
|
||||
(*it)->setToolTip(QApplication::translate(cmd->className(), cmd->getToolTipText()));
|
||||
(*it)->setStatusTip(QApplication::translate(cmd->className(), cmd->getStatusTip()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getHelpUrl(void) const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getResource(const char* sName) const
|
||||
{
|
||||
PyObject* pcTemp;
|
||||
|
||||
// get the "MenuText" resource string
|
||||
pcTemp = PyDict_GetItemString(_pcPyResource, sName);
|
||||
if (!pcTemp)
|
||||
return "";
|
||||
if (!PyString_Check(pcTemp)) {
|
||||
throw Base::ValueError("PythonGroupCommand::getResource(): Method GetResources() of the Python "
|
||||
"group command object returns a dictionary which holds not only strings");
|
||||
}
|
||||
|
||||
return PyString_AsString(pcTemp);
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getWhatsThis() const
|
||||
{
|
||||
const char* whatsthis = getResource("WhatsThis");
|
||||
if (!whatsthis || whatsthis[0] == '\0')
|
||||
whatsthis = this->getName();
|
||||
return whatsthis;
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getMenuText() const
|
||||
{
|
||||
return getResource("MenuText");
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getToolTipText() const
|
||||
{
|
||||
return getResource("ToolTip");
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getStatusTip() const
|
||||
{
|
||||
return getResource("StatusTip");
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getPixmap() const
|
||||
{
|
||||
return getResource("Pixmap");
|
||||
}
|
||||
|
||||
const char* PythonGroupCommand::getAccel() const
|
||||
{
|
||||
return getResource("Accel");
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
// CommandManager
|
||||
//===========================================================================
|
||||
|
|
|
@ -322,7 +322,7 @@ private:
|
|||
class PythonCommand: public Command
|
||||
{
|
||||
public:
|
||||
PythonCommand(const char* name,PyObject * pcPyCommand, const char* pActivationString);
|
||||
PythonCommand(const char* name, PyObject * pcPyCommand, const char* pActivationString);
|
||||
virtual ~PythonCommand() {}
|
||||
|
||||
protected:
|
||||
|
@ -364,6 +364,53 @@ protected:
|
|||
std::string Activation;
|
||||
};
|
||||
|
||||
/** The Python group command class
|
||||
* @see CommandManager
|
||||
* @author Werner Mayer
|
||||
*/
|
||||
class PythonGroupCommand: public Command
|
||||
{
|
||||
public:
|
||||
PythonGroupCommand(const char* name, PyObject * pcPyCommand);
|
||||
virtual ~PythonGroupCommand();
|
||||
|
||||
protected:
|
||||
/** @name Methods reimplemented for Command Framework */
|
||||
//@{
|
||||
/// Method which gets called when activated
|
||||
virtual void activated(int iMsg);
|
||||
/// if the command is not always active
|
||||
virtual bool isActive(void);
|
||||
/// Get the help URL
|
||||
const char* getHelpUrl(void) const;
|
||||
/// Creates the used Action
|
||||
virtual Action * createAction(void);
|
||||
//@}
|
||||
|
||||
public:
|
||||
/** @name Methods to get the properties of the command */
|
||||
//@{
|
||||
/// Reassigns QAction stuff after the language has changed.
|
||||
void languageChange();
|
||||
const char* className() const
|
||||
{ return "PythonGroupCommand"; }
|
||||
const char* getWhatsThis () const;
|
||||
const char* getMenuText () const;
|
||||
const char* getToolTipText() const;
|
||||
const char* getStatusTip () const;
|
||||
const char* getPixmap () const;
|
||||
const char* getAccel () const;
|
||||
//@}
|
||||
|
||||
protected:
|
||||
/// Returns the resource values
|
||||
const char* getResource(const char* sName) const;
|
||||
/// a pointer to the Python command object
|
||||
PyObject * _pcPyCommand;
|
||||
/// the command object resources
|
||||
PyObject * _pcPyResource;
|
||||
};
|
||||
|
||||
|
||||
/** The script command class
|
||||
* This is a special type of command class. Its used to bind a macro or Python script to the
|
||||
|
|
|
@ -193,6 +193,44 @@ class TemplatePyMod_Cmd6:
|
|||
def GetResources(self):
|
||||
return {'Pixmap' : 'python', 'MenuText': 'Create a box', 'ToolTip': 'Use Box feature class which is completely written in Python'}
|
||||
|
||||
class TemplatePyGrp_1:
|
||||
def Activated(self):
|
||||
import FreeCAD
|
||||
FreeCAD.Console.PrintMessage("TemplatePyGrp_1\n")
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Part_JoinConnect', 'MenuText': 'TemplatePyGrp_1', 'ToolTip': 'Print a message'}
|
||||
|
||||
class TemplatePyGrp_2:
|
||||
def Activated(self):
|
||||
import FreeCAD
|
||||
FreeCAD.Console.PrintMessage("TemplatePyGrp_2\n")
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Part_JoinEmbed', 'MenuText': 'TemplatePyGrp_2', 'ToolTip': 'Print a message'}
|
||||
|
||||
class TemplatePyGrp_3:
|
||||
def Activated(self):
|
||||
import FreeCAD
|
||||
FreeCAD.Console.PrintMessage("TemplatePyGrp_3\n")
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'Part_JoinCutout', 'MenuText': 'TemplatePyGrp_3', 'ToolTip': 'Print a message'}
|
||||
|
||||
class TemplatePyGroup:
|
||||
"Example group command class"
|
||||
#def Activated(self, index):
|
||||
# print "TemplatePyGroup activated ;-) "
|
||||
|
||||
def GetCommands(self):
|
||||
return ("TemplatePyGrp_1", "TemplatePyGrp_2", "TemplatePyGrp_3", "Std_New")
|
||||
|
||||
def GetDefaultCommand(self):
|
||||
return 2
|
||||
|
||||
def GetResources(self):
|
||||
return {'Pixmap' : 'python', 'MenuText': 'Group command', 'ToolTip': 'Example group command'}
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Adds the commands to the FreeCAD command manager
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -202,4 +240,7 @@ addCommand('TemplatePyMod_Cmd3',TemplatePyMod_Cmd3())
|
|||
FreeCADGui.addCommand('TemplatePyMod_Cmd4',TemplatePyMod_Cmd4())
|
||||
FreeCADGui.addCommand('TemplatePyMod_Cmd5',TemplatePyMod_Cmd5())
|
||||
FreeCADGui.addCommand('TemplatePyMod_Cmd6',TemplatePyMod_Cmd6())
|
||||
|
||||
FreeCADGui.addCommand('TemplatePyGrp_1',TemplatePyGrp_1())
|
||||
FreeCADGui.addCommand('TemplatePyGrp_2',TemplatePyGrp_2())
|
||||
FreeCADGui.addCommand('TemplatePyGrp_3',TemplatePyGrp_3())
|
||||
FreeCADGui.addCommand('TemplatePyGroup',TemplatePyGroup())
|
||||
|
|
Loading…
Reference in New Issue
Block a user