first take on enhanced feature pick task

This commit is contained in:
Stefan Tröger 2015-07-15 22:04:58 +02:00
parent a6fe5e664a
commit a35c231d2a
5 changed files with 228 additions and 113 deletions

View File

@ -116,7 +116,7 @@ bool GeoFeatureGroup::hasObject(const DocumentObject* obj, bool recursive) const
if (*it == obj) if (*it == obj)
return true; return true;
if (recursive && (*it)->getTypeId().isDerivedFrom(GeoFeatureGroup::getClassTypeId())) { if (recursive && (*it)->getTypeId().isDerivedFrom(GeoFeatureGroup::getClassTypeId())) {
if (this->hasObject(static_cast<GeoFeatureGroup*>(*it), recursive)) if (static_cast<GeoFeatureGroup*>(*it)->hasObject(obj, recursive))
return true; return true;
} }
} }

View File

@ -703,6 +703,7 @@ void CmdPartDesignNewSketch::activated(int iMsg)
QObject::tr("You have to select a single face as support for a sketch!")); QObject::tr("You have to select a single face as support for a sketch!"));
return; return;
} }
// get the selected sub shape (a Face) // get the selected sub shape (a Face)
const Part::TopoShape &shape = feat->Shape.getValue(); const Part::TopoShape &shape = feat->Shape.getValue();
TopoDS_Shape sh = shape.getSubShape(sub[0].c_str()); TopoDS_Shape sh = shape.getSubShape(sub[0].c_str());
@ -773,6 +774,7 @@ void CmdPartDesignNewSketch::activated(int iMsg)
unsigned validPlanes = 0; unsigned validPlanes = 0;
std::vector<App::DocumentObject*>::const_iterator firstValidPlane = planes.end(); std::vector<App::DocumentObject*>::const_iterator firstValidPlane = planes.end();
App::Part* pcActivePart = Gui::Application::Instance->activeView()->getActiveObject<App::Part*>(PARTKEY);
for (std::vector<App::DocumentObject*>::iterator p = planes.begin(); p != planes.end(); p++) { for (std::vector<App::DocumentObject*>::iterator p = planes.begin(); p != planes.end(); p++) {
// Check whether this plane is a base plane // Check whether this plane is a base plane
bool base = false; bool base = false;
@ -780,7 +782,11 @@ void CmdPartDesignNewSketch::activated(int iMsg)
App::Plane* pfeat = static_cast<App::Plane*>(*p); App::Plane* pfeat = static_cast<App::Plane*>(*p);
for (unsigned i = 0; i < 3; i++) { for (unsigned i = 0; i < 3; i++) {
if (strcmp(App::Part::BaseplaneTypes[i], pfeat->PlaneType.getValue()) == 0) { 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()) if (firstValidPlane == planes.end())
firstValidPlane = p; firstValidPlane = p;
validPlanes++; validPlanes++;
@ -793,7 +799,11 @@ void CmdPartDesignNewSketch::activated(int iMsg)
// Check whether this plane belongs to the active body // Check whether this plane belongs to the active body
if (!pcActiveBody->hasFeature(*p)) { 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; continue;
} else { } else {
if (pcActiveBody->isAfterTip(*p)){ if (pcActiveBody->isAfterTip(*p)){

View File

@ -34,10 +34,14 @@
#include <Gui/Document.h> #include <Gui/Document.h>
#include <Gui/ViewProviderOrigin.h> #include <Gui/ViewProviderOrigin.h>
#include <App/Document.h> #include <App/Document.h>
#include <App/Part.h>
#include <Base/Tools.h> #include <Base/Tools.h>
#include <Base/Reader.h>
#include "ui_TaskFeaturePick.h" #include "ui_TaskFeaturePick.h"
#include "TaskFeaturePick.h" #include "TaskFeaturePick.h"
#include "Workbench.h"
#include <Mod/PartDesign/App/Body.h>
using namespace PartDesignGui; using namespace PartDesignGui;
@ -48,9 +52,10 @@ const QString TaskFeaturePick::getFeatureStatusString(const featureStatus st)
case invalidShape: return tr("Invalid shape"); case invalidShape: return tr("Invalid shape");
case noWire: return tr("No wire in sketch"); case noWire: return tr("No wire in sketch");
case isUsed: return tr("Sketch already used by other feature"); 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 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(""); return tr("");
@ -66,23 +71,13 @@ TaskFeaturePick::TaskFeaturePick(std::vector<App::DocumentObject*>& objects,
proxy = new QWidget(this); proxy = new QWidget(this);
ui->setupUi(proxy); ui->setupUi(proxy);
connect(ui->checkReverse, SIGNAL(toggled(bool)), this, SLOT(onCheckReverse(bool))); connect(ui->checkOtherBody, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool)));
connect(ui->checkOtherBody, SIGNAL(toggled(bool)), this, SLOT(onCheckOtherBody(bool))); connect(ui->bodyRadioIndependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool)));
connect(ui->checkOtherFeature, SIGNAL(toggled(bool)), this, SLOT(onCheckOtherFeature(bool))); connect(ui->bodyRadioXRef, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool)));
connect(ui->radioIndependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); connect(ui->checkOtherPart, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool)));
connect(ui->radioDependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); connect(ui->partRadioIndependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool)));
connect(ui->radioXRef, 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)));
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);
auto guidoc = Gui::Application::Instance->activeDocument(); auto guidoc = Gui::Application::Instance->activeDocument();
auto origin_obj = App::GetApplication().getActiveDocument()->getObjectsOfType<App::Origin>(); auto origin_obj = App::GetApplication().getActiveDocument()->getObjectsOfType<App::Origin>();
@ -93,11 +88,10 @@ TaskFeaturePick::TaskFeaturePick(std::vector<App::DocumentObject*>& objects,
QListWidgetItem* item = new QListWidgetItem(QString::fromAscii((*o)->getNameInDocument()) + QListWidgetItem* item = new QListWidgetItem(QString::fromAscii((*o)->getNameInDocument()) +
QString::fromAscii(" (") + getFeatureStatusString(*st) + QString::fromAscii(")")); QString::fromAscii(" (") + getFeatureStatusString(*st) + QString::fromAscii(")"));
ui->listWidget->addItem(item); ui->listWidget->addItem(item);
st++;
//check if we need to set any origin in temporary visibility mode //check if we need to set any origin in temporary visibility mode
for(App::Origin* obj : origin_obj) { for(App::Origin* obj : origin_obj) {
if(obj->hasObject(*o)) { if(obj->hasObject(*o) && (*st != invalidShape)) {
Gui::ViewProviderOrigin* vpo = static_cast<Gui::ViewProviderOrigin*>(guidoc->getViewProvider(obj)); Gui::ViewProviderOrigin* vpo = static_cast<Gui::ViewProviderOrigin*>(guidoc->getViewProvider(obj));
if(!vpo->isTemporaryVisibilityMode()) if(!vpo->isTemporaryVisibilityMode())
vpo->setTemporaryVisibilityMode(true, guidoc); vpo->setTemporaryVisibilityMode(true, guidoc);
@ -107,6 +101,8 @@ TaskFeaturePick::TaskFeaturePick(std::vector<App::DocumentObject*>& objects,
break; break;
} }
} }
st++;
} }
groupLayout()->addWidget(proxy); groupLayout()->addWidget(proxy);
@ -132,59 +128,35 @@ void TaskFeaturePick::updateList()
QListWidgetItem* item = ui->listWidget->item(index); QListWidgetItem* item = ui->listWidget->item(index);
switch (*st) { switch (*st) {
case validFeature: item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); break; case validFeature: item->setHidden(false); break;
case invalidShape: item->setFlags(Qt::NoItemFlags); break; case invalidShape: item->setHidden(true); break;
case noWire: item->setFlags(Qt::NoItemFlags); break; case noWire: item->setHidden(true); break;
case isUsed: item->setFlags(ui->checkOtherFeature->isChecked() ? Qt::ItemIsSelectable | Qt::ItemIsEnabled : Qt::NoItemFlags); break; case otherBody: item->setHidden(ui->checkOtherBody->isChecked() ? false : true); break;
case otherBody: item->setFlags(ui->checkOtherBody->isChecked() ? Qt::ItemIsSelectable | Qt::ItemIsEnabled : Qt::NoItemFlags); break; case otherPart: item->setHidden(ui->checkOtherPart->isChecked() ? false : true); break;
case basePlane: item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); break; case basePlane: item->setHidden(false); break;
case afterTip: item->setFlags(Qt::NoItemFlags); break; case afterTip: item->setHidden(true); break;
} }
index++; 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) void TaskFeaturePick::onUpdate(bool)
{ {
updateList(); updateList();
} }
bool TaskFeaturePick::getReverse()
{
return ui->checkReverse->isChecked();
}
std::vector<App::DocumentObject*> TaskFeaturePick::getFeatures() { std::vector<App::DocumentObject*> TaskFeaturePick::getFeatures() {
features.clear(); features.clear();
QListIterator<QListWidgetItem*> i(ui->listWidget->selectedItems()); QListIterator<QListWidgetItem*> i(ui->listWidget->selectedItems());
while (i.hasNext()) { 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); t = t.left(t.indexOf(QString::fromAscii("(")) - 1);
features.push_back(t); features.push_back(t);
} }
@ -197,6 +169,117 @@ std::vector<App::DocumentObject*> TaskFeaturePick::getFeatures() {
return result; return result;
} }
std::vector<App::DocumentObject*> TaskFeaturePick::buildFeatures() {
int index = 0;
std::vector<App::DocumentObject*> result;
auto activeBody = PartDesignGui::getBody(false);
auto activePart = PartDesignGui::getPartFor(activeBody, false);
for (std::vector<featureStatus>::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<App::Property*> props;
std::vector<App::Property*> 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() << "<Prop>" << std::endl;
writer.ind();
prop->Save(writer);
writer.decInd();
writer.Stream() << writer.ind() << "</Prop>" << 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) void TaskFeaturePick::onSelectionChanged(const Gui::SelectionChanges& msg)
{ {
ui->listWidget->clearSelection(); ui->listWidget->clearSelection();
@ -211,8 +294,7 @@ void TaskFeaturePick::onSelectionChanged(const Gui::SelectionChanges& msg)
ui->listWidget->setItemSelected(item, true); ui->listWidget->setItemSelected(item, true);
} }
} }
} }
} }
//************************************************************************** //**************************************************************************
@ -236,9 +318,9 @@ TaskDlgFeaturePick::TaskDlgFeaturePick(std::vector<App::DocumentObject*> &object
TaskDlgFeaturePick::~TaskDlgFeaturePick() TaskDlgFeaturePick::~TaskDlgFeaturePick()
{ {
//do the work now as before in accept() the dialog is still open, hence the work //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) if(accepted)
workFunction(pick->getFeatures()); workFunction(pick->buildFeatures());
} }
//==== calls from the TaskView =============================================================== //==== calls from the TaskView ===============================================================

View File

@ -46,6 +46,7 @@ public:
noWire, noWire,
isUsed, isUsed,
otherBody, otherBody,
otherPart,
basePlane, basePlane,
afterTip afterTip
}; };
@ -57,14 +58,10 @@ public:
~TaskFeaturePick(); ~TaskFeaturePick();
std::vector<App::DocumentObject*> getFeatures(); std::vector<App::DocumentObject*> getFeatures();
bool getReverse(); std::vector<App::DocumentObject*> buildFeatures();
protected Q_SLOTS: protected Q_SLOTS:
void onCheckReverse(bool);
void onCheckOtherFeature(bool);
void onCheckOtherBody(bool);
void onUpdate(bool); void onUpdate(bool);
void onSelectionChanged(const Gui::SelectionChanges& msg); void onSelectionChanged(const Gui::SelectionChanges& msg);
private: private:
@ -77,6 +74,7 @@ private:
std::vector<featureStatus> statuses; std::vector<featureStatus> statuses;
void updateList(); void updateList();
App::DocumentObject* makeCopy(App::DocumentObject*, bool independent);
const QString getFeatureStatusString(const featureStatus st); const QString getFeatureStatusString(const featureStatus st);
}; };

