Skip to content

Integrate Qml and Rust by building the QMetaObject at compile time.

License

Notifications You must be signed in to change notification settings

kurumpa/qmetaobject-rs

 
 

Repository files navigation

QMetaObject crate for Rust

The qmetaobject crate is a crate which is used to expose rust object to Qt and QML.

Travis Build Status Appveyor Build status Crates.io Documentation

Objectives

  • Rust procedural macro (custom derive) to generate a QMetaObject at compile time.
  • Bindings for the main Qt types using the cpp! macro from the cpp crate.
  • Users of this crate should not require to type any line of C++ or use another build system than cargo.
  • Performance: Avoid any unnecessary conversion or heap allocation.

Presentation Blog Post: https://woboq.com/blog/qmetaobject-from-rust.html

Overview

extern crate qmetaobject;
use qmetaobject::*;
#[macro_use] extern crate cstr;

#[derive(QObject,Default)]
struct Greeter {
    base : qt_base_class!(trait QObject),
    name : qt_property!(QString; NOTIFY name_changed),
    name_changed : qt_signal!(),
    compute_greetings : qt_method!(fn compute_greetings(&self, verb : String) -> QString {
        return (verb + " " + &self.name.to_string()).into()
    })
}

fn main() {
    qmetaobject::log::init_qt_to_rust();
    qml_register_type::<Greeter>(cstr!("Greeter"), 1, 0, cstr!("Greeter"));
    let mut engine = QmlEngine::new();
    engine.load_data(r#"import QtQuick 2.6; import QtQuick.Window 2.0;
import Greeter 1.0
Window {
    visible: true;
    Greeter { id: greeter; name: 'World'; }
    Text { anchors.centerIn: parent; text: greeter.compute_greetings('hello'); }
}"#.into());
    engine.exec();

}

Features

  • Create object inheriting from QObject, QQuickItem, QAbstractListModel, QQmlExtensionPlugin, ...
  • Export Qt properties, signals, methods, ...
  • Also support #[derive(QGadget)] (same as Q_GADGET)
  • Create Qt plugin (see examples/qmlextensionplugins)
  • Partial scene graph support

Requires Qt >= 5.8

Cargo features

Cargo provides a way to enable (or disable default) optional features.

log

By default, Qt's logging system is not initialized, and messages from e.g. QML's console.log don't go anywhere. The "log" feature enables integration with log crate, the Rust logging facade.

The feature is enabled by default. To activate it, execute the following code as early as possible in main():

fn main() {
    qmetaobject::log::init_qt_to_rust();
    // don't forget to set up env_logger or any other logging backend.
}

chrono_qdatetime

Enables interoperability of QDate and QTime with Rust chrono package.

This feature is disabled by default.

What if a binding for the Qt C++ API you want to use is missing?

It is quite likely that you would like to call a particular Qt function which is not wrapped by this crate.

In this case, it is always possible to access C++ directly from your rust code using the cpp! macro.

Example: from examples/graph/src/main.rs, the struct Graph is a QObject deriving from QQuickItem, QQuickItem::setFlag is currently not exposed in the API but we wish to call it anyway.

impl Graph {
    fn appendSample(&mut self, value: f64) {
        // ...
        let obj = self.get_cpp_object();
        cpp!(unsafe [obj as "QQuickItem*"] { obj->setFlag(QQuickItem::ItemHasContents); });
        // ...
    }
}

But ideally, we should wrap as much as possible so this would not be needed. You can request API as a github issue, or contribute via a pull request.

About

Integrate Qml and Rust by building the QMetaObject at compile time.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 98.1%
  • C++ 1.9%