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)
return true;
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;
}
}

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!"));
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<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++) {
// 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<App::Plane*>(*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)){

View File

@ -34,10 +34,14 @@
#include <Gui/Document.h>
#include <Gui/ViewProviderOrigin.h>
#include <App/Document.h>
#include <App/Part.h>
#include <Base/Tools.h>
#include <Base/Reader.h>
#include "ui_TaskFeaturePick.h"
#include "TaskFeaturePick.h"
#include "Workbench.h"
#include <Mod/PartDesign/App/Body.h>
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<App::DocumentObject*>& 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<App::Origin>();
@ -93,11 +88,10 @@ TaskFeaturePick::TaskFeaturePick(std::vector<App::DocumentObject*>& 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<Gui::ViewProviderOrigin*>(guidoc->getViewProvider(obj));
if(!vpo->isTemporaryVisibilityMode())
vpo->setTemporaryVisibilityMode(true, guidoc);
@ -107,6 +101,8 @@ TaskFeaturePick::TaskFeaturePick(std::vector<App::DocumentObject*>& 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<App::DocumentObject*> TaskFeaturePick::getFeatures() {
features.clear();
QListIterator<QListWidgetItem*> 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<App::DocumentObject*> TaskFeaturePick::getFeatures() {
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)
{
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<App::DocumentObject*> &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 ===============================================================

View File

@ -46,6 +46,7 @@ public:
noWire,
isUsed,
otherBody,
otherPart,
basePlane,
afterTip
};
@ -57,14 +58,10 @@ public:
~TaskFeaturePick();
std::vector<App::DocumentObject*> getFeatures();
bool getReverse();
std::vector<App::DocumentObject*> 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<featureStatus> statuses;
void updateList();
App::DocumentObject* makeCopy(App::DocumentObject*, bool independent);
const QString getFeatureStatusString(const featureStatus st);
};

View File

@ -6,64 +6,89 @@
<rect>
<x>0</x>
<y>0</y>
<width>328</width>
<height>445</height>
<width>388</width>
<height>479</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
<item>
<widget class="QCheckBox" name="checkReverse">
<property name="text">
<string>Reverse direction</string>
<widget class="QGroupBox" name="checkOtherBody">
<property name="title">
<string>Allow features from other bodies</string>
</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>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<widget class="QGroupBox" name="checkOtherPart">
<property name="title">
<string>Allow features from other parts</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkOtherBody">
<property name="text">
<string>Allow feature from other Body</string>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<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 name="checked">
<bool>false</bool>
</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>
</item>
</layout>