<commit_before>/***************************************************************************
 *   Copyright (c) 2008 <NAME> <<EMAIL>>              *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/


#include "PreCompiled.h"
#ifndef _PreComp_
# include <TopoDS_Shape.hxx>
# include <TopoDS_Face.hxx>
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <QApplication>
# include <QInputDialog>
# include <QMessageBox>
#endif

#include <App/DocumentObjectGroup.h>
#include <App/OriginFeature.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/CommandT.h>
#include <Gui/Control.h>
#include <Gui/MainWindow.h>
#include <Gui/DlgEditFileIncludePropertyExternal.h>
#include <Gui/SelectionFilter.h>

#include <Mod/Sketcher/App/SketchObjectSF.h>
#include <Mod/Sketcher/App/SketchObject.h>
#include <Mod/Part/App/Attacher.h>
#include <Mod/Part/App/Part2DObject.h>

#include "SketchOrientationDialog.h"
#include "SketchMirrorDialog.h"
#include "ViewProviderSketch.h"
#include "TaskSketcherValidation.h"
#include "../App/Constraint.h"

using namespace std;
using namespace SketcherGui;
using namespace Part;
using namespace Attacher;


namespace SketcherGui {

    class ExceptionWrongInput : public Base::Exception {
    public:
        ExceptionWrongInput()
            : ErrMsg(QString())
        {

        }

        //Pass untranslated strings, enclosed in QT_TR_NOOP()
        ExceptionWrongInput(const char* ErrMsg){
            this->ErrMsg = QObject::tr( ErrMsg );
            this->setMessage(ErrMsg);
        }

        virtual ~ExceptionWrongInput() throw() {}

        QString ErrMsg;
    };


    Attacher::eMapMode SuggestAutoMapMode(Attacher::SuggestResult::eSuggestResult* pMsgId = 0,
                                      QString* message = 0,
                                      std::vector<Attacher::eMapMode>* allmodes = 0){
        //convert pointers into valid references, to avoid checking for null pointers everywhere
        Attacher::SuggestResult::eSuggestResult buf;
        if (pMsgId == 0)
            pMsgId = &buf;
        Attacher::SuggestResult::eSuggestResult &msg = *pMsgId;
        QString buf2;
        if (message == 0)
            message = &buf2;
        QString &msg_str = *message;

        App::PropertyLinkSubList tmpSupport;
        Gui::Selection().getAsPropertyLinkSubList(tmpSupport);

        Attacher::SuggestResult sugr;
        AttachEngine3D eng;
        eng.setUp(tmpSupport);
        eng.suggestMapModes(sugr);
        if (allmodes)
            *allmodes = sugr.allApplicableModes;
        msg = sugr.message;
        switch(msg){
            case Attacher::SuggestResult::srOK:
            break;
            case Attacher::SuggestResult::srNoModesFit:
                msg_str = QObject::tr("There are no modes that accept the selected set of subelements");
            break;
            case Attacher::SuggestResult::srLinkBroken:
                msg_str = QObject::tr("Broken link to support subelements");
            break;
            case Attacher::SuggestResult::srUnexpectedError:
                msg_str = QObject::tr("Unexpected error");
            break;
            case Attacher::SuggestResult::srIncompatibleGeometry:
                if(tmpSupport.getSubValues()[0].substr(0,4) == std::string("Face"))
                    msg_str = QObject::tr("Face is non-planar");
                else
                    msg_str = QObject::tr("Selected shapes are of wrong form (e.g., a curved edge where a straight one is needed)");
            break;
            default:
                msg_str = QObject::tr("Unexpected error");
                assert(0/*no message for eSuggestResult enum item*/);
        }

        return sugr.bestFitMode;
    }
} //namespace SketcherGui


/* Sketch commands =======================================================*/
DEF_STD_CMD_A(CmdSketcherNewSketch)

