Enhanced Pick dialog for PartDesign feature's sketches

This commit is contained in:
jrheinlaender 2013-03-30 14:33:06 +04:30 committed by Stefan Tröger
parent d16a886ad9
commit 94b6b89610
9 changed files with 467 additions and 1598 deletions

View File

@ -86,7 +86,7 @@ const Part::TopoShape Body::getPreviousSolid(const PartDesign::Feature* f)
return static_cast<const PartDesign::Feature*>(*it)->Shape.getShape();
}
const bool Body::hasFeature(const PartDesign::Feature* f)
const bool Body::hasFeature(const App::DocumentObject* f)
{
std::vector<App::DocumentObject*> features = Model.getValues();
return std::find(features.begin(), features.end(), f) != features.end();

View File

@ -58,7 +58,7 @@ public:
const Part::TopoShape getPreviousSolid(const PartDesign::Feature* f);
/// Return true if the feature belongs to this body
const bool hasFeature(const PartDesign::Feature* f);
const bool hasFeature(const App::DocumentObject *f);
PyObject *getPyObject(void);

View File

@ -81,7 +81,6 @@ PartDesign::Body *getBody(void)
}
//===========================================================================
// PartDesign_Sketch
//===========================================================================
@ -217,37 +216,46 @@ bool CmdPartDesignNewSketch::isActive(void)
//===========================================================================
// Take a list of Part2DObjects and erase those which are not eligible for creating a
// SketchBased feature. If supportRequired is true, also erase those that cannot be used to define
// a Subtractive feature
void validateSketches(std::vector<App::DocumentObject*>& sketches, const bool supportRequired)
{
std::vector<App::DocumentObject*>::iterator s = sketches.begin();
// SketchBased feature.
const unsigned validateSketches(std::vector<App::DocumentObject*>& sketches,
std::vector<PartDesignGui::FeaturePickDialog::featureStatus>& status,
std::vector<App::DocumentObject*>::iterator& firstValidSketch)
{
// TODO: If the user previously opted to allow multiple use of sketches or use of sketches from other bodies,
// then count these as valid sketches!
unsigned validSketches = 0;
firstValidSketch = sketches.end();
while (s != sketches.end()) {
// sketch is always part of the body first.
//// Check whether this sketch is already being used by another feature
//std::vector<App::DocumentObject*> ref = (*s)->getInList();
//std::vector<App::DocumentObject*>::iterator r = ref.begin();
//while (r != ref.end()) {
// if (!(*r)->getTypeId().isDerivedFrom(PartDesign::SketchBased().getClassTypeId())) {
// r = ref.erase(r);
// continue;
// }
// ++r;
//}
//if (!ref.empty()) {
// // TODO: Display some information message that this sketch was removed?
// s = sketches.erase(s);
// continue;
//}
for (std::vector<App::DocumentObject*>::iterator s = sketches.begin(); s != sketches.end(); s++) {
// Check whether this sketch is already being used by another feature
// Body features don't count...
std::vector<App::DocumentObject*> inList = (*s)->getInList();
std::vector<App::DocumentObject*>::iterator o = inList.begin();
while (o != inList.end()) {
Base::Console().Error("InList: %s\n", (*o)->getNameInDocument());
if ((*o)->getTypeId().isDerivedFrom(PartDesign::Body::getClassTypeId()))
o = inList.erase(o);
else
++o;
}
if (inList.size() > 0) {
status.push_back(PartDesignGui::FeaturePickDialog::isUsed);
continue;
}
// Check whether this sketch belongs to the active body
PartDesign::Body* body = getBody();
if (!body->hasFeature(*s)) {
status.push_back(PartDesignGui::FeaturePickDialog::otherBody);
continue;
}
// Check whether the sketch shape is valid
Part::Part2DObject* sketch = static_cast<Part::Part2DObject*>(*s);
const TopoDS_Shape& shape = sketch->Shape.getValue();
if (shape.IsNull()) {
s = sketches.erase(s);
status.push_back(PartDesignGui::FeaturePickDialog::invalidShape);
continue;
// TODO: Display some information message that this sketch was removed?
}
// count free wires
@ -257,24 +265,18 @@ void validateSketches(std::vector<App::DocumentObject*>& sketches, const bool su
ctWires++;
}
if (ctWires == 0) {
s = sketches.erase(s);
status.push_back(PartDesignGui::FeaturePickDialog::noWire);
continue;
// TODO: Display some information message that this sketch was removed?
}
// Check for support
if (supportRequired) {
App::DocumentObject* support = sketch->Support.getValue();
if (support == NULL) {
s = sketches.erase(s);
continue;
// TODO: Display some information message that this sketch was removed?
}
}
// All checks passed - go on to next candidate
s++;
// All checks passed - found a valid sketch
if (firstValidSketch == sketches.end())
firstValidSketch = s;
validSketches++;
status.push_back(PartDesignGui::FeaturePickDialog::validFeature);
}
return validSketches;
}
void prepareSketchBased(Gui::Command* cmd, const std::string& which,
@ -283,35 +285,33 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which,
PartDesign::Body *pcActiveBody = getBody();
if (!pcActiveBody) return;
bool bNoSketchWasSelected = false;
// Get a valid sketch from the user
// First check selections
FeatName = ""; // Empty string means prepareSketchBased() was not successful
std::vector<PartDesignGui::FeaturePickDialog::featureStatus> status;
std::vector<App::DocumentObject*>::iterator firstValidSketch;
std::vector<App::DocumentObject*> sketches = cmd->getSelection().getObjectsOfType(Part::Part2DObject::getClassTypeId());
validateSketches(sketches, false);
// Next let the user choose from a list of all eligible objects
if (sketches.size() == 0) {
// Next let the user choose from a list of all eligible objects
unsigned validSketches = validateSketches(sketches, status, firstValidSketch);
if (validSketches == 0) {
status.clear();
sketches = cmd->getDocument()->getObjectsOfType(Part::Part2DObject::getClassTypeId());
bNoSketchWasSelected = true;
}
if (sketches.size() == 0) {
if (bNoSketchWasSelected) {
validSketches = validateSketches(sketches, status, firstValidSketch);
if (validSketches == 0) {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No valid sketches in this document"),
QObject::tr("Please create a sketch or 2D object first."));
} else {
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No valid sketches selected"),
QObject::tr("None of selected sketches/2D objects is valid for padding. Please select a valid sketch or 2D object that is not used by any other feature."));
return;
}
return;
}
// If there is more than one selection/possibility, show dialog and let user pick sketch
if (sketches.size() > 1) {
PartDesignGui::FeaturePickDialog Dlg(sketches);
if (validSketches > 1) {
PartDesignGui::FeaturePickDialog Dlg(sketches, status);
if ((Dlg.exec() != QDialog::Accepted) || (sketches = Dlg.getFeatures()).empty())
return; // Cancelled or nothing selected
firstValidSketch = sketches.begin();
}
sketch = static_cast<Part::Part2DObject*>(sketches.front());
sketch = static_cast<Part::Part2DObject*>(*firstValidSketch);
FeatName = cmd->getUniqueObjectName(which.c_str());
cmd->openCommand((std::string("Make ") + which).c_str());
@ -323,7 +323,7 @@ void prepareSketchBased(Gui::Command* cmd, const std::string& which,
void finishSketchBased(const Gui::Command* cmd, const Part::Part2DObject* sketch, const std::string& FeatName)
{
App::DocumentObjectGroup* grp = sketch->getGroup();
App::DocumentObjectGroup* grp = sketch->getGroup();
if (grp) {
cmd->doCommand(cmd->Doc,"App.activeDocument().%s.addObject(App.activeDocument().%s)"
,grp->getNameInDocument(),FeatName.c_str());
@ -334,18 +334,17 @@ void finishSketchBased(const Gui::Command* cmd, const Part::Part2DObject* sketch
cmd->updateActive();
if (cmd->isActiveObjectValid()) {
cmd->doCommand(cmd->Gui,"Gui.activeDocument().hide(\"%s\")", sketch->getNameInDocument());
}
}
// #0001721: use '0' as edit value to avoid switching off selection in
// ViewProviderGeometryObject::setEditViewer
cmd->doCommand(cmd->Gui,"Gui.activeDocument().setEdit('%s', 0)", FeatName.c_str());
cmd->doCommand(cmd->Gui,"Gui.activeDocument().setEdit('%s', 0)", FeatName.c_str());
/*
PartDesign::Body *pcActiveBody = getBody();
if (pcActiveBody) {
cmd->copyVisual(FeatName.c_str(), "ShapeColor", pcActiveBody->getNameInDocument());
cmd->copyVisual(FeatName.c_str(), "LineColor", pcActiveBody->getNameInDocument());
cmd->copyVisual(FeatName.c_str(), "PointColor", pcActiveBody->getNameInDocument());
}*/
}
}
//===========================================================================
@ -370,6 +369,7 @@ void CmdPartDesignPad::activated(int iMsg)
Part::Part2DObject* sketch;
std::string FeatName;
prepareSketchBased(this, "Pad", sketch, FeatName);
if (FeatName.empty()) return;
// specific parameters for Pad
doCommand(Doc,"App.activeDocument().%s.Length = 10.0",FeatName.c_str());
@ -405,6 +405,7 @@ void CmdPartDesignPocket::activated(int iMsg)
Part::Part2DObject* sketch;
std::string FeatName;
prepareSketchBased(this, "Pocket", sketch, FeatName);
if (FeatName.empty()) return;
doCommand(Doc,"App.activeDocument().%s.Length = 5.0",FeatName.c_str());
@ -439,6 +440,7 @@ void CmdPartDesignRevolution::activated(int iMsg)
Part::Part2DObject* sketch;
std::string FeatName;
prepareSketchBased(this, "Revolution", sketch, FeatName);
if (FeatName.empty()) return;
doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])",
FeatName.c_str(), sketch->getNameInDocument());
@ -478,6 +480,7 @@ void CmdPartDesignGroove::activated(int iMsg)
Part::Part2DObject* sketch;
std::string FeatName;
prepareSketchBased(this, "Groove", sketch, FeatName);
if (FeatName.empty()) return;
doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])",
FeatName.c_str(), sketch->getNameInDocument());

