Add addObjects to add multiple objects in one step
This commit is contained in:
@@ -2206,6 +2206,93 @@ DocumentObject * Document::addObject(const char* sType, const char* pObjectName,
|
||||
return pcObject;
|
||||
}
|
||||
|
||||
std::vector<DocumentObject *> Document::addObjects(const char* sType, const std::vector<std::string>& objectNames, bool isNew)
|
||||
{
|
||||
Base::Type::importModule(sType);
|
||||
Base::Type type = Base::Type::fromName(sType);
|
||||
if (!type.isDerivedFrom(App::DocumentObject::getClassTypeId())) {
|
||||
std::stringstream str;
|
||||
str << "'" << sType << "' is not a document object type";
|
||||
throw Base::TypeError(str.str());
|
||||
}
|
||||
|
||||
std::vector<DocumentObject *> objects;
|
||||
objects.resize(objectNames.size());
|
||||
std::generate(objects.begin(), objects.end(),
|
||||
[&]{ return static_cast<App::DocumentObject*>(type.createInstance()); });
|
||||
|
||||
// get all existing object names
|
||||
std::vector<std::string> reservedNames;
|
||||
reservedNames.reserve(d->objectMap.size());
|
||||
for (auto pos = d->objectMap.begin();pos != d->objectMap.end();++pos) {
|
||||
reservedNames.push_back(pos->first);
|
||||
}
|
||||
|
||||
for (auto it = objects.begin(); it != objects.end(); ++it) {
|
||||
auto index = std::distance(objects.begin(), it);
|
||||
App::DocumentObject* pcObject = *it;
|
||||
pcObject->setDocument(this);
|
||||
|
||||
// do no transactions if we do a rollback!
|
||||
if (!d->rollback) {
|
||||
// Undo stuff
|
||||
if (d->activeUndoTransaction) {
|
||||
d->activeUndoTransaction->addObjectDel(pcObject);
|
||||
}
|
||||
}
|
||||
|
||||
// get unique name
|
||||
std::string ObjectName = objectNames[index];
|
||||
if (ObjectName.empty())
|
||||
ObjectName = sType;
|
||||
ObjectName = Base::Tools::getIdentifier(ObjectName);
|
||||
if (d->objectMap.find(ObjectName) != d->objectMap.end()) {
|
||||
// remove also trailing digits from clean name which is to avoid to create lengthy names
|
||||
// like 'Box001001'
|
||||
if (!testStatus(KeepTrailingDigits)) {
|
||||
std::string::size_type index = ObjectName.find_last_not_of("0123456789");
|
||||
if (index+1 < ObjectName.size()) {
|
||||
ObjectName = ObjectName.substr(0,index+1);
|
||||
}
|
||||
}
|
||||
|
||||
ObjectName = Base::Tools::getUniqueName(ObjectName, reservedNames, 3);
|
||||
}
|
||||
|
||||
reservedNames.push_back(ObjectName);
|
||||
|
||||
// insert in the name map
|
||||
d->objectMap[ObjectName] = pcObject;
|
||||
// cache the pointer to the name string in the Object (for performance of DocumentObject::getNameInDocument())
|
||||
pcObject->pcNameInDocument = &(d->objectMap.find(ObjectName)->first);
|
||||
// insert in the vector
|
||||
d->objectArray.push_back(pcObject);
|
||||
|
||||
pcObject->Label.setValue(ObjectName);
|
||||
|
||||
// Call the object-specific initialization
|
||||
if (!d->undoing && !d->rollback && isNew) {
|
||||
pcObject->setupObject();
|
||||
}
|
||||
|
||||
// mark the object as new (i.e. set status bit 2) and send the signal
|
||||
pcObject->StatusBits.set(2);
|
||||
signalNewObject(*pcObject);
|
||||
|
||||
// do no transactions if we do a rollback!
|
||||
if (!d->rollback && d->activeUndoTransaction) {
|
||||
signalTransactionAppend(*pcObject, d->activeUndoTransaction);
|
||||
}
|
||||
}
|
||||
|
||||
if (!objects.empty()) {
|
||||
d->activeObject = objects.back();
|
||||
signalActivatedObject(*objects.back());
|
||||
}
|
||||
|
||||
return objects;
|
||||
}
|
||||
|
||||
void Document::addObject(DocumentObject* pcObject, const char* pObjectName)
|
||||
{
|
||||
if (pcObject->getDocument()) {
|
||||
|
||||
@@ -182,6 +182,13 @@ public:
|
||||
* @param isNew if false don't call the \c DocumentObject::setupObject() callback (default is true)
|
||||
*/
|
||||
DocumentObject *addObject(const char* sType, const char* pObjectName=0, bool isNew=true);
|
||||
/** Add an array of features of the given types and names.
|
||||
* Unicode names are set through the Label propery.
|
||||
* @param sType The type of created object
|
||||
* @param objectNames A list of object names
|
||||
* @param isNew If false don't call the \c DocumentObject::setupObject() callback (default is true)
|
||||
*/
|
||||
std::vector<DocumentObject *>addObjects(const char* sType, const std::vector<std::string>& objectNames, bool isNew=true);
|
||||
/// Remove a feature out of the document
|
||||
void remObject(const char* sName);
|
||||
/** Add an existing feature with sName (ASCII) to this document and set it active.
|
||||
|
||||
@@ -75,6 +75,29 @@ void GroupExtension::addObject(DocumentObject* obj)
|
||||
}
|
||||
}
|
||||
|
||||
void GroupExtension::addObjects(const std::vector<App::DocumentObject*>& objs)
|
||||
{
|
||||
bool objectAdded = false;
|
||||
std::vector<DocumentObject*> grp = Group.getValues();
|
||||
for (auto obj : objs) {
|
||||
if (allowObject(obj)) {
|
||||
|
||||
//only one group per object
|
||||
auto *group = App::GroupExtension::getGroupOfObject(obj);
|
||||
if (group && group != getExtendedObject())
|
||||
group->getExtensionByType<App::GroupExtension>()->removeObject(obj);
|
||||
|
||||
if (std::find(grp.begin(), grp.end(), obj) == grp.end()) {
|
||||
grp.push_back(obj);
|
||||
objectAdded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (objectAdded)
|
||||
Group.setValues(grp);
|
||||
}
|
||||
|
||||
void GroupExtension::removeObject(DocumentObject* obj)
|
||||
{
|
||||
const std::vector<DocumentObject*> & grp = Group.getValues();
|
||||
|
||||
@@ -53,9 +53,12 @@ public:
|
||||
/* Adds the object \a obj to this group.
|
||||
*/
|
||||
virtual void addObject(DocumentObject* obj);
|
||||
/* Adds an array of object \a objs to this group.
|
||||
*/
|
||||
virtual void addObjects(const std::vector<App::DocumentObject*>& objs);
|
||||
/*override this function if you want only special objects
|
||||
*/
|
||||
virtual bool allowObject(DocumentObject* ) {return true;};
|
||||
virtual bool allowObject(DocumentObject* ) {return true;}
|
||||
|
||||
/** Removes an object from this group.
|
||||
*/
|
||||
|
||||
@@ -92,24 +92,7 @@ void *Type::createInstanceByName(const char* TypeName, bool bLoadModule)
|
||||
{
|
||||
// if not already, load the module
|
||||
if(bLoadModule)
|
||||
{
|
||||
// cut out the module name
|
||||
string Mod = getModuleName(TypeName);
|
||||
// ignore base modules
|
||||
if(Mod != "App" && Mod != "Gui" && Mod != "Base")
|
||||
{
|
||||
// remember already loaded modules
|
||||
set<string>::const_iterator pos = loadModuleSet.find(Mod);
|
||||
if(pos == loadModuleSet.end())
|
||||
{
|
||||
Interpreter().loadModule(Mod.c_str());
|
||||
#ifdef FC_LOGLOADMODULE
|
||||
Console().Log("Act: Module %s loaded through class %s \n",Mod.c_str(),TypeName);
|
||||
#endif
|
||||
loadModuleSet.insert(Mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
importModule(TypeName);
|
||||
|
||||
// now the type should be in the type map
|
||||
Type t = fromName(TypeName);
|
||||
@@ -117,7 +100,24 @@ void *Type::createInstanceByName(const char* TypeName, bool bLoadModule)
|
||||
return 0;
|
||||
|
||||
return t.createInstance();
|
||||
}
|
||||
|
||||
void Type::importModule(const char* TypeName)
|
||||
{
|
||||
// cut out the module name
|
||||
string Mod = getModuleName(TypeName);
|
||||
// ignore base modules
|
||||
if (Mod != "App" && Mod != "Gui" && Mod != "Base") {
|
||||
// remember already loaded modules
|
||||
set<string>::const_iterator pos = loadModuleSet.find(Mod);
|
||||
if (pos == loadModuleSet.end()) {
|
||||
Interpreter().loadModule(Mod.c_str());
|
||||
#ifdef FC_LOGLOADMODULE
|
||||
Console().Log("Act: Module %s loaded through class %s \n",Mod.c_str(),TypeName);
|
||||
#endif
|
||||
loadModuleSet.insert(Mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string Type::getModuleName(const char* ClassName)
|
||||
|
||||
@@ -87,6 +87,7 @@ public:
|
||||
void *createInstance(void);
|
||||
/// creates a instance of the named type
|
||||
static void *createInstanceByName(const char* TypeName, bool bLoadModule=false);
|
||||
static void importModule(const char* TypeName);
|
||||
|
||||
typedef void * (*instantiationMethod)(void);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user