### Run Basic QML Example Source: https://github.com/kdab/cxx-qt/blob/main/README.md Execute the compiled basic QML example from the build directory. ```bash ./build/examples/qml_minimal/example_qml_minimal ``` -------------------------------- ### Example Emscripten Installation Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/wasm-builds.md Example command to install Emscripten version 3.1.14, typically used with Qt 6.4. ```bash ./emsdk install 3.1.14 ``` -------------------------------- ### Run Compiled Example Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Command to execute the compiled CXX-Qt project. ```shell ./build/examples/qml_minimal/example_qml_minimal ``` -------------------------------- ### Basic CMakeLists.txt Setup for Qt Projects Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Standard CMakeLists.txt configuration for C++ projects using Qt, supporting both Qt5 and Qt6 compatibility. ```cmake cmake_minimum_required(VERSION 3.16) project(qml_minimal LANGUAGES CXX) find_package(Qt6 REQUIRED COMPONENTS Qml Quick) target_compile_features(qml_minimal PRIVATE cxx_std_17 ) qt_add_executable(qml_minimal main.cpp) target_link_libraries(qml_minimal PRIVATE Qt6::Qml Qt6::Quick ) qt_add_qml_module(qml_minimal URI "com.mycompany.example" VERSION 1.0 QML_FILES qml/main.qml ) ``` -------------------------------- ### Install and Activate Emscripten SDK Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/wasm-builds.md Installs and activates a specific Emscripten version. Ensure this matches the version used to build your Qt WebAssembly installation. ```bash ./emsdk install ./emsdk activate source ./emsdk_env.sh ``` -------------------------------- ### CXX-Qt and Qt Component Setup Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_minimal/CMakeLists.txt Enables CMake's automatic handling of Qt's MOC, C++ standard, and defines the necessary Qt components for CXX-Qt. This prepares the build environment for Qt integration. ```cmake set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CXXQT_QTCOMPONENTS Core Gui Qml QuickControls2 QuickTest Test) ``` -------------------------------- ### Demo Threading Example Error Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/wasm-builds.md This error message arises when attempting to build the `demo_threading` example for WebAssembly, often due to upstream issues with libraries like `async-std` or `socket2` not supporting WASM. ```console error[E0433]: failed to resolve: use of undeclared type `IovLen` ``` -------------------------------- ### Minimal QML GUI Example Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/3-qml-gui.md This QML code defines a basic GUI with labels and buttons, demonstrating the integration of a Rust-defined QObject. It showcases property binding and interaction with the Rust backend. ```qml import QtQuick import QtQuick.Controls ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Hello World") Column { anchors.centerIn: parent spacing: 10 Label { text: qsTr("Hello from Rust!") font.pixelSize: 20 anchors.horizontalCenter: parent.horizontalCenter } Label { text: myObject.string font.pixelSize: 16 anchors.horizontalCenter: parent.horizontalCenter } Row { spacing: 10 anchors.horizontalCenter: parent.horizontalCenter Button { text: qsTr("Increment") onClicked: myObject.increment() } Button { text: qsTr("Decrement") onClicked: myObject.decrement() } } } MyObject { id: myObject // Property binding: myObject.string is bound to myObject.number // This means that whenever myObject.number changes, myObject.string will update automatically. // The QML engine handles this automatically. string: number.toString() } } ``` -------------------------------- ### C++ main function for QML application Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md A basic C++ main file to start a QML application. Place this in a 'cpp' folder to separate C++ and Rust code. ```cpp #include #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; // Load QML file from the application's resources engine.load(QUrl(QStringLiteral("qrc:main.qml"))); if (engine.rootObjects().isEmpty()) { return -1; } return app.exec(); } ``` -------------------------------- ### Basic CMake Project Setup Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_minimal/CMakeLists.txt Sets the minimum CMake version and project name. It also configures the MSVC runtime library for non-debug builds, which is important for Rust compatibility. ```cmake cmake_minimum_required(VERSION 3.24) project(example_qml_minimal) # Rust always links against non-debug Windows runtime on *-msvc targets # Note it is best to set this on the command line to ensure all targets are consistent # https://github.com/corrosion-rs/corrosion/blob/master/doc/src/common_issues.md#linking-debug-cc-libraries-into-rust-fails-on-windows-msvc-targets # https://github.com/rust-lang/rust/issues/39016 if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL") endif() ``` -------------------------------- ### Run Tests with CTest Source: https://github.com/kdab/cxx-qt/blob/main/README.md Execute all tests for the CXX-Qt project using CTest, which assumes clippy, fmt, mdbook, mdbook-linkcheck, reuse, and valgrind are installed. ```bash ctest --test-dir build ``` -------------------------------- ### Expose Rust Types and Methods to Qt/C++ Source: https://context7.com/kdab/cxx-qt/llms.txt Use `extern "RustQt"` to declare Rust types and function signatures for C++ header generation. This example defines a `QObject` with custom QML naming, singleton exposure, and properties with custom getters/setters. ```rust #[cxx_qt::bridge] pub mod qobject { extern "RustQt" { // #[qobject] generates a QObject subclass in C++ backed by the Rust struct #[qobject] #[qml_element = "MyWidget"] // custom QML name #[qml_singleton] // expose as a singleton in QML #[qproperty(i32, count)] #[qproperty(bool, active, READ = is_active, WRITE = set_active, NOTIFY = active_changed)] type MyWidget = super::MyWidgetRust; // Regular C++ method (not Q_INVOKABLE) fn reset(self: Pin<&mut MyWidget>); // Q_INVOKABLE — callable from QML #[qinvokable] fn do_work(&self, value: i32) -> i32; } } #[derive(Default)] pub struct MyWidgetRust { count: i32, active: bool, } impl qobject::MyWidget { pub fn reset(self: Pin<&mut Self>) { self.set_count(0); } // Custom getter for active property pub fn is_active(&self) -> &bool { &self.rust().active } pub fn do_work(&self, value: i32) -> i32 { value * 2 } } ``` -------------------------------- ### Main function for Qt Application Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/4-cargo-executable.md This `main` function sets up a Qt application by creating a `QGuiApplication` and `QQmlApplicationEngine`, loading a QML file, and running the application event loop. ```rust fn main() { let app = QApplication::new(); let engine = QQmlApplicationEngine::new(); engine.load_file("qml/main.qml"); app.exec()) } ``` -------------------------------- ### Configure and Build with CMake Source: https://github.com/kdab/cxx-qt/blob/main/README.md Configure the CXX-Qt project using CMake and then build it. This process uses Cargo under the hood. ```bash cmake -S . -B build cmake --build build ``` -------------------------------- ### Property with Custom Reset Function Source: https://github.com/kdab/cxx-qt/blob/main/book/src/bridge/extern_rustqt.md Example of specifying a custom reset function for a property. The `RESET` flag requires a user-defined function to be provided. ```rust #[qproperty(i32, num, RESET = my_reset)] ``` -------------------------------- ### Using qmllint with CXX-Qt QML Modules Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/build_systems.md This command shows how to execute qmllint with the necessary QML import paths for CXX-Qt generated QML modules. Ensure the path to `cxxqt/qml_modules` is correctly specified. ```console qmllint -I /path/to/cxxqt/qml_modules /path/to/test.qml ``` -------------------------------- ### Compile and Link CXX-Qt Project Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/wasm-builds.md Compile and link the CXX-Qt project after configuration. This command should be run from the build directory. ```bash $ cmake --build build ``` -------------------------------- ### Read-Only Property with Auto-Generated Getter Source: https://github.com/kdab/cxx-qt/blob/main/book/src/bridge/extern_rustqt.md Example of defining a read-only property using `#[qproperty]` with the `READ` flag. CXX-Qt will automatically generate the getter function. ```rust #[qproperty(i32, num, READ)] ``` -------------------------------- ### Manual Initializer Calls in `main` Source: https://github.com/kdab/cxx-qt/blob/main/book/src/common-issues.md For older linkers or to ensure initialization, manually call `init_crate!` and `init_qml_module!` macros from the `cxx_qt` crate at startup. ```rust fn main() { cxx_qt::init_crate!(another_crate); cxx_qt::init_qml_module!("com.kdab.cxx_qt.demo"); } ``` -------------------------------- ### Unit Test Executable Configuration Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_features/CMakeLists.txt Sets up the unit test executable, including its source files, include directories, and linked libraries. ```cmake if(BUILD_TESTING) # # Unit test # set(APP_TEST_NAME ${APP_NAME}_test) add_executable(${APP_TEST_NAME} tests/main.cpp) target_include_directories(${APP_TEST_NAME} PRIVATE cpp) target_link_libraries( ${APP_TEST_NAME} PRIVATE ${CRATE}_qml Qt::Test Qt::QuickTest Qt::Core Qt::Gui Qt::Qml Qt::QuickControls2 ) qt_import_qml_plugins(${APP_TEST_NAME}) set(TEST_CMD $ -input ${CMAKE_CURRENT_SOURCE_DIR}/tests ) add_test( NAME ${APP_TEST_NAME} COMMAND ${TEST_CMD} ) # Unfortunately due to the static linking in our CI on macOS we can't load the # offscreen plugin, so just leave it at the default. if (NOT APPLE) set_tests_properties(${APP_TEST_NAME} PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=offscreen") endif() # RUNTIME_ENV comes from the CMakeLists.txt at the root of this repository. set_tests_properties( ${APP_TEST_NAME} PROPERTIES ENVIRONMENT_MODIFICATION "${RUNTIME_ENV}" ) if (COMMAND add_valgrind_test) add_valgrind_test( ${APP_TEST_NAME} "${TEST_CMD}" ${CMAKE_CURRENT_BINARY_DIR} ) else() MESSAGE(STATUS "add_valgrind_test is defined in the top level of CXX-Qt. It will not executed") endif() # qmllint --max-warnings only exists in Qt 6 if(Qt6_FOUND AND Qt6_VERSION VERSION_GREATER_EQUAL 6.8.0) find_program(QMLLINT_COMMAND qmllint PATHS "${QT_INSTALL_BINS}") if("${QMLLINT_COMMAND}" STREQUAL "QMLLINT_COMMAND-NOTFOUND") MESSAGE(STATUS "qmllint not found. Please install it. Skipping qmllint tests.") else() file(GLOB QMLLINT_QML_FILES ${CMAKE_CURRENT_SOURCE_DIR}/qml/**/*.qml) add_test(NAME example_qml_features_qmllint_check COMMAND ${QMLLINT_COMMAND} --max-warnings 0 -I ${CMAKE_CURRENT_BINARY_DIR}/cxxqt/qml_modules ${QMLLINT_QML_FILES}) endif() endif() endif() ``` -------------------------------- ### Property with Custom Rust Name Source: https://github.com/kdab/cxx-qt/blob/main/book/src/bridge/extern_rustqt.md Example of specifying a custom name for a property on the Rust side using the `rust_name` attribute. This affects both the property name and any auto-generated function names. ```rust #[qproperty(i32, num, rust_name = "my_number")] ``` -------------------------------- ### Property with Custom C++ Name Source: https://github.com/kdab/cxx-qt/blob/main/book/src/bridge/extern_rustqt.md Example of specifying a custom name for a property on the C++ side using the `cxx_name` attribute. This affects both the property name and any auto-generated function names. ```rust #[qproperty(i32, num, cxx_name = "numberProp")] ``` -------------------------------- ### Configure CXX-Qt Build Script Source: https://context7.com/kdab/cxx-qt/llms.txt Use CxxQtBuilder in `build.rs` to specify Rust source files with `#[cxx_qt::bridge]` macros, declare QML modules, and link additional Qt modules. ```rust use cxx_qt_build::{CxxQtBuilder, QmlModule}; fn main() { CxxQtBuilder::new() // Add each Rust source file containing a #[cxx_qt::bridge] .file("src/my_object.rs") .file("src/another_object.rs") // Declare a QML module for QML-registered types .qml_module( QmlModule::new("com.mycompany.myapp") .qml_file("qml/main.qml") .qml_file("qml/MyPage.qml"), ) // Link additional Qt modules beyond Core/Gui/Qml .qt_module("Network") .qt_module("Multimedia") .build(); } ``` -------------------------------- ### Application Include Directories and Libraries Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_features/CMakeLists.txt Configures include directories and links necessary libraries for the main application executable. ```cmake target_include_directories(${APP_NAME} PRIVATE cpp) target_link_libraries(${APP_NAME} PRIVATE ${CRATE}_qml Qt::Core Qt::Gui Qt::Qml Qt::QuickControls2) ``` -------------------------------- ### Build Project with CMake Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Commands to configure and build the project using CMake. ```shell cmake -S . -B build cmake --build build ``` -------------------------------- ### Custom Getter, Auto Setter, and Notify Signal Source: https://github.com/kdab/cxx-qt/blob/main/book/src/bridge/extern_rustqt.md Example of a property with a custom getter function (`myGetter`), an auto-generated setter, and an auto-generated notify signal. The `READ` flag is required when specifying other flags. ```rust #[qproperty(i32, num, READ = myGetter, WRITE, NOTIFY)] ``` -------------------------------- ### Running the Cargo Project Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/4-cargo-executable.md Use the `cargo run` command to build and execute your CXX-Qt application. If the project is part of a larger workspace, specify the package name using `-p`. ```shell cargo run ``` ```shell cargo run -p qml-minimal-no-cmake ``` -------------------------------- ### Run CXX-Qt WASM Application Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/wasm-builds.md Execute a compiled CXX-Qt WebAssembly application using `emrun`. The path to the HTML file will vary based on the application name. ```bash $ emrun ./build/examples/qml_minimal/example_qml_minimal.html ``` -------------------------------- ### Explicit CXX Trait and CXX-Qt Trait Implementations Source: https://github.com/kdab/cxx-qt/blob/main/book/src/bridge/traits.md Demonstrates explicit CXX trait implementation for `UniquePtr` and CXX-Qt trait implementation for a custom trait. These are used within `#[cxx_qt::bridge]` to guide code generation. ```rust impl UniquePtr {} // explicit CXX trait implementation of UniquePtr for A ``` ```rust impl cxx_qt::Trait for A {} // explicit CXX-Qt trait implementation of Trait for A ``` -------------------------------- ### Declare CXX-Qt Bridge Module with Namespace Source: https://context7.com/kdab/cxx-qt/llms.txt Use the `#[cxx_qt::bridge]` macro to declare a bridge module. The `namespace` argument scopes generated C++ items. This example defines a `QObject` implemented in Rust with properties and invokable methods. ```rust use core::pin::Pin; use cxx_qt_lib::QString; #[cxx_qt::bridge(namespace = "my_object")] pub mod qobject { // Import a Qt type from cxx-qt-lib unsafe extern "C++" { include!("cxx-qt-lib/qstring.h"); type QString = cxx_qt_lib::QString; } // Declare a QObject implemented in Rust extern "RustQt" { #[qobject] #[qml_element] // registers as a QML type automatically #[qproperty(i32, number)] // generates getter/setter/changed-signal #[qproperty(QString, string)] type MyObject = super::MyObjectRust; // Q_INVOKABLE methods callable from QML/C++ #[qinvokable] #[cxx_name = "incrementNumber"] fn increment_number(self: Pin<&mut Self>); #[qinvokable] #[cxx_name = "sayHi"] fn say_hi(&self, string: &QString, number: i32); } } // The backing Rust struct — must implement Default (or cxx_qt::Constructor) #[derive(Default)] pub struct MyObjectRust { number: i32, string: QString, } // Implement methods on the generated C++ QObject type impl qobject::MyObject { pub fn increment_number(self: Pin<&mut Self>) { let previous = *self.number(); self.set_number(previous + 1); } pub fn say_hi(&self, string: &QString, number: i32) { println!("Hi from Rust! String is '{}' and number is {}\n", string, number); } } ``` -------------------------------- ### Check qmake Version Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/index.md Verify that qmake is accessible in your system's PATH. If not, you may need to add it or specify the path using the QMAKE environment variable. ```shell qmake --version QMake version 3.1 Using Qt version 6.5.1 in /usr/lib64 ``` -------------------------------- ### Fetch CXX-Qt using FetchContent in CMake Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Integrates CXX-Qt into your CMake project using FetchContent, specifying a Git tag for version control. ```cmake include(FetchContent) FetchContent_Declare( cxx_qt GIT_REPOSITORY https://github.com/KDAB/cxx-qt.git GIT_TAG 0.8.1 ) FetchContent_MakeAvailable(cxx_qt) ``` -------------------------------- ### Cargo.toml for static library build Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Configure Cargo.toml to build a static library, include necessary dependencies like cxx, cxx-qt, cxx-qt-lib, and cxx-qt-build with the 'link_qt_object_files' feature. ```toml [package] name = "qml_minimal" version = "0.1.0" edition = "2021" [lib] crate-type = ["staticlib"] [dependencies] cxx = "1.0.95" cxx-qt = "0.8" cxx-qt-lib = { version="0.8", features = ["qt_full"] } [build-dependencies] # The link_qt_object_files feature is required for statically linking Qt 6. cxx-qt-build = { version = "0.8", features = [ "link_qt_object_files" ] } ``` -------------------------------- ### Initialize Rust Project with Cargo Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/2-our-first-cxx-qt-module.md Use `cargo new` to create a new Rust project for your CXX-Qt module. This sets up the basic project structure. ```shell $ cargo new qml_minimal $ cd qml_minimal ``` -------------------------------- ### Qt Package Discovery Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_multi_crates/CMakeLists.txt Finds either Qt6 or Qt5 components based on availability. Requires Qt5 5.15 or later if Qt6 is not found. ```cmake if(NOT USE_QT5) find_package(Qt6 COMPONENTS ${CXXQT_QTCOMPONENTS}) set(Qt "Qt6") endif() if(NOT Qt6_FOUND) find_package(Qt5 5.15 COMPONENTS ${CXXQT_QTCOMPONENTS} REQUIRED) set(Qt "Qt5") endif() ``` -------------------------------- ### Link Libraries and Import QML Plugins Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_minimal/CMakeLists.txt Links the main executable to the imported QML module and imports any necessary QML plugins. This step ensures that the application can correctly load and use QML components. ```cmake # Link to the qml module, which in turn links to the Rust qml_minimal library target_link_libraries(example_qml_minimal PRIVATE qml_minimal_qml_module) # If we are using a statically linked Qt then we need to import any qml plugins qt_import_qml_plugins(example_qml_minimal) ``` -------------------------------- ### Shorthand for `cxx_qt::Constructor` Source: https://github.com/kdab/cxx-qt/blob/main/book/src/bridge/extern_rustqt.md A shorthand `impl cxx_qt::Initialize for x {}` is available as a simpler way to implement the `cxx_qt::Constructor` trait within the bridge. ```rust impl cxx_qt::Initialize for MyObjectRust {} ``` -------------------------------- ### Define CXX-Qt Bridge Module Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/2-our-first-cxx-qt-module.md Create the Rust module file (`src/cxxqt_object.rs`) and use the `#[cxx_qt::bridge]` macro to enable interaction between Rust and Qt. ```rust #[cxx_qt::bridge] mod cxxqt_object { // ... } ``` -------------------------------- ### CXX-Qt Project Settings Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_features/CMakeLists.txt Configures essential C++ and Qt build settings, including enabling automoc, setting the C++ standard, and defining required Qt components. ```cmake set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CXXQT_QTCOMPONENTS Core Gui Qml Quick QuickControls2 QuickTest Test) if(NOT BUILD_WASM) set(CXXQT_QTCOMPONENTS ${CXXQT_QTCOMPONENTS} QmlImportScanner) endif() ``` -------------------------------- ### build.rs for CXX-Qt Compilation Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/4-cargo-executable.md This `build.rs` script is essential for generating C++ code from Rust using `#[cxx_qt::bridge]` macros and for linking Qt to your Rust binary. It also defines the QML module. ```rust use cxx_qt_build::CxxQtBuilder; fn main() { CxxQtBuilder::new() .file("src/cxxqt_object.rs") .qml_module( "com.kdab.cxx_qt", "1.0", "qml", &["src/MyObject.qml"], ) .build(); } ``` -------------------------------- ### Using cxx-qt-lib Qt Types in Rust Source: https://context7.com/kdab/cxx-qt/llms.txt Leverage pre-built Rust bindings for common Qt types provided by the `cxx-qt-lib` crate. Ensure correct feature flags are enabled in `Cargo.toml`. ```rust use cxx_qt_lib::{ QString, QUrl, QColor, QDateTime, QPoint, QSize, QRect, QVariant, QModelIndex, QList, QVector, QSet, QMap, QHash, QStringList, }; // QString — bidirectional conversion let s = QString::from("Hello, Qt!"); let rs: String = s.to_string(); // QVariant — type-erased value container let v = QVariant::from(&42_i32); let v2 = QVariant::from(&QString::from("text")); // Container types — must use the naming convention TYPE_ElementType // in the bridge declaration: // type QList_QString = cxx_qt_lib::QList; // type QSet_i32 = cxx_qt_lib::QSet; // type QHash_QString_QVariant = cxx_qt_lib::QHash; // Custom type with QVariant — implement QVariantValue struct MyPoint { x: f64, y: f64 } // impl cxx_qt_lib::QVariantValue for MyPoint { ... } // Enabling features in Cargo.toml for selective Qt module linking: // cxx-qt-lib = { version = "0.8", features = ["qt_full"] } // Individual feature flags: qt_gui, qt_qml, qt_quickcontrols2, etc. ``` -------------------------------- ### Import QML Module Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_features/CMakeLists.txt Imports a QML module using cxx_qt_import_qml_module, linking it to a source Rust crate. ```cmake cxx_qt_import_qml_module(${CRATE}_qml URI "com.kdab.cxx_qt.demo" SOURCE_CRATE ${CRATE}) ``` -------------------------------- ### Import Rust Crate for CXX-Qt Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_features/CMakeLists.txt Imports a Rust crate using cxx_qt_import_crate, specifying the manifest path, crate name, and required Qt modules. ```cmake set(CRATE qml_features) cxx_qt_import_crate( MANIFEST_PATH rust/Cargo.toml CRATES ${CRATE} LOCKED QT_MODULES Qt::Core Qt::Gui Qt::Qml Qt::Quick ) ``` -------------------------------- ### Rust build script for CXX-Qt integration Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md A build.rs script that generates and compiles C++ code for CXX-Qt objects at build time. It also defines the QML module with a QML URI and version. ```rust use cxx_qt_build::CxxQtBuilder; fn main() { CxxQtBuilder::new() .qml_module( "com.kdab.cxx_qt.examples.qml_minimal", "1.0", "qml", ) .expect("Failed to create QML module") .build(); } ``` -------------------------------- ### Declare a CXX-Qt bridge module with `#[cxx_qt::bridge]` Source: https://context7.com/kdab/cxx-qt/llms.txt The `#[cxx_qt::bridge]` attribute macro is the entry point for all CXX-Qt functionality. It allows defining Rust types as Qt objects with properties and invokable methods. ```APIDOC ## `#[cxx_qt::bridge]` — Declare a CXX-Qt bridge module The `#[cxx_qt::bridge]` attribute macro is the entry point for all CXX-Qt functionality. It is a superset of `#[cxx::bridge]` and supports `extern "RustQt"` and `extern "C++Qt"` blocks in addition to the standard CXX blocks. An optional `namespace` argument scopes all generated C++ items into that namespace. ```rust // src/cxxqt_object.rs #[cxx_qt::bridge(namespace = "my_object")] pub mod qobject { // Import a Qt type from cxx-qt-lib unsafe extern "C++" { include!("cxx-qt-lib/qstring.h"); type QString = cxx_qt_lib::QString; } // Declare a QObject implemented in Rust extern "RustQt" { #[qobject] #[qml_element] // registers as a QML type automatically #[qproperty(i32, number)] // generates getter/setter/changed-signal #[qproperty(QString, string)] type MyObject = super::MyObjectRust; // Q_INVOKABLE methods callable from QML/C++ #[qinvokable] #[cxx_name = "incrementNumber"] fn increment_number(self: Pin<&mut Self>); #[qinvokable] #[cxx_name = "sayHi"] fn say_hi(&self, string: &QString, number: i32); } } use core::pin::Pin; use cxx_qt_lib::QString; // The backing Rust struct — must implement Default (or cxx_qt::Constructor) #[derive(Default)] pub struct MyObjectRust { number: i32, string: QString, } // Implement methods on the generated C++ QObject type impl qobject::MyObject { pub fn increment_number(self: Pin<&mut Self>) { let previous = *self.number(); self.set_number(previous + 1); } pub fn say_hi(&self, string: &QString, number: i32) { println!("Hi from Rust! String is '{string}' and number is {number}"); } } ``` ``` -------------------------------- ### Importing QString for CXX-Qt Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/2-our-first-cxx-qt-module.md Include necessary types from the cxx_qt_lib crate to use Qt types like QString within your CXX bridge. ```rust use cxx_qt_lib::QString; use my_object::qobject; ``` -------------------------------- ### Build CXX-Qt WASM with Generic CMake Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/wasm-builds.md Configure CXX-Qt for WebAssembly builds using a generic CMake binary. Specify the toolchain file and set `BUILD_WASM` to ON. ```bash $ -DCMAKE_TOOLCHAIN_FILE=/path/to/qt.toolchain.cmake -DBUILD_WASM=ON -B build . ``` -------------------------------- ### Build CXX-Qt WASM with Qt CMake Source: https://github.com/kdab/cxx-qt/blob/main/book/src/concepts/wasm-builds.md Configure CXX-Qt for WebAssembly builds using the `qt-cmake` binary. Ensure the `BUILD_WASM` option is set to ON. ```bash $ /path/to/qt-cmake -DBUILD_WASM=ON -B build . ``` -------------------------------- ### Importing CXX-Qt Types in main.rs Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/4-cargo-executable.md Import necessary types from `cxx_qt` and `qt_core` to initialize and run a Qt application within your Rust executable. ```rust use cxx_qt::CxxQt; use qt_core::{ gui::QGuiApplication, QApplication, QObject, QVariant, Vec3, }; use qt_engine::QQmlApplicationEngine; #[derive(Default)] struct MyObject; impl MyObject { fn new() -> Self { Default::default() } } impl QObject for MyObject {} impl CxxQt for MyObject {} ``` -------------------------------- ### Import Rust Crate for QML Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_multi_crates/CMakeLists.txt Imports a Rust crate as a static library for use with CxxQt. Specifies the manifest path, crate name, and required Qt modules. ```cmake cxx_qt_import_crate(MANIFEST_PATH rust/main/Cargo.toml CRATES qml_multi_crates CRATE_TYPES staticlib LOCKED QT_MODULES Qt::Core Qt::Gui Qt::Qml Qt::QuickControls2 Qt::Network ) ``` -------------------------------- ### C++ Main File for CXX-Qt CMake Integration Source: https://context7.com/kdab/cxx-qt/llms.txt Include the generated C++ header and load the QML module in your C++ application's main file. ```cpp // cpp/main.cpp — The generated header is named after the Rust file #include int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); QQmlApplicationEngine engine; engine.loadFromModule("com.mycompany.myapp", "Main"); return app.exec(); } ``` -------------------------------- ### Import QML Plugins Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_features/CMakeLists.txt Imports QML plugins for the specified application target. ```cmake qt_import_qml_plugins(${APP_NAME}) ``` -------------------------------- ### Fetch CxxQt CMake Module Source: https://github.com/kdab/cxx-qt/blob/main/examples/qml_multi_crates/CMakeLists.txt Fetches the CxxQt CMake module from GitHub if it's not found locally. Uses the 'main' branch. ```cmake find_package(CxxQt QUIET) if(NOT CxxQt_FOUND) include(FetchContent) FetchContent_Declare( CxxQt GIT_REPOSITORY https://github.com/kdab/cxx-qt-cmake.git GIT_TAG main ) FetchContent_MakeAvailable(CxxQt) endif() ``` -------------------------------- ### Instantiate QObjects Directly in Rust Source: https://context7.com/kdab/cxx-qt/llms.txt Use CXX-Qt helper templates like `make_unique` to construct `QObject` instances directly from Rust code. ```rust #[cxx_qt::bridge] pub mod qobject { extern "RustQt" { #[qobject] type MyObject = super::MyObjectRust; } // Expose the make_unique helper template from cxx-qt-lib #[namespace = "rust::cxxqtlib1"] unsafe extern "C++" { include!("cxx-qt-lib/common.h"); // Default constructor #[rust_name = "new_my_object"] fn make_unique() -> UniquePtr; // Constructor with QObject parent #[rust_name = "new_my_object_with_parent"] fn make_unique(parent: *mut QObject) -> UniquePtr; } } use cxx::UniquePtr; fn create_object() -> UniquePtr { // Create a heap-allocated QObject wrapped in UniquePtr (auto-deleted on drop) qobject::new_my_object() } ``` -------------------------------- ### Expose Rust types and methods to Qt/C++ using `extern "RustQt"` Source: https://context7.com/kdab/cxx-qt/llms.txt The `extern "RustQt"` block within a `#[cxx_qt::bridge]` module declares Rust types and function signatures that will be generated into C++ headers, enabling interoperability with Qt/C++. ```APIDOC ## `extern "RustQt"` — Expose Rust types and methods to Qt/C++ The `extern "RustQt"` block declares Rust types and function signatures that will be generated into C++ headers. CXX-Qt produces a `.cxxqt.h` header file (named after the Rust source file) with the corresponding C++ declarations. ```rust #[cxx_qt::bridge] pub mod qobject { extern "RustQt" { // #[qobject] generates a QObject subclass in C++ backed by the Rust struct #[qobject] #[qml_element = "MyWidget"] // custom QML name #[qml_singleton] // expose as a singleton in QML #[qproperty(i32, count)] #[qproperty(bool, active, READ = is_active, WRITE = set_active, NOTIFY = active_changed)] type MyWidget = super::MyWidgetRust; // Regular C++ method (not Q_INVOKABLE) fn reset(self: Pin<&mut MyWidget>); // Q_INVOKABLE — callable from QML #[qinvokable] fn do_work(&self, value: i32) -> i32; } } #[derive(Default)] pub struct MyWidgetRust { count: i32, active: bool, } impl qobject::MyWidget { pub fn reset(self: Pin<&mut Self>) { self.set_count(0); } // Custom getter for active property pub fn is_active(&self) -> &bool { &self.rust().active } pub fn do_work(&self, value: i32) -> i32 { value * 2 } } ``` ``` -------------------------------- ### Import Rust Crate with CXX-Qt CMake Wrapper Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Uses the `cxx_qt_import_crate` CMake function to import a Rust crate, specifying required Qt modules. ```cmake cxx_qt_import_crate( CRATE "qml_minimal" QT_MODULES Qt6::Qml Qt6::Quick ) ``` -------------------------------- ### Create Executable Target and Link CXX-Qt Module Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Defines the main executable target for the project and links it against the CXX-Qt generated QML module target. ```cmake add_executable(example_qml_minimal main.cpp) target_link_libraries(example_qml_minimal PRIVATE qml_minimal_qml_module) ``` -------------------------------- ### Declare CXX-Qt Module in `lib.rs` Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/2-our-first-cxx-qt-module.md Inform Cargo about the CXX-Qt module you are about to create by adding the module statement in your `src/lib.rs` file. ```rust cxx_qt::module::rust_token!(); ``` -------------------------------- ### Import QML Module with CXX-Qt CMake Wrapper Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/5-cmake-integration.md Imports a QML module as a CMake target using `cxx_qt_import_qml_module`, linking it to the source Rust crate. ```cmake cxx_qt_import_qml_module( TARGET_NAME qml_minimal_qml_module URI "com.mycompany.example" SOURCE_CRATE qml_minimal ) ``` -------------------------------- ### Importing Necessary Items for Implementation Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/2-our-first-cxx-qt-module.md Ensure all required types and traits are imported when implementing invokable methods for your QObject. ```rust use my_object::qobject; use std::pin::Pin; ``` -------------------------------- ### Cargo.toml Dependencies for CXX-Qt Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/4-cargo-executable.md Add these dependencies to your `Cargo.toml` file to use CXX-Qt. The `cxx-qt-build` dependency with the `link_qt_object_files` feature is crucial for statically linking Qt 6. ```toml cxx = "1.0.95" cxx-qt = "0.8" cxx-qt-lib = { version="0.8", features = ["qt_full"] } [build-dependencies] # The link_qt_object_files feature is required for statically linking Qt 6. cxx-qt-build = { version = "0.8", features = [ "link_qt_object_files" ] } ``` -------------------------------- ### Create a QObject Subclass with Properties Source: https://github.com/kdab/cxx-qt/blob/main/book/src/getting-started/2-our-first-cxx-qt-module.md Use `#[qobject]` and `#[qproperty]` to define a new `QObject` subclass in Rust with properties that can be accessed from C++ and QML. ```rust #[qobject] #[qml_element] struct MyObject; impl MyObject { #[qproperty] number: i32; #[qproperty] string: QString; } ``` -------------------------------- ### Inherit from Qt C++ Classes with `#[base]` and `#[inherit]` Source: https://context7.com/kdab/cxx-qt/llms.txt Use `#[base = T]` on `#[qobject]` to set the C++ base class and `#[inherit]` in `extern "RustQt"` to access base class methods from Rust. Override virtual methods using `#[cxx_override]`, `#[cxx_virtual]`, and `#[cxx_final]`. ```rust #[cxx_qt::bridge] pub mod qobject { unsafe extern "C++Qt" { include!(); #[qobject] type QAbstractListModel; } unsafe extern "C++" { include!("cxx-qt-lib/qvariant.h"); type QVariant = cxx_qt_lib::QVariant; include!("cxx-qt-lib/qmodelindex.h"); type QModelIndex = cxx_qt_lib::QModelIndex; } extern "RustQt" { #[qobject] #[base = QAbstractListModel] #[qml_element] type MyListModel = super::MyListModelRust; // Override virtual methods from QAbstractListModel #[qinvokable] #[cxx_override] #[cxx_name = "rowCount"] fn row_count(self: &MyListModel, parent: &QModelIndex) -> i32; #[qinvokable] #[cxx_override] fn data(self: &MyListModel, index: &QModelIndex, role: i32) -> QVariant; // Access base class methods from Rust #[inherit] #[cxx_name = "beginResetModel"] unsafe fn begin_reset_model(self: Pin<&mut MyListModel>); #[inherit] #[cxx_name = "endResetModel"] unsafe fn end_reset_model(self: Pin<&mut MyListModel>); } } use core::pin::Pin; use cxx_qt_lib::{QModelIndex, QVariant}; #[derive(Default)] pub struct MyListModelRust { items: Vec, } impl qobject::MyListModel { pub fn row_count(&self, _parent: &QModelIndex) -> i32 { self.items.len() as i32 } pub fn data(&self, index: &QModelIndex, _role: i32) -> QVariant { self.items .get(index.row() as usize) .map(|s| QVariant::from(&cxx_qt_lib::QString::from(s.as_str()))) .unwrap_or_default() } pub fn reset(mut self: Pin<&mut Self>) { unsafe { self.as_mut().begin_reset_model(); self.as_mut().rust_mut().items.clear(); self.as_mut().end_reset_model(); } } } ```