Skip to content

Commit 14907d5

Browse files
committed
cxx-qt-gen: add example showing how QQuickPaintedItem works
This then allows you to create a QQuickItem such as a QQuickPaintedItem. Closes KDAB#474
1 parent 8efc6be commit 14907d5

File tree

7 files changed

+200
-2
lines changed

7 files changed

+200
-2
lines changed

examples/qml_features/CMakeLists.txt

+3-2
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ set(CMAKE_CXX_STANDARD 17)
1515
set(CMAKE_CXX_STANDARD_REQUIRED ON)
1616

1717
if(NOT USE_QT5)
18-
find_package(Qt6 COMPONENTS Core Gui Qml QuickControls2 QmlImportScanner QuickTest Test)
18+
find_package(Qt6 COMPONENTS Core Gui Qml Quick QuickControls2 QmlImportScanner QuickTest Test)
1919
endif()
2020
if(NOT Qt6_FOUND)
21-
find_package(Qt5 5.15 COMPONENTS Core Gui Qml QuickControls2 QmlImportScanner QuickTest Test REQUIRED)
21+
find_package(Qt5 5.15 COMPONENTS Core Gui Qml Quick QuickControls2 QmlImportScanner QuickTest Test REQUIRED)
2222
endif()
2323
get_target_property(QMAKE Qt::qmake IMPORTED_LOCATION)
2424

@@ -48,6 +48,7 @@ target_link_libraries(${APP_NAME}_lib INTERFACE
4848
Qt::Core
4949
Qt::Gui
5050
Qt::Qml
51+
Qt::Quick
5152
Qt::QuickControls2
5253
)
5354

examples/qml_features/qml/main.qml

+4
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ ApplicationWindow {
112112
name: "Singleton"
113113
source: "qrc:/pages/SingletonPage.qml"
114114
}
115+
ListElement {
116+
name: "Custom Parent Class"
117+
source: "qrc:/pages/CustomParentClassPage.qml"
118+
}
115119
}
116120
}
117121
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
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+
import QtQuick 2.12
6+
import QtQuick.Controls 2.12
7+
import QtQuick.Layouts 1.12
8+
9+
import com.kdab.cxx_qt.demo 1.0
10+
11+
Page {
12+
header: ToolBar {
13+
RowLayout {
14+
anchors.fill: parent
15+
16+
ToolButton {
17+
text: qsTr("Red")
18+
19+
onClicked: customPainter.color = "red"
20+
}
21+
22+
ToolButton {
23+
text: qsTr("Green")
24+
25+
onClicked: customPainter.color = "green"
26+
}
27+
28+
ToolButton {
29+
text: qsTr("Blue")
30+
31+
onClicked: customPainter.color = "blue"
32+
}
33+
34+
Item {
35+
Layout.fillWidth: true
36+
}
37+
}
38+
}
39+
40+
41+
ColumnLayout {
42+
anchors.left: parent.left
43+
anchors.right: parent.right
44+
anchors.verticalCenter: parent.verticalCenter
45+
46+
CustomParentClass {
47+
id: customPainter
48+
color: "red"
49+
Layout.alignment: Qt.AlignHCenter
50+
height: 200
51+
width: 200
52+
}
53+
54+
Label {
55+
Layout.fillWidth: true
56+
horizontalAlignment: Text.AlignHCenter
57+
text: qsTr("In this demo the Rectangle is rendered in Rust by implementing a QQuickPaintedItem.")
58+
wrapMode: Text.Wrap
59+
}
60+
}
61+
}

examples/qml_features/qml/qml.qrc

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ SPDX-License-Identifier: MIT OR Apache-2.0
1111
<file>main.qml</file>
1212
<file>pages/ContainersPage.qml</file>
1313
<file>pages/CustomBaseClassPage.qml</file>
14+
<file>pages/CustomParentClassPage.qml</file>
1415
<file>pages/InvokablesPage.qml</file>
1516
<file>pages/MultipleQObjectsPage.qml</file>
1617
<file>pages/NestedQObjectsPage.qml</file>

examples/qml_features/rust/build.rs

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ fn main() {
1111
CxxQtBuilder::new()
1212
.file("src/containers.rs")
1313
.file("src/custom_base_class.rs")
14+
.file("src/custom_parent_class.rs")
1415
.file("src/invokables.rs")
1516
.file("src/multiple_qobjects.rs")
1617
.file("src/nested_qobjects.rs")
@@ -28,6 +29,9 @@ fn main() {
2829
cc.file("../cpp/custom_object.cpp");
2930
})
3031
.qobject_header("../cpp/custom_object.h")
32+
// Ensure that Quick module is linked, so that cargo test can work.
33+
// In a CMake project this isn't required as the linking happens in CMake.
34+
.qt_module("Quick")
3135
.build();
3236
}
3337
// ANCHOR_END: book_build_rs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
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+
}

examples/qml_features/rust/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
1313
pub mod containers;
1414
pub mod custom_base_class;
15+
pub mod custom_parent_class;
1516
pub mod invokables;
1617
pub mod multiple_qobjects;
1718
pub mod nested_qobjects;

0 commit comments

Comments
 (0)