From 492f1d24a467cbb74c31263e7b484105af05cbce Mon Sep 17 00:00:00 2001 From: Alexander Golubev Date: Mon, 17 Aug 2015 12:54:39 +0300 Subject: [PATCH] PartDesign/Gui: initial migration command implementation --- src/Mod/PartDesign/Gui/CommandBody.cpp | 249 +++++++++++++++++++-- src/Mod/PartDesign/Gui/Utils.cpp | 118 +++++++++- src/Mod/PartDesign/Gui/Utils.h | 14 +- src/Mod/PartDesign/Gui/Workbench.cpp | 147 ------------ src/Mod/PartDesign/Gui/Workbench.h | 1 - src/Mod/PartDesign/Gui/WorkflowManager.cpp | 12 +- src/Mod/PartDesign/Gui/WorkflowManager.h | 1 - 7 files changed, 361 insertions(+), 181 deletions(-) diff --git a/src/Mod/PartDesign/Gui/CommandBody.cpp b/src/Mod/PartDesign/Gui/CommandBody.cpp index c0d5ef616..5f49cd08b 100644 --- a/src/Mod/PartDesign/Gui/CommandBody.cpp +++ b/src/Mod/PartDesign/Gui/CommandBody.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2015 Alexander Golubev (Fat-Zer) * * * * This file is part of the FreeCAD CAx development system. * * * @@ -28,20 +28,47 @@ # include #endif +#include #include #include #include #include #include +#include #include #include #include +#include #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 ( PARTKEY ); + + if ( !rv ) { + Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + rcCmdMgr.runCommandByName("PartDesign_Part"); + rv = Gui::Application::Instance->activeView()->getActiveObject ( 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(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 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(); - std::string PartName; - - if(!actPart){ - Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); - rcCmdMgr.runCommandByName("PartDesign_Part"); - actPart = getDocument()->Tip.getValue(); + 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 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 ( 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 > featureChains; + std::list 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 (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 ( 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::iterator baseFeatIt; + auto chainIt = std::find_if( featureChains.begin(), featureChains.end(), + [baseFeat, &baseFeatIt] ( std::list&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 ( 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 ( 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(); } //=========================================================================== diff --git a/src/Mod/PartDesign/Gui/Utils.cpp b/src/Mod/PartDesign/Gui/Utils.cpp index eca7d6358..693e2b1f7 100644 --- a/src/Mod/PartDesign/Gui/Utils.cpp +++ b/src/Mod/PartDesign/Gui/Utils.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2015 Alexander Golubev (Fat-Zer) * * * * 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 properties; + obj->getPropertyList ( properties ); + for (auto prop: properties ) { + if ( prop->isDerivedFrom ( App::PropertyLink::getClassTypeId() ) ) { + if ( static_cast ( prop )->getValue () == feature ) { + return true; + } + } else if ( prop->isDerivedFrom ( App::PropertyLinkSub::getClassTypeId() ) ) { + if ( static_cast ( prop )->getValue () == feature ) { + return true; + } + } else if ( prop->isDerivedFrom ( App::PropertyLinkList::getClassTypeId() ) ) { + auto values = static_cast ( 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 ( 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 properties; + obj->getPropertyList ( properties ); + for (auto prop: properties ) { + std::string valueStr; + if ( prop->isDerivedFrom ( App::PropertyLink::getClassTypeId() ) ) { + App::PropertyLink *propLink = static_cast ( 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 ( prop ); + if ( propLink->getValue() != feature ) { + continue; + } + valueStr = buildLinkSubPythonStr ( body, propLink->getSubValues() ); + } else if ( prop->isDerivedFrom ( App::PropertyLinkList::getClassTypeId() ) ) { + App::PropertyLinkList *propLink = static_cast ( prop ); + std::vector 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 ( prop ); + std::vector 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 */ diff --git a/src/Mod/PartDesign/Gui/Utils.h b/src/Mod/PartDesign/Gui/Utils.h index ec8e2b24a..63a59ebbd 100644 --- a/src/Mod/PartDesign/Gui/Utils.h +++ b/src/Mod/PartDesign/Gui/Utils.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2015 Alexander Golubev (Fat-Zer) * * * * 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 */ diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index 3c64c9e7c..c50d8cbea 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -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( -// "

Converting PartDesign features to new Body centric schema

" -// "If you are unsure what that mean save the document under a new name.
" -// "You will not be able to load your work in an older Version of FreeCAD,
" -// "After the translation took place...

" -// "More information you will find here:
" -// " http://www.freecadweb.org/wiki/index.php?title=Assembly_project
" -// "Or the Assembly dedicated portion of our forum:
" -// " http://forum.freecadweb.org/
" -// ), -// 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 features = doc->getObjects(); -// -// // Assign all non-PartDesign features to a new group -// for (std::vector::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 roots; -// for (std::vector::iterator f = features.begin(); f != features.end(); f++) { -// // Note: The dependency list always contains at least the object itself -// std::vector 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(PDBODYKEY); -// assert(activeBody); -// -// // Create one Body for every root and put the appropriate features into it -// for (std::vector::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(PDBODYKEY); -// } -// -// std::set inList; -// inList.insert(*r); // start with the root feature -// std::vector bodyFeatures; -// std::string modelString = ""; -// do { -// for (std::set::const_iterator o = inList.begin(); o != inList.end(); o++) { -// std::vector::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 newInList; -// for (std::set::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 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::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::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::const_iterator prevf; -// -// for (std::vector::const_iterator f = bodyFeatures.begin(); f != bodyFeatures.end(); f++) { -// if ((*f)->getTypeId().isDerivedFrom(Sketcher::SketchObject::getClassTypeId())) { -// Sketcher::SketchObject *sketch = static_cast(*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; diff --git a/src/Mod/PartDesign/Gui/Workbench.h b/src/Mod/PartDesign/Gui/Workbench.h index 490ec1091..382fab4e9 100644 --- a/src/Mod/PartDesign/Gui/Workbench.h +++ b/src/Mod/PartDesign/Gui/Workbench.h @@ -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); }; diff --git a/src/Mod/PartDesign/Gui/WorkflowManager.cpp b/src/Mod/PartDesign/Gui/WorkflowManager.cpp index 4402bad8f..69d0e36c3 100644 --- a/src/Mod/PartDesign/Gui/WorkflowManager.cpp +++ b/src/Mod/PartDesign/Gui/WorkflowManager.cpp @@ -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; } diff --git a/src/Mod/PartDesign/Gui/WorkflowManager.h b/src/Mod/PartDesign/Gui/WorkflowManager.h index 27532ffaf..d5cb7930f 100644 --- a/src/Mod/PartDesign/Gui/WorkflowManager.h +++ b/src/Mod/PartDesign/Gui/WorkflowManager.h @@ -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);