Merge branch 'master' into master
This commit is contained in:
@@ -219,7 +219,12 @@ bool Origin::OriginExtension::extensionGetSubObject(DocumentObject *&ret, const
|
||||
ret = obj->getOriginFeature(name.c_str());
|
||||
if (!ret)
|
||||
return false;
|
||||
ret = ret->getSubObject(subname + name.size() + 1, pyobj, mat, true, depth+1);
|
||||
const char *dot = strchr(subname, '.');
|
||||
if (dot)
|
||||
subname = dot+1;
|
||||
else
|
||||
subname = "";
|
||||
ret = ret->getSubObject(subname, pyobj, mat, true, depth+1);
|
||||
return true;
|
||||
}
|
||||
catch (const Base::Exception& e) {
|
||||
|
||||
@@ -369,7 +369,7 @@ void Command::invoke(int i, TriggerSource trigger)
|
||||
{
|
||||
CommandTrigger cmdTrigger(_trigger,trigger);
|
||||
if (displayText.empty()) {
|
||||
displayText = getMenuText();
|
||||
displayText = getMenuText() ? getMenuText() : "";
|
||||
boost::replace_all(displayText,"&","");
|
||||
if (displayText.empty())
|
||||
displayText = getName();
|
||||
|
||||
@@ -15,116 +15,107 @@
|
||||
</Documentation>
|
||||
<Methode Name="get" Static='true'>
|
||||
<Documentation>
|
||||
<UserDocu>Get a given command by name or None if it doesn't exist.
|
||||
get(string) -> Command
|
||||
</UserDocu>
|
||||
<UserDocu>get(name) -> Gui.Command or None\n
|
||||
Get a given command by name or None if it doesn't exist.\n
|
||||
name : str\n Command name.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="update" Static='true'>
|
||||
<Documentation>
|
||||
<UserDocu>Update active status of all commands.
|
||||
update() -> None
|
||||
</UserDocu>
|
||||
<UserDocu>update() -> None\n
|
||||
Update active status of all commands.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="listAll" Static='true'>
|
||||
<Documentation>
|
||||
<UserDocu>Returns the name of all commands.
|
||||
listAll() -> list of strings
|
||||
</UserDocu>
|
||||
<UserDocu>listAll() -> list of str\n
|
||||
Returns the name of all commands.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="listByShortcut" Static='true'>
|
||||
<Documentation>
|
||||
<UserDocu>Returns a list of all commands, filtered by shortcut.
|
||||
listByShortcut(string, bool bUseRegExp=False) -> list of strings
|
||||
--
|
||||
Shortcuts are converted to uppercase and spaces removed prior to comparison.
|
||||
</UserDocu>
|
||||
<UserDocu>listByShortcut(string, useRegExp=False) -> list of str\n
|
||||
Returns a list of all commands, filtered by shortcut.
|
||||
Shortcuts are converted to uppercase and spaces removed
|
||||
prior to comparison.\n
|
||||
string : str\n Shortcut to be searched.
|
||||
useRegExp : bool\n Filter using regular expression.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="run">
|
||||
<Documentation>
|
||||
<UserDocu>Runs the given command.
|
||||
run() -> None
|
||||
</UserDocu>
|
||||
<UserDocu>run(item=0) -> None\n
|
||||
Runs the given command.\n
|
||||
item : int\n Item to be run.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="isActive" Const="true">
|
||||
<Documentation>
|
||||
<UserDocu>Returns True if the command is active, False otherwise.
|
||||
isActive() -> bool
|
||||
</UserDocu>
|
||||
<UserDocu>isActive() -> bool\n
|
||||
Returns True if the command is active, False otherwise.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getShortcut">
|
||||
<Documentation>
|
||||
<UserDocu>Returns string representing shortcut key accelerator for command.
|
||||
getShortcut() -> string
|
||||
</UserDocu>
|
||||
<UserDocu>getShortcut() -> str\n
|
||||
Returns string representing shortcut key accelerator for command.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="setShortcut">
|
||||
<Documentation>
|
||||
<UserDocu>Sets shortcut for given command, returns bool True for success.
|
||||
setShortcut(string) -> bool
|
||||
</UserDocu>
|
||||
<UserDocu>setShortcut(string) -> bool\n
|
||||
Sets shortcut for given command, returns True for success.\n
|
||||
string : str\n Shortcut to be set.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="resetShortcut">
|
||||
<Documentation>
|
||||
<UserDocu>Resets shortcut for given command back to the default, returns bool True for success.
|
||||
resetShortcut() -> bool
|
||||
</UserDocu>
|
||||
<UserDocu>resetShortcut() -> bool\n
|
||||
Resets shortcut for given command back to the default, returns True for success.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getInfo">
|
||||
<Documentation>
|
||||
<UserDocu>Return information about this command.
|
||||
getInfo() -> list of strings
|
||||
--
|
||||
Usage: menuText, tooltipText, whatsThisText, statustipText, pixmapText, shortcutText.
|
||||
</UserDocu>
|
||||
<UserDocu>getInfo() -> dict\n
|
||||
Return information about this command.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="getAction">
|
||||
<Documentation>
|
||||
<UserDocu>Return the associated QAction object.
|
||||
getAction() -> list of QAction</UserDocu>
|
||||
<UserDocu>getAction() -> list of QAction\n
|
||||
Return the associated QAction object.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="createCustomCommand" Static='true'>
|
||||
<Methode Name="createCustomCommand" Static='true' Keyword='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>
|
||||
<UserDocu>createCustomCommand(macroFile, menuText, toolTip, whatsThis, statusTip, pixmap, shortcut) -> str\n
|
||||
Create a custom command for a macro. Returns name of the created command.\n
|
||||
macroFile : str\n Macro file.
|
||||
menuText : str\n Menu text. Optional.
|
||||
toolTip : str\n Tool tip text. Optional.
|
||||
whatsThis : str\n `What's this?` text. Optional.
|
||||
statusTip : str\n Status tip text. Optional.
|
||||
pixmap : str\n Pixmap name. Optional.
|
||||
shortcut : str\n Shortcut key sequence. Optional.</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>
|
||||
<UserDocu>removeCustomCommand(name) -> bool\n
|
||||
Remove the custom command if it exists.
|
||||
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.\n
|
||||
name : str\n Command name.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
<Methode Name="findCustomCommand" Static='true'>
|
||||
<Documentation>
|
||||
<UserDocu>Find the name of a custom command, given a macro name
|
||||
findCustomCommand(name) -> Optional[str]
|
||||
--
|
||||
Given the name of a macro, return the name of the custom command for that macro, or
|
||||
None if there is no command matching that macro script name.
|
||||
</UserDocu>
|
||||
<UserDocu>findCustomCommand(name) -> str or None\n
|
||||
Given the name of a macro, return the name of the custom command for that macro
|
||||
or None if there is no command matching that macro script name.\n
|
||||
name : str\n Macro name.</UserDocu>
|
||||
</Documentation>
|
||||
</Methode>
|
||||
</PythonExport>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "Window.h"
|
||||
#include "PythonWrapper.h"
|
||||
|
||||
// inclusion of the generated files (generated out of AreaPy.xml)
|
||||
// inclusion of the generated files (generated out of CommandPy.xml)
|
||||
#include "CommandPy.h"
|
||||
#include "CommandPy.cpp"
|
||||
|
||||
@@ -86,8 +86,8 @@ PyObject* CommandPy::listAll(PyObject *args)
|
||||
PyObject* CommandPy::listByShortcut(PyObject *args)
|
||||
{
|
||||
char* shortcut_to_find;
|
||||
bool bIsRegularExp = false;
|
||||
if (!PyArg_ParseTuple(args, "s|b", &shortcut_to_find, &bIsRegularExp))
|
||||
PyObject* bIsRegularExp = Py_False;
|
||||
if (!PyArg_ParseTuple(args, "s|O!", &shortcut_to_find, &PyBool_Type, &bIsRegularExp))
|
||||
return nullptr;
|
||||
|
||||
std::vector <Command*> cmds = Application::Instance->commandManager().getAllCommands();
|
||||
@@ -96,7 +96,7 @@ PyObject* CommandPy::listByShortcut(PyObject *args)
|
||||
Action* action = c->getAction();
|
||||
if (action){
|
||||
QString spc = QString::fromLatin1(" ");
|
||||
if(bIsRegularExp){
|
||||
if(PyObject_IsTrue(bIsRegularExp)){
|
||||
QRegExp re = QRegExp(QString::fromLatin1(shortcut_to_find));
|
||||
re.setCaseSensitivity(Qt::CaseInsensitive);
|
||||
if (!re.isValid()){
|
||||
@@ -105,7 +105,7 @@ PyObject* CommandPy::listByShortcut(PyObject *args)
|
||||
throw Py::RuntimeError(str.str());
|
||||
}
|
||||
|
||||
if (re.indexIn(action->shortcut().toString().remove(spc).toUpper()) != -1){
|
||||
if (re.indexIn(action->shortcut().toString().remove(spc).toUpper()) != -1) {
|
||||
matches.push_back(c->getName());
|
||||
}
|
||||
}
|
||||
@@ -261,7 +261,8 @@ PyObject* CommandPy::getInfo(PyObject *args)
|
||||
Command* cmd = this->getCommandPtr();
|
||||
if (cmd) {
|
||||
Action* action = cmd->getAction();
|
||||
PyObject* pyList = PyList_New(6);
|
||||
PyObject* pyDict = PyDict_New();
|
||||
const char* cmdName = cmd->getName();
|
||||
const char* menuTxt = cmd->getMenuText();
|
||||
const char* tooltipTxt = cmd->getToolTipText();
|
||||
const char* whatsThisTxt = cmd->getWhatsThis();
|
||||
@@ -271,19 +272,21 @@ PyObject* CommandPy::getInfo(PyObject *args)
|
||||
if (action)
|
||||
shortcutTxt = action->shortcut().toString().toStdString();
|
||||
|
||||
PyObject* strCmdName = PyUnicode_FromString(cmdName);
|
||||
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() : "");
|
||||
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;
|
||||
PyDict_SetItemString(pyDict, "name", strCmdName);
|
||||
PyDict_SetItemString(pyDict, "menuText", strMenuTxt);
|
||||
PyDict_SetItemString(pyDict, "toolTip", strTooltipTxt);
|
||||
PyDict_SetItemString(pyDict, "whatsThis", strWhatsThisTxt);
|
||||
PyDict_SetItemString(pyDict, "statusTip", strStatustipTxt);
|
||||
PyDict_SetItemString(pyDict, "pixmap", strPixMapTxt);
|
||||
PyDict_SetItemString(pyDict, "shortcut", strShortcutTxt);
|
||||
return pyDict;
|
||||
}
|
||||
else {
|
||||
PyErr_Format(Base::PyExc_FC_GeneralError, "No such command");
|
||||
@@ -322,16 +325,18 @@ PyObject* CommandPy::getAction(PyObject *args)
|
||||
}
|
||||
|
||||
|
||||
PyObject* CommandPy::createCustomCommand(PyObject* args)
|
||||
PyObject* CommandPy::createCustomCommand(PyObject* args, PyObject* kw)
|
||||
{
|
||||
const char* macroFile = nullptr;
|
||||
const char* macroFile;
|
||||
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))
|
||||
static char* kwlist[] = {"macroFile", "menuText", "toolTip", "whatsThis","statusTip", "pixmap", "shortcut", nullptr};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "s|zzzzzz", kwlist, ¯oFile, &menuTxt,
|
||||
&tooltipTxt, &whatsthisTxt, &statustipTxt, &pixmapTxt, &shortcutTxt))
|
||||
return nullptr;
|
||||
|
||||
auto name = Application::Instance->commandManager().newMacroName();
|
||||
@@ -400,13 +405,10 @@ PyObject* CommandPy::findCustomCommand(PyObject* args)
|
||||
return false;
|
||||
});
|
||||
|
||||
if (action != macros.end()) {
|
||||
if (action != macros.end())
|
||||
return PyUnicode_FromString((*action)->getName());
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
else
|
||||
Py_Return;
|
||||
}
|
||||
|
||||
PyObject *CommandPy::getCustomAttributes(const char* /*attr*/) const
|
||||
|
||||
@@ -719,7 +719,7 @@ Py::Object AbstractSplitViewPy::getViewer(const Py::Tuple& args)
|
||||
}
|
||||
}
|
||||
|
||||
Py::Object AbstractSplitViewPy::sequence_item(ssize_t viewIndex)
|
||||
Py::Object AbstractSplitViewPy::sequence_item(Py_ssize_t viewIndex)
|
||||
{
|
||||
AbstractSplitView* view = getSplitViewPtr();
|
||||
if (viewIndex >= view->getSize() || viewIndex < 0)
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
Py::Object viewTop(const Py::Tuple&);
|
||||
Py::Object viewIsometric(const Py::Tuple&);
|
||||
Py::Object getViewer(const Py::Tuple&);
|
||||
Py::Object sequence_item(ssize_t);
|
||||
Py::Object sequence_item(Py_ssize_t);
|
||||
Py::Object close(const Py::Tuple&);
|
||||
int sequence_length();
|
||||
|
||||
|
||||
@@ -96,7 +96,11 @@ def makeWindow(baseobj=None,width=None,height=None,parts=None,name=None):
|
||||
else:
|
||||
if baseobj:
|
||||
if baseobj.getLinkedObject().isDerivedFrom("Part::Part2DObject"):
|
||||
# create default component
|
||||
if baseobj.Shape.Wires:
|
||||
tp = "Frame"
|
||||
if len(baseobj.Shape.Wires) == 1:
|
||||
tp = "Solid panel"
|
||||
i = 0
|
||||
ws = ''
|
||||
for w in baseobj.Shape.Wires:
|
||||
@@ -104,7 +108,7 @@ def makeWindow(baseobj=None,width=None,height=None,parts=None,name=None):
|
||||
if ws: ws += ","
|
||||
ws += "Wire" + str(i)
|
||||
i += 1
|
||||
obj.WindowParts = ["Default","Frame",ws,"1","0"]
|
||||
obj.WindowParts = ["Default",tp,ws,"1","0"]
|
||||
else:
|
||||
# bind properties from base obj if existing
|
||||
for prop in ["Height","Width","Subvolume","Tag","Description","Material"]:
|
||||
|
||||
@@ -1591,14 +1591,15 @@ class svgHandler(xml.sax.ContentHandler):
|
||||
cy = 0
|
||||
angle = argsplit[0]
|
||||
if len(argsplit) >= 3:
|
||||
# Rotate around a non-origin centerpoint (note: SVG y axis is opposite FreeCAD y axis)
|
||||
cx = argsplit[1]
|
||||
cy = argsplit[2]
|
||||
m.move(Vector(cx, -cy, 0))
|
||||
m.move(Vector(-cx, cy, 0)) # Reposition for rotation
|
||||
# Mirroring one axis is equal to changing the direction
|
||||
# of rotation
|
||||
m.rotateZ(math.radians(-angle))
|
||||
if len(argsplit) >= 3:
|
||||
m.move(Vector(-cx, cy, 0))
|
||||
m.move(Vector(cx, -cy, 0)) # Reverse repositioning
|
||||
elif transformation == 'skewX':
|
||||
_m = FreeCAD.Matrix(1,
|
||||
-math.tan(math.radians(argsplit[0])))
|
||||
|
||||
@@ -31,6 +31,14 @@ $CMLSTYLE
|
||||
2
|
||||
STANDARD
|
||||
9
|
||||
$LUNITS
|
||||
70
|
||||
2
|
||||
9
|
||||
$INSUNITS
|
||||
70
|
||||
4
|
||||
9
|
||||
$PEXTMAX
|
||||
10
|
||||
50
|
||||
|
||||
@@ -134,7 +134,7 @@ void ViewProviderSketch::ParameterObserver::updateGridSize(const std::string & s
|
||||
|
||||
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
|
||||
|
||||
Client.GridSize.setValue(Base::Quantity::parse(QString::fromLatin1(hGrp->GetGroup("GridSize")->GetASCII("Hist0", "10.0").c_str())).getValue());
|
||||
Client.GridSize.setValue(Base::Quantity::parse(QString::fromLatin1(hGrp->GetGroup("GridSize")->GetASCII("GridSize", "10.0").c_str())).getValue());
|
||||
}
|
||||
|
||||
void ViewProviderSketch::ParameterObserver::updateEscapeKeyBehaviour(const std::string & string, App::Property * property)
|
||||
|
||||
@@ -306,6 +306,17 @@ class DocumentBasicCases(unittest.TestCase):
|
||||
self.assertEqual(obj.getSubObject(("XY_Plane", "YZ_Plane"), retType=4)[0], obj.getSubObject("XY_Plane", retType=4))
|
||||
self.assertEqual(obj.getSubObject(("XY_Plane", "YZ_Plane"), retType=4)[1], obj.getSubObject("YZ_Plane", retType=4))
|
||||
|
||||
# Create a second origin object
|
||||
obj2 = self.Doc.addObject("App::Origin", "Origin2")
|
||||
self.Doc.recompute()
|
||||
|
||||
# Use the names of the origin's out-list
|
||||
for i in obj2.OutList:
|
||||
self.assertEqual(obj2.getSubObject(i.Name, retType=1).Name, i.Name)
|
||||
# Add a '.' to the names
|
||||
for i in obj2.OutList:
|
||||
self.assertEqual(obj2.getSubObject(i.Name + '.', retType=1).Name, i.Name)
|
||||
|
||||
def testExtensions(self):
|
||||
#we try to create a normal python object and add an extension to it
|
||||
obj = self.Doc.addObject("App::DocumentObject", "Extension_1")
|
||||
|
||||
@@ -306,7 +306,7 @@ void UnitTestDialog::setProgressFraction(float fraction, const QString& color)
|
||||
}
|
||||
|
||||
/**
|
||||
* Emtpies the error listview.
|
||||
* Empties the error listview.
|
||||
*/
|
||||
void UnitTestDialog::clearErrorList()
|
||||
{
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
# Workbench test module
|
||||
|
||||
import FreeCAD, FreeCADGui, os, unittest
|
||||
import tempfile
|
||||
|
||||
from PySide2 import QtWidgets, QtCore
|
||||
from PySide2.QtWidgets import QApplication
|
||||
@@ -79,3 +80,16 @@ class WorkbenchTestCase(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
FreeCADGui.activateWorkbench(self.Active.name())
|
||||
FreeCAD.Console.PrintLog(self.Active.name())
|
||||
|
||||
class CommandTestCase(unittest.TestCase):
|
||||
def testPR6889(self):
|
||||
# Fixes a crash
|
||||
TempPath = tempfile.gettempdir()
|
||||
macroName = TempPath + os.sep + "testmacro.py"
|
||||
macroFile = open(macroName, "w")
|
||||
macroFile.write("print ('Hello, World!')")
|
||||
macroFile.close()
|
||||
|
||||
name = FreeCADGui.Command.createCustomCommand(macroName)
|
||||
cmd = FreeCADGui.Command.get(name)
|
||||
cmd.run()
|
||||
|
||||
Reference in New Issue
Block a user