Skip to main content
Gå till innehåll

Kirigami med Rust

Skapa ditt första Kirigami-program med Rust

Installera Kirigami

Innan vi börjar måste vi installera Kirigami och Rust på datorn.

logo of Linux operating system ManjaroManjarologo of Linux operating system Arch LinuxArch
sudo pacman -S cargo cmake extra-cmake-modules kirigami breeze qqc2-desktop-style
logo of Linux operating system openSUSEOpenSUSE
sudo zypper install cargo cmake kf6-extra-cmake-modules kf6-kirigami-devel qt6-quickcontrols2-devel kf6-qqc2-desktop-style
logo of Linux operating system FedoraFedora
sudo dnf install cargo cmake extra-cmake-modules kf6-kirigami2-devel kf6-qqc2-desktop-style

Ytterligare information för andra distributioner finns här.

Projektstruktur

Först skapar vi vår projektkatalog (du kan använda kommandona nedan). Vi kallar vår kirigami_rust/.

kirigami_rust/
├── CMakeLists.txt
├── Cargo.toml
├── build.rs
├── org.kde.kirigami_rust.desktop
└── src/
    ├── main.rs
    └── qml/
        └── Main.qml

Projektet använder CMake för att anropa Cargo, som i sin tur bygger projektet.

The project will be called kirigami_rust and it will generate an executable called kirigami_hello.

org.kde.kirigami_rust.desktop

Det primära syftet med Desktop Entry-filer är att visa programmet i programstart på Linux. En annan anledning att ha dem är att ha fönsterikoner på Wayland, eftersom de måste tala om för sammansättningen att "det här fönstret hör ihop med den här ikonen".

Det måste följa ett omvänt domännamnsschema följt av tillägget .desktop såsom org.kde.kirigami_rust.desktop:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
[Desktop Entry]
Name=Kirigami Tutorial in Rust
Name[ca]=Guia d'aprenentatge del Kirigami en Rust
Name[es]=Tutorial de Kirigami en Rust
Name[sv]=Kirigami-handledning i Rust
Name[uk]=Підручник з Kirigami для Rust
Name[x-test]=xxKirigami Tutorial in Rustxx
Exec=kirigami_hello
Icon=kde
Type=Application
Terminal=false
Categories=Utility

CMakeLists.txt

The CMakeLists.txt file is going to be used to run Cargo and to install the necessary files together with our application. It also provides certain quality of life features, such as making sure that Kirigami is installed during compilation and to signal Linux distributions to install the necessary dependencies with the application.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
cmake_minimum_required(VERSION 3.28)

project(kirigami_rust)