View File

@ -6,64 +6,89 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>328</width> <width>388</width>
<height>445</height> <height>479</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
<widget class="QListWidget" name="listWidget"/> <widget class="QListWidget" name="listWidget"/>
</item> </item>
<item> <item>
<widget class="QCheckBox" name="checkReverse"> <widget class="QGroupBox" name="checkOtherBody">
<property name="text"> <property name="title">
<string>Reverse direction</string> <string>Allow features from other bodies</string>
</property> </property>
<property name="flat">
<bool>false</bool>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QRadioButton" name="bodyRadioIndependent">
<property name="text">
<string>Make independent copy (recommended)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="bodyRadioXRef">
<property name="text">
<string>Create cross-reference</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="Line" name="line"> <widget class="QGroupBox" name="checkOtherPart">
<property name="orientation"> <property name="title">
<enum>Qt::Horizontal</enum> <string>Allow features from other parts</string>
</property> </property>
</widget> <property name="checkable">
</item> <bool>true</bool>
<item>
<widget class="QCheckBox" name="checkOtherBody">
<property name="text">
<string>Allow feature from other Body</string>
</property> </property>
</widget> <property name="checked">
</item> <bool>false</bool>
<item>
<widget class="QCheckBox" name="checkOtherFeature">
<property name="text">
<string>Allow sketch used by other feature</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioIndependent">
<property name="text">
<string>Make independent copy (recommended)</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioDependent">
<property name="text">
<string>Make dependent copy</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="radioXRef">
<property name="text">
<string>Create cross-reference</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="partRadioIndependent">
<property name="text">
<string>Make independent copy (recommended)</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="partRadioDependent">
<property name="text">
<string>Make dependent copy</string>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="partRadioXRef">
<property name="text">
<string>Create cross-reference</string>
</property>
</widget>
</item>
</layout>
</widget> </widget>
</item> </item>
</layout> </layout>