Skip to content

Commit

Permalink
Extensions: Fix GeoFeatureGroup drag&drop
Browse files Browse the repository at this point in the history
  • Loading branch information
ickby authored and wwmayer committed Jan 4, 2017
1 parent dd0b714 commit 109f869
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 7 deletions.
6 changes: 3 additions & 3 deletions src/App/GeoFeatureGroupExtension.cpp
Expand Up @@ -57,7 +57,7 @@ void GeoFeatureGroupExtension::initExtension(ExtensionContainer* obj) {
if(!obj->isDerivedFrom(App::GeoFeature::getClassTypeId()))
throw Base::Exception("GeoFeatureGroupExtension can only be applied to GeoFeatures");

App::Extension::initExtension(obj);
App::GroupExtension::initExtension(obj);
}

PropertyPlacement& GeoFeatureGroupExtension::placement() {
Expand Down Expand Up @@ -143,9 +143,9 @@ bool GeoFeatureGroupExtension::geoHasObject (const DocumentObject* obj) const {
DocumentObject* GeoFeatureGroupExtension::getGroupOfObject(const DocumentObject* obj, bool indirect)
{
const Document* doc = obj->getDocument();
std::vector<DocumentObject*> grps = doc->getObjectsOfType(GeoFeatureGroupExtension::getExtensionClassTypeId());
std::vector<DocumentObject*> grps = doc->getObjectsWithExtension(GeoFeatureGroupExtension::getExtensionClassTypeId());
for (std::vector<DocumentObject*>::const_iterator it = grps.begin(); it != grps.end(); ++it) {
GeoFeatureGroupExtension* grp = (GeoFeatureGroupExtension*)(*it);
GeoFeatureGroupExtension* grp = (*it)->getExtensionByType<GeoFeatureGroupExtension>();
if ( indirect ) {
if (grp->geoHasObject(obj)) {
return dynamic_cast<App::DocumentObject*>(grp);
Expand Down
9 changes: 7 additions & 2 deletions src/App/GroupExtension.cpp
Expand Up @@ -63,6 +63,11 @@ void GroupExtension::addObject(DocumentObject* obj)
if(!allowObject(obj))
return;

//only one group per object
auto *group = App::GroupExtension::getGroupOfObject(obj);
if(group && group != getExtendedObject())
group->getExtensionByType<App::GroupExtension>()->removeObject(obj);

if (!hasObject(obj)) {
std::vector<DocumentObject*> grp = Group.getValues();
grp.push_back(obj);
Expand Down Expand Up @@ -180,9 +185,9 @@ int GroupExtension::countObjectsOfType(const Base::Type& typeId) const
DocumentObject* GroupExtension::getGroupOfObject(const DocumentObject* obj)
{
const Document* doc = obj->getDocument();
std::vector<DocumentObject*> grps = doc->getObjectsOfType(GroupExtension::getExtensionClassTypeId());
std::vector<DocumentObject*> grps = doc->getObjectsWithExtension(GroupExtension::getExtensionClassTypeId());
for (std::vector<DocumentObject*>::const_iterator it = grps.begin(); it != grps.end(); ++it) {
GroupExtension* grp = (GroupExtension*)(*it);
GroupExtension* grp = (*it)->getExtensionByType<GroupExtension>();
if (grp->hasObject(obj))
return *it;
}
Expand Down
63 changes: 63 additions & 0 deletions src/App/OriginGroupExtension.cpp
Expand Up @@ -129,6 +129,69 @@ void OriginGroupExtension::onExtendedUnsetupObject () {
GeoFeatureGroupExtension::onExtendedUnsetupObject ();
}

void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
{
//we get all links and replace the origin objects if needed (subnames need not to change, they
//would stay the same)
std::vector< App::DocumentObject* > result;
std::vector<App::Property*> list;
obj->getPropertyList(list);
for(App::Property* prop : list) {
if(prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId())) {

auto p = static_cast<App::PropertyLink*>(prop);
if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
continue;

p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()));
}
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
auto p = static_cast<App::PropertyLinkList*>(prop);
auto vec = p->getValues();
std::vector<App::DocumentObject*> result;
bool changed = false;
for(App::DocumentObject* o : vec) {
if(!o || !o->isDerivedFrom(App::OriginFeature::getClassTypeId()))
result.push_back(o);
else {
result.push_back(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(o)->Role.getValue()));
changed = true;
}
}
if(changed)
static_cast<App::PropertyLinkList*>(prop)->setValues(result);
}
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSub::getClassTypeId())) {
auto p = static_cast<App::PropertyLinkSub*>(prop);
if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
continue;

p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()));
}
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())) {
auto p = static_cast<App::PropertyLinkList*>(prop);
auto vec = p->getValues();
std::vector<App::DocumentObject*> result;
bool changed = false;
for(App::DocumentObject* o : vec) {
if(!o || !o->isDerivedFrom(App::OriginFeature::getClassTypeId()))
result.push_back(o);
else {
result.push_back(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(o)->Role.getValue()));
changed = true;
}
}
if(changed)
static_cast<App::PropertyLinkList*>(prop)->setValues(result);
}
}
}

