Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pre-commit - add markdownlint-cli2 checking #96

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"default": true,
"MD007": {
"indent": 2,
"start_indented": false
},
"MD013": {
"line_length": 100,
"tables": false,
"code_blocks": false
},
"MD029": {
"style": "ordered"
},
"MD033": false
}
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,9 @@ repos:
hooks:
- id: reuse
args: [--suppress-deprecation]
- repo: https://github.com/DavidAnson/markdownlint-cli2
rev: v0.12.0
hooks:
- id: markdownlint-cli2
files: \.(md|mdown|markdown)$
exclude: (docs/api/docs/license.md)
72 changes: 39 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,68 +1,74 @@
KDBindings
==========
# KDBindings

Reactive programming & data binding in C++

From plain C++ you get:

* Signals + Slots.
* Properties templated on the contained type.
* Property bindings allowing reactive code to be written without having to do all the low-level, error prone plumbing by hand.
* Lazy evaluation of property bindings.
* No more broken bindings.
* Totally stand-alone "header-only" library. No heavy Qt dependency.
* Can still be used with Qt if you so wish.
* Signals + Slots.
* Properties templated on the contained type.
* Property bindings allowing reactive code to be written without having to do all the low-level,
error prone plumbing by hand.
* Lazy evaluation of property bindings.
* No more broken bindings.
* Totally stand-alone "header-only" library. No heavy Qt dependency.
* Can still be used with Qt if you so wish.

## Using KDBindings

Using KDBindings
================
KDBindings requires a C++ compiler with C++17 support.

Find more information at:

