mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-27 20:42:25 +00:00
C++: Fix and test the reset
function on model adapter
They were causing infinite recursion because they were calling themselves. Also add the missing MapModel::reset Yet another motivation for https://github.com/slint-ui/slint/issues/3888 as the code was mixing the `reset` function on the adapter meaning "please re-apply the adapter filter/map/sort function" with the `reset` function on Model which means "the subclass has changed and we should notify listeners". Fixes #4968
This commit is contained in:
parent
dc5004f9c4
commit
fe38a1e97d
2 changed files with 100 additions and 5 deletions
|
@ -632,7 +632,7 @@ struct FilterModelInner : private_api::ModelChangeListener
|
||||||
void reset() override
|
void reset() override
|
||||||
{
|
{
|
||||||
update_mapping();
|
update_mapping();
|
||||||
target_model.reset();
|
target_model.Model<ModelData>::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_mapping()
|
void update_mapping()
|
||||||
|
@ -721,7 +721,7 @@ struct MapModelInner : private_api::ModelChangeListener
|
||||||
{
|
{
|
||||||
target_model.row_removed(index, count);
|
target_model.row_removed(index, count);
|
||||||
}
|
}
|
||||||
void reset() override { target_model.reset(); }
|
void reset() override { target_model.Model<SourceModelData>::reset(); }
|
||||||
|
|
||||||
slint::MapModel<SourceModelData, MappedModelData> &target_model;
|
slint::MapModel<SourceModelData, MappedModelData> &target_model;
|
||||||
};
|
};
|
||||||
|
@ -767,6 +767,10 @@ public:
|
||||||
/// Returns the source model of this filter model.
|
/// Returns the source model of this filter model.
|
||||||
std::shared_ptr<Model<SourceModelData>> source_model() const { return model; }
|
std::shared_ptr<Model<SourceModelData>> source_model() const { return model; }
|
||||||
|
|
||||||
|
/// Re-applies the model's mapping function on each row of the source model. Use this if state
|
||||||
|
/// external to the mapping function has changed.
|
||||||
|
void reset() { inner->reset(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<private_api::MapModelInner<SourceModelData, MappedModelData>> inner;
|
std::shared_ptr<private_api::MapModelInner<SourceModelData, MappedModelData>> inner;
|
||||||
std::shared_ptr<slint::Model<SourceModelData>> model;
|
std::shared_ptr<slint::Model<SourceModelData>> model;
|
||||||
|
@ -874,7 +878,7 @@ struct SortModelInner : private_api::ModelChangeListener
|
||||||
void reset() override
|
void reset() override
|
||||||
{
|
{
|
||||||
sorted_rows_dirty = true;
|
sorted_rows_dirty = true;
|
||||||
target_model.reset();
|
target_model.Model<ModelData>::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ensure_sorted()
|
void ensure_sorted()
|
||||||
|
@ -987,7 +991,7 @@ struct ReverseModelInner : private_api::ModelChangeListener
|
||||||
target_model.row_removed(source_model->row_count() - first_removed_row, count);
|
target_model.row_removed(source_model->row_count() - first_removed_row, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset() override { source_model.reset(); }
|
void reset() override { target_model.reset(); }
|
||||||
|
|
||||||
std::shared_ptr<slint::Model<ModelData>> source_model;
|
std::shared_ptr<slint::Model<ModelData>> source_model;
|
||||||
slint::ReverseModel<ModelData> &target_model;
|
slint::ReverseModel<ModelData> &target_model;
|
||||||
|
|
|
@ -221,12 +221,47 @@ SCENARIO("Filtering Model Remove")
|
||||||
REQUIRE(even_rows->row_data(1) == 4);
|
REQUIRE(even_rows->row_data(1) == 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCENARIO("Filtering Model Reset")
|
||||||
|
{
|
||||||
|
auto vec_model =
|
||||||
|
std::make_shared<slint::VectorModel<int>>(std::vector<int> { 1, 2, 3, 4, 5, 6 });
|
||||||
|
|
||||||
|
bool even = true;
|
||||||
|
|
||||||
|
auto even_rows = std::make_shared<slint::FilterModel<int>>(
|
||||||
|
vec_model, [&even](auto value) { return value % 2 == !even; });
|
||||||
|
|
||||||
|
auto observer = std::make_shared<ModelObserver>();
|
||||||
|
even_rows->attach_peer(observer);
|
||||||
|
|
||||||
|
REQUIRE(even_rows->row_count() == 3);
|
||||||
|
REQUIRE(even_rows->row_data(0) == 2);
|
||||||
|
REQUIRE(even_rows->row_data(1) == 4);
|
||||||
|
REQUIRE(even_rows->row_data(2) == 6);
|
||||||
|
|
||||||
|
even = false;
|
||||||
|
even_rows->reset();
|
||||||
|
|
||||||
|
REQUIRE(observer->added_rows.empty());
|
||||||
|
REQUIRE(observer->changed_rows.empty());
|
||||||
|
REQUIRE(observer->removed_rows.empty());
|
||||||
|
REQUIRE(observer->model_reset);
|
||||||
|
observer->clear();
|
||||||
|
|
||||||
|
REQUIRE(even_rows->row_count() == 3);
|
||||||
|
REQUIRE(even_rows->row_data(0) == 1);
|
||||||
|
REQUIRE(even_rows->row_data(1) == 3);
|
||||||
|
REQUIRE(even_rows->row_data(2) == 5);
|
||||||
|
}
|
||||||
|
|
||||||
SCENARIO("Mapped Model")
|
SCENARIO("Mapped Model")
|
||||||
{
|
{
|
||||||
auto vec_model = std::make_shared<slint::VectorModel<int>>(std::vector<int> { 1, 2, 3, 4 });
|
auto vec_model = std::make_shared<slint::VectorModel<int>>(std::vector<int> { 1, 2, 3, 4 });
|
||||||
|
|
||||||
|
int to_add = 1;
|
||||||
|
|
||||||
auto plus_one_model = std::make_shared<slint::MapModel<int, int>>(
|
auto plus_one_model = std::make_shared<slint::MapModel<int, int>>(
|
||||||
vec_model, [](auto value) { return value + 1; });
|
vec_model, [&to_add](auto value) { return value + to_add; });
|
||||||
|
|
||||||
auto observer = std::make_shared<ModelObserver>();
|
auto observer = std::make_shared<ModelObserver>();
|
||||||
plus_one_model->attach_peer(observer);
|
plus_one_model->attach_peer(observer);
|
||||||
|
@ -283,6 +318,21 @@ SCENARIO("Mapped Model")
|
||||||
REQUIRE(plus_one_model->row_data(1) == 4);
|
REQUIRE(plus_one_model->row_data(1) == 4);
|
||||||
REQUIRE(plus_one_model->row_data(2) == 3);
|
REQUIRE(plus_one_model->row_data(2) == 3);
|
||||||
REQUIRE(plus_one_model->row_data(3) == 5);
|
REQUIRE(plus_one_model->row_data(3) == 5);
|
||||||
|
|
||||||
|
to_add = 51;
|
||||||
|
plus_one_model->reset();
|
||||||
|
|
||||||
|
REQUIRE(observer->added_rows.empty());
|
||||||
|
REQUIRE(observer->changed_rows.empty());
|
||||||
|
REQUIRE(observer->removed_rows.empty());
|
||||||
|
REQUIRE(observer->model_reset);
|
||||||
|
observer->clear();
|
||||||
|
|
||||||
|
REQUIRE(plus_one_model->row_count() == 4);
|
||||||
|
REQUIRE(plus_one_model->row_data(0) == 151);
|
||||||
|
REQUIRE(plus_one_model->row_data(1) == 54);
|
||||||
|
REQUIRE(plus_one_model->row_data(2) == 53);
|
||||||
|
REQUIRE(plus_one_model->row_data(3) == 55);
|
||||||
}
|
}
|
||||||
|
|
||||||
SCENARIO("Sorted Model Insert")
|
SCENARIO("Sorted Model Insert")
|
||||||
|
@ -400,6 +450,38 @@ SCENARIO("Sorted Model Change")
|
||||||
REQUIRE(sorted_model->row_data(3) == 3);
|
REQUIRE(sorted_model->row_data(3) == 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCENARIO("Sorted Model Reset")
|
||||||
|
{
|
||||||
|
auto vec_model = std::make_shared<slint::VectorModel<int>>(std::vector<int> { 3, 4, 1, 2 });
|
||||||
|
|
||||||
|
bool ascending = true;
|
||||||
|
|
||||||
|
auto sorted_model =
|
||||||
|
std::make_shared<slint::SortModel<int>>(vec_model, [&ascending](auto lhs, auto rhs) {
|
||||||
|
return ascending ? lhs < rhs : rhs < lhs;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto observer = std::make_shared<ModelObserver>();
|
||||||
|
sorted_model->attach_peer(observer);
|
||||||
|
|
||||||
|
REQUIRE(sorted_model->row_count() == 4);
|
||||||
|
REQUIRE(sorted_model->row_data(0) == 1);
|
||||||
|
REQUIRE(sorted_model->row_data(1) == 2);
|
||||||
|
REQUIRE(sorted_model->row_data(2) == 3);
|
||||||
|
REQUIRE(sorted_model->row_data(3) == 4);
|
||||||
|
|
||||||
|
ascending = false;
|
||||||
|
sorted_model->reset();
|
||||||
|
|
||||||
|
REQUIRE(sorted_model->row_count() == 4);
|
||||||
|
REQUIRE(sorted_model->row_data(0) == 4);
|
||||||
|
REQUIRE(sorted_model->row_data(1) == 3);
|
||||||
|
REQUIRE(sorted_model->row_data(2) == 2);
|
||||||
|
REQUIRE(sorted_model->row_data(3) == 1);
|
||||||
|
|
||||||
|
REQUIRE(observer->model_reset);
|
||||||
|
}
|
||||||
|
|
||||||
SCENARIO("Reverse Model Insert")
|
SCENARIO("Reverse Model Insert")
|
||||||
{
|
{
|
||||||
auto vec_model = std::make_shared<slint::VectorModel<int>>(std::vector<int> { 3, 4, 1, 2 });
|
auto vec_model = std::make_shared<slint::VectorModel<int>>(std::vector<int> { 3, 4, 1, 2 });
|
||||||
|
@ -493,6 +575,15 @@ SCENARIO("Reverse Model Change")
|
||||||
REQUIRE(reverse_model->row_data(1) == 1);
|
REQUIRE(reverse_model->row_data(1) == 1);
|
||||||
REQUIRE(reverse_model->row_data(2) == 10);
|
REQUIRE(reverse_model->row_data(2) == 10);
|
||||||
REQUIRE(reverse_model->row_data(3) == 3);
|
REQUIRE(reverse_model->row_data(3) == 3);
|
||||||
|
|
||||||
|
vec_model->clear();
|
||||||
|
REQUIRE(observer->added_rows.empty());
|
||||||
|
REQUIRE(observer->changed_rows.empty());
|
||||||
|
REQUIRE(observer->removed_rows.empty());
|
||||||
|
REQUIRE(observer->model_reset);
|
||||||
|
observer->clear();
|
||||||
|
|
||||||
|
REQUIRE(reverse_model->row_count() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("VectorModel clear and replace")
|
TEST_CASE("VectorModel clear and replace")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue