Permalink
Cannot retrieve contributors at this time
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
1338 lines (1090 sloc)
49.1 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*************************************************************************** | |
* Copyright (c) Jürgen Riegel (juergen.riegel@web.de) 2002 * | |
* * | |
* 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 * | |
* * | |
***************************************************************************/ | |
#ifndef APP_PROPERTYLINKS_H | |
#define APP_PROPERTYLINKS_H | |
// Std. configurations | |
#include <vector> | |
#include <map> | |
#include <list> | |
#include <string> | |
#include <memory> | |
#include <cinttypes> | |
#include "Property.h" | |
namespace Base { | |
class Writer; | |
} | |
namespace App | |
{ | |
class DocumentObject; | |
class Document; | |
class DocInfo; | |
typedef std::shared_ptr<DocInfo> DocInfoPtr; | |
class PropertyXLink; | |
/** | |
* @brief Defines different scopes for which a link can be valid | |
* The scopes defined in this enum describe the different possibilities of where a link can point to. | |
* Local: links are valid only within the same GeoFeatureGroup as the linkowner is in or in none. | |
* Child: links are valid within the same or any sub GeoFeatureGroup | |
* Global: all possible links are valid | |
* Hidden: links are not included in dependency calculation | |
*/ | |
enum class LinkScope { | |
Local, | |
Child, | |
Global, | |
Hidden, | |
}; | |
/** | |
* @brief Enables scope handling for links | |
* This class is a base for all link properties and enables them to handle scopes of the linked objects. | |
* The possible scopes are defined by LinkScope enum class. The default value is Local. | |
* The scope of a property is not saved in the document. It is a value that needs to be fixed when | |
* the object holding the property is loaded. That is possible with two methods: | |
* 1. Set the scope value in the constructor of the link property | |
* 2. Use setScope to change the scope in the constructor of the link property | |
* | |
* The second option is only available in c++, not in python, as setscope is not exposed. It would | |
* not make sense to expose it there, as restoring python objects does not call the constructor again. | |
* Hence in python the only way to create a LinkProperty with different scope than local is to use a | |
* specialized property for that. In c++ existing properties can simply be changed via setScope in the | |
* objects constructor. | |
*/ | |
class AppExport ScopedLink { | |
public: | |
/** | |
* @brief Set the links scope | |
* Allows to define what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and | |
* all Childs or to all objects within the Glocal scope. | |
*/ | |
void setScope(LinkScope scope) {_pcScope = scope;}; | |
/** | |
* @brief Get the links scope | |
* Retrieve what kind of links are allowed. Only in the Local GeoFeatureGroup, in this and | |
* all Childs or to all objects within the Glocal scope. | |
*/ | |
LinkScope getScope() {return _pcScope;}; | |
protected: | |
LinkScope _pcScope = LinkScope::Local; | |
}; | |
/// Parent class of all link type properties | |
class AppExport PropertyLinkBase : public Property, public ScopedLink | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
typedef std::pair<std::string,std::string> ShadowSub; | |
PropertyLinkBase(); | |
virtual ~PropertyLinkBase(); | |
friend class DocInfo; | |
/** Link type property interface APIs | |
* These APIs are moved here so that any type of property can have the | |
* property link behavior, e.g. the PropertyExpressionEngine | |
*/ | |
//@{ | |
/** Called to update the element reference of this link property | |
* | |
* @sa _updateElementReference() | |
*/ | |
virtual void updateElementReference(App::DocumentObject *feature, | |
bool reverse=false, bool notify=false) | |
{ | |
(void)feature; | |
(void)reverse; | |
(void)notify; | |
} | |
/// Clear internal element reference registration | |
void unregisterElementReference(); | |
/** Register label reference for future object relabel update | |
* | |
* @param labels: labels to be registered | |
* @param reset: if ture, then calls unregisterLabelReference() before | |
* registering | |
*/ | |
void registerLabelReferences(std::vector<std::string> &&labels, bool reset=true); | |
/** Check subnames for label registeration | |
* | |
* @param subs: subname references | |
* @param reset: if ture, then calls unregisterLabelReference() before | |
* registering | |
* | |
* Check the give subname references and extract any label reference | |
* inside (by calling getLabelReferences()), and register them. | |
*/ | |
void checkLabelReferences(const std::vector<std::string> &subs, bool reset=true); | |
/// Clear internal label references registration | |
void unregisterLabelReferences(); | |
/// Test if the element reference has changed after restore | |
virtual bool referenceChanged() const { | |
return false; | |
} | |
/** Test if the link is restored unchanged | |
* | |
* @param msg: optional error message | |
* | |
* @return For external linked object, return 2 in case the link is | |
* missing, and 1 if the time stamp has changed. | |
*/ | |
virtual int checkRestore(std::string *msg=0) const { | |
(void)msg; | |
return 0; | |
} | |
/** Obtain the linked objects | |
* | |
* @param objs: hold the returned linked objects on output | |
* @param all: if true, then return all the linked object regardless of | |
* this LinkScope. If false, then return only if the LinkScope | |
* is not hidden. | |
* @param sub: if given, then return subname references. | |
* @param newStyle: whether to return new or old style subname reference | |
*/ | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const = 0; | |
/** Called to reset this link property | |
* | |
* @param obj: reset link property if it is linked to this object | |
* @param clear: if true, then also reset property if the owner of this proeprty is \a obj | |
* | |
* @sa breakLinks() | |
*/ | |
virtual void breakLink(App::DocumentObject *obj, bool clear) = 0; | |
/** Called to adjust the link to avoid potential cyclic dependency | |
* | |
* @param inList: recursive in-list of the would-be parent | |
* | |
* @return Return whether the link has been adjusted | |
* | |
* This function tries to correct the link to avoid any (sub)object inside | |
* in-list. If the adjustment is impossible, exception will be raised | |
*/ | |
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) = 0; | |
/** Return a copy of the property if the link replacement affects this property | |
* | |
* @param owner: the parent object whose link property is to be replace. | |
* Note that The parent may not be the container of this | |
* property. Link sub property can use this opportunity to | |
* adjust its relative links. | |
* @param oldObj: object to be replaced | |
* @param newObj: object to replace with | |
* | |
* @return Return a copy of the property that is adjusted for the link | |
* replacement operation. | |
*/ | |
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, App::DocumentObject *newObj) const = 0; | |
/** Return a copy of the property if any changes caused by importing external linked object | |
* | |
* @param nameMap: a map from the original external object name to the | |
* imported new object name | |
* | |
* @return Returns a copy of the property with the updated link reference if | |
* affected. The copy will later be assgiend to this property by calling its | |
* Paste(). | |
*/ | |
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const { | |
(void)nameMap; | |
return 0; | |
} | |
/** Update object label reference in this property | |
* | |
* @param obj: the object owner of the changing label | |
* @param ref: subname reference to old label | |
* @param newLabel: the future new label | |
* | |
* @return Returns a copy of the property if its link reference is affected. | |
* The copy will later be assgiend to this property by calling its Paste(). | |
*/ | |
virtual Property *CopyOnLabelChange(App::DocumentObject *obj, | |
const std::string &ref, const char *newLabel) const | |
{ | |
(void)obj; | |
(void)ref; | |
(void)newLabel; | |
return 0; | |
} | |
/// Helper function to return all linked objects of this property | |
std::vector<App::DocumentObject *> linkedObjects(bool all=false) const { | |
std::vector<App::DocumentObject*> ret; | |
getLinks(ret,all); | |
return ret; | |
} | |
/// Helper function to return linked objects using an std::inserter | |
template<class T> | |
void getLinkedObjects(T &inserter, bool all=false) const { | |
std::vector<App::DocumentObject*> ret; | |
getLinks(ret,all); | |
std::copy(ret.begin(),ret.end(),inserter); | |
} | |
/// Helper function to return a map of linked object and its subname references | |
void getLinkedElements(std::map<App::DocumentObject*, std::vector<std::string> > &elements, | |
bool newStyle=true, bool all=true) const | |
{ | |
std::vector<App::DocumentObject*> ret; | |
std::vector<std::string> subs; | |
getLinks(ret,all,&subs,newStyle); | |
assert(ret.size()==subs.size()); | |
int i=0; | |
for(auto obj : ret) | |
elements[obj].push_back(subs[i++]); | |
} | |
/// Helper function to return a map of linked object and its subname references | |
std::map<App::DocumentObject*, std::vector<std::string> > | |
linkedElements(bool newStyle=true, bool all=true) const | |
{ | |
std::map<App::DocumentObject*, std::vector<std::string> > ret; | |
getLinkedElements(ret,newStyle,all); | |
return ret; | |
} | |
//@} | |
/** Enable/disable temporary holding external object without throwing exception | |
* | |
* Warning, non-PropertyXLink related property does not have internal | |
* tracking of external objects, therefore the link will not by auto broken | |
* when external document is closed. Only use this for temporary case, or | |
* if you handle signalDeleteDocument yourself, or use one of the | |
* ProeprtyXLink related property. | |
*/ | |
void setAllowExternal(bool allow); | |
/// Helper functions | |
//@{ | |
/** Helper function to check and replace a link | |
* | |
* @param owner: the owner of the current property | |
* @param obj: the current linked object | |
* @param parent: the parent of the changing link property, may or may not | |
* be equal to \c owner | |
* @param oldObj: the object to be replaced | |
* @param newObj: the object to replace with | |
* @param sub: optional the current subname reference | |
* | |
* @return Returns a pair(obj,subname). If no replacement is found, | |
* pair.first will be NULL | |
* | |
* Say a group has one of its child object replaced with another. Any | |
* existing link sub reference that refer to the original child object | |
* through the group will be broken. This helper function is used to check | |
* and correct any link sub reference. | |
*/ | |
static std::pair<App::DocumentObject*,std::string> tryReplaceLink( | |
const App::PropertyContainer *owner, App::DocumentObject *obj, | |
const App::DocumentObject *parent, App::DocumentObject *oldObj, | |
App::DocumentObject *newObj, const char *sub=0); | |
/** Helper function to check and replace a link with multiple subname refereces | |
* | |
* @param owner: the owner of the current property | |
* @param obj: the current linked object | |
* @param parent: the parent of the changing link property, may or may not | |
* be equal to \c owner | |
* @param oldObj: the object to be replaced | |
* @param newObj: the object to replace with | |
* @param subs: the current subname references | |
* | |
* @return Returns the a pair(obj,subs). If no replacement is found, | |
* pair.first will be NULL | |
* @sa tryReplaceLink() | |
*/ | |
static std::pair<App::DocumentObject*, std::vector<std::string> > | |
tryReplaceLinkSubs( const App::PropertyContainer *owner, | |
App::DocumentObject *obj, | |
const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, | |
App::DocumentObject *newObj, | |
const std::vector<std::string> &subs); | |
/// Update all element references in all link properties of \a feature | |
static void updateElementReferences(DocumentObject *feature, bool reverse=false); | |
/** Helper function for update individual element reference | |
* | |
* @param feature: if given, than only update element reference belonging | |
* to this feature. If not, then update geometry element | |
* references. | |
* @param sub: the subname reference to be updated. | |
* @param shadow: a pair of new and old style element references to be updated. | |
* @param reverse: if true, then use the old style, i.e. non-mapped element | |
* reference to query for the new style, i.e. mapped | |
* element reference when update. If false, then the other | |
* way around. | |
* @param notify: if true, call aboutToSetValue() before change | |
* | |
* This helper function is to be called by each link property in the event of | |
* geometry element reference change due to geometry model changes. | |
*/ | |
bool _updateElementReference(App::DocumentObject *feature, | |
App::DocumentObject *obj, std::string &sub, ShadowSub &shadow, | |
bool reverse, bool notify=false); | |
/** Helper function to register geometry element reference | |
* | |
* @param obj: the linked object | |
* @param sub: the subname reference | |
* @param shadow: a pair of new and old style element references to be updated. | |
* | |
* Search for any geometry element reference inside the subname, and | |
* register for future update in case of geometry model update. | |
*/ | |
void _registerElementReference(App::DocumentObject *obj, std::string &sub, ShadowSub &shadow); | |
/** Helper function for breaking link properties | |
* | |
* @param link: reset link property if it is linked to this object | |
* @param objs: the objects to check for the link properties | |
* @param clear: if ture, then also reset property if the owner of the link property is \a link | |
* | |
* App::Document::breakDependency() calls this function to break the link property | |
*/ | |
static void breakLinks(App::DocumentObject *link, const std::vector<App::DocumentObject*> &objs, bool clear); | |
/** Helper function for link import operation | |
* | |
* @param obj: the linked object | |
* @param sub: subname reference | |
* @param doc: importing document | |
* @param nameMap: a name map from source object to its imported counter part | |
* | |
* @return Return a changed subname reference, or empty string if no change. | |
* | |
* Link import operation will go through all link property and imports all | |
* externally linked object. After import, the link property must be | |
* changed to point to the newly imported objects, which should happen inside | |
* the API CopyOnImportExternal(). This function helps to rewrite subname | |
* reference to point to the correct sub objects that are imported. | |
*/ | |
static std::string tryImportSubName(const App::DocumentObject *obj, const char *sub, | |
const App::Document *doc, const std::map<std::string,std::string> &nameMap); | |
/** Helper function for link import operation | |
* | |
* @param doc: owner document of the imported objects | |
* @param obj: the linked object | |
* @param nameMap: a name map from source object to its imported counter part | |
* | |
* @return Return the imported object if found, or the input \c obj if no change. | |
* @sa tryImportSubNames | |
* | |
* This function searches for the name map and tries to find the imported | |
* object from the given source object. | |
*/ | |
static App::DocumentObject *tryImport(const App::Document *doc, const App::DocumentObject *obj, | |
const std::map<std::string,std::string> &nameMap); | |
/** Helper function to export a subname reference | |
* | |
* @param output: output subname if the subname is modified | |
* @param obj: linked object | |
* @param sub: input subname reference | |
* @param first_obj: if true, then the first object referenced in subname | |
* is obtained by searching the owner document of obj, | |
* otherwise the subname search among obj's sub-objects. | |
* | |
* @return Return output.c_str() if the subname is modified for exporting | |
* otherwise, return the input subname | |
* | |
* @sa importSubName(), restoreLabelReference() | |
* | |
* The function go through the input subname reference and changes any sub | |
* object references inside for exporting. If the sub object is referenced | |
* by its internal object name, then the reference is changed from | |
* 'objName' to 'objName@docName'. If referenced by label, then it will be | |
* changed to 'objName@docName@' instead. importSubName() and | |
* restoreLabelReference() can be used together to restore the reference | |
* during import. | |
*/ | |
static const char *exportSubName(std::string &output, | |
const App::DocumentObject *obj, const char *subname, bool first_obj=false); | |
/** Helper function to import a subname reference | |
* | |
* @param reader: the import reader | |
* @param sub: input subname reference | |
* @param restoreLabel: output indicate whether post process is required | |
* after restore. | |
* | |
* @sa exportSubName(), restoreLabelReference() | |
* | |
* @return return either an updated subname reference or the input | |
* reference if no change. If restoreLabel is set to true on output, it | |
* means there are some label reference changes that must be corrected | |
* after restore, by calling restoreLabelReference() in property's | |
* afterRestore(). | |
*/ | |
static std::string importSubName(Base::XMLReader &reader, const char *sub, bool &restoreLabel); | |
/** Helper function to restore label references during import | |
* | |
* @param obj: linked object | |
* @param sub: subname reference | |
* @param shadow: optional shadow subname reference | |
* | |
* @sa exportSubName(), importSubName() | |
* | |
* When exporting and importing (i.e. copy and paste) objects into the same | |
* document, the new object must be renamed, both the internal name and the | |
* label. Therefore, the link reference of the new objects must be | |
* corrected accordingly. The basic idea is that when exporting object, all | |
* object name references are changed to 'objName@docName', and label | |
* references are changed to 'objName@docName@'. During import, | |
* MergeDocument will maintain a map from objName@docName to object's new | |
* name. Object name reference can be restored on spot by consulting the | |
* map, while label reference will be restored later in property's | |
* afterRestore() function, which calls this function to do the string | |
* parsing. | |
*/ | |
static void restoreLabelReference(const App::DocumentObject *obj, std::string &sub, ShadowSub *shadow=0); | |
/** Helper function to extract labels from a subname reference | |
* | |
* @param labels: output vector of extracted labels | |
* @param subname: subname reference | |
* | |
* @sa registerLabelReferences() | |
* | |
* This function is used to extrac label from subname reference for | |
* registering of label changes. | |
*/ | |
static void getLabelReferences(std::vector<std::string> &labels, const char *subname); | |
/** Helper function to collect changed property when an object re-label | |
* | |
* @param obj: the object that owns the label | |
* @param newLabel: the new label | |
* | |
* @return return a map from the affected property to a copy of it with | |
* updated subname references | |
*/ | |
static std::vector<std::pair<Property*, std::unique_ptr<Property> > > updateLabelReferences( | |
App::DocumentObject *obj, const char *newLabel); | |
/** Helper function to update subname reference on label change | |
* | |
* @param linked: linked object | |
* @param subname: subname reference | |
* @param obj: the object that owns the label | |
* @param ref: label reference in the format of '$<old_label>.', which is | |
* the format used in subname reference for label reference. | |
* This parameter is provided for easy search of label | |
* reference. | |
* @param newLabel: new label | |
* | |
* @return Returns an updated subname reference, or empty string if no change. | |
* | |
* This function helps to update subname reference on label change. It is | |
* usually called inside CopyOnLabelChange(), the API for handling label | |
* change, which is called just before label change. In other word, when | |
* called, the sub object can still be reached using the original label | |
* references, but not the new labels. | |
*/ | |
static std::string updateLabelReference(const App::DocumentObject *linked, const char *subname, | |
App::DocumentObject *obj, const std::string &ref, const char *newLabel); | |
//@} | |
enum LinkFlags { | |
LinkAllowExternal, | |
LinkDetached, | |
LinkRestoring, | |
LinkAllowPartial, | |
LinkRestoreLabel, | |
}; | |
inline bool testFlag(int flag) const { | |
return _Flags.test((std::size_t)flag); | |
} | |
virtual void setAllowPartial(bool enable) { (void)enable; } | |
protected: | |
virtual void hasSetValue() override; | |
protected: | |
std::bitset<32> _Flags; | |
inline void setFlag(int flag, bool value=true) { | |
_Flags.set((std::size_t)flag,value); | |
} | |
private: | |
std::set<std::string> _LabelRefs; | |
std::set<App::DocumentObject*> _ElementRefs; | |
}; | |
/** The general Link Property | |
* Main Purpose of this property is to Link Objects and Features in a document. Like all links this | |
* property is scope aware, meaning it does define which objects are allowed to be linked depending | |
* of the GeoFeatureGroup where it is in. Default is Local. | |
* | |
* @note Links that are invalid in respect to the scope of this property is set to are not rejected. | |
* They are only detected to be invalid and prevent the feature from recomputing. | |
*/ | |
class AppExport PropertyLink : public PropertyLinkBase | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
/** | |
* A constructor. | |
* A more elaborate description of the constructor. | |
*/ | |
PropertyLink(); | |
/** | |
* A destructor. | |
* A more elaborate description of the destructor. | |
*/ | |
virtual ~PropertyLink(); | |
void resetLink(); | |
/** Sets the property | |
*/ | |
virtual void setValue(App::DocumentObject *); | |
/** This method returns the linked DocumentObject | |
*/ | |
App::DocumentObject * getValue(void) const; | |
/** Returns the link type checked | |
*/ | |
App::DocumentObject * getValue(Base::Type t) const; | |
/** Returns the link type checked | |
*/ | |
template <typename _type> | |
inline _type getValue(void) const { | |
return _pcLink ? dynamic_cast<_type>(_pcLink) : 0; | |
} | |
virtual PyObject *getPyObject(void); | |
virtual void setPyObject(PyObject *); | |
virtual void Save (Base::Writer &writer) const; | |
virtual void Restore(Base::XMLReader &reader); | |
virtual Property *Copy(void) const; | |
virtual void Paste(const Property &from); | |
virtual unsigned int getMemSize (void) const{ | |
return sizeof(App::DocumentObject *); | |
} | |
virtual const char* getEditorName(void) const | |
{ return "Gui::PropertyEditor::PropertyLinkItem"; } | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override; | |
virtual void breakLink(App::DocumentObject *obj, bool clear) override; | |
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) override; | |
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; | |
protected: | |
App::DocumentObject *_pcLink; | |
}; | |
/** The general Link Property with Child scope | |
*/ | |
class AppExport PropertyLinkChild : public PropertyLink | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkChild() {_pcScope = LinkScope::Child;}; | |
}; | |
/** The general Link Property with Global scope | |
*/ | |
class AppExport PropertyLinkGlobal : public PropertyLink | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkGlobal() {_pcScope = LinkScope::Global;}; | |
}; | |
/** The general Link Property that are hidden from dependency checking | |
*/ | |
class AppExport PropertyLinkHidden : public PropertyLink | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkHidden() {_pcScope = LinkScope::Hidden;}; | |
}; | |
class AppExport PropertyLinkListBase: public PropertyLinkBase, public PropertyListsBase | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
virtual void setPyObject(PyObject *obj) override { | |
_setPyObject(obj); | |
} | |
}; | |
class AppExport PropertyLinkList : | |
public PropertyListsT<DocumentObject*,std::vector<DocumentObject*>, PropertyLinkListBase> | |
{ | |
TYPESYSTEM_HEADER(); | |
typedef PropertyListsT<DocumentObject*,std::vector<DocumentObject*>,PropertyLinkListBase> inherited; | |
public: | |
/** | |
* A constructor. | |
* A more elaborate description of the constructor. | |
*/ | |
PropertyLinkList(); | |
/** | |
* A destructor. | |
* A more elaborate description of the destructor. | |
*/ | |
virtual ~PropertyLinkList(); | |
virtual void setSize(int newSize); | |
virtual void setSize(int newSize, const_reference def); | |
/** Sets the property | |
*/ | |
void setValues(const std::vector<DocumentObject*>&) override; | |
void set1Value(int idx, DocumentObject * const &value) override; | |
virtual PyObject *getPyObject(void); | |
virtual void Save(Base::Writer &writer) const; | |
virtual void Restore(Base::XMLReader &reader); | |
virtual Property *Copy(void) const; | |
virtual void Paste(const Property &from); | |
virtual unsigned int getMemSize(void) const; | |
virtual const char* getEditorName(void) const | |
{ return "Gui::PropertyEditor::PropertyLinkListItem"; } | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override; | |
virtual void breakLink(App::DocumentObject *obj, bool clear) override; | |
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) override; | |
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; | |
DocumentObject *find(const std::string &, int *pindex=0) const; | |
DocumentObject *find(const char *sub, int *pindex=0) const { | |
if(!sub) return 0; | |
return find(std::string(sub),pindex); | |
} | |
protected: | |
DocumentObject *getPyValue(PyObject *item) const override; | |
protected: | |
mutable std::map<std::string, int> _nameMap; | |
}; | |
/** The general Link Property with Child scope | |
*/ | |
class AppExport PropertyLinkListChild : public PropertyLinkList | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkListChild() {_pcScope = LinkScope::Child;}; | |
}; | |
/** The general Link Property with Global scope | |
*/ | |
class AppExport PropertyLinkListGlobal : public PropertyLinkList | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkListGlobal() {_pcScope = LinkScope::Global;}; | |
}; | |
/** The general Link Property that are hidden from dependency checking | |
*/ | |
class AppExport PropertyLinkListHidden : public PropertyLinkList | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkListHidden() {_pcScope = LinkScope::Hidden;}; | |
}; | |
class PropertyXLinkSub; | |
/** the Link Property with sub elements | |
* This property links an object and a defined sequence of | |
* sub elements. These subelements (like Edges of a Shape) | |
* are stored as names, which can be resolved by the | |
* ComplexGeoDataType interface to concrete sub objects. | |
*/ | |
class AppExport PropertyLinkSub : public PropertyLinkBase | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
/** | |
* A constructor. | |
* A more elaborate description of the constructor. | |
*/ | |
PropertyLinkSub(); | |
/** | |
* A destructor. | |
* A more elaborate description of the destructor. | |
*/ | |
virtual ~PropertyLinkSub(); | |
virtual void afterRestore() override; | |
virtual void onContainerRestored() override; | |
/** Sets the property | |
*/ | |
void setValue(App::DocumentObject *,const std::vector<std::string> &SubList, | |
std::vector<ShadowSub> &&ShadowSubList={}); | |
void setValue(App::DocumentObject *,std::vector<std::string> &&SubList={}, | |
std::vector<ShadowSub> &&ShadowSubList={}); | |
/** This method returns the linked DocumentObject | |
*/ | |
App::DocumentObject * getValue(void) const; | |
/// return the list of sub elements | |
const std::vector<std::string>& getSubValues(void) const; | |
/// return the list of sub elements with mapped names | |
const std::vector<ShadowSub> &getShadowSubs() const { | |
return _ShadowSubList; | |
} | |
std::vector<std::string> getSubValues(bool newStyle) const; | |
/// return the list of sub elements starts with a special string | |
std::vector<std::string> getSubValuesStartsWith(const char*, bool newStyle=false) const; | |
/** Returns the link type checked | |
*/ | |
App::DocumentObject * getValue(Base::Type t) const; | |
/** Returns the link type checked | |
*/ | |
template <typename _type> | |
inline _type getValue(void) const { | |
return _pcLinkSub ? dynamic_cast<_type>(_pcLinkSub) : 0; | |
} | |
virtual PyObject *getPyObject(void); | |
virtual void setPyObject(PyObject *); | |
virtual void Save (Base::Writer &writer) const; | |
virtual void Restore(Base::XMLReader &reader); | |
virtual Property *Copy(void) const; | |
virtual void Paste(const Property &from); | |
/// Return a copy of the property if any changes caused by importing external object | |
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override; | |
virtual Property *CopyOnLabelChange(App::DocumentObject *obj, | |
const std::string &ref, const char *newLabel) const override; | |
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; | |
virtual unsigned int getMemSize (void) const{ | |
return sizeof(App::DocumentObject *); | |
} | |
virtual void updateElementReference( | |
DocumentObject *feature,bool reverse=false, bool notify=false) override; | |
virtual bool referenceChanged() const override; | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override; | |
virtual void breakLink(App::DocumentObject *obj, bool clear) override; | |
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) override; | |
protected: | |
App::DocumentObject* _pcLinkSub; | |
std::vector<std::string> _cSubList; | |
std::vector<ShadowSub> _ShadowSubList; | |
std::vector<int> _mapped; | |
bool _restoreLabel; | |
}; | |
/** The general Link Property with Child scope | |
*/ | |
class AppExport PropertyLinkSubChild : public PropertyLinkSub | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkSubChild() {_pcScope = LinkScope::Child;}; | |
}; | |
/** The general Link Property with Global scope | |
*/ | |
class AppExport PropertyLinkSubGlobal : public PropertyLinkSub | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkSubGlobal() {_pcScope = LinkScope::Global;}; | |
}; | |
/** The general Link Property that are hidden from dependency checking | |
*/ | |
class AppExport PropertyLinkSubHidden : public PropertyLinkSub | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkSubHidden() {_pcScope = LinkScope::Hidden;}; | |
}; | |
class AppExport PropertyLinkSubList : public PropertyLinkBase | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
typedef std::pair<DocumentObject*, std::vector<std::string> > SubSet; | |
/** | |
* A constructor. | |
* A more elaborate description of the constructor. | |
*/ | |
PropertyLinkSubList(); | |
/** | |
* A destructor. | |
* A more elaborate description of the destructor. | |
*/ | |
virtual ~PropertyLinkSubList(); | |
virtual void afterRestore() override; | |
virtual void onContainerRestored() override; | |
int getSize(void) const; | |
void setSize(int newSize); | |
/** Sets the property. | |
* setValue(0, whatever) clears the property | |
*/ | |
void setValue(DocumentObject*,const char*); | |
void setValues(const std::vector<DocumentObject*>&,const std::vector<const char*>&); | |
void setValues(const std::vector<DocumentObject*>&,const std::vector<std::string>&, | |
std::vector<ShadowSub> &&ShadowSubList={}); | |
void setValues(std::vector<DocumentObject*>&&, std::vector<std::string> &&subs, | |
std::vector<ShadowSub> &&ShadowSubList={}); | |
/** | |
* @brief setValue: PropertyLinkSub-compatible overload | |
* @param SubList | |
*/ | |
void setValue(App::DocumentObject *lValue, const std::vector<std::string> &SubList=std::vector<std::string>()); | |
const std::vector<DocumentObject*> &getValues(void) const { | |
return _lValueList; | |
} | |
const std::string getPyReprString() const; | |
/** | |
* @brief getValue emulates the action of a single-object link. | |
* @return reference to object, if the link is to only one object. NULL if | |
* the link is empty, or links to subelements of more than one document | |
* object. | |
*/ | |
DocumentObject* getValue() const; | |
const std::vector<std::string> &getSubValues(void) const { | |
return _lSubList; | |
} | |
std::vector<std::string> getSubValues(bool newStyle) const; | |
const std::vector<ShadowSub> &getShadowSubs() const { | |
return _ShadowSubList; | |
} | |
/** | |
* @brief Removes all occurrences of \a lValue in the property | |
* together with its sub-elements and returns the number of entries removed. | |
*/ | |
int removeValue(App::DocumentObject *lValue); | |
void setSubListValues(const std::vector<SubSet>&); | |
std::vector<SubSet> getSubListValues(bool newStyle=false) const; | |
virtual PyObject *getPyObject(void); | |
virtual void setPyObject(PyObject *); | |
virtual void Save (Base::Writer &writer) const; | |
virtual void Restore(Base::XMLReader &reader); | |
virtual Property *Copy(void) const; | |
virtual void Paste(const Property &from); | |
/// Return a copy of the property if any changes caused by importing external object | |
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override; | |
virtual Property *CopyOnLabelChange(App::DocumentObject *obj, | |
const std::string &ref, const char *newLabel) const override; | |
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; | |
virtual unsigned int getMemSize (void) const; | |
virtual void updateElementReference( | |
DocumentObject *feature,bool reverse=false, bool notify=false) override; | |
virtual bool referenceChanged() const override; | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override; | |
virtual void breakLink(App::DocumentObject *obj, bool clear) override; | |
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) override; | |
private: | |
//FIXME: Do not make two independent lists because this will lead to some inconsistencies! | |
std::vector<DocumentObject*> _lValueList; | |
std::vector<std::string> _lSubList; | |
std::vector<ShadowSub> _ShadowSubList; | |
std::vector<int> _mapped; | |
bool _restoreLabel; | |
}; | |
/** The general Link Property with Child scope | |
*/ | |
class AppExport PropertyLinkSubListChild : public PropertyLinkSubList | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkSubListChild() {_pcScope = LinkScope::Child;}; | |
}; | |
/** The general Link Property with Global scope | |
*/ | |
class AppExport PropertyLinkSubListGlobal : public PropertyLinkSubList | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkSubListGlobal() {_pcScope = LinkScope::Global;}; | |
}; | |
/** The general Link Property that are hidden from dependency checking | |
*/ | |
class AppExport PropertyLinkSubListHidden : public PropertyLinkSubList | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyLinkSubListHidden() {_pcScope = LinkScope::Hidden;}; | |
}; | |
class PropertyXLinkSubList; | |
/** Link to an (sub)object in the same or different document | |
*/ | |
class AppExport PropertyXLink : public PropertyLinkGlobal | |
{ | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyXLink(bool allowPartial=false, PropertyLinkBase *parent=0); | |
virtual ~PropertyXLink(); | |
PropertyLinkBase *parent() const { return parentProp; } | |
virtual void afterRestore() override; | |
virtual void onContainerRestored() override; | |
void setValue(App::DocumentObject *) override; | |
void setValue(App::DocumentObject *, const char *subname); | |
const char *getSubName(bool newStyle=true) const; | |
void setSubName(const char *subname); | |
bool hasSubName() const {return !_SubList.empty();} | |
App::Document *getDocument() const; | |
const char *getDocumentPath() const; | |
const char *getObjectName() const; | |
virtual int checkRestore(std::string *msg=0) const override; | |
virtual void Save (Base::Writer &writer) const; | |
virtual void Restore(Base::XMLReader &reader); | |
virtual Property *Copy(void) const; | |
virtual void Paste(const Property &from); | |
/// Return a copy of the property if any changes caused by importing external object | |
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override; | |
virtual Property *CopyOnLabelChange(App::DocumentObject *obj, | |
const std::string &ref, const char *newLabel) const override; | |
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; | |
virtual PyObject *getPyObject(void); | |
virtual void setPyObject(PyObject *); | |
friend class DocInfo; | |
static bool supportXLink(const App::Property *prop); | |
static bool hasXLink(const App::Document *doc); | |
static bool hasXLink(const std::vector<App::DocumentObject*> &objs, std::vector<App::Document*> *unsaved=0); | |
static std::map<App::Document*,std::set<App::Document*> > getDocumentOutList(App::Document *doc=0); | |
static std::map<App::Document*,std::set<App::Document*> > getDocumentInList(App::Document *doc=0); | |
virtual void updateElementReference( | |
DocumentObject *feature,bool reverse=false, bool notify=false) override; | |
virtual bool referenceChanged() const override; | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override; | |
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) override; | |
// The following APIs are provided to be compatible with PropertyLinkSub. | |
// Note that although PropertyXLink is capable of holding multiple subnames, | |
// there no public APIs allowing user to set more that one subname. Multiple | |
// subname adding API is published in PropertyXLinkSub. | |
const std::vector<std::string>& getSubValues(void) const { | |
return _SubList; | |
} | |
const std::vector<ShadowSub > &getShadowSubs() const { | |
return _ShadowSubList; | |
} | |
std::vector<std::string> getSubValues(bool newStyle) const; | |
std::vector<std::string> getSubValuesStartsWith(const char*, bool newStyle=false) const; | |
virtual void setAllowPartial(bool enable) override; | |
protected: | |
void unlink(); | |
void detach(); | |
void restoreLink(App::DocumentObject *); | |
void _setSubValues(std::vector<std::string> &&SubList, | |
std::vector<ShadowSub> &&ShadowSubList = {}); | |
void _setValue(std::string &&filePath, std::string &&objectName, std::vector<std::string> &&SubList, | |
std::vector<ShadowSub> &&ShadowSubList = {}); | |
void _setValue(App::DocumentObject *,std::vector<std::string> &&SubList, | |
std::vector<ShadowSub> &&ShadowSubList = {}); | |
virtual PropertyXLink *createInstance() const; | |
virtual bool upgrade(Base::XMLReader &reader, const char *typeName); | |
void copyTo(PropertyXLink &other, App::DocumentObject *linked=0, std::vector<std::string> *subs=0) const; | |
virtual void aboutToSetValue() override; | |
virtual void hasSetValue() override; | |
friend class PropertyXLinkSubList; | |
protected: | |
DocInfoPtr docInfo; | |
std::string filePath; | |
std::string docName; | |
std::string objectName; | |
std::string stamp; | |
std::vector<std::string> _SubList; | |
std::vector<ShadowSub> _ShadowSubList; | |
std::vector<int> _mapped; | |
PropertyLinkBase *parentProp; | |
}; | |
/** Link to one or more (sub)object from the same or different document | |
*/ | |
class AppExport PropertyXLinkSub: public PropertyXLink { | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyXLinkSub(bool allowPartial=false, PropertyLinkBase *parent=0); | |
virtual ~PropertyXLinkSub(); | |
void setValue(App::DocumentObject *,const std::vector<std::string> &SubList, | |
std::vector<ShadowSub > &&ShadowSubList={}); | |
void setValue(App::DocumentObject *,std::vector<std::string> &&SubList={}, | |
std::vector<ShadowSub > &&ShadowSubList={}); | |
void setSubValues(std::vector<std::string> &&SubList, | |
std::vector<ShadowSub> &&ShadowSubList={}); | |
virtual bool upgrade(Base::XMLReader &reader, const char *typeName) override; | |
virtual PyObject *getPyObject(void); | |
virtual void setPyObject(PyObject *); | |
protected: | |
virtual PropertyXLink *createInstance() const; | |
}; | |
/** Link to one or more (sub)object(s) of one or more object(s) from the same or different document | |
*/ | |
class AppExport PropertyXLinkSubList: public PropertyLinkBase { | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyXLinkSubList(); | |
virtual ~PropertyXLinkSubList(); | |
virtual void afterRestore() override; | |
virtual void onContainerRestored() override; | |
int getSize(void) const; | |
/** Sets the property. | |
* setValue(0, whatever) clears the property | |
*/ | |
void setValue(DocumentObject*,const char*); | |
void setValues(const std::vector<DocumentObject*>&,const std::vector<const char*>&); | |
void setValues(const std::vector<DocumentObject*>&,const std::vector<std::string>&); | |
void setValues(std::map<App::DocumentObject*,std::vector<std::string> > &&); | |
void setValues(const std::map<App::DocumentObject*,std::vector<std::string> > &); | |
void addValue(App::DocumentObject *obj, const std::vector<std::string> &SubList={}, bool reset=false); | |
void addValue(App::DocumentObject *obj, std::vector<std::string> &&SubList={}, bool reset=false); | |
/** | |
* @brief setValue: PropertyLinkSub-compatible overload | |
* @param SubList | |
*/ | |
void setValue(App::DocumentObject *lValue, const std::vector<std::string> &SubList=std::vector<std::string>()); | |
std::vector<DocumentObject*> getValues(void); | |
const std::string getPyReprString() const; | |
DocumentObject* getValue() const; | |
const std::vector<std::string> &getSubValues(App::DocumentObject *obj) const; | |
std::vector<std::string> getSubValues(App::DocumentObject *obj, bool newStyle) const; | |
const std::vector<ShadowSub> &getShadowSubs(App::DocumentObject *obj) const; | |
/** | |
* @brief Removes all occurrences of \a lValue in the property | |
* together with its sub-elements and returns the number of entries removed. | |
*/ | |
int removeValue(App::DocumentObject *lValue); | |
void setSubListValues(const std::vector<PropertyLinkSubList::SubSet>&); | |
const std::list<PropertyXLinkSub> &getSubListValues() const { | |
return _Links; | |
} | |
virtual PyObject *getPyObject(void); | |
virtual void setPyObject(PyObject *); | |
virtual void Save (Base::Writer &writer) const; | |
virtual void Restore(Base::XMLReader &reader); | |
virtual Property *Copy(void) const; | |
virtual void Paste(const Property &from); | |
virtual Property *CopyOnImportExternal(const std::map<std::string,std::string> &nameMap) const override; | |
virtual Property *CopyOnLabelChange(App::DocumentObject *obj, | |
const std::string &ref, const char *newLabel) const override; | |
virtual Property *CopyOnLinkReplace(const App::DocumentObject *parent, | |
App::DocumentObject *oldObj, App::DocumentObject *newObj) const override; | |
virtual unsigned int getMemSize (void) const; | |
virtual void updateElementReference( | |
DocumentObject *feature,bool reverse=false, bool notify=false) override; | |
virtual bool referenceChanged() const override; | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override; | |
virtual void breakLink(App::DocumentObject *obj, bool clear) override; | |
virtual bool adjustLink(const std::set<App::DocumentObject *> &inList) override; | |
bool upgrade(Base::XMLReader &reader, const char *typeName); | |
virtual int checkRestore(std::string *msg=0) const override; | |
virtual void setAllowPartial(bool enable) override; | |
virtual void hasSetChildValue(Property &) override; | |
virtual void aboutToSetChildValue(Property &) override; | |
protected: | |
std::list<PropertyXLinkSub> _Links; | |
}; | |
/** Abstract property that can link to multiple external objects | |
* | |
* @sa See PropertyExpressionEngine for example usage | |
*/ | |
class AppExport PropertyXLinkContainer : public PropertyLinkBase { | |
TYPESYSTEM_HEADER(); | |
public: | |
PropertyXLinkContainer(); | |
~PropertyXLinkContainer(); | |
virtual void afterRestore() override; | |
virtual int checkRestore(std::string *msg=0) const override; | |
virtual void Save (Base::Writer &writer) const override; | |
virtual void Restore(Base::XMLReader &reader) override; | |
virtual void breakLink(App::DocumentObject *obj, bool clear) override; | |
virtual void getLinks(std::vector<App::DocumentObject *> &objs, | |
bool all=false, std::vector<std::string> *subs=0, bool newStyle=true) const override; | |
bool isLinkedToDocument(const App::Document &doc) const; | |
protected: | |
virtual void aboutToSetChildValue(App::Property &prop) override; | |
virtual PropertyXLink *createXLink(); | |
virtual void onBreakLink(App::DocumentObject *obj); | |
virtual void onAddDep(App::DocumentObject *) {} | |
virtual void onRemoveDep(App::DocumentObject *) {} | |
void updateDeps(std::set<DocumentObject*> &&newDeps); | |
void clearDeps(); | |
protected: | |
std::set<App::DocumentObject*> _Deps; | |
std::map<std::string, std::unique_ptr<PropertyXLink> > _XLinks; | |
std::map<std::string, std::string> _DocMap; | |
bool _LinkRestored; | |
private: | |
struct RestoreInfo { | |
std::unique_ptr<PropertyXLink> xlink; | |
std::string docName; | |
std::string docLabel; | |
}; | |
std::unique_ptr<std::vector<RestoreInfo> > _XLinkRestores; | |
}; | |
} // namespace App | |
#endif // APP_PROPERTYLINKS_H |