Merge pull request #22751 from PaddleStroke/sk-messages-refactor

Sketcher: Refactor TaskSketcherMessages
This commit is contained in:
Kacper Donat
2025-08-11 11:13:18 +02:00
committed by GitHub
13 changed files with 824 additions and 508 deletions

View File

@@ -452,6 +452,7 @@ SET(Gui_UIC_SRCS
TaskView/TaskAppearance.ui
TaskView/TaskOrientation.ui
TaskView/TaskImage.ui
TaskView/TaskSolverMessages.ui
TaskView/TaskSelectLinkProperty.ui
TaskElementColors.ui
Dialogs/DlgObjectSelection.ui
@@ -864,6 +865,9 @@ SET(Task_View_SRCS
TaskView/TaskSelectLinkProperty.cpp
TaskView/TaskSelectLinkProperty.h
TaskView/TaskSelectLinkProperty.ui
TaskView/TaskSolverMessages.cpp
TaskView/TaskSolverMessages.h
TaskView/TaskSolverMessages.ui
TaskView/TaskEditControl.cpp
TaskView/TaskEditControl.h
TaskView/TaskEditControl.ui
@@ -1437,6 +1441,7 @@ if(MSVC)
TaskView/TaskOrientation.cpp
TaskView/TaskImage.cpp
TaskView/TaskSelectLinkProperty.cpp
TaskView/TaskSolverMessages.ui
TaskView/TaskEditControl.cpp
TaskView/TaskView.cpp
${Command_CPP_SRCS}

View File

@@ -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 */
}
@@ -2736,7 +2735,7 @@ PlotWidget {
SKETCHER
==================================================================================================*/
Gui--StatefulLabel[state="empty_sketch"] {
Gui--StatefulLabel[state="empty"] {
color : #ffffff; /* 50% opacity white */
}
Gui--StatefulLabel[state="under_constrained"] {

View File

@@ -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 */
}
@@ -2741,7 +2740,7 @@ PlotWidget {
SKETCHER
==================================================================================================*/
Gui--StatefulLabel[state="empty_sketch"] {
Gui--StatefulLabel[state="empty"] {
color : #393939; /* 50% opacity white */
}
Gui--StatefulLabel[state="under_constrained"] {

View File

@@ -2479,7 +2479,7 @@ PlotWidget {
SKETCHER
==================================================================================================*/
Gui--StatefulLabel[state="empty_sketch"] {
Gui--StatefulLabel[state="empty"] {
color : @SketcherEmptySketchColor}
Gui--StatefulLabel[state="under_constrained"] {
color : @SketcherUnderConstrainedColor;

View File

@@ -0,0 +1,136 @@
// SPDX - License - Identifier: LGPL - 2.1 - or -later
/****************************************************************************
* *
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QAction>
#include <QMenu>
#endif
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/ViewProvider.h>
#include "TaskSolverMessages.h"
#include "ui_TaskSolverMessages.h"
using namespace Gui;
using namespace Gui::TaskView;
namespace sp = std::placeholders;
TaskSolverMessages::TaskSolverMessages(const QPixmap& icon,
const QString& title)
: TaskBox(icon, title, true, nullptr)
, ui(new Ui_TaskSolverMessages)
{
// we need a separate container widget to add all controls to
auto* proxy = new QWidget(this);
ui->setupUi(proxy);
setupConnections();
this->groupLayout()->addWidget(proxy);
ui->labelStatus->setOpenExternalLinks(false);
// Set up the possible state values for the status label
ui->labelStatus->setParameterGroup(
"User parameter:BaseApp/Preferences/Mod/Sketcher/General");
ui->labelStatus->registerState(QStringLiteral("empty"),
palette().windowText().color(),
std::string("EmptySketchMessageColor"));
ui->labelStatus->registerState(QStringLiteral("under_constrained"),
palette().windowText().color(),
std::string("UnderconstrainedMessageColor"));
ui->labelStatus->registerState(QStringLiteral("malformed_constraints"),
QColor("red"),
std::string("MalformedConstraintMessageColor"));
ui->labelStatus->registerState(QStringLiteral("conflicting_constraints"),
QColor("orangered"),
std::string("ConflictingConstraintMessageColor"));
ui->labelStatus->registerState(QStringLiteral("redundant_constraints"),
QColor("red"),
std::string("RedundantConstraintMessageColor"));
ui->labelStatus->registerState(
QStringLiteral("partially_redundant_constraints"),
QColor("royalblue"),
std::string("PartiallyRedundantConstraintMessageColor"));
ui->labelStatus->registerState(
QStringLiteral("solver_failed"), QColor("red"), std::string("SolverFailedMessageColor"));
ui->labelStatus->registerState(QStringLiteral("fully_constrained"),
QColor("green"),
std::string("FullyConstrainedMessageColor"));
ui->labelStatusLink->setLaunchExternal(false);
createSettingsButtonActions();
}
TaskSolverMessages::~TaskSolverMessages() = default;
void TaskSolverMessages::setupConnections()
{
connect(ui->labelStatusLink,
&Gui::UrlLabel::linkClicked,
this,
&TaskSolverMessages::onLabelStatusLinkClicked);
connect(ui->manualUpdate,
&QToolButton::clicked,
this,
&TaskSolverMessages::onManualUpdateClicked);
}
void TaskSolverMessages::slotSetUp(const QString& state, const QString& msg, const QString& link,
const QString& linkText)
{
ui->labelStatus->setState(state);
ui->labelStatus->setText(msg);
ui->labelStatusLink->setUrl(link);
ui->labelStatusLink->setText(linkText);
updateToolTip(link);
}
void TaskSolverMessages::setLinkTooltip(const QString& tooltip)
{
ui->labelStatusLink->setToolTip(tooltip);
}
QToolButton* TaskSolverMessages::getSettingsButton()
{
return ui->settingsButton;
}
void TaskSolverMessages::onManualUpdateClicked(bool checked)
{
Q_UNUSED(checked);
Gui::Command::updateActive();
}
void TaskSolverMessages::createSettingsButtonActions()
{
ui->settingsButton->hide();
}
#include "moc_TaskSolverMessages.cpp"

View File

@@ -0,0 +1,77 @@
// SPDX - License - Identifier: LGPL - 2.1 - or -later
/****************************************************************************
* *
* Copyright (c) 2011 Jürgen Riegel <juergen.riegel@web.de> *
* *
* This file is part of FreeCAD. *
* *
* FreeCAD is free software: you can redistribute it and/or modify it *
* under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 2.1 of the *
* License, or (at your option) any later version. *
* *
* FreeCAD 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with FreeCAD. If not, see *
* <https://www.gnu.org/licenses/>. *
* *
***************************************************************************/
#ifndef GUI_TASKVIEW_TaskSolverMessages_H
#define GUI_TASKVIEW_TaskSolverMessages_H
#include <boost/signals2.hpp>
#include <Gui/TaskView/TaskView.h>
class Ui_TaskSolverMessages;
using Connection = boost::signals2::connection;
namespace App
{
class Property;
}
namespace Gui
{
class GuiExport TaskSolverMessages: public Gui::TaskView::TaskBox
{
Q_OBJECT
public:
explicit TaskSolverMessages(const QPixmap& icon,
const QString& title);
~TaskSolverMessages() override;
FC_DISABLE_COPY_MOVE(TaskSolverMessages)
void slotSetUp(const QString& state,
const QString& msg,
const QString& link,
const QString& linkText);
private:
void setupConnections();
virtual void createSettingsButtonActions();
virtual void onLabelStatusLinkClicked(const QString&) = 0;
void onManualUpdateClicked(bool checked);
virtual void updateToolTip(const QString&) = 0;
protected:
void setLinkTooltip(const QString& tooltip);
QToolButton* getSettingsButton();
Connection connectionSetUp;
private:
std::unique_ptr<Ui_TaskSolverMessages> ui;
};
} // namespace Gui
#endif // GUI_TASKVIEW_TaskSolverMessages_H

View File

@@ -1,70 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TaskSketcherMessages</class>
<widget class="QWidget" name="TaskSketcherMessages">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>253</width>
<height>48</height>
</rect>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="Gui::StatefulLabel" name="labelConstrainStatus">
<property name="text">
<string>DOF</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::UrlLabel" name="labelConstrainStatusLink">
<property name="text">
<string>Link</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="manualUpdate">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Forces the recomputation of the active document</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/view-refresh.svg</normaloff>:/icons/view-refresh.svg</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::StatefulLabel</class>
<extends>QLabel</extends>
<header>Gui/Widgets.h</header>
</customwidget>
<customwidget>
<class>Gui::UrlLabel</class>
<extends>QLabel</extends>
<header>Gui/Widgets.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
<?xml version="1.0" encoding="utf-8"?>
<ui version="4.0">
<class>TaskSolverMessages</class>
<widget class="QWidget" name="TaskSolverMessages">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>48</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>320</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string notr="true">Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="Gui::StatefulLabel" name="labelStatus">
<property name="text">
<string>DOF</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::UrlLabel" name="labelStatusLink">
<property name="text">
<string>Link</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="manualUpdate">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Forces the recomputation of the active document</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/view-refresh.svg</normaloff>:/icons/view-refresh.svg</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="settingsButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Settings</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/preferences-general.svg</normaloff>:/icons/preferences-general.svg</iconset>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::StatefulLabel</class>
<extends>QLabel</extends>
<header>Gui/Widgets.h</header>
</customwidget>
<customwidget>
<class>Gui::UrlLabel</class>
<extends>QLabel</extends>
<header>Gui/Widgets.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -23,7 +23,6 @@ set(SketcherGui_UIC_SRCS
TaskSketcherConstraints.ui
TaskSketcherElements.ui
SketcherToolDefaultWidget.ui
TaskSketcherMessages.ui
TaskSketcherSolverAdvanced.ui
TaskSketcherValidation.ui
InsertDatum.ui
@@ -42,6 +41,7 @@ SET(SketcherGui_SRCS
${SketcherGui_UIC_HDRS}
AppSketcherGui.cpp
GeometryCreationMode.h
Command.h
Command.cpp
AutoConstraint.h
Utils.h
@@ -102,7 +102,6 @@ SET(SketcherGui_SRCS
SketcherToolDefaultWidget.h
TaskSketcherTool.cpp
TaskSketcherTool.h
TaskSketcherMessages.ui
TaskSketcherMessages.cpp
TaskSketcherMessages.h
TaskSketcherSolverAdvanced.ui

View File

@@ -25,6 +25,7 @@
#include <QApplication>
#include <QCheckBox>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QInputDialog>
#include <QLabel>
#include <QMenu>
@@ -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<double>(&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<SketcherGui::ViewProviderSketch*>(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<double>(&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<SketcherGui::ViewProviderSketch*>(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();
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);
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();
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<double>(&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<double>(&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
{

View File

@@ -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 <QWidgetAction>
#include <QCoreApplication>
#include <Base/Parameter.h>
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

View File

@@ -23,6 +23,8 @@
#include "PreCompiled.h"
#ifndef _PreComp_
#include <QAction>
#include <QMenu>
#include <QCheckBox>
#endif
#include <Gui/Application.h>
@@ -30,9 +32,9 @@
#include <Gui/Command.h>
#include <Mod/Sketcher/App/SketchObject.h>
#include "Command.h"
#include "TaskSketcherMessages.h"
#include "ViewProviderSketch.h"
#include "ui_TaskSketcherMessages.h"
// clang-format off
@@ -41,53 +43,67 @@ using namespace Gui::TaskView;
namespace sp = std::placeholders;
TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch* sketchView)
: TaskBox(Gui::BitmapFactory().pixmap("Sketcher_Sketch"), tr("Solver Messages"), true, nullptr)
: TaskSolverMessages(Gui::BitmapFactory().pixmap("Sketcher_Sketch"), tr("Sketch Edit"))
, sketchView(sketchView)
, ui(new Ui_TaskSketcherMessages)
{
// we need a separate container widget to add all controls to
proxy = new QWidget(this);
ui->setupUi(proxy);
setupConnections();
this->groupLayout()->addWidget(proxy);
createSettingsButtonActions();
//NOLINTBEGIN
connectionSetUp = sketchView->signalSetUp.connect(std::bind(
&SketcherGui::TaskSketcherMessages::slotSetUp, this, sp::_1, sp::_2, sp::_3, sp::_4));
//NOLINTEND
}
ui->labelConstrainStatus->setOpenExternalLinks(false);
TaskSketcherMessages::~TaskSketcherMessages()
{
connectionSetUp.disconnect();
}
// Set up the possible state values for the status label
ui->labelConstrainStatus->setParameterGroup(
"User parameter:BaseApp/Preferences/Mod/Sketcher/General");
ui->labelConstrainStatus->registerState(QStringLiteral("empty_sketch"),
palette().windowText().color(),
std::string("EmptySketchMessageColor"));
ui->labelConstrainStatus->registerState(QStringLiteral("under_constrained"),
palette().windowText().color(),
std::string("UnderconstrainedMessageColor"));
ui->labelConstrainStatus->registerState(QStringLiteral("malformed_constraints"),
QColor("red"),
std::string("MalformedConstraintMessageColor"));
ui->labelConstrainStatus->registerState(QStringLiteral("conflicting_constraints"),
QColor("orangered"),
std::string("ConflictingConstraintMessageColor"));
ui->labelConstrainStatus->registerState(QStringLiteral("redundant_constraints"),
QColor("red"),
std::string("RedundantConstraintMessageColor"));
ui->labelConstrainStatus->registerState(
QStringLiteral("partially_redundant_constraints"),
QColor("royalblue"),
std::string("PartiallyRedundantConstraintMessageColor"));
ui->labelConstrainStatus->registerState(
QStringLiteral("solver_failed"), QColor("red"), std::string("SolverFailedMessageColor"));
ui->labelConstrainStatus->registerState(QStringLiteral("fully_constrained"),
QColor("green"),
std::string("FullyConstrainedMessageColor"));
void TaskSketcherMessages::updateToolTip(const QString& link)
{
if (link == QStringLiteral("#conflicting")) {
setLinkTooltip(tr("Click to select these conflicting constraints."));
}
else if (link == QStringLiteral("#redundant")) {
setLinkTooltip(tr("Click to select these redundant constraints."));
}
else if (link == QStringLiteral("#dofs")) {
setLinkTooltip(tr("The sketch has unconstrained elements giving rise to those "
"Degrees Of Freedom. Click to select these unconstrained elements."));
}
else if (link == QStringLiteral("#malformed")) {
setLinkTooltip(tr("Click to select these malformed constraints."));
}
else if (link == QStringLiteral("#partiallyredundant")) {
setLinkTooltip(
tr("Some constraints in combination are partially redundant. Click to select these "
"partially redundant constraints."));
}
}
ui->labelConstrainStatusLink->setLaunchExternal(false);
void TaskSketcherMessages::onLabelStatusLinkClicked(const QString& str)
{
if (str == QStringLiteral("#conflicting")) {
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectConflictingConstraints");
}
else if (str == QStringLiteral("#redundant")) {
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectRedundantConstraints");
}
else if (str == QStringLiteral("#dofs")) {
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectElementsWithDoFs");
}
else if (str == QStringLiteral("#malformed")) {
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectMalformedConstraints");
}
else if (str == QStringLiteral("#partiallyredundant")) {
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectPartiallyRedundantConstraints");
}
}
void TaskSketcherMessages::createSettingsButtonActions()
{
QToolButton* btn = getSettingsButton();
btn->show();
// Set Auto Update in the 'Manual Update' button menu.
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
@@ -96,97 +112,44 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch* sketchView)
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);
auto* autoUpdateAction = new QWidgetAction(this);
auto* containerWidget = new QWidget();
auto* layout = new QGridLayout(containerWidget);
auto* checkbox = new QCheckBox(tr("Auto-update"));
checkbox->setToolTip(tr("Executes a recomputation of active document after every sketch action"));
checkbox->setChecked(state);
layout->addWidget(checkbox, 0, 0, 1, 2);
containerWidget->setLayout(layout);
autoUpdateAction->setDefaultWidget(containerWidget);
QObject::connect(std::as_const(ui->manualUpdate)->actions()[0],
&QAction::changed,
this,
&TaskSketcherMessages::onAutoUpdateStateChanged);
}
connect(checkbox, &QCheckBox::toggled, this, [this](bool checked) {
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Sketcher");
hGrp->SetBool("AutoRecompute", checked);
sketchView->getSketchObject()->noRecomputes = !checked;
});
TaskSketcherMessages::~TaskSketcherMessages()
{
connectionSetUp.disconnect();
}
auto* gridAction = new GridSpaceAction(this);
auto* snapAction = new SnapSpaceAction(this);
auto* renderingAction = new RenderingOrderAction(this);
void TaskSketcherMessages::setupConnections()
{
connect(ui->labelConstrainStatusLink,
&Gui::UrlLabel::linkClicked,
this,
&TaskSketcherMessages::onLabelConstrainStatusLinkClicked);
connect(ui->manualUpdate,
&QToolButton::clicked,
this,
&TaskSketcherMessages::onManualUpdateClicked);
}
QMenu* myMenu = new QMenu(this);
myMenu->addAction(autoUpdateAction);
myMenu->addSeparator();
myMenu->addAction(gridAction);
myMenu->addSeparator();
myMenu->addAction(snapAction);
myMenu->addSeparator();
myMenu->addAction(renderingAction);
btn->setMenu(myMenu);
void TaskSketcherMessages::slotSetUp(const QString& state, const QString& msg, const QString& link,
const QString& linkText)
{
ui->labelConstrainStatus->setState(state);
ui->labelConstrainStatus->setText(msg);
ui->labelConstrainStatusLink->setUrl(link);
ui->labelConstrainStatusLink->setText(linkText);
updateToolTip(link);
}
QObject::connect(myMenu, &QMenu::aboutToShow, [gridAction, snapAction, renderingAction]() {
gridAction->updateWidget();
snapAction->updateWidget(true);
renderingAction->updateWidget();
});
void TaskSketcherMessages::updateToolTip(const QString& link)
{
if (link == QStringLiteral("#conflicting"))
ui->labelConstrainStatusLink->setToolTip(
tr("Click to select these conflicting constraints."));
else if (link == QStringLiteral("#redundant"))
ui->labelConstrainStatusLink->setToolTip(tr("Click to select these redundant constraints."));
else if (link == QStringLiteral("#dofs"))
ui->labelConstrainStatusLink->setToolTip(
tr("The sketch has unconstrained elements giving rise to those Degrees Of Freedom. "
"Click to select these unconstrained elements."));
else if (link == QStringLiteral("#malformed"))
ui->labelConstrainStatusLink->setToolTip(tr("Click to select these malformed constraints."));
else if (link == QStringLiteral("#partiallyredundant"))
ui->labelConstrainStatusLink->setToolTip(
tr("Some constraints in combination are partially redundant. Click to select these "
"partially redundant constraints."));
}
void TaskSketcherMessages::onLabelConstrainStatusLinkClicked(const QString& str)
{
if (str == QStringLiteral("#conflicting"))
Gui::Application::Instance->commandManager().runCommandByName(
"Sketcher_SelectConflictingConstraints");
else if (str == QStringLiteral("#redundant"))
Gui::Application::Instance->commandManager().runCommandByName(
"Sketcher_SelectRedundantConstraints");
else if (str == QStringLiteral("#dofs"))
Gui::Application::Instance->commandManager().runCommandByName(
"Sketcher_SelectElementsWithDoFs");
else if (str == QStringLiteral("#malformed"))
Gui::Application::Instance->commandManager().runCommandByName(
"Sketcher_SelectMalformedConstraints");
else if (str == QStringLiteral("#partiallyredundant"))
Gui::Application::Instance->commandManager().runCommandByName(
"Sketcher_SelectPartiallyRedundantConstraints");
}
void TaskSketcherMessages::onAutoUpdateStateChanged()
{
bool state = std::as_const(ui->manualUpdate)->actions()[0]->isChecked();
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath(
"User parameter:BaseApp/Preferences/Mod/Sketcher");
hGrp->SetBool("AutoRecompute", state);
sketchView->getSketchObject()->noRecomputes = !state;
}
void TaskSketcherMessages::onManualUpdateClicked(bool checked)
{
Q_UNUSED(checked);
Gui::Command::updateActive();
QObject::connect(btn, &QToolButton::clicked, btn, &QToolButton::showMenu);
}
#include "moc_TaskSketcherMessages.cpp"

View File

@@ -23,25 +23,14 @@
#ifndef GUI_TASKVIEW_TaskSketcherMessages_H
#define GUI_TASKVIEW_TaskSketcherMessages_H
#include <boost/signals2.hpp>
#include <Gui/TaskView/TaskView.h>
class Ui_TaskSketcherMessages;
using Connection = boost::signals2::connection;
namespace App
{
class Property;
}
#include <Gui/TaskView/TaskSolverMessages.h>
namespace SketcherGui
{
class ViewProviderSketch;
class TaskSketcherMessages: public Gui::TaskView::TaskBox
class TaskSketcherMessages: public Gui::TaskSolverMessages
{
Q_OBJECT
@@ -49,26 +38,14 @@ public:
explicit TaskSketcherMessages(ViewProviderSketch* sketchView);
~TaskSketcherMessages() override;
void slotSetUp(const QString& state,
const QString& msg,
const QString& link,
const QString& linkText);
private:
void setupConnections();
void onLabelConstrainStatusLinkClicked(const QString&);
void onAutoUpdateStateChanged();
void onManualUpdateClicked(bool checked);
void createSettingsButtonActions() override;
void onLabelStatusLinkClicked(const QString&) override;
void updateToolTip(const QString& link);
void updateToolTip(const QString& link) override;
protected:
ViewProviderSketch* sketchView;
Connection connectionSetUp;
private:
QWidget* proxy;
std::unique_ptr<Ui_TaskSketcherMessages> ui;
};
} // namespace SketcherGui

View File

@@ -3259,7 +3259,7 @@ void ViewProviderSketch::UpdateSolverInformation()
bool hasMalformed = getSketchObject()->getLastHasMalformedConstraints();
if (getSketchObject()->Geometry.getSize() == 0) {
signalSetUp(QStringLiteral("empty_sketch"), tr("Empty sketch"), QString(), QString());
signalSetUp(QStringLiteral("empty"), tr("Empty sketch"), QString(), QString());
}
else if (dofs < 0 || hasConflicts) {// over-constrained sketch
signalSetUp(