File diff suppressed because it is too large Load Diff

View File

@ -39,12 +39,51 @@
using namespace PartDesignGui;
FeaturePickDialog::FeaturePickDialog(std::vector<App::DocumentObject*>& objects)
const QString FeaturePickDialog::getFeatureStatusString(const featureStatus st)
{
switch (st) {
case validFeature: return tr("Valid");
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");
}
return tr("");
}
FeaturePickDialog::FeaturePickDialog(std::vector<App::DocumentObject*>& objects,
const std::vector<featureStatus>& status)
: QDialog(Gui::getMainWindow()), ui(new Ui_FeaturePickDialog)
{
ui->setupUi(this);
for (std::vector<App::DocumentObject*>::const_iterator o = objects.begin(); o != objects.end(); ++o)
ui->listWidget->addItem(QString::fromLatin1((*o)->getNameInDocument()));
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->checkOtherBody->setChecked(false);
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);
std::vector<featureStatus>::const_iterator st = status.begin();
for (std::vector<App::DocumentObject*>::const_iterator o = objects.begin(); o != objects.end(); ++o) {
QListWidgetItem* item = new QListWidgetItem(QString::fromAscii((*o)->getNameInDocument()) +
QString::fromAscii(" (") + getFeatureStatusString(*st) + QString::fromAscii(")"));
ui->listWidget->addItem(item);
st++;
}
statuses = status;
updateList();
}
FeaturePickDialog::~FeaturePickDialog()
@ -52,6 +91,50 @@ FeaturePickDialog::~FeaturePickDialog()
}
void FeaturePickDialog::updateList()
{
int index = 0;
for (std::vector<featureStatus>::const_iterator st = statuses.begin(); st != statuses.end(); st++) {
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;
}
index++;
}
}
void FeaturePickDialog::onCheckOtherFeature(bool checked)
{
ui->radioIndependent->setEnabled(checked);
// TODO: Not implemented yet
//ui->radioDependent->setEnabled(checked);
//ui->radioXRef->setEnabled(checked);
updateList();
}
void FeaturePickDialog::onCheckOtherBody(bool checked)
{
ui->radioIndependent->setEnabled(checked);
// TODO: Not implemented yet
//ui->radioDependent->setEnabled(checked);
//ui->radioXRef->setEnabled(checked);
updateList();
}
void FeaturePickDialog::onUpdate(bool)
{
updateList();
}
std::vector<App::DocumentObject*> FeaturePickDialog::getFeatures() {
std::vector<App::DocumentObject*> result;
@ -67,8 +150,11 @@ void FeaturePickDialog::accept()
{
features.clear();
QListIterator<QListWidgetItem*> i(ui->listWidget->selectedItems());
while (i.hasNext())
features.push_back(i.next()->text());
while (i.hasNext()) {
QString t = i.next()->text();
t = t.left(t.indexOf(QString::fromAscii("(")) - 1);
features.push_back(t);
}
QDialog::accept();
}

View File

@ -0,0 +1,166 @@
/******************************************************************************
* Copyright (c)2012 Jan Rheinlaender <jrheinlaender@users.sourceforge.net> *
* *
* This file is part of the FreeCAD CAx development system. *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Library General Public *
* License as published by the Free Software Foundation; either *
* version 2 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Library General Public License for more details. *
* *
* You should have received a copy of the GNU Library General Public *
* License along with this library; see the file COPYING.LIB. If not, *
* write to the Free Software Foundation, Inc., 59 Temple Place, *
* Suite 330, Boston, MA 02111-1307, USA *
* *
******************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
# include <QPixmap>
# include <QDialog>
# include <QListIterator>
#endif
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/MainWindow.h>
#include <App/Document.h>
#include <Base/Tools.h>
#include "ui_FeaturePickDialog.h"
#include "FeaturePickDialog.h"
using namespace PartDesignGui;
const QString FeaturePickDialog::getFeatureStatusString(const featureStatus st)
{
switch (st) {
case validFeature: return tr("Valid");
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");
}
return tr("");
}
FeaturePickDialog::FeaturePickDialog(std::vector<App::DocumentObject*>& objects,
const std::vector<featureStatus>& status)
: QDialog(Gui::getMainWindow()), ui(new Ui_FeaturePickDialog)
{
ui->setupUi(this);
<<<<<<< 90079612b9f3db27654ac1d04ee2262d99842e1b
for (std::vector<App::DocumentObject*>::const_iterator o = objects.begin(); o != objects.end(); ++o)
ui->listWidget->addItem(QString::fromLatin1((*o)->getNameInDocument()));
=======
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->checkOtherBody->setChecked(false);
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);
std::vector<featureStatus>::const_iterator st = status.begin();
for (std::vector<App::DocumentObject*>::const_iterator o = objects.begin(); o != objects.end(); ++o) {
QListWidgetItem* item = new QListWidgetItem(QString::fromAscii((*o)->getNameInDocument()) +
QString::fromAscii(" (") + getFeatureStatusString(*st) + QString::fromAscii(")"));
ui->listWidget->addItem(item);
st++;
}
statuses = status;
updateList();
>>>>>>> Enhanced Pick dialog for PartDesign feature's sketches
}
FeaturePickDialog::~FeaturePickDialog()
{
}
void FeaturePickDialog::updateList()
{
int index = 0;
for (std::vector<featureStatus>::const_iterator st = statuses.begin(); st != statuses.end(); st++) {
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;
}
index++;
}
}
void FeaturePickDialog::onCheckOtherFeature(bool checked)
{
ui->radioIndependent->setEnabled(checked);
// TODO: Not implemented yet
//ui->radioDependent->setEnabled(checked);
//ui->radioXRef->setEnabled(checked);
updateList();
}
void FeaturePickDialog::onCheckOtherBody(bool checked)
{
ui->radioIndependent->setEnabled(checked);
// TODO: Not implemented yet
//ui->radioDependent->setEnabled(checked);
//ui->radioXRef->setEnabled(checked);
updateList();
}
void FeaturePickDialog::onUpdate(bool)
{
updateList();
}
std::vector<App::DocumentObject*> FeaturePickDialog::getFeatures() {
std::vector<App::DocumentObject*> result;
for (std::vector<QString>::const_iterator s = features.begin(); s != features.end(); ++s)
result.push_back(App::GetApplication().getActiveDocument()->getObject(s->toLatin1().data()));
return result;
}
void FeaturePickDialog::accept()
{
features.clear();
QListIterator<QListWidgetItem*> i(ui->listWidget->selectedItems());
while (i.hasNext()) {
QString t = i.next()->text();
t = t.left(t.indexOf(QString::fromAscii("(")) - 1);
features.push_back(t);
}
QDialog::accept();
}
#include "moc_FeaturePickDialog.cpp"

View File

@ -35,7 +35,15 @@ class FeaturePickDialog : public QDialog
Q_OBJECT
public:
FeaturePickDialog(std::vector<App::DocumentObject*> &objects);
enum featureStatus {
validFeature = 0,
invalidShape,
noWire,
isUsed,
otherBody
};
FeaturePickDialog(std::vector<App::DocumentObject*> &objects, const std::vector<featureStatus> &status);
~FeaturePickDialog();
std::vector<App::DocumentObject*> getFeatures();
@ -43,11 +51,19 @@ public:
void accept();
protected Q_SLOTS:
void onCheckOtherFeature(bool);
void onCheckOtherBody(bool);
void onUpdate(bool);
private:
Ui_FeaturePickDialog* ui;
std::vector<QString> features;
std::vector<featureStatus> statuses;
void updateList();
const QString getFeatureStatusString(const featureStatus st);
};
}

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>218</width>
<height>235</height>
<width>318</width>
<height>357</height>
</rect>
</property>
<property name="windowTitle">
@ -17,6 +17,41 @@
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
<item>
<widget class="QCheckBox" name="checkOtherBody">
<property name="text">
<string>Allow sketch from other Body</string>
</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>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">

View File

@ -549,10 +549,8 @@ bool TaskDlgPadParameters::reject()
// get the support and Sketch
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(PadView->getObject());
Sketcher::SketchObject *pcSketch = 0;
App::DocumentObject *pcSupport = 0;
if (pcPad->Sketch.getValue()) {
pcSketch = static_cast<Sketcher::SketchObject*>(pcPad->Sketch.getValue());
pcSupport = pcSketch->Support.getValue();
pcSketch = static_cast<Sketcher::SketchObject*>(pcPad->Sketch.getValue());
}
// roll back the done things
@ -563,13 +561,8 @@ bool TaskDlgPadParameters::reject()
if (!Gui::Application::Instance->getViewProvider(pcPad)) {
if (pcSketch && Gui::Application::Instance->getViewProvider(pcSketch))
Gui::Application::Instance->getViewProvider(pcSketch)->show();
if (pcSupport && Gui::Application::Instance->getViewProvider(pcSupport))
Gui::Application::Instance->getViewProvider(pcSupport)->show();
}
//Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()");
//Gui::Command::commitCommand();
return true;
}