Sketcher: Add copy/cut/paste sketcher commands

This commit is contained in:
Paddle
2023-11-26 07:50:02 +01:00
parent 62bd9b5e4a
commit 88883faaf8
5 changed files with 267 additions and 21 deletions

View File

@@ -26,6 +26,7 @@
#include <memory>
#include <QApplication>
#include <QClipboard>
#include <QMessageBox>
#include <Inventor/SbString.h>
@@ -33,6 +34,8 @@
#include <App/Application.h>
#include <Base/Console.h>
#include <Base/Reader.h>
#include <Base/Writer.h>
#include <Gui/Action.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
@@ -140,6 +143,260 @@ Sketcher::SketchObject* getSketchObject()
// ================================================================================
// Copy
bool copySelectionToClipboard() {
std::vector<Gui::SelectionObject> selection = Gui::Command::getSelection().getSelectionEx();
Sketcher::SketchObject* obj = static_cast<Sketcher::SketchObject*>(selection[0].getObject());
// only one sketch with its subelements are allowed to be selected
if (selection.size() != 1) { return false; }
std::vector<std::string> SubNames = selection[0].getSubNames();
if (SubNames.empty()) { return false; }
//First we need listOfGeoId and sort them.
std::vector<int> listOfGeoId;
for (std::vector<std::string>::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<int>& 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<SketcherGui::ViewProviderSketch*>(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<SketcherGui::ViewProviderSketch*>(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("</GeometryList>", 0) != std::string::npos) {
geoString = data.substr(0, data.find("</GeometryList>", 0) + 16);
}
else { return ; }
std::istringstream istream(geoString);
Base::XMLReader reader("importingGeo", istream);
Part::PropertyGeometryList geoToCopy;
geoToCopy.Restore(reader);
const std::vector<Part::Geometry*>& 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("<ConstraintList", 0) != std::string::npos) {
std::string constrString;
constrString = data.substr(data.find("<ConstraintList", 0), data.size() - data.find("<ConstraintList", 0));
std::istringstream istream2(constrString);
Base::XMLReader reader2("importingConstraints", istream2);
Sketcher::PropertyConstraintList constToCopy;
constToCopy.Restore(reader2);
auto isAxisOrRoot = [](int value) {
return value == GeoEnum::GeoUndef || value == GeoEnum::RtPnt || value == GeoEnum::VAxis || value == GeoEnum::HAxis;
};
for (auto constr : constToCopy.getValuesForce()) {
Sketcher::Constraint* constraintToAdd = constr->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

View File

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

View File

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

View File

@@ -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);

View File

@@ -543,7 +543,11 @@ inline void SketcherAddWorkbenchTools<Gui::MenuItem>(Gui::MenuItem& consaccel)
<< "Sketcher_RemoveAxesAlignment"
<< "Separator"
<< "Sketcher_DeleteAllGeometry"
<< "Sketcher_DeleteAllConstraints";
<< "Sketcher_DeleteAllConstraints"
<< "Separator"
<< "Sketcher_CopyClipboard"
<< "Sketcher_Cut"
<< "Sketcher_Paste";
}
template<>