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<>