void OriginGroupExtension::addObject(DocumentObject* obj) {
relinkToOrigin(obj);
App::GeoFeatureGroupExtension::addObject(obj);
}


// Python feature ---------------------------------------------------------

Expand Down
5 changes: 5 additions & 0 deletions src/App/OriginGroupExtension.h
Expand Up @@ -62,6 +62,11 @@ class AppExport OriginGroupExtension : public App::GeoFeatureGroupExtension

/// Origin linked to the group
PropertyLink Origin;

//changes all links of obj to a origin to point to this groupes origin
void relinkToOrigin(App::DocumentObject* obj);

virtual void addObject(DocumentObject* obj);

protected:
/// Checks integrity of the Origin
Expand Down
86 changes: 86 additions & 0 deletions src/Gui/ViewProviderGeoFeatureGroupExtension.cpp
Expand Up @@ -29,6 +29,9 @@
#endif

#include "ViewProviderGeoFeatureGroupExtension.h"
#include "Command.h"
#include "Application.h"
#include "Document.h"
#include <App/GeoFeatureGroupExtension.h>
#include <Inventor/nodes/SoGroup.h>

Expand Down Expand Up @@ -91,6 +94,89 @@ void ViewProviderGeoFeatureGroupExtension::extensionUpdateData(const App::Proper
}
}

std::vector< App::DocumentObject* > ViewProviderGeoFeatureGroupExtension::getLinkedObjects(App::DocumentObject* obj) {

if(!obj)
return std::vector< App::DocumentObject* >();

//we get all linked objects, and that recursively
std::vector< App::DocumentObject* > result;
std::vector<App::Property*> list;
obj->getPropertyList(list);
for(App::Property* prop : list) {
if(prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId()))
result.push_back(static_cast<App::PropertyLink*>(prop)->getValue());
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
auto vec = static_cast<App::PropertyLinkList*>(prop)->getValues();
result.insert(result.end(), vec.begin(), vec.end());
}
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSub::getClassTypeId()))
result.push_back(static_cast<App::PropertyLinkSub*>(prop)->getValue());
else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())) {
auto vec = static_cast<App::PropertyLinkList*>(prop)->getValues();
result.insert(result.end(), vec.begin(), vec.end());
}
}

//clear all null objects
result.erase(std::remove(result.begin(), result.end(), nullptr), result.end());

//collect all dependencies of those objects
for(App::DocumentObject *obj : result) {
auto vec = getLinkedObjects(obj);
result.insert(result.end(), vec.begin(), vec.end());
}

return result;
}

