diff --git a/src/Mod/Part/App/Attacher.cpp b/src/Mod/Part/App/Attacher.cpp index 3520d355e27b..ef6b0f3da074 100644 --- a/src/Mod/Part/App/Attacher.cpp +++ b/src/Mod/Part/App/Attacher.cpp @@ -258,31 +258,21 @@ Base::Placement AttachEngine::placementFactory(const gp_Dir &ZAxis, } -eMapMode AttachEngine::listMapModes(eSuggestResult& msg, - std::vector* allApplicableModes, - std::set* nextRefTypeHint, - std::map* reachableModes) const +void AttachEngine::suggestMapModes(SuggestResult &result) const { - //replace a pointer with a valid reference, to avoid checks for zero pointer everywhere - std::vector buf; - if (allApplicableModes == 0) - allApplicableModes = &buf; - std::vector &mlist = *allApplicableModes; + std::vector &mlist = result.allApplicableModes; mlist.clear(); mlist.reserve(mmDummy_NumberOfModes); - std::set buf2; - if (nextRefTypeHint == 0) - nextRefTypeHint = &buf2; - std::set &hints = *nextRefTypeHint; + std::set &hints = result.nextRefTypeHint; hints.clear(); - std::map buf3; - if (reachableModes == 0) - reachableModes = &buf3; - std::map &mlist_reachable = *reachableModes; + std::map &mlist_reachable = result.reachableModes; mlist_reachable.clear(); + result.message = SuggestResult::srLinkBroken; + result.bestFitMode = mmDeactivated; + std::vector parts; std::vector shapes; @@ -290,15 +280,18 @@ eMapMode AttachEngine::listMapModes(eSuggestResult& msg, std::vector typeStr; try{ readLinks(this->references, parts, shapes, shapeStorage, typeStr); - } catch (Base::Exception) { - msg = srLinkBroken; - return mmDeactivated; + } catch (Base::Exception &err) { + result.references_Types = typeStr; + result.message = SuggestResult::srLinkBroken; + result.error = err; + return; } + result.references_Types = typeStr; + //search valid modes. - eMapMode bestMatchType = mmDeactivated; int bestMatchScore = -1; - msg = srNoModesFit; + result.message = SuggestResult::srNoModesFit; for (std::size_t iMode = 0; iMode < this->modeRefTypes.size(); ++iMode) { if (! this->modeEnabled[iMode]) continue; @@ -352,8 +345,8 @@ eMapMode AttachEngine::listMapModes(eSuggestResult& msg, if (score > -1){//still output a best match, even if it is not completely compatible if (score > bestMatchScore){ bestMatchScore = score; - bestMatchType = eMapMode(iMode); - msg = score > 0 ? srOK : srIncompatibleGeometry; + result.bestFitMode = eMapMode(iMode); + result.message = score > 0 ? SuggestResult::srOK : SuggestResult::srIncompatibleGeometry; } } if (score > 0){ @@ -365,16 +358,6 @@ eMapMode AttachEngine::listMapModes(eSuggestResult& msg, } } - return bestMatchType; - -} - -const std::set AttachEngine::getHint(bool forCurrentModeOnly) const -{ - eSuggestResult msg; - std::set ret; - this->listMapModes(msg, 0, &ret); - return ret; } void AttachEngine::EnableAllSupportedModes() diff --git a/src/Mod/Part/App/Attacher.h b/src/Mod/Part/App/Attacher.h index 7b83229bae4f..d2eb8b22c568 100644 --- a/src/Mod/Part/App/Attacher.h +++ b/src/Mod/Part/App/Attacher.h @@ -102,13 +102,6 @@ enum eMapMode { mmDummy_NumberOfModes//a value useful to check the validity of mode value };//see also eMapModeStrings[] definition in .cpp -enum eSuggestResult{ - srOK, - srLinkBroken, - srUnexpectedError, - srNoModesFit,//none of the avaliable mapping modes accepts the set of topological type - srIncompatibleGeometry,//there is a mode that could fit, but geometry is wrong (e.g. a line is required, but a curve was passed). -}; /** * @brief The eRefType enum lists the types of references. If adding one, see @@ -144,6 +137,66 @@ enum eRefType { }; +typedef std::vector refTypeString; //a sequence of ref types, according to Support contents for example +typedef std::vector refTypeStringList; //a set of type strings, defines which selection sets are supported by a certain mode + + +/** + * @brief The SuggestResult struct is a container for output information of AttachEngine mode suggesting routine. + */ +struct SuggestResult{ + /** + * @brief message contains overall verdict of suggestor on current reference set + */ + enum eSuggestResult{ + srOK, //references are valid for at least one mode + srLinkBroken, //failed to resolve out some of current references. Exception info is stored in SuggestResult::error. + srUnexpectedError, + srNoModesFit,//none of the avaliable mapping modes accepts the set of topological type + srIncompatibleGeometry,//there is a mode that could fit, but geometry is wrong (e.g. a line is required, but a curve was passed). + }; + eSuggestResult message; + + /** + * @brief allApplicableModes. Vector array that will recieve the list of + * all modes that are applicable to current set of references. It doesn't + * guarantee that all modes will work, it only checks that subelemnts are + * of right type. + */ + std::vector allApplicableModes; + + /** + * @brief bestFitMode is the mode that is the most specific to current + * references. Note that the mode may not be valid for current references; + * check if it's listed in allApplicableModes, or test if message == srOK. + */ + eMapMode bestFitMode; + + /** + * @brief nextRefTypeHint: a hint of what can be added to references to + * achieve other modes. + */ + std::set nextRefTypeHint; + + /** + * @brief reachableModes. List of modes that can be reached by selecing + * more references. Is a map, where key is the mode that can be reached, + * and value is a list of reference sequences that can be added to reach + * the mode (stuff already linked is omitted from these lists; only extra + * links needed are listed) + */ + std::map reachableModes; + + /** + * @brief references_Types: list of types of references, as queried when + * running suggesting routine. + */ + refTypeString references_Types; + + Base::Exception error; +}; + + /** * @brief The AttachEngine class is the placement calculation routine, modes, * hints and so on. It can be used separately, without deriving from @@ -152,10 +205,6 @@ enum eRefType { class PartExport AttachEngine : public Base::BaseClass { TYPESYSTEM_HEADER(); -public: //typedefs - typedef std::vector refTypeString; //a sequence of ref types, according to Support contents for example - typedef std::vector refTypeStringList; //a set of type strings, defines which selection sets are supported by a certain mode - public: //methods AttachEngine(); virtual void setUp(const App::PropertyLinkSubList &references, @@ -214,43 +263,15 @@ class PartExport AttachEngine : public Base::BaseClass Base::Placement* placeOfRef = 0) const; /** - * @brief listMapModes is the procedure that knows everything about + * @brief suggestMapModes is the procedure that knows everything about * mapping modes. It returns the most appropriate mapping mode, as well as * list of all modes that will accept the set of references. In case no modes apply, * extra information regarding reasons is returned in msg. * - * @param msg (output). Returns a message from the decision logic: OK if - * the mode was chosen, a reason if not. - * - * @param allApplicableModes (output). Pointer to a vector array that will recieve the - * list of all modes that are applicable to the support. It doesn't - * guarantee that all modes will work, it only checks that subelemnts are of - * right type. - * - * @param nextRefTypeHint (output). A hint of what can be added to references. - * - * @param reachableModes (output). List of modes that can be reached by - * selecing more references. Is a map, where key is the mode that can be - * reached and value is a list of reference sequences that can be added to - * reach the mode (stuff already linked is omitted from these lists; only - * extra links needed are listed) - */ - virtual eMapMode listMapModes(eSuggestResult &msg, - std::vector* allApplicableModes = 0, - std::set* nextRefTypeHint = 0, - std::map *reachableModes = 0) const; - - /** - * @brief getHint function returns a set of types that user can add to - * references to arrive to combinations valid for some modes. This function - * is a shoutcut to listMapModes. - * - * @return a set of selection types that can be appended to the support. - * - * Subclassing: This function works out of the box via a call to - * listMapModes, so there is no need to reimplement it. + * @param result (output). Returns results of suggestion, such as best fit + * mode, list of all modes that apply, hints, etc. */ - virtual const std::set getHint(bool forCurrentModeOnly) const; + virtual void suggestMapModes(SuggestResult &result) const; /** * @brief EnableAllModes enables all modes that have shape type lists filled. The function acts on modeEnabled array. diff --git a/src/Mod/Part/Gui/AttacherTexts.cpp b/src/Mod/Part/Gui/AttacherTexts.cpp index fb4fb7783914..742b74c484e7 100644 --- a/src/Mod/Part/Gui/AttacherTexts.cpp +++ b/src/Mod/Part/Gui/AttacherTexts.cpp @@ -313,9 +313,9 @@ QString getShapeTypeText(eRefType type) QStringList getRefListForMode(AttachEngine &attacher, eMapMode mmode) { - AttachEngine::refTypeStringList list = attacher.modeRefTypes[mmode]; + refTypeStringList list = attacher.modeRefTypes[mmode]; QStringList strlist; - for(AttachEngine::refTypeString &rts : list){ + for(refTypeString &rts : list){ QStringList buf; for(eRefType rt : rts){ buf.append(getShapeTypeText(rt)); diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 09f887114a0b..94a262084695 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -114,12 +114,12 @@ void UnifiedDatumCommand(Gui::Command &cmd, Base::Type type, std::string name) if (support.getSize() > 0) { Part::AttachableObject* pcDatum = static_cast(cmd.getDocument()->getObject(FeatName.c_str())); pcDatum->attacher().references.Paste(support); - eSuggestResult msg; - eMapMode suggMode = pcDatum->attacher().listMapModes(msg); - if (msg == srOK) { + SuggestResult sugr; + pcDatum->attacher().suggestMapModes(sugr); + if (sugr.message == Attacher::SuggestResult::srOK) { //fits some mode. Populate support property. cmd.doCommand(Gui::Command::Doc,"App.activeDocument().%s.Support = %s",FeatName.c_str(),support.getPyReprString().c_str()); - cmd.doCommand(Gui::Command::Doc,"App.activeDocument().%s.MapMode = '%s'",FeatName.c_str(),AttachEngine::eMapModeStrings[suggMode]); + cmd.doCommand(Gui::Command::Doc,"App.activeDocument().%s.MapMode = '%s'",FeatName.c_str(),AttachEngine::getModeName(sugr.bestFitMode).c_str()); } else { QMessageBox::information(Gui::getMainWindow(),QObject::tr("Invalid selection"), QObject::tr("There are no attachment modes that fit seleted objects. Select something else.")); } diff --git a/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp b/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp index e6b540ba67f8..89dc7131a83c 100644 --- a/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp @@ -315,13 +315,12 @@ void TaskDatumParameters::updateUI(std::string message, bool error) completed = false; // Get hints for further required references - eSuggestResult msg; - std::set hint; + SuggestResult sugr; - pcDatum->attacher().listMapModes(msg,0,&hint); + pcDatum->attacher().suggestMapModes(sugr); - if (msg != srOK) { - if(hint.size() > 0) + if (sugr.message != SuggestResult::srOK) { + if(sugr.nextRefTypeHint.size() > 0) message = "Need more references"; } else { completed = true; @@ -344,10 +343,10 @@ void TaskDatumParameters::updateUI(std::string message, bool error) ui->labelAngle->setEnabled(true); ui->spinAngle->setEnabled(true); - QString hintText = makeHintText(hint); + QString hintText = makeHintText(sugr.nextRefTypeHint); // Check if we have all required references - if (hint.size() == 0) { + if (sugr.nextRefTypeHint.size() == 0) { ui->buttonRef2->setEnabled(numrefs >= 2); ui->lineRef2->setEnabled(numrefs >= 2); ui->buttonRef3->setEnabled(numrefs >= 3); @@ -674,15 +673,15 @@ void TaskDatumParameters::updateListOfModes(eMapMode curMode) //obtain list of available modes: Part::Datum* pcDatum = static_cast(DatumView->getObject()); - eMapMode suggMode = mmDeactivated; - std::map reachableModes; + SuggestResult sugr; + sugr.bestFitMode = mmDeactivated; int lastValidModeItemIndex = mmDummy_NumberOfModes; if (pcDatum->Support.getSize() > 0){ - eSuggestResult msg; - suggMode = pcDatum->attacher().listMapModes(msg, &modesInList, 0, &reachableModes); + pcDatum->attacher().suggestMapModes(sugr); + modesInList = sugr.allApplicableModes; //add reachable modes to the list, too, but gray them out (using lastValidModeItemIndex, later) lastValidModeItemIndex = modesInList.size()-1; - for(std::pair &rm: reachableModes){ + for(std::pair &rm: sugr.reachableModes){ modesInList.push_back(rm.first); } } else { @@ -713,7 +712,7 @@ void TaskDatumParameters::updateListOfModes(eMapMode curMode) //potential mode - can be reached by selecting more stuff item->setFlags(item->flags() & ~(Qt::ItemFlag::ItemIsEnabled | Qt::ItemFlag::ItemIsSelectable)); - AttachEngine::refTypeStringList &extraRefs = reachableModes[mmode]; + refTypeStringList &extraRefs = sugr.reachableModes[mmode]; if (extraRefs.size() == 1){ QStringList buf; for(eRefType rt : extraRefs[0]){ @@ -726,7 +725,7 @@ void TaskDatumParameters::updateListOfModes(eMapMode curMode) } else { item->setText(tr("%1 (add more references)").arg(item->text())); } - } else if (mmode == suggMode){ + } else if (mmode == sugr.bestFitMode){ //suggested mode - make bold assert (item); QFont fnt = item->font(); @@ -750,10 +749,10 @@ Attacher::eMapMode TaskDatumParameters::getActiveMapMode() return modesInList[ui->listOfModes->row(sel[0])]; else { Part::Datum* pcDatum = static_cast(DatumView->getObject()); - eSuggestResult msg; - eMapMode suggMode = pcDatum->attacher().listMapModes(msg); - if (msg == srOK) - return suggMode; + SuggestResult sugr; + pcDatum->attacher().suggestMapModes(sugr); + if (sugr.message == SuggestResult::srOK) + return sugr.bestFitMode; else return mmDeactivated; }; diff --git a/src/Mod/Sketcher/Gui/Command.cpp b/src/Mod/Sketcher/Gui/Command.cpp index 0ebaaaf4fc2c..5b33edfc169e 100644 --- a/src/Mod/Sketcher/Gui/Command.cpp +++ b/src/Mod/Sketcher/Gui/Command.cpp @@ -79,14 +79,14 @@ namespace SketcherGui { }; - Attacher::eMapMode SuggestAutoMapMode(Attacher::eSuggestResult* pMsgId = 0, + Attacher::eMapMode SuggestAutoMapMode(Attacher::SuggestResult::eSuggestResult* pMsgId = 0, QString* message = 0, std::vector* allmodes = 0){ //convert pointers into valid references, to avoid checking for null pointers everywhere - Attacher::eSuggestResult buf; + Attacher::SuggestResult::eSuggestResult buf; if (pMsgId == 0) pMsgId = &buf; - Attacher::eSuggestResult &msg = *pMsgId; + Attacher::SuggestResult::eSuggestResult &msg = *pMsgId; QString buf2; if (message == 0) message = &buf2; @@ -95,23 +95,26 @@ namespace SketcherGui { App::PropertyLinkSubList tmpSupport; Gui::Selection().getAsPropertyLinkSubList(tmpSupport); + Attacher::SuggestResult sugr; AttachEngine3D eng; eng.setUp(tmpSupport); - Attacher::eMapMode ret; - ret = eng.listMapModes(msg, allmodes); + eng.suggestMapModes(sugr); + if (allmodes) + *allmodes = sugr.allApplicableModes; + msg = sugr.message; switch(msg){ - case Attacher::srOK: + case Attacher::SuggestResult::srOK: break; - case Attacher::srNoModesFit: + case Attacher::SuggestResult::srNoModesFit: msg_str = QObject::tr("There are no modes that accept the selected set of subelements"); break; - case Attacher::srLinkBroken: + case Attacher::SuggestResult::srLinkBroken: msg_str = QObject::tr("Broken link to support subelements"); break; - case Attacher::srUnexpectedError: + case Attacher::SuggestResult::srUnexpectedError: msg_str = QObject::tr("Unexpected error"); break; - case Attacher::srIncompatibleGeometry: + case Attacher::SuggestResult::srIncompatibleGeometry: if(tmpSupport.getSubValues()[0].substr(0,4) == std::string("Face")) msg_str = QObject::tr("Face is non-planar"); else @@ -122,7 +125,7 @@ namespace SketcherGui { assert(0/*no message for eSuggestResult enum item*/); } - return ret; + return sugr.bestFitMode; } } //namespace SketcherGui @@ -147,13 +150,13 @@ void CmdSketcherNewSketch::activated(int iMsg) Attacher::eMapMode mapmode = Attacher::mmDeactivated; bool bAttach = false; if (Gui::Selection().hasSelection()){ - Attacher::eSuggestResult msgid = Attacher::srOK; + Attacher::SuggestResult::eSuggestResult msgid = Attacher::SuggestResult::srOK; QString msg_str; std::vector validModes; mapmode = SuggestAutoMapMode(&msgid, &msg_str, &validModes); - if (msgid == Attacher::srOK) + if (msgid == Attacher::SuggestResult::srOK) bAttach = true; - if (msgid != Attacher::srOK && msgid != Attacher::srNoModesFit){ + if (msgid != Attacher::SuggestResult::srOK && msgid != Attacher::SuggestResult::srNoModesFit){ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Sketch mapping"), QObject::tr("Can't map the skecth to selected object. %1.").arg(msg_str)); @@ -166,7 +169,7 @@ void CmdSketcherNewSketch::activated(int iMsg) items.push_back(QObject::tr("Don't attach")); int iSugg = 0;//index of the auto-suggested mode in the list of valid modes for (size_t i = 0 ; i < validModes.size() ; ++i){ - items.push_back(QString::fromLatin1(AttachEngine::eMapModeStrings[validModes[i]])); + items.push_back(QString::fromLatin1(AttachEngine::getModeName(validModes[i]).c_str())); if (validModes[i] == mapmode) iSugg = items.size()-1; } @@ -447,7 +450,7 @@ void CmdSketcherMapSketch::activated(int iMsg) std::vector validModes; //check that selection is valid for at least some mapping mode. - Attacher::eSuggestResult msgid = Attacher::srOK; + Attacher::SuggestResult::eSuggestResult msgid = Attacher::SuggestResult::srOK; suggMapMode = SuggestAutoMapMode(&msgid, &msg_str, &validModes); App::Document* doc = App::GetApplication().getActiveDocument();