Skip to main content
Passa al contenuto

Configurazione con Rust

Crea la tua prima applicazione Kirigami con Rust

Installazione di Kirigami

Prima di iniziare, dovremo installare Kirigami e Rust sulla nostra macchina.

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

Ulteriori informazioni per altre distribuzioni sono disponibili in Installazione delle dipendenze di build.

Struttura del progetto

Per prima cosa creiamo la cartella del nostro progetto (puoi utilizzare i comandi seguenti). Chiameremo il nostro kirigami_rust/. Questa sarà la struttura del progetto:

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

Questo progetto utilizzerà CMake per chiamare Cargo, che a sua volta creerà il progetto.

Il progetto si chiamerà kirigami_rust e genererà un eseguibile chiamato kirigami_hello.

org.kde.kirigami_rust.desktop

Lo scopo principale dei file Desktop Entry è mostrare la tua app nell'avviatore applicazioni su Linux. Un altro motivo per averli è avere le icone delle finestre su Wayland, poiché sono necessarie per dire al compositore "questa finestra va con questa icona".

Deve seguire uno schema di denominazione DNS inverso seguito dall'estensione .desktop come org.kde.kirigami_rust.desktop:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
[Desktop Entry]
Name=Kirigami Tutorial in Rust
Name[ca]=Guia d'aprenentatge del Kirigami en Rust
Name[es]=Tutorial de Kirigami en Rust
Name[fr]=Tutoriel pour Kirigami en Rust
Name[it]=Esercitazione di Kirigami in Rust
Name[nl]=Kirigami handleiding in Rust
Name[pt_BR]=Tutorial do Kirigami em Rust
Name[ro]=Îndrumar Kirigami în Rust
Name[sl]=Učbenik Kirigami v Rustu
Name[sv]=Kirigami-handledning i Rust
Name[tr]=Rust ile Kirigami Öğreticisi
Name[uk]=Підручник з Kirigami для Rust
Exec=kirigami_hello
Icon=kde
Type=Application
Terminal=false
Categories=Utility

CMakeLists.txt

Il file CMakeLists.txt verrà utilizzato per eseguire Cargo e per installare i file necessari insieme alla nostra applicazione. Fornisce inoltre alcune funzionalità di qualità della vita, come assicurarsi che Kirigami sia installato durante la compilazione e segnalare alle distribuzioni Linux di installare le dipendenze necessarie con l'applicazione.

 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})

La prima cosa che facciamo è aggiungere gli Extra CMake Modules (ECM) di KDE al nostro progetto in modo da poter usare ecm_find_qml_module per verificare che Kirigami sia installato quando proviamo a creare l'applicazione e se è no, fallisci immediatamente. Un'altra utile funzionalità ECM è ECMUninstallTarget, che consente di disinstallare facilmente l'applicazione con CMake, se lo si desidera.

Usiamo anche find_package() di CMake per assicurarci di avere qqc2-desktop-style, lo stile QML di KDE per il desktop. Questo è uno dei due motivi per cui utilizziamo CMake in questo tutorial.

Tipicamente i progetti Rust sono realizzati con Cargo, e qui non sarà diverso. Creiamo un target che eseguirà semplicemente Cargo quando viene eseguito e lo contrassegniamo con "ALL" in modo che venga creato per impostazione predefinita. Cargo creerà l'eseguibile all'interno della directory binaria di CMake (tipicamente build/).

Per ulteriori informazioni su CMake, destinazioni e directory binaria, vedere Creazione manuale del software KDE.

Dopodiché, installiamo semplicemente l'eseguibile kirigami_rust generato da Cargo nella directory binaria e lo installiamo in BINDIR, che di solito è /usr/bin, /usr/local/bin o ~/.local/bin. Installiamo anche il file desktop necessario su "APPDIR", che di solito è "/usr/share/applications" o "~/.local/share/applications". Questo è il secondo motivo per cui utilizziamo CMake in questo tutorial.

Per ulteriori informazioni su dove è installato il software KDE, vedere Creazione manuale del software KDE: il passaggio di installazione.

Ora che CMake se n'è preso cura, vediamo i file su cui lavoreremo di più.

carico.toml

Successivamente abbiamo un Cargo.toml molto semplice:

 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" ] }

Consiste nei metadati del progetto e in un elenco di dipendenze che verranno recuperate automaticamente da Cargo, ovvero cxx e cxx-qt, necessarie per eseguire le applicazioni Qt scritte in Rust.

build.rs

Dove in C++ normalmente registreresti gli elementi QML con QML_ELEMENT e ecm_add_qml_module utilizzando dichiarativo registrazione, con Rust dovrai dichiararlo in un file build script build.rs:

 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();
}

Ciò è necessario per rendere disponibile il file QML nel punto di ingresso della nostra applicazione, "main.rs".

src/main.rs

Il file kirigami_rust/src/main.rs inizializza il progetto e quindi carica il file QML, che consisterà nell'interfaccia utente per l'applicazione.

 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();
    }
}

La prima parte contrassegnata con la #[cxx_qt::bridge] macro Rust crea semplicemente un QObject fittizio da una struttura Rust fittizia. Questo è necessario solo per completare l'uso di QmlModule nello script di build precedente build.rs. Questo avrà un ruolo più importante in un futuro tutorial che insegnerà come esporre il codice Rust a QML, ma per ora puoi ignorarlo.

