Sketcher: Constraint widget: Improve the filter such that the filter state and checkboxe state is cross-cession. Enabling user to 'save' filter state.

This commit is contained in:
Paddle
2022-11-23 12:55:52 +01:00
committed by Uwe
parent 6f93989777
commit 0eef8b50b3
2 changed files with 64 additions and 30 deletions

View File

@@ -637,6 +637,9 @@ void ConstraintView::swapNamedOfSelectedItems()
ConstraintFilterList::ConstraintFilterList(QWidget* parent)
: QListWidget(parent)
{
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
int filterState = hGrp->GetInt("ConstraintFilterState", INT_MAX); //INT_MAX = 1111111111111111111111111111111 in binary.
normalFilterCount = filterItems.size() - 2; //All filter but selected and associated
selectedFilterIndex = normalFilterCount;
associatedFilterIndex = normalFilterCount + 1;
@@ -647,12 +650,17 @@ ConstraintFilterList::ConstraintFilterList(QWidget* parent)
it->setFlags(it->flags() | Qt::ItemIsUserCheckable);
addItem(it);
if (row(it) < normalFilterCount)
it->setCheckState(Qt::Checked);
if (row(it) < normalFilterCount) {
bool isChecked = static_cast<bool>(filterState & 1); //get the first bit of filterState
it->setCheckState(isChecked ? Qt::Checked : Qt::Unchecked);
filterState = filterState >> 1; //shift right to get rid of the used bit.
}
else //associated and selected should not be checked by default.
it->setCheckState(Qt::Unchecked);
}
languageChange();
setPartiallyChecked();
}
ConstraintFilterList::~ConstraintFilterList()
@@ -679,6 +687,37 @@ void ConstraintFilterList::languageChange()
}
}
void ConstraintFilterList::setPartiallyChecked()
{
/* If a group is partially checked or unchecked then we apply Qt::PartiallyChecked.
The for-loop index is starting from the end. This way sub-groups are first set, which enables the bigger group to be set correctly after.
Example: If we go from 0 to count, then the loop starts at 'All' group, which check state of 'Geometric' which is not updated yet.*/
for (int i = normalFilterCount - 1; i >= 0; i--) {
bool mustBeChecked = true;
bool mustBeUnchecked = true;
int numberOfFilterInGroup = 0;
for (int j = 0; j < FilterValueLength; j++) {
if (i == j)
continue;
if (filterAggregates[i][j]) { // if it is in group
numberOfFilterInGroup++;
mustBeChecked = mustBeChecked && item(j)->checkState() == Qt::Checked;
mustBeUnchecked = mustBeUnchecked && item(j)->checkState() == Qt::Unchecked;
}
}
if (numberOfFilterInGroup > 1) { //avoid groups of single filters.
if (mustBeChecked)
item(i)->setCheckState(Qt::Checked);
else if (mustBeUnchecked)
item(i)->setCheckState(Qt::Unchecked);
else
item(i)->setCheckState(Qt::PartiallyChecked);
}
}
}
FilterValueBitset ConstraintFilterList::getMultiFilter()
{
FilterValueBitset tmpBitset;
@@ -714,7 +753,11 @@ TaskSketcherConstraints::TaskSketcherConstraints(ViewProviderSketch *sketchView)
this->groupLayout()->addWidget(proxy);
multiFilterStatus.set(); // Match 'All' selection, all bits set.
multiFilterStatus = filterList->getMultiFilter();
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
ui->filterBox->setChecked(hGrp->GetBool("ConstraintFilterEnabled", true) ? Qt::Checked : Qt::Unchecked);
ui->filterButton->setEnabled(ui->filterBox->checkState() == Qt::Checked);
slotConstraintsChanged();
@@ -868,6 +911,10 @@ void TaskSketcherConstraints::createFilterButtonActions()
void TaskSketcherConstraints::on_filterBox_stateChanged(int val)
{
Q_UNUSED(val);
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
hGrp->SetBool("ConstraintFilterEnabled", ui->filterBox->checkState() == Qt::Checked);
ui->filterButton->setEnabled(ui->filterBox->checkState() == Qt::Checked);
updateList();
}
@@ -1508,33 +1555,8 @@ void TaskSketcherConstraints::on_filterList_itemChanged(QListWidgetItem* item)
filterList->item(i)->setCheckState(item->checkState());
}
/* Now we also need to see if any modified group is all checked or all unchecked and set their status accordingly
If a group is partially checked or unchecked then we apply Qt::PartiallyChecked.
The for-loop index is starting from the end. This way sub-groups are first set, which enables the bigger group to be set correctly after.
Example: If we go from 0 to count, then the loop starts at 'All' group, which check state of 'Geometric' which is not updated yet.*/
for (int i = filterList->normalFilterCount - 1; i >= 0; i--) {
if (filterAggregates[i][filterindex] && i != filterList->row(item)) { // only for groups comprising the changed filter && not for selected item.
bool mustBeChecked = true;
bool mustBeUnchecked = true;
for (int j = 0; j < FilterValueLength; j++) {
if (i == j)
continue;
if (filterAggregates[i][j]) { // if it is in group
mustBeChecked = mustBeChecked && filterList->item(j)->checkState() == Qt::Checked;
mustBeUnchecked = mustBeUnchecked && filterList->item(j)->checkState() == Qt::Unchecked;
}
}
if (mustBeChecked)
filterList->item(i)->setCheckState(Qt::Checked);
else if (mustBeUnchecked)
filterList->item(i)->setCheckState(Qt::Unchecked);
else
filterList->item(i)->setCheckState(Qt::PartiallyChecked);
}
}
/* Now we also need to see if any modified group is all checked or all unchecked and set their status accordingly*/
filterList->setPartiallyChecked();
}
else if (filterindex == filterList->selectedFilterIndex) { //Selected constraints
if (item->checkState() == Qt::Checked) {
@@ -1557,6 +1579,16 @@ void TaskSketcherConstraints::on_filterList_itemChanged(QListWidgetItem* item)
filterList->blockSignals(false);
//Save the state of the filter.
int filterState = INT_MIN; //INT_MIN = 000000000000000000000000000000 in binary.
for (int i = filterList->count() - 1; i >= 0; i--) {
bool isChecked = filterList->item(i)->checkState() == Qt::Checked;
filterState = filterState << 1; //we shift left first, else the list is shifted at the end.
filterState = filterState | isChecked;
}
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Sketcher/General");
hGrp->SetInt("ConstraintFilterState", filterState);
// if tracking, it will call slotConstraintChanged via update mechanism as Multi Filter affects not only visibility, but also filtered list content, if not tracking will still update the list to match the multi-filter.
updateList();
}

View File

@@ -83,6 +83,8 @@ public:
explicit ConstraintFilterList(QWidget* parent = nullptr);
~ConstraintFilterList() override;
void setPartiallyChecked();
FilterValueBitset getMultiFilter();
int normalFilterCount; //All filters but selected and associated