PartDesign/Gui: initial migration command implementation
This commit is contained in:
parent
c4f094bba4
commit
492f1d24a4
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com *
|
||||
* Copyright (C) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
|
@ -28,20 +28,47 @@
|
|||
# include <QInputDialog>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <App/Part.h>
|
||||
#include <Gui/Command.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/ActiveObjectList.h>
|
||||
#include <Gui/MainWindow.h>
|
||||
#include <Gui/MDIView.h>
|
||||
|
||||
#include <Mod/Sketcher/App/SketchObject.h>
|
||||
#include <Mod/PartDesign/App/Body.h>
|
||||
#include <Mod/PartDesign/App/Feature.h>
|
||||
#include <Mod/PartDesign/App/FeatureSketchBased.h>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "WorkflowManager.h"
|
||||
|
||||
|
||||
//===========================================================================
|
||||
// Shared functions
|
||||
//===========================================================================
|
||||
|
||||
namespace PartDesignGui {
|
||||
|
||||
/// Returns active part, if there is no such, creates a new part, if it fails, shows a message
|
||||
App::Part* assertActivePart () {
|
||||
App::Part* rv= Gui::Application::Instance->activeView()->getActiveObject<App::Part *> ( PARTKEY );
|
||||
|
||||
if ( !rv ) {
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
rcCmdMgr.runCommandByName("PartDesign_Part");
|
||||
rv = Gui::Application::Instance->activeView()->getActiveObject<App::Part *> ( PARTKEY );
|
||||
if ( !rv ) {
|
||||
QMessageBox::critical ( 0, QObject::tr( "Part creation failed" ),
|
||||
QObject::tr( "Failed to create a part object." ) );
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
} /* PartDesignGui */
|
||||
|
||||
//===========================================================================
|
||||
// PartDesign_Part
|
||||
|
@ -62,7 +89,7 @@ CmdPartDesignPart::CmdPartDesignPart()
|
|||
|
||||
void CmdPartDesignPart::activated(int iMsg)
|
||||
{
|
||||
if ( PartDesignGui::assureModernWorkflow( getDocument() ) )
|
||||
if ( !PartDesignGui::assureModernWorkflow( getDocument() ) )
|
||||
return;
|
||||
|
||||
openCommand("Add a part");
|
||||
|
@ -71,7 +98,9 @@ void CmdPartDesignPart::activated(int iMsg)
|
|||
std::string PartName;
|
||||
PartName = getUniqueObjectName("Part");
|
||||
doCommand(Doc,"App.activeDocument().Tip = App.activeDocument().addObject('App::Part','%s')",PartName.c_str());
|
||||
doCommand(Doc,"App.activeDocument().ActiveObject.Label = '%s'", QObject::tr(PartName.c_str()).toStdString().c_str());
|
||||
// TODO We really must to set label ourselfs? (2015-08-17, Fat-Zer)
|
||||
doCommand(Doc,"App.activeDocument().%s.Label = '%s'", PartName.c_str(),
|
||||
QObject::tr(PartName.c_str()).toUtf8().data());
|
||||
PartDesignGui::setUpPart(dynamic_cast<App::Part *>(getDocument()->getObject(PartName.c_str())));
|
||||
doCommand(Gui::Command::Gui, "Gui.activeView().setActiveObject('%s', App.activeDocument().%s)", PARTKEY, PartName.c_str());
|
||||
|
||||
|
@ -102,7 +131,7 @@ CmdPartDesignBody::CmdPartDesignBody()
|
|||
|
||||
void CmdPartDesignBody::activated(int iMsg)
|
||||
{
|
||||
if ( PartDesignGui::assureModernWorkflow( getDocument() ) )
|
||||
if ( !PartDesignGui::assureModernWorkflow( getDocument() ) )
|
||||
return;
|
||||
std::vector<App::DocumentObject*> features =
|
||||
getSelection().getObjectsOfType(Part::Feature::getClassTypeId());
|
||||
|
@ -128,19 +157,17 @@ void CmdPartDesignBody::activated(int iMsg)
|
|||
}
|
||||
|
||||
// first check if Part is already created:
|
||||
App::Part *actPart = getDocument()->Tip.getValue<App::Part *>();
|
||||
std::string PartName;
|
||||
|
||||
if(!actPart){
|
||||
Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager();
|
||||
rcCmdMgr.runCommandByName("PartDesign_Part");
|
||||
actPart = getDocument()->Tip.getValue<App::Part *>();
|
||||
App::Part *actPart = PartDesignGui::assertActivePart ();
|
||||
if (!actPart) {
|
||||
return;
|
||||
}
|
||||
|
||||
openCommand("Add a body");
|
||||
std::string PartName = actPart->getNameInDocument();
|
||||
|
||||
openCommand("Add a Body");
|
||||
|
||||
std::string FeatName = getUniqueObjectName("Body");
|
||||
|
||||
PartName = actPart->getNameInDocument();
|
||||
// add the Body feature itself, and make it active
|
||||
doCommand(Doc,"App.activeDocument().addObject('PartDesign::Body','%s')", FeatName.c_str());
|
||||
if (baseFeature) {
|
||||
|
@ -175,7 +202,7 @@ CmdPartDesignMigrate::CmdPartDesignMigrate()
|
|||
sAppModule = "PartDesign";
|
||||
sGroup = QT_TR_NOOP("PartDesign");
|
||||
sMenuText = QT_TR_NOOP("Migrate");
|
||||
sToolTipText = QT_TR_NOOP("Migrate document to the new workflow");
|
||||
sToolTipText = QT_TR_NOOP("Migrate document to the modern partdesign workflow");
|
||||
sWhatsThis = sToolTipText;
|
||||
sStatusTip = sToolTipText;
|
||||
}
|
||||
|
@ -183,17 +210,197 @@ CmdPartDesignMigrate::CmdPartDesignMigrate()
|
|||
void CmdPartDesignMigrate::activated(int iMsg)
|
||||
{
|
||||
App::Document *doc = getDocument();
|
||||
// TODO make a proper implementation
|
||||
QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Not implemented yet"),
|
||||
QObject::tr("The migration not implemented yet, just force-switching to the new workflow.\n"
|
||||
"Previous workflow was: %1").arg(int(
|
||||
PartDesignGui::WorkflowManager::instance()->determinWorkflow( doc ) )));
|
||||
PartDesignGui::WorkflowManager::instance()->forceWorkflow(doc, PartDesignGui::Workflow::Modern);
|
||||
|
||||
std::set<PartDesign::Feature*> migrateFeatures;
|
||||
|
||||
|
||||
// Retrive all PartDesign Features objects and filter out features already belongs to some body
|
||||
for ( const auto & feat: doc->getObjects( ) ) {
|
||||
if( feat->isDerivedFrom( PartDesign::Feature::getClassTypeId() ) &&
|
||||
!PartDesign::Body::findBodyOf( feat ) && PartDesign::Body::isSolidFeature ( feat ) ) {
|
||||
migrateFeatures.insert ( static_cast <PartDesign::Feature *>( feat ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( migrateFeatures.empty() ) {
|
||||
if ( !PartDesignGui::isModernWorkflow ( doc ) ) {
|
||||
// If there is nothing to migrate and workflow is still old just set it to modern
|
||||
PartDesignGui::WorkflowManager::instance()->forceWorkflow (
|
||||
doc, PartDesignGui::Workflow::Modern );
|
||||
} else {
|
||||
// Huh? nothing to migrate?
|
||||
QMessageBox::warning ( 0, QObject::tr ( "Nothing to migrate" ),
|
||||
QObject::tr ( "No PartDesign features which doesn't belong to a body found."
|
||||
" Nothing to migrate." ) );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: this action is undoable, should it be?
|
||||
PartDesignGui::WorkflowManager::instance()->forceWorkflow ( doc, PartDesignGui::Workflow::Modern );
|
||||
|
||||
// Put features into chains. Each chain should become a separate body.
|
||||
std::list< std::list<PartDesign::Feature *> > featureChains;
|
||||
std::list<PartDesign::Feature *> chain; //< the current chain we are working on
|
||||
|
||||
for (auto featIt = migrateFeatures.begin(); !migrateFeatures.empty(); ) {
|
||||
Part::Feature *base = (*featIt)->getBaseObject( /*silent =*/ true );
|
||||
|
||||
chain.push_front ( *featIt );
|
||||
|
||||
if ( !base || !base->isDerivedFrom (PartDesign::Feature::getClassTypeId () ) ||
|
||||
PartDesignGui::isAnyNonPartDesignLinksTo ( static_cast <PartDesign::Feature *>(base),
|
||||
/*respectGroups=*/ true ) ) {
|
||||
// a feature based on nothing as well as on non-partdesign solid starts a new chain
|
||||
auto newChainIt = featureChains.emplace (featureChains.end());
|
||||
newChainIt->splice (newChainIt->end(), chain);
|
||||
} else {
|
||||
// we are basing on some partdesign feature wich supposed to belong to some body
|
||||
PartDesign::Feature *baseFeat = static_cast <PartDesign::Feature *>( base );
|
||||
|
||||
auto baseFeatSetIt = find ( migrateFeatures.begin (), migrateFeatures.end (), baseFeat );
|
||||
|
||||
if ( baseFeatSetIt != migrateFeatures.end() ) {
|
||||
// base feature is pending for migration, switch to it and continue over
|
||||
migrateFeatures.erase(featIt);
|
||||
featIt = baseFeatSetIt;
|
||||
continue;
|
||||
} else {
|
||||
// The base feature seems already assigned to some chain
|
||||
// Find which
|
||||
std::list<PartDesign::Feature *>::iterator baseFeatIt;
|
||||
auto chainIt = std::find_if( featureChains.begin(), featureChains.end(),
|
||||
[baseFeat, &baseFeatIt] ( std::list<PartDesign::Feature *>&chain ) mutable -> bool {
|
||||
baseFeatIt = std::find( chain.begin(), chain.end(), baseFeat );
|
||||
return baseFeatIt != chain.end();
|
||||
} );
|
||||
|
||||
if ( chainIt != featureChains.end() ) {
|
||||
assert (baseFeatIt != chainIt->end());
|
||||
if ( std::next ( baseFeatIt ) == chainIt->end() ) {
|
||||
// just append our chain to already found
|
||||
chainIt->splice ( chainIt->end(), chain );
|
||||
// TODO If we will hit a third part everything will be messed up again.
|
||||
// Probably it will require a yet another smart-ass find_if. (2015-08-10, Fat-Zer)
|
||||
} else {
|
||||
// We have a fork of a partDesign feature here
|
||||
// add a chain for current body
|
||||
auto newChainIt = featureChains.emplace (featureChains.end());
|
||||
newChainIt->splice (newChainIt->end(), chain);
|
||||
// add a chain for forked one
|
||||
newChainIt = featureChains.emplace (featureChains.end());
|
||||
newChainIt->splice (newChainIt->end(), *chainIt,
|
||||
std::next ( baseFeatIt ), chainIt->end());
|
||||
}
|
||||
} else {
|
||||
// The feature is not present in list pending for migration,
|
||||
// This generally shouldn't happen but may be if we run into some broken file
|
||||
// Try to find out the body we should insert into
|
||||
// TODO Some error/warning is needed here (2015-08-10, Fat-Zer)
|
||||
auto newChainIt = featureChains.emplace (featureChains.end());
|
||||
newChainIt->splice (newChainIt->end(), chain);
|
||||
}
|
||||
}
|
||||
}
|
||||
migrateFeatures.erase ( featIt );
|
||||
featIt = migrateFeatures.begin ();
|
||||
// TODO Align visability (2015-08-17, Fat-Zer)
|
||||
} /* for */
|
||||
|
||||
// add a part if there is no active yet
|
||||
App::Part *actPart = PartDesignGui::assertActivePart ();
|
||||
|
||||
if (!actPart) {
|
||||
return;
|
||||
}
|
||||
|
||||
// do the actual migration
|
||||
Gui::Command::openCommand("Migrate legacy part design features to Bodies");
|
||||
|
||||
for ( auto chainIt = featureChains.begin(); !featureChains.empty();
|
||||
featureChains.erase (chainIt), chainIt = featureChains.begin () ) {
|
||||
#ifndef FC_DEBUG
|
||||
if ( chainIt->empty () ) { // prevent crash in release in case of errors
|
||||
continue;
|
||||
}
|
||||
#else
|
||||
assert ( !chainIt->empty () );
|
||||
#endif
|
||||
Part::Feature *base = chainIt->front()->getBaseObject ( /*silent =*/ true );
|
||||
|
||||
// Find a suitable chain to work with
|
||||
for( ; chainIt != featureChains.end(); chainIt ++) {
|
||||
base = chainIt->front()->getBaseObject ( /*silent =*/ true );
|
||||
if (!base || !base->isDerivedFrom ( PartDesign::Feature::getClassTypeId () ) ) {
|
||||
break; // no base is ok
|
||||
} else {
|
||||
// The base feature is a PartDesign, it's a fork, try to reassign it to a body...
|
||||
base = PartDesign::Body::findBodyOf ( base );
|
||||
if ( base ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( chainIt == featureChains.end() ) {
|
||||
// Shouldn't happen, may be only in case of some circular dependency?
|
||||
// TODO Some error message (2015-08-11, Fat-Zer)
|
||||
chainIt = featureChains.begin();
|
||||
base = chainIt->front()->getBaseObject ( /*silent =*/ true );
|
||||
}
|
||||
|
||||
// Construct a Pretty Body name based on the Tip
|
||||
std::string bodyName = getUniqueObjectName (
|
||||
std::string ( chainIt->back()->getNameInDocument() ).append ( "Body" ).c_str () ) ;
|
||||
|
||||
// Create a body for the chain
|
||||
doCommand ( Doc,"App.activeDocument().addObject('PartDesign::Body','%s')", bodyName.c_str () );
|
||||
doCommand ( Doc,"App.activeDocument().%s.addObject(App.ActiveDocument.%s)",
|
||||
actPart->getNameInDocument (), bodyName.c_str () );
|
||||
if (base) {
|
||||
doCommand ( Doc,"App.activeDocument().%s.BaseFeature = App.activeDocument().%s",
|
||||
bodyName.c_str (), base->getNameInDocument () );
|
||||
}
|
||||
|
||||
// Fill the body with features
|
||||
for ( auto feature: *chainIt ) {
|
||||
if ( feature->isDerivedFrom ( PartDesign::SketchBased::getClassTypeId() ) ) {
|
||||
// add the sketch and also reroute it if needed
|
||||
PartDesign::SketchBased *sketchBased = static_cast<PartDesign::SketchBased *> ( feature );
|
||||
Part::Part2DObject *sketch = sketchBased->getVerifiedSketch( /*silent =*/ true);
|
||||
if ( sketch ) {
|
||||
doCommand ( Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
|
||||
bodyName.c_str (), sketch->getNameInDocument() );
|
||||
|
||||
if ( sketch->isDerivedFrom ( Sketcher::SketchObject::getClassTypeId() ) ) {
|
||||
try {
|
||||
PartDesignGui::fixSketchSupport ( static_cast<Sketcher::SketchObject *> ( sketch ) );
|
||||
} catch (Base::Exception &) {
|
||||
QMessageBox::critical(Gui::getMainWindow(),
|
||||
QObject::tr("Sketch plane cannot be migrated"),
|
||||
QObject::tr("Please edit '%1' and redefine it to use a Base or "
|
||||
"Datum plane as the sketch plane.").
|
||||
arg(QString::fromUtf8(sketch->Label.getValue()) ) );
|
||||
}
|
||||
} else {
|
||||
// TODO Message that sketchbased is based not on a sketch (2015-08-11, Fat-Zer)
|
||||
}
|
||||
}
|
||||
}
|
||||
doCommand ( Doc,"App.activeDocument().%s.addFeature(App.activeDocument().%s)",
|
||||
bodyName.c_str (), feature->getNameInDocument() );
|
||||
|
||||
PartDesignGui::relinkToBody ( feature );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
updateActive();
|
||||
}
|
||||
|
||||
bool CmdPartDesignMigrate::isActive(void)
|
||||
{
|
||||
return hasActiveDocument() && !PartDesignGui::isLegacyWorkflow ( getDocument () );
|
||||
return hasActiveDocument();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com *
|
||||
* Copyright (C) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
|
@ -189,6 +189,7 @@ void fixSketchSupport (Sketcher::SketchObject* sketch)
|
|||
// Find the normal distance from origin to the sketch plane
|
||||
gp_Pln pln(gp_Pnt (pnt.x, pnt.y, pnt.z), gp_Dir(sketchVector.x, sketchVector.y, sketchVector.z));
|
||||
double offset = pln.Distance(gp_Pnt(0,0,0));
|
||||
// TODO Issue a message if sketch have coordinates offset inside the plain (2016-08-15, Fat-Zer)
|
||||
|
||||
if (fabs(offset) < Precision::Confusion()) {
|
||||
// One of the base planes
|
||||
|
@ -222,9 +223,120 @@ void fixSketchSupport (Sketcher::SketchObject* sketch)
|
|||
sketch->getNameInDocument(), reverseSketch ? "True" : "False");
|
||||
Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.MapMode = '%s'",
|
||||
sketch->getNameInDocument(),Attacher::AttachEngine::eMapModeStrings[Attacher::mmFlatFace]);
|
||||
Gui::Command::doCommand(Gui::Command::Gui,"App.activeDocument().recompute()"); // recompute the feature based on its references
|
||||
}
|
||||
}
|
||||
|
||||
bool isPartDesignAwareObjecta (App::DocumentObject *obj, bool respectGroups = false ) {
|
||||
return (obj->isDerivedFrom( PartDesign::Feature::getClassTypeId () ) ||
|
||||
PartDesign::Body::isAllowed ( obj ) ||
|
||||
obj->isDerivedFrom ( PartDesign::Body::getClassTypeId () ) ||
|
||||
( respectGroups && (
|
||||
obj->isDerivedFrom (App::GeoFeatureGroup::getClassTypeId () ) ||
|
||||
obj->isDerivedFrom (App::DocumentObjectGroup::getClassTypeId () )
|
||||
) ) );
|
||||
}
|
||||
|
||||
} /* PartDesignGui */
|
||||
bool isAnyNonPartDesignLinksTo ( PartDesign::Feature *feature, bool respectGroups ) {
|
||||
App::Document *doc = feature->getDocument();
|
||||
|
||||
for ( const auto & obj: doc->getObjects () ) {
|
||||
if ( !isPartDesignAwareObjecta ( obj, respectGroups ) ) {
|
||||
std::vector <App::Property *> properties;
|
||||
obj->getPropertyList ( properties );
|
||||
for (auto prop: properties ) {
|
||||
if ( prop->isDerivedFrom ( App::PropertyLink::getClassTypeId() ) ) {
|
||||
if ( static_cast <App::PropertyLink *> ( prop )->getValue () == feature ) {
|
||||
return true;
|
||||
}
|
||||
} else if ( prop->isDerivedFrom ( App::PropertyLinkSub::getClassTypeId() ) ) {
|
||||
if ( static_cast <App::PropertyLinkSub *> ( prop )->getValue () == feature ) {
|
||||
return true;
|
||||
}
|
||||
} else if ( prop->isDerivedFrom ( App::PropertyLinkList::getClassTypeId() ) ) {
|
||||
auto values = static_cast <App::PropertyLinkList *> ( prop )->getValues ();
|
||||
if ( std::find ( values.begin (), values.end (), feature ) != values.end() ) {
|
||||
return true;
|
||||
}
|
||||
} else if ( prop->isDerivedFrom ( App::PropertyLinkSubList::getClassTypeId() ) ) {
|
||||
auto values = static_cast <App::PropertyLinkSubList *> ( prop )->getValues ();
|
||||
if ( std::find ( values.begin (), values.end (), feature ) != values.end() ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void relinkToBody (PartDesign::Feature *feature) {
|
||||
App::Document *doc = feature->getDocument();
|
||||
PartDesign::Body *body = PartDesign::Body::findBodyOf ( feature );
|
||||
|
||||
if (!body) {
|
||||
throw Base::Exception ("Coudn't find body for the feature");
|
||||
}
|
||||
|
||||
std::string bodyName = body->getNameInDocument ();
|
||||
|
||||
for ( const auto & obj: doc->getObjects () ) {
|
||||
if ( !isPartDesignAwareObjecta ( obj ) ) {
|
||||
std::vector <App::Property *> properties;
|
||||
obj->getPropertyList ( properties );
|
||||
for (auto prop: properties ) {
|
||||
std::string valueStr;
|
||||
if ( prop->isDerivedFrom ( App::PropertyLink::getClassTypeId() ) ) {
|
||||
App::PropertyLink *propLink = static_cast <App::PropertyLink *> ( prop );
|
||||
if ( propLink->getValue() != feature ) {
|
||||
continue;
|
||||
}
|
||||
valueStr = std::string ( "App.activeDocument()." ).append ( bodyName );
|
||||
} else if ( prop->isDerivedFrom ( App::PropertyLinkSub::getClassTypeId() ) ) {
|
||||
App::PropertyLinkSub *propLink = static_cast <App::PropertyLinkSub *> ( prop );
|
||||
if ( propLink->getValue() != feature ) {
|
||||
continue;
|
||||
}
|
||||
valueStr = buildLinkSubPythonStr ( body, propLink->getSubValues() );
|
||||
} else if ( prop->isDerivedFrom ( App::PropertyLinkList::getClassTypeId() ) ) {
|
||||
App::PropertyLinkList *propLink = static_cast <App::PropertyLinkList *> ( prop );
|
||||
std::vector <App::DocumentObject *> linkList = propLink->getValues ();
|
||||
bool valueChanged=false;
|
||||
for (auto & link : linkList ) {
|
||||
if ( link == feature ) {
|
||||
link = body;
|
||||
valueChanged = true;
|
||||
}
|
||||
}
|
||||
if ( valueChanged ) {
|
||||
valueStr = buildLinkListPythonStr ( linkList );
|
||||
// TODO Issue some message here due to it likely will break something
|
||||
// (2015-08-13, Fat-Zer)
|
||||
}
|
||||
} else if ( prop->isDerivedFrom ( App::PropertyLinkSub::getClassTypeId() ) ) {
|
||||
App::PropertyLinkSubList *propLink = static_cast <App::PropertyLinkSubList *> ( prop );
|
||||
std::vector <App::DocumentObject *> linkList = propLink->getValues ();
|
||||
bool valueChanged=false;
|
||||
for (auto & link : linkList ) {
|
||||
if ( link == feature ) {
|
||||
link = body;
|
||||
valueChanged = true;
|
||||
}
|
||||
}
|
||||
if ( valueChanged ) {
|
||||
valueStr = buildLinkSubListPythonStr ( linkList, propLink->getSubValues() );
|
||||
// TODO Issue some message here due to it likely will break something
|
||||
// (2015-08-13, Fat-Zer)
|
||||
}
|
||||
}
|
||||
|
||||
if ( !valueStr.empty () ) {
|
||||
Gui::Command::doCommand ( Gui::Command::Doc, "App.activeDocument().%s.%s=%s",
|
||||
obj->getNameInDocument (), prop->getName (), valueStr.c_str() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} /* PartDesignGui */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/***************************************************************************
|
||||
* Copyright (C) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com *
|
||||
* Copyright (C) 2015 Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> *
|
||||
* *
|
||||
* This file is part of the FreeCAD CAx development system. *
|
||||
* *
|
||||
|
@ -28,6 +28,7 @@
|
|||
*/
|
||||
namespace PartDesign {
|
||||
class Body;
|
||||
class Feature;
|
||||
}
|
||||
|
||||
namespace App {
|
||||
|
@ -64,6 +65,15 @@ PartDesign::Body *setUpPart(const App::Part *);
|
|||
/// Fix sketch support after moving a free sketch into a body
|
||||
void fixSketchSupport(Sketcher::SketchObject* sketch);
|
||||
|
||||
} /* PartDesignGui */
|
||||
/**
|
||||
* Returns true if document has any non-PartDesign objects that links to the given object.
|
||||
* If respectGroups is true don't count links from App::GeoFeatureGroup-derived objects (default is false)
|
||||
*/
|
||||
bool isAnyNonPartDesignLinksTo ( PartDesign::Feature *feature, bool respectGroups=false );
|
||||
|
||||
/// Relink all nonPartDesign features to the body instead of the given partDesign Feature
|
||||
void relinkToBody ( PartDesign::Feature *feature );
|
||||
|
||||
} /* PartDesignGui */
|
||||
|
||||
#endif /* end of include guard: UTILS_H_CS5LK2ZQ */
|
||||
|
|
|
@ -65,153 +65,6 @@ Workbench::~Workbench() {
|
|||
WorkflowManager::destruct();
|
||||
}
|
||||
|
||||
// Commented out due to later to be moves and/or generall rewrighted from scratch (Fat-Zer 2015-08-08)
|
||||
// void Workbench::_doMigration(const App::Document* doc)
|
||||
// {
|
||||
// bool groupCreated = false;
|
||||
//
|
||||
// if(doc->countObjects() != 0) {
|
||||
// // show a warning about the convertion
|
||||
// Gui::Dialog::DlgCheckableMessageBox::showMessage(
|
||||
// QString::fromLatin1("PartDesign conversion warning"),
|
||||
// QString::fromLatin1(
|
||||
// "<h2>Converting PartDesign features to new Body centric schema</h2>"
|
||||
// "If you are unsure what that mean save the document under a new name.<br>"
|
||||
// "You will not be able to load your work in an older Version of FreeCAD,<br>"
|
||||
// "After the translation took place...<br><br>"
|
||||
// "More information you will find here:<br>"
|
||||
// " <a href=\"http://www.freecadweb.org/wiki/index.php?title=Assembly_project\">http://www.freecadweb.org/wiki/index.php?title=Assembly_project</a> <br>"
|
||||
// "Or the Assembly dedicated portion of our forum:<br>"
|
||||
// " <a href=\"http://forum.freecadweb.org/viewforum.php?f=20&sid=2a1a326251c44576f450739e4a74c37d\">http://forum.freecadweb.org/</a> <br>"
|
||||
// ),
|
||||
// false,
|
||||
// QString::fromLatin1("Don't tell me again, I know!")
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// Gui::Command::openCommand("Migrate part to Body feature");
|
||||
//
|
||||
// // Get the objects now, before adding the Body and the base planes
|
||||
// std::vector<App::DocumentObject*> features = doc->getObjects();
|
||||
//
|
||||
// // Assign all non-PartDesign features to a new group
|
||||
// for (std::vector<App::DocumentObject*>::iterator f = features.begin(); f != features.end(); ) {
|
||||
// if ((*f)->getTypeId().isDerivedFrom(PartDesign::Feature::getClassTypeId()) ||
|
||||
// (*f)->getTypeId().isDerivedFrom(Part::Part2DObject::getClassTypeId())) {
|
||||
// ++f;
|
||||
// } else {
|
||||
// if (!groupCreated) {
|
||||
// Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().addObject('App::DocumentObjectGroup','NonBodyFeatures')");
|
||||
// Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().ActiveObject.Label = '%s'",
|
||||
// QObject::tr("NonBodyFeatures").toStdString().c_str());
|
||||
// groupCreated = true;
|
||||
// }
|
||||
// Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().NonBodyFeatures.addObject(App.activeDocument().getObject('%s'))",
|
||||
// (*f)->getNameInDocument());
|
||||
// f = features.erase(f);
|
||||
// }
|
||||
// }
|
||||
// // TODO: Fold the group (is that possible through the Python interface?)
|
||||
//
|
||||
// // Try to find the root(s) of the model tree (the features that depend on no other feature)
|
||||
// // Note: We assume a linear graph, except for MultiTransform features
|
||||
// std::vector<App::DocumentObject*> roots;
|
||||
// for (std::vector<App::DocumentObject*>::iterator f = features.begin(); f != features.end(); f++) {
|
||||
// // Note: The dependency list always contains at least the object itself
|
||||
// std::vector<App::DocumentObject*> ftemp;
|
||||
// ftemp.push_back(*f);
|
||||
// if (doc->getDependencyList(ftemp).size() == 1)
|
||||
// roots.push_back(*f);
|
||||
// }
|
||||
//
|
||||
// // Always create at least the first body, even if the document is empty
|
||||
// buildDefaultPartAndBody(doc);
|
||||
// PartDesign::Body *activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY);
|
||||
// assert(activeBody);
|
||||
//
|
||||
// // Create one Body for every root and put the appropriate features into it
|
||||
// for (std::vector<App::DocumentObject*>::iterator r = roots.begin(); r != roots.end(); r++) {
|
||||
// if (r != roots.begin()) {
|
||||
// Gui::Command::runCommand(Gui::Command::Doc, "FreeCADGui.runCommand('PartDesign_Body')");
|
||||
// activeBody = Gui::Application::Instance->activeView()->getActiveObject<PartDesign::Body*>(PDBODYKEY);
|
||||
// }
|
||||
//
|
||||
// std::set<App::DocumentObject*> inList;
|
||||
// inList.insert(*r); // start with the root feature
|
||||
// std::vector<App::DocumentObject*> bodyFeatures;
|
||||
// std::string modelString = "";
|
||||
// do {
|
||||
// for (std::set<App::DocumentObject*>::const_iterator o = inList.begin(); o != inList.end(); o++) {
|
||||
// std::vector<App::DocumentObject*>::iterator feat = std::find(features.begin(), features.end(), *o);
|
||||
// if (feat != features.end()) {
|
||||
// bodyFeatures.push_back(*o);
|
||||
// modelString += std::string(modelString.empty() ? "" : ",") + "App.ActiveDocument." + (*o)->getNameInDocument();
|
||||
// features.erase(feat);
|
||||
// } else {
|
||||
// QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Non-linear tree"),
|
||||
// QObject::tr("Please look at '%1' and make sure that the migration result is what you"
|
||||
// " would expect.").arg(QString::fromAscii((*o)->getNameInDocument())));
|
||||
// }
|
||||
// }
|
||||
// std::set<App::DocumentObject*> newInList;
|
||||
// for (std::set<App::DocumentObject*>::const_iterator o = inList.begin(); o != inList.end(); o++) {
|
||||
// // Omit members of a MultiTransform from the inList, to avoid migration errors
|
||||
// if (PartDesign::Body::isMemberOfMultiTransform(*o))
|
||||
// continue;
|
||||
// std::vector<App::DocumentObject*> iL = doc->getInList(*o);
|
||||
// newInList.insert(iL.begin(), iL.end());
|
||||
// }
|
||||
// inList = newInList; // TODO: Memory leak? Unnecessary copying?
|
||||
// } while (!inList.empty());
|
||||
//
|
||||
// if (!modelString.empty()) {
|
||||
// modelString = std::string("[") + modelString + "]";
|
||||
// Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Model = %s", activeBody->getNameInDocument(), modelString.c_str());
|
||||
// // Set the Tip, but not to a member of a MultiTransform!
|
||||
// for (std::vector<App::DocumentObject*>::const_reverse_iterator f = bodyFeatures.rbegin(); f != bodyFeatures.rend(); f++) {
|
||||
// if (PartDesign::Body::isMemberOfMultiTransform(*f))
|
||||
// continue;
|
||||
// Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Tip = App.activeDocument().%s",
|
||||
// activeBody->getNameInDocument(), (*f)->getNameInDocument());
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Initialize the BaseFeature property of all PartDesign solid features
|
||||
// App::DocumentObject* baseFeature = NULL;
|
||||
// for (std::vector<App::DocumentObject*>::const_iterator f = bodyFeatures.begin(); f != bodyFeatures.end(); f++) {
|
||||
// if (PartDesign::Body::isSolidFeature(*f)) {
|
||||
// Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.BaseFeature = %s",
|
||||
// (*f)->getNameInDocument(),
|
||||
// baseFeature == NULL ?
|
||||
// "None" :
|
||||
// (std::string("App.activeDocument().") + baseFeature->getNameInDocument()).c_str());
|
||||
//
|
||||
// baseFeature = *f;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Re-route all sketches without support to the base planes
|
||||
// std::vector<App::DocumentObject*>::const_iterator prevf;
|
||||
//
|
||||
// for (std::vector<App::DocumentObject*>::const_iterator f = bodyFeatures.begin(); f != bodyFeatures.end(); f++) {
|
||||
// if ((*f)->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) {
|
||||
// Sketcher::SketchObject *sketch = static_cast<Sketcher::SketchObject*>(*f);
|
||||
// try {
|
||||
// fixSketchSupport(sketch);
|
||||
// } catch (Base::Exception &) {
|
||||
// QMessageBox::critical(Gui::getMainWindow(), QObject::tr("Sketch plane cannot be migrated"),
|
||||
// QObject::tr("Please edit '%1' and redefine it to use a Base or Datum plane as the sketch plane.").
|
||||
// arg(QString::fromAscii(sketch->getNameInDocument()) ) );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// prevf = f;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
void Workbench::_switchToDocument(const App::Document* doc)
|
||||
{
|
||||
if (doc == NULL) return;
|
||||
|
|
|
@ -78,7 +78,6 @@ private:
|
|||
// Add new objects to the body, if appropriate
|
||||
//void slotNewObject(const App::DocumentObject& obj);
|
||||
|
||||
//void _doMigration(const App::Document* doc);
|
||||
void _switchToDocument(const App::Document* doc);
|
||||
|
||||
};
|
||||
|
|
|
@ -72,10 +72,11 @@ WorkflowManager::~WorkflowManager() {
|
|||
// Those destruction/construction is not really needed and could be done in the instance()
|
||||
// but to make things a bit more cleare better to keep them around.
|
||||
void WorkflowManager::init() {
|
||||
if (_instance) {
|
||||
throw Base::Exception( "Trying to init the workflow manager second time." );
|
||||
if (!_instance) {
|
||||
_instance = new WorkflowManager();
|
||||
} else {
|
||||
//throw Base::Exception( "Trying to init the workflow manager second time." );
|
||||
}
|
||||
_instance = new WorkflowManager();
|
||||
}
|
||||
|
||||
WorkflowManager *WorkflowManager::instance() {
|
||||
|
@ -135,7 +136,6 @@ Workflow WorkflowManager::determinWorkflow( App::Document *doc) {
|
|||
|
||||
// Guess the workflow again
|
||||
rv = guessWorkflow (doc);
|
||||
|
||||
if (rv != Workflow::Modern) {
|
||||
QMessageBox msgBox;
|
||||
|
||||
|
@ -156,7 +156,7 @@ Workflow WorkflowManager::determinWorkflow( App::Document *doc) {
|
|||
"If you refuse to migrate you won't be able to use new PartDesign features"
|
||||
" like Bodies and Parts. As a result you also won't be able to use your parts"
|
||||
" in the assembly workbench.\n"
|
||||
"Although you will be able to migrate any moment later with 'Part Design->Migrate'." ) );
|
||||
"Although you will be able to migrate any moment later with 'Part Design->Migrate...'." ) );
|
||||
msgBox.setIcon( QMessageBox::Question );
|
||||
QPushButton * yesBtn = msgBox.addButton ( QMessageBox::Yes );
|
||||
QPushButton * manuallyBtn = msgBox.addButton (
|
||||
|
@ -171,7 +171,6 @@ Workflow WorkflowManager::determinWorkflow( App::Document *doc) {
|
|||
msgBox.exec();
|
||||
|
||||
if ( msgBox.clickedButton() == yesBtn ) {
|
||||
// TODO Assure that this will actually work (2015-08-02, Fat-Zer)
|
||||
Gui::Application::Instance->commandManager().runCommandByName("PartDesign_Migrate");
|
||||
rv = Workflow::Modern;
|
||||
} else if ( msgBox.clickedButton() == manuallyBtn ) {
|
||||
|
@ -183,6 +182,7 @@ Workflow WorkflowManager::determinWorkflow( App::Document *doc) {
|
|||
|
||||
// Actually set the result in our map
|
||||
dwMap[ doc ] = rv;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ public:
|
|||
|
||||
/**
|
||||
* Force the desired workflow in document
|
||||
* Note: currently added for testing purpose; May be removed later
|
||||
*/
|
||||
void forceWorkflow (const App::Document *doc, Workflow wf);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user