void ViewProviderGeoFeatureGroupExtension::extensionDropObject(App::DocumentObject* obj) {

// Open command
App::DocumentObject* grp = static_cast<App::DocumentObject*>(getExtendedViewProvider()->getObject());
App::Document* doc = grp->getDocument();
Gui::Document* gui = Gui::Application::Instance->getDocument(doc);
gui->openCommand("Move object");

//links between different CS are not allowed, hence we need to ensure if all dependencies are in
//the same geofeaturegroup
auto vec = getLinkedObjects(obj);

//remove all objects already in the correct group
vec.erase(std::remove_if(vec.begin(), vec.end(), [this](App::DocumentObject* o){
return App::GroupExtension::getGroupOfObject(o) == this->getExtendedViewProvider()->getObject();
}), vec.end());

vec.push_back(obj);

for(App::DocumentObject* o : vec) {
// build Python command for execution
QString cmd;
cmd = QString::fromLatin1("App.getDocument(\"%1\").getObject(\"%2\").addObject("
"App.getDocument(\"%1\").getObject(\"%3\"))")
.arg(QString::fromLatin1(doc->getName()))
.arg(QString::fromLatin1(grp->getNameInDocument()))
.arg(QString::fromLatin1(o->getNameInDocument()));

Gui::Command::doCommand(Gui::Command::App, cmd.toUtf8());
}
gui->commitCommand();
}


void ViewProviderGeoFeatureGroupExtension::extensionDragObject(App::DocumentObject* obj) {
//links between different coordinate systems are not allowed, hence draging one object also needs
//to drag out all dependend objects
auto vec = getLinkedObjects(obj);

//add this object
vec.push_back(obj);

for(App::DocumentObject* obj : vec)
ViewProviderGroupExtension::extensionDragObject(obj);
}



namespace Gui {
EXTENSION_PROPERTY_SOURCE_TEMPLATE(Gui::ViewProviderGeoFeatureGroupExtensionPython, Gui::ViewProviderGeoFeatureGroupExtension)
Expand Down
5 changes: 5 additions & 0 deletions src/Gui/ViewProviderGeoFeatureGroupExtension.h
Expand Up @@ -58,8 +58,13 @@ class GuiExport ViewProviderGeoFeatureGroupExtension : public ViewProviderGroupE

virtual void extensionUpdateData(const App::Property*) override;

virtual void extensionDropObject(App::DocumentObject*);
virtual void extensionDragObject(App::DocumentObject*);

protected:
SoGroup *pcGroupChildren;

std::vector<App::DocumentObject*> getLinkedObjects(App::DocumentObject* obj);
};

typedef ViewProviderExtensionPythonT<Gui::ViewProviderGeoFeatureGroupExtension> ViewProviderGeoFeatureGroupExtensionPython;
Expand Down
58 changes: 58 additions & 0 deletions src/Gui/ViewProviderOriginGroupExtension.cpp
Expand Up @@ -34,6 +34,7 @@
#include "ViewProviderOrigin.h"
#include "View3DInventorViewer.h"
#include "View3DInventor.h"
#include "Command.h"
#include <App/OriginGroupExtension.h>
#include <App/Document.h>
#include <App/Origin.h>
Expand Down Expand Up @@ -196,6 +197,63 @@ void ViewProviderOriginGroupExtension::updateOriginSize () {
vpOrigin->Size.setValue ( size * 1.3 );
}

void ViewProviderOriginGroupExtension::extensionDragObject(App::DocumentObject* obj) {

//links between different coordinate systems are not allowed, hence draging one object also needs
//to drag out all dependend objects
auto vec = getLinkedObjects(obj);

//remove all origin objects
vec.erase(std::remove_if(vec.begin(), vec.end(), [this](App::DocumentObject* o) {
return o->isDerivedFrom(App::OriginFeature::getClassTypeId());}), vec.end());

//add the original object
vec.push_back(obj);

for(App::DocumentObject* obj : vec)
ViewProviderGroupExtension::extensionDragObject(obj);
}