* [detailed browsable API reference](https://kdab.github.io/KDBindings/md__home_runner_work_KDBindings_KDBindings_docs_api_docs_getting_started_index.html)
* [our assorted example programs](https://github.com/KDAB/KDBindings/blob/main/examples)
* [detailed browsable API reference](https://kdab.github.io/KDBindings/md__home_runner_work_KDBindings_KDBindings_docs_api_docs_getting_started_index.html)
* [our assorted example programs](https://github.com/KDAB/KDBindings/blob/main/examples)

Compatibility with Qt
=====================
Because Qt defines `emit` as a keyword, Qt is by default incompatible with KDBindings, which uses `emit` as a function name.
## Compatibility with Qt

This can only be fixed by defining `QT_NO_EMIT` or `QT_NO_KEYWORDS` and simply omitting `emit` in your Qt code.
Because Qt defines `emit` as a keyword, Qt is by default incompatible with KDBindings, which
uses `emit` as a function name.

To make this easy, KDBindings includes a CMake option: `KDBindings_QT_NO_EMIT`, which defines this for all dependents of KDBindings.
This can only be fixed by defining `QT_NO_EMIT` or `QT_NO_KEYWORDS` and simply omitting
`emit` in your Qt code.

To make this easy, KDBindings includes a CMake option: `KDBindings_QT_NO_EMIT`, which defines this
for all dependents of KDBindings.

See also: [#79](https://github.com/KDAB/KDBindings/issues/79)

Contact
=======
* Visit us on GitHub: https://github.com/KDAB/KDBindings
* Email [email protected] for questions about copyright, licensing or commercial support.
## Contact

* Visit us on GitHub: <https://github.com/KDAB/KDBindings>
* Email <[email protected]> for questions about copyright, licensing or commercial support.

Stay up-to-date with KDAB product announcements:

* [KDAB Newsletter](https://news.kdab.com)
* [KDAB Blogs](https://www.kdab.com/category/blogs)
* [KDAB on Twitter](https://twitter.com/KDABQt)

Licensing
=========
## Licensing

KDBindings is © Klarälvdalens Datakonsult AB and available under the terms of
the [MIT](https://github.com/KDAB/KDBindings/blob/main/LICENSES/MIT.txt) license.

Contact KDAB at <[email protected]> if you need different licensing options.

KDBindings includes these source files, also available under the terms of the MIT license:

* [doctest.h](https://github.com/onqtam/doctest) - the lightest feature-rich C++ single-header testing framework for unit tests and TDD (C) 2016-2021 Viktor Kirilov <[email protected]>
* [genindex_array.h](https://gist.github.com/jaburns/ca72487198832f6203e831133ffdfff4) (C) 2021 Jeremy Burns (adapted by KDAB for KDBindings)
* [doctest.h](https://github.com/onqtam/doctest) - the lightest feature-rich C++ single-header
testing framework for unit tests and TDD (C) 2016-2021 Viktor Kirilov <[email protected]>
* [genindex_array.h](https://gist.github.com/jaburns/ca72487198832f6203e831133ffdfff4)
(C) 2021 Jeremy Burns (adapted by KDAB for KDBindings)

## Get Involved

Get Involved
============
Please submit your contributions or issue reports from our GitHub space at
https://github.com/KDAB/KDBindings
<https://github.com/KDAB/KDBindings>.

Contact <[email protected]> for more information.

Contact [email protected] for more information.
## About KDAB

About KDAB
==========
KDBindings is supported and maintained by Klarälvdalens Datakonsult AB (KDAB).

The KDAB Group is the global No.1 software consultancy for Qt, C++ and
Expand All @@ -74,4 +80,4 @@ We continue to help develop parts of Qt and are one of the major contributors
to the Qt Project. We can give advanced or standard trainings anywhere
around the globe on Qt as well as C++, OpenGL, 3D and more.

Please visit https://www.kdab.com to meet the people who write code like this.
Please visit <https://www.kdab.com> to meet the people who write code like this.
81 changes: 53 additions & 28 deletions docs/api/docs/getting-started/data-binding.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
# Data Binding

[Data Binding](https://en.wikipedia.org/wiki/Data_binding), or [Property Binding](https://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html) in Qt terminology, is a programming paradigm that allows binding of data sources to their respective consumers.
That means that if a value depends on another, it will automatically be updated whenever the input value changes.
[Data Binding](https://en.wikipedia.org/wiki/Data_binding), or
[Property Binding](https://doc.qt.io/qt-5/qtqml-syntax-propertybinding.html) in Qt terminology,
is a programming paradigm that allows binding of data sources to their respective consumers.
That means that if a value depends on another, it will automatically be updated whenever the
input value changes.

## Basic Data Binding in KDBindings

The basis for Data Binding in KDBindings is formed by [Properties](@ref KDBindings::Property).

They can be combined using arithmetic operators or just plain functions, to create new properties that are bound to the input properties.
This means the result of the calculation will be updated automatically every time the input of the calculation changes.
They can be combined using arithmetic operators or just plain functions, to create new properties
that are bound to the input properties. This means the result of the calculation will be updated
automatically every time the input of the calculation changes.

To create a binding, use the free KDBindings::makeBoundProperty function.

### Example
### Example: basic data binding

``` cpp
#include <kdbindings/binding.h>

Expand All @@ -26,16 +32,19 @@ width = 5;
std::cout << area << std::endl; // will print 15
```

Pretty much all arithmetic operators are supported, as well as combinations of properties with constant values.
Pretty much all arithmetic operators are supported, as well as combinations of properties with
constant values.

## Declaring functions for use in data binding

KDBindings also allows you to declare arbitrary functions as usable in the context of data binding.
See the [`node_functions.h`](./node__functions_8h.html) file for documentation on the associated macros.

This is already done for some of the `std` arithmetic functions, like abs and floor.
You can use the KDBINDINGS_DECLARE_STD_FUNCTION macro to declare more of these when necessary.

### Example
### Example: declaring functions for data binding

``` cpp
#include <kdbindings/binding.h>

Expand All @@ -46,11 +55,13 @@ Property<int> positiveValue = makeBoundProperty(abs(value));
// positiveValue is 1
```


## Binding arbitrary functions
KDBindings::makeBoundProperty also accepts functions as binding, so arbitrary code can be executed to produce the new property value.

### Example
KDBindings::makeBoundProperty also accepts functions as binding, so arbitrary code can be executed
to produce the new property value.

### Example: binding arbitrary functions

``` cpp
#include <kdbindings/binding.h>

Expand All @@ -68,18 +79,22 @@ Property<std::string> lowerCase = makeBoundProperty(
text = "Hello World!";
std::cout << lowerCase.get() << std::endl;
```

Expected output:
```

```text
hello world!
```

## No more broken bindings

A common mistake in data binding is accidentally breaking a binding by assigning a value to it.

With KDBindings this is no longer possible.
Assigning a value to a property that is the result of a data binding will result in an error!

### Example
### Example: broken bindings

``` cpp
#include <kdbindings/binding.h>

Expand All @@ -92,21 +107,28 @@ Property<int> result = makeBoundProperty(2 * value);
result = 5; // this will throw a KDBindings::ReadOnlyProperty error!
```

To intentionally remove a binding from a property, use its [`reset`](/ref KDBindings::Property::reset) function.
To intentionally remove a binding from a property, use its
[`reset`](/ref KDBindings::Property::reset) function.

### Reassigning a Binding
Even though KDBindings prevents you from accidentally overriding a binding with a concrete value, assigning a
new binding to a Property with an existing binding is possible.

For this, use the KDBindings::makeBinding function instead of KDBindings::makeBoundProperty to create the binding.
Even though KDBindings prevents you from accidentally overriding a binding with a concrete value,
assigning a new binding to a Property with an existing binding is possible.

For this, use the KDBindings::makeBinding function instead of KDBindings::makeBoundProperty to
create the binding.

It is also possible to use makeBoundProperty, which will move-assign a new Property into the
existing one, therefore completely replacing the existing Property with a new one. This means that
all signals of the old property will be disconnected (see [signals & slots](signals-slots.md)) and
any existing data bindings that depended on the property will be removed, which might not be what
you want!

It is also possible to use makeBoundProperty, which will move-assign a new Property into the existing one, therefore completely replacing the existing Property with a new one.
This means that all signals of the old property will be disconnected (see [signals & slots](signals-slots.md)) and any existing data bindings that depended on the property will be removed, which might not be what you want!
Rule of thumb: If you want to create a new property, use makeBoundProperty, if you want to add
a new binding to an existing Property, use makeBinding.

Rule of thumb: If you want to create a new property, use makeBoundProperty, if you want to add a new binding to an
existing Property, use makeBinding.
#### Example: reassign a binding

#### Example
``` cpp
#include <kdbindings/binding.h>

Expand All @@ -122,20 +144,23 @@ result = makeBoundProperty(4 * value); // This works too, but will override all
// result is now 8
```


## Deferred evaluation
KDBindings optionally offers data bindings with controlled, deferred evaluation.

This feature is enabled by passing a KDBindings::BindingEvaluator to makeBoundProperty.
The binding will then only be evaluated when [`evaluateAll()`](@ref KDbindings::BindingEvaluator::evaluateAll) is called on the evaluator instance.
KDBindings optionally offers data bindings with controlled, deferred evaluation.

Deferred evaluation is useful to avoid unnecessary reevaluation of a binding, as well as controlling the frequency of binding evaluation.
Especially in UI applications, only updating the displayed values once per second can help in making them readable, compared to a bunch of values updating at 60Hz.
This feature is enabled by passing a KDBindings::BindingEvaluator to makeBoundProperty. The binding
will then only be evaluated when [`evaluateAll()`](@ref KDbindings::BindingEvaluator::evaluateAll)
is called on the evaluator instance.

See the [06-lazy-property-bindings](./06-lazy-property-bindings_2main_8cpp-example.html) example for more details on how to use deferred evaluation.
Deferred evaluation is useful to avoid unnecessary reevaluation of a binding, as well as controlling
the frequency of binding evaluation. Especially in UI applications, only updating the displayed
values once per second can help in making them readable, compared to a bunch of values updating at 60Hz.

See the [06-lazy-property-bindings](./06-lazy-property-bindings_2main_8cpp-example.html) example for
more details on how to use deferred evaluation.

## Further reading

Classes involved in data binding are KDBindings::Property, KDBindings::Binding, and KDBindings::BindingEvaluator.

See KDBindings::makeBoundProperty for the different ways to create a binding.
Expand Down
22 changes: 17 additions & 5 deletions docs/api/docs/getting-started/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,30 @@

## Installation

KDBindings is a header-only library, so you could just add the `/src/kdbindings/` directory to your projects include path or copy it into your project and start using KDBindings.
KDBindings is a header-only library, so you could just add the `/src/kdbindings/` directory to your
projects include path or copy it into your project and start using KDBindings.

However, we recommend using [CMake](https://cmake.org/) to install KDBindings so it's available to any CMake project on your computer.
However, we recommend using [CMake](https://cmake.org/) to install KDBindings so it's available to
any CMake project on your computer.

For this, first clone the project and install it:

### Linux/macOS

``` shell
mkdir build
cd build
cmake ..
cmake --build . --target install # this command might need super user privileges (i.e. sudo)
```

### Windows:
### Windows

Navigate to the repository and create a folder named `build`.
Navigate into the folder.
Use `Shift`+`Right Click` and select `Open command window here`.
In the terminal window, run:

``` cmd
cmake ..
cmake --build . --target install
Expand All @@ -29,24 +34,31 @@ cmake --build . --target install
## Accessing KDBindings

### Linking using CMake
After installation, KDBindings is available using CMakes [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) directive.

After installation, KDBindings is available using CMake's
[find_package](https://cmake.org/cmake/help/latest/command/find_package.html) directive.
This directive then exposes a KDAB::KDBindings library that can be linked against.

Example CMake code:

``` cmake
find_package(KDBindings)
target_link_libraries(${PROJECT_NAME} KDAB::KDBindings)
```

Also make sure C++17 or later is enabled in your project:

``` cmake
set(CMAKE_CXX_STANDARD 17)
```

### Including KDBindings
Once the library is correctly added to your project, the different features of KDBindings are available for include under the `kdbindings` directory.

Once the library is correctly added to your project, the different features of KDBindings are
available for include under the `kdbindings` directory.

All parts of KDBindings are then accessible in the KDBindings namespace.

``` cpp
// Example includes
#include <kdbindings/signal.h>
Expand Down
Loading