From a2e697d6efc2f36155ad2236ec52915b59cce738 Mon Sep 17 00:00:00 2001 From: mpv Date: Wed, 4 Dec 2019 09:35:18 +0300 Subject: [PATCH] =?utf8?q?Task=20#3059=20implementation:=20When=20?= =?utf8?q?=E2=80=9Cmove=20to=20the=20end=E2=80=9D=20of=20a=20group,=20prop?= =?utf8?q?ose=20to=20the=20user=20a=20new=20group=20update=20mode.?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- doc/gui/Introduction.rst | 2 +- .../popup_menu_object_browser_feature.png | Bin 17504 -> 15852 bytes src/CollectionPlugin/CMakeLists.txt | 3 + .../CollectionPlugin_Group.cpp | 106 ++++++++++++++++++ src/CollectionPlugin/CollectionPlugin_Group.h | 2 + .../Test/TestGroupMoveAndSplit1.py | 63 +++++++++++ .../Test/TestGroupMoveAndSplit2.py | 95 ++++++++++++++++ .../Test/TestGroupMoveAndSplit3.py | 76 +++++++++++++ src/Model/Model_Document.cpp | 11 +- src/Model/Model_Document.h | 3 +- src/ModelAPI/ModelAPI_Document.h | 3 +- src/PartSet/PartSet_Module.cpp | 2 +- src/SketcherPrs/SketcherPrs_SymbolPrs.cpp | 2 +- src/XGUI/XGUI_ContextMenuMgr.cpp | 16 ++- src/XGUI/XGUI_Workshop.cpp | 14 ++- src/XGUI/XGUI_Workshop.h | 5 +- src/XGUI/XGUI_msg_fr.ts | 4 + src/XGUI/XGUI_pictures.qrc | 2 + src/XGUI/pictures/move_to_end.png | Bin 0 -> 631 bytes src/XGUI/pictures/move_to_end_split.png | Bin 0 -> 595 bytes 20 files changed, 393 insertions(+), 16 deletions(-) create mode 100644 src/CollectionPlugin/Test/TestGroupMoveAndSplit1.py create mode 100644 src/CollectionPlugin/Test/TestGroupMoveAndSplit2.py create mode 100644 src/CollectionPlugin/Test/TestGroupMoveAndSplit3.py create mode 100644 src/XGUI/pictures/move_to_end.png create mode 100644 src/XGUI/pictures/move_to_end_split.png diff --git a/doc/gui/Introduction.rst b/doc/gui/Introduction.rst index d78aba3b9..c35c806f6 100644 --- a/doc/gui/Introduction.rst +++ b/doc/gui/Introduction.rst @@ -241,7 +241,7 @@ Each feature, result, construction, group, field, parameter can be renamed using .. centered:: Construction pop-up menu -The order of features can be changed using *Move to the end* pop-up menu command. It works only for Group features. The selected group will be moved to the end of features list. +The order of features can be changed using *Move to the end* and *Move to the end and split* pop-up menu commands. They work only for Group features. The selected group or several groups will be moved to the end of features list. The *Move to the end and split* also splits the resulting group in several groups: one group per one selection. Folders can be used to arrange long Tree View for features. diff --git a/doc/gui/images/popup_menu_object_browser_feature.png b/doc/gui/images/popup_menu_object_browser_feature.png index 30e40564de322526f602705c080f79103c65dbd7..ed32e2f4cfcf22a0645cfd4f37baf54fee8ec086 100755 GIT binary patch literal 15852 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 literal 17504 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 Sz^8z`kQP@ED-|*P_WuC8lGM`x diff --git a/src/CollectionPlugin/CMakeLists.txt b/src/CollectionPlugin/CMakeLists.txt index a02f2aa66..a8770cb7c 100644 --- a/src/CollectionPlugin/CMakeLists.txt +++ b/src/CollectionPlugin/CMakeLists.txt @@ -160,4 +160,7 @@ ADD_UNIT_TESTS( Test3031.py TestGroupWholeFeature1.py TestGroupWholeFeature2.py + TestGroupMoveAndSplit1.py + TestGroupMoveAndSplit2.py + TestGroupMoveAndSplit3.py ) diff --git a/src/CollectionPlugin/CollectionPlugin_Group.cpp b/src/CollectionPlugin/CollectionPlugin_Group.cpp index 82926ab21..c2110a64e 100644 --- a/src/CollectionPlugin/CollectionPlugin_Group.cpp +++ b/src/CollectionPlugin/CollectionPlugin_Group.cpp @@ -24,7 +24,9 @@ #include #include #include +#include #include +#include CollectionPlugin_Group::CollectionPlugin_Group() { @@ -44,3 +46,107 @@ void CollectionPlugin_Group::execute() setResult(aGroup); } } + +// returns name with suffix, not existing in the existing set +static std::string findName( + const std::string theOrigin, int& theSuffix, std::set& theExisting) +{ + std::string aRes; + do { + std::ostringstream aName; + aName< aFeatNames, aResNames; + std::list allFeat = aDoc->allFeatures(); + std::list::iterator allFeatIter = allFeat.begin(); + for(; allFeatIter != allFeat.end(); allFeatIter++) { + FeaturePtr aFeat = *allFeatIter; + if (aFeat->data().get() && aFeat->data()->isValid()) { + aFeatNames.insert(aFeat->name()); + if (aFeat->getKind() == ID() && aFeat->data().get() && aFeat->data()->isValid()) { + std::list::const_iterator aRess = aFeat->results().cbegin(); + for(; aRess != aFeat->results().cend(); aRess++) { + ResultPtr aRes = *aRess; + if (aRes->data().get() && aRes->data()->isValid()) { + aResNames.insert(aRes->data()->name()); + } + } + } + } + } + + AttributeSelectionListPtr aList = selectionList(LIST_ID()); + std::set aRemoved; + bool aStay = false; // to indicate that the good attribute found stays in the list + int anIndex = 1; // index of the name assigned to group-feature and result + // added in the order: 3 2 1 orig=0, so, keep the results to give names later + std::list aResults; + for(int aNext = aList->size() - 1; aNext >= 0; aNext--) { + AttributeSelectionPtr anOldAttr = aList->value(aNext); + if (anOldAttr->isInvalid() || !anOldAttr->context().get()) {// remove invalids + aRemoved.insert(aNext); + continue; + } + if (!aStay) { + aStay = true; + continue; + } + aRemoved.insert(aNext); + FeaturePtr aNew = aDoc->addFeature(ID(), false); + AttributeSelectionListPtr aNewList = aNew->selectionList(LIST_ID()); + aNewList->setSelectionType(aList->selectionType()); + aNewList->append(anOldAttr->contextObject(), anOldAttr->value()); + aResults.push_front(aNew); // to keep the order + } + aResults.push_back(data()->owner()); + // remove all selections except the first + aList->remove(aRemoved); + // set names + if (aResults.size() > 1) { // rename if there are new groups appeared only + std::list::iterator aResIter = aResults.begin(); + for(int aSuffix = 1; aResIter != aResults.end(); aResIter++) { + FeaturePtr aFeat = std::dynamic_pointer_cast(*aResIter); + aFeat->data()->setName(findName(name(), aSuffix, aFeatNames)); + if (!aFeat->results().empty() && !results().empty()) { + int aResSuf = aSuffix - 1; + std::string aResName = findName(firstResult()->data()->name(), aResSuf, aResNames); + aFeat->firstResult()->data()->setName(aResName); + // set the same color of result as in origin + if (firstResult()->data()->attribute(ModelAPI_Result::COLOR_ID()).get()) { + AttributeIntArrayPtr aSourceColor = + firstResult()->data()->intArray(ModelAPI_Result::COLOR_ID()); + if (aSourceColor.get() && aSourceColor->size()) { + AttributeIntArrayPtr aDestColor = + aFeat->firstResult()->data()->intArray(ModelAPI_Result::COLOR_ID()); + aDestColor->setSize(aSourceColor->size()); + for(int a = 0; a < aSourceColor->size(); a++) + aDestColor->setValue(a, aSourceColor->value(a)); + } + } + } + } + // remove also filters if split performed + FiltersFeaturePtr aFilters = aList->filters(); + if (aFilters.get()) { + std::list aFiltersList = aFilters->filters(); + std::list::iterator aFilterName = aFiltersList.begin(); + for(; aFilterName != aFiltersList.end(); aFilterName++) { + aFilters->removeFilter(*aFilterName); + } + } + } + } + return true; +} diff --git a/src/CollectionPlugin/CollectionPlugin_Group.h b/src/CollectionPlugin/CollectionPlugin_Group.h index 0d61046e3..3c1dd0d16 100644 --- a/src/CollectionPlugin/CollectionPlugin_Group.h +++ b/src/CollectionPlugin/CollectionPlugin_Group.h @@ -66,6 +66,8 @@ class CollectionPlugin_Group : public ModelAPI_Feature /// Use plugin manager for features creation CollectionPlugin_Group(); + /// Used for the split action of the group (Move to the end and split) + COLLECTIONPLUGIN_EXPORT virtual bool customAction(const std::string& theActionId); }; #endif diff --git a/src/CollectionPlugin/Test/TestGroupMoveAndSplit1.py b/src/CollectionPlugin/Test/TestGroupMoveAndSplit1.py new file mode 100644 index 000000000..d468c4d34 --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMoveAndSplit1.py @@ -0,0 +1,63 @@ +# Copyright (C) 2014-2019 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# Check the specification case of move to the end and split (#3059) + +from salome.shaper import model +from ModelAPI import * +from GeomAPI import * + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 12, 0) +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchCircle_1 = Sketch_1.addCircle(33.32502963835739, 19.24021483244179, 5) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 5) +SketchLine_1 = Sketch_1.addLine(0, 0, 33.32502963835739, 19.24021483244179) +SketchLine_1.setAuxiliary(True) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_1.startPoint(), SketchPoint_1.result()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchCircle_1.center(), SketchLine_1.endPoint()) +SketchProjection_2 = Sketch_1.addProjection(model.selection("EDGE", "PartSet/OX"), False) +SketchLine_2 = SketchProjection_2.createdFeature() +SketchConstraintAngle_1 = Sketch_1.setAngle(SketchLine_2.result(), SketchLine_1.result(), 30) +Extrusion_1.setNestedSketch(Sketch_1) +Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("FACE", "Extrusion_1_1/To_Face")]) +AngularCopy_1 = model.addMultiRotation(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1")], model.selection("EDGE", "PartSet/OZ"), 12) +model.do() +Part_1_doc.moveFeature(Group_1.feature(), AngularCopy_1.feature(), True) +model.end() + +# must be created 12 groups of faces, 12 results +assert(Part_1_doc.size("Groups") == 12) + +for i in range(12): + resShape = modelAPI_Result(Part_1_doc.object("Groups", i)).shape() + assert(not resShape.isNull()) + # the group result is a compund, check that this is a compound of one face + aShapeExplorer = GeomAPI_ShapeExplorer(resShape, GeomAPI_Shape.FACE) + assert(aShapeExplorer.more()) + assert(aShapeExplorer.current().isFace()) + aShapeExplorer.next() + assert(not aShapeExplorer.more()) + +assert(model.checkPythonDump()) diff --git a/src/CollectionPlugin/Test/TestGroupMoveAndSplit2.py b/src/CollectionPlugin/Test/TestGroupMoveAndSplit2.py new file mode 100644 index 000000000..c39ae457b --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMoveAndSplit2.py @@ -0,0 +1,95 @@ +# Copyright (C) 2014-2019 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# Check the movement to the end and split: move to intermediate position, no duplicates appeared + +from SketchAPI import * + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchProjection_1 = Sketch_1.addProjection(model.selection("VERTEX", "PartSet/Origin"), False) +SketchPoint_1 = SketchProjection_1.createdFeature() +SketchCircle_1 = Sketch_1.addCircle(0, 0, 10) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchPoint_1.result(), SketchCircle_1.center()) +SketchConstraintRadius_1 = Sketch_1.setRadius(SketchCircle_1.results()[1], 10) +model.do() +Extrusion_1 = model.addExtrusion(Part_1_doc, [model.selection("FACE", "Sketch_1/Face-SketchCircle_1_2f")], model.selection(), 10, 0) +Group_1 = model.addGroup(Part_1_doc, "Edges", [model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]")]) +ExtrusionCut_1 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 5, [model.selection("SOLID", "Extrusion_1_1")]) +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face")) +SketchProjection_2 = Sketch_2.addProjection(model.selection("EDGE", "[Extrusion_1_1/Generated_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/To_Face]"), False) +SketchCircle_2 = SketchProjection_2.createdFeature() +SketchCircle_3 = Sketch_2.addCircle(0, 10, 3) +SketchConstraintCoincidence_2 = Sketch_2.setCoincident(SketchCircle_2.results()[1], SketchCircle_3.center()) +SketchCircle_4 = Sketch_2.addCircle(0, -10, 3) +SketchConstraintCoincidence_3 = Sketch_2.setCoincident(SketchCircle_2.results()[1], SketchCircle_4.center()) +SketchProjection_3 = Sketch_2.addProjection(model.selection("EDGE", "PartSet/OY"), True) +SketchLine_1 = SketchProjection_3.createdFeature() +SketchConstraintCoincidence_4 = Sketch_2.setCoincident(SketchCircle_3.center(), SketchLine_1.result()) +SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchCircle_4.center(), SketchLine_1.result()) +SketchConstraintRadius_2 = Sketch_2.setRadius(SketchCircle_3.results()[1], 3) +SketchConstraintEqual_1 = Sketch_2.setEqual(SketchCircle_3.results()[1], SketchCircle_4.results()[1]) +ExtrusionCut_1.setNestedSketch(Sketch_2) + +ExtrusionCut_2 = model.addExtrusionCut(Part_1_doc, [], model.selection(), 0, 3, [model.selection("SOLID", "ExtrusionCut_1_1")]) +Sketch_3 = model.addSketch(Part_1_doc, model.selection("FACE", "ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face")) +SketchLine_2 = Sketch_3.addLine(10, 2, -10, 2) +SketchLine_3 = Sketch_3.addLine(-10, 2, -10, -2) +SketchLine_4 = Sketch_3.addLine(-10, -2, 10, -2) +SketchLine_5 = Sketch_3.addLine(10, -2, 10, 2) +SketchConstraintCoincidence_6 = Sketch_3.setCoincident(SketchLine_5.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_7 = Sketch_3.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_8 = Sketch_3.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintCoincidence_9 = Sketch_3.setCoincident(SketchLine_4.endPoint(), SketchLine_5.startPoint()) +SketchConstraintHorizontal_1 = Sketch_3.setHorizontal(SketchLine_2.result()) +SketchConstraintVertical_1 = Sketch_3.setVertical(SketchLine_3.result()) +SketchConstraintHorizontal_2 = Sketch_3.setHorizontal(SketchLine_4.result()) +SketchConstraintVertical_2 = Sketch_3.setVertical(SketchLine_5.result()) +SketchProjection_4 = Sketch_3.addProjection(model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Sketch_1/SketchCircle_1_2][Extrusion_1_1/From_Face])2(ExtrusionCut_1_1/Generated_Edge&ExtrusionCut_1_1/From_Face_1)2([ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchCircle_4_2])2"), False) +SketchArc_1 = SketchProjection_4.createdFeature() +SketchConstraintTangent_1 = Sketch_3.setTangent(SketchLine_5.result(), SketchArc_1.results()[1]) +SketchProjection_5 = Sketch_3.addProjection(model.selection("EDGE", "([ExtrusionCut_1_1/Modified_Face&Extrusion_1_1/To_Face][ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchCircle_4_2])(ExtrusionCut_1_1/Generated_Edge&ExtrusionCut_1_1/From_Face_3)2(ExtrusionCut_1_1/Generated_Edge&ExtrusionCut_1_1/From_Face_2)2([ExtrusionCut_1_1/Generated_Face&Sketch_2/SketchCircle_4_2][ExtrusionCut_1_1/Modified_Face&ExtrusionCut_1_1/From_Face_3])2"), False) +SketchArc_2 = SketchProjection_5.createdFeature() +SketchConstraintTangent_2 = Sketch_3.setTangent(SketchArc_2.results()[1], SketchLine_3.result()) +SketchConstraintDistanceVertical_1 = Sketch_3.setVerticalDistance(SketchAPI_Arc(SketchArc_1).center(), SketchLine_2.startPoint(), 2) +SketchConstraintDistanceVertical_2 = Sketch_3.setVerticalDistance(SketchAPI_Arc(SketchArc_1).center(), SketchLine_4.endPoint(), 2) +ExtrusionCut_2.setNestedSketch(Sketch_3) +model.do() +# move only after the first extrusion-cut +Part_1_doc.setCurrentFeature(ExtrusionCut_1.feature(), True) +model.do() +Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_1.feature(), True) +model.end() +assert(Part_1_doc.size("Groups") == 3) # 3 edges in groups results + +# check that simple move to the end provides 4 edges (no duplicates) +model.undo() +model.undo() + +model.begin() +Part_1_doc.moveFeature(Group_1.feature(), ExtrusionCut_2.feature(), True) +model.end() +assert(Part_1_doc.size("Groups") == 4) # 4 edges in groups results + +assert(model.checkPythonDump()) diff --git a/src/CollectionPlugin/Test/TestGroupMoveAndSplit3.py b/src/CollectionPlugin/Test/TestGroupMoveAndSplit3.py new file mode 100644 index 000000000..047237625 --- /dev/null +++ b/src/CollectionPlugin/Test/TestGroupMoveAndSplit3.py @@ -0,0 +1,76 @@ +# Copyright (C) 2014-2019 CEA/DEN, EDF R&D +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +# Check the movement to the end and split: whole results, check names of splitted results and groups + +from salome.shaper import model + +model.begin() +partSet = model.moduleDocument() +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() +Extrusion_1 = model.addExtrusion(Part_1_doc, [], model.selection(), 10, 0) +Sketch_1 = model.addSketch(Part_1_doc, model.defaultPlane("XOY")) +SketchLine_1 = Sketch_1.addLine(-8.333743842364534, 20.52339901477833, -20.15024630541872, 20.52339901477833) +SketchLine_2 = Sketch_1.addLine(-20.15024630541872, 20.52339901477833, -20.15024630541872, 3.980295566502462) +SketchLine_3 = Sketch_1.addLine(-20.15024630541872, 3.980295566502462, -8.333743842364534, 3.980295566502462) +SketchLine_4 = Sketch_1.addLine(-8.333743842364534, 3.980295566502462, -8.333743842364534, 20.52339901477833) +SketchConstraintCoincidence_1 = Sketch_1.setCoincident(SketchLine_4.endPoint(), SketchLine_1.startPoint()) +SketchConstraintCoincidence_2 = Sketch_1.setCoincident(SketchLine_1.endPoint(), SketchLine_2.startPoint()) +SketchConstraintCoincidence_3 = Sketch_1.setCoincident(SketchLine_2.endPoint(), SketchLine_3.startPoint()) +SketchConstraintCoincidence_4 = Sketch_1.setCoincident(SketchLine_3.endPoint(), SketchLine_4.startPoint()) +SketchConstraintHorizontal_1 = Sketch_1.setHorizontal(SketchLine_1.result()) +SketchConstraintVertical_1 = Sketch_1.setVertical(SketchLine_2.result()) +SketchConstraintHorizontal_2 = Sketch_1.setHorizontal(SketchLine_3.result()) +SketchConstraintVertical_2 = Sketch_1.setVertical(SketchLine_4.result()) +SketchCircle_1 = Sketch_1.addCircle(5.721674876847291, 12.81157635467982, 6.421166795138789) +Extrusion_1.setNestedSketch(Sketch_1) +Group_1 = model.addGroup(Part_1_doc, "Faces", [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_1_2")]) +Group_1.setName("GroupResult") +Group_1.result().setName("GroupResult") +Sketch_2 = model.addSketch(Part_1_doc, model.selection("FACE", "Extrusion_1_1/To_Face")) +SketchLine_5 = Sketch_2.addLine(3.924377723198604, 15.23693857548147, -14.36967929032953, 15.23693857548147) +SketchLine_6 = Sketch_2.addLine(-14.36967929032953, 15.23693857548147, -14.36967929032953, 11.61585476914922) +SketchLine_7 = Sketch_2.addLine(-14.36967929032953, 11.61585476914922, 3.924377723198604, 11.61585476914922) +SketchLine_8 = Sketch_2.addLine(3.924377723198604, 11.61585476914922, 3.924377723198604, 15.23693857548147) +SketchConstraintCoincidence_5 = Sketch_2.setCoincident(SketchLine_8.endPoint(), SketchLine_5.startPoint()) +SketchConstraintCoincidence_6 = Sketch_2.setCoincident(SketchLine_5.endPoint(), SketchLine_6.startPoint()) +SketchConstraintCoincidence_7 = Sketch_2.setCoincident(SketchLine_6.endPoint(), SketchLine_7.startPoint()) +SketchConstraintCoincidence_8 = Sketch_2.setCoincident(SketchLine_7.endPoint(), SketchLine_8.startPoint()) +SketchConstraintHorizontal_3 = Sketch_2.setHorizontal(SketchLine_5.result()) +SketchConstraintVertical_3 = Sketch_2.setVertical(SketchLine_6.result()) +SketchConstraintHorizontal_4 = Sketch_2.setHorizontal(SketchLine_7.result()) +SketchConstraintVertical_4 = Sketch_2.setVertical(SketchLine_8.result()) +model.do() +Extrusion_2 = model.addExtrusion(Part_1_doc, [model.selection("WIRE", "Sketch_2/Face-SketchLine_5r-SketchLine_6f-SketchLine_7f-SketchLine_8f_wire")], model.selection(), 2, 5) +Fuse_1 = model.addFuse(Part_1_doc, [model.selection("SOLID", "Extrusion_1_1"), model.selection("SOLID", "Extrusion_2_1")], keepSubResults = True) +model.do() +Part_1_doc.moveFeature(Group_1.feature(), Fuse_1.feature(), True) +model.end() + +assert(Part_1_doc.size("Groups") == 2) # 2 results because initially 2 results were selected + +# check names of results +from ModelAPI import * +res1 = modelAPI_Result(Part_1_doc.object("Groups", 0)) +assert(res1.data().name() == "GroupResult_1") +res2 = modelAPI_Result(Part_1_doc.object("Groups", 1)) +assert(res2.data().name() == "GroupResult_2") + +assert(model.checkPythonDump()) diff --git a/src/Model/Model_Document.cpp b/src/Model/Model_Document.cpp index b1efb51d0..79162a779 100644 --- a/src/Model/Model_Document.cpp +++ b/src/Model/Model_Document.cpp @@ -1239,7 +1239,7 @@ static bool isSub(const CompositeFeaturePtr theMain, const FeaturePtr theSub) { return isSub(theMain, aParent); } -void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) +void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis, const bool theSplit) { bool aCurrentUp = theMoved == currentFeature(false); if (aCurrentUp) { @@ -1264,12 +1264,21 @@ void Model_Document::moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis) } myObjs->moveFeature(theMoved, anAfterThisSub); + + if (theSplit) { // split the group into sub-features + theMoved->customAction("split"); + } + if (aCurrentUp) { // make the moved feature enabled or disabled due to the real status setCurrentFeature(currentFeature(false), false); } else if (theAfterThis == currentFeature(false) || anAfterThisSub == currentFeature(false)) { // must be after move to make enabled all features which are before theMoved setCurrentFeature(theMoved, true); } + + if (theSplit) { // split the group into sub-features + theMoved->customAction("split"); + } } void Model_Document::updateHistory(const std::shared_ptr theObject) diff --git a/src/Model/Model_Document.h b/src/Model/Model_Document.h index 1615ffce4..277c822ba 100644 --- a/src/Model/Model_Document.h +++ b/src/Model/Model_Document.h @@ -127,7 +127,8 @@ class Model_Document : public ModelAPI_Document MODEL_EXPORT virtual void removeFeature(FeaturePtr theFeature); //! Moves the feature to make it after the given one in the history. - MODEL_EXPORT virtual void moveFeature(FeaturePtr theMoved, FeaturePtr theAfterThis); + MODEL_EXPORT virtual void moveFeature( + FeaturePtr theMoved, FeaturePtr theAfterThis, const bool theSplit = false); //! Returns the first found object in the group by the object name //! \param theGroupID group that contains an object diff --git a/src/ModelAPI/ModelAPI_Document.h b/src/ModelAPI/ModelAPI_Document.h index 5f51a3376..602c4e803 100644 --- a/src/ModelAPI/ModelAPI_Document.h +++ b/src/ModelAPI/ModelAPI_Document.h @@ -81,7 +81,8 @@ public: //! Moves the feature to make it after the given one in the history. virtual void moveFeature(std::shared_ptr theMoved, - std::shared_ptr theAfterThis) = 0; + std::shared_ptr theAfterThis, + const bool theSplit = false) = 0; ///! Returns the id of the document virtual const int id() const = 0; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index 342134c7a..f3e9a2856 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -553,7 +553,7 @@ bool PartSet_Module::canRedo() const bool PartSet_Module::canApplyAction(const ObjectPtr& theObject, const QString& theActionId) const { bool aValid = true; - if (theActionId == "MOVE_CMD") { + if (theActionId == "MOVE_CMD" || theActionId == "MOVE_SPLIT_CMD") { FeaturePtr aFeature = ModelAPI_Feature::feature(theObject); if (aFeature) { ResultPtr aResult = ModuleBase_Tools::firstResult(aFeature); diff --git a/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp b/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp index 5f79c5fba..e10434cf9 100644 --- a/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp +++ b/src/SketcherPrs/SketcherPrs_SymbolPrs.cpp @@ -185,7 +185,7 @@ Handle(Image_AlienPixMap) SketcherPrs_SymbolPrs::icon() aSizedMap->InitTrash(aPixMap->Format(), aWidth, aHeigh); for (Standard_Size i = 0; i < aWidth; i++) { for (Standard_Size j = 0; j < aHeigh; j++) { - aSizedMap->SetPixelColor(i, j, aPixMap->PixelColor(i / aRatio, j / aRatio)); + aSizedMap->SetPixelColor(int(i), int(j), aPixMap->PixelColor(i / aRatio, j / aRatio)); } } aPixMap = aSizedMap; diff --git a/src/XGUI/XGUI_ContextMenuMgr.cpp b/src/XGUI/XGUI_ContextMenuMgr.cpp index 60db4013c..a174bea87 100644 --- a/src/XGUI/XGUI_ContextMenuMgr.cpp +++ b/src/XGUI/XGUI_ContextMenuMgr.cpp @@ -96,10 +96,14 @@ void XGUI_ContextMenuMgr::createActions() aDesktop, this, SLOT(onRename())); addAction("RENAME_CMD", aAction); - aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move.png"), + aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_to_end.png"), XGUI_Workshop::MOVE_TO_END_COMMAND, this); addAction("MOVE_CMD", aAction); + aAction = ModuleBase_Tools::createAction(QIcon(":pictures/move_to_end_split.png"), + XGUI_Workshop::MOVE_TO_END_SPLIT_COMMAND, this); + addAction("MOVE_SPLIT_CMD", aAction); + aAction = ModuleBase_Tools::createAction(QIcon(":pictures/clean_history.png"), tr("Clean history"), aDesktop); addAction("CLEAN_HISTORY_CMD", aAction); @@ -326,8 +330,10 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu() if (!(hasParameter || hasFeature)) action("SHOW_ONLY_CMD")->setEnabled(true); } - else if (hasFeature && myWorkshop->canMoveFeature()) + else if (hasFeature && myWorkshop->canMoveFeature()) { action("MOVE_CMD")->setEnabled(true); + action("MOVE_SPLIT_CMD")->setEnabled(true); + } if( aMgr->activeDocument() == aObject->document() ) { @@ -347,8 +353,10 @@ void XGUI_ContextMenuMgr::updateObjectBrowserMenu() action("SHADING_CMD")->setEnabled(true); action("WIREFRAME_CMD")->setEnabled(true); } - if (hasFeature && myWorkshop->canMoveFeature()) + if (hasFeature && myWorkshop->canMoveFeature()) { action("MOVE_CMD")->setEnabled(true); + action("MOVE_SPLIT_CMD")->setEnabled(true); + } } // end multi-selection // Check folder management commands state if only features are selected @@ -662,6 +670,7 @@ void XGUI_ContextMenuMgr::buildObjBrowserMenu() aList.append(action("RENAME_CMD")); aList.append(action("SHOW_RESULTS_CMD")); aList.append(action("MOVE_CMD")); + aList.append(action("MOVE_SPLIT_CMD")); aList.append(mySeparator1); aList.append(action("INSERT_FOLDER_CMD")); aList.append(action("ADD_TO_FOLDER_BEFORE_CMD")); @@ -770,6 +779,7 @@ void XGUI_ContextMenuMgr::addObjBrowserMenu(QMenu* theMenu) const aActions.append(action("ADD_OUT_FOLDER_AFTER_CMD")); aActions.append(mySeparator3); aActions.append(action("MOVE_CMD")); + aActions.append(action("MOVE_SPLIT_CMD")); aActions.append(action("COLOR_CMD")); aActions.append(action("DEFLECTION_CMD")); aActions.append(action("TRANSPARENCY_CMD")); diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index aa66b4896..fcee5e38a 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -170,6 +170,7 @@ static Handle(VInspector_CallBack) MyVCallBack; //#define DEBUG_WITH_MESSAGE_REPORT QString XGUI_Workshop::MOVE_TO_END_COMMAND = QObject::tr("Move to the end"); +QString XGUI_Workshop::MOVE_TO_END_SPLIT_COMMAND = QObject::tr("Move to the end and split"); //#define DEBUG_DELETE //#define DEBUG_FEATURE_NAME @@ -1215,7 +1216,8 @@ void XGUI_Workshop::processUndoRedo(const ModuleBase_ActionType theActionType, i else aMgr->redo(); - if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND) + if (QString((*aIt).c_str()) == MOVE_TO_END_COMMAND || + QString((*aIt).c_str()) == MOVE_TO_END_SPLIT_COMMAND) myObjectBrowser->rebuildDataTree(); } operationMgr()->updateApplyOfOperations(); @@ -1636,8 +1638,8 @@ void XGUI_Workshop::onContextMenuCommand(const QString& theId, bool isChecked) deleteObjects(); else if (theId == "CLEAN_HISTORY_CMD") cleanHistory(); - else if (theId == "MOVE_CMD") - moveObjects(); + else if (theId == "MOVE_CMD" || theId == "MOVE_SPLIT_CMD") + moveObjects(theId == "MOVE_SPLIT_CMD"); else if (theId == "COLOR_CMD") changeColor(aObjects); else if (theId == "DEFLECTION_CMD") @@ -2095,7 +2097,7 @@ bool compareFeature(const FeaturePtr& theF1, const FeaturePtr& theF2) { DocumentPtr aDoc = theF1->document(); return aDoc->index(theF1) < aDoc->index(theF2); } -void XGUI_Workshop::moveObjects() +void XGUI_Workshop::moveObjects(const bool theSplit) { if (!abortAllOperations()) return; @@ -2112,7 +2114,7 @@ void XGUI_Workshop::moveObjects() if (!XGUI_Tools::canRemoveOrRename(desktop(), aFeatures)) return; - QString anActionId = "MOVE_CMD"; + QString anActionId = theSplit ? "MOVE_CMD" : "MOVE_SPLIT_CMD"; QString aDescription = contextMenuMgr()->action(anActionId)->text(); aMgr->startOperation(aDescription.toStdString()); @@ -2128,7 +2130,7 @@ void XGUI_Workshop::moveObjects() if (!aFeature.get() || !myModule->canApplyAction(aFeature, anActionId)) continue; - anActiveDocument->moveFeature(aFeature, aCurrentFeature); + anActiveDocument->moveFeature(aFeature, aCurrentFeature, theSplit); aCurrentFeature = anActiveDocument->currentFeature(true); } aMgr->finishOperation(); diff --git a/src/XGUI/XGUI_Workshop.h b/src/XGUI/XGUI_Workshop.h index 4b06dac3f..37ae6a8a2 100644 --- a/src/XGUI/XGUI_Workshop.h +++ b/src/XGUI/XGUI_Workshop.h @@ -186,7 +186,7 @@ Q_OBJECT bool canMoveFeature(); /// Move selected features to be after the current feature - void moveObjects(); + void moveObjects(const bool theSplit); /// Returns true if the object can be shaded. If the object is a compsolid result, the method /// checks subobjects of the result @@ -316,6 +316,9 @@ Q_OBJECT /// A constant string used for "Move to end" command definition /// It is used for specific processing of Undo/Redo for this command. static QString MOVE_TO_END_COMMAND; + /// A constant string used for "Move to end and split" command definition + /// It is used for specific processing of Undo/Redo for this command. + static QString MOVE_TO_END_SPLIT_COMMAND; /// Closes all in the current session and load the directory /// \param theDirectory a path to directory diff --git a/src/XGUI/XGUI_msg_fr.ts b/src/XGUI/XGUI_msg_fr.ts index 9b519926b..ebe3b8867 100644 --- a/src/XGUI/XGUI_msg_fr.ts +++ b/src/XGUI/XGUI_msg_fr.ts @@ -15,6 +15,10 @@ Move to the end Aller à la fin + + Move to the end and split + Aller à la fin et diviser + SHAPER files (*.shaper *.cadbld) Fichiers SHAPER (*.shaper *.cadbld) diff --git a/src/XGUI/XGUI_pictures.qrc b/src/XGUI/XGUI_pictures.qrc index acb22325c..9b958d9e7 100644 --- a/src/XGUI/XGUI_pictures.qrc +++ b/src/XGUI/XGUI_pictures.qrc @@ -90,5 +90,7 @@ pictures/color.png pictures/normal-view-inversed.png pictures/normal-view.png + pictures/move_to_end.png + pictures/move_to_end_split.png diff --git a/src/XGUI/pictures/move_to_end.png b/src/XGUI/pictures/move_to_end.png new file mode 100644 index 0000000000000000000000000000000000000000..a80ce7fd55399b41116e41f2b7ba9ed922099969 GIT binary patch literal 631 zcmV--0*L*IP)x~B2f{cWM(MLIhe6@wP2O=eY;3& z5T6D;cjw`G&Nm_!vF!k|Y4I{J~`1k+#~6*7OA08Z3V>7Y>QHdK}%~ORDuCrvN1IXjPgs zmOof+8$s!e&|Dpw(0jL(VV-Trt2MpzDJG>7>Vb)oGZ5vr4Ycvy6z1#aF&-x72!Ac` z^72WVVxwG_CguRJPusZxgl3iEMWAtNj`>$Z^mPX4^X{g}0G-;%TY}%Z*cgvvV`O%? zvE<@PuHACFd_u{swh@Fbd|av>Eup^U^5m+k*d{%)<^o#ZLMYoC2>9Wt$#yS7&l*); zRe>v$C2b(oX~5RJ1}EsQ^`hCwnbrf;%_NzY2Ie`13L&)Z8wJMa`uxbq{zJS-q`7qb zDCZ|Xusl4$?M(&);OJ=K-kS(Z;SjTtZf4R^RyzFL-PGCW!MfH(JRe8vadbLL@y->d zPBe34U1M(4z~#oVy@EaOlYE(7z$|l8`E-E${e#^6m(~A@;@wG$-^a01@+Y1Xuz06~ RvLpZi002ovPDHLkV1hp4A^rdW literal 0 HcmV?d00001 diff --git a/src/XGUI/pictures/move_to_end_split.png b/src/XGUI/pictures/move_to_end_split.png new file mode 100644 index 0000000000000000000000000000000000000000..bcc017d1eb6d3a6fa744fd58d29b9c8aab708657 GIT binary patch literal 595 zcmV-Z0<8UsP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGh)&Kwv)&Y=jd7J1;MAa*k@H7+qQF!XYv0005PNklK+1DvG-VRs(SdE-dB} zSSsNeDhgE22+@TEfRazdUHsccUH!{(VKHa_DPpdHSN!c6PG^NMEY^`{(1dCS84&PL z%E4Cz%Ebymt^}(4Fu9EJ^8Ygo|JQagJod6-hy+UlCF;dp0^R}X|G2ULb8+W@>122ec8Q3qpOm<3K)!@)U^y-_F+tBe(ao3D!&@Ci20f^mxIum-gAXvkcHP;?@MX&chLl=>002ovPDHLkV1mF-?z#W~ literal 0 HcmV?d00001 -- 2.39.2