CmdSketcherNewSketch::CmdSketcherNewSketch()
    :Command("Sketcher_NewSketch")
{
    sAppModule      = "Sketcher";
    sGroup          = QT_TR_NOOP("Sketcher");
    sMenuText       = QT_TR_NOOP("Create sketch");
    sToolTipText    = QT_TR_NOOP("Create a new sketch.");
    sWhatsThis      = "Sketcher_NewSketch";
    sStatusTip      = sToolTipText;
    sPixmap         = "Sketcher_NewSketch";
}

void CmdSketcherNewSketch::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    Attacher::eMapMode mapmode = Attacher::mmDeactivated;
    bool bAttach = false;
    if (Gui::Selection().hasSelection()){
        Attacher::SuggestResult::eSuggestResult msgid = Attacher::SuggestResult::srOK;
        QString msg_str;
        std::vector<Attacher::eMapMode> validModes;
        mapmode = SuggestAutoMapMode(&msgid, &msg_str, &validModes);
        if (msgid == Attacher::SuggestResult::srOK)
            bAttach = true;
        if (msgid != Attacher::SuggestResult::srOK && msgid != Attacher::SuggestResult::srNoModesFit){
            QMessageBox::warning(Gui::getMainWindow(),
                QObject::tr("Sketch mapping"),
                QObject::tr("Can't map the sketch to selected object. %1.").arg(msg_str));
            return;
        }
        if (validModes.size() > 1){
            validModes.insert(validModes.begin(), Attacher::mmDeactivated);
            bool ok;
            QStringList items;
            items.push_back(QObject::tr("Don't attach"));
            int iSugg = 0;//index of the auto-suggested mode in the list of valid modes
            for (size_t i = 0  ;  i < validModes.size()  ;  ++i){
                items.push_back(QString::fromLatin1(AttachEngine::getModeName(validModes[i]).c_str()));
                if (validModes[i] == mapmode)
                    iSugg = items.size()-1;
            }
            QString text = QInputDialog::getItem(Gui::getMainWindow(),
                qApp->translate("Sketcher_NewSketch", "Sketch attachment"),
                qApp->translate("Sketcher_NewSketch", "Select the method to attach this sketch to selected object"),
                items, iSugg, false, &ok);
            if (!ok) return;
            int index = items.indexOf(text);
            if (index == 0){
                bAttach = false;
                mapmode = Attacher::mmDeactivated;
            } else {
                bAttach = true;
                mapmode = validModes[index-1];
            }
        }
    }

    if (bAttach) {

        std::vector<Gui::SelectionObject> objects = Gui::Selection().getSelectionEx();
        //assert (objects.size() == 1); //should have been filtered out by SuggestAutoMapMode
        //Gui::SelectionObject &sel_support = objects[0];
        App::PropertyLinkSubList support;
        Gui::Selection().getAsPropertyLinkSubList(support);
        std::string supportString = support.getPyReprString();

        // create Sketch on Face
        std::string FeatName = getUniqueObjectName("Sketch");

        openCommand("Create a new sketch on a face");
        doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject', '%s')", FeatName.c_str());
        if (mapmode < Attacher::mmDummy_NumberOfModes)
            doCommand(Gui,"App.activeDocument().%s.MapMode = \"%s\"",FeatName.c_str(),AttachEngine::getModeName(mapmode).c_str());
        else
            assert(0 /* mapmode index out of range */);
        doCommand(Gui,"App.activeDocument().%s.Support = %s", FeatName.c_str(), supportString.c_str());
        doCommand(Gui,"App.activeDocument().recompute()");  // recompute the sketch placement based on its support
        doCommand(Gui,"Gui.activeDocument().setEdit('%s')", FeatName.c_str());

        Part::Feature *part = static_cast<Part::Feature*>(support.getValue());  // if multi-part support, this will return 0
        if (part){
            App::DocumentObjectGroup* grp = part->getGroup();
            if (grp) {
                doCommand(Doc,
                          "App.activeDocument().%s.addObject(App.activeDocument().%s)",
                          grp->getNameInDocument(), FeatName.c_str());
            }
        }
    }
    else {
        // ask user for orientation
        SketchOrientationDialog Dlg;

        if (Dlg.exec() != QDialog::Accepted)
            return; // canceled
        Base::Vector3d p = Dlg.Pos.getPosition();
        Base::Rotation r = Dlg.Pos.getRotation();

        std::string FeatName = getUniqueObjectName("Sketch");

        openCommand("Create a new sketch");
        doCommand(Doc, "App.activeDocument().addObject('Sketcher::SketchObject', '%s')", FeatName.c_str());
        doCommand(Doc,
                  "App.activeDocument().%s.Placement = App.Placement(App.Vector(%f, %f, %f), App.Rotation(%f, %f, %f, %f))",
                  FeatName.c_str(), p.x, p.y, p.z, r[0], r[1], r[2], r[3]);
        doCommand(Doc,"App.activeDocument().%s.MapMode = \"%s\"",
                  FeatName.c_str(), AttachEngine::getModeName(Attacher::mmDeactivated).c_str());
        doCommand(Gui,"Gui.activeDocument().setEdit('%s')", FeatName.c_str());
    }

}

