/****************************************************************************** * Copyright (c)2012 Jan Rheinlaender * * * * 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 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Utils.h" #include "ui_TaskFeaturePick.h" #include "TaskFeaturePick.h" using namespace PartDesignGui; // TODO Do ve should snap here to App:Part or GeoFeatureGroup/DocumentObjectGroup ? (2015-09-04, Fat-Zer) const QString TaskFeaturePick::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("Belongs to another body"); case otherPart: return tr("Belongs to another part"); case notInBody: return tr("Doesn't belongs to any body"); case basePlane: return tr("Base plane"); case afterTip: return tr("Feature is located after the tip feature"); } return tr(""); } TaskFeaturePick::TaskFeaturePick(std::vector& objects, const std::vector& status, QWidget* parent) : TaskBox(Gui::BitmapFactory().pixmap("edit-select-box"), QString::fromAscii("Select feature"), true, parent), ui(new Ui_TaskFeaturePick) { proxy = new QWidget(this); ui->setupUi(proxy); connect(ui->checkUsed, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); 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))); connect(ui->checkNoBody, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); connect(ui->nobodyRadioIndependent, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); connect(ui->nobodyRadioXRef, SIGNAL(toggled(bool)), this, SLOT(onUpdate(bool))); enum { axisBit=0, planeBit = 1}; // NOTE: generally there shouldn't be more then one origin std::map > originVisStatus; auto statusIt = status.cbegin(); auto objIt = objects.begin(); assert(status.size() == objects.size()); for (; statusIt != status.end(); ++statusIt, ++objIt) { QListWidgetItem* item = new QListWidgetItem( QString::fromAscii((*objIt)->getNameInDocument()) + QString::fromAscii(" (") + getFeatureStatusString(*statusIt) + QString::fromAscii(")") ); ui->listWidget->addItem(item); //check if we need to set any origin in temporary visibility mode if (*statusIt != invalidShape && (*objIt)->isDerivedFrom ( App::OriginFeature::getClassTypeId () )) { App::Origin *origin = static_cast (*objIt)->getOrigin (); if (origin) { if ((*objIt)->isDerivedFrom ( App::Plane::getClassTypeId () )) { originVisStatus[ origin ].set (planeBit, true); } else if ( (*objIt)->isDerivedFrom ( App::Line::getClassTypeId () ) ) { originVisStatus[ origin ].set (axisBit, true); } } } } // Setup the origin's temporary visability for ( const auto & originPair: originVisStatus ) { const auto &origin = originPair.first; const auto &status = originPair.second; Gui::ViewProviderOrigin* vpo = static_cast ( Gui::Application::Instance->getViewProvider ( origin ) ); if (vpo) { vpo->setTemporaryVisibility( originVisStatus[origin][axisBit], originVisStatus[origin][planeBit]); origins.push_back(vpo); } } // TODO may be update origin API to show only some objects (2015-08-31, Fat-Zer) groupLayout()->addWidget(proxy); statuses = status; updateList(); } TaskFeaturePick::~TaskFeaturePick() { for(Gui::ViewProviderOrigin* vpo : origins) vpo->resetTemporaryVisibility(); } void TaskFeaturePick::updateList() { int index = 0; //get all origins in temporary mode for (std::vector::const_iterator st = statuses.begin(); st != statuses.end(); st++) { QListWidgetItem* item = ui->listWidget->item(index); switch (*st) { case validFeature: item->setHidden(false); break; case invalidShape: item->setHidden(true); break; case isUsed: item->setHidden(!ui->checkUsed->isChecked()); break; case noWire: item->setHidden(true); break; case otherBody: item->setHidden(!ui->checkOtherBody->isChecked()); break; case otherPart: item->setHidden(!ui->checkOtherPart->isChecked()); break; case notInBody: item->setHidden(!ui->checkNoBody->isChecked()); break; case basePlane: item->setHidden(false); break; case afterTip: item->setHidden(true); break; } index++; } } void TaskFeaturePick::onUpdate(bool) { updateList(); } std::vector TaskFeaturePick::getFeatures() { features.clear(); QListIterator i(ui->listWidget->selectedItems()); while (i.hasNext()) { auto item = i.next(); if(item->isHidden()) continue; QString t = item->text(); t = t.left(t.indexOf(QString::fromAscii("(")) - 1); features.push_back(t); } std::vector result; for (std::vector::const_iterator s = features.begin(); s != features.end(); s++) result.push_back(App::GetApplication().getActiveDocument()->getObject(s->toAscii().data())); 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 if(*st == notInBody) { if(ui->bodyRadioIndependent->isChecked()) { auto copy = makeCopy(obj, true); activeBody->addFeature(copy); // doesn't supposed to get here anything but sketch but to be on the safe side better to check if (copy->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) { Sketcher::SketchObject *sketch = static_cast(copy); PartDesignGui::fixSketchSupport(sketch); } 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 = std::string("Copy") + std::string(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); copy->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; } App::Property* cprop = *it++; if( strcmp(prop->getName(), "Label") == 0 ) { static_cast(cprop)->setValue("wuhahahahah"); continue; } cprop->Paste(*prop); } } 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(); for(Gui::SelectionSingleton::SelObj obj : Gui::Selection().getSelection()) { for(int row = 0; row < ui->listWidget->count(); row++) { QListWidgetItem *item = ui->listWidget->item(row); QString t = item->text(); t = t.left(t.indexOf(QString::fromAscii("(")) - 1); if(t.compare(QString::fromAscii(obj.FeatName))==0) { ui->listWidget->setItemSelected(item, true); } } } } void TaskFeaturePick::showExternal(bool val) { ui->checkOtherBody->setChecked(val); ui->checkOtherPart->setChecked(val); ui->checkNoBody->setChecked(val); updateList(); } //************************************************************************** //************************************************************************** // TaskDialog //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ TaskDlgFeaturePick::TaskDlgFeaturePick(std::vector &objects, const std::vector &status, boost::function)> afunc, boost::function)> wfunc) : TaskDialog(), accepted(false) { pick = new TaskFeaturePick(objects, status); Content.push_back(pick); acceptFunction = afunc; workFunction = wfunc; } TaskDlgFeaturePick::~TaskDlgFeaturePick() { //do the work now as before in accept() the dialog is still open, hence the work //function could not open annother dialog if(accepted) workFunction(pick->buildFeatures()); } //==== calls from the TaskView =============================================================== void TaskDlgFeaturePick::open() { } void TaskDlgFeaturePick::clicked(int) { } bool TaskDlgFeaturePick::accept() { accepted = acceptFunction(pick->getFeatures()); return accepted; } bool TaskDlgFeaturePick::reject() { accepted = false; return true; } void TaskDlgFeaturePick::showExternal(bool val) { pick->showExternal(val); } #include "moc_TaskFeaturePick.cpp"