SlintでC++のGUIアプリを作る

## Slintについて

SlintはQMLにインスパイアされた宣言的なGUIツールキットです。

https://slint.dev/

要するにQMLっぽいモダンなやつです。

Rust、C++、Node.js (β版)、Python (α版) から利用できます。ライセンスはGPLと商用ライセンスのほかに、デスクトップ用途であればロイヤリティフリーライセンスが選べます。

Qt、QMLとの違いについては開発者がコメントしています。👇

https://news.ycombinator.com/item?id=39227690
> - Qt is a C++ framework for C++ developers, its language bindings for other languages, are second-class citizens and not truly idiomatic (I know, I've made bindings for Rust before). C++ may not always be the optimal language for writing GUI application logic. Slint is designed with a smaller API surface and improved bindings for multiple programming languages. (eg, we don't duplicate half of the C++ stdlib) With our JavaScript binding, we are a good lightweight alternative to Electron.
> - The Slint language is using static typing, and each file is self-contained, simplifying tooling. We already offer IDE support with the language server protocol, featuring a Live Preview. We're also developing a WYSIWYG editor. Catching errors at compile time is better than at runtime.
> - Slint is optimized to work on less powerful hardware devices, even supporting micro controllers with less than 300K of RAM, while Qt require 100 or 1000 times that amount)
> - As a young and small company, every customer is invaluable to us. We are offering personalized support and implementing features to allow for the product of our customers. Even small customer receive the attention they deserve.
> - In general, Slint is what we think QML could be without its legacy, by starting afresh. We acknowledge that this is an ambitious project that will take time to mature, but we encourage you to give it a try.

Qtとかの大御所GUIツールキットが忘れている何か大切な、、熱いものを感じますよね...！

...つまり、現状はパッションで使う感じが強めです！！

## デスクトップ対応

Slintのデスクトップアプリケーション向けの対応はまだ途中で、production-readyではありません。マルチウィンドウ、メニューバー、コンテキストメニュー、タスクトレイといった基本的な機能が実装されていません。[#MadeWithSlint](https://madewithslint.com/) の作例を眺めてみると、単一ページorタブ切り替えの単純なGUIしかなく用途が限られる感じです。

開発は活発に行われているため今後に期待です。

## C++での開発

公式ドキュメントにstep-by-stepのチュートリアルが用意されています。

https://slint.dev/releases/latest/docs/slint/

ビルドシステムとしてCMakeを利用します。`CMakeLists.txt` にSlintのビルド設定をいろいろと書きます。その後、`.slint` ファイルにUI定義を記述してビルドを実行すると、SlintコンパイラがC++のヘッダファイルを自動生成します。C++側でそのヘッダを参照してデータの入出力やイベント処理を実装していく感じです。

公式サンプルの [slint-cpp-template](https://github.com/slint-ui/slint-cpp-template/blob/b6ed75b0dbfbb9a008a975ae253479a885df0dff/ui/appwindow.slint) の場合は、下記のような.slintファイルにカウントした数を覚えておくためのプロパティ `counter` と、その数を増やすコールバック `request-increase-value()` を定義してUIコンポーネントにバインドしています。

```qml
// "ui/appwindow.slint"
import { Button, VerticalBox } from "std-widgets.slint";

export component AppWindow inherits Window {
    in-out property<int> counter: 42;   // プロパティ
    callback request-increase-value();  // コールバック
    VerticalBox {
        Text {
            text: "Counter: \{root.counter}";  // データバインド
        }
        Button {
            text: "Increase value";
            clicked => {
                root.request-increase-value();  // ボタンクリック時にコールバック呼び出し
            }
        }
     }
}
```

下記のC++コード内でコールバック処理を記述し、`counter` プロパティを読み書きしています。インクルードしている `appwindow.h` ヘッダはSlintコンパイラが自動生成したものです。

```c++
// "src/main.cpp"
#include "appwindow.h"

int main(int argc, char **argv)
{
    auto ui = AppWindow::create();

    ui->on_request_increase_value([&]{  // コールバックの定義
        ui->set_counter(ui->get_counter() + 1);  // プロパティのゲットとセット
    });

    ui->run();
    return 0;
}
```

## 使ってみる

物は試し、ということで自分でもSlintアプリを作ってみました。Alembicファイルを開きオブジェクトの階層構造をリスト表示するやつです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1662605/607fcb0f-7c5c-a89f-7f2a-5091be01507e.png" width="50%" height="50%" alt="screenshot">

https://github.com/ugai/seseragi

公式テンプレート [slint-cpp-template](https://github.com/slint-ui/slint-cpp-template/) をベースにプロジェクトを構成し、[cargo-ui](https://github.com/slint-ui/cargo-ui/) などを参考にコーディングを進めていくと、わりと簡単に自分のアプリを作ることができました。

VSCodeに[Slint拡張機能](https://marketplace.visualstudio.com/items?itemName=Slint.slint)を導入するとシンタックスハイライトや入力補完が利用できるため開発作業がスムーズになります。以前QMLを少し触った経験がありますが、Javascriptのコードでエラーが発生し、入力補完もうまく機能しないことが多々ありました。そのため、公式リファレンスを頻繁に参照したり、デバッグ作業を繰り返すことで開発者体験としてはストレスを感じることがありました。Slintはそういった問題を改善していると思います。

## 所感

Slintでできることはまだまだ限られていますが、その分かなりとっつきやすい印象です。複数の言語から利用できる点はFlutterやRustの[iced](https://iced.rs/)等にはない強みです。PythonにおいてはPySideの有力な代替になる可能性も秘めています。

デスクトップ用途に限っていえば、個人的なプロジェクトでシンプルなGUIアプリを作る場合に適していると思います。

Slintの開発チームには元Qtの関係者が複数名在籍しているようで、なんだか他の新興GUIツールキットよりもガチめな雰囲気があります。Rustベースのデスクトップ環境であるCosmicとも協力関係にあり、将来性もあるのかなと思います。今後もアップデートを注視していきたいです。