mirror of
				https://github.com/slint-ui/slint.git
				synced 2025-11-04 13:39:03 +00:00 
			
		
		
		
	Updated the version from 1.1 to 1.2 Renamed the header to "Slint Royalty-free Desktop, Mobile, and Web Applications License" Added definition of "Mobile Application" and grant of right Moved "Limitations" to 3rd section and "License Conditions - Attributions" to 2nd section Added flexibility to choose between showing "MadeWithSlint" as a dialog/splash screen or on a public webpage Moved the para on copyright notices to section under "Limitations"
		
			
				
	
	
		
			252 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
	
		
			6.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright © SixtyFPS GmbH <info@slint.dev>
 | 
						|
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.2 OR LicenseRef-Slint-commercial
 | 
						|
 | 
						|
#include <chrono>
 | 
						|
#define CATCH_CONFIG_MAIN
 | 
						|
#include "catch2/catch.hpp"
 | 
						|
 | 
						|
#include <slint.h>
 | 
						|
#include <slint_image.h>
 | 
						|
 | 
						|
SCENARIO("SharedString API")
 | 
						|
{
 | 
						|
    slint::SharedString str;
 | 
						|
 | 
						|
    REQUIRE(str.empty());
 | 
						|
    REQUIRE(str == "");
 | 
						|
    REQUIRE(std::string_view(str.data()) == ""); // this test null termination of data()
 | 
						|
 | 
						|
    SECTION("Construct from string_view")
 | 
						|
    {
 | 
						|
        std::string foo("Foo");
 | 
						|
        std::string_view foo_view(foo);
 | 
						|
        str = foo_view;
 | 
						|
        REQUIRE(str == "Foo");
 | 
						|
        REQUIRE(std::string_view(str.data()) == "Foo");
 | 
						|
    }
 | 
						|
 | 
						|
    SECTION("Construct from char*")
 | 
						|
    {
 | 
						|
        str = "Bar";
 | 
						|
        REQUIRE(str == "Bar");
 | 
						|
    }
 | 
						|
 | 
						|
    SECTION("concatenate")
 | 
						|
    {
 | 
						|
        str = "Hello";
 | 
						|
        str += " ";
 | 
						|
        str += slint::SharedString("🦊") + slint::SharedString("!");
 | 
						|
        REQUIRE(str == "Hello 🦊!");
 | 
						|
        REQUIRE(std::string_view(str.data()) == "Hello 🦊!");
 | 
						|
    }
 | 
						|
 | 
						|
    SECTION("begin/end")
 | 
						|
    {
 | 
						|
        str = "Hello";
 | 
						|
        REQUIRE(str.begin() + std::string_view(str).size() == str.end());
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE("Basic SharedVector API", "[vector]")
 | 
						|
{
 | 
						|
    slint::SharedVector<int> vec;
 | 
						|
    REQUIRE(vec.empty());
 | 
						|
 | 
						|
    SECTION("Initializer list")
 | 
						|
    {
 | 
						|
        slint::SharedVector<int> vec({ 1, 4, 10 });
 | 
						|
        REQUIRE(vec.size() == 3);
 | 
						|
        REQUIRE(vec[0] == 1);
 | 
						|
        REQUIRE(vec[1] == 4);
 | 
						|
        REQUIRE(vec[2] == 10);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE("Property Tracker")
 | 
						|
{
 | 
						|
    using namespace slint::private_api;
 | 
						|
    PropertyTracker tracker1;
 | 
						|
    PropertyTracker tracker2;
 | 
						|
    Property<int> prop(42);
 | 
						|
 | 
						|
    auto r = tracker1.evaluate([&]() { return tracker2.evaluate([&]() { return prop.get(); }); });
 | 
						|
    REQUIRE(r == 42);
 | 
						|
 | 
						|
    prop.set(1);
 | 
						|
    REQUIRE(tracker2.is_dirty());
 | 
						|
    REQUIRE(tracker1.is_dirty());
 | 
						|
 | 
						|
    r = tracker1.evaluate(
 | 
						|
            [&]() { return tracker2.evaluate_as_dependency_root([&]() { return prop.get(); }); });
 | 
						|
    REQUIRE(r == 1);
 | 
						|
    prop.set(100);
 | 
						|
    REQUIRE(tracker2.is_dirty());
 | 
						|
    REQUIRE(!tracker1.is_dirty());
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE("Model row changes")
 | 
						|
{
 | 
						|
    using namespace slint::private_api;
 | 
						|
 | 
						|
    auto model = std::make_shared<slint::VectorModel<int>>();
 | 
						|
 | 
						|
    PropertyTracker tracker;
 | 
						|
 | 
						|
    REQUIRE(tracker.evaluate([&]() {
 | 
						|
        model->track_row_count_changes();
 | 
						|
        return model->row_count();
 | 
						|
    }) == 0);
 | 
						|
    REQUIRE(!tracker.is_dirty());
 | 
						|
    model->push_back(1);
 | 
						|
    model->push_back(2);
 | 
						|
    REQUIRE(tracker.is_dirty());
 | 
						|
    REQUIRE(tracker.evaluate([&]() {
 | 
						|
        model->track_row_count_changes();
 | 
						|
        return model->row_count();
 | 
						|
    }) == 2);
 | 
						|
    REQUIRE(!tracker.is_dirty());
 | 
						|
    model->erase(0);
 | 
						|
    REQUIRE(tracker.is_dirty());
 | 
						|
    REQUIRE(tracker.evaluate([&]() {
 | 
						|
        model->track_row_count_changes();
 | 
						|
        return model->row_count();
 | 
						|
    }) == 1);
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE("Track model row data changes")
 | 
						|
{
 | 
						|
    using namespace slint::private_api;
 | 
						|
 | 
						|
    auto model = std::make_shared<slint::VectorModel<int>>(std::vector<int> { 0, 1, 2, 3, 4 });
 | 
						|
 | 
						|
    PropertyTracker tracker;
 | 
						|
 | 
						|
    REQUIRE(tracker.evaluate([&]() {
 | 
						|
        model->track_row_data_changes(1);
 | 
						|
        return model->row_data(1);
 | 
						|
    }) == 1);
 | 
						|
    REQUIRE(!tracker.is_dirty());
 | 
						|
 | 
						|
    model->set_row_data(2, 42);
 | 
						|
    REQUIRE(!tracker.is_dirty());
 | 
						|
    model->set_row_data(1, 100);
 | 
						|
    REQUIRE(tracker.is_dirty());
 | 
						|
 | 
						|
    REQUIRE(tracker.evaluate([&]() {
 | 
						|
        model->track_row_data_changes(1);
 | 
						|
        return model->row_data(1);
 | 
						|
    }) == 100);
 | 
						|
    REQUIRE(!tracker.is_dirty());
 | 
						|
 | 
						|
    // Any changes to rows (even if after tracked rows) for now also marks watched rows as dirty, to
 | 
						|
    // keep the logic simple.
 | 
						|
    model->push_back(200);
 | 
						|
    REQUIRE(tracker.is_dirty());
 | 
						|
 | 
						|
    REQUIRE(tracker.evaluate([&]() {
 | 
						|
        model->track_row_data_changes(1);
 | 
						|
        return model->row_data(1);
 | 
						|
    }) == 100);
 | 
						|
    REQUIRE(!tracker.is_dirty());
 | 
						|
 | 
						|
    model->insert(0, 255);
 | 
						|
    REQUIRE(tracker.is_dirty());
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE("Image")
 | 
						|
{
 | 
						|
    using namespace slint;
 | 
						|
 | 
						|
    Image img;
 | 
						|
    {
 | 
						|
        auto size = img.size();
 | 
						|
        REQUIRE(size.width == 0.);
 | 
						|
        REQUIRE(size.height == 0.);
 | 
						|
    }
 | 
						|
    {
 | 
						|
        REQUIRE(!img.path().has_value());
 | 
						|
    }
 | 
						|
 | 
						|
#ifndef SLINT_FEATURE_FREESTANDING
 | 
						|
    img = Image::load_from_path(SOURCE_DIR "/../../../logo/slint-logo-square-light-128x128.png");
 | 
						|
    {
 | 
						|
        auto size = img.size();
 | 
						|
        REQUIRE(size.width == 128.);
 | 
						|
        REQUIRE(size.height == 128.);
 | 
						|
    }
 | 
						|
    {
 | 
						|
        auto actual_path = img.path();
 | 
						|
        REQUIRE(actual_path.has_value());
 | 
						|
        REQUIRE(*actual_path == SOURCE_DIR "/../../../logo/slint-logo-square-light-128x128.png");
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    img = Image(SharedPixelBuffer<Rgba8Pixel> {});
 | 
						|
    {
 | 
						|
        auto size = img.size();
 | 
						|
        REQUIRE(size.width == 0);
 | 
						|
        REQUIRE(size.height == 0);
 | 
						|
        REQUIRE(!img.path().has_value());
 | 
						|
    }
 | 
						|
    auto red = Rgb8Pixel { 0xff, 0, 0 };
 | 
						|
    auto blu = Rgb8Pixel { 0, 0, 0xff };
 | 
						|
    Rgb8Pixel some_data[] = { red, red, blu, red, blu, blu };
 | 
						|
    img = Image(SharedPixelBuffer<Rgb8Pixel>(3, 2, some_data));
 | 
						|
    {
 | 
						|
        auto size = img.size();
 | 
						|
        REQUIRE(size.width == 3);
 | 
						|
        REQUIRE(size.height == 2);
 | 
						|
        REQUIRE(!img.path().has_value());
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
TEST_CASE("SharedVector")
 | 
						|
{
 | 
						|
    using namespace slint;
 | 
						|
 | 
						|
    SharedVector<SharedString> vec;
 | 
						|
    vec.clear();
 | 
						|
    vec.push_back("Hello");
 | 
						|
    vec.push_back("World");
 | 
						|
    vec.push_back("of");
 | 
						|
    vec.push_back("Vectors");
 | 
						|
 | 
						|
    auto copy = vec;
 | 
						|
 | 
						|
    REQUIRE(vec.size() == 4);
 | 
						|
    auto orig_cap = vec.capacity();
 | 
						|
    REQUIRE(orig_cap >= vec.size());
 | 
						|
 | 
						|
    vec.clear();
 | 
						|
    REQUIRE(vec.size() == 0);
 | 
						|
    REQUIRE(vec.capacity() == 0); // vec was shared, so start with new empty vector.
 | 
						|
    vec.push_back("Welcome back");
 | 
						|
    REQUIRE(vec.size() == 1);
 | 
						|
    REQUIRE(vec.capacity() >= vec.size());
 | 
						|
 | 
						|
    REQUIRE(copy.size() == 4);
 | 
						|
    REQUIRE(copy.capacity() == orig_cap);
 | 
						|
 | 
						|
    SharedVector<SharedString> vec2 { "Hello", "World", "of", "Vectors" };
 | 
						|
    REQUIRE(copy == vec2);
 | 
						|
    REQUIRE(copy != vec);
 | 
						|
 | 
						|
    copy.clear(); // copy is not shared (anymore), retain capacity.
 | 
						|
    REQUIRE(copy.capacity() == orig_cap);
 | 
						|
 | 
						|
    SharedVector<SharedString> vec3(2, "Welcome back");
 | 
						|
    REQUIRE(vec3.size() == 2);
 | 
						|
    REQUIRE(vec3[1] == "Welcome back");
 | 
						|
    REQUIRE(vec3 != vec);
 | 
						|
 | 
						|
    vec.push_back("Welcome back");
 | 
						|
    REQUIRE(vec3 == vec);
 | 
						|
 | 
						|
    SharedVector<int> vec4(5);
 | 
						|
    REQUIRE(vec4.size() == 5);
 | 
						|
    REQUIRE(vec4[3] == 0);
 | 
						|
 | 
						|
    std::vector<SharedString> std_v(vec2.begin(), vec2.end());
 | 
						|
    SharedVector<SharedString> vec6(std_v.begin(), std_v.end());
 | 
						|
    REQUIRE(vec6 == vec2);
 | 
						|
}
 |