diff --git a/src/App/DynamicProperty.cpp b/src/App/DynamicProperty.cpp index 925783850c..5851814b34 100644 --- a/src/App/DynamicProperty.cpp +++ b/src/App/DynamicProperty.cpp @@ -297,6 +297,18 @@ DynamicProperty::PropData DynamicProperty::getDynamicPropertyData(const Property return PropData(); } +bool DynamicProperty::changeDynamicProperty(const Property *prop, const char *group, const char *doc) { + auto &index = props.get<1>(); + auto it = index.find(const_cast(prop)); + if (it == index.end()) + return false; + if(group) + it->group = group; + if(doc) + it->doc = doc; + return true; +} + const char *DynamicProperty::getPropertyName(const Property *prop) const { auto &index = props.get<1>(); diff --git a/src/App/DynamicProperty.h b/src/App/DynamicProperty.h index 760bfdc834..ba09a48568 100644 --- a/src/App/DynamicProperty.h +++ b/src/App/DynamicProperty.h @@ -149,8 +149,8 @@ public: Property* property; std::string name; const char *pName; - std::string group; - std::string doc; + mutable std::string group; + mutable std::string doc; short attr; bool readonly; bool hidden; @@ -168,6 +168,8 @@ public: PropData getDynamicPropertyData(const Property* prop) const; + bool changeDynamicProperty(const Property *prop, const char *group, const char *doc); + private: std::string getUniquePropertyName(PropertyContainer &pc, const char *Name) const; diff --git a/src/App/PropertyContainer.h b/src/App/PropertyContainer.h index bb03473cec..b9763de970 100644 --- a/src/App/PropertyContainer.h +++ b/src/App/PropertyContainer.h @@ -200,6 +200,10 @@ public: return dynamicProps.getDynamicPropertyData(prop); } + bool changeDynamicProperty(const Property *prop, const char *group, const char *doc) { + return dynamicProps.changeDynamicProperty(prop,group,doc); + } + virtual bool removeDynamicProperty(const char* name) { return dynamicProps.removeDynamicProperty(name); } diff --git a/src/App/PropertyContainerPy.xml b/src/App/PropertyContainerPy.xml index 061709405b..44833e5ea5 100644 --- a/src/App/PropertyContainerPy.xml +++ b/src/App/PropertyContainerPy.xml @@ -68,6 +68,11 @@ If the list contains 'Hidden' then the item even doesn't appear in the property Return the name of the group which the property belongs to in this class. The properties sorted in different named groups for convenience. + + + Set the name of the group of a dynamic property. + + @@ -97,6 +102,11 @@ text names of the status. Return the documentation string of the property of this class. + + + Set the documentation string of a dynamic property of this class. + + Return all enumeration strings of the property of this class or None if not a PropertyEnumeration. diff --git a/src/App/PropertyContainerPyImp.cpp b/src/App/PropertyContainerPyImp.cpp index f1775bb127..29aba7869b 100644 --- a/src/App/PropertyContainerPyImp.cpp +++ b/src/App/PropertyContainerPyImp.cpp @@ -339,6 +339,25 @@ PyObject* PropertyContainerPy::getGroupOfProperty(PyObject *args) return Py::new_reference_to(Py::String("")); } +PyObject* PropertyContainerPy::setGroupOfProperty(PyObject *args) +{ + char *pstr; + char *group; + if (!PyArg_ParseTuple(args, "ss", &pstr, &group)) // convert args: Python->C + return NULL; // NULL triggers exception + + PY_TRY { + Property* prop = getPropertyContainerPtr()->getDynamicPropertyByName(pstr); + if (!prop) { + PyErr_Format(PyExc_AttributeError, "Property container has no dynamic property '%s'", pstr); + return 0; + } + prop->getContainer()->changeDynamicProperty(prop,group,0); + Py_Return; + } PY_CATCH +} + + PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args) { char *pstr; @@ -358,6 +377,24 @@ PyObject* PropertyContainerPy::getDocumentationOfProperty(PyObject *args) return Py::new_reference_to(Py::String("")); } +PyObject* PropertyContainerPy::setDocumentationOfProperty(PyObject *args) +{ + char *pstr; + char *doc; + if (!PyArg_ParseTuple(args, "ss", &pstr, &doc)) // convert args: Python->C + return NULL; // NULL triggers exception + + PY_TRY { + Property* prop = getPropertyContainerPtr()->getDynamicPropertyByName(pstr); + if (!prop) { + PyErr_Format(PyExc_AttributeError, "Property container has no dynamic property '%s'", pstr); + return 0; + } + prop->getContainer()->changeDynamicProperty(prop,0,doc); + Py_Return; + } PY_CATCH +} + PyObject* PropertyContainerPy::getEnumerationsOfProperty(PyObject *args) { char *pstr; diff --git a/src/Gui/propertyeditor/PropertyEditor.cpp b/src/Gui/propertyeditor/PropertyEditor.cpp index 9bfc78639e..47f3c15975 100644 --- a/src/Gui/propertyeditor/PropertyEditor.cpp +++ b/src/Gui/propertyeditor/PropertyEditor.cpp @@ -31,8 +31,11 @@ # include # include # include +# include #endif +#include + #include #include #include @@ -57,6 +60,7 @@ PropertyEditor::PropertyEditor(QWidget *parent) , committing(false) , delaybuild(false) , binding(false) + , checkDocument(false) { propertyModel = new PropertyModel(this); setModel(propertyModel); @@ -362,8 +366,10 @@ void PropertyEditor::drawBranches(QPainter *painter, const QRect &rect, const QM //painter->setPen(savedPen); } -void PropertyEditor::buildUp(PropertyModel::PropertyList &&props, bool checkDocument) +void PropertyEditor::buildUp(PropertyModel::PropertyList &&props, bool _checkDocument) { + checkDocument = _checkDocument; + if (committing) { Base::Console().Warning("While committing the data to the property the selection has changed.\n"); delaybuild = true; @@ -493,6 +499,7 @@ enum MenuAction { MA_Expression, MA_RemoveProp, MA_AddProp, + MA_EditPropGroup, MA_Transient, MA_Output, MA_NoRecompute, @@ -532,8 +539,20 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent *) { } } - if(props.size()) + if(props.size()) { menu.addAction(tr("Add property"))->setData(QVariant(MA_AddProp)); + unsigned count = 0; + for(auto prop : props) { + if(prop->testStatus(App::Property::PropDynamic) + && !boost::starts_with(prop->getName(),prop->getGroup())) + { + ++count; + } else + break; + } + if(count == props.size()) + menu.addAction(tr("Rename property group"))->setData(QVariant(MA_EditPropGroup)); + } bool canRemove = !props.empty(); unsigned long propType = 0; @@ -645,6 +664,22 @@ void PropertyEditor::contextMenuEvent(QContextMenuEvent *) { dlg.exec(); return; } + case MA_EditPropGroup: { + // This operation is not undoable yet. + const char *groupName = (*props.begin())->getGroup(); + if(!groupName) + groupName = "Base"; + QString res = QInputDialog::getText(Gui::getMainWindow(), + tr("Rename property group"), tr("Group name:"), + QLineEdit::Normal, QString::fromUtf8(groupName)); + if(res.size()) { + std::string group = res.toUtf8().constData(); + for(auto prop : props) + prop->getContainer()->changeDynamicProperty(prop,group.c_str(),0); + buildUp(PropertyModel::PropertyList(propList),checkDocument); + } + return; + } case MA_RemoveProp: { App::AutoTransaction committer("Remove property"); for(auto prop : props) { diff --git a/src/Gui/propertyeditor/PropertyEditor.h b/src/Gui/propertyeditor/PropertyEditor.h index c865b13c24..f9b55798af 100644 --- a/src/Gui/propertyeditor/PropertyEditor.h +++ b/src/Gui/propertyeditor/PropertyEditor.h @@ -124,6 +124,7 @@ private: bool committing; bool delaybuild; bool binding; + bool checkDocument; int transactionID = 0;