[Sketcher] Make status message styleable

Reduce the size and verbosity of the solver and constraint status
messages, and make them styleable both via stylesheets and user
preferences.
This commit is contained in:
Chris Hennes
2021-10-05 23:24:09 -05:00
parent 5a51cc9103
commit ec6d4623d1
5 changed files with 121 additions and 130 deletions

View File

@@ -59,8 +59,7 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch *sketchView) :
this->groupLayout()->addWidget(proxy);
connectionSetUp = sketchView->signalSetUp.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSetUp, this, bp::_1, bp::_2));
connectionSolved = sketchView->signalSolved.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSolved, this, bp::_1, bp::_2));
connectionSetUp = sketchView->signalSetUp.connect(boost::bind(&SketcherGui::TaskSketcherMessages::slotSetUp, this, bp::_1, bp::_2, bp::_3, bp::_4));
ui->labelConstrainStatus->setOpenExternalLinks(false);
@@ -72,19 +71,22 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch *sketchView) :
else
sketchView->getSketchObject()->noRecomputes=true;
// Set up the possible state values for the solver status label
const std::string paramGroup ("User parameter:BaseApp/Preferences/Mod/Sketcher");
ui->labelConstrainStatus->registerState(QString::fromUtf8("empty_sketch"), QColor("black"), paramGroup, "emptySketchMessageColor");
ui->labelConstrainStatus->registerState(QString::fromUtf8("under_constrained"), QColor("black"), paramGroup, "underconstrainedMessageColor");
ui->labelConstrainStatus->registerState(QString::fromUtf8("malformed_constraints"), QColor("red"), paramGroup, "malformedConstraintMessageColor");
ui->labelConstrainStatus->registerState(QString::fromUtf8("conflicting_constraints"), QColor("orangered"), paramGroup, "conflictingConstraintMessageColor");
ui->labelConstrainStatus->registerState(QString::fromUtf8("redundant_constraints"), QColor("red"), paramGroup, "redundantConstraintMessageColor");
ui->labelConstrainStatus->registerState(QString::fromUtf8("partially_redundant_constraints"), QColor("royalblue"), paramGroup, "partiallyRedundantConstraintMessageColor");
ui->labelConstrainStatus->registerState(QString::fromUtf8("fully_constrained"), QColor("green"), paramGroup, "fullyConstrainedMessageColor");
// Set up the possible state values for the status label
ui->labelConstrainStatus->setParameterGroup("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
ui->labelConstrainStatus->registerState(QString::fromUtf8("empty_sketch"), QColor("black"), std::string("EmptySketchMessageColor"));
ui->labelConstrainStatus->registerState(QString::fromUtf8("under_constrained"), QColor("black"), std::string("UnderconstrainedMessageColor"));
ui->labelConstrainStatus->registerState(QString::fromUtf8("malformed_constraints"), QColor("red"), std::string("MalformedConstraintMessageColor"));
ui->labelConstrainStatus->registerState(QString::fromUtf8("conflicting_constraints"), QColor("orangered"), std::string("ConflictingConstraintMessageColor"));
ui->labelConstrainStatus->registerState(QString::fromUtf8("redundant_constraints"), QColor("red"), std::string("RedundantConstraintMessageColor"));
ui->labelConstrainStatus->registerState(QString::fromUtf8("partially_redundant_constraints"), QColor("royalblue"), std::string("PartiallyRedundantConstraintMessageColor"));
ui->labelConstrainStatus->registerState(QString::fromUtf8("solver_failed"), QColor("red"), std::string("SolverFailedMessageColor"));
ui->labelConstrainStatus->registerState(QString::fromUtf8("fully_constrained"), QColor("green"), std::string("FullyConstrainedMessageColor"));
ui->labelSolverStatus->registerState(QString::fromUtf8("good"), QColor("green"), QColor(255, 255, 255, 50), paramGroup, "solverGoodMessageColor");
ui->labelSolverStatus->registerState(QString::fromUtf8("bad"), QColor("red"), QColor(255, 255, 255, 50), paramGroup, "solverBadMessageColor");
ui->labelSolverStatus->registerState(QString::fromUtf8("neutral"), QColor("black"), paramGroup, "solverNeutralMessageColor");
ui->labelConstrainStatusLink->setLaunchExternal(false);
// Manually connect the link since it uses "clicked()", which labels don't have natively
connect(ui->labelConstrainStatusLink, &Gui::UrlLabel::linkClicked,
this, &TaskSketcherMessages::on_labelConstrainStatusLink_linkClicked);
/*QObject::connect(
ui->labelConstrainStatus, SIGNAL(linkActivated(const QString &)),
@@ -103,22 +105,17 @@ TaskSketcherMessages::TaskSketcherMessages(ViewProviderSketch *sketchView) :
TaskSketcherMessages::~TaskSketcherMessages()
{
connectionSetUp.disconnect();
connectionSolved.disconnect();
}
void TaskSketcherMessages::slotSetUp(const QString &state, const QString &msg)
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);
}
void TaskSketcherMessages::slotSolved(const QString& state, const QString& msg)
{
ui->labelSolverStatus->setState(state);
ui->labelSolverStatus->setText(msg);
}
void TaskSketcherMessages::on_labelConstrainStatus_linkActivated(const QString &str)
void TaskSketcherMessages::on_labelConstrainStatusLink_linkClicked(const QString &str)
{
if( str == QString::fromLatin1("#conflicting"))
Gui::Application::Instance->commandManager().runCommandByName("Sketcher_SelectConflictingConstraints");

View File

@@ -47,11 +47,10 @@ public:
TaskSketcherMessages(ViewProviderSketch *sketchView);
~TaskSketcherMessages();
void slotSetUp(const QString &state, const QString &msg);
void slotSolved(const QString& state, const QString &msg);
void slotSetUp(const QString &state, const QString &msg, const QString& link, const QString& linkText);
private Q_SLOTS:
void on_labelConstrainStatus_linkActivated(const QString &);
void on_labelConstrainStatusLink_linkClicked(const QString &);
void on_autoUpdate_stateChanged(int state);
void on_autoRemoveRedundants_stateChanged(int state);
void on_manualUpdate_clicked(bool checked);
@@ -59,7 +58,6 @@ private Q_SLOTS:
protected:
ViewProviderSketch *sketchView;
Connection connectionSetUp;
Connection connectionSolved;
private:
QWidget* proxy;

View File

@@ -15,24 +15,35 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="Gui::StatefulLabel" name="labelConstrainStatus">
<property name="text">
<string>Undefined degrees of freedom</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="Gui::StatefulLabel" name="labelSolverStatus">
<property name="text">
<string>Not solved yet</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<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>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="Gui::PrefCheckBox" name="autoRemoveRedundants">
@@ -94,11 +105,16 @@
<extends>QCheckBox</extends>
<header>Gui/PrefWidgets.h</header>
</customwidget>
<customwidget>
<class>Gui::StatefulLabel</class>
<extends>QLabel</extends>
<header>Gui/Widgets.h</header>
</customwidget>
<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/>

View File

@@ -1312,10 +1312,6 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
if (getSketchObject()->moveTemporaryPoint(GeoId, PosId, vec, false) == 0) {
setPositionText(Base::Vector2d(x,y));
draw(true,false);
signalSolved(QString::fromUtf8("neutral"), QString::fromLatin1("Solved in %1 sec").arg(getSolvedSketch().getSolveTime()));
} else {
signalSolved(QString::fromUtf8("bad"), QString::fromLatin1("Unsolved (%1 sec)").arg(getSolvedSketch().getSolveTime()));
//Base::Console().Log("Error solving:%d\n",ret);
}
}
}
@@ -1353,9 +1349,6 @@ bool ViewProviderSketch::mouseMove(const SbVec2s &cursorPos, Gui::View3DInventor
if (getSketchObject()->moveTemporaryPoint(edit->DragCurve, Sketcher::none, vec, relative) == 0) {
setPositionText(Base::Vector2d(x,y));
draw(true,false);
signalSolved(QString::fromUtf8("neutral"), QString::fromLatin1("Solved in %1 sec").arg(getSolvedSketch().getSolveTime()));
} else {
signalSolved(QString::fromUtf8("bad"), QString::fromLatin1("Unsolved (%1 sec)").arg(getSolvedSketch().getSolveTime()));
}
}
return true;
@@ -6584,6 +6577,29 @@ QString ViewProviderSketch::appendConstraintMsg(const QString & singularmsg,
return msg;
}
inline QString intListHelper(const std::vector<int> &ints)
{
QString results;
if (ints.size() < 8) { // The 8 is a bit heuristic... more than that and we shift formats
for (const auto i : ints) {
if (results.isEmpty())
results.append(QString::fromUtf8("%1").arg(i));
else
results.append(QString::fromUtf8(", %1").arg(i));
}
}
else {
const int numToShow = 3;
int more = ints.size() - numToShow;
for (int i = 0; i < numToShow; ++i) {
results.append(QString::fromUtf8("%1, ").arg(ints[i]));
}
results.append(QCoreApplication::translate("ViewProviderSketch","and %1 more").arg(more));
}
std::string testString = results.toStdString();
return results;
}
void ViewProviderSketch::UpdateSolverInformation()
{
// Updates Solver Information with the Last solver execution at SketchObject level
@@ -6594,82 +6610,48 @@ void ViewProviderSketch::UpdateSolverInformation()
bool hasMalformed = getSketchObject()->getLastHasMalformedConstraints();
if (getSketchObject()->Geometry.getSize() == 0) {
signalSetUp(QString::fromUtf8("empty_sketch"), tr("Empty sketch"));
signalSolved(QString::fromUtf8("neutral"), QString());
signalSetUp(QString::fromUtf8("empty_sketch"), tr("Empty sketch"), QString(), QString());
}
else if (dofs < 0) { // over-constrained sketch
std::string msg;
SketchObject::appendConflictMsg(getSketchObject()->getLastConflicting(), msg);
signalSetUp(QString::fromUtf8("conflicting_constraints"),
QString::fromLatin1("%1 <a href=\"#conflicting\"><span style=\" text-decoration: underline; color:#0000ff; background-color: #F8F8FF;\">%2</span></a><br/>%3<br/>")
.arg(tr("Over-constrained sketch"))
.arg(tr("(click to select)"))
.arg(QString::fromStdString(msg)));
signalSolved(QString::fromUtf8("neutral"), QString());
else if (dofs < 0 || hasConflicts) { // over-constrained sketch
signalSetUp(QString::fromUtf8("conflicting_constraints"),
tr("Over-constrained: "),
QString::fromUtf8("#conflicting"),
QString::fromUtf8("(%1)").arg(intListHelper(getSketchObject()->getLastConflicting())));
}
else if (hasMalformed) { // malformed constraints
signalSetUp(QString::fromUtf8("malformed_constraints"),
QString::fromLatin1("%1 <a href=\"#malformed\"><span style=\" text-decoration: underline; color:#0000ff; background-color: #F8F8FF;\">%2</span></a><br/>%3<br/>")
.arg(tr("Sketch contains malformed constraints"))
.arg(tr("(click to select)"))
.arg(appendMalformedMsg(getSketchObject()->getLastMalformedConstraints())));
signalSolved(QString::fromUtf8("neutral"), QString());
signalSetUp(QString::fromUtf8("malformed_constraints"),
tr("Malformed constraints: "),
QString::fromUtf8("#malformed"),
QString::fromUtf8("(%1)").arg(intListHelper(getSketchObject()->getLastMalformedConstraints())));
}
else if (hasConflicts) { // conflicting constraints
signalSetUp(QString::fromUtf8("conflicting_constraints"),
QString::fromLatin1("%1 <a href=\"#conflicting\"><span style=\" text-decoration: underline; color:#0000ff; background-color: #F8F8FF;\">%2</span></a><br/>%3<br/>")
.arg(tr("Sketch contains conflicting constraints"))
.arg(tr("(click to select)"))
.arg(appendConflictMsg(getSketchObject()->getLastConflicting())));
signalSolved(QString::fromUtf8("neutral"), QString());
else if (hasRedundancies) {
signalSetUp(QString::fromUtf8("redundant_constraints"),
tr("Redundant constraints:"),
QString::fromUtf8("#redundant"),
QString::fromUtf8("(%1)").arg(intListHelper(getSketchObject()->getLastRedundant())));
}
else if (hasPartiallyRedundant) {
signalSetUp(QString::fromUtf8("partially_redundant_constraints"),
tr("Partially redundant:"),
QString::fromUtf8("#partiallyredundant"),
QString::fromUtf8("(%1)").arg(intListHelper(getSketchObject()->getLastPartiallyRedundant())));
}
else if (getSketchObject()->getLastSolverStatus() != 0) {
signalSetUp(QString::fromUtf8("solver_failed"),
tr("Solver failed to converge"),
QString::fromUtf8(""),
QString::fromUtf8(""));
} else if (dofs > 0) {
signalSetUp(QString::fromUtf8("under_constrained"),
tr("Under constrained:"),
QString::fromUtf8("#dofs"),
QString::fromUtf8("%1 %2").arg(dofs).arg(tr("DoF")));
}
else {
if (hasRedundancies) { // redundant constraints
signalSetUp(QString::fromUtf8("redundant_constraints"),
QString::fromLatin1("%1 <a href=\"#redundant\"><span style=\" text-decoration: underline; color:#0000ff; background-color: #F8F8FF;\">%2</span></a><br/>%3<br/>")
.arg(tr("Sketch contains redundant constraints"))
.arg(tr("(click to select)"))
.arg(appendRedundantMsg(getSketchObject()->getLastRedundant())));
}
QString partiallyRedundantString;
if(hasPartiallyRedundant) {
partiallyRedundantString = QString::fromLatin1("<br/><span style=\"background-color: rgba(255,255,255,50) ;\">%1 <a href=\"#partiallyredundant\"><span style=\" text-decoration: underline; color:#0000ff; background-color: #F8F8FF;\">%2</span></a><br/>%3</span><br/>")
.arg(tr("Sketch contains partially redundant constraints"))
.arg(tr("(click to select)"))
.arg(appendPartiallyRedundantMsg(getSketchObject()->getLastPartiallyRedundant()));
}
if (getSketchObject()->getLastSolverStatus() == 0) {
if (dofs == 0) {
// color the sketch as fully constrained if it has geometry (other than the axes)
if(getSolvedSketch().getGeometrySize()>2)
edit->FullyConstrained = true;
if (!hasRedundancies) {
signalSetUp(QString::fromUtf8("fully_constrained"),
partiallyRedundantString + tr("Fully constrained sketch"));
}
}
else if (!hasRedundancies) {
QString infoString;
if (dofs == 1)
signalSetUp(QString::fromUtf8("under_constrained"),
tr("Under-constrained sketch with <a href=\"#dofs\"><span style=\" text-decoration: underline; color:#0000ff; background-color: #F8F8FF;\">1 degree</span></a> of freedom. %1")
.arg(partiallyRedundantString));
else
signalSetUp(QString::fromUtf8("under_constrained"),
tr("Under-constrained sketch with <a href=\"#dofs\"><span style=\" text-decoration: underline; color:#0000ff; background-color: #F8F8FF;\">%1 degrees</span></a> of freedom. %2")
.arg(dofs)
.arg(partiallyRedundantString));
}
signalSolved(QString::fromUtf8("good"), tr("Solved in %1 sec").arg(getSketchObject()->getLastSolveTime()));
}
else {
signalSolved(QString::fromUtf8("bad"), tr("Unsolved (%1 sec)").arg(getSketchObject()->getLastSolveTime()));
}
signalSetUp(QString::fromUtf8("fully_constrained"), tr("Fully constrained"), QString(), QString());
// color the sketch as fully constrained if it has geometry (other than the axes)
if(getSolvedSketch().getGeometrySize()>2)
edit->FullyConstrained = true;
}
}

View File

@@ -273,9 +273,7 @@ public:
/// signals if the constraints list has changed
boost::signals2::signal<void ()> signalConstraintsChanged;
/// signals if the sketch has been set up
boost::signals2::signal<void (const QString &state, const QString &msg)> signalSetUp;
/// signals if the sketch has been solved
boost::signals2::signal<void (const QString &state, const QString &msg)> signalSolved;
boost::signals2::signal<void (const QString &state, const QString &msg, const QString &url, const QString &linkText)> signalSetUp;
/// signals if the elements list has changed
boost::signals2::signal<void ()> signalElementsChanged;