bool CmdSketcherNewSketch::isActive(void)
{
    if (getActiveGuiDocument())
        return true;
    else
        return false;
}

DEF_STD_CMD_A(CmdSketcherEditSketch)

CmdSketcherEditSketch::CmdSketcherEditSketch()
    :Command("Sketcher_EditSketch")
{
    sAppModule      = "Sketcher";
    sGroup          = QT_TR_NOOP("Sketcher");
    sMenuText       = QT_TR_NOOP("Edit sketch");
    sToolTipText    = QT_TR_NOOP("Edit the selected sketch.");
    sWhatsThis      = "Sketcher_EditSketch";
    sStatusTip      = sToolTipText;
    sPixmap         = "Sketcher_EditSketch";
}

void CmdSketcherEditSketch::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    Gui::SelectionFilter SketchFilter("SELECT Sketcher::SketchObject COUNT 1");

    if (SketchFilter.match()) {
        Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(SketchFilter.Result[0][0].getObject());
        openCommand("Edit sketch");
        doCommand(Gui,"Gui.activeDocument().setEdit('%s')",Sketch->getNameInDocument());
    }
}

bool CmdSketcherEditSketch::isActive(void)
{
    return Gui::Selection().countObjectsOfType(Sketcher::SketchObject::getClassTypeId()) == 1;
}

DEF_STD_CMD_A(CmdSketcherLeaveSketch)

CmdSketcherLeaveSketch::CmdSketcherLeaveSketch()
  : Command("Sketcher_LeaveSketch")
{
    sAppModule      = "Sketcher";
    sGroup          = QT_TR_NOOP("Sketcher");
    sMenuText       = QT_TR_NOOP("Leave sketch");
    sToolTipText    = QT_TR_NOOP("Finish editing the active sketch.");
    sWhatsThis      = "Sketcher_LeaveSketch";
    sStatusTip      = sToolTipText;
    sPixmap         = "Sketcher_LeaveSketch";
    eType           = 0;
}

