Add addObjects to add multiple objects in one step

This commit is contained in:
wmayer
2017-05-05 21:21:09 +02:00
parent 77386684fb
commit 3e862bd557
6 changed files with 140 additions and 19 deletions

View File

@@ -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()) {

View File

@@ -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.

View File

@@ -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();

View File

@@ -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.
*/

View File

@@ -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)

View File

@@ -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);