find_package(ECM 6.0 REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
include(KDEInstallDirs)
include(ECMUninstallTarget)

include(ECMFindQmlModule)
ecm_find_qmlmodule(org.kde.kirigami REQUIRED)
find_package(KF6 REQUIRED COMPONENTS QQC2DesktopStyle)

add_custom_target(kirigami_rust
    ALL
    COMMAND cargo build --target-dir ${CMAKE_CURRENT_BINARY_DIR}
)

install(
    PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/debug/kirigami_hello
    DESTINATION ${KDE_INSTALL_BINDIR}
)

install(FILES org.kde.kirigami_rust.desktop DESTINATION ${KDE_INSTALL_APPDIR})

The first thing we do is add KDE's Extra CMake Modules (ECM) to our project so we can use ecm_find_qml_module to check that Kirigami is installed when trying to build the application, and if it's not, fail immediately. Another useful ECM feature is ECMUninstallTarget, which allows to easily uninstall the application with CMake if desired.

We also use CMake's find_package() to make sure we have qqc2-desktop-style, KDE's QML style for the desktop. This is one of the two reasons we use CMake in this tutorial.

Typically Rust projects are built with Cargo, and it won't be different here. We create a target that will simply run Cargo when run, and mark it with ALL so it builds by default. Cargo will build the executable inside CMake's binary directory (typically build/).

For more information about CMake, targets, and the binary directory, see Building KDE software manually.

After this, we simply install the kirigami_rust executable generated by Cargo in the binary directory and install it to the BINDIR, which is usually /usr/bin, /usr/local/bin or ~/.local/bin. We also install the necessary desktop file to APPDIR, which is usually /usr/share/applications or ~/.local/share/applications. This is the second reason we use CMake in this tutorial.

For more information about where KDE software is installed, see Building KDE software manually: The install step.

Nu när vi har tagit hand om CMake, låt oss titta på filerna vi ska spendera den största delen av tiden att arbeta med.

Cargo.toml

Därefter har vi en väldigt enkel Cargo.toml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
[package]
name = "kirigami_hello"
version = "0.1.0"
authors = [ "Konqi the Konqueror <konqi@kde.org>" ]
edition = "2021"
license = "GPLv3"

[dependencies]
cxx = "1.0.95"
cxx-qt = "0.7"
cxx-qt-lib = { version="0.7", features = ["qt_full"] }
cxx-qt-lib-extras = "0.7"

[build-dependencies]
# The link_qt_object_files feature is required for statically linking Qt 6.
cxx-qt-build = { version = "0.7", features = [ "link_qt_object_files" ] }

It consists of project metadata and a list of dependencies that will be pulled automatically by Cargo, namely cxx and cxx-qt, which are necessary to run Qt applications written in Rust.

build.rs

Where in C++ you'd typically register QML elements with QML_ELEMENT and ecm_add_qml_module using declarative registration, with Rust you'll need to declare it in a build script build.rs file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
use cxx_qt_build::{CxxQtBuilder, QmlModule};

fn main() {
    CxxQtBuilder::new()
        .qml_module(QmlModule {
            uri: "org.kde.tutorial",
            qml_files: &["src/qml/Main.qml"],
            rust_files: &["src/main.rs"],
            ..Default::default()
        })
        .build();
}

This is necessary to make the QML file available in the entrypoint for our application, main.rs.

src/main.rs

The file kirigami_rust/src/main.rs initializes the project and then loads the QML file, which will consist of the user interface for the application.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#[cxx_qt::bridge]
mod ffi {
    extern "RustQt" {
        #[qobject]
        type DummyQObject = super::DummyRustStruct;
    }
}

#[derive(Default)]
pub struct DummyRustStruct;

use cxx_qt_lib::{QGuiApplication, QQmlApplicationEngine, QQuickStyle, QString, QUrl};
use cxx_qt_lib_extras::QApplication;
use std::env;

fn main() {
    let mut app = QApplication::new();
    let mut engine = QQmlApplicationEngine::new();

    // To associate the executable to the installed desktop file
    QGuiApplication::set_desktop_file_name(&QString::from("org.kde.kirigami_rust"));
    // To ensure the style is set correctly
    let style = env::var("QT_QUICK_CONTROLS_STYLE");
    if style.is_err() {
        QQuickStyle::set_style(&QString::from("org.kde.desktop"));
    }

    if let Some(engine) = engine.as_mut() {
        engine.load(&QUrl::from("qrc:/qt/qml/org/kde/tutorial/src/qml/Main.qml"));
    }

    if let Some(app) = app.as_mut() {
        app.exec();
    }
}

The first part that is marked with the #[cxx_qt::bridge] Rust macro just creates a dummy QObject out of a dummy Rust struct. This is needed just to complete the use of QmlModule in the previous build script build.rs. This will play a larger part in a future tutorial teaching how to expose Rust code to QML, but for now you can ignore it.

Efter det börjar den viktiga delen:

Raderna 12-13 importerar de nödvändiga Qt-biblioteken som exponeras via cxx-qt.

Vi skapar först en ny instans av en QApplication och utför sedan några integreringar på raderna 20-26.

Sedan kommer den del som faktiskt skapar programfönstret:

28
29
30
    if let Some(engine) = engine.as_mut() {
        engine.load(&QUrl::from("qrc:/qt/qml/org/kde/tutorial/src/qml/Main.qml"));
    }

Den långa webbadressen qrc:/qt/qml/org/kde/tutorial/src/qml/Main.qml motsvarar filen Main.qml enligt Qt:s resurssystem, och följer det här schemat: <resurs_prefix><import_webbadress><QML_katalog><fil>.

In other words: the default resource prefix qrc:/qt/qml/ + the import URI org/kde/tutorial (set in build.rs, separated by slashes instead of dots) + the QML dir src/qml/ + the QML file Main.qml.

src/qml/Main.qml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Includes relevant modules used by the QML
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami

// Provides basic features needed for all kirigami applications
Kirigami.ApplicationWindow {
    // Unique identifier to reference this object
    id: root

    width: 400
    height: 300

    // Window title
    title: "Hello World"

    // Set the first page that will be loaded when the app opens
    // This can also be set to an id of a Kirigami.Page
    pageStack.initialPage: Kirigami.Page {
        Controls.Label {
            // Center label horizontally and vertically within parent object
            anchors.centerIn: parent
            text: "Hello World!"
        }
    }
}

Här är stället där vi hanterar vårt förgrundsprogram.

Om du kan lite Javascript ser mycket av QML bekant ut (även om det har sina egenheter). Qt:s dokumentation har en omfattande mängd material om språket om du känner för att prova något på egen hand. Genom alla de här handledningarna kommer vi att fokusera mycket av vår uppmärksamhet på vår QML-kod, där vi kan använda Kirigami för att få ut så mycket som möjligt av den.

Låt oss för tillfället fokusera på Main.qml. Först importerar vi ett antal viktiga moduler:

  • QtQuick, standardbiblioteket som används i QML-program.
  • QtQuick Controls, som tillhandahåller ett antal standardkontroller som vi kan använda för att göra vårt program interaktivt.
  • QtQuick Layouts, som tillhandahåller verktyg för att placera komponenter inom programmets fönster.
  • Kirigami, som tillhandahåller ett antal komponenter lämpade för att skapa program som fungerar över apparater av olika form och storlek.

Sedan kommer vi till vårt baselement, Kirigami.ApplicationWindow som tillhandahåller några grundfunktioner nödvändiga för alla Kirigami-program. Det är fönstret som kommer att innehålla alla våra sidor, huvuddelen av vårt användargränssnitt.

Vi ställer sedan in fönstrets egenskap id till 'root'. Identifierare är användbara eftersom de låter oss referera till en komponent unikt, även om vi har flera av samma typ.

Vi ställer också in fönstrets egenskap title till "Hello World".

Därefter anger vi första sidan i vår sidstapel. Del flesta Kirigami-program är organiserade som en stapel av sidor, där varje sida innehåller relaterade komponenter anpassade för en viss uppgift. För närvarande låter vi det vara enkelt, och håller oss till en enda sida. pageStack är en sidstapel som initialt är tom som Kirigami.ApplicationWindow tillhandahåller, och med pageStack.initialPage: Kirigami.Page {...} ställer vi in den första sidan som presenteras när programmet laddas i en Kirigami.Page. Sidan står för allt vårt innehåll.

Slutligen inkluderar vi en Controls.Label på vår sida, som låter oss placera text på den. Vi använder anchors.centerIn: parent för att centrera vår beteckning horisontellt och vertikalt inom vårt överliggande element. I det här fallet är det överliggande elementet för Controls.Label vår Kirigami.Page. Det sista vi behöver göra är att ange texten: text: "Hello World!".

Kompilera och installera programmet

You should find the generated executable kirigami_hello under build/debug/kirigami_hello and you may run it directly or with cargo run, but it will lack a Window icon. To address this, we'll install the application first.

Kör följande:

cmake -B build --install-prefix ~/.local
cmake --build build/
cmake --install build/

With the first command, CMake will search for Kirigami and qqc2-desktop-style.

With the second command, CMake will build the kirigami_rust target, which just calls cargo build --target-dir build/. This step will take a while to complete, but the next time you repeat the second CMake command it will be faster or you will not need to compile at all.

In the third step, CMake will install the executable kirigami_hello under ~/.local/bin/kirigami_hello and the desktop file under ~/.local/share/applications, and a new entry named "Kirigami Tutorial in Rust" will appear on your menu.

Öppna menyalternativet och voilà! Nu dyker ditt allra första Kirigami-program upp framför dina ögon.

Skärmbild av det genererade Kirigami-programmet

För att köra den nya QML-applikationen i mobilläge kan man använda QT_QUICK_CONTROLS_MOBILE=1:

QT_QUICK_CONTROLS_MOBILE=1 kirigami_hello

Om du har kompilerat projektet manuellt med CMake och av någon anledning vill avinstallera projektet kan du köra:

cmake --build build/ --target uninstall