void CmdSketcherLeaveSketch::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    Gui::Document *doc = getActiveGuiDocument();

    if (doc) {
        // checks if a Sketch Viewprovider is in Edit and is in no special mode
        SketcherGui::ViewProviderSketch* vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
        if (vp && vp->getSketchMode() != ViewProviderSketch::STATUS_NONE)
            vp->purgeHandler();
    }

    openCommand("Finish editting sketch");
    doCommand(Gui,"Gui.activeDocument().resetEdit()");
    doCommand(Doc,"App.ActiveDocument.recompute()");
    commitCommand();
}<commit_msg>Sketcher: [skip ci] remove superfluous transaction when start/finish editing a sketch<commit_after>/***************************************************************************
 *   Copyright (c) 2008 <NAME> <<EMAIL>>              *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/


#include "PreCompiled.h"
#ifndef _PreComp_
# include <TopoDS_Shape.hxx>
# include <TopoDS_Face.hxx>
# include <TopoDS.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <QApplication>
# include <QInputDialog>
# include <QMessageBox>
#endif

#include <App/DocumentObjectGroup.h>
#include <App/OriginFeature.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/CommandT.h>
#include <Gui/Control.h>
#include <Gui/MainWindow.h>
#include <Gui/DlgEditFileIncludePropertyExternal.h>
#include <Gui/SelectionFilter.h>

#include <Mod/Sketcher/App/SketchObjectSF.h>
#include <Mod/Sketcher/App/SketchObject.h>
#include <Mod/Part/App/Attacher.h>
#include <Mod/Part/App/Part2DObject.h>

#include "SketchOrientationDialog.h"
#include "SketchMirrorDialog.h"
#include "ViewProviderSketch.h"
#include "TaskSketcherValidation.h"
#include "../App/Constraint.h"

using namespace std;
using namespace SketcherGui;
using namespace Part;
using namespace Attacher;


namespace SketcherGui {

    class ExceptionWrongInput : public Base::Exception {
    public:
        ExceptionWrongInput()
            : ErrMsg(QString())
        {

        }

        //Pass untranslated strings, enclosed in QT_TR_NOOP()
        ExceptionWrongInput(const char* ErrMsg){
            this->ErrMsg = QObject::tr( ErrMsg );
            this->setMessage(ErrMsg);
        }

        virtual ~ExceptionWrongInput() throw() {}

        QString ErrMsg;
    };


    Attacher::eMapMode SuggestAutoMapMode(Attacher::SuggestResult::eSuggestResult* pMsgId = 0,
                                      QString* message = 0,
                                      std::vector<Attacher::eMapMode>* allmodes = 0){
        //convert pointers into valid references, to avoid checking for null pointers everywhere
        Attacher::SuggestResult::eSuggestResult buf;
        if (pMsgId == 0)
            pMsgId = &buf;
        Attacher::SuggestResult::eSuggestResult &msg = *pMsgId;
        QString buf2;
        if (message == 0)
            message = &buf2;
        QString &msg_str = *message;

        App::PropertyLinkSubList tmpSupport;
        Gui::Selection().getAsPropertyLinkSubList(tmpSupport);

        Attacher::SuggestResult sugr;
        AttachEngine3D eng;
        eng.setUp(tmpSupport);
        eng.suggestMapModes(sugr);
        if (allmodes)
            *allmodes = sugr.allApplicableModes;
        msg = sugr.message;
        switch(msg){
            case Attacher::SuggestResult::srOK:
            break;
            case Attacher::SuggestResult::srNoModesFit:
                msg_str = QObject::tr("There are no modes that accept the selected set of subelements");
            break;
            case Attacher::SuggestResult::srLinkBroken:
                msg_str = QObject::tr("Broken link to support subelements");
            break;
            case Attacher::SuggestResult::srUnexpectedError:
                msg_str = QObject::tr("Unexpected error");
            break;
            case Attacher::SuggestResult::srIncompatibleGeometry:
                if(tmpSupport.getSubValues()[0].substr(0,4) == std::string("Face"))
                    msg_str = QObject::tr("Face is non-planar");
                else
                    msg_str = QObject::tr("Selected shapes are of wrong form (e.g., a curved edge where a straight one is needed)");
            break;
            default:
                msg_str = QObject::tr("Unexpected error");
                assert(0/*no message for eSuggestResult enum item*/);
        }

        return sugr.bestFitMode;
    }
} //namespace SketcherGui


/* Sketch commands =======================================================*/
DEF_STD_CMD_A(CmdSketcherNewSketch)

CmdSketcherNewSketch::CmdSketcherNewSketch()
    :Command("Sketcher_NewSketch")
{
    sAppModule      = "Sketcher";
    sGroup          = QT_TR_NOOP("Sketcher");
    sMenuText       = QT_TR_NOOP("Create sketch");
    sToolTipText    = QT_TR_NOOP("Create a new sketch.");
    sWhatsThis      = "Sketcher_NewSketch";
    sStatusTip      = sToolTipText;
    sPixmap         = "Sketcher_NewSketch";
}

