From fd2e35b7eb74c2dfde77dafaafbde24dbe7ebe90 Mon Sep 17 00:00:00 2001 From: Paddle Date: Sun, 26 Nov 2023 07:50:02 +0100 Subject: [PATCH 1/4] Sketcher: Add copy/cut/paste sketcher commands --- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 260 ++++++++++++++++++ src/Mod/Sketcher/Gui/ShortcutListener.cpp | 8 +- src/Mod/Sketcher/Gui/ShortcutListener.h | 9 - src/Mod/Sketcher/Gui/ViewProviderSketch.h | 5 +- src/Mod/Sketcher/Gui/Workbench.cpp | 6 +- 5 files changed, 267 insertions(+), 21 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index c08e135aa2..2fc791558f 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -33,6 +34,8 @@ #include #include +#include +#include #include #include #include @@ -140,6 +143,260 @@ Sketcher::SketchObject* getSketchObject() // ================================================================================ +// Copy + +bool copySelectionToClipboard() { + + std::vector selection = Gui::Command::getSelection().getSelectionEx(); + Sketcher::SketchObject* obj = static_cast(selection[0].getObject()); + // only one sketch with its subelements are allowed to be selected + if (selection.size() != 1) { return false; } + std::vector SubNames = selection[0].getSubNames(); + if (SubNames.empty()) { return false; } + + //First we need listOfGeoId and sort them. + std::vector listOfGeoId; + for (std::vector::const_iterator it = SubNames.begin(); it != SubNames.end(); ++it) { + int GeoId = -1; + // only handle non-external edges + if (it->size() > 4 && it->substr(0, 4) == "Edge") { + GeoId = std::atoi(it->substr(4, 4000).c_str()) - 1; + if (GeoId >= 0) { + listOfGeoId.push_back(GeoId); + } + } + else if (it->size() > 6 && it->substr(0, 6) == "Vertex") { + // only if it is a GeomPoint + int VtId = std::atoi(it->substr(6, 4000).c_str()) - 1; + Sketcher::PointPos PosId; + obj->getGeoVertexIndex(VtId, GeoId, PosId); + if (obj->getGeometry(GeoId)->getTypeId() == Part::GeomPoint::getClassTypeId()) { + if (GeoId >= 0) { + listOfGeoId.push_back(GeoId); + } + } + } + } + if (listOfGeoId.empty()) { return false; } + sort(listOfGeoId.begin(), listOfGeoId.end()); + + Base::StringWriter writer; + + //Export selected geometries as a formated string. + std::vector< Part::Geometry* > newVals; + for (auto geoId : listOfGeoId) { + Part::Geometry* geoNew = obj->getGeometry(geoId)->copy(); + newVals.push_back(geoNew); + } + Part::PropertyGeometryList geoToCopy; + geoToCopy.setValues(std::move(newVals)); + geoToCopy.Save(writer); + + //add constraints to the stream string. + std::vector< Sketcher::Constraint* > newConstrVals; + for (auto constr : obj->Constraints.getValues()) { + + auto isSelectedGeoOrAxis = [](const std::vector& vec, int value) { + return (std::find(vec.begin(), vec.end(), value) != vec.end()) + || value == GeoEnum::GeoUndef || value == GeoEnum::RtPnt + || value == GeoEnum::VAxis || value == GeoEnum::HAxis; + }; + + if (!isSelectedGeoOrAxis(listOfGeoId, constr->First) + || !isSelectedGeoOrAxis(listOfGeoId, constr->Second) + || !isSelectedGeoOrAxis(listOfGeoId, constr->Third)) { + continue; + } + + Constraint* temp = constr->copy(); + for (size_t j = 0; j < listOfGeoId.size(); j++) { + if (temp->First == listOfGeoId[j]) { + temp->First = j; + } + if (temp->Second == listOfGeoId[j]) { + temp->Second = j; + } + if (temp->Third == listOfGeoId[j]) { + temp->Third = j; + } + } + newConstrVals.push_back(temp); + } + Sketcher::PropertyConstraintList constToCopy; + constToCopy.setValues(std::move(newConstrVals)); + constToCopy.Save(writer); + + std::string exportedData = writer.getString(); + + if (!exportedData.empty()) { + QClipboard* clipboard = QGuiApplication::clipboard(); + clipboard->setText(QString::fromStdString(exportedData)); + return true; + } + return false; +} + +DEF_STD_CMD_A(CmdSketcherCopyClipboard) + +CmdSketcherCopyClipboard::CmdSketcherCopyClipboard() + : Command("Sketcher_CopyClipboard") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("C&opy in sketcher"); + sToolTipText = QT_TR_NOOP("Copy selected geometries and constraints to the clipboard"); + sWhatsThis = "Sketcher_CopyClipboard"; + sStatusTip = sToolTipText; + sPixmap = "edit-copy"; + sAccel = keySequenceToAccel(QKeySequence::Copy); + eType = ForEdit; +} + +void CmdSketcherCopyClipboard::activated(int iMsg) +{ + Q_UNUSED(iMsg); + copySelectionToClipboard(); +} + +bool CmdSketcherCopyClipboard::isActive() +{ + return isCommandActive(getActiveGuiDocument(), true); +} + +// ================================================================================ + +// Cut + +DEF_STD_CMD_A(CmdSketcherCut) + +CmdSketcherCut::CmdSketcherCut() + : Command("Sketcher_Cut") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("C&ut in sketcher"); + sToolTipText = QT_TR_NOOP("Cut selected geometries and constraints to the clipboard"); + sWhatsThis = "Sketcher_Cut"; + sStatusTip = sToolTipText; + sPixmap = "edit-cut"; + sAccel = keySequenceToAccel(QKeySequence::Cut); + eType = ForEdit; +} + +void CmdSketcherCut::activated(int iMsg) +{ + Q_UNUSED(iMsg); + if (copySelectionToClipboard()) { + + Gui::Document* doc = getActiveGuiDocument(); + ReleaseHandler(doc); + auto* vp = static_cast(doc->getInEdit()); + + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Cut in Sketcher")); + vp->deleteSelected(); + Gui::Command::commitCommand(); + } +} + +bool CmdSketcherCut::isActive() +{ + return isCommandActive(getActiveGuiDocument(), true); +} + +// ================================================================================ + +// Paste + +DEF_STD_CMD_A(CmdSketcherPaste) + +CmdSketcherPaste::CmdSketcherPaste() + : Command("Sketcher_Paste") +{ + sAppModule = "Sketcher"; + sGroup = "Sketcher"; + sMenuText = QT_TR_NOOP("P&aste in sketcher"); + sToolTipText = QT_TR_NOOP("Paste selected geometries and constraints from the clipboard"); + sWhatsThis = "Sketcher_Paste"; + sStatusTip = sToolTipText; + sPixmap = "edit-paste"; + sAccel = keySequenceToAccel(QKeySequence::Paste); + eType = ForEdit; +} + +void CmdSketcherPaste::activated(int iMsg) +{ + Q_UNUSED(iMsg); + Gui::Document* doc = getActiveGuiDocument(); + ReleaseHandler(doc); + auto* vp = static_cast(doc->getInEdit()); + Sketcher::SketchObject* Obj = vp->getSketchObject(); + + std::string data = QGuiApplication::clipboard()->text().toStdString(); + int importedFirstGeoId = Obj->getHighestCurveIndex() + 1; + + std::string geoString; + if (data.find("", 0) != std::string::npos) { + geoString = data.substr(0, data.find("", 0) + 16); + } + else { return ; } + + std::istringstream istream(geoString); + Base::XMLReader reader("importingGeo", istream); + Part::PropertyGeometryList geoToCopy; + geoToCopy.Restore(reader); + + const std::vector& geos = geoToCopy.getValues(); + if (geos.empty()) { return; } + + Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Paste in Sketcher")); + + for (auto geo : geos) { + Part::Geometry* geocopy = geo->copy(); + Obj->addGeometry(geocopy); + } + + if (data.find("copy(); + //update the geoIds of the constraints + if (!isAxisOrRoot(constraintToAdd->First)) { + constraintToAdd->First += importedFirstGeoId; + } + if (!isAxisOrRoot(constraintToAdd->Second)) { + constraintToAdd->Second += importedFirstGeoId; + } + if (!isAxisOrRoot(constraintToAdd->Third)) { + constraintToAdd->Third += importedFirstGeoId; + } + Obj->addConstraint(constraintToAdd); + } + } + + Obj->solve(true); + vp->draw(false, false); // Redraw + + Gui::Command::commitCommand(); +} + +bool CmdSketcherPaste::isActive() +{ + return isCommandActive(getActiveGuiDocument(), false); +} + +// ================================================================================ + // Select Constraints of selected elements DEF_STD_CMD_A(CmdSketcherSelectConstraints) @@ -2432,5 +2689,8 @@ void CreateSketcherCommandsConstraintAccel() rcCmdMgr.addCommand(new CmdSketcherDeleteAllGeometry()); rcCmdMgr.addCommand(new CmdSketcherDeleteAllConstraints()); rcCmdMgr.addCommand(new CmdSketcherRemoveAxesAlignment()); + rcCmdMgr.addCommand(new CmdSketcherCopyClipboard()); + rcCmdMgr.addCommand(new CmdSketcherCut()); + rcCmdMgr.addCommand(new CmdSketcherPaste()); } // clang-format on diff --git a/src/Mod/Sketcher/Gui/ShortcutListener.cpp b/src/Mod/Sketcher/Gui/ShortcutListener.cpp index 805e54f1f4..b161cb4194 100644 --- a/src/Mod/Sketcher/Gui/ShortcutListener.cpp +++ b/src/Mod/Sketcher/Gui/ShortcutListener.cpp @@ -31,12 +31,6 @@ using namespace SketcherGui; -// ******************** ViewProvider attorney *********************************************// -inline void ViewProviderSketchShortcutListenerAttorney::deleteSelected(ViewProviderSketch& vp) -{ - vp.deleteSelected(); -}; - // ******************** ShortcutListener *********************************************// ShortcutListener::ShortcutListener(ViewProviderSketch* vp) { @@ -55,7 +49,7 @@ bool ShortcutListener::eventFilter(QObject* obj, QEvent* event) switch (kevent->key()) { case Qt::Key_Delete: kevent->accept(); - ViewProviderSketchShortcutListenerAttorney::deleteSelected(*pViewProvider); + pViewProvider->deleteSelected(); return true; default: break; diff --git a/src/Mod/Sketcher/Gui/ShortcutListener.h b/src/Mod/Sketcher/Gui/ShortcutListener.h index 414da71fa3..70366adc83 100644 --- a/src/Mod/Sketcher/Gui/ShortcutListener.h +++ b/src/Mod/Sketcher/Gui/ShortcutListener.h @@ -31,15 +31,6 @@ namespace SketcherGui class ViewProviderSketch; -class ViewProviderSketchShortcutListenerAttorney -{ -private: - static inline void deleteSelected(ViewProviderSketch& vp); - - - friend class ShortcutListener; -}; - class ShortcutListener: public QObject { // Q_OBJECT diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index e8e16c5c08..bcadc5bed6 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -672,6 +672,7 @@ public: const Gui::View3DInventorViewer* viewer) override; //@} + void deleteSelected(); /// Control the overlays appearing on the Tree and reflecting different sketcher states QIcon mergeColorfulOverlayIcons(const QIcon& orig) const override; @@ -702,7 +703,6 @@ public: friend class ViewProviderSketchDrawSketchHandlerAttorney; friend class ViewProviderSketchCoinAttorney; friend class ViewProviderSketchSnapAttorney; - friend class ViewProviderSketchShortcutListenerAttorney; //@} protected: /** @name enter/exit edit mode */ @@ -867,9 +867,6 @@ private: bool isConstraintSelected(int constraintId) const; - //********* ViewProviderSketchShortcutListenerAttorney ***********// - void deleteSelected(); - //********* ViewProviderSketchDrawSketchHandlerAttorney **********// void setConstraintSelectability(bool enabled = true); void setPositionText(const Base::Vector2d& Pos, const SbString& txt); diff --git a/src/Mod/Sketcher/Gui/Workbench.cpp b/src/Mod/Sketcher/Gui/Workbench.cpp index 5c2d74ed2e..c1be2c1ac5 100644 --- a/src/Mod/Sketcher/Gui/Workbench.cpp +++ b/src/Mod/Sketcher/Gui/Workbench.cpp @@ -543,7 +543,11 @@ inline void SketcherAddWorkbenchTools(Gui::MenuItem& consaccel) << "Sketcher_RemoveAxesAlignment" << "Separator" << "Sketcher_DeleteAllGeometry" - << "Sketcher_DeleteAllConstraints"; + << "Sketcher_DeleteAllConstraints" + << "Separator" + << "Sketcher_CopyClipboard" + << "Sketcher_Cut" + << "Sketcher_Paste"; } template<> From a8b6e1e9c334b394c4205f89d2a9d72bc8962003 Mon Sep 17 00:00:00 2001 From: Paddle Date: Thu, 11 Jan 2024 18:31:25 +0100 Subject: [PATCH 2/4] Sketcher: python converter : add possibility to add lastGeoId to the constraint process. --- src/Mod/Sketcher/App/PythonConverter.cpp | 318 ++++++++++++++--------- src/Mod/Sketcher/App/PythonConverter.h | 14 +- 2 files changed, 203 insertions(+), 129 deletions(-) diff --git a/src/Mod/Sketcher/App/PythonConverter.cpp b/src/Mod/Sketcher/App/PythonConverter.cpp index d063378161..fe5def95dd 100644 --- a/src/Mod/Sketcher/App/PythonConverter.cpp +++ b/src/Mod/Sketcher/App/PythonConverter.cpp @@ -59,11 +59,11 @@ std::string PythonConverter::convert(const Part::Geometry* geo, Mode mode) return command; } -std::string PythonConverter::convert(const Sketcher::Constraint* constraint) +std::string PythonConverter::convert(const Sketcher::Constraint* constraint, bool useLastGeoIdVar) { // addConstraint(Sketcher.Constraint('Distance',%d,%f)) std::string command; - auto cg = process(constraint); + auto cg = process(constraint, useLastGeoIdVar); command = boost::str(boost::format("addConstraint(%s)\n") % cg); @@ -85,13 +85,13 @@ std::string PythonConverter::convert(const std::string& doc, if (ngeos > 0) { if (construction) { command = boost::str( - boost::format("constrGeoList = []\n%s\n%s.addGeometry(constrGeoList,%s)\ndel " - "constrGeoList") + boost::format("constrGeoList = []\n%s%s.addGeometry(constrGeoList,%s)\n" + "del constrGeoList\n") % geolist % doc % "True"); } else { command = boost::str( - boost::format("geoList = []\n%s\n%s.addGeometry(geoList,%s)\ndel geoList") + boost::format("geoList = []\n%s%s.addGeometry(geoList,%s)\ndel geoList\n") % geolist % doc % "False"); } } @@ -134,10 +134,10 @@ std::string PythonConverter::convert(const std::string& doc, if (sg.construction) { geolist = - boost::str(boost::format("%s\nconstrGeoList.append(%s)\n") % geolist % sg.creation); + boost::str(boost::format("%sconstrGeoList.append(%s)\n") % geolist % sg.creation); } else { - geolist = boost::str(boost::format("%s\ngeoList.append(%s)\n") % geolist % sg.creation); + geolist = boost::str(boost::format("%sgeoList.append(%s)\n") % geolist % sg.creation); } ngeos++; @@ -165,7 +165,8 @@ std::string PythonConverter::convert(const std::string& doc, } std::string PythonConverter::convert(const std::string& doc, - const std::vector& constraints) + const std::vector& constraints, + bool useLastGeoIdVar) { if (constraints.size() == 1) { auto cg = convert(constraints[0]); @@ -176,7 +177,7 @@ std::string PythonConverter::convert(const std::string& doc, std::string constraintlist = "constraintList = []"; for (auto constraint : constraints) { - auto cg = process(constraint); + auto cg = process(constraint, useLastGeoIdVar); constraintlist = boost::str(boost::format("%s\nconstraintList.append(%s)") % constraintlist % cg); @@ -200,7 +201,8 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g auto sgeo = static_cast(geo); SingleGeometry sg; sg.creation = boost::str( - boost::format("Part.LineSegment(App.Vector(%f,%f,%f),App.Vector(%f,%f,%f))") + boost::format( + "Part.LineSegment(App.Vector(%f, %f, %f),App.Vector(%f, %f, %f))") % sgeo->getStartPoint().x % sgeo->getStartPoint().y % sgeo->getStartPoint().z % sgeo->getEndPoint().x % sgeo->getEndPoint().y % sgeo->getEndPoint().z); sg.construction = Sketcher::GeometryFacade::getConstruction(geo); @@ -225,7 +227,7 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g auto sgeo = static_cast(geo); SingleGeometry sg; sg.creation = - boost::str(boost::format("Part.Point(App.Vector(%f,%f,%f))") + boost::str(boost::format("Part.Point(App.Vector(%f, %f, %f))") % sgeo->getPoint().x % sgeo->getPoint().y % sgeo->getPoint().z); sg.construction = Sketcher::GeometryFacade::getConstruction(geo); return sg; @@ -309,10 +311,10 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g controlpoints.append(1, ']'); SingleGeometry sg; - sg.creation = - boost::str(boost::format("Part.BSplineCurve (%s,None,None,%s,%d,None,False)") - % controlpoints.c_str() % (bSpline->isPeriodic() ? "True" : "False") - % bSpline->getDegree()); + sg.creation = boost::str( + boost::format("Part.BSplineCurve (%s, None, None, %s, %d, None, False)") + % controlpoints.c_str() % (bSpline->isPeriodic() ? "True" : "False") + % bSpline->getDegree()); sg.construction = Sketcher::GeometryFacade::getConstruction(geo); return sg; }}, @@ -342,128 +344,158 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g return creator(geo); } -std::string PythonConverter::process(const Sketcher::Constraint* constraint) +std::string PythonConverter::process(const Sketcher::Constraint* constraint, bool useLastIdVar) { - static std::map> + std::string geoId1 = (useLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->First); + std::string geoId2 = (useLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->Second); + std::string geoId3 = (useLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->Third); + + static std::map< + const Sketcher::ConstraintType, + std::function< + std::string(const Sketcher::Constraint*, std::string&, std::string&, std::string&)>> converterMap = { {Sketcher::Coincident, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { return boost::str( - boost::format("Sketcher.Constraint('Coincident', %i, %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('Coincident', %s, %i, %s, %i)") % geoId1 + % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos)); }}, {Sketcher::Horizontal, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { if (constr->Second == GeoEnum::GeoUndef) { - return boost::str(boost::format("Sketcher.Constraint('Horizontal', %i)") - % constr->First); + return boost::str(boost::format("Sketcher.Constraint('Horizontal', %s)") + % geoId1); } else { return boost::str( - boost::format("Sketcher.Constraint('Horizontal', %i, %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('Horizontal', %s, %i, %s, %i)") % geoId1 + % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos)); } }}, {Sketcher::Vertical, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { if (constr->Second == GeoEnum::GeoUndef) { - return boost::str(boost::format("Sketcher.Constraint('Vertical', %i)") - % constr->First); + return boost::str(boost::format("Sketcher.Constraint('Vertical', %s)") + % geoId1); } else { return boost::str( - boost::format("Sketcher.Constraint('Vertical', %i, %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('Vertical', %s, %i, %s, %i)") % geoId1 + % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos)); } }}, {Sketcher::Block, - [](const Sketcher::Constraint* constr) { - return boost::str(boost::format("Sketcher.Constraint('Block', %i)") - % constr->First); + []([[maybe_unused]] const Sketcher::Constraint* constr, + std::string& geoId1, + [[maybe_unused]] std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { + return boost::str(boost::format("Sketcher.Constraint('Block', %s)") % geoId1); }}, {Sketcher::Tangent, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { if (constr->FirstPos == Sketcher::PointPos::none) { - return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i)") - % constr->First % constr->Second); + return boost::str(boost::format("Sketcher.Constraint('Tangent', %s, %s)") + % geoId1 % geoId2); } else if (constr->SecondPos == Sketcher::PointPos::none) { - return boost::str(boost::format("Sketcher.Constraint('Tangent', %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) - % constr->Second); + return boost::str(boost::format("Sketcher.Constraint('Tangent', %s, %i, %s)") + % geoId1 % static_cast(constr->FirstPos) % geoId2); } else { return boost::str( - boost::format("Sketcher.Constraint('Tangent', %i, %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('Tangent', %s, %i, %s, %i)") % geoId1 + % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos)); } }}, {Sketcher::Parallel, - [](const Sketcher::Constraint* constr) { - return boost::str(boost::format("Sketcher.Constraint('Parallel', %i, %i)") - % constr->First % constr->Second); + []([[maybe_unused]] const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { + return boost::str(boost::format("Sketcher.Constraint('Parallel', %s, %s)") % geoId1 + % geoId2); }}, {Sketcher::Perpendicular, - [](const Sketcher::Constraint* constr) { + []([[maybe_unused]] const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { if (constr->FirstPos == Sketcher::PointPos::none) { - return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %i, %i)") - % constr->First % constr->Second); + return boost::str(boost::format("Sketcher.Constraint('Perpendicular', %s, %s)") + % geoId1 % geoId2); } else if (constr->SecondPos == Sketcher::PointPos::none) { return boost::str( - boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second); + boost::format("Sketcher.Constraint('Perpendicular', %s, %i, %s)") % geoId1 + % static_cast(constr->FirstPos) % geoId2); } else { return boost::str( - boost::format("Sketcher.Constraint('Perpendicular', %i, %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('Perpendicular', %s, %i, %s, %i)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos)); } }}, {Sketcher::Equal, - [](const Sketcher::Constraint* constr) { - return boost::str(boost::format("Sketcher.Constraint('Equal', %i, %i)") - % constr->First % constr->Second); + []([[maybe_unused]] const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { + return boost::str(boost::format("Sketcher.Constraint('Equal', %s, %s)") % geoId1 + % geoId2); }}, {Sketcher::InternalAlignment, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { if (constr->AlignmentType == EllipseMajorDiameter || constr->AlignmentType == EllipseMinorDiameter || constr->AlignmentType == HyperbolaMajor || constr->AlignmentType == HyperbolaMinor || constr->AlignmentType == ParabolaFocalAxis) { return boost::str( - boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i)") - % constr->internalAlignmentTypeToString() % constr->First - % constr->Second); + boost::format("Sketcher.Constraint('InternalAlignment:%s', %s, %s)") + % constr->internalAlignmentTypeToString() % geoId1 % geoId2); } else if (constr->AlignmentType == EllipseFocus1 || constr->AlignmentType == EllipseFocus2 || constr->AlignmentType == HyperbolaFocus || constr->AlignmentType == ParabolaFocus) { return boost::str( - boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i)") - % constr->internalAlignmentTypeToString() % constr->First - % static_cast(constr->FirstPos) % constr->Second); + boost::format("Sketcher.Constraint('InternalAlignment:%s', %s, %i, %s)") + % constr->internalAlignmentTypeToString() % geoId1 + % static_cast(constr->FirstPos) % geoId2); } else if (constr->AlignmentType == BSplineControlPoint) { return boost::str( boost::format( - "Sketcher.Constraint('InternalAlignment:%s', %i, %i, %i, %i)") - % constr->internalAlignmentTypeToString() % constr->First - % static_cast(constr->FirstPos) % constr->Second + "Sketcher.Constraint('InternalAlignment:%s', %s, %i, %s, %i)") + % constr->internalAlignmentTypeToString() % geoId1 + % static_cast(constr->FirstPos) % geoId2 % constr->InternalAlignmentIndex); } else if (constr->AlignmentType == BSplineKnotPoint) { return boost::str( - boost::format("Sketcher.Constraint('InternalAlignment:%s', %i, 1, %i, %i)") - % constr->internalAlignmentTypeToString() % constr->First % constr->Second + boost::format("Sketcher.Constraint('InternalAlignment:%s', %s, 1, %s, %i)") + % constr->internalAlignmentTypeToString() % geoId1 % geoId2 % constr->InternalAlignmentIndex); } @@ -471,124 +503,160 @@ std::string PythonConverter::process(const Sketcher::Constraint* constraint) "PythonConverter: Constraint Alignment Type not supported") }}, {Sketcher::Distance, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { if (constr->Second == GeoEnum::GeoUndef) { - return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %f)") - % constr->First % constr->getValue()); + return boost::str(boost::format("Sketcher.Constraint('Distance', %s, %f)") + % geoId1 % constr->getValue()); } else if (constr->FirstPos == Sketcher::PointPos::none) { - return boost::str(boost::format("Sketcher.Constraint('Distance', %i, %i, %f)") - % constr->First % constr->Second % constr->getValue()); + return boost::str(boost::format("Sketcher.Constraint('Distance', %s, %s, %f)") + % geoId1 % geoId2 % constr->getValue()); } else if (constr->SecondPos == Sketcher::PointPos::none) { return boost::str( - boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) % constr->Second - % constr->getValue()); + boost::format("Sketcher.Constraint('Distance', %s, %i, %s, %f)") % geoId1 + % static_cast(constr->FirstPos) % geoId2 % constr->getValue()); } else { return boost::str( - boost::format("Sketcher.Constraint('Distance', %i, %i, %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('Distance', %s, %i, %s, %i, %f)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos) % constr->getValue()); } }}, {Sketcher::Angle, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + std::string& geoId3) { if (constr->Second == GeoEnum::GeoUndef) { - return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %f)") - % constr->First % constr->getValue()); + return boost::str(boost::format("Sketcher.Constraint('Angle', %s, %f)") + % geoId1 % constr->getValue()); } - else if (constr->SecondPos == Sketcher::PointPos::none) { - return boost::str(boost::format("Sketcher.Constraint('Angle', %i, %i, %f)") - % constr->First % constr->Second % constr->getValue()); + else if (constr->Third == GeoEnum::GeoUndef) { + if (constr->SecondPos == Sketcher::PointPos::none) { + return boost::str(boost::format("Sketcher.Constraint('Angle', %s, %s, %f)") + % geoId1 % geoId2 % constr->getValue()); + } + else { + return boost::str( + boost::format("Sketcher.Constraint('Angle', %s, %i, %s, %i, %f)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 + % static_cast(constr->SecondPos) % constr->getValue()); + } } else { return boost::str( - boost::format("Sketcher.Constraint('Angle', %i, %i, %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) % constr->Second - % static_cast(constr->SecondPos) % constr->getValue()); + boost::format("Sketcher.Constraint('AngleViaPoint', %s, %s, %s, %i, %f)") + % geoId1 % geoId2 % geoId3 % static_cast(constr->ThirdPos) + % constr->getValue()); } }}, {Sketcher::DistanceX, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + std::string& geoId3) { if (constr->Second == GeoEnum::GeoUndef) { - return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %f)") - % constr->First % constr->getValue()); + return boost::str(boost::format("Sketcher.Constraint('DistanceX', %s, %f)") + % geoId1 % constr->getValue()); } else if (constr->SecondPos == Sketcher::PointPos::none) { - return boost::str(boost::format("Sketcher.Constraint('DistanceX', %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) + return boost::str(boost::format("Sketcher.Constraint('DistanceX', %s, %i, %f)") + % geoId1 % static_cast(constr->FirstPos) % constr->getValue()); } else { return boost::str( - boost::format("Sketcher.Constraint('DistanceX', %i, %i, %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('DistanceX', %s, %i, %s, %i, %f)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos) % constr->getValue()); } }}, {Sketcher::DistanceY, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { if (constr->Second == GeoEnum::GeoUndef) { - return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %f)") - % constr->First % constr->getValue()); + return boost::str(boost::format("Sketcher.Constraint('DistanceY', %s, %f)") + % geoId1 % constr->getValue()); } else if (constr->SecondPos == Sketcher::PointPos::none) { - return boost::str(boost::format("Sketcher.Constraint('DistanceY', %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) + return boost::str(boost::format("Sketcher.Constraint('DistanceY', %s, %i, %f)") + % geoId1 % static_cast(constr->FirstPos) % constr->getValue()); } else { return boost::str( - boost::format("Sketcher.Constraint('DistanceY', %i, %i, %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) % constr->Second + boost::format("Sketcher.Constraint('DistanceY', %s, %i, %s, %i, %f)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 % static_cast(constr->SecondPos) % constr->getValue()); } }}, {Sketcher::Radius, - [](const Sketcher::Constraint* constr) { - return boost::str(boost::format("Sketcher.Constraint('Radius', %i, %f)") - % constr->First % constr->getValue()); + [](const Sketcher::Constraint* constr, + std::string& geoId1, + [[maybe_unused]] std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { + return boost::str(boost::format("Sketcher.Constraint('Radius', %s, %f)") % geoId1 + % constr->getValue()); }}, {Sketcher::Diameter, - [](const Sketcher::Constraint* constr) { - return boost::str(boost::format("Sketcher.Constraint('Diameter', %i, %f)") - % constr->First % constr->getValue()); + [](const Sketcher::Constraint* constr, + std::string& geoId1, + [[maybe_unused]] std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { + return boost::str(boost::format("Sketcher.Constraint('Diameter', %s, %f)") % geoId1 + % constr->getValue()); }}, {Sketcher::Weight, - [](const Sketcher::Constraint* constr) { - return boost::str(boost::format("Sketcher.Constraint('Weight', %i, %f)") - % constr->First % constr->getValue()); + [](const Sketcher::Constraint* constr, + std::string& geoId1, + [[maybe_unused]] std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { + return boost::str(boost::format("Sketcher.Constraint('Weight', %s, %f)") % geoId1 + % constr->getValue()); }}, {Sketcher::PointOnObject, - [](const Sketcher::Constraint* constr) { - return boost::str(boost::format("Sketcher.Constraint('PointOnObject', %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) - % constr->Second); + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + [[maybe_unused]] std::string& geoId3) { + return boost::str(boost::format("Sketcher.Constraint('PointOnObject', %s, %i, %s)") + % geoId1 % static_cast(constr->FirstPos) % geoId2); }}, {Sketcher::Symmetric, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + std::string& geoId3) { if (constr->ThirdPos == Sketcher::PointPos::none) { return boost::str( - boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second - % static_cast(constr->SecondPos) % constr->Third); + boost::format("Sketcher.Constraint('Symmetric', %s, %i, %s, %i, %s)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 + % static_cast(constr->SecondPos) % geoId3); } else { return boost::str( - boost::format("Sketcher.Constraint('Symmetric', %i, %i, %i, %i, %i, %i)") - % constr->First % static_cast(constr->FirstPos) % constr->Second - % static_cast(constr->SecondPos) % constr->Third + boost::format("Sketcher.Constraint('Symmetric', %s, %i, %s, %i, %s, %i)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 + % static_cast(constr->SecondPos) % geoId3 % static_cast(constr->ThirdPos)); } }}, {Sketcher::SnellsLaw, - [](const Sketcher::Constraint* constr) { + [](const Sketcher::Constraint* constr, + std::string& geoId1, + std::string& geoId2, + std::string& geoId3) { return boost::str( - boost::format("Sketcher.Constraint('SnellsLaw', %i, %i, %i, %i, %i, %f)") - % constr->First % static_cast(constr->FirstPos) % constr->Second - % static_cast(constr->SecondPos) % constr->Third % constr->getValue()); + boost::format("Sketcher.Constraint('SnellsLaw', %s, %i, %s, %i, %s, %f)") + % geoId1 % static_cast(constr->FirstPos) % geoId2 + % static_cast(constr->SecondPos) % geoId3 % constr->getValue()); }}, }; @@ -600,7 +668,7 @@ std::string PythonConverter::process(const Sketcher::Constraint* constraint) auto creator = result->second; - return creator(constraint); + return creator(constraint, geoId1, geoId2, geoId3); } std::vector PythonConverter::multiLine(std::string&& singlestring) diff --git a/src/Mod/Sketcher/App/PythonConverter.h b/src/Mod/Sketcher/App/PythonConverter.h index 98535583b1..050d09dada 100644 --- a/src/Mod/Sketcher/App/PythonConverter.h +++ b/src/Mod/Sketcher/App/PythonConverter.h @@ -24,6 +24,9 @@ #ifndef SKETCHER_PythonConverter_H #define SKETCHER_PythonConverter_H +#include +#include + #include namespace Part @@ -57,7 +60,7 @@ public: OmitInternalGeometry }; - explicit PythonConverter() = delete; + PythonConverter() = delete; ~PythonConverter() = delete; /// Convert a geometry into the string representing the command creating it @@ -68,17 +71,20 @@ public: const std::vector& geos, Mode mode = Mode::CreateInternalGeometry); - static std::string convert(const Sketcher::Constraint* constraint); + static std::string convert(const Sketcher::Constraint* constraint, + bool useLastGeoIdVar = false); static std::string convert(const std::string& doc, - const std::vector& constraints); + const std::vector& constraints, + bool useLastGeoIdVar = false); static std::vector multiLine(std::string&& singlestring); private: static SingleGeometry process(const Part::Geometry* geo); - static std::string process(const Sketcher::Constraint* constraint); + static std::string process(const Sketcher::Constraint* constraint, + bool useLastGeoIdVar = false); }; } // namespace Sketcher From 8ed22b0fd887e33b3619c319cf7499aef3398901 Mon Sep 17 00:00:00 2001 From: Paddle Date: Thu, 11 Jan 2024 18:31:57 +0100 Subject: [PATCH 3/4] Sketcher: copy paste : move from XML to python. --- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 124 ++++-------------- 1 file changed, 25 insertions(+), 99 deletions(-) diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index 2fc791558f..a16c6db99f 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -145,55 +146,24 @@ Sketcher::SketchObject* getSketchObject() // Copy -bool copySelectionToClipboard() { - - std::vector selection = Gui::Command::getSelection().getSelectionEx(); - Sketcher::SketchObject* obj = static_cast(selection[0].getObject()); - // only one sketch with its subelements are allowed to be selected - if (selection.size() != 1) { return false; } - std::vector SubNames = selection[0].getSubNames(); - if (SubNames.empty()) { return false; } - - //First we need listOfGeoId and sort them. - std::vector listOfGeoId; - for (std::vector::const_iterator it = SubNames.begin(); it != SubNames.end(); ++it) { - int GeoId = -1; - // only handle non-external edges - if (it->size() > 4 && it->substr(0, 4) == "Edge") { - GeoId = std::atoi(it->substr(4, 4000).c_str()) - 1; - if (GeoId >= 0) { - listOfGeoId.push_back(GeoId); - } - } - else if (it->size() > 6 && it->substr(0, 6) == "Vertex") { - // only if it is a GeomPoint - int VtId = std::atoi(it->substr(6, 4000).c_str()) - 1; - Sketcher::PointPos PosId; - obj->getGeoVertexIndex(VtId, GeoId, PosId); - if (obj->getGeometry(GeoId)->getTypeId() == Part::GeomPoint::getClassTypeId()) { - if (GeoId >= 0) { - listOfGeoId.push_back(GeoId); - } - } - } - } +bool copySelectionToClipboard(Sketcher::SketchObject* obj) { + std::vector listOfGeoId = getListOfSelectedGeoIds(true); if (listOfGeoId.empty()) { return false; } sort(listOfGeoId.begin(), listOfGeoId.end()); - Base::StringWriter writer; - - //Export selected geometries as a formated string. - std::vector< Part::Geometry* > newVals; + //Export selected geometries as a formatted string. + std::vector shapeGeometry; for (auto geoId : listOfGeoId) { Part::Geometry* geoNew = obj->getGeometry(geoId)->copy(); - newVals.push_back(geoNew); + shapeGeometry.push_back(geoNew); } - Part::PropertyGeometryList geoToCopy; - geoToCopy.setValues(std::move(newVals)); - geoToCopy.Save(writer); + std::string geosAsStr = Sketcher::PythonConverter::convert( + "objectStr", + shapeGeometry, + Sketcher::PythonConverter::Mode::OmitInternalGeometry); - //add constraints to the stream string. - std::vector< Sketcher::Constraint* > newConstrVals; + // Export constraints of selected geos. + std::vector shapeConstraints; for (auto constr : obj->Constraints.getValues()) { auto isSelectedGeoOrAxis = [](const std::vector& vec, int value) { @@ -220,13 +190,12 @@ bool copySelectionToClipboard() { temp->Third = j; } } - newConstrVals.push_back(temp); + shapeConstraints.push_back(temp); } - Sketcher::PropertyConstraintList constToCopy; - constToCopy.setValues(std::move(newConstrVals)); - constToCopy.Save(writer); + std::string cstrAsStr = Sketcher::PythonConverter::convert("objectStr", shapeConstraints, true); - std::string exportedData = writer.getString(); + std::string exportedData = "# Copied from sketcher. From:\n#objectStr = " + Gui::Command::getObjectCmd(obj) + "\n" + + geosAsStr + "\n" + cstrAsStr; if (!exportedData.empty()) { QClipboard* clipboard = QGuiApplication::clipboard(); @@ -255,7 +224,7 @@ CmdSketcherCopyClipboard::CmdSketcherCopyClipboard() void CmdSketcherCopyClipboard::activated(int iMsg) { Q_UNUSED(iMsg); - copySelectionToClipboard(); + copySelectionToClipboard(getSketchObject()); } bool CmdSketcherCopyClipboard::isActive() @@ -286,7 +255,7 @@ CmdSketcherCut::CmdSketcherCut() void CmdSketcherCut::activated(int iMsg) { Q_UNUSED(iMsg); - if (copySelectionToClipboard()) { + if (copySelectionToClipboard(getSketchObject())) { Gui::Document* doc = getActiveGuiDocument(); ReleaseHandler(doc); @@ -329,63 +298,20 @@ void CmdSketcherPaste::activated(int iMsg) Gui::Document* doc = getActiveGuiDocument(); ReleaseHandler(doc); auto* vp = static_cast(doc->getInEdit()); - Sketcher::SketchObject* Obj = vp->getSketchObject(); + Sketcher::SketchObject* obj = vp->getSketchObject(); std::string data = QGuiApplication::clipboard()->text().toStdString(); - int importedFirstGeoId = Obj->getHighestCurveIndex() + 1; - - std::string geoString; - if (data.find("", 0) != std::string::npos) { - geoString = data.substr(0, data.find("", 0) + 16); + if (data.find("# Copied from sketcher.", 0) == std::string::npos) { + return; } - else { return ; } - - std::istringstream istream(geoString); - Base::XMLReader reader("importingGeo", istream); - Part::PropertyGeometryList geoToCopy; - geoToCopy.Restore(reader); - - const std::vector& geos = geoToCopy.getValues(); - if (geos.empty()) { return; } + data = "objectStr = " + Gui::Command::getObjectCmd(obj) +"\n" + data; Gui::Command::openCommand(QT_TRANSLATE_NOOP("Command", "Paste in Sketcher")); - for (auto geo : geos) { - Part::Geometry* geocopy = geo->copy(); - Obj->addGeometry(geocopy); - } + Gui::Command::doCommand(Gui::Command::Doc, data.c_str()); - if (data.find("copy(); - //update the geoIds of the constraints - if (!isAxisOrRoot(constraintToAdd->First)) { - constraintToAdd->First += importedFirstGeoId; - } - if (!isAxisOrRoot(constraintToAdd->Second)) { - constraintToAdd->Second += importedFirstGeoId; - } - if (!isAxisOrRoot(constraintToAdd->Third)) { - constraintToAdd->Third += importedFirstGeoId; - } - Obj->addConstraint(constraintToAdd); - } - } - - Obj->solve(true); - vp->draw(false, false); // Redraw + obj->solve(true); + vp->draw(false, false); Gui::Command::commitCommand(); } From 17893d39caa98aa5d32c4d28b03d7628324f4796 Mon Sep 17 00:00:00 2001 From: Paddle Date: Sat, 20 Jan 2024 06:49:32 +0100 Subject: [PATCH 4/4] Sketcher: PythonConverter: Replace useLastGeoIdVar bool by enum class --- src/Mod/Sketcher/App/PythonConverter.cpp | 17 +++++++++-------- src/Mod/Sketcher/App/PythonConverter.h | 12 +++++++++--- src/Mod/Sketcher/Gui/CommandSketcherTools.cpp | 2 +- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/Mod/Sketcher/App/PythonConverter.cpp b/src/Mod/Sketcher/App/PythonConverter.cpp index fe5def95dd..506463ae62 100644 --- a/src/Mod/Sketcher/App/PythonConverter.cpp +++ b/src/Mod/Sketcher/App/PythonConverter.cpp @@ -59,11 +59,11 @@ std::string PythonConverter::convert(const Part::Geometry* geo, Mode mode) return command; } -std::string PythonConverter::convert(const Sketcher::Constraint* constraint, bool useLastGeoIdVar) +std::string PythonConverter::convert(const Sketcher::Constraint* constraint, GeoIdMode geoIdMode) { // addConstraint(Sketcher.Constraint('Distance',%d,%f)) std::string command; - auto cg = process(constraint, useLastGeoIdVar); + auto cg = process(constraint, geoIdMode); command = boost::str(boost::format("addConstraint(%s)\n") % cg); @@ -166,7 +166,7 @@ std::string PythonConverter::convert(const std::string& doc, std::string PythonConverter::convert(const std::string& doc, const std::vector& constraints, - bool useLastGeoIdVar) + GeoIdMode geoIdMode) { if (constraints.size() == 1) { auto cg = convert(constraints[0]); @@ -177,7 +177,7 @@ std::string PythonConverter::convert(const std::string& doc, std::string constraintlist = "constraintList = []"; for (auto constraint : constraints) { - auto cg = process(constraint, useLastGeoIdVar); + auto cg = process(constraint, geoIdMode); constraintlist = boost::str(boost::format("%s\nconstraintList.append(%s)") % constraintlist % cg); @@ -344,11 +344,12 @@ PythonConverter::SingleGeometry PythonConverter::process(const Part::Geometry* g return creator(geo); } -std::string PythonConverter::process(const Sketcher::Constraint* constraint, bool useLastIdVar) +std::string PythonConverter::process(const Sketcher::Constraint* constraint, GeoIdMode geoIdMode) { - std::string geoId1 = (useLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->First); - std::string geoId2 = (useLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->Second); - std::string geoId3 = (useLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->Third); + bool addLastIdVar = geoIdMode == GeoIdMode::AddLastGeoIdToGeoIds; + std::string geoId1 = (addLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->First); + std::string geoId2 = (addLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->Second); + std::string geoId3 = (addLastIdVar ? "lastGeoId + " : "") + std::to_string(constraint->Third); static std::map< const Sketcher::ConstraintType, diff --git a/src/Mod/Sketcher/App/PythonConverter.h b/src/Mod/Sketcher/App/PythonConverter.h index 050d09dada..8062064589 100644 --- a/src/Mod/Sketcher/App/PythonConverter.h +++ b/src/Mod/Sketcher/App/PythonConverter.h @@ -60,6 +60,12 @@ public: OmitInternalGeometry }; + enum class GeoIdMode + { + DoNotChangeGeoIds, + AddLastGeoIdToGeoIds, + }; + PythonConverter() = delete; ~PythonConverter() = delete; @@ -72,11 +78,11 @@ public: Mode mode = Mode::CreateInternalGeometry); static std::string convert(const Sketcher::Constraint* constraint, - bool useLastGeoIdVar = false); + GeoIdMode geoIdMode = GeoIdMode::DoNotChangeGeoIds); static std::string convert(const std::string& doc, const std::vector& constraints, - bool useLastGeoIdVar = false); + GeoIdMode geoIdMode = GeoIdMode::DoNotChangeGeoIds); static std::vector multiLine(std::string&& singlestring); @@ -84,7 +90,7 @@ private: static SingleGeometry process(const Part::Geometry* geo); static std::string process(const Sketcher::Constraint* constraint, - bool useLastGeoIdVar = false); + GeoIdMode geoIdMode = GeoIdMode::DoNotChangeGeoIds); }; } // namespace Sketcher diff --git a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp index a16c6db99f..3905fdcaaa 100644 --- a/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp +++ b/src/Mod/Sketcher/Gui/CommandSketcherTools.cpp @@ -192,7 +192,7 @@ bool copySelectionToClipboard(Sketcher::SketchObject* obj) { } shapeConstraints.push_back(temp); } - std::string cstrAsStr = Sketcher::PythonConverter::convert("objectStr", shapeConstraints, true); + std::string cstrAsStr = Sketcher::PythonConverter::convert("objectStr", shapeConstraints, Sketcher::PythonConverter::GeoIdMode::AddLastGeoIdToGeoIds); std::string exportedData = "# Copied from sketcher. From:\n#objectStr = " + Gui::Command::getObjectCmd(obj) + "\n" + geosAsStr + "\n" + cstrAsStr;