void ViewProviderOriginGroupExtension::extensionDropObject(App::DocumentObject* obj) {

// Open command
App::DocumentObject* grp = static_cast<App::DocumentObject*>(getExtendedViewProvider()->getObject());
App::Document* doc = grp->getDocument();
Gui::Document* gui = Gui::Application::Instance->getDocument(doc);
gui->openCommand("Move object");

//links between different CS are not allowed, hence we need to enure if all dependencies are in
//the same geofeaturegroup
auto vec = getLinkedObjects(obj);

//remove all origin objects
vec.erase(std::remove_if(vec.begin(), vec.end(), [](App::DocumentObject* o) {
return o->isDerivedFrom(App::OriginFeature::getClassTypeId());}), vec.end());

//remove all objects already in the correct group
vec.erase(std::remove_if(vec.begin(), vec.end(), [this](App::DocumentObject* o){
return App::GroupExtension::getGroupOfObject(o) == this->getExtendedViewProvider()->getObject();
}), vec.end());

//add the original object
vec.push_back(obj);

for(App::DocumentObject* o : vec) {

// build Python command for execution
QString cmd;
cmd = QString::fromLatin1("App.getDocument(\"%1\").getObject(\"%2\").addObject("
"App.getDocument(\"%1\").getObject(\"%3\"))")
.arg(QString::fromLatin1(doc->getName()))
.arg(QString::fromLatin1(grp->getNameInDocument()))
.arg(QString::fromLatin1(o->getNameInDocument()));

Gui::Command::doCommand(Gui::Command::App, cmd.toUtf8());
}
gui->commitCommand();

}


namespace Gui {
EXTENSION_PROPERTY_SOURCE_TEMPLATE(Gui::ViewProviderOriginGroupExtensionPython, Gui::ViewProviderOriginGroupExtension)
Expand Down
3 changes: 3 additions & 0 deletions src/Gui/ViewProviderOriginGroupExtension.h
Expand Up @@ -46,6 +46,9 @@ class GuiExport ViewProviderOriginGroupExtension : public ViewProviderGeoFeature
virtual void extensionAttach(App::DocumentObject *pcObject) override;
virtual void extensionUpdateData(const App::Property* prop) override;

virtual void extensionDragObject(App::DocumentObject*) override;
virtual void extensionDropObject(App::DocumentObject*);

void updateOriginSize();

protected:
Expand Down
12 changes: 10 additions & 2 deletions src/Mod/PartDesign/App/Body.cpp
Expand Up @@ -169,7 +169,7 @@ App::DocumentObject* Body::getNextSolidFeature(App::DocumentObject *start)
start = Tip.getValue();
}

if ( !start ) { // no tip
if ( !start || !hasObject(start) ) { // no or faulty tip
return nullptr;
}

Expand Down Expand Up @@ -268,7 +268,12 @@ void Body::addObject(App::DocumentObject *feature)
{
if(!isAllowed(feature))
throw Base::Exception("Body: object is not allowed");


//only one group per object
auto *group = App::GroupExtension::getGroupOfObject(feature);
if(group && group != getExtendedObject())
group->getExtensionByType<App::GroupExtension>()->removeObject(feature);

insertObject (feature, getNextSolidFeature (), /*after = */ false);
// Move the Tip if we added a solid
if (isSolidFeature(feature)) {
Expand All @@ -292,6 +297,9 @@ void Body::insertObject(App::DocumentObject* feature, App::DocumentObject* targe
throw Base::Exception("Body: the feature we should insert relative to is not part of that body");
}
}

//ensure that all origin links are ok
relinkToOrigin(feature);

std::vector<App::DocumentObject*> model = Group.getValues();
std::vector<App::DocumentObject*>::iterator insertInto;
Expand Down

0 comments on commit 109f869

Please sign in to comment.