void CmdSketcherNewSketch::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    Attacher::eMapMode mapmode = Attacher::mmDeactivated;
    bool bAttach = false;
    if (Gui::Selection().hasSelection()){
        Attacher::SuggestResult::eSuggestResult msgid = Attacher::SuggestResult::srOK;
        QString msg_str;
        std::vector<Attacher::eMapMode> validModes;
        mapmode = SuggestAutoMapMode(&msgid, &msg_str, &validModes);
        if (msgid == Attacher::SuggestResult::srOK)
            bAttach = true;
        if (msgid != Attacher::SuggestResult::srOK && msgid != Attacher::SuggestResult::srNoModesFit){
            QMessageBox::warning(Gui::getMainWindow(),
                QObject::tr("Sketch mapping"),
                QObject::tr("Can't map the sketch to selected object. %1.").arg(msg_str));
            return;
        }
        if (validModes.size() > 1){
            validModes.insert(validModes.begin(), Attacher::mmDeactivated);
            bool ok;
            QStringList items;
            items.push_back(QObject::tr("Don't attach"));
            int iSugg = 0;//index of the auto-suggested mode in the list of valid modes
            for (size_t i = 0  ;  i < validModes.size()  ;  ++i){
                items.push_back(QString::fromLatin1(AttachEngine::getModeName(validModes[i]).c_str()));
                if (validModes[i] == mapmode)
                    iSugg = items.size()-1;
            }
            QString text = QInputDialog::getItem(Gui::getMainWindow(),
                qApp->translate("Sketcher_NewSketch", "Sketch attachment"),
                qApp->translate("Sketcher_NewSketch", "Select the method to attach this sketch to selected object"),
                items, iSugg, false, &ok);
            if (!ok) return;
            int index = items.indexOf(text);
            if (index == 0){
                bAttach = false;
                mapmode = Attacher::mmDeactivated;
            } else {
                bAttach = true;
                mapmode = validModes[index-1];
            }
        }
    }

    if (bAttach) {

        std::vector<Gui::SelectionObject> objects = Gui::Selection().getSelectionEx();
        //assert (objects.size() == 1); //should have been filtered out by SuggestAutoMapMode
        //Gui::SelectionObject &sel_support = objects[0];
        App::PropertyLinkSubList support;
        Gui::Selection().getAsPropertyLinkSubList(support);
        std::string supportString = support.getPyReprString();

        // create Sketch on Face
        std::string FeatName = getUniqueObjectName("Sketch");

        openCommand("Create a new sketch on a face");
        doCommand(Doc,"App.activeDocument().addObject('Sketcher::SketchObject', '%s')", FeatName.c_str());
        if (mapmode < Attacher::mmDummy_NumberOfModes)
            doCommand(Gui,"App.activeDocument().%s.MapMode = \"%s\"",FeatName.c_str(),AttachEngine::getModeName(mapmode).c_str());
        else
            assert(0 /* mapmode index out of range */);
        doCommand(Gui,"App.activeDocument().%s.Support = %s", FeatName.c_str(), supportString.c_str());
        doCommand(Gui,"App.activeDocument().recompute()");  // recompute the sketch placement based on its support
        doCommand(Gui,"Gui.activeDocument().setEdit('%s')", FeatName.c_str());

        Part::Feature *part = static_cast<Part::Feature*>(support.getValue());  // if multi-part support, this will return 0
        if (part){
            App::DocumentObjectGroup* grp = part->getGroup();
            if (grp) {
                doCommand(Doc,
                          "App.activeDocument().%s.addObject(App.activeDocument().%s)",
                          grp->getNameInDocument(), FeatName.c_str());
            }
        }
    }
    else {
        // ask user for orientation
        SketchOrientationDialog Dlg;

        if (Dlg.exec() != QDialog::Accepted)
            return; // canceled
        Base::Vector3d p = Dlg.Pos.getPosition();
        Base::Rotation r = Dlg.Pos.getRotation();

        std::string FeatName = getUniqueObjectName("Sketch");

        openCommand("Create a new sketch");
        doCommand(Doc, "App.activeDocument().addObject('Sketcher::SketchObject', '%s')", FeatName.c_str());
        doCommand(Doc,
                  "App.activeDocument().%s.Placement = App.Placement(App.Vector(%f, %f, %f), App.Rotation(%f, %f, %f, %f))",
                  FeatName.c_str(), p.x, p.y, p.z, r[0], r[1], r[2], r[3]);
        doCommand(Doc,"App.activeDocument().%s.MapMode = \"%s\"",
                  FeatName.c_str(), AttachEngine::getModeName(Attacher::mmDeactivated).c_str());
        doCommand(Gui,"Gui.activeDocument().setEdit('%s')", FeatName.c_str());
    }

}

