[][src]Crate qmetaobject

This crate implements binding to the Qt API which allow to use QML from a rust application.

Example:

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

// The `QObject` custom derive macro allows to expose a class to Qt and QML
#[derive(QObject,Default)]
struct Greeter {
    // Specify the base class with the qt_base_class macro
    base : qt_base_class!(trait QObject),
    // Decalare `name` as a property usable from Qt
    name : qt_property!(QString; NOTIFY name_changed),
    // Declare a signal
    name_changed : qt_signal!(),
    // And even a slot
    compute_greetings : qt_method!(fn compute_greetings(&self, verb : String) -> QString {
        return (verb + " " + &self.name.to_string()).into()
    })
}

fn main() {
    // Register the `Greeter` struct to QML
    qml_register_type::<Greeter>(cstr!("Greeter"), 1, 0, cstr!("Greeter"));
    // Create a QML engine from rust
    let mut engine = QmlEngine::new();
    // (Here the QML code is inline, but one can also load from a file)
    engine.load_data(r#"
        import QtQuick 2.6;
        import QtQuick.Window 2.0;
        import Greeter 1.0  // import our Rust classes
        Window {
            visible: true;
            Greeter { //  Instentiate the rust struct
                id: greeter;
                name: 'World'; // set a property
            }
            Text {
                anchors.centerIn: parent;
                // Call a method
                text: greeter.compute_greetings('hello');
            }
        }"#.into());
    engine.exec();
}

Basic types

The re-exported module qttypes contains binding to the most usefull basic types such as QString, QVariant, ...

You can also simply use rust type String, but using QString might avoid unecessary conversions in some case.

Meta type

In order to be able to use a type in a signal or method parameter, or as a property type, the type need to implement the QMetaType trait. All the method are provided so you can just implement the QMetaType like this:

#[derive(Default, Clone)]
struct MyPoint(u32, u32);
impl QMetaType for MyPoint {};

With that it is also possible to put the type in a QVariant

Object pinning

Once an object that derives from QObject is exposed to C++, it needs to be pinned, and cannot be moved in memory. Also, since the Qt code can be re-entrant, the object must be placed in a RefCell. The QObjectPinned object is used to enforce the pinning.

If you want to keep pointer to reference, tou can use QPointer.

Threading

The QML engine only runs in a single thread. And probably all the QObject needs to be living in the Qt thread. But you can use the queued_callback function to create callback that can be called from any thread and are going to run in the Qt thread.

This can be done like so:

#[derive(QObject,Default)]
struct MyAsyncObject {
    base : qt_base_class!(trait QObject),
    result : qt_property!(QString; NOTIFY result_changed),
    result_changed : qt_signal!(),
    recompute_result : qt_method!(fn recompute_result(&self, name : String) {
        let qptr = QPointer::from(&*self);
        let set_value = qmetaobject::queued_callback(move |val : QString| {
            qptr.as_pinned().map(|self_| {
                self_.borrow_mut().result = val;
                self_.borrow().result_changed();
            });
        });
        std::thread::spawn(move || {
            // do stuff asynchroniously ...
            let r = QString::from("Hello ".to_owned() + &name);
            set_value(r);
        }).join();
    })
}

Re-exports

pub use qttypes::*;
pub use itemmodel::*;
pub use listmodel::*;
pub use qtdeclarative::*;
pub use qmetatype::*;
pub use connections::RustSignal;
pub use connections::connect;
pub use connections::CppSignal;
pub use connections::SignalCppRepresentation;
pub use qtquickcontrols2::*;

Modules

connections
itemmodel
listmodel
qmetatype
qrc
qtdeclarative
qtquickcontrols2
qttypes
scenegraph

Macros

qrc

Macro to embed files and made them available to the Qt resource system

qt_base_class

This macro must be used once as a type in a struct that derives from QObject. It is anotate from which QObject like trait it is supposed to derive. the field which it annotate will be an internal property holding a pointer to the actual C++ object

qt_method

This macro can be used to declare a method which will become a meta method.

qt_plugin

Equivalent to the Q_PLUGIN_METADATA macro.

qt_property

This macro can be used as a type of a field and can then turn this field in a Qt property. The first parameter is the type of this property. Then we can have the meta keywords similar to these found in Q_PROPERTY.

qt_signal

Declares a signal

Structs

QMessageLogContext

Wrapper for Qt's QMessageLogContext

QObjectBox

A wrapper around RefCell, whose content cannot be move in memory

QObjectPinned

A reference to a RefCell, where T is a QObject, which does not move in memory

QObjectRefMut

Same as std::cell::RefMut, but does not allow to move from

QPointer

A Wrapper around a QPointer

Enums

QtMsgType

Wrap Qt's QtMsgType enum

Constants

USER_ROLE

Refer to the documentation of Qt::UserRole

Traits

QEnum

Trait that is implemented by the QEnum custom derive macro

QGadget

Trait that is implemented by the QGadget custom derive macro

QObject

Trait that is implemented by the QObject custom derive macro

Functions

install_message_handler

Wrap qt's qInstallMessageHandler. Useful in order to forward the log to a rust logging framework

into_leaked_cpp_ptr

Create the C++ object and return a C++ pointer to a QObject.

queued_callback

Create a callback to invoke a queued callback in the current thread.

single_shot

Call the callback once, after a given duration.