diff --git a/src/App/GeoFeatureGroup.cpp b/src/App/GeoFeatureGroup.cpp index ba4bf51c7..85375b9f2 100644 --- a/src/App/GeoFeatureGroup.cpp +++ b/src/App/GeoFeatureGroup.cpp @@ -116,7 +116,7 @@ bool GeoFeatureGroup::hasObject(const DocumentObject* obj, bool recursive) const if (*it == obj) return true; if (recursive && (*it)->getTypeId().isDerivedFrom(GeoFeatureGroup::getClassTypeId())) { - if (this->hasObject(static_cast(*it), recursive)) + if (static_cast(*it)->hasObject(obj, recursive)) return true; } } diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 07b444014..298d8dd25 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -703,6 +703,7 @@ void CmdPartDesignNewSketch::activated(int iMsg) QObject::tr("You have to select a single face as support for a sketch!")); return; } + // get the selected sub shape (a Face) const Part::TopoShape &shape = feat->Shape.getValue(); TopoDS_Shape sh = shape.getSubShape(sub[0].c_str()); @@ -773,6 +774,7 @@ void CmdPartDesignNewSketch::activated(int iMsg) unsigned validPlanes = 0; std::vector::const_iterator firstValidPlane = planes.end(); + App::Part* pcActivePart = Gui::Application::Instance->activeView()->getActiveObject(PARTKEY); for (std::vector::iterator p = planes.begin(); p != planes.end(); p++) { // Check whether this plane is a base plane bool base = false; @@ -780,7 +782,11 @@ void CmdPartDesignNewSketch::activated(int iMsg) App::Plane* pfeat = static_cast(*p); for (unsigned i = 0; i < 3; i++) { if (strcmp(App::Part::BaseplaneTypes[i], pfeat->PlaneType.getValue()) == 0) { - status.push_back(PartDesignGui::TaskFeaturePick::basePlane); + if(pcActivePart->hasObject(pfeat, true)) + status.push_back(PartDesignGui::TaskFeaturePick::basePlane); + else + status.push_back(PartDesignGui::TaskFeaturePick::invalidShape); + if (firstValidPlane == planes.end()) firstValidPlane = p; validPlanes++; @@ -793,7 +799,11 @@ void CmdPartDesignNewSketch::activated(int iMsg) // Check whether this plane belongs to the active body if (!pcActiveBody->hasFeature(*p)) { - status.push_back(PartDesignGui::TaskFeaturePick::otherBody); + if(pcActivePart->hasObject(*p, true)) + status.push_back(PartDesignGui::TaskFeaturePick::otherBody); + else + status.push_back(PartDesignGui::TaskFeaturePick::otherPart); + continue; } else { if (pcActiveBody->isAfterTip(*p)){ diff --git a/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp b/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp index 9606c5c7e..e93a26118 100644 --- a/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp +++ b/src/Mod/PartDesign/Gui/TaskFeaturePick.cpp @@ -34,10 +34,14 @@ #include #include #include +#include #include +#include #include "ui_TaskFeaturePick.h" #include "TaskFeaturePick.h" +#include "Workbench.h" +#include using namespace PartDesignGui; @@ -48,9 +52,10 @@ const QString TaskFeaturePick::getFeatureStatusString(const featureStatus st) case invalidShape: return tr("Invalid shape"); case noWire: return tr("No wire in sketch"); case isUsed: return tr("Sketch already used by other feature"); - case otherBody: return tr("Sketch belongs to another Body feature"); + case otherBody: return tr("Belongs to another body"); + case otherPart: return tr("Belongs to another part"); case basePlane: return tr("Base plane"); - case afterTip: return tr("Feature is located after the Tip feature"); + case afterTip: return tr("Feature is located after the tip feature"); } return tr(""); @@ -66,23 +71,13 @@ TaskFeaturePick::TaskFeaturePick(std::vector& objects, proxy = new QWidget(this); ui->setupUi(proxy); - connect(ui->checkReverse, SIGNAL(toggled(bool)), this, SLOT(onCheckReverse(bool))); - connect(ui->checkOtherBody, SIGNAL(toggled(bool)), this, SLOT(onCheckOtherBody(bool))); - connect(ui->checkOtherFeature, SIGNAL(toggled(bool)), this, SLOT(onCheckOtherFeature(bool))); - connect(ui->radioIndependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); - connect(ui->radioDependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); - connect(ui->radioXRef, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); - - ui->checkReverse->setChecked(false); - ui->checkOtherBody->setChecked(true); - ui->checkOtherBody->setEnabled(false); // TODO: implement - ui->checkOtherFeature->setChecked(false); - ui->checkOtherFeature->setEnabled(false); // TODO: implement - ui->radioIndependent->setChecked(true); - ui->radioIndependent->setEnabled(false); - // These are not implemented yet - ui->radioDependent->setEnabled(false); - ui->radioXRef->setEnabled(false); + connect(ui->checkOtherBody, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); + connect(ui->bodyRadioIndependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); + connect(ui->bodyRadioXRef, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); + connect(ui->checkOtherPart, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); + connect(ui->partRadioIndependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); + connect(ui->partRadioDependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); + connect(ui->partRadioXRef, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); auto guidoc = Gui::Application::Instance->activeDocument(); auto origin_obj = App::GetApplication().getActiveDocument()->getObjectsOfType(); @@ -93,11 +88,10 @@ TaskFeaturePick::TaskFeaturePick(std::vector& objects, QListWidgetItem* item = new QListWidgetItem(QString::fromAscii((*o)->getNameInDocument()) + QString::fromAscii(" (") + getFeatureStatusString(*st) + QString::fromAscii(")")); ui->listWidget->addItem(item); - st++; //check if we need to set any origin in temporary visibility mode for(App::Origin* obj : origin_obj) { - if(obj->hasObject(*o)) { + if(obj->hasObject(*o) && (*st != invalidShape)) { Gui::ViewProviderOrigin* vpo = static_cast(guidoc->getViewProvider(obj)); if(!vpo->isTemporaryVisibilityMode()) vpo->setTemporaryVisibilityMode(true, guidoc); @@ -107,6 +101,8 @@ TaskFeaturePick::TaskFeaturePick(std::vector& objects, break; } } + + st++; } groupLayout()->addWidget(proxy); @@ -132,59 +128,35 @@ void TaskFeaturePick::updateList() QListWidgetItem* item = ui->listWidget->item(index); switch (*st) { - case validFeature: item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); break; - case invalidShape: item->setFlags(Qt::NoItemFlags); break; - case noWire: item->setFlags(Qt::NoItemFlags); break; - case isUsed: item->setFlags(ui->checkOtherFeature->isChecked() ? Qt::ItemIsSelectable | Qt::ItemIsEnabled : Qt::NoItemFlags); break; - case otherBody: item->setFlags(ui->checkOtherBody->isChecked() ? Qt::ItemIsSelectable | Qt::ItemIsEnabled : Qt::NoItemFlags); break; - case basePlane: item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); break; - case afterTip: item->setFlags(Qt::NoItemFlags); break; + case validFeature: item->setHidden(false); break; + case invalidShape: item->setHidden(true); break; + case noWire: item->setHidden(true); break; + case otherBody: item->setHidden(ui->checkOtherBody->isChecked() ? false : true); break; + case otherPart: item->setHidden(ui->checkOtherPart->isChecked() ? false : true); break; + case basePlane: item->setHidden(false); break; + case afterTip: item->setHidden(true); break; } index++; } } -void TaskFeaturePick::onCheckReverse(bool checked) -{ -} - -void TaskFeaturePick::onCheckOtherFeature(bool checked) -{ - ui->radioIndependent->setEnabled(checked); - // TODO: Not implemented yet - //ui->radioDependent->setEnabled(checked); - //ui->radioXRef->setEnabled(checked); - - updateList(); -} - -void TaskFeaturePick::onCheckOtherBody(bool checked) -{ - ui->radioIndependent->setEnabled(checked); - // TODO: Not implemented yet - //ui->radioDependent->setEnabled(checked); - //ui->radioXRef->setEnabled(checked); - - updateList(); -} - void TaskFeaturePick::onUpdate(bool) { updateList(); } -bool TaskFeaturePick::getReverse() -{ - return ui->checkReverse->isChecked(); -} - std::vector TaskFeaturePick::getFeatures() { features.clear(); QListIterator i(ui->listWidget->selectedItems()); while (i.hasNext()) { - QString t = i.next()->text(); + + auto item = i.next(); + if(item->isHidden()) + continue; + + QString t = item->text(); t = t.left(t.indexOf(QString::fromAscii("(")) - 1); features.push_back(t); } @@ -197,6 +169,117 @@ std::vector TaskFeaturePick::getFeatures() { return result; } +std::vector TaskFeaturePick::buildFeatures() { + + + int index = 0; + std::vector result; + auto activeBody = PartDesignGui::getBody(false); + auto activePart = PartDesignGui::getPartFor(activeBody, false); + + for (std::vector::const_iterator st = statuses.begin(); st != statuses.end(); st++) { + QListWidgetItem* item = ui->listWidget->item(index); + + if(item->isSelected() && !item->isHidden()) { + + QString t = item->text(); + t = t.left(t.indexOf(QString::fromAscii("(")) - 1); + auto obj = App::GetApplication().getActiveDocument()->getObject(t.toAscii().data()); + + //build the dependend copy if wanted by the user + if(*st == otherBody) { + + if(ui->bodyRadioIndependent->isChecked()) { + auto copy = makeCopy(obj, true); + activeBody->addFeature(copy); + result.push_back(copy); + } + else + result.push_back(obj); + } + else if(*st == otherPart) { + + if(!ui->partRadioXRef->isChecked()) { + auto copy = makeCopy(obj, ui->partRadioIndependent->isChecked()); + + auto oBody = PartDesignGui::getBodyFor(obj, false); + if(oBody) + activeBody->addFeature(copy); + else + activePart->addObject(copy); + + result.push_back(copy); + } + else + result.push_back(obj); + } + else + result.push_back(obj); + + break; + } + + index++; + } + + return result; +} + +App::DocumentObject* TaskFeaturePick::makeCopy(App::DocumentObject* obj, bool independent) { + + //we do know that the created instance is a document object, as obj is one. But we do not know which + //exact type + auto name = App::GetApplication().getActiveDocument()->getUniqueObjectName(obj->getNameInDocument()); + auto copy = App::GetApplication().getActiveDocument()->addObject(obj->getTypeId().getName(), name.c_str()); + + if(copy) { + //copy over all properties + std::vector props; + std::vector cprops; + obj->getPropertyList(props); + obj->getPropertyList(cprops); + try{ + auto it = cprops.begin(); + for( App::Property* prop : props ) { + + //independent copys dont have links and are not attached + if(independent && ( + prop->getTypeId() == App::PropertyLink::getClassTypeId() || + prop->getTypeId() == App::PropertyLinkList::getClassTypeId() || + prop->getTypeId() == App::PropertyLinkSub::getClassTypeId() || + prop->getTypeId() == App::PropertyLinkSubList::getClassTypeId()|| + ( prop->getGroup() && strcmp(prop->getGroup(),"Attachment")==0) )) { + + ++it; + continue; + } + + Base::StringWriter writer; + //the properties xml tag is often not correctly cosed and only has "". This leads + //to a end of document exception. To prevent this we add a dummy tag arround. + writer.Stream() << writer.ind() << "" << std::endl; + writer.ind(); + prop->Save(writer); + writer.decInd(); + writer.Stream() << writer.ind() << "" << std::endl; + + std::stringstream stream(writer.getString()); + Base::XMLReader reader("test", stream); + reader.readElement("Prop"); + App::Property* cprop = *it++; + cprop->Restore(reader); + } + } + catch(const Base::Exception& e) { + + Base::Console().Message("Exception: %s\n", e.what()); + } + } + + return copy; +} + + void TaskFeaturePick::onSelectionChanged(const Gui::SelectionChanges& msg) { ui->listWidget->clearSelection(); @@ -211,8 +294,7 @@ void TaskFeaturePick::onSelectionChanged(const Gui::SelectionChanges& msg) ui->listWidget->setItemSelected(item, true); } } - } - + } } //************************************************************************** @@ -236,9 +318,9 @@ TaskDlgFeaturePick::TaskDlgFeaturePick(std::vector &object TaskDlgFeaturePick::~TaskDlgFeaturePick() { //do the work now as before in accept() the dialog is still open, hence the work - //function could not open annother dialog + //function could not open annother dialog if(accepted) - workFunction(pick->getFeatures()); + workFunction(pick->buildFeatures()); } //==== calls from the TaskView =============================================================== diff --git a/src/Mod/PartDesign/Gui/TaskFeaturePick.h b/src/Mod/PartDesign/Gui/TaskFeaturePick.h index aac5f1daf..34f16da0a 100644 --- a/src/Mod/PartDesign/Gui/TaskFeaturePick.h +++ b/src/Mod/PartDesign/Gui/TaskFeaturePick.h @@ -46,6 +46,7 @@ public: noWire, isUsed, otherBody, + otherPart, basePlane, afterTip }; @@ -57,14 +58,10 @@ public: ~TaskFeaturePick(); std::vector getFeatures(); - bool getReverse(); - + std::vector buildFeatures(); + protected Q_SLOTS: - void onCheckReverse(bool); - void onCheckOtherFeature(bool); - void onCheckOtherBody(bool); void onUpdate(bool); - void onSelectionChanged(const Gui::SelectionChanges& msg); private: @@ -77,6 +74,7 @@ private: std::vector statuses; void updateList(); + App::DocumentObject* makeCopy(App::DocumentObject*, bool independent); const QString getFeatureStatusString(const featureStatus st); }; diff --git a/src/Mod/PartDesign/Gui/TaskFeaturePick.ui b/src/Mod/PartDesign/Gui/TaskFeaturePick.ui index 7e53ae312..9af17c6a2 100644 --- a/src/Mod/PartDesign/Gui/TaskFeaturePick.ui +++ b/src/Mod/PartDesign/Gui/TaskFeaturePick.ui @@ -6,64 +6,89 @@ 0 0 - 328 - 445 + 388 + 479 Form - + - - - Reverse direction + + + Allow features from other bodies + + false + + + true + + + false + + + + + + Make independent copy (recommended) + + + true + + + + + + + Create cross-reference + + + + - - - Qt::Horizontal + + + Allow features from other parts - - - - - - Allow feature from other Body + + true - - - - - - Allow sketch used by other feature - - - - - - - Make independent copy (recommended) - - - - - - - Make dependent copy - - - - - - - Create cross-reference + + false + + + + + Make independent copy (recommended) + + + true + + + + + + + Make dependent copy + + + + + + + Create cross-reference + + + +