|
| 1 | +// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]> |
| 2 | +// SPDX-FileContributor: Andrew Hayzen <[email protected]> |
| 3 | +// |
| 4 | +// SPDX-License-Identifier: MIT OR Apache-2.0 |
| 5 | + |
| 6 | +//! This example shows how a custom parent class can be used to inherit from a QQuickItem based object. |
| 7 | +
|
| 8 | +/// A CXX-Qt bridge which shows a custom parent class can be used |
| 9 | +#[cxx_qt::bridge(cxx_file_stem = "custom_parent_class")] |
| 10 | +mod ffi { |
| 11 | + unsafe extern "C++" { |
| 12 | + /// QColor from cxx_qt_lib |
| 13 | + type QColor = cxx_qt_lib::QColor; |
| 14 | + include!("cxx-qt-lib/qcolor.h"); |
| 15 | + |
| 16 | + /// QRectF from cxx_qt_lib |
| 17 | + type QRectF = cxx_qt_lib::QRectF; |
| 18 | + include!("cxx-qt-lib/qrectf.h"); |
| 19 | + |
| 20 | + /// QSizeF from cxx_qt_lib |
| 21 | + type QSizeF = cxx_qt_lib::QSizeF; |
| 22 | + include!("cxx-qt-lib/qsizef.h"); |
| 23 | + } |
| 24 | + |
| 25 | + // Define the API from QPainter that we need |
| 26 | + unsafe extern "C++" { |
| 27 | + /// QPainter from Qt |
| 28 | + type QPainter; |
| 29 | + include!(<QtGui/QPainter>); |
| 30 | + |
| 31 | + /// QPainter::fillRect from Qt |
| 32 | + #[rust_name = "fill_rect"] |
| 33 | + fn fillRect(self: Pin<&mut QPainter>, rectangle: &QRectF, color: &QColor); |
| 34 | + } |
| 35 | + |
| 36 | + // Define the API from QtQuick that we need |
| 37 | + unsafe extern "C++" { |
| 38 | + /// Define QQuickItem as a type |
| 39 | + type QQuickItem; |
| 40 | + include!(<QtQuick/QQuickItem>); |
| 41 | + |
| 42 | + include!(<QtQuick/QQuickPaintedItem>); |
| 43 | + } |
| 44 | + |
| 45 | + /// A struct which inherits from QQuickPaintedItem |
| 46 | + /// |
| 47 | + /// Which has a parent of the type QQuickItem rather than QObject. |
| 48 | + #[cxx_qt::qobject( |
| 49 | + base = "QQuickPaintedItem", |
| 50 | + qml_uri = "com.kdab.cxx_qt.demo", |
| 51 | + qml_version = "1.0" |
| 52 | + )] |
| 53 | + #[derive(Default)] |
| 54 | + pub struct CustomParentClass { |
| 55 | + #[qproperty] |
| 56 | + color: QColor, |
| 57 | + } |
| 58 | + |
| 59 | + impl cxx_qt::Constructor<()> for qobject::CustomParentClass {} |
| 60 | + |
| 61 | + unsafe extern "RustQt" { |
| 62 | + /// Override QQuickPaintedItem::paint to draw two rectangles in Rust using QPainter |
| 63 | + #[qinvokable(cxx_override)] |
| 64 | + unsafe fn paint(self: Pin<&mut qobject::CustomParentClass>, painter: *mut QPainter); |
| 65 | + |
| 66 | + // Define that we need to inherit size() from the base class |
| 67 | + #[inherit] |
| 68 | + fn size(self: &qobject::CustomParentClass) -> QSizeF; |
| 69 | + |
| 70 | + // Define that we need to inherit update() from the base class |
| 71 | + #[inherit] |
| 72 | + fn update(self: Pin<&mut qobject::CustomParentClass>); |
| 73 | + } |
| 74 | +} |
| 75 | + |
| 76 | +use core::pin::Pin; |
| 77 | +use cxx_qt_lib::QRectF; |
| 78 | + |
| 79 | +// TODO: this will change to qobject::RustInvokables once |
| 80 | +// https://github.com/KDAB/cxx-qt/issues/559 is done |
| 81 | +impl ffi::CustomParentClassQt { |
| 82 | + /// Override QQuickPaintedItem::paint to draw two rectangles in Rust using QPainter |
| 83 | + fn paint(self: Pin<&mut Self>, painter: *mut ffi::QPainter) { |
| 84 | + // We need to convert the *mut QPainter to a Pin<&mut QPainter> so that we can reach the methods |
| 85 | + if let Some(painter) = unsafe { painter.as_mut() } { |
| 86 | + let mut pinned_painter = unsafe { Pin::new_unchecked(painter) }; |
| 87 | + |
| 88 | + // Now pinned painter can be used as normal |
| 89 | + // to render a rectangle with two colours |
| 90 | + let size = self.as_ref().size(); |
| 91 | + pinned_painter.as_mut().fill_rect( |
| 92 | + &QRectF::new(0.0, 0.0, size.width() / 2.0, size.height()), |
| 93 | + self.as_ref().color(), |
| 94 | + ); |
| 95 | + let darker_color = self.as_ref().color().darker(150); |
| 96 | + pinned_painter.as_mut().fill_rect( |
| 97 | + &QRectF::new(size.width() / 2.0, 0.0, size.width() / 2.0, size.height()), |
| 98 | + &darker_color, |
| 99 | + ); |
| 100 | + } |
| 101 | + } |
| 102 | +} |
| 103 | + |
| 104 | +impl cxx_qt::Constructor<()> for qobject::CustomParentClass { |
| 105 | + type NewArguments = (); |
| 106 | + type BaseArguments = (*mut ffi::QQuickItem,); |
| 107 | + type InitializeArguments = (); |
| 108 | + |
| 109 | + fn route_arguments( |
| 110 | + _args: (), |
| 111 | + ) -> ( |
| 112 | + Self::NewArguments, |
| 113 | + Self::BaseArguments, |
| 114 | + Self::InitializeArguments, |
| 115 | + ) { |
| 116 | + ((), (core::ptr::null_mut(),), ()) |
| 117 | + } |
| 118 | + |
| 119 | + fn new((): ()) -> CustomParentClass { |
| 120 | + CustomParentClass::default() |
| 121 | + } |
| 122 | + |
| 123 | + fn initialize(self: core::pin::Pin<&mut Self>, _arguments: Self::InitializeArguments) { |
| 124 | + self.on_color_changed(|qobject| qobject.update()).release(); |
| 125 | + } |
| 126 | +} |
0 commit comments