Sketcher: ConstraintList: prevent N transaction on box selection (#25254)
This commit is contained in:
@@ -822,6 +822,7 @@ TaskSketcherConstraints::TaskSketcherConstraints(ViewProviderSketch* sketchView)
|
||||
, specialFilterMode{SpecialFilterType::None}
|
||||
, sketchView(sketchView)
|
||||
, inEditMode(false)
|
||||
, updateListPending(false)
|
||||
, ui(new Ui_TaskSketcherConstraints)
|
||||
{
|
||||
// we need a separate container widget to add all controls to
|
||||
@@ -1304,78 +1305,90 @@ void TaskSketcherConstraints::onSelectionChanged(const Gui::SelectionChanges& ms
|
||||
ui->listWidgetConstraints->clearSelection();
|
||||
ui->listWidgetConstraints->blockSignals(tmpBlock);
|
||||
|
||||
if (specialFilterMode == SpecialFilterType::Selected) {
|
||||
updateSelectionFilter();
|
||||
if (ui->filterBox->checkState() == Qt::Checked) {
|
||||
if (specialFilterMode == SpecialFilterType::Selected) {
|
||||
updateSelectionFilter();
|
||||
|
||||
bool block = this->blockSelection(true);// avoid to be notified by itself
|
||||
updateList();
|
||||
this->blockSelection(block);
|
||||
}
|
||||
else if (specialFilterMode == SpecialFilterType::Associated) {
|
||||
associatedConstraintsFilter.clear();
|
||||
updateList();
|
||||
bool block = this->blockSelection(true);// avoid to be notified by itself
|
||||
updateList();
|
||||
this->blockSelection(block);
|
||||
}
|
||||
else if (specialFilterMode == SpecialFilterType::Associated) {
|
||||
associatedConstraintsFilter.clear();
|
||||
updateList();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (msg.Type == Gui::SelectionChanges::AddSelection
|
||||
|| msg.Type == Gui::SelectionChanges::RmvSelection) {
|
||||
bool select = (msg.Type == Gui::SelectionChanges::AddSelection);
|
||||
// is it this object??
|
||||
if (strcmp(msg.pDocName, sketchView->getSketchObject()->getDocument()->getName()) == 0
|
||||
&& strcmp(msg.pObjectName, sketchView->getSketchObject()->getNameInDocument()) == 0) {
|
||||
if (msg.pSubName) {
|
||||
QRegularExpression rx(QStringLiteral("^Constraint(\\d+)$"));
|
||||
QRegularExpressionMatch match;
|
||||
QString expr = QString::fromLatin1(msg.pSubName);
|
||||
boost::ignore_unused(expr.indexOf(rx, 0, &match));
|
||||
if (match.hasMatch()) {// is a constraint
|
||||
bool ok;
|
||||
int ConstrId = match.captured(1).toInt(&ok) - 1;
|
||||
if (ok) {
|
||||
int countItems = ui->listWidgetConstraints->count();
|
||||
for (int i = 0; i < countItems; i++) {
|
||||
ConstraintItem* item =
|
||||
static_cast<ConstraintItem*>(ui->listWidgetConstraints->item(i));
|
||||
if (item->ConstraintNbr == ConstrId) {
|
||||
auto tmpBlock = ui->listWidgetConstraints->blockSignals(true);
|
||||
item->setSelected(select);
|
||||
ui->listWidgetConstraints->blockSignals(tmpBlock);
|
||||
SketcherGui::scrollTo(ui->listWidgetConstraints, i, select);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (specialFilterMode == SpecialFilterType::Selected) {
|
||||
updateSelectionFilter();
|
||||
bool block =
|
||||
this->blockSelection(true);// avoid to be notified by itself
|
||||
updateList();
|
||||
this->blockSelection(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (specialFilterMode == SpecialFilterType::Associated) {// is NOT a constraint
|
||||
int geoid = Sketcher::GeoEnum::GeoUndef;
|
||||
Sketcher::PointPos pointpos = Sketcher::PointPos::none;
|
||||
getSelectionGeoId(expr, geoid, pointpos);
|
||||
bool select = msg.Type == Gui::SelectionChanges::AddSelection;
|
||||
if (!select && msg.Type != Gui::SelectionChanges::RmvSelection) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (geoid != Sketcher::GeoEnum::GeoUndef
|
||||
&& pointpos == Sketcher::PointPos::none) {
|
||||
// It is not possible to update on single addition/removal of a geometric
|
||||
// element, as one removal may imply removing a constraint that should be
|
||||
// added by a different element that is still selected. The necessary checks
|
||||
// outweigh a full rebuild of the filter.
|
||||
updateAssociatedConstraintsFilter();
|
||||
updateList();
|
||||
}
|
||||
// is it this object??
|
||||
if (strcmp(msg.pDocName, sketchView->getSketchObject()->getDocument()->getName()) != 0
|
||||
|| strcmp(msg.pObjectName, sketchView->getSketchObject()->getNameInDocument()) != 0
|
||||
|| !msg.pSubName) {
|
||||
return;
|
||||
}
|
||||
|
||||
QRegularExpression rx(QStringLiteral("^Constraint(\\d+)$"));
|
||||
QRegularExpressionMatch match;
|
||||
QString expr = QString::fromLatin1(msg.pSubName);
|
||||
boost::ignore_unused(expr.indexOf(rx, 0, &match));
|
||||
if (match.hasMatch()) {// is a constraint
|
||||
bool ok;
|
||||
int ConstrId = match.captured(1).toInt(&ok) - 1;
|
||||
if (ok) {
|
||||
int countItems = ui->listWidgetConstraints->count();
|
||||
for (int i = 0; i < countItems; i++) {
|
||||
ConstraintItem* item =
|
||||
static_cast<ConstraintItem*>(ui->listWidgetConstraints->item(i));
|
||||
if (item->ConstraintNbr == ConstrId) {
|
||||
auto tmpBlock = ui->listWidgetConstraints->blockSignals(true);
|
||||
item->setSelected(select);
|
||||
ui->listWidgetConstraints->blockSignals(tmpBlock);
|
||||
SketcherGui::scrollTo(ui->listWidgetConstraints, i, select);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (specialFilterMode == SpecialFilterType::Selected) {
|
||||
updateSelectionFilter();
|
||||
bool block =
|
||||
this->blockSelection(true);// avoid to be notified by itself
|
||||
updateList();
|
||||
this->blockSelection(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (msg.Type == Gui::SelectionChanges::SetSelection) {
|
||||
// do nothing here
|
||||
else if (ui->filterBox->checkState() == Qt::Checked && specialFilterMode == SpecialFilterType::Associated) {
|
||||
int geoid = Sketcher::GeoEnum::GeoUndef;
|
||||
Sketcher::PointPos pointpos = Sketcher::PointPos::none;
|
||||
getSelectionGeoId(expr, geoid, pointpos);
|
||||
|
||||
if (geoid != Sketcher::GeoEnum::GeoUndef
|
||||
&& pointpos == Sketcher::PointPos::none) {
|
||||
// It is not possible to update on single addition/removal of a geometric
|
||||
// element, as one removal may imply removing a constraint that should be
|
||||
// added by a different element that is still selected. The necessary checks
|
||||
// outweigh a full rebuild of the filter.
|
||||
if (!updateListPending) {
|
||||
updateListPending = true;
|
||||
QTimer::singleShot(0, this, &TaskSketcherConstraints::deferredUpdateList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskSketcherConstraints::deferredUpdateList()
|
||||
{
|
||||
updateAssociatedConstraintsFilter();
|
||||
updateList();
|
||||
updateListPending = false;
|
||||
}
|
||||
|
||||
void TaskSketcherConstraints::OnChange(Base::Subject<const char*>& rCaller, const char* rcReason)
|
||||
{
|
||||
Q_UNUSED(rCaller);
|
||||
|
||||
@@ -203,9 +203,13 @@ protected:
|
||||
private:
|
||||
void onChangedSketchView(const Gui::ViewProvider&, const App::Property&);
|
||||
|
||||
private Q_SLOTS:
|
||||
void deferredUpdateList();
|
||||
|
||||
private:
|
||||
QWidget* proxy;
|
||||
bool inEditMode;
|
||||
bool updateListPending;
|
||||
std::unique_ptr<Ui_TaskSketcherConstraints> ui;
|
||||
ConstraintFilter::FilterValueBitset multiFilterStatus; // Stores the filters to be aggregated
|
||||
// to form the multifilter.
|
||||
|
||||
Reference in New Issue
Block a user