bool CmdSketcherNewSketch::isActive(void)
{
    if (getActiveGuiDocument())
        return true;
    else
        return false;
}

DEF_STD_CMD_A(CmdSketcherEditSketch)

CmdSketcherEditSketch::CmdSketcherEditSketch()
    :Command("Sketcher_EditSketch")
{
    sAppModule      = "Sketcher";
    sGroup          = QT_TR_NOOP("Sketcher");
    sMenuText       = QT_TR_NOOP("Edit sketch");
    sToolTipText    = QT_TR_NOOP("Edit the selected sketch.");
    sWhatsThis      = "Sketcher_EditSketch";
    sStatusTip      = sToolTipText;
    sPixmap         = "Sketcher_EditSketch";
}

void CmdSketcherEditSketch::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    Gui::SelectionFilter SketchFilter("SELECT Sketcher::SketchObject COUNT 1");

    if (SketchFilter.match()) {
        Sketcher::SketchObject *Sketch = static_cast<Sketcher::SketchObject*>(SketchFilter.Result[0][0].getObject());
        doCommand(Gui,"Gui.activeDocument().setEdit('%s')",Sketch->getNameInDocument());
    }
}

bool CmdSketcherEditSketch::isActive(void)
{
    return Gui::Selection().countObjectsOfType(Sketcher::SketchObject::getClassTypeId()) == 1;
}

DEF_STD_CMD_A(CmdSketcherLeaveSketch)

CmdSketcherLeaveSketch::CmdSketcherLeaveSketch()
  : Command("Sketcher_LeaveSketch")
{
    sAppModule      = "Sketcher";
    sGroup          = QT_TR_NOOP("Sketcher");
    sMenuText       = QT_TR_NOOP("Leave sketch");
    sToolTipText    = QT_TR_NOOP("Finish editing the active sketch.");
    sWhatsThis      = "Sketcher_LeaveSketch";
    sStatusTip      = sToolTipText;
    sPixmap         = "Sketcher_LeaveSketch";
    eType           = 0;
}

void CmdSketcherLeaveSketch::activated(int iMsg)
{
    Q_UNUSED(iMsg);
    Gui::Document *doc = getActiveGuiDocument();

    if (doc) {
        // checks if a Sketch Viewprovider is in Edit and is in no special mode
        SketcherGui::ViewProviderSketch* vp = dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
        if (vp && vp->getSketchMode() != ViewProviderSketch::STATUS_NONE)
            vp->purgeHandler();
    }

    // See also TaskDlgEditSketch::reject
    doCommand(Gui,"Gui.activeDocument().resetEdit()");
    doCommand(Doc,"App.ActiveDocument.recompute()");
}
{'fraction_non_alphanumeric': 0.13398434411322843, 'fraction_numerical': 0.0042697873013362855, 'mean_word_length': 2.4182432432432432, 'pattern_counts': {'":': 0, '<': 65, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5607496', 'n_tokens_mistral': 7538, 'n_tokens_neox': 7232, 'n_words': 1527}