Merge pull request #22751 from PaddleStroke/sk-messages-refactor
Sketcher: Refactor TaskSketcherMessages
This commit is contained in:
@@ -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}
|
||||
|
||||
@@ -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"] {
|
||||
|
||||
@@ -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"] {
|
||||
|
||||
@@ -2479,7 +2479,7 @@ PlotWidget {
|
||||
SKETCHER
|
||||
==================================================================================================*/
|
||||
|
||||
Gui--StatefulLabel[state="empty_sketch"] {
|
||||
Gui--StatefulLabel[state="empty"] {
|
||||
color : @SketcherEmptySketchColor}
|
||||
Gui--StatefulLabel[state="under_constrained"] {
|
||||
color : @SketcherUnderConstrainedColor;
|
||||
|
||||
136
src/Gui/TaskView/TaskSolverMessages.cpp
Normal file
136
src/Gui/TaskView/TaskSolverMessages.cpp
Normal 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"
|
||||
|
||||
77
src/Gui/TaskView/TaskSolverMessages.h
Normal file
77
src/Gui/TaskView/TaskSolverMessages.h
Normal 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
|
||||
@@ -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>
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
120
src/Mod/Sketcher/Gui/Command.h
Normal file
120
src/Mod/Sketcher/Gui/Command.h
Normal 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
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user