Dopodiché inizia la parte importante:

Le righe 12-13 importano le librerie Qt necessarie esposte tramite cxx-qt.

Per prima cosa creiamo una nuova istanza di QApplication, quindi eseguiamo alcune integrazioni nelle righe 20-26.

Poi arriva la parte che crea effettivamente la finestra dell'applicazione:

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

L'URL lungo qrc:/qt/qml/org/kde/tutorial/src/qml/Main.qml corrisponde al file Main.qml secondo il Qt Resource System, e segue questo schema: <resource_prefix><import_URI><QML_dir><file>.

In altre parole: il prefisso predefinito della risorsa qrc:/qt/qml/ + l'URI di importazione org/kde/tutorial (impostato in build.rs, separato da barre anziché punti) + la directory QML src/qml/ + il file QML 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!"
        }
    }
}

Ecco dove gestiremo l'interfaccia della nostra applicazione.

Se conosci un po' di Javascript, allora la gran parte di QML ti sembrerà familiare (sebbene abbia delle sue caratteristiche proprie)). Se hai voglia di provare a fare qualcosa da solo la documentazione di Qt ha un'ampia quantità di materiale su questo linguaggio. In queste esercitazioni focalizzeremo la nostra attenzione principalmente sul codice QML, nel quale possiamo utilizzare Kirigami per ottenerne il massimo.

Per ora concentriamoci su Main.qml. Per prima cosa importiamo una serie di moduli importanti:

  • QtQuick, la libreria standard utilizzata nelle applicazioni QML.
  • QtQuick Controls, che fornisce una serie di controlli standard che possiamo utilizzare per rendere interattive le nostre applicazioni.
  • QtQuick Layouts, che fornisce strumenti per posizionare i componenti all'interno della finestra dell'applicazione.
  • Kirigami, che fornisce una serie di componenti adatti per creare applicazioni che funzionano su dispositivi di diverse forme e dimensioni.

Arriviamo quindi al nostro elemento di base, Kirigami.ApplicationWindow, che fornisce alcune funzionalità di base necessarie per tutte le applicazioni Kirigami. Questa è la finestra che conterrà ciascuna delle nostre pagine, le sezioni principali della nostra UI.

Successivamente impostiamo la proprietà id della finestra su "root". Gli ID sono utili perché ci consentono di fare riferimento in modo univoco a un componente, anche se ne abbiamo diversi dello stesso tipo.

Impostiamo anche la proprietà title della finestra su "Hello World".

Impostiamo quindi la prima pagina del nostro stack di pagine. La maggior parte delle applicazioni Kirigami sono organizzate come una pila di pagine, ciascuna pagina contenente componenti correlati adatti a un'attività specifica. Per ora, manteniamo le cose semplici e ci atteniamo a una singola pagina. pageStack è una pila di pagine inizialmente vuota fornita da Kirigami.ApplicationWindow e con pageStack.initialPage: Kirigami.Page {...} impostiamo la prima pagina presentata al caricamento dell'applicazione su Kirigami.Pagina. Questa pagina conterrà tutti i nostri contenuti.

Infine, includiamo nella nostra pagina un Controls.Label che ci consente di inserire del testo nella nostra pagina. Usiamo anchors.centerIn: parent per centrare la nostra etichetta orizzontalmente e verticalmente all'interno del nostro elemento genitore. In questo caso, il componente principale della nostra etichetta è Kirigami.Page. L'ultima cosa che dobbiamo fare è impostarne il testo: text: "Hello World!".

Compilazione ed installazione dell'applicazione

Dovresti trovare l'eseguibile generato kirigami_hello sotto build/debug/kirigami_hello e puoi eseguirlo direttamente o con cargo run, ma mancherà un'icona Finestra. Per risolvere questo problema, installeremo prima l'applicazione.

Esegui quanto segue:

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

Con il primo comando, CMake cercherà Kirigami e qqc2-desktop-style.

Con il secondo comando, CMake creerà il target kirigami_rust, che chiama semplicemente cargo build --target-dir build/. Questo passaggio richiederà del tempo per essere completato, ma la prossima volta che ripeterai il secondo comando CMake sarà più veloce o non sarà necessario compilare affatto.

Nel terzo passaggio, CMake installerà l'eseguibile kirigami_hello in ~/.local/bin/kirigami_hello e il file desktop in ~/.local/share/applications, e una nuova voce denominata "Kirigami Tutorial in Rust" apparirà nel menu.

Aprite la voce del menu e voilà! Ora vedrai la tua primissima app Kirigami apparire davanti ai tuoi occhi.

Schermata dell'applicazione in Kirigami generata

Per eseguire la nuova applicazione QML in modalità mobile, puoi utilizzare QT_QUICK_CONTROLS_MOBILE=1:

QT_QUICK_CONTROLS_MOBILE=1 kirigami_hello

Se hai compilato manualmente il progetto con CMake e per qualche motivo desideri disinstallare il progetto, puoi eseguire:

cmake --build build/ --target uninstall