Sketcher: Snap: initial implementation: - creation of SnapManager class. - Move grid snap to this new class. - Add snap to object. - Add snap at angle.

This commit is contained in:
Paddle
2023-03-15 11:08:54 +01:00
committed by abdullahtahiriyo
parent 21c2eb6014
commit 0f274c2e07
10 changed files with 1526 additions and 73 deletions

View File

@@ -995,7 +995,7 @@ public:
updateCheckBox(checkbox, propvalue);
};
updateCheckBox(gridSnap, sketchView->getSnapMode() == SnapMode::SnapToGrid);
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
updateCheckBoxFromProperty(gridAutoSpacing, sketchView->GridAuto);
@@ -1005,10 +1005,6 @@ public:
void languageChange()
{
gridSnap->setText(tr("Grid Snap"));
gridSnap->setToolTip(tr("New points will snap to the nearest grid line.\nPoints must be set closer than a fifth of the grid spacing to a grid line to snap."));
gridSnap->setStatusTip(gridSnap->toolTip());
gridAutoSpacing->setText(tr("Grid Auto Spacing"));
gridAutoSpacing->setToolTip(tr("Resize grid automatically depending on zoom."));
gridAutoSpacing->setStatusTip(gridAutoSpacing->toolTip());
@@ -1020,8 +1016,6 @@ public:
protected:
QWidget* createWidget(QWidget* parent) override
{
gridSnap = new QCheckBox();
gridAutoSpacing = new QCheckBox();
sizeLabel = new QLabel();
@@ -1034,27 +1028,12 @@ protected:
QWidget* gridSizeW = new QWidget(parent);
auto* layout = new QGridLayout(gridSizeW);
layout->addWidget(gridSnap, 0, 0);
layout->addWidget(gridAutoSpacing, 1, 0);
layout->addWidget(sizeLabel, 2, 0);
layout->addWidget(gridSizeBox, 2, 1);
layout->addWidget(gridAutoSpacing, 0, 0, 1, 2);
layout->addWidget(sizeLabel, 1, 0);
layout->addWidget(gridSizeBox, 1, 1);
languageChange();
QObject::connect(gridSnap, &QCheckBox::stateChanged, [this](int state) {
auto* sketchView = getView();
if(sketchView) {
if(state == Qt::Checked) {
sketchView->setSnapMode(SnapMode::SnapToGrid);
}
else {
sketchView->setSnapMode(SnapMode::None);
}
}
});
QObject::connect(gridAutoSpacing, &QCheckBox::stateChanged, [this](int state) {
auto* sketchView = getView();
@@ -1086,7 +1065,6 @@ private:
}
private:
QCheckBox * gridSnap;
QCheckBox * gridAutoSpacing;
QLabel * sizeLabel;
Gui::QuantitySpinBox * gridSizeBox;
@@ -1213,6 +1191,250 @@ bool CmdSketcherGrid::isActive()
return false;
}
/* Snap tool */
class SnapSpaceAction : public QWidgetAction
{
public:
SnapSpaceAction(QObject* parent) : QWidgetAction(parent) {
setEnabled(false);
}
void updateWidget() {
auto* sketchView = getView();
if (sketchView) {
auto updateCheckBox = [](QCheckBox* checkbox, bool value) {
auto checked = checkbox->checkState() == Qt::Checked;
if (value != checked) {
const QSignalBlocker blocker(checkbox);
checkbox->setChecked(value);
}
};
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
updateCheckBox(snapToObjects, hGrp->GetBool("SnapToObjects", true));
updateCheckBox(snapToGrid, hGrp->GetBool("SnapToGrid", false));
snapAngle->setValue(hGrp->GetFloat("SnapAngle", 5.0));
bool snapActivated = hGrp->GetBool("Snap", true);
snapToObjects->setEnabled(snapActivated);
snapToGrid->setEnabled(snapActivated);
angleLabel->setEnabled(snapActivated);
snapAngle->setEnabled(snapActivated);
}
}
void languageChange()
{
snapToObjects->setText(tr("Snap to objects"));
snapToObjects->setToolTip(tr("New points will snap to the currently preselected object. It will also snap to the middle of lines and arcs."));
snapToObjects->setStatusTip(snapToObjects->toolTip());
snapToGrid->setText(tr("Snap to Grid"));
snapToGrid->setToolTip(tr("New points will snap to the nearest grid line.\nPoints must be set closer than a fifth of the grid spacing to a grid line to snap."));
snapToGrid->setStatusTip(snapToGrid->toolTip());
angleLabel->setText(tr("Snap angle"));
snapAngle->setToolTip(tr("Angular step for tools that use 'Snap at Angle' (line for instance). Hold CTRL to enable 'Snap at Angle'. The angle start from the East axis (horizontal right)"));
}
protected:
QWidget* createWidget(QWidget* parent) override
{
snapToObjects = new QCheckBox();
snapToGrid = new QCheckBox();
angleLabel = new QLabel();
snapAngle = new Gui::QuantitySpinBox();
snapAngle->setProperty("unit", QVariant(QStringLiteral("deg")));
snapAngle->setObjectName(QStringLiteral("snapAngle"));
snapAngle->setMaximum(99999999.0);
snapAngle->setMinimum(0);
QWidget* snapW = new QWidget(parent);
auto* layout = new QGridLayout(snapW);
layout->addWidget(snapToGrid, 0, 0, 1, 2);
layout->addWidget(snapToObjects, 1, 0, 1, 2);
layout->addWidget(angleLabel, 2, 0);
layout->addWidget(snapAngle, 2, 1);
languageChange();
QObject::connect(snapToObjects, &QCheckBox::stateChanged, [this](int state) {
auto* sketchView = getView();
if (sketchView) {
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
hGrp->SetBool("SnapToObjects", state == Qt::Checked);
}
});
QObject::connect(snapToGrid, &QCheckBox::stateChanged, [this](int state) {
auto* sketchView = getView();
if (sketchView) {
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
hGrp->SetBool("SnapToGrid", state == Qt::Checked);
}
});
QObject::connect(snapAngle, qOverload<double>(&Gui::QuantitySpinBox::valueChanged), [this](double val) {
auto* sketchView = getView();
if (sketchView) {
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
hGrp->SetFloat("SnapAngle", val);
}
});
return snapW;
}
private:
ViewProviderSketch* getView() {
Gui::Document* doc = Gui::Application::Instance->activeDocument();
if (doc) {
return dynamic_cast<SketcherGui::ViewProviderSketch*>(doc->getInEdit());
}
return nullptr;
}
private:
QCheckBox* snapToObjects;
QCheckBox* snapToGrid;
QLabel* angleLabel;
Gui::QuantitySpinBox* snapAngle;
};
class CmdSketcherSnap : public Gui::Command
{
public:
CmdSketcherSnap();
virtual ~CmdSketcherSnap() {}
virtual const char* className() const
{
return "CmdSketcherSnap";
}
virtual void languageChange();
protected:
virtual void activated(int iMsg);
virtual bool isActive(void);
virtual Gui::Action* createAction(void);
private:
void updateIcon(bool value);
CmdSketcherSnap(const CmdSketcherSnap&) = delete;
CmdSketcherSnap(CmdSketcherSnap&&) = delete;
CmdSketcherSnap& operator= (const CmdSketcherSnap&) = delete;
CmdSketcherSnap& operator= (CmdSketcherSnap&&) = delete;
};
CmdSketcherSnap::CmdSketcherSnap()
: Command("Sketcher_Snap")
{
sAppModule = "Sketcher";
sGroup = "Sketcher";
sMenuText = QT_TR_NOOP("Toggle Snap");
sToolTipText = QT_TR_NOOP("Toggle all snapping functionalities. In the menu you can toggle individually 'Snap to Grid', 'Snap to Objects' and further snap settings");
sWhatsThis = "Sketcher_Snap";
sStatusTip = sToolTipText;
eType = 0;
}
void CmdSketcherSnap::updateIcon(bool value)
{
static QIcon active = Gui::BitmapFactory().iconFromTheme("Sketcher_Snap");
static QIcon inactive = Gui::BitmapFactory().iconFromTheme("Sketcher_Snap_Deactivated");
auto* pcAction = qobject_cast<Gui::ActionGroup*>(getAction());
pcAction->setIcon(value ? active : inactive);
}
void CmdSketcherSnap::activated(int iMsg)
{
Q_UNUSED(iMsg);
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
bool value = !hGrp->GetBool("Snap", true);
hGrp->SetBool("Snap", value);
updateIcon(value);
//Update the widget :
if (!_pcAction)
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
auto* ssa = static_cast<SnapSpaceAction*>(a[0]);
ssa->updateWidget();
}
Gui::Action* CmdSketcherSnap::createAction()
{
auto* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow());
pcAction->setDropDownMenu(true);
pcAction->setExclusive(false);
applyCommandData(this->className(), pcAction);
SnapSpaceAction* ssa = new SnapSpaceAction(pcAction);
pcAction->addAction(ssa);
_pcAction = pcAction;
QObject::connect(pcAction, &Gui::ActionGroup::aboutToShow, [ssa](QMenu* menu) {
Q_UNUSED(menu)
ssa->updateWidget();
});
// set the right pixmap
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
updateIcon(hGrp->GetBool("Snap", true));
return pcAction;
}
void CmdSketcherSnap::languageChange()
{
Command::languageChange();
if (!_pcAction)
return;
Gui::ActionGroup* pcAction = qobject_cast<Gui::ActionGroup*>(_pcAction);
QList<QAction*> a = pcAction->actions();
auto* ssa = static_cast<SnapSpaceAction*>(a[0]);
ssa->languageChange();
}
bool CmdSketcherSnap::isActive()
{
auto* vp = getInactiveHandlerEditModeSketchViewProvider();
if (vp) {
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
bool value = hGrp->GetBool("Snap", true);
updateIcon(value);
return true;
}
return false;
}
void CreateSketcherCommands()
{
@@ -1230,4 +1452,5 @@ void CreateSketcherCommands()
rcCmdMgr.addCommand(new CmdSketcherMergeSketches());
rcCmdMgr.addCommand(new CmdSketcherViewSection());
rcCmdMgr.addCommand(new CmdSketcherGrid());
rcCmdMgr.addCommand(new CmdSketcherSnap());
}