From ccb28af4a1fc8c94376db1375e13f3444ec34d88 Mon Sep 17 00:00:00 2001 From: paddle Date: Sat, 26 Jul 2025 09:25:55 +0200 Subject: [PATCH] Sketcher: Rename "Solver messages" to "Sketch edit". Add setting button to the solver message box. In which there're grid, snap and ordering widgets. --- src/Gui/Stylesheets/FreeCAD Dark.qss | 3 +- src/Gui/Stylesheets/FreeCAD Light.qss | 3 +- src/Mod/Sketcher/Gui/CMakeLists.txt | 1 + src/Mod/Sketcher/Gui/Command.cpp | 564 +++++++++--------- src/Mod/Sketcher/Gui/Command.h | 120 ++++ src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp | 65 +- src/Mod/Sketcher/Gui/TaskSketcherMessages.h | 1 + src/Mod/Sketcher/Gui/TaskSketcherMessages.ui | 26 + 8 files changed, 483 insertions(+), 300 deletions(-) create mode 100644 src/Mod/Sketcher/Gui/Command.h diff --git a/src/Gui/Stylesheets/FreeCAD Dark.qss b/src/Gui/Stylesheets/FreeCAD Dark.qss index c4a218fc48..7ab8f572b0 100644 --- a/src/Gui/Stylesheets/FreeCAD Dark.qss +++ b/src/Gui/Stylesheets/FreeCAD Dark.qss @@ -1715,8 +1715,7 @@ QSint--ActionGroup QToolButton::menu-button { } QSint--ActionGroup QToolButton#settingsButton, -QSint--ActionGroup QToolButton#filterButton, -QSint--ActionGroup QToolButton#manualUpdate { +QSint--ActionGroup QToolButton#filterButton { padding-right: 20px; /* make way for the popup button */ } diff --git a/src/Gui/Stylesheets/FreeCAD Light.qss b/src/Gui/Stylesheets/FreeCAD Light.qss index 3b7f794a78..e2e16c1399 100644 --- a/src/Gui/Stylesheets/FreeCAD Light.qss +++ b/src/Gui/Stylesheets/FreeCAD Light.qss @@ -1713,8 +1713,7 @@ QSint--ActionGroup QToolButton::menu-button { } QSint--ActionGroup QToolButton#settingsButton, -QSint--ActionGroup QToolButton#filterButton, -QSint--ActionGroup QToolButton#manualUpdate { +QSint--ActionGroup QToolButton#filterButton { padding-right: 20px; /* make way for the popup button */ } diff --git a/src/Mod/Sketcher/Gui/CMakeLists.txt b/src/Mod/Sketcher/Gui/CMakeLists.txt index 2161d4f545..2bc6acc834 100644 --- a/src/Mod/Sketcher/Gui/CMakeLists.txt +++ b/src/Mod/Sketcher/Gui/CMakeLists.txt @@ -42,6 +42,7 @@ SET(SketcherGui_SRCS ${SketcherGui_UIC_HDRS} AppSketcherGui.cpp GeometryCreationMode.h + Command.h Command.cpp AutoConstraint.h Utils.h diff --git a/src/Mod/Sketcher/Gui/Command.cpp b/src/Mod/Sketcher/Gui/Command.cpp index 36929ba8cc..188ee31309 100644 --- a/src/Mod/Sketcher/Gui/Command.cpp +++ b/src/Mod/Sketcher/Gui/Command.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ #include "TaskSketcherValidation.h" #include "Utils.h" #include "ViewProviderSketch.h" +#include "Command.h" // Hint: this is to prevent to re-format big parts of the file. Remove it later again. // clang-format off @@ -1129,118 +1131,155 @@ bool CmdSketcherViewSection::isActive() } /* Grid tool */ -class GridSpaceAction: public QWidgetAction +GridSpaceAction::GridSpaceAction(QObject* parent) + : QWidgetAction(parent) { - Q_DECLARE_TR_FUNCTIONS(GridSpaceAction) -public: - GridSpaceAction(QObject* parent) - : QWidgetAction(parent) - { - setEnabled(false); + setEnabled(false); +} + +void GridSpaceAction::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); + } + }; + + auto updateCheckBoxFromProperty = [updateCheckBox](QCheckBox* checkbox, + App::PropertyBool& property) { + auto propvalue = property.getValue(); + + updateCheckBox(checkbox, propvalue); + }; + + updateCheckBoxFromProperty(gridShow, sketchView->ShowGrid); + + updateCheckBoxFromProperty(gridAutoSpacing, sketchView->GridAuto); + + ParameterGrp::handle hGrp = getParameterPath(); + updateCheckBox(snapToGrid, hGrp->GetBool("SnapToGrid", false)); + + gridSizeBox->setValue(sketchView->GridSize.getValue()); } +} - void updateWidget() - { +void GridSpaceAction::languageChange() +{ + gridShow->setText(tr("Display grid")); + gridShow->setToolTip(tr("Toggles the visibility of the grid in the active sketch")); + gridShow->setStatusTip(gridAutoSpacing->toolTip()); + gridAutoSpacing->setText(tr("Grid auto-spacing")); + gridAutoSpacing->setToolTip(tr("Automatically adjusts the grid spacing based on the zoom level")); + gridAutoSpacing->setStatusTip(gridAutoSpacing->toolTip()); + + sizeLabel->setText(tr("Spacing")); + gridSizeBox->setToolTip(tr("Distance between two subsequent grid lines")); + + 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()); +} + +QWidget* GridSpaceAction::createWidget(QWidget* parent) +{ + gridShow = new QCheckBox(); + + gridAutoSpacing = new QCheckBox(); + + snapToGrid = new QCheckBox(); + + sizeLabel = new QLabel(); + + gridSizeBox = new Gui::QuantitySpinBox(); + gridSizeBox->setProperty("unit", QVariant(QStringLiteral("mm"))); + gridSizeBox->setObjectName(QStringLiteral("gridSize")); + gridSizeBox->setMaximum(99999999.0); + gridSizeBox->setMinimum(0.001); + + QWidget* gridSizeW = new QWidget(parent); + auto* layout = new QGridLayout(gridSizeW); + layout->addWidget(gridShow, 0, 0, 1, 2); + layout->addWidget(gridAutoSpacing, 1, 0, 1, 2); + layout->addWidget(snapToGrid, 2, 0, 1, 2); + layout->addWidget(sizeLabel, 3, 0); + layout->addWidget(gridSizeBox, 3, 1); + + languageChange(); + +#if QT_VERSION >= QT_VERSION_CHECK(6,7,0) + QObject::connect(gridShow, &QCheckBox::checkStateChanged, [this](int state) { +#else + QObject::connect(gridShow, &QCheckBox::stateChanged, [this](int state) { +#endif 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); - } - }; - - auto updateCheckBoxFromProperty = [updateCheckBox](QCheckBox* checkbox, - App::PropertyBool& property) { - auto propvalue = property.getValue(); - - updateCheckBox(checkbox, propvalue); - }; - - updateCheckBoxFromProperty(gridAutoSpacing, sketchView->GridAuto); - - gridSizeBox->setValue(sketchView->GridSize.getValue()); + auto enable = (state == Qt::Checked); + sketchView->ShowGrid.setValue(enable); } - } - - void languageChange() - { - gridAutoSpacing->setText(tr("Grid auto spacing")); - gridAutoSpacing->setToolTip(tr("Automatically adjusts the grid spacing based on the zoom level")); - gridAutoSpacing->setStatusTip(gridAutoSpacing->toolTip()); - - sizeLabel->setText(tr("Spacing")); - gridSizeBox->setToolTip(tr("Distance between two subsequent grid lines")); - } - -protected: - QWidget* createWidget(QWidget* parent) override - { - gridAutoSpacing = new QCheckBox(); - - sizeLabel = new QLabel(); - - gridSizeBox = new Gui::QuantitySpinBox(); - gridSizeBox->setProperty("unit", QVariant(QStringLiteral("mm"))); - gridSizeBox->setObjectName(QStringLiteral("gridSize")); - gridSizeBox->setMaximum(99999999.0); - gridSizeBox->setMinimum(0.001); - - QWidget* gridSizeW = new QWidget(parent); - auto* layout = new QGridLayout(gridSizeW); - layout->addWidget(gridAutoSpacing, 0, 0, 1, 2); - layout->addWidget(sizeLabel, 1, 0); - layout->addWidget(gridSizeBox, 1, 1); - - languageChange(); + }); #if QT_VERSION >= QT_VERSION_CHECK(6,7,0) - QObject::connect(gridAutoSpacing, &QCheckBox::checkStateChanged, [this](int state) { + QObject::connect(gridAutoSpacing, &QCheckBox::checkStateChanged, [this](int state) { #else - QObject::connect(gridAutoSpacing, &QCheckBox::stateChanged, [this](int state) { + QObject::connect(gridAutoSpacing, &QCheckBox::stateChanged, [this](int state) { #endif - auto* sketchView = getView(); + auto* sketchView = getView(); - if (sketchView) { - auto enable = (state == Qt::Checked); - sketchView->GridAuto.setValue(enable); - } - }); - - QObject::connect(gridSizeBox, - qOverload(&Gui::QuantitySpinBox::valueChanged), - [this](double val) { - auto* sketchView = getView(); - if (sketchView) { - sketchView->GridSize.setValue(val); - } - }); - - return gridSizeW; - } - -private: - ViewProviderSketch* getView() - { - Gui::Document* doc = Gui::Application::Instance->activeDocument(); - - if (doc) { - return dynamic_cast(doc->getInEdit()); + if (sketchView) { + auto enable = (state == Qt::Checked); + sketchView->GridAuto.setValue(enable); } + }); - return nullptr; +#if QT_VERSION >= QT_VERSION_CHECK(6,7,0) + QObject::connect(snapToGrid, &QCheckBox::checkStateChanged, [this](int state) { +#else + QObject::connect(snapToGrid, &QCheckBox::stateChanged, [this](int state) { +#endif + ParameterGrp::handle hGrp = this->getParameterPath(); + hGrp->SetBool("SnapToGrid", state == Qt::Checked); + }); + + QObject::connect(gridSizeBox, + qOverload(&Gui::QuantitySpinBox::valueChanged), + [this](double val) { + auto* sketchView = getView(); + if (sketchView) { + sketchView->GridSize.setValue(val); + } + }); + + return gridSizeW; +} + +ViewProviderSketch* GridSpaceAction::getView() +{ + Gui::Document* doc = Gui::Application::Instance->activeDocument(); + + if (doc) { + return dynamic_cast(doc->getInEdit()); + } + + return nullptr; +} + +ParameterGrp::handle GridSpaceAction::getParameterPath() + { + return App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Sketcher/Snap"); } -private: - QCheckBox* gridAutoSpacing; - QLabel* sizeLabel; - Gui::QuantitySpinBox* gridSizeBox; -}; class CmdSketcherGrid: public Gui::Command { @@ -1371,133 +1410,101 @@ bool CmdSketcherGrid::isActive() } /* Snap tool */ -class SnapSpaceAction: public QWidgetAction -{ - Q_DECLARE_TR_FUNCTIONS(SnapSpaceAction) -public: - SnapSpaceAction(QObject* parent) +SnapSpaceAction::SnapSpaceAction(QObject* parent) : QWidgetAction(parent) { setEnabled(false); } - void updateWidget(bool snapenabled) - { +void SnapSpaceAction::updateWidget(bool snapenabled) +{ - auto updateCheckBox = [](QCheckBox* checkbox, bool value) { - auto checked = checkbox->checkState() == Qt::Checked; + auto updateCheckBox = [](QCheckBox* checkbox, bool value) { + auto checked = checkbox->checkState() == Qt::Checked; - if (value != checked) { - const QSignalBlocker blocker(checkbox); - checkbox->setChecked(value); - } - }; + if (value != checked) { + const QSignalBlocker blocker(checkbox); + checkbox->setChecked(value); + } + }; - auto updateSpinBox = [](Gui::QuantitySpinBox* spinbox, double value) { - auto currentvalue = spinbox->rawValue(); + auto updateSpinBox = [](Gui::QuantitySpinBox* spinbox, double value) { + auto currentvalue = spinbox->rawValue(); - if (currentvalue != value) { - const QSignalBlocker blocker(spinbox); - spinbox->setValue(value); - } - }; + if (currentvalue != value) { + const QSignalBlocker blocker(spinbox); + spinbox->setValue(value); + } + }; - ParameterGrp::handle hGrp = getParameterPath(); + ParameterGrp::handle hGrp = getParameterPath(); - updateCheckBox(snapToObjects, hGrp->GetBool("SnapToObjects", true)); + updateCheckBox(snapToObjects, hGrp->GetBool("SnapToObjects", true)); - updateCheckBox(snapToGrid, hGrp->GetBool("SnapToGrid", false)); + updateSpinBox(snapAngle, hGrp->GetFloat("SnapAngle", 5.0)); - updateSpinBox(snapAngle, hGrp->GetFloat("SnapAngle", 5.0)); + snapToObjects->setEnabled(snapenabled); + angleLabel->setEnabled(snapenabled); + snapAngle->setEnabled(snapenabled); +} - snapToObjects->setEnabled(snapenabled); - snapToGrid->setEnabled(snapenabled); - angleLabel->setEnabled(snapenabled); - snapAngle->setEnabled(snapenabled); - } +void SnapSpaceAction::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()); - 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()); + angleLabel->setText(tr("Snap angle")); + snapAngle->setToolTip( + tr("Angular step for tools that use 'Snap at angle'. Hold Ctrl to " + "enable 'Snap at angle'. The angle starts from the positive X axis of the sketch.")); +} - 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()); +QWidget* SnapSpaceAction::createWidget(QWidget* parent) +{ + snapToObjects = new QCheckBox(); - angleLabel->setText(tr("Snap angle")); - snapAngle->setToolTip( - tr("Sets the angular step for tools using 'Snap at angle' (e.g., line). Hold Ctrl to " - "enable 'Snap at angle'. The angle starts from the positive X-axis of the sketch.")); - } + angleLabel = new QLabel(); -protected: - QWidget* createWidget(QWidget* parent) override - { - snapToObjects = new QCheckBox(); + snapAngle = new Gui::QuantitySpinBox(); + snapAngle->setProperty("unit", QVariant(QStringLiteral("deg"))); + snapAngle->setObjectName(QStringLiteral("snapAngle")); + snapAngle->setMaximum(99999999.0); + snapAngle->setMinimum(0); - 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(); + QWidget* snapW = new QWidget(parent); + auto* layout = new QGridLayout(snapW); + layout->addWidget(snapToObjects, 0, 0, 1, 2); + layout->addWidget(angleLabel, 1, 0); + layout->addWidget(snapAngle, 1, 1); + languageChange(); + #if QT_VERSION >= QT_VERSION_CHECK(6,7,0) - QObject::connect(snapToObjects, &QCheckBox::checkStateChanged, [this](int state) { + QObject::connect(snapToObjects, &QCheckBox::checkStateChanged, [this](int state) { #else - QObject::connect(snapToObjects, &QCheckBox::stateChanged, [this](int state) { + QObject::connect(snapToObjects, &QCheckBox::stateChanged, [this](int state) { #endif + ParameterGrp::handle hGrp = this->getParameterPath(); + hGrp->SetBool("SnapToObjects", state == Qt::Checked); + }); + + QObject::connect( + snapAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), [this](double val) { ParameterGrp::handle hGrp = this->getParameterPath(); - hGrp->SetBool("SnapToObjects", state == Qt::Checked); - }); -#if QT_VERSION >= QT_VERSION_CHECK(6,7,0) - QObject::connect(snapToGrid, &QCheckBox::checkStateChanged, [this](int state) { -#else - QObject::connect(snapToGrid, &QCheckBox::stateChanged, [this](int state) { -#endif - ParameterGrp::handle hGrp = this->getParameterPath(); - hGrp->SetBool("SnapToGrid", state == Qt::Checked); + hGrp->SetFloat("SnapAngle", val); }); - QObject::connect( - snapAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), [this](double val) { - ParameterGrp::handle hGrp = this->getParameterPath(); - hGrp->SetFloat("SnapAngle", val); - }); + return snapW; +} - return snapW; - } +ParameterGrp::handle SnapSpaceAction::getParameterPath() +{ + return App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Sketcher/Snap"); +} -private: - ParameterGrp::handle getParameterPath() - { - return App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Sketcher/Snap"); - } - -private: - QCheckBox* snapToObjects; - QCheckBox* snapToGrid; - QLabel* angleLabel; - Gui::QuantitySpinBox* snapAngle; -}; class CmdSketcherSnap: public Gui::Command, public ParameterGrp::ObserverType { @@ -1646,111 +1653,113 @@ bool CmdSketcherSnap::isActive() /* Rendering Order */ -class RenderingOrderAction: public QWidgetAction -{ - Q_DECLARE_TR_FUNCTIONS(RenderingOrderAction) -public: - RenderingOrderAction(QObject* parent) +RenderingOrderAction::RenderingOrderAction(QObject* parent) : QWidgetAction(parent) - { - setEnabled(false); - } +{ + setEnabled(false); +} - void updateWidget() - { +void RenderingOrderAction::updateWidget() +{ + auto hGrp = getParameterPath(); - auto hGrp = getParameterPath(); + // 1->Normal Geometry, 2->Construction, 3->External + int topid = hGrp->GetInt("TopRenderGeometryId", 1); + int midid = hGrp->GetInt("MidRenderGeometryId", 2); + int lowid = hGrp->GetInt("LowRenderGeometryId", 3); - // 1->Normal Geometry, 2->Construction, 3->External - int topid = hGrp->GetInt("TopRenderGeometryId", 1); - int midid = hGrp->GetInt("MidRenderGeometryId", 2); - int lowid = hGrp->GetInt("LowRenderGeometryId", 3); - - { - QSignalBlocker block(this); - list->clear(); - - QListWidgetItem* newItem = new QListWidgetItem; - newItem->setData(Qt::UserRole, QVariant(topid)); - newItem->setText(topid == 1 ? tr("Normal Geometry") - : topid == 2 ? tr("Construction Geometry") - : tr("External Geometry")); - list->insertItem(0, newItem); - - newItem = new QListWidgetItem; - newItem->setData(Qt::UserRole, QVariant(midid)); - newItem->setText(midid == 1 ? tr("Normal Geometry") - : midid == 2 ? tr("Construction Geometry") - : tr("External Geometry")); - list->insertItem(1, newItem); - - newItem = new QListWidgetItem; - newItem->setData(Qt::UserRole, QVariant(lowid)); - newItem->setText(lowid == 1 ? tr("Normal Geometry") - : lowid == 2 ? tr("Construction Geometry") - : tr("External Geometry")); - list->insertItem(2, newItem); + auto idToText = [this](int id) -> QString { + switch (id) { + case 1: + return tr("Normal geometry"); + case 2: + return tr("Construction geometry"); + case 3: + return tr("External geometry"); + default: + // Fallback for an unexpected ID + return tr("Unknown geometry"); } - } + }; - void languageChange() { - updateWidget(); + QSignalBlocker block(this); + list->clear(); + + QListWidgetItem* itemTop = new QListWidgetItem; + itemTop->setData(Qt::UserRole, QVariant(topid)); + itemTop->setText(idToText(topid)); + list->insertItem(0, itemTop); + + QListWidgetItem* itemMid = new QListWidgetItem; + itemMid->setData(Qt::UserRole, QVariant(midid)); + itemMid->setText(idToText(midid)); + list->insertItem(1, itemMid); + + QListWidgetItem* itemLow = new QListWidgetItem; + itemLow->setData(Qt::UserRole, QVariant(lowid)); + itemLow->setText(idToText(lowid)); + list->insertItem(2, itemLow); } +} -protected: - QWidget* createWidget(QWidget* parent) override - { - list = new QListWidget(); - list->setDragDropMode(QAbstractItemView::InternalMove); - list->setDefaultDropAction(Qt::MoveAction); - list->setSelectionMode(QAbstractItemView::SingleSelection); - list->setDragEnabled(true); +void RenderingOrderAction::languageChange() +{ + updateWidget(); +} - QWidget* renderingWidget = new QWidget(parent); - auto* layout = new QGridLayout(renderingWidget); - layout->addWidget(list, 0, 0, 0, 0); +QWidget* RenderingOrderAction::createWidget(QWidget* parent) +{ + list = new QListWidget(); + list->setDragDropMode(QAbstractItemView::InternalMove); + list->setDefaultDropAction(Qt::MoveAction); + list->setSelectionMode(QAbstractItemView::SingleSelection); + list->setDragEnabled(true); + list->setFixedSize(200, 50); - languageChange(); - // Handle change in the order of the list entries - QObject::connect(list->model(), - &QAbstractItemModel::rowsMoved, - [this](const QModelIndex& sourceParent, - int sourceStart, - int sourceEnd, - const QModelIndex& destinationParent, - int destinationRow) { - Q_UNUSED(sourceParent) - Q_UNUSED(sourceStart) - Q_UNUSED(sourceEnd) - Q_UNUSED(destinationParent) - Q_UNUSED(destinationRow) + QWidget* renderingWidget = new QWidget(parent); + auto* label = new QLabel(tr("Rendering order"), renderingWidget); + auto* layout = new QVBoxLayout(renderingWidget); + layout->addWidget(label); + layout->addWidget(list); - int topid = list->item(0)->data(Qt::UserRole).toInt(); - int midid = list->item(1)->data(Qt::UserRole).toInt(); - int lowid = list->item(2)->data(Qt::UserRole).toInt(); + languageChange(); - auto hGrp = getParameterPath(); + // Handle change in the order of the list entries + QObject::connect(list->model(), + &QAbstractItemModel::rowsMoved, + [this](const QModelIndex& sourceParent, + int sourceStart, + int sourceEnd, + const QModelIndex& destinationParent, + int destinationRow) { + Q_UNUSED(sourceParent) + Q_UNUSED(sourceStart) + Q_UNUSED(sourceEnd) + Q_UNUSED(destinationParent) + Q_UNUSED(destinationRow) - hGrp->SetInt("TopRenderGeometryId", topid); - hGrp->SetInt("MidRenderGeometryId", midid); - hGrp->SetInt("LowRenderGeometryId", lowid); - }); + int topid = list->item(0)->data(Qt::UserRole).toInt(); + int midid = list->item(1)->data(Qt::UserRole).toInt(); + int lowid = list->item(2)->data(Qt::UserRole).toInt(); - return renderingWidget; - } + auto hGrp = getParameterPath(); -private: - ParameterGrp::handle getParameterPath() + hGrp->SetInt("TopRenderGeometryId", topid); + hGrp->SetInt("MidRenderGeometryId", midid); + hGrp->SetInt("LowRenderGeometryId", lowid); + }); + + return renderingWidget; +} + +ParameterGrp::handle RenderingOrderAction::getParameterPath() { return App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Sketcher/General"); } -private: - QListWidget* list; -}; class CmdRenderingOrder: public Gui::Command, public ParameterGrp::ObserverType { @@ -1916,3 +1925,4 @@ void CreateSketcherCommands() rcCmdMgr.addCommand(new CmdRenderingOrder()); } // clang-format on + diff --git a/src/Mod/Sketcher/Gui/Command.h b/src/Mod/Sketcher/Gui/Command.h new file mode 100644 index 0000000000..6074e70570 --- /dev/null +++ b/src/Mod/Sketcher/Gui/Command.h @@ -0,0 +1,120 @@ +/*************************************************************************** + * Copyright (c) 2025 Boyer Pierre-Louis * + * * + * 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 * + * * + ***************************************************************************/ + + +#ifndef SKETCHERGUI_CommandConstraints_H +#define SKETCHERGUI_CommandConstraints_H + +#include +#include + +#include + +class QCheckBox; +class QLabel; +class QWidget; +class QObject; +class QListWidget; + +namespace Gui +{ +class Command; +class QuantitySpinBox; +} // namespace Gui + +namespace SketcherGui +{ + +class ViewProviderSketch; + +class GridSpaceAction: public QWidgetAction +{ + Q_DECLARE_TR_FUNCTIONS(SketcherGui::GridSpaceAction) +public: + GridSpaceAction(QObject* parent); + + void updateWidget(); + + void languageChange(); + +protected: + QWidget* createWidget(QWidget* parent) override; + +private: + ViewProviderSketch* getView(); + + ParameterGrp::handle getParameterPath(); + +private: + QCheckBox* gridShow; + QCheckBox* gridAutoSpacing; + QCheckBox* snapToGrid; + QLabel* sizeLabel; + Gui::QuantitySpinBox* gridSizeBox; +}; + + +class SnapSpaceAction: public QWidgetAction +{ + Q_DECLARE_TR_FUNCTIONS(SketcherGui::SnapSpaceAction) +public: + SnapSpaceAction(QObject* parent); + + void updateWidget(bool snapenabled); + + void languageChange(); + +protected: + QWidget* createWidget(QWidget* parent) override; + +private: + ParameterGrp::handle getParameterPath(); + +private: + QCheckBox* snapToObjects; + QLabel* angleLabel; + Gui::QuantitySpinBox* snapAngle; +}; + + +class RenderingOrderAction: public QWidgetAction +{ + Q_DECLARE_TR_FUNCTIONS(SketcherGui::RenderingOrderAction) +public: + RenderingOrderAction(QObject* parent); + + void updateWidget(); + + void languageChange(); + +protected: + QWidget* createWidget(QWidget* parent) override; + +private: + ParameterGrp::handle getParameterPath(); + +private: + QListWidget* list; +}; + +} // namespace SketcherGui +#endif // SKETCHERGUI_Command_H diff --git a/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp b/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp index ad0d03a09a..fb408042eb 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp +++ b/src/Mod/Sketcher/Gui/TaskSketcherMessages.cpp @@ -23,6 +23,7 @@ #include "PreCompiled.h" #ifndef _PreComp_ #include +#include #endif #include @@ -30,6 +31,7 @@ #include #include +#include "Command.h" #include "TaskSketcherMessages.h" #include "ViewProviderSketch.h" #include "ui_TaskSketcherMessages.h" @@ -41,7 +43,7 @@ using namespace Gui::TaskView; namespace sp = std::placeholders; TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch* sketchView) - : TaskBox(Gui::BitmapFactory().pixmap("Sketcher_Sketch"), tr("Solver Messages"), true, nullptr) + : TaskBox(Gui::BitmapFactory().pixmap("Sketcher_Sketch"), tr("Sketch Edit"), true, nullptr) , sketchView(sketchView) , ui(new Ui_TaskSketcherMessages) { @@ -89,23 +91,7 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch* sketchView) ui->labelConstrainStatusLink->setLaunchExternal(false); - // Set Auto Update in the 'Manual Update' button menu. - ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( - "User parameter:BaseApp/Preferences/Mod/Sketcher"); - bool state = hGrp->GetBool("AutoRecompute", false); - - sketchView->getSketchObject()->noRecomputes = !state; - - QAction* action = new QAction(tr("Auto-update"), this); - action->setToolTip(tr("Executes a recomputation of active document after every sketch action")); - action->setCheckable(true); - action->setChecked(state); - ui->manualUpdate->addAction(action); - - QObject::connect(std::as_const(ui->manualUpdate)->actions()[0], - &QAction::changed, - this, - &TaskSketcherMessages::onAutoUpdateStateChanged); + createSettingsButtonActions(); } TaskSketcherMessages::~TaskSketcherMessages() @@ -175,7 +161,7 @@ void TaskSketcherMessages::onLabelConstrainStatusLinkClicked(const QString& str) void TaskSketcherMessages::onAutoUpdateStateChanged() { - bool state = std::as_const(ui->manualUpdate)->actions()[0]->isChecked(); + bool state = std::as_const(ui->settingsButton)->actions()[0]->isChecked(); ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( "User parameter:BaseApp/Preferences/Mod/Sketcher"); @@ -189,5 +175,46 @@ void TaskSketcherMessages::onManualUpdateClicked(bool checked) Gui::Command::updateActive(); } +void TaskSketcherMessages::createSettingsButtonActions() +{ + // Set Auto Update in the 'Manual Update' button menu. + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath( + "User parameter:BaseApp/Preferences/Mod/Sketcher"); + bool state = hGrp->GetBool("AutoRecompute", false); + + sketchView->getSketchObject()->noRecomputes = !state; + QAction* action = new QAction(tr("Auto-update"), this); + action->setToolTip(tr("Executes a recomputation of active document after every sketch action")); + action->setCheckable(true); + action->setChecked(state); + + + auto* gsa = new GridSpaceAction(this); + auto* ssa = new SnapSpaceAction(this); + auto* roa = new RenderingOrderAction(this); + + QMenu* myMenu = new QMenu(this); + myMenu->addAction(action); + myMenu->addSeparator(); + myMenu->addAction(gsa); + myMenu->addSeparator(); + myMenu->addAction(ssa); + myMenu->addSeparator(); + myMenu->addAction(roa); + ui->settingsButton->setMenu(myMenu); + + QObject::connect(myMenu, &QMenu::aboutToShow, [gsa, ssa, roa]() { + gsa->updateWidget(); + ssa->updateWidget(true); + roa->updateWidget(); + }); + + QObject::connect(ui->settingsButton, &QToolButton::clicked, ui->settingsButton, &QToolButton::showMenu); + QObject::connect(std::as_const(myMenu)->actions()[0], + &QAction::changed, + this, + &TaskSketcherMessages::onAutoUpdateStateChanged); +} + #include "moc_TaskSketcherMessages.cpp" // clang-format on diff --git a/src/Mod/Sketcher/Gui/TaskSketcherMessages.h b/src/Mod/Sketcher/Gui/TaskSketcherMessages.h index 791d377130..ac38b7d571 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherMessages.h +++ b/src/Mod/Sketcher/Gui/TaskSketcherMessages.h @@ -56,6 +56,7 @@ public: private: void setupConnections(); + void createSettingsButtonActions(); void onLabelConstrainStatusLinkClicked(const QString&); void onAutoUpdateStateChanged(); void onManualUpdateClicked(bool checked); diff --git a/src/Mod/Sketcher/Gui/TaskSketcherMessages.ui b/src/Mod/Sketcher/Gui/TaskSketcherMessages.ui index b46c8b6e35..1ea763b2e2 100644 --- a/src/Mod/Sketcher/Gui/TaskSketcherMessages.ui +++ b/src/Mod/Sketcher/Gui/TaskSketcherMessages.ui @@ -36,6 +36,12 @@ 0 + + + 0 + 0 + + Forces the recomputation of the active document @@ -46,6 +52,26 @@ :/icons/view-refresh.svg:/icons/view-refresh.svg + + + + + + + 0 + 0 + + + + Sketch edit settings + + + + + + + :/icons/dialogs/Sketcher_Settings.svg:/icons/dialogs/Sketcher_Settings.svg + QToolButton::MenuButtonPopup