├── .gitignore
├── rustfmt.toml
├── examples
├── webengine
│ ├── index.html
│ ├── main.qml
│ ├── Cargo.toml
│ ├── src
│ │ └── main.rs
│ └── build.rs
├── nested_qobjects
│ ├── README.md
│ ├── Cargo.toml
│ └── src
│ │ └── main.rs
├── qenum
│ ├── Cargo.toml
│ └── src
│ │ └── main.rs
├── todos
│ ├── Cargo.toml
│ ├── README
│ ├── src
│ │ ├── main.rs
│ │ └── implementation.rs
│ └── main.qml
├── qmlextensionplugins
│ ├── Cargo.toml
│ ├── README
│ └── src
│ │ └── lib.rs
├── kefia
│ ├── README
│ ├── 0001-Fix-compile-with-stable.patch
│ └── 0002-Port-to-qmetaobject-rs.patch
├── graph
│ ├── Cargo.toml
│ ├── src
│ │ ├── nodes.rs
│ │ ├── noisynode.h
│ │ ├── gridnode.h
│ │ ├── linenode.h
│ │ ├── main.qml
│ │ ├── gridnode.cpp
│ │ ├── main.rs
│ │ ├── linenode.cpp
│ │ └── noisynode.cpp
│ ├── build.rs
│ └── shaders
│ │ ├── line.fsh
│ │ ├── line.vsh
│ │ ├── noisy.vsh
│ │ └── noisy.fsh
└── rqbg
│ ├── 0002-Fix-build.patch
│ └── README.md
├── qmetaobject
├── tests
│ ├── qml
│ │ ├── Bar.qml
│ │ └── main.qml
│ ├── models.rs
│ └── common
│ │ └── mod.rs
├── src
│ ├── qtquickcontrols2.rs
│ ├── webengine.rs
│ ├── qtcore
│ │ ├── mod.rs
│ │ └── core_application.rs
│ ├── qrc.rs
│ ├── future.rs
│ ├── log.rs
│ └── tablemodel.rs
├── Cargo.toml
├── build.rs
└── qmetaobject_rust.hpp
├── qttypes
├── src
│ ├── qtgui
│ │ └── mod.rs
│ └── qtcore
│ │ ├── qlist
│ │ ├── mod.rs
│ │ ├── common.rs
│ │ ├── qvariantlist.rs
│ │ └── qstringlist.rs
│ │ ├── primitives.rs
│ │ ├── mod.rs
│ │ ├── qurl.rs
│ │ ├── qchar.rs
│ │ ├── qbytearray.rs
│ │ ├── qsettings.rs
│ │ └── qvariant.rs
├── Cargo.toml
└── README.md
├── Cargo.toml
├── qmetaobject_impl
├── Cargo.toml
└── src
│ ├── simplelistitem_impl.rs
│ ├── qbjs.rs
│ └── lib.rs
├── LICENSE
├── .github
└── workflows
│ └── rust.yml
└── CHANGELOG.md
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 | Cargo.lock
3 |
--------------------------------------------------------------------------------
/rustfmt.toml:
--------------------------------------------------------------------------------
1 | use_small_heuristics = "Max"
2 |
--------------------------------------------------------------------------------
/examples/webengine/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello from WebEngineView
4 |
5 |
--------------------------------------------------------------------------------
/qmetaobject/tests/qml/Bar.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | Item {}
3 | // This file exists only for doctests
4 |
--------------------------------------------------------------------------------
/qmetaobject/tests/qml/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.0
2 | Item {}
3 | // This file exists only for doctests
4 |
--------------------------------------------------------------------------------
/qttypes/src/qtgui/mod.rs:
--------------------------------------------------------------------------------
1 | mod qcolor;
2 | pub use self::qcolor::{QColor, QColorNameFormat, QColorSpec, QRgb, QRgba64};
3 |
--------------------------------------------------------------------------------
/examples/nested_qobjects/README.md:
--------------------------------------------------------------------------------
1 | # Nested QObjects
2 |
3 | This example illustrate how to put a `QObject` inside another `QObject` using `RefCell`.
4 |
--------------------------------------------------------------------------------
/examples/qenum/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "qenum"
3 | version = "0.1.0"
4 | edition = "2018"
5 |
6 | [dependencies]
7 | qmetaobject = { path = "../../qmetaobject" }
8 | cstr = "0.2"
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qlist/mod.rs:
--------------------------------------------------------------------------------
1 | mod common;
2 | mod qstringlist;
3 | mod qvariantlist;
4 |
5 | pub use self::common::QListIterator;
6 | pub use self::qstringlist::QStringList;
7 | pub use self::qvariantlist::QVariantList;
8 |
--------------------------------------------------------------------------------
/examples/todos/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "todos"
3 | version = "0.1.0"
4 | edition = "2018"
5 | authors = ["Olivier Goffart "]
6 |
7 | [dependencies]
8 | qmetaobject = { path = "../../qmetaobject" }
9 | cstr = "0.2"
10 |
--------------------------------------------------------------------------------
/examples/nested_qobjects/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "nested_qobjects"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 |
8 | [dependencies]
9 | qmetaobject = { path = "../../qmetaobject" }
10 | cstr = "0.2"
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | members = [
3 | 'qmetaobject',
4 | 'qmetaobject_impl',
5 | 'qttypes',
6 |
7 | 'examples/graph',
8 | 'examples/qmlextensionplugins',
9 | 'examples/todos',
10 | 'examples/webengine',
11 | 'examples/qenum',
12 | 'examples/nested_qobjects',
13 | ]
14 |
15 | resolver = "2"
16 |
--------------------------------------------------------------------------------
/examples/webengine/main.qml:
--------------------------------------------------------------------------------
1 | import QtQuick 2.6;
2 | import QtQuick.Window 2.0;
3 | import QtWebEngine 1.4
4 |
5 | Window {
6 | visible: true
7 | title: "WebEngineView"
8 | width: 800
9 | height: 600
10 | WebEngineView {
11 | anchors.fill: parent
12 | url: "qrc:/webengine/index.html"
13 | }
14 | }
--------------------------------------------------------------------------------
/qmetaobject/src/qtquickcontrols2.rs:
--------------------------------------------------------------------------------
1 | /// Refer to the Qt documentation for QQuickStyle
2 | pub struct QQuickStyle {}
3 |
4 | impl QQuickStyle {
5 | /// Refer to the Qt documentation for QQuickStyle::setStyle
6 | pub fn set_style(style: &str) {
7 | std::env::set_var("QT_QUICK_CONTROLS_STYLE", style);
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/primitives.rs:
--------------------------------------------------------------------------------
1 | /// Bindings for [`qreal`][type] typedef.
2 | ///
3 | /// [type]: https://doc.qt.io/qt-5/qtglobal.html#qreal-typedef
4 | #[allow(non_camel_case_types)]
5 | #[cfg(qreal_is_float)]
6 | pub type qreal = f32;
7 |
8 | #[allow(non_camel_case_types)]
9 | #[cfg(not(qreal_is_float))]
10 | pub type qreal = f64;
11 |
--------------------------------------------------------------------------------
/examples/todos/README:
--------------------------------------------------------------------------------
1 | This example is based on a rust-qt-binding-generator example from Jos van den Oever .
2 | https://github.com/KDE/rust-qt-binding-generator/tree/9822dcef071f8c6d6ec2f6b39bab436613493221/examples/todos
3 | The file main.qml is imported unmodified, and the file implementation.rs was used and adapted to
4 | the qmetaobject crate
5 |
--------------------------------------------------------------------------------
/examples/webengine/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "webengine"
3 | version = "0.1.0"
4 | edition = "2018"
5 | build = "build.rs"
6 |
7 | [dependencies]
8 | qmetaobject = { path = "../../qmetaobject", features = ["webengine"] }
9 | qttypes = { path = "../../qttypes" } # required to get the DEP_QT_* env variables
10 |
11 | [build-dependencies]
12 | semver = "1"
13 |
--------------------------------------------------------------------------------
/examples/qmlextensionplugins/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "qmlextensionplugins"
3 | version = "0.1.0"
4 | edition = "2018"
5 | authors = ["Olivier Goffart "]
6 |
7 | [lib]
8 | name = "qmlqtimeexampleplugin"
9 | crate-type = ["cdylib"]
10 |
11 | [dependencies]
12 | qmetaobject = { path = "../../qmetaobject" }
13 | chrono = "^0.4"
14 | cstr = "0.2"
15 |
--------------------------------------------------------------------------------
/examples/kefia/README:
--------------------------------------------------------------------------------
1 | Here is patches to port the kefia examples from qml-rust to the qmetaobject crate.
2 |
3 | To try this example, go to the parent repository of qmetaobject-rs, and run
4 |
5 | git clone https://github.com/White-Oak/kefia
6 | cd kefia
7 | git am ../qmetaobject-rs/examples/kefia/*.patch
8 | cargo run
9 |
10 | (The patches apply to commit ec8b9ed82446b79f1eece70860cc1995c2d43558)
11 |
--------------------------------------------------------------------------------
/examples/graph/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "graph"
3 | version = "0.1.0"
4 | edition = "2018"
5 | authors = ["Olivier Goffart "]
6 | build = "build.rs"
7 |
8 | [dependencies]
9 | qmetaobject = { path = "../../qmetaobject" }
10 | qttypes = { path = "../../qttypes" } # required to get the DEP_QT_* env variables
11 | cstr = "0.2"
12 | cpp = "0.5.6"
13 |
14 | [build-dependencies]
15 | cpp_build = "0.5.6"
16 | semver = "1"
17 |
--------------------------------------------------------------------------------
/examples/todos/src/main.rs:
--------------------------------------------------------------------------------
1 | use cstr::cstr;
2 |
3 | use qmetaobject::prelude::*;
4 |
5 | mod implementation;
6 |
7 | qrc!(my_resource,
8 | "todos/qml" {
9 | "main.qml",
10 | },
11 | );
12 |
13 | fn main() {
14 | my_resource();
15 | qml_register_type::(cstr!("RustCode"), 1, 0, cstr!("Todos"));
16 | let mut engine = QmlEngine::new();
17 | engine.load_file("qrc:/todos/qml/main.qml".into());
18 | engine.exec();
19 | }
20 |
--------------------------------------------------------------------------------
/examples/webengine/src/main.rs:
--------------------------------------------------------------------------------
1 | use qmetaobject::prelude::*;
2 | #[cfg(not(no_qt))]
3 | use qmetaobject::webengine;
4 |
5 | qrc!(my_resource,
6 | "webengine" {
7 | "main.qml",
8 | "index.html",
9 | },
10 | );
11 |
12 | fn main() {
13 | #[cfg(not(no_qt))]
14 | webengine::initialize();
15 | my_resource();
16 | let mut engine = QmlEngine::new();
17 | engine.load_file("qrc:/webengine/main.qml".into());
18 | #[cfg(not(no_qt))]
19 | engine.exec();
20 | }
21 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/mod.rs:
--------------------------------------------------------------------------------
1 | mod primitives;
2 | mod qbytearray;
3 | mod qchar;
4 | mod qlist;
5 | mod qsettings;
6 | mod qstring;
7 | mod qurl;
8 | mod qvariant;
9 |
10 | pub use self::primitives::qreal;
11 | pub use self::qbytearray::QByteArray;
12 | pub use self::qchar::UnicodeVersion;
13 | pub use self::qlist::{QListIterator, QStringList, QVariantList};
14 | pub use self::qsettings::QSettings;
15 | pub use self::qstring::{NormalizationForm, QString};
16 | pub use self::qurl::QUrl;
17 | pub use self::qvariant::QVariant;
18 |
--------------------------------------------------------------------------------
/qmetaobject_impl/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "qmetaobject_impl"
3 | version = "0.2.10"
4 | edition = "2018"
5 | authors = ["Olivier Goffart "]
6 | description = "Custom derive for the qmetaobject crate."
7 | readme = "../README.md"
8 | license = "MIT"
9 | keywords = ["Qt", "QML", "QMetaObject",]
10 | repository = "https://github.com/woboq/qmetaobject-rs"
11 |
12 |
13 | [lib]
14 | proc-macro = true
15 |
16 | [dependencies]
17 | syn = { version = "1", features = ["full"] }
18 | quote = "1"
19 | proc-macro2 = "1"
20 |
--------------------------------------------------------------------------------
/examples/qmlextensionplugins/README:
--------------------------------------------------------------------------------
1 | This example shows how you can use plugins with qml builder.
2 | It is based on the `qmlextensionplugins` example found in the qtdeclarative
3 | source code. It needs the QML files from that example in the Qt source tree.
4 |
5 | Build with:
6 |
7 | cargo build
8 |
9 |
10 | Run with:
11 |
12 | qmlscene -P ./target/debug/ \
13 | -I $QTSRCDIR/qtdeclarative/examples/qml/qmlextensionplugins/imports \
14 | $QTSRCDIR/qtdeclarative/examples/qml/qmlextensionplugins/plugins.qml
15 |
16 | Where $QTSRCDIR is the path to the Qt source
17 |
18 |
19 |
--------------------------------------------------------------------------------
/qmetaobject/src/webengine.rs:
--------------------------------------------------------------------------------
1 | use cpp::cpp;
2 |
3 | cpp! {{
4 | #if !(_WIN32 && ! defined(_MSC_VER))
5 | # if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
6 | # if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
7 | # include
8 | # endif
9 | # else
10 | # include
11 | # endif
12 | #endif
13 | }}
14 |
15 | /// Refer to the Qt documentation of QtWebEngine::initialize()
16 | pub fn initialize() {
17 | cpp!(unsafe [] {
18 | #if !(_WIN32 && ! defined(_MSC_VER))
19 | # if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
20 | # if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
21 | QtWebEngineQuick::initialize();
22 | # endif
23 | # else
24 | QtWebEngine::initialize();
25 | # endif
26 | #endif
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/examples/qenum/src/main.rs:
--------------------------------------------------------------------------------
1 | use cstr::cstr;
2 |
3 | use qmetaobject::prelude::*;
4 |
5 | #[derive(Copy, Clone, Debug, Eq, PartialEq, QEnum)]
6 | #[repr(C)]
7 | enum Options {
8 | Foo = 1,
9 | Bar = 2,
10 | Quaz = 3,
11 | }
12 |
13 | fn main() {
14 | qml_register_enum::(cstr!("RustCode"), 1, 0, cstr!("Options"));
15 | let mut engine = QmlEngine::new();
16 | engine.load_data(
17 | r#"
18 | import QtQuick 2.6
19 | import QtQuick.Window 2.0
20 | // Import our Rust classes
21 | import RustCode 1.0
22 |
23 | Window {
24 | visible: true
25 | Text {
26 | anchors.centerIn: parent
27 | text: `Hello! Bar is ${Options.Bar}, Foo is ${Options.Foo}.`
28 | }
29 | }
30 | "#
31 | .into(),
32 | );
33 | engine.exec();
34 | }
35 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qurl.rs:
--------------------------------------------------------------------------------
1 | use crate::internal_prelude::*;
2 | use crate::QString;
3 |
4 | cpp! {{
5 | #include
6 | #include
7 | }}
8 |
9 | cpp_class!(
10 | /// Wrapper around [`QUrl`][class] class.
11 | ///
12 | /// [class]: https://doc.qt.io/qt-5/qurl.html
13 | #[derive(PartialEq, PartialOrd, Eq, Ord)]
14 | pub unsafe struct QUrl as "QUrl"
15 | );
16 | impl QUrl {
17 | /// Wrapper around [`QUrl::fromUserInput(const QString &userInput)`][method] static method.
18 | ///
19 | /// [method]: https://doc.qt.io/qt-5/qurl.html#fromUserInput
20 | pub fn from_user_input(user_input: QString) -> QUrl {
21 | cpp!(unsafe [user_input as "QString"] -> QUrl as "QUrl" {
22 | return QUrl::fromUserInput(user_input);
23 | })
24 | }
25 | }
26 | impl From for QUrl {
27 | fn from(qstring: QString) -> QUrl {
28 | cpp!(unsafe [qstring as "QString"] -> QUrl as "QUrl" {
29 | return QUrl(qstring);
30 | })
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qlist/common.rs:
--------------------------------------------------------------------------------
1 | use std::{marker::PhantomData, ops::Index};
2 |
3 | /// Internal class used to iterate over a [`QList`][]
4 | ///
5 | /// [`QList`]: https://doc.qt.io/qt-5/qlist.html
6 | pub struct QListIterator<'a, T, I>
7 | where
8 | T: Index,
9 | {
10 | list: &'a T,
11 | index: usize,
12 | size: usize,
13 | item: PhantomData<&'a I>,
14 | }
15 |
16 | impl<'a, T, I> QListIterator<'a, T, I>
17 | where
18 | T: Index,
19 | {
20 | pub fn new(list: &'a T, index: usize, size: usize) -> Self {
21 | Self { list, index, size, item: PhantomData }
22 | }
23 | }
24 |
25 | impl<'a, T, I> Iterator for QListIterator<'a, T, I>
26 | where
27 | T: Index,
28 | {
29 | type Item = &'a I;
30 |
31 | fn next(&mut self) -> Option {
32 | if self.index == self.size {
33 | None
34 | } else {
35 | self.index += 1;
36 | Some(&self.list[self.index - 1])
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qchar.rs:
--------------------------------------------------------------------------------
1 | /// Bindings for [`QChar::UnicodeVersion`][enum] enum.
2 | ///
3 | /// [enum]: https://doc.qt.io/qt-5/qchar.html#UnicodeVersion-enum
4 | #[repr(C)]
5 | #[derive(Clone, Copy, PartialEq, Debug)]
6 | #[allow(non_camel_case_types)]
7 | pub enum UnicodeVersion {
8 | Unicode_Unassigned = 0,
9 | Unicode_1_1 = 1,
10 | Unicode_2_0 = 2,
11 | Unicode_2_1_2 = 3,
12 | Unicode_3_0 = 4,
13 | Unicode_3_1 = 5,
14 | Unicode_3_2 = 6,
15 | Unicode_4_0 = 7,
16 | Unicode_4_1 = 8,
17 | Unicode_5_0 = 9,
18 | Unicode_5_1 = 10,
19 | Unicode_5_2 = 11,
20 | Unicode_6_0 = 12,
21 | Unicode_6_1 = 13,
22 | Unicode_6_2 = 14,
23 | Unicode_6_3 = 15,
24 | Unicode_7_0 = 16,
25 | Unicode_8_0 = 17,
26 | #[cfg(qt_5_11)]
27 | Unicode_9_0 = 18,
28 | #[cfg(qt_5_11)]
29 | Unicode_10_0 = 19,
30 | #[cfg(qt_5_15)]
31 | Unicode_11_0 = 20,
32 | #[cfg(qt_5_15)]
33 | Unicode_12_0 = 21,
34 | #[cfg(qt_5_15)]
35 | Unicode_12_1 = 22,
36 | #[cfg(qt_5_15)]
37 | Unicode_13_0 = 23,
38 | }
39 |
--------------------------------------------------------------------------------
/qmetaobject/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "qmetaobject"
3 | version = "0.2.10"
4 | edition = "2018"
5 | authors = ["Olivier Goffart "]
6 | build = "build.rs"
7 | description = "Expose rust object to Qt and QML."
8 | readme = "../README.md"
9 | license = "MIT"
10 | categories = ["api-bindings", "gui"]
11 | keywords = ["Qt", "QML", "QMetaObject",]
12 | repository = "https://github.com/woboq/qmetaobject-rs"
13 |
14 | [features]
15 | default = ["log"]
16 | chrono_qdatetime = ["qttypes/chrono"]
17 | webengine = ["qttypes/qtwebengine"]
18 |
19 | [dependencies]
20 | qttypes = { path = "../qttypes", version = "0.2.0", features = ["qtquick"] }
21 | qmetaobject_impl = { path = "../qmetaobject_impl", version = "=0.2.10"}
22 | lazy_static = "1.0"
23 | cpp = "0.5.6"
24 | log = { version = "0.4", optional = true }
25 |
26 | [build-dependencies]
27 | cpp_build = "0.5.6"
28 | semver = "1"
29 |
30 | [dev-dependencies]
31 | cstr = "0.2"
32 | if_rust_version = "1"
33 | tempfile = "^3"
34 |
35 | [package.metadata.docs.rs]
36 | dependencies = [ "qtbase5-dev", "qtdeclarative5-dev" ]
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2019 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/qmetaobject/src/qtcore/mod.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 | Copyright (C) 2021 ivan tkachenko a.k.a. ratijas
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | associated documentation files (the "Software"), to deal in the Software without restriction,
6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
8 | subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial
11 | portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
16 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | */
19 | //! Wrappers around QtCore module.
20 |
21 | pub mod core_application;
22 |
--------------------------------------------------------------------------------
/examples/rqbg/0002-Fix-build.patch:
--------------------------------------------------------------------------------
1 | From c9b77aa3120c0c8e10701baf125ebd7d3c699f1c Mon Sep 17 00:00:00 2001
2 | From: Olivier Robert
3 | Date: Sun, 22 Nov 2020 14:23:48 +0100
4 | Subject: [PATCH] Fix build
5 |
6 | ---
7 | Cargo.toml | 4 ++--
8 | src/implementation.rs | 2 +-
9 | 2 files changed, 3 insertions(+), 3 deletions(-)
10 |
11 | diff --git a/Cargo.toml b/Cargo.toml
12 | index 27c07ee..9bd68e6 100644
13 | --- a/Cargo.toml
14 | +++ b/Cargo.toml
15 | @@ -12,8 +12,8 @@ grep-regex = "0.1.1"
16 | grep-searcher = "0.1.1"
17 | htmlescape = "0.3.1"
18 | libc = "0.2"
19 | -spmc = "0.2.2"
20 | +spmc = "0.3.0"
21 | walkdir = "2"
22 | -qmetaobject = "0.0.4"
23 | +qmetaobject = { path = "../qmetaobject-rs/qmetaobject/"}
24 | cstr = "0.1"
25 |
26 | diff --git a/src/implementation.rs b/src/implementation.rs
27 | index 8330769..b6be809 100644
28 | --- a/src/implementation.rs
29 | +++ b/src/implementation.rs
30 | @@ -124,7 +124,7 @@ fn grep(
31 | if query.is_empty() {
32 | return list(&emit, item_sender, active);
33 | }
34 | - let (sender, receiver) = spmc::channel();
35 | + let (mut sender, receiver) = spmc::channel();
36 | let mut threads = Vec::new();
37 | for _ in 0..4 {
38 | let sender = item_sender.clone();
39 | --
40 | 2.29.2
41 |
42 |
--------------------------------------------------------------------------------
/qttypes/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "qttypes"
3 | version = "0.2.12"
4 | edition = "2018"
5 | authors = ["Olivier Goffart "]
6 | build = "build.rs"
7 | description = "Manually maintained buildings for Qt value types"
8 | readme = "README.md"
9 | license = "MIT"
10 | categories = ["api-bindings"]
11 | keywords = ["Qt", "QtCore", "QtGui"]
12 | repository = "https://github.com/woboq/qmetaobject-rs"
13 | links = "qt"
14 | rust-version = "1.56"
15 |
16 | [features]
17 | # When this feature is enabled (the default), the build script will panic with an error
18 | # if Qt is not found.
19 | required = []
20 |
21 | # Link against QtQuick
22 | qtquick = []
23 | # Link against QtWebEngine
24 | qtwebengine = []
25 | # Link against QtQuickControls2
26 | qtquickcontrols2 = []
27 | # Link against QtMultimedia
28 | qtmultimedia = []
29 | # Link against QtMultimediaWidgets
30 | qtmultimediawidgets = []
31 | # Link against QtSql
32 | qtsql = []
33 | # Link against QtTest
34 | qttest = []
35 |
36 | default = ["required"]
37 |
38 | [dependencies]
39 | cpp = "0.5.6"
40 | chrono = { version = "0.4", optional = true }
41 |
42 | [build-dependencies]
43 | cpp_build = "0.5.6"
44 | semver = "1"
45 |
46 | [dev-dependencies]
47 | cpp_build = "0.5.6"
48 | tempfile = { version = "3.4.0", default-features = false }
49 |
50 | [package.metadata.docs.rs]
51 | dependencies = [ "qtbase5-dev", "qtdeclarative5-dev" ]
52 |
--------------------------------------------------------------------------------
/qttypes/README.md:
--------------------------------------------------------------------------------
1 | # qttypes
2 |
3 | This crate contains manually generated bindings to Qt basic value types.
4 | It is meant to be used by other crates, such as the `qmetaobject` crate which re-expose them
5 |
6 | The Qt types are basically exposed using the `cpp` crate. They have manually writen rust idiomatic
7 | API which expose the C++ API.
8 | These types are the direct equivalent of the Qt types and are exposed on the stack.
9 |
10 | In addition, the build script of this crate expose some metadata to downstream crate that also
11 | want to use Qt's C++ API:
12 | - `DEP_QT_VERSION`: The Qt version as given by qmake
13 | - `DEP_QT_INCLUDE_PATH`: The include directory to give to the `cpp_build` crate to locate the Qt headers
14 | - `DEP_QT_LIBRARY_PATH`: The path containing the Qt libraries.
15 |
16 | See the [crate documentation](https://docs.rs/qttypes) for more info.
17 |
18 | ## Philosophy
19 |
20 | The goal of this crate is to expose a idiomatic Qt API for the core value type classes.
21 | The API is manually generated to expose required feature in the most rust-like API, while
22 | still keeping the similarities with the Qt API itself.
23 |
24 | It is not meant to expose all of the Qt API exhaustively, but only the part which is
25 | relevant for the usage in other crate.
26 | If you see a feature missing, feel free to write a issue or a pull request.
27 |
28 | Note that this crate concentrate on the value types, not the widgets or the
29 | the `QObject`. For that, there is the `qmetaobject` crate.
--------------------------------------------------------------------------------
/examples/rqbg/README.md:
--------------------------------------------------------------------------------
1 | ## More port from rust-qt-binding-generator
2 |
3 | This directory contains patches that can be applied to port example
4 | using rust-qt-binding-generator to this crate.
5 |
6 | The goal of the patch is to attempt to show that using this crate is
7 | simpler than using the binding generator.
8 |
9 | ### qrep
10 |
11 | Is the tool presented here:
12 | https://www.vandenoever.info/blog/2018/10/30/building_qt_apps_with_cargo.html
13 |
14 | To apply the patch and run the program:
15 |
16 | ```
17 | git clone https://invent.kde.org/vandenoever/qrep
18 | cd qrep
19 | git checkout bdbde040e74819351609581c0d98a59bbfeecbf9 -b qmetaobject-rs
20 | git am ../qmetaobject-rs/examples/rqbg/0001-Port-to-qmetaobject-rs.patch
21 | git am ../qmetaobject-rs/examples/rqbg/0002-Fix-build.patch
22 | cargo run
23 | ```
24 |
25 | The port does the same as the original.
26 | Contrary to the original, there is no need to write a single line of C++.
27 | And even implementations.rs has less lines than before.
28 |
29 | ### mailmodel
30 |
31 | Mailmodel was introduced here
32 | https://www.vandenoever.info/blog/2018/09/16/browsing_your_mail_with_rust_and_qt.html
33 |
34 | To apply the patch and run the program:
35 |
36 | ```
37 | git clone https://anongit.kde.org/scratch/vandenoever/mailmodel
38 | cd mailmodel
39 | git checkout 87991f1090b57706f5c713c8425684eba144cec2 -b qmetaobject-rs
40 | git am ../qmetaobject-rs/examples/rqbg/mailmodel.patch
41 | cat README.md
42 | # create a configuration file as explained
43 | cargo run config.json
44 | ```
45 |
46 | Note: If you get compilation error because of openssl, try setting these environment variable:
47 | `OPENSSL_LIB_DIR=/usr/lib/openssl-1.0 OPENSSL_INCLUDE_DIR=/usr/include/openssl-1.0`
48 |
49 |
--------------------------------------------------------------------------------
/qmetaobject/build.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 |
19 | use semver::Version;
20 |
21 | fn main() {
22 | let qt_include_path = std::env::var("DEP_QT_INCLUDE_PATH").unwrap();
23 | let qt_version = std::env::var("DEP_QT_VERSION")
24 | .unwrap()
25 | .parse::()
26 | .expect("Parsing Qt version failed");
27 |
28 | let mut config = cpp_build::Config::new();
29 | for f in std::env::var("DEP_QT_COMPILE_FLAGS").unwrap().split_terminator(";") {
30 | config.flag(f);
31 | }
32 | config.include(&qt_include_path).build("src/lib.rs");
33 |
34 | for minor in 7..=15 {
35 | if qt_version >= Version::new(5, minor, 0) {
36 | println!("cargo:rustc-cfg=qt_{}_{}", 5, minor);
37 | }
38 | }
39 | let mut minor = 0;
40 | while qt_version >= Version::new(6, minor, 0) {
41 | println!("cargo:rustc-cfg=qt_{}_{}", 6, minor);
42 | minor += 1;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/qmetaobject/src/qrc.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 | use cpp::cpp;
19 |
20 | cpp! {{
21 | Q_CORE_EXPORT bool qRegisterResourceData(int, const unsigned char *,
22 | const unsigned char *, const unsigned char *);
23 | }}
24 |
25 | /// Internal function used from qrc procedural macro.
26 | /// Unsafe because it can crash if the data structure are not proper.
27 | #[doc(hidden)]
28 | pub unsafe fn register_resource_data(
29 | version: i32,
30 | tree: &'static [u8],
31 | names: &'static [u8],
32 | payload: &'static [u8],
33 | ) {
34 | let tree_ptr = tree.as_ptr();
35 | let names_ptr = names.as_ptr();
36 | let payload_ptr = payload.as_ptr();
37 | cpp!([version as "int", tree_ptr as "const unsigned char*", names_ptr as "const unsigned char*", payload_ptr as "const unsigned char*"] {
38 | qRegisterResourceData(version, tree_ptr, names_ptr, payload_ptr);
39 | });
40 | }
41 |
--------------------------------------------------------------------------------
/examples/webengine/build.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 | Copyright (C) 2021 ivan tkachenko a.k.a. ratijas
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | associated documentation files (the "Software"), to deal in the Software without restriction,
6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
8 | subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial
11 | portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
16 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | */
19 |
20 | use semver::Version;
21 |
22 | fn main() {
23 | let cargo_target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap();
24 | let cargo_target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap();
25 |
26 | if (cargo_target_os == "windows") && (cargo_target_env != "msvc") {
27 | println!("cargo:warning=On Windows, WebEngine module is only available under MSVC 2017 or MSVC2019.");
28 | println!("cargo:rustc-cfg=no_qt");
29 | }
30 |
31 | let qt_version = std::env::var("DEP_QT_VERSION")
32 | .unwrap()
33 | .parse::()
34 | .expect("Parsing Qt version failed");
35 |
36 | if qt_version >= Version::new(6, 0, 0) && qt_version < Version::new(6, 2, 0) {
37 | println!(
38 | "cargo:warning=WebEngine is not supported on Qt {} yet. It is planned for Qt 6.2 LTS.",
39 | qt_version
40 | );
41 | println!("cargo:rustc-cfg=no_qt");
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/.github/workflows/rust.yml:
--------------------------------------------------------------------------------
1 | name: Rust
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 | workflow_dispatch:
9 |
10 | env:
11 | CARGO_TERM_COLOR: always
12 |
13 | jobs:
14 | build:
15 | env:
16 | QT_QPA_PLATFORM: offscreen
17 | strategy:
18 | matrix:
19 | os: [ubuntu-latest, windows-latest]
20 | qt: [5.15.2, 5.9.9, 5.12.9]
21 | rust: [stable, nightly]
22 | runs-on: ${{ matrix.os }}
23 | steps:
24 | - uses: actions/checkout@v4
25 | - uses: dtolnay/rust-toolchain@stable
26 | with:
27 | toolchain: ${{ matrix.rust }}
28 | - uses: Swatinem/rust-cache@v2
29 | with:
30 | key: rust_cache
31 |
32 | - name: Install Qt
33 | uses: jurplel/install-qt-action@v4
34 | with:
35 | version: ${{ matrix.qt }}
36 | cache: true
37 | modules: 'qtwebengine'
38 | - name: Build
39 | run: cargo build --all-features
40 | - name: Run tests
41 | run: cargo test --all-features
42 | shell: bash
43 |
44 |
45 | # Qt6 is in a different job right now because it does not have many modules and most example don't compile
46 | qt6:
47 | strategy:
48 | matrix:
49 | os: [ubuntu-latest, windows-latest]
50 | ver: [6.2.0, 6.5.0]
51 | env:
52 | QT_QPA_PLATFORM: offscreen
53 | runs-on: ${{ matrix.os }}
54 | steps:
55 | - uses: actions/checkout@v4
56 | - uses: dtolnay/rust-toolchain@stable
57 | - uses: Swatinem/rust-cache@v2
58 | with:
59 | key: rust_cache6
60 |
61 | - name: Install Qt
62 | uses: jurplel/install-qt-action@v4
63 | with:
64 | version: ${{ matrix.ver }}
65 | cache: true
66 | - name: Test
67 | run: |
68 | cargo test --manifest-path qttypes/Cargo.toml
69 | cargo test --manifest-path qmetaobject_impl/Cargo.toml
70 | cargo test --manifest-path qmetaobject/Cargo.toml
71 |
72 |
73 | no_qt:
74 | strategy:
75 | matrix:
76 | os: [ubuntu-latest, windows-latest]
77 | runs-on: ${{ matrix.os }}
78 | steps:
79 | - uses: actions/checkout@v4
80 | - uses: dtolnay/rust-toolchain@stable
81 | - uses: Swatinem/rust-cache@v2
82 | with:
83 | key: rust_cache
84 | - name: Build qttypes without qt
85 | run: |
86 | cargo build --manifest-path qttypes/Cargo.toml --no-default-features
87 |
--------------------------------------------------------------------------------
/examples/graph/src/nodes.rs:
--------------------------------------------------------------------------------
1 | use qmetaobject::scenegraph::SGNode;
2 | use qmetaobject::{qrc, QQuickItem};
3 | use qttypes::{QColor, QRectF};
4 |
5 | #[cfg(not(no_qt))]
6 | use cpp::cpp;
7 |
8 | qrc! {
9 | pub init_resources,
10 | "scenegraph/graph" {
11 | "shaders/noisy.vsh",
12 | "shaders/noisy.fsh",
13 | "shaders/line.vsh",
14 | "shaders/line.fsh",
15 | },
16 | "src" as "qml" {
17 | "main.qml"
18 | }
19 | }
20 |
21 | // Ideally, everything should be possible to do in plain rust.
22 | // However, there is quite some API to expose.
23 |
24 | cpp! {{
25 | #include
26 |
27 | #include "src/gridnode.cpp"
28 | #include "src/linenode.cpp"
29 | #include "src/noisynode.cpp"
30 | }}
31 |
32 | pub enum NoisyNode {}
33 |
34 | pub fn create_noisy_node(s: &mut SGNode, ctx: &dyn QQuickItem) {
35 | let item_ptr = ctx.get_cpp_object();
36 | cpp!(unsafe [s as "NoisyNode**", item_ptr as "QQuickItem*"] {
37 | if (!*s && item_ptr) {
38 | *s = new NoisyNode(item_ptr->window());
39 | }
40 | });
41 | }
42 |
43 | pub fn noisy_node_set_rect(s: &mut SGNode, rect: QRectF) {
44 | cpp!(unsafe [s as "NoisyNode**", rect as "QRectF"] {
45 | if (*s) {
46 | (*s)->setRect(rect);
47 | }
48 | });
49 | }
50 |
51 | pub enum GridNode {}
52 | pub fn update_grid_node(s: &mut SGNode, rect: QRectF) {
53 | cpp!(unsafe [s as "GridNode**", rect as "QRectF"] {
54 | if (!*s) *s = new GridNode;
55 | (*s)->setRect(rect);
56 | });
57 | }
58 |
59 | pub enum LineNode {}
60 | pub fn create_line_node(s: &mut SGNode, size: f32, spread: f32, color: QColor) {
61 | cpp!(unsafe [s as "LineNode**", size as "float", spread as "float", color as "QColor"] {
62 | if (!*s) *s = new LineNode(size, spread, color);
63 | });
64 | }
65 |
66 | pub fn update_line_node(s: &mut SGNode, rect: QRectF, samples: &[f64]) {
67 | let samples_ptr = samples.as_ptr();
68 | let samples_len = samples.len();
69 | cpp!(unsafe [s as "LineNode**", rect as "QRectF", samples_ptr as "double*",
70 | samples_len as "std::size_t"] {
71 | if (!*s) return;
72 | QList samples;
73 | samples.reserve(samples_len);
74 | std::copy(samples_ptr, samples_ptr + samples_len, std::back_inserter(samples));
75 | (*s)->updateGeometry(rect, samples);
76 | });
77 | }
78 |
--------------------------------------------------------------------------------
/examples/graph/build.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 |
19 | use semver::Version;
20 |
21 | fn main() {
22 | let qt_include_path = std::env::var("DEP_QT_INCLUDE_PATH").unwrap();
23 | let qt_version = std::env::var("DEP_QT_VERSION")
24 | .unwrap()
25 | .parse::()
26 | .expect("Parsing Qt version failed");
27 |
28 | if qt_version >= Version::new(6, 0, 0) {
29 | // This example is not supported on Qt 6 and above because graphics
30 | // API used for it were removed.
31 | println!("cargo:rustc-cfg=no_qt");
32 | return;
33 | }
34 |
35 | #[allow(unused_mut)]
36 | let mut config = cpp_build::Config::new();
37 |
38 | for f in std::env::var("DEP_QT_COMPILE_FLAGS").unwrap().split_terminator(";") {
39 | config.flag(f);
40 | }
41 |
42 | config
43 | .include(&qt_include_path)
44 | .include(format!("{}/QtQuick", qt_include_path))
45 | .include(format!("{}/QtCore", qt_include_path))
46 | // See https://github.com/woboq/qmetaobject-rs/pull/168
47 | //
48 | // QSGSimpleMaterial{,Shader} classes ain't going to be removed from Qt5
49 | // which is on a life support at this point; and we know for sure they are
50 | // already gone in Qt6. So, there's just no point seeing these warning
51 | // over and over again.
52 | .flag_if_supported("-Wno-deprecated-declarations")
53 | .build("src/main.rs");
54 | }
55 |
--------------------------------------------------------------------------------
/examples/qmlextensionplugins/src/lib.rs:
--------------------------------------------------------------------------------
1 | use std::ffi::CStr;
2 | use std::sync::{Arc, Condvar, Mutex};
3 | use std::thread::JoinHandle;
4 |
5 | use chrono::Timelike;
6 | use cstr::cstr;
7 |
8 | use qmetaobject::prelude::*;
9 |
10 | #[derive(Default)]
11 | struct AbortCondVar {
12 | is_aborted: Mutex,
13 | abort_condvar: Condvar,
14 | }
15 |
16 | #[allow(non_snake_case)]
17 | #[derive(Default, QObject)]
18 | struct TimeModel {
19 | base: qt_base_class!(trait QObject),
20 | hour: qt_property!(u32; NOTIFY timeChanged READ get_hour),
21 | minute: qt_property!(u32; NOTIFY timeChanged READ get_minute),
22 | timeChanged: qt_signal!(),
23 |
24 | thread: Option<(JoinHandle<()>, Arc)>,
25 | }
26 |
27 | impl Drop for TimeModel {
28 | fn drop(&mut self) {
29 | self.thread.as_ref().map(|x| {
30 | let mut lock = x.1.is_aborted.lock().unwrap();
31 | *lock = true;
32 | x.1.abort_condvar.notify_one();
33 | });
34 | }
35 | }
36 |
37 | impl TimeModel {
38 | fn lazy_init(&mut self) {
39 | if self.thread.is_none() {
40 | let ptr = QPointer::from(&*self);
41 | let cb = qmetaobject::queued_callback(move |()| {
42 | ptr.as_ref().map(|x| x.timeChanged());
43 | });
44 | let arc = Arc::::new(Default::default());
45 | let arc2 = arc.clone();
46 | let thread = std::thread::spawn(move || loop {
47 | let lock = arc2.is_aborted.lock().unwrap();
48 | if *lock {
49 | break;
50 | }
51 | // We just wait on the condition variable for 1 second to simulate a one second timer
52 | let lock = arc2
53 | .abort_condvar
54 | .wait_timeout(lock, std::time::Duration::from_millis(1000))
55 | .unwrap()
56 | .0;
57 | std::mem::drop(lock);
58 | cb(());
59 | });
60 | self.thread = Some((thread, arc));
61 | }
62 | }
63 | fn get_hour(&mut self) -> u32 {
64 | self.lazy_init();
65 | chrono::offset::Local::now().time().hour()
66 | }
67 | fn get_minute(&mut self) -> u32 {
68 | self.lazy_init();
69 | chrono::offset::Local::now().time().minute()
70 | }
71 | }
72 |
73 | #[derive(Default, QObject)]
74 | struct QExampleQmlPlugin {
75 | base: qt_base_class!(trait QQmlExtensionPlugin),
76 | plugin: qt_plugin!("org.qt-project.Qt.QQmlExtensionInterface/1.0"),
77 | }
78 |
79 | impl QQmlExtensionPlugin for QExampleQmlPlugin {
80 | fn register_types(&mut self, uri: &CStr) {
81 | //assert_eq!(uri, cstr!("TimeExample"));
82 | qml_register_type::(uri, 1, 0, cstr!("Time"));
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qbytearray.rs:
--------------------------------------------------------------------------------
1 | use crate::internal_prelude::*;
2 | use crate::QString;
3 | use std::fmt::Display;
4 | use std::os::raw::c_char;
5 | use std::str::Utf8Error;
6 |
7 | cpp! {{
8 | #include
9 | #include
10 | }}
11 |
12 | cpp_class!(
13 | /// Wrapper around [`QByteArray`][class] class.
14 | ///
15 | /// [class]: https://doc.qt.io/qt-5/qbytearray.html
16 | #[derive(PartialEq, PartialOrd, Eq, Ord)]
17 | pub unsafe struct QByteArray as "QByteArray"
18 | );
19 | impl QByteArray {
20 | pub fn to_slice(&self) -> &[u8] {
21 | unsafe {
22 | let mut size: usize = 0;
23 | let c_ptr = cpp!([self as "const QByteArray*", mut size as "size_t"] -> *const u8 as "const char*" {
24 | size = self->size();
25 | return self->constData();
26 | });
27 | std::slice::from_raw_parts(c_ptr, size)
28 | }
29 | }
30 | pub fn to_str(&self) -> Result<&str, Utf8Error> {
31 | std::str::from_utf8(self.to_slice())
32 | }
33 | }
34 | impl<'a> From<&'a [u8]> for QByteArray {
35 | /// Constructs a `QByteArray` from a slice. (Copy the slice.)
36 | fn from(s: &'a [u8]) -> QByteArray {
37 | let len = s.len();
38 | let ptr = s.as_ptr();
39 | cpp!(unsafe [len as "size_t", ptr as "char*"] -> QByteArray as "QByteArray" {
40 | return QByteArray(ptr, len);
41 | })
42 | }
43 | }
44 | impl<'a> From<&'a str> for QByteArray {
45 | /// Constructs a `QByteArray` from a `&str`. (Copy the string.)
46 | fn from(s: &'a str) -> QByteArray {
47 | s.as_bytes().into()
48 | }
49 | }
50 | impl From for QByteArray {
51 | /// Constructs a `QByteArray` from a `String`. (Copy the string.)
52 | fn from(s: String) -> QByteArray {
53 | QByteArray::from(&*s)
54 | }
55 | }
56 | impl From for QByteArray {
57 | /// Converts a `QString` to a `QByteArray`
58 | fn from(s: QString) -> QByteArray {
59 | cpp!(unsafe [s as "QString"] -> QByteArray as "QByteArray" {
60 | return std::move(s).toUtf8();
61 | })
62 | }
63 | }
64 | impl Display for QByteArray {
65 | /// Prints the contents of the `QByteArray` if it contains UTF-8, do nothing otherwise.
66 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
67 | unsafe {
68 | let c_ptr = cpp!([self as "const QByteArray*"] -> *const c_char as "const char*" {
69 | return self->constData();
70 | });
71 | f.write_str(std::ffi::CStr::from_ptr(c_ptr).to_str().map_err(|_| Default::default())?)
72 | }
73 | }
74 | }
75 | impl std::fmt::Debug for QByteArray {
76 | /// Prints the contents of the `QByteArray` if it contains UTF-8, nothing otherwise
77 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
78 | write!(f, "{}", self)
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/examples/kefia/0001-Fix-compile-with-stable.patch:
--------------------------------------------------------------------------------
1 | From 8356d25ae66ebe130a73e9782a9e3134b94a293d Mon Sep 17 00:00:00 2001
2 | From: Olivier Goffart
3 | Date: Wed, 28 Feb 2018 17:57:59 +0100
4 | Subject: [PATCH 1/2] Fix compile with stable
5 |
6 | ---
7 | Cargo.lock | 18 +++++++++---------
8 | src/main.rs | 1 -
9 | src/view.rs | 10 +++++-----
10 | 3 files changed, 14 insertions(+), 15 deletions(-)
11 |
12 | diff --git a/Cargo.lock b/Cargo.lock
13 | index 4cbcbc1..49cdf47 100644
14 | --- a/Cargo.lock
15 | +++ b/Cargo.lock
16 | @@ -1,12 +1,3 @@
17 | -[root]
18 | -name = "kefia"
19 | -version = "0.1.0"
20 | -dependencies = [
21 | - "lazysort 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
22 | - "qml 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
23 | - "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
24 | -]
25 | -
26 | [[package]]
27 | name = "aho-corasick"
28 | version = "0.6.1"
29 | @@ -15,6 +6,15 @@ dependencies = [
30 | "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
31 | ]
32 |
33 | +[[package]]
34 | +name = "kefia"
35 | +version = "0.1.0"
36 | +dependencies = [
37 | + "lazysort 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
38 | + "qml 0.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
39 | + "regex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
40 | +]
41 | +
42 | [[package]]
43 | name = "kernel32-sys"
44 | version = "0.2.2"
45 | diff --git a/src/main.rs b/src/main.rs
46 | index 68c3013..d540594 100644
47 | --- a/src/main.rs
48 | +++ b/src/main.rs
49 | @@ -1,4 +1,3 @@
50 | -#![feature(box_syntax)]
51 | extern crate regex;
52 | #[macro_use]
53 | extern crate qml;
54 | diff --git a/src/view.rs b/src/view.rs
55 | index 3b80ca6..162d6ab 100644
56 | --- a/src/view.rs
57 | +++ b/src/view.rs
58 | @@ -126,14 +126,14 @@ impl QPackages {
59 | let data = {
60 | let s = &self;
61 | let closure: Box bool> = match (self.chosen_repo, self.chosen_group) {
62 | - (-1, -1) => box |_| true,
63 | - (-1, group) => box move |pkg| pkg.meta.contains(&s.groups[group as usize]),
64 | - (repo, -1) => box move |pkg| pkg.group == s.repos[repo as usize],
65 | + (-1, -1) => Box::new( |_| true ),
66 | + (-1, group) => Box::new( move |pkg| pkg.meta.contains(&s.groups[group as usize])),
67 | + (repo, -1) => Box::new( move |pkg| pkg.group == s.repos[repo as usize]),
68 | (repo, group) => {
69 | - box move |pkg| {
70 | + Box::new( move |pkg| {
71 | pkg.group == s.repos[repo as usize] &&
72 | pkg.meta.contains(&s.groups[group as usize])
73 | - }
74 | + })
75 | }
76 | };
77 | let selected = Some(&self.selected);
78 | --
79 | 2.17.1
80 |
81 |
--------------------------------------------------------------------------------
/examples/graph/shaders/line.fsh:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | uniform lowp vec4 color;
52 | uniform lowp float qt_Opacity;
53 | uniform lowp float spread;
54 |
55 | varying lowp float vT;
56 |
57 | #define PI 3.14159265358979323846
58 |
59 | void main(void)
60 | {
61 | lowp float tt = smoothstep(spread, 1.0, sin(vT * PI));
62 |
63 | gl_FragColor = color * qt_Opacity * tt;
64 | }
65 |
--------------------------------------------------------------------------------
/examples/graph/src/noisynode.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | #ifndef NOISYNODE_H
52 | #define NOISYNODE_H
53 |
54 | #include
55 | #include
56 |
57 | class NoisyNode : public QSGGeometryNode
58 | {
59 | public:
60 | NoisyNode(QQuickWindow *window);
61 |
62 | void setRect(const QRectF &bounds);
63 | };
64 |
65 | #endif // NOISYNODE_H
66 |
--------------------------------------------------------------------------------
/examples/graph/shaders/line.vsh:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | attribute highp vec4 pos;
52 | attribute highp float t;
53 |
54 | uniform lowp float size;
55 | uniform highp mat4 qt_Matrix;
56 |
57 | varying lowp float vT;
58 |
59 | void main(void)
60 | {
61 | vec4 adjustedPos = pos;
62 | adjustedPos.y += (t * size);
63 | gl_Position = qt_Matrix * adjustedPos;
64 |
65 | vT = t;
66 | }
67 |
--------------------------------------------------------------------------------
/examples/graph/shaders/noisy.vsh:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | attribute highp vec4 aVertex;
52 | attribute highp vec2 aTexCoord;
53 |
54 | uniform highp mat4 qt_Matrix;
55 | uniform highp vec2 textureSize;
56 |
57 | varying highp vec2 vTexCoord;
58 | varying lowp vec2 vShadeCoord;
59 |
60 | void main() {
61 | gl_Position = qt_Matrix * aVertex;
62 | vTexCoord = aVertex.xy * textureSize;
63 | vShadeCoord = aTexCoord;
64 | }
65 |
--------------------------------------------------------------------------------
/examples/graph/src/gridnode.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | #ifndef GRIDNODE_H
52 | #define GRIDNODE_H
53 |
54 | #include
55 | #include
56 |
57 | class GridNode : public QSGGeometryNode
58 | {
59 | public:
60 | GridNode();
61 |
62 | void setRect(const QRectF &rect);
63 |
64 | private:
65 | QSGFlatColorMaterial m_material;
66 | QSGGeometry m_geometry;
67 | };
68 |
69 | #endif // GRIDNODE_H
70 |
--------------------------------------------------------------------------------
/examples/graph/src/linenode.h:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | #ifndef LINENODE_H
52 | #define LINENODE_H
53 |
54 | #include
55 |
56 | class LineNode : public QSGGeometryNode
57 | {
58 | public:
59 | LineNode(float size, float spread, const QColor &color);
60 |
61 | void updateGeometry(const QRectF &bounds, const QList &samples);
62 |
63 | private:
64 | QSGGeometry m_geometry;
65 |
66 | };
67 |
68 | #endif // LINENODE_H
69 |
--------------------------------------------------------------------------------
/qmetaobject_impl/src/simplelistitem_impl.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 | use proc_macro::TokenStream;
19 | use quote::quote;
20 | use syn::{parse_macro_input, Data, DeriveInput, Ident, Visibility};
21 |
22 | pub fn derive(input: TokenStream) -> TokenStream {
23 | let input = parse_macro_input!(input as DeriveInput);
24 | let crate_ = super::get_crate(&input);
25 |
26 | let values = if let Data::Struct(ref data) = input.data {
27 | data.fields
28 | .iter()
29 | .filter_map(|field| {
30 | if let Visibility::Public(_) = field.vis {
31 | field.ident.clone()
32 | } else {
33 | None
34 | }
35 | })
36 | .collect::>()
37 | } else {
38 | panic!("#[derive(SimpleListItem)] is only defined for structs");
39 | };
40 |
41 | if values.is_empty() {
42 | panic!("#[derive(SimpleListItem)] only expose public named member, and there are none")
43 | }
44 |
45 | let arms = values
46 | .iter()
47 | .enumerate()
48 | .map(|(i, ref ident)| {
49 | let i = i as i32;
50 | quote! { #i => #crate_::QMetaType::to_qvariant(&self.#ident), }
51 | })
52 | .collect::>();
53 |
54 | let name = &input.ident;
55 | let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
56 |
57 | quote!(
58 | impl #impl_generics #crate_::listmodel::SimpleListItem for #name #ty_generics #where_clause {
59 | fn get(&self, idx : i32) -> #crate_::QVariant {
60 | match idx {
61 | #(#arms)*
62 | _ => #crate_::QVariant::default()
63 | }
64 | }
65 | fn names() -> Vec<#crate_::QByteArray> {
66 | vec![ #(#crate_::QByteArray::from(stringify!(#values))),* ]
67 | }
68 | }
69 | ).into()
70 | }
71 |
--------------------------------------------------------------------------------
/examples/graph/shaders/noisy.fsh:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | uniform sampler2D texture;
52 | uniform lowp float qt_Opacity;
53 | uniform lowp vec4 color;
54 |
55 | varying highp vec2 vTexCoord;
56 | varying lowp vec2 vShadeCoord;
57 |
58 | #define PI 3.14159265358979323846
59 |
60 | void main()
61 | {
62 | lowp float shade = texture2D(texture, vTexCoord).r * 0.05 - length(vec2(0.5, 0.4) - vShadeCoord) * 0.3;
63 | lowp vec4 c = vec4(color.xyz + shade, color.w);
64 | gl_FragColor = c * qt_Opacity;
65 | }
66 |
--------------------------------------------------------------------------------
/examples/nested_qobjects/src/main.rs:
--------------------------------------------------------------------------------
1 | use cstr::cstr;
2 | use qmetaobject::{
3 | qml_register_type, qt_base_class, qt_method, qt_property, qt_signal, QObject, QString,
4 | QmlEngine,
5 | };
6 | use std::cell::RefCell;
7 |
8 | // Here we define a custom QObject Person with a property and two methods.
9 | #[derive(QObject, Default)]
10 | struct Person {
11 | base: qt_base_class!(trait QObject),
12 | name: qt_property!(QString; NOTIFY name_changed),
13 | name_changed: qt_signal!(),
14 | }
15 |
16 | impl Person {
17 | fn set_name(&mut self, name: String) {
18 | self.name = name.into();
19 | self.name_changed();
20 | }
21 |
22 | fn get_name(&self) -> String {
23 | self.name.to_string()
24 | }
25 | }
26 |
27 | // Now we want to use the Person as a property of another QObject.
28 | #[derive(QObject, Default)]
29 | struct Greeter {
30 | base: qt_base_class!(trait QObject),
31 |
32 | // To store our Person QObject as a property of another QObject, we need to use a RefCell.
33 | person: qt_property!(RefCell; NOTIFY person_changed),
34 | person_changed: qt_signal!(),
35 |
36 | compute_greetings: qt_method!(
37 | fn compute_greetings(&self, verb: String) -> QString {
38 | // To access the person, we need to borrow it.
39 | format!("{} {}", verb, self.person.borrow().get_name()).into()
40 | }
41 | ),
42 | set_person_name: qt_method!(
43 | fn set_person_name(&mut self, name: String) {
44 | // To modify the nested object we need to borrow it as mutable
45 | println!("Person name set to {}", &name);
46 | self.person.borrow_mut().set_name(name);
47 | self.person_changed();
48 | }
49 | ),
50 | }
51 |
52 | fn main() {
53 | // We need to register our two custom QObjects with the QML engine.
54 | qml_register_type::(cstr!("Greeter"), 1, 0, cstr!("Greeter"));
55 | qml_register_type::(cstr!("Person"), 1, 0, cstr!("Person"));
56 |
57 | let mut engine = QmlEngine::new();
58 | engine.load_data(
59 | r#"
60 | import QtQuick 2.6
61 | import QtQuick.Window 2.0
62 | import Greeter 1.0
63 |
64 | Window {
65 | visible: true
66 | Greeter {
67 | id: greeter;
68 | // Here we can directly set the person name inside the Greeter's Person property
69 | person.name: "World"
70 | // or we can use the set_person_name method to set the name
71 | //Component.onCompleted : {
72 | // greeter.set_person_name("foo");
73 | //}
74 | }
75 | Text {
76 | id: txt
77 | anchors.centerIn: parent
78 | text: greeter.compute_greetings("hello")
79 |
80 | // When the person's name changes, we update the text
81 | Connections {
82 | target: greeter
83 | function onPersonChanged() {
84 | txt.text = greeter.compute_greetings("hello")
85 | }
86 | }
87 | }
88 |
89 |
90 | }
91 | "#
92 | .into(),
93 | );
94 | engine.exec();
95 | }
96 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6 |
7 | ## [Unreleased]
8 |
9 | ## 0.2.12 2024-10-22 (qttype only)
10 |
11 | - Prefer Qt6 over Qt5 if there is a `qmake6` binary in PATH
12 | - `impl From for QVariant`
13 | - Add QVariant::to_qvariantmap wrapper
14 | - Add QVariant::to_qstring wrapper
15 | - Add QVariant::type_name wrapper
16 | - Add Debug for QVariantList
17 | - Add QVariant::toInt wrapper
18 | - Fix Qt linkage on macOS when Qt was configured with -no-framework
19 |
20 | ## 0.2.11 2023-11-03 (qttype only)
21 |
22 | - reenable `cargo:rustc-cdylib-link-arg=-Wl,-rpath,` command even if it is depracated as it broke people's build
23 |
24 | ## 0.2.10 2023-11-03
25 |
26 | - qttypes: detect MSVC and MinGW incompatibilities
27 | - qttypes: Added wrapper around QSettings
28 | - Added QmlEngine::invoke_method_noreturn
29 | - Added QmlEngine::trim_component_cache and QmlEngine::clear_component_cache
30 |
31 | ## 0.2.9 2023-06-15
32 |
33 | - Implement QMetaType for QStringList and QVariantMap
34 | - Added QGlobalColor
35 | - implemented Add and AddAsing for QString
36 | - Added QVariant::is_null
37 | - Expose begin_move_rows and end_move_rows
38 | - Fixed UTF8 in QJSonObject
39 | - Fixed compulation with Qt 6.5
40 |
41 | ## 0.2.8 2022-02-25 (qttype only)
42 |
43 | - Fix qttype crate always being rebuilt (#252)
44 |
45 | ## 0.2.7 2022-02-23
46 |
47 | - Expand the API of QStringList, QString
48 | - Expand the API of QJSValue
49 | - Added QVariantMap
50 | - Add wrapper around qmlRegisterModule
51 | - Fix compilation with Qt 6.3 and MSVC
52 | - qttypes: Expose the flags through a COMPILE_FLAGS env variable
53 |
54 |
55 | ## 0.2.6 2021-11-19 (qttype only)
56 |
57 | - Fix build when Qt is not found and the required feature is off
58 |
59 | ## 0.2.5 2021-11-19
60 |
61 | - Completed QColor API
62 | - Added wrapper around QJSon* types, QPainter, QPen, QBrush, QLineF
63 | - Added QQuickPaintedItem
64 | - Fixes to the qttype build script
65 |
66 | ## 0.2.4 2021-09-30
67 |
68 | - Fixed build with Qt < 5.8 and >= 6.2
69 |
70 | ## 0.2.3 2021-08-11
71 |
72 | ### Added
73 | - Tutorial on adding Rust wrappers #171.
74 | - QCoreApplication: wrappers around public static getters & setters #185.
75 |
76 | ### Deprecated
77 | - Rename QObjectDescription in favor of its new name RustQObjectDescriptor #172.
78 |
79 | ### Removed
80 | - No longer set QT_SELECT environment variable when running qmake #173.
81 |
82 | ### Fixed
83 | - Build scripts improvements #174, d7c6587.
84 | - Symbol required for the QEnum macro are in the prelude
85 |
86 | ## 0.2.2 - 2021-06-28
87 |
88 | - Added QVariant conversion from QObjectPinned
89 | - Added release_resources to QQuickItem
90 | - Fix non-MSVC Windows build and cross compilation
91 | - Fixed SimpleListItem when not QVariant or QByteArray are not in scope
92 |
93 | ## 0.2.1 - 2021-05-22
94 |
95 | - Qt6 support
96 | - allow to select qt with env variables QT_INCLUDE_PATH and QT_LIBRARY_PATH
97 | - Added more features to link to more modules
98 | - Added a prelude
99 | - Set the rpath on linux
100 |
101 | ## 0.2.0 - 2021-04-21
102 |
103 |
104 |
--------------------------------------------------------------------------------
/examples/graph/src/main.qml:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | import QtQuick 2.0
52 | import Graph 1.0
53 |
54 | Item {
55 | width: 800
56 | height: 400
57 |
58 | Graph {
59 | id: graph
60 | anchors.fill: parent
61 | anchors.margins: 100
62 |
63 | function newSample(i) {
64 | return (Math.sin(i / 100.0 * Math.PI * 2) + 1) * 0.4 + Math.random() * 0.05;
65 | }
66 |
67 | Component.onCompleted: {
68 | for (let i = 0; i < 100; ++i) {
69 | appendSample(newSample(i));
70 | }
71 | }
72 |
73 | property int offset: 100
74 | }
75 |
76 | Timer {
77 | id: timer
78 | interval: 500
79 | repeat: true
80 | running: true
81 | onTriggered: {
82 | graph.removeFirstSample();
83 | graph.appendSample(graph.newSample(++graph.offset));
84 | }
85 | }
86 |
87 | Rectangle {
88 | anchors.fill: graph
89 | color: "transparent"
90 | border.color: "black"
91 | border.width: 2
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/examples/graph/src/gridnode.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | #include "gridnode.h"
52 |
53 | #include
54 |
55 | #define GRID_SIZE 32
56 |
57 | GridNode::GridNode()
58 | : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 0)
59 | {
60 | setGeometry(&m_geometry);
61 | m_geometry.setDrawingMode(GL_LINES);
62 |
63 | setMaterial(&m_material);
64 | m_material.setColor(Qt::gray);
65 | }
66 |
67 | /*
68 | * The function hardcodes a fixed set of grid lines and scales
69 | * those to the bounding rect.
70 | */
71 | void GridNode::setRect(const QRectF &rect)
72 | {
73 | int vCount = int((rect.width() - 1) / GRID_SIZE);
74 | int hCount = int((rect.height() - 1) / GRID_SIZE);
75 |
76 | int lineCount = vCount + hCount;
77 |
78 | QSGGeometry *g = geometry();
79 |
80 | g->allocate(lineCount * 2);
81 |
82 | float x = rect.x();
83 | float y = rect.y();
84 | float w = rect.width();
85 | float h = rect.height();
86 |
87 | QSGGeometry::Point2D *v = g->vertexDataAsPoint2D();
88 |
89 | // Then write the vertical lines
90 | for (int i=0; i
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 |
19 | // That's the same as parent::write_u32, but it should always be little endian
20 | fn write_u32(val: u32) -> [u8; 4] {
21 | [
22 | (val & 0xff) as u8,
23 | ((val >> 8) & 0xff) as u8,
24 | ((val >> 16) & 0xff) as u8,
25 | ((val >> 24) & 0xff) as u8,
26 | ]
27 | }
28 |
29 | // That's the same as parent::write_u32, but it should always be little endian
30 | fn write_u16(val: u16) -> [u8; 2] {
31 | [(val & 0xff) as u8, ((val >> 8) & 0xff) as u8]
32 | }
33 |
34 | pub enum Value {
35 | String(String),
36 | Double(f64),
37 | Bool(bool),
38 | // TODO: other things
39 | }
40 |
41 | fn write_string(result: &mut Vec, str: &str) {
42 | result.extend_from_slice(&write_u16(str.len() as u16));
43 | result.extend_from_slice(str.as_bytes());
44 | let pad = (str.len() + 2) % 4;
45 | if pad != 0 {
46 | for _ in 0..(4 - pad) {
47 | result.push(0); //Padding
48 | }
49 | }
50 | }
51 |
52 | fn string_size(str: &str) -> u32 {
53 | ((2 + str.len() + 3) & !3) as u32
54 | }
55 |
56 | fn write_value(result: &mut Vec, v: &Value) {
57 | match v {
58 | Value::String(ref s) => {
59 | write_string(result, &s);
60 | }
61 | Value::Double(d) => {
62 | let bits = unsafe { std::mem::transmute::(*d) };
63 | result.extend_from_slice(&write_u32((bits & 0xffff_ffff) as u32));
64 | result.extend_from_slice(&write_u32((bits >> 32) as u32));
65 | }
66 | Value::Bool(_) => {} // value encoded in header
67 | }
68 | }
69 |
70 | fn compute_header(v: &Value, off: u32) -> u32 {
71 | match v {
72 | Value::String(_) => (3 | (1 << 3)) | (off << 5), // FIXME: Assume ascii (as does all the code)
73 | Value::Double(_) => 2 | (off << 5),
74 | Value::Bool(v) => 1 | ((*v as u32) << 5),
75 | }
76 | }
77 |
78 | fn compute_size(v: &Value) -> u32 {
79 | match v {
80 | Value::String(ref s) => string_size(&s),
81 | Value::Double(_) => 8,
82 | Value::Bool(_) => 0,
83 | }
84 | }
85 |
86 | pub fn serialize(obj: &[(&'static str, Value)]) -> Vec {
87 | let mut result: Vec = Vec::new();
88 | let mut size = 12;
89 | for e in obj {
90 | size += string_size(e.0) + compute_size(&e.1) + 8;
91 | }
92 |
93 | result.extend_from_slice(&write_u32(size as u32));
94 | result.extend_from_slice(&write_u32(1 | (obj.len() as u32) << 1));
95 | result.extend_from_slice(&write_u32(size - (obj.len() as u32) * 4));
96 |
97 | let mut table: Vec = Vec::new();
98 | let mut off = 12;
99 | for e in obj {
100 | table.push(off);
101 | off += 4 + string_size(e.0);
102 | let mut h = compute_header(&e.1, off);
103 | h |= 1 << 4;
104 | result.extend_from_slice(&write_u32(h));
105 | write_string(&mut result, e.0);
106 | write_value(&mut result, &e.1);
107 | off += compute_size(&e.1);
108 | }
109 | for x in table {
110 | result.extend_from_slice(&write_u32(x));
111 | }
112 | result
113 | }
114 |
--------------------------------------------------------------------------------
/qmetaobject_impl/src/lib.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 |
19 | //! This crates implement the custom derive used by the `qmetaobject` crate.
20 |
21 | #![recursion_limit = "256"]
22 | #![allow(clippy::unreadable_literal)] // Because we copy-paste constants from Qt
23 | #![allow(clippy::cognitive_complexity)]
24 |
25 | use proc_macro::TokenStream;
26 | use quote::{quote, ToTokens};
27 | use syn::DeriveInput;
28 |
29 | mod qbjs;
30 | mod qobject_impl;
31 | mod qrc_impl;
32 | mod simplelistitem_impl;
33 |
34 | /// Get the tokens to refer to the qmetaobject crate. By default, return "::qmetaobject" unless
35 | /// the QMetaObjectCrate is specified
36 | fn get_crate(input: &DeriveInput) -> impl ToTokens {
37 | for i in input.attrs.iter() {
38 | if let Ok(x) = i.parse_meta() {
39 | if x.path().is_ident("QMetaObjectCrate") {
40 | if let syn::Meta::NameValue(mnv) = x {
41 | use syn::Lit::*;
42 | let lit: syn::Path = match mnv.lit {
43 | Str(s) => syn::parse_str(&s.value())
44 | .expect("Can't parse QMetaObjectCrate Attribute"),
45 | _ => panic!("Can't parse QMetaObjectCrate Attribute"),
46 | };
47 | return quote!( #lit );
48 | }
49 | }
50 | }
51 | }
52 |
53 | quote!(::qmetaobject)
54 | }
55 |
56 | /// Implementation of #[derive(QObject)]
57 | #[proc_macro_derive(QObject, attributes(QMetaObjectCrate, qt_base_class))]
58 | pub fn qobject_impl(input: TokenStream) -> TokenStream {
59 | qobject_impl::generate(input, true, 5)
60 | }
61 |
62 | /// Implementation of #[derive(QObject)]
63 | #[proc_macro_derive(QObject6, attributes(QMetaObjectCrate, qt_base_class))]
64 | pub fn qobject_impl6(input: TokenStream) -> TokenStream {
65 | qobject_impl::generate(input, true, 6)
66 | }
67 |
68 | /// Implementation of #[derive(QGadget)]
69 | #[proc_macro_derive(QGadget, attributes(QMetaObjectCrate))]
70 | pub fn qgadget_impl(input: TokenStream) -> TokenStream {
71 | qobject_impl::generate(input, false, 5)
72 | }
73 |
74 | /// Implementation of #[derive(QGadget)]
75 | #[proc_macro_derive(QGadget6, attributes(QMetaObjectCrate))]
76 | pub fn qgadget_impl6(input: TokenStream) -> TokenStream {
77 | qobject_impl::generate(input, false, 6)
78 | }
79 |
80 | /// Implementation of #[derive(QEnum)]
81 | #[proc_macro_derive(QEnum, attributes(QMetaObjectCrate))]
82 | pub fn qenum_impl(input: TokenStream) -> TokenStream {
83 | qobject_impl::generate_enum(input, 5)
84 | }
85 |
86 | /// Implementation of #[derive(QEnum)]
87 | #[proc_macro_derive(QEnum6, attributes(QMetaObjectCrate))]
88 | pub fn qenum_impl6(input: TokenStream) -> TokenStream {
89 | qobject_impl::generate_enum(input, 6)
90 | }
91 |
92 | // Implementation of the qmetaobject::qrc! macro
93 | #[proc_macro]
94 | pub fn qrc_internal(input: TokenStream) -> TokenStream {
95 | qrc_impl::process_qrc(input)
96 | }
97 |
98 | /// Implementation of #[derive(SimpleListItem)]
99 | #[proc_macro_derive(SimpleListItem, attributes(QMetaObjectCrate))]
100 | pub fn simplelistitem(input: TokenStream) -> TokenStream {
101 | simplelistitem_impl::derive(input)
102 | }
103 |
--------------------------------------------------------------------------------
/qmetaobject/tests/models.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 | use std::cell::RefCell;
19 | use std::iter::FromIterator;
20 |
21 | use qmetaobject::*;
22 |
23 | mod common;
24 | use self::common::*;
25 |
26 | #[test]
27 | fn simple_model() {
28 | #[derive(Default, SimpleListItem)]
29 | struct TM {
30 | pub a: QString,
31 | pub b: u32,
32 | }
33 | let model: qmetaobject::listmodel::SimpleListModel =
34 | std::iter::once(TM { a: "hello".into(), b: 42 }).collect();
35 | assert!(do_test(
36 | model,
37 | "
38 | Item {
39 | Repeater {
40 | id: rep;
41 | model: _obj
42 | Text {
43 | text: a + b
44 | }
45 | }
46 | function doTest() {
47 | console.log('simple_model:', rep.count, rep.itemAt(0).text);
48 | return rep.count === 1 && rep.itemAt(0).text === 'hello42';
49 | }
50 | }
51 | "
52 | ));
53 | }
54 |
55 | #[test]
56 | fn simple_model_remove() {
57 | #[derive(QObject, Default)]
58 | pub struct Foo {
59 | base: qt_base_class!(trait QObject),
60 | pub list: qt_property!(RefCell>; CONST),
61 | pub remove: qt_method!(
62 | fn remove(&mut self, index: usize) {
63 | self.list.borrow_mut().remove(index);
64 | }
65 | ),
66 | }
67 |
68 | #[derive(Debug, Clone, SimpleListItem, Default)]
69 | pub struct X {
70 | pub val: usize,
71 | }
72 |
73 | impl Foo {
74 | pub fn new() -> Self {
75 | Self {
76 | list: RefCell::new(FromIterator::from_iter(vec![
77 | X { val: 10 },
78 | X { val: 11 },
79 | X { val: 12 },
80 | X { val: 13 },
81 | ])),
82 | ..Default::default()
83 | }
84 | }
85 | }
86 |
87 | let obj = Foo::new();
88 |
89 | assert!(do_test(
90 | obj,
91 | "
92 | Item {
93 | Repeater{
94 | id: rep
95 | model: _obj.list
96 | Text {
97 | text: val
98 | }
99 | }
100 | function doTest() {
101 | _obj.remove(1);
102 | console.log('simple_model_remove', rep.count, rep.itemAt(0).text, rep.itemAt(1).text, rep.itemAt(2).text);
103 | return rep.count === 3
104 | && rep.itemAt(0).text === '10'
105 | && rep.itemAt(1).text === '12'
106 | && rep.itemAt(2).text === '13';
107 | }
108 | }
109 | "
110 | ));
111 | }
112 |
113 | #[test]
114 | fn simple_model_iter() {
115 | #[derive(QObject, Default)]
116 | pub struct Foo {
117 | base: qt_base_class!(trait QObject),
118 | pub list: qt_property!(RefCell>; CONST),
119 | }
120 |
121 | #[derive(Debug, Clone, SimpleListItem, Default, PartialEq)]
122 | pub struct X {
123 | pub val: usize,
124 | }
125 |
126 | let original_items: Vec = vec![X { val: 10 }, X { val: 11 }, X { val: 12 }, X { val: 13 }];
127 |
128 | let obj = Foo {
129 | list: RefCell::new(FromIterator::from_iter(original_items.iter())),
130 | ..Default::default()
131 | };
132 |
133 | let iterated_items = obj.list.borrow().iter().cloned().collect::>();
134 | assert_eq!(original_items, iterated_items);
135 | }
136 |
--------------------------------------------------------------------------------
/qmetaobject/tests/common/mod.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
4 | associated documentation files (the "Software"), to deal in the Software without restriction,
5 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
7 | subject to the following conditions:
8 |
9 | The above copyright notice and this permission notice shall be included in all copies or substantial
10 | portions of the Software.
11 |
12 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
13 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
14 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
15 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
17 | */
18 |
19 | #![allow(dead_code)]
20 |
21 | use std::cell::RefCell;
22 | use std::sync::Mutex;
23 |
24 | use qmetaobject::*;
25 |
26 | lazy_static! {
27 | pub static ref TEST_MUTEX: Mutex<()> = Mutex::new(());
28 | pub static ref QML_LOGS: Mutex> = Mutex::new(Vec::new());
29 | }
30 |
31 | /// There can only be one thread running at the time with a QQuickEngine
32 | /// (in principle, everything should be in the same main thread)
33 | pub fn lock_for_test() -> std::sync::MutexGuard<'static, ()> {
34 | TEST_MUTEX.lock().unwrap_or_else(|e| e.into_inner())
35 | }
36 |
37 | extern "C" fn log_capture(msg_type: QtMsgType, context: &QMessageLogContext, message: &QString) {
38 | let log = format!(
39 | "{}:{} [{:?} {} {}] {}",
40 | context.file(),
41 | context.line(),
42 | msg_type,
43 | context.category(),
44 | context.function(),
45 | message
46 | );
47 | println!("{}", log);
48 | let mut logs = QML_LOGS.lock().unwrap_or_else(|e| e.into_inner());
49 | logs.push(log);
50 | }
51 |
52 | pub fn do_test(obj: T, qml: &str) -> bool {
53 | let _lock = lock_for_test();
54 | QML_LOGS.lock().unwrap_or_else(|e| e.into_inner()).clear();
55 |
56 | install_message_handler(Some(log_capture));
57 |
58 | let qml_text = "import QtQuick 2.0\n".to_owned() + qml;
59 |
60 | let obj = RefCell::new(obj);
61 |
62 | let mut engine = QmlEngine::new();
63 | engine.set_object_property("_obj".into(), unsafe { QObjectPinned::new(&obj) });
64 | engine.load_data(qml_text.into());
65 | engine.invoke_method("doTest".into(), &[]).to_bool()
66 | }
67 |
68 | /// Expect error from QmlEngine. Return it.
69 | pub fn do_test_error_with_url(obj: T, qml: &str, url: &str) -> String {
70 | let _lock = lock_for_test();
71 | QML_LOGS.lock().unwrap_or_else(|e| e.into_inner()).clear();
72 |
73 | install_message_handler(Some(log_capture));
74 |
75 | let qml_text = "import QtQuick 2.0\n".to_owned() + qml;
76 |
77 | let obj = RefCell::new(obj);
78 |
79 | let mut engine = QmlEngine::new();
80 | engine.set_object_property("_obj".into(), unsafe { QObjectPinned::new(&obj) });
81 | engine.load_data_as(qml_text.into(), QString::from(url).into());
82 | engine.invoke_method("doTest".into(), &[]);
83 | let errors = QML_LOGS.lock().unwrap_or_else(|e| e.into_inner());
84 | errors.last().expect("An error from QmlEngine was expected").clone()
85 | }
86 |
87 | pub fn do_test_variant(obj: QVariant, qml: &str) -> bool {
88 | let _lock = lock_for_test();
89 | QML_LOGS.lock().unwrap_or_else(|e| e.into_inner()).clear();
90 |
91 | install_message_handler(Some(log_capture));
92 |
93 | let qml_text = "import QtQuick 2.0\n".to_owned() + qml;
94 |
95 | let mut engine = QmlEngine::new();
96 | engine.set_property("_obj".into(), obj);
97 | engine.load_data(qml_text.into());
98 | engine.invoke_method("doTest".into(), &[]).to_bool()
99 | }
100 |
101 | pub fn test_loading_logs(qml: &str, log: &str) -> bool {
102 | let _lock = TEST_MUTEX.lock().unwrap_or_else(|e| e.into_inner());
103 | QML_LOGS.lock().unwrap_or_else(|e| e.into_inner()).clear();
104 |
105 | install_message_handler(Some(log_capture));
106 |
107 | let qml_text = "import QtQuick 2.0\n".to_owned() + qml;
108 |
109 | let mut engine = QmlEngine::new();
110 | engine.load_data(qml_text.into());
111 |
112 | let logs = QML_LOGS.lock().unwrap_or_else(|e| e.into_inner());
113 | logs.iter().any(|x| x.contains(log))
114 | }
115 |
--------------------------------------------------------------------------------
/examples/graph/src/main.rs:
--------------------------------------------------------------------------------
1 | #![allow(non_snake_case)]
2 | #![allow(unused_variables)]
3 |
4 | use cstr::cstr;
5 |
6 | #[cfg(not(no_qt))]
7 | use cpp::cpp;
8 |
9 | #[cfg(no_qt)]
10 | mod no_qt {
11 | pub fn panic() -> T {
12 | panic!("This example is not supported on Qt 6 and above")
13 | }
14 | }
15 |
16 | #[cfg(no_qt)]
17 | macro_rules! cpp {
18 | {{ $($t:tt)* }} => {};
19 | {$(unsafe)? [$($a:tt)*] -> $ret:ty as $b:tt { $($t:tt)* } } => {
20 | crate::no_qt::panic::<$ret>()
21 | };
22 | { $($t:tt)* } => {
23 | crate::no_qt::panic::<()>()
24 | };
25 | }
26 |
27 | use qmetaobject::prelude::*;
28 | use qmetaobject::scenegraph::*;
29 |
30 | mod nodes;
31 |
32 | cpp! {{
33 | #include
34 | }}
35 |
36 | #[derive(Default, QObject)]
37 | struct Graph {
38 | base: qt_base_class!(trait QQuickItem),
39 |
40 | m_samples: Vec,
41 | m_samplesChanged: bool,
42 | m_geometryChanged: bool,
43 |
44 | appendSample: qt_method!(fn(&mut self, value: f64)),
45 | removeFirstSample: qt_method!(
46 | fn removeFirstSample(&mut self) {
47 | self.m_samples.drain(0..1);
48 | self.m_samplesChanged = true;
49 | (self as &dyn QQuickItem).update();
50 | }
51 | ),
52 | }
53 |
54 | // Example of adding an enum wrapper.
55 |
56 | /// Wrapper for [`QQuickItem::Flag`][enum] enum.
57 | ///
58 | /// [enum]: https://doc.qt.io/qt-5/qquickitem.html#Flag-enum
59 | #[allow(unused)]
60 | #[repr(C)]
61 | enum QQuickItemFlag {
62 | ItemClipsChildrenToShape = 0x01,
63 | ItemAcceptsInputMethod = 0x02,
64 | ItemIsFocusScope = 0x04,
65 | ItemHasContents = 0x08,
66 | ItemAcceptsDrops = 0x10,
67 | }
68 |
69 | impl Graph {
70 | // Example of adding a method wrapper with wrapper-specific notice.
71 |
72 | /// Wrapper for [`QQuickItem::setFlag(QQuickItem::Flag flag, bool enabled = true)`][method] method.
73 | ///
74 | /// # Wrapper-specific behavior
75 | ///
76 | /// The `enabled` argument is always set to true.
77 | ///
78 | /// [method]: https://doc.qt.io/qt-5/qquickitem.html#setFlag
79 | fn set_flag(&mut self, flag: QQuickItemFlag) {
80 | let obj = self.get_cpp_object();
81 | assert!(!obj.is_null());
82 | cpp!(unsafe [obj as "QQuickItem *", flag as "QQuickItem::Flag"] {
83 | obj->setFlag(flag);
84 | });
85 | }
86 |
87 | fn appendSample(&mut self, value: f64) {
88 | self.m_samples.push(value);
89 | self.m_samplesChanged = true;
90 | // FIXME! find a better way maybe
91 | self.set_flag(QQuickItemFlag::ItemHasContents);
92 | (self as &dyn QQuickItem).update();
93 | }
94 | }
95 |
96 | impl QQuickItem for Graph {
97 | fn geometry_changed(&mut self, new_geometry: QRectF, old_geometry: QRectF) {
98 | self.m_geometryChanged = true;
99 | (self as &dyn QQuickItem).update();
100 | }
101 |
102 | fn update_paint_node(&mut self, mut node: SGNode) -> SGNode {
103 | let rect = (self as &dyn QQuickItem).bounding_rect();
104 |
105 | node.update_static((
106 | |mut n| -> SGNode {
107 | nodes::create_noisy_node(&mut n, self);
108 | if self.m_geometryChanged {
109 | nodes::noisy_node_set_rect(&mut n, rect);
110 | }
111 | n
112 | },
113 | |mut n| -> SGNode {
114 | if self.m_geometryChanged {
115 | nodes::update_grid_node(&mut n, rect);
116 | }
117 | n
118 | },
119 | |mut n| {
120 | if self.m_geometryChanged || self.m_samplesChanged {
121 | nodes::create_line_node(&mut n, 10., 0.5, QColor::from_name("steelblue"));
122 | nodes::update_line_node(&mut n, rect, &self.m_samples);
123 | }
124 | n
125 | },
126 | |mut n| {
127 | if self.m_geometryChanged || self.m_samplesChanged {
128 | nodes::create_line_node(
129 | &mut n,
130 | 20.,
131 | 0.2,
132 | QColor::from_rgba_f(0.2, 0.2, 0.2, 0.4),
133 | );
134 | // Fixme! share the geometry
135 | nodes::update_line_node(&mut n, rect, &self.m_samples);
136 | }
137 | n
138 | },
139 | ));
140 |
141 | self.m_geometryChanged = false;
142 | self.m_samplesChanged = false;
143 | node
144 | }
145 | }
146 |
147 | fn main() {
148 | nodes::init_resources();
149 | qml_register_type::(cstr!("Graph"), 1, 0, cstr!("Graph"));
150 | let mut view = QQuickView::new();
151 | view.set_source("qrc:/qml/main.qml".into());
152 | view.show();
153 | view.engine().exec();
154 | }
155 |
--------------------------------------------------------------------------------
/qmetaobject/src/qtcore/core_application.rs:
--------------------------------------------------------------------------------
1 | /* Copyright (C) 2018 Olivier Goffart
2 | Copyright (C) 2021 ivan tkachenko a.k.a. ratijas
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | associated documentation files (the "Software"), to deal in the Software without restriction,
6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
8 | subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial
11 | portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
16 | OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
17 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | */
19 | //! Wrappers around [`QtCore/QCoreApplication`][qt] header.
20 | //!
21 | //! [qt]: https://doc.qt.io/qt-5/qcoreapplication.html
22 |
23 | use cpp::cpp;
24 |
25 | use crate::*;
26 |
27 | cpp! {{
28 | #include
29 | }}
30 |
31 | /// Wrapper around [`QCoreApplication`][qt] class.
32 | ///
33 | /// # Wrapper-specific
34 | ///
35 | /// Currently it is uncreatible, non-obtainable, and exists purely as a
36 | /// namespace for public static members (associated functions in Rust).
37 | ///
38 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html
39 | pub struct QCoreApplication {
40 | // Private field makes this dummy struct uncreatable by user. Since
41 | // there's no way to obtain an instance of it, we won't have to worry
42 | // about layout compatibility and stuff.
43 | _private: (),
44 | }
45 |
46 | impl QCoreApplication {
47 | /// Wrapper around [`QString applicationName()`][qt] static method.
48 | ///
49 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#applicationName-prop
50 | pub fn application_name() -> QString {
51 | cpp!(unsafe [] -> QString as "QString" {
52 | return QCoreApplication::applicationName();
53 | })
54 | }
55 |
56 | /// Wrapper around [`void setApplicationName(const QString &application)`][qt] static method.
57 | ///
58 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#applicationName-prop
59 | pub fn set_application_name(application: QString) {
60 | cpp!(unsafe [application as "QString"] {
61 | QCoreApplication::setApplicationName(application);
62 | });
63 | }
64 |
65 | /// Wrapper around [`QString applicationVersion()`][qt] static method.
66 | ///
67 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#applicationVersion-prop
68 | pub fn application_version() -> QString {
69 | cpp!(unsafe [] -> QString as "QString" {
70 | return QCoreApplication::applicationVersion();
71 | })
72 | }
73 |
74 | /// Wrapper around [`void setApplicationVersion(const QString &version)`][qt] static method.
75 | ///
76 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#applicationVersion-prop
77 | pub fn set_application_version(version: QString) {
78 | cpp!(unsafe [version as "QString"] {
79 | QCoreApplication::setApplicationVersion(version);
80 | });
81 | }
82 |
83 | /// Wrapper around [`QString organizationDomain()`][qt] static method.
84 | ///
85 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#organizationDomain-prop
86 | pub fn organization_domain() -> QString {
87 | cpp!(unsafe [] -> QString as "QString" {
88 | return QCoreApplication::organizationDomain();
89 | })
90 | }
91 |
92 | /// Wrapper around [`void setOrganizationDomain(const QString &orgDomain)`][qt] static method.
93 | ///
94 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#organizationDomain-prop
95 | pub fn set_organization_domain(org_domain: QString) {
96 | cpp!(unsafe [org_domain as "QString"] {
97 | QCoreApplication::setOrganizationDomain(org_domain);
98 | });
99 | }
100 |
101 | /// Wrapper around [`QString organizationName()`][qt] static method.
102 | ///
103 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#organizationName-prop
104 | pub fn organization_name() -> QString {
105 | cpp!(unsafe [] -> QString as "QString" {
106 | return QCoreApplication::organizationName();
107 | })
108 | }
109 |
110 | /// Wrapper around [`void setOrganizationName(const QString &orgName)`][qt] static method.
111 | ///
112 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#organizationName-prop
113 | pub fn set_organization_name(org_name: QString) {
114 | cpp!(unsafe [org_name as "QString"] {
115 | QCoreApplication::setOrganizationName(org_name);
116 | });
117 | }
118 |
119 | /// Wrapper around [`void QCoreApplication::quit()`][qt] static method.
120 | ///
121 | /// # Note
122 | ///
123 | /// Unlike the C library function of the same name, this function does
124 | /// return to the caller — it is event processing that stops.
125 | ///
126 | /// [qt]: https://doc.qt.io/qt-5/qcoreapplication.html#quit
127 | pub fn quit() {
128 | cpp!(unsafe [] {
129 | QCoreApplication::quit();
130 | });
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/examples/graph/src/linenode.cpp:
--------------------------------------------------------------------------------
1 | /****************************************************************************
2 | **
3 | ** Copyright (C) 2017 The Qt Company Ltd.
4 | ** Contact: https://www.qt.io/licensing/
5 | **
6 | ** This file is part of the examples of the Qt Toolkit.
7 | **
8 | ** $QT_BEGIN_LICENSE:BSD$
9 | ** Commercial License Usage
10 | ** Licensees holding valid commercial Qt licenses may use this file in
11 | ** accordance with the commercial license agreement provided with the
12 | ** Software or, alternatively, in accordance with the terms contained in
13 | ** a written agreement between you and The Qt Company. For licensing terms
14 | ** and conditions see https://www.qt.io/terms-conditions. For further
15 | ** information use the contact form at https://www.qt.io/contact-us.
16 | **
17 | ** BSD License Usage
18 | ** Alternatively, you may use this file under the terms of the BSD license
19 | ** as follows:
20 | **
21 | ** "Redistribution and use in source and binary forms, with or without
22 | ** modification, are permitted provided that the following conditions are
23 | ** met:
24 | ** * Redistributions of source code must retain the above copyright
25 | ** notice, this list of conditions and the following disclaimer.
26 | ** * Redistributions in binary form must reproduce the above copyright
27 | ** notice, this list of conditions and the following disclaimer in
28 | ** the documentation and/or other materials provided with the
29 | ** distribution.
30 | ** * Neither the name of The Qt Company Ltd nor the names of its
31 | ** contributors may be used to endorse or promote products derived
32 | ** from this software without specific prior written permission.
33 | **
34 | **
35 | ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36 | ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37 | ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38 | ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39 | ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 | ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42 | ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43 | ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 | ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45 | ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46 | **
47 | ** $QT_END_LICENSE$
48 | **
49 | ****************************************************************************/
50 |
51 | #include "linenode.h"
52 |
53 | #include
54 |
55 | #include
56 |
57 | struct LineMaterial
58 | {
59 | QColor color;
60 | float spread;
61 | float size;
62 | };
63 |
64 | class LineShader : public QSGSimpleMaterialShader
65 | {
66 | QSG_DECLARE_SIMPLE_SHADER(LineShader, LineMaterial)
67 |
68 | public:
69 | LineShader() : id_color(-1), id_spread(-1), id_size(-1) {
70 | setShaderSourceFile(QOpenGLShader::Vertex, ":/scenegraph/graph/shaders/line.vsh");
71 | setShaderSourceFile(QOpenGLShader::Fragment, ":/scenegraph/graph/shaders/line.fsh");
72 | }
73 |
74 | QList attributes() const { return QList() << "pos" << "t"; }
75 |
76 | void updateState(const LineMaterial *m, const LineMaterial *) {
77 | program()->setUniformValue(id_color, m->color);
78 | program()->setUniformValue(id_spread, m->spread);
79 | program()->setUniformValue(id_size, m->size);
80 | }
81 |
82 | void resolveUniforms() {
83 | id_spread = program()->uniformLocation("spread");
84 | id_size = program()->uniformLocation("size");
85 | id_color = program()->uniformLocation("color");
86 | }
87 |
88 | private:
89 | int id_color;
90 | int id_spread;
91 | int id_size;
92 | };
93 |
94 | struct LineVertex {
95 | float x;
96 | float y;
97 | float t;
98 | inline void set(float xx, float yy, float tt) { x = xx; y = yy; t = tt; }
99 | };
100 |
101 | static const QSGGeometry::AttributeSet &attributes()
102 | {
103 | static QSGGeometry::Attribute attr[] = {
104 | QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true),
105 | QSGGeometry::Attribute::create(1, 1, GL_FLOAT)
106 | };
107 | static QSGGeometry::AttributeSet set = { 2, 3 * sizeof(float), attr };
108 | return set;
109 | }
110 |
111 | LineNode::LineNode(float size, float spread, const QColor &color)
112 | : m_geometry(attributes(), 0)
113 | {
114 | setGeometry(&m_geometry);
115 | m_geometry.setDrawingMode(GL_TRIANGLE_STRIP);
116 |
117 | QSGSimpleMaterial *m = LineShader::createMaterial();
118 | m->state()->color = color;
119 | m->state()->size = size;
120 | m->state()->spread = spread;
121 | m->setFlag(QSGMaterial::Blending);
122 | setMaterial(m);
123 | setFlag(OwnsMaterial);
124 | }
125 |
126 | /*
127 | * Assumes that samples have values in the range of 0 to 1 and scales them to
128 | * the height of bounds. The samples are stretched out horizontally along the
129 | * width of the bounds.
130 | *
131 | * The position of each pair of points is identical, but we use the third value
132 | * "t" to shift the point up or down and to add antialiasing.
133 | */
134 | void LineNode::updateGeometry(const QRectF &bounds, const QList &samples)
135 | {
136 | m_geometry.allocate(samples.size() * 2);
137 |
138 | float x = bounds.x();
139 | float y = bounds.y();
140 | float w = bounds.width();
141 | float h = bounds.height();
142 |
143 | float dx = w / (samples.size() - 1);
144 |
145 | LineVertex *v = (LineVertex *) m_geometry.vertexData();
146 | for (int i=0; i= QT_VERSION_CHECK(5, 10, 0)
54 | #include
55 | #endif
56 | #include
57 | #include
58 | #include
59 |
60 | #define NOISE_SIZE 64
61 |
62 | struct NoisyMaterial
63 | {
64 | ~NoisyMaterial() {
65 | delete texture;
66 | }
67 |
68 | QColor color;
69 | QSGTexture *texture;
70 | };
71 |
72 | class NoisyShader : public QSGSimpleMaterialShader
73 | {
74 | QSG_DECLARE_SIMPLE_SHADER(NoisyShader, NoisyMaterial)
75 |
76 | public:
77 | NoisyShader() : id_color(-1), id_texture(-1), id_textureSize(-1) {
78 | setShaderSourceFile(QOpenGLShader::Vertex, ":/scenegraph/graph/shaders/noisy.vsh");
79 | setShaderSourceFile(QOpenGLShader::Fragment, ":/scenegraph/graph/shaders/noisy.fsh");
80 | }
81 |
82 | QList attributes() const { return QList() << "aVertex" << "aTexCoord"; }
83 |
84 | void updateState(const NoisyMaterial *m, const NoisyMaterial *) {
85 |
86 | // Set the color
87 | program()->setUniformValue(id_color, m->color);
88 |
89 | // Bind the texture and set program to use texture unit 0 (the default)
90 | m->texture->bind();
91 |
92 | // Then set the texture size so we can adjust the texture coordinates accordingly in the
93 | // vertex shader..
94 | QSize s = m->texture->textureSize();
95 | program()->setUniformValue(id_textureSize, QSizeF(1.0 / s.width(), 1.0 / s.height()));
96 | }
97 |
98 | void resolveUniforms() {
99 | id_texture = program()->uniformLocation("texture");
100 | id_textureSize = program()->uniformLocation("textureSize");
101 | id_color = program()->uniformLocation("color");
102 |
103 | // We will only use texture unit 0, so set it only once.
104 | program()->setUniformValue(id_texture, 0);
105 | }
106 |
107 | private:
108 | int id_color;
109 | int id_texture;
110 | int id_textureSize;
111 | };
112 |
113 | NoisyNode::NoisyNode(QQuickWindow *window)
114 | {
115 | // Make some noise...
116 | QImage image(NOISE_SIZE, NOISE_SIZE, QImage::Format_RGB32);
117 | uint *data = (uint *) image.bits();
118 | for (int i=0; i= QT_VERSION_CHECK(5, 10, 0)
120 | uint g = QRandomGenerator::global()->bounded(0xff);
121 | #else
122 | uint g = qrand() % 0xff;
123 | #endif
124 | data[i] = 0xff000000 | (g << 16) | (g << 8) | g;
125 | }
126 |
127 | QSGTexture *t = window->createTextureFromImage(image);
128 | t->setFiltering(QSGTexture::Nearest);
129 | t->setHorizontalWrapMode(QSGTexture::Repeat);
130 | t->setVerticalWrapMode(QSGTexture::Repeat);
131 |
132 | QSGSimpleMaterial *m = NoisyShader::createMaterial();
133 | m->state()->texture = t;
134 | m->state()->color = QColor::fromRgbF(0.95, 0.95, 0.97);
135 | m->setFlag(QSGMaterial::Blending);
136 |
137 | setMaterial(m);
138 | setFlag(OwnsMaterial, true);
139 |
140 | QSGGeometry *g = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
141 | QSGGeometry::updateTexturedRectGeometry(g, QRect(), QRect());
142 | setGeometry(g);
143 | setFlag(OwnsGeometry, true);
144 | }
145 |
146 | void NoisyNode::setRect(const QRectF &bounds)
147 | {
148 | QSGGeometry::updateTexturedRectGeometry(geometry(), bounds, QRectF(0, 0, 1, 1));
149 | markDirty(QSGNode::DirtyGeometry);
150 | }
151 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qsettings.rs:
--------------------------------------------------------------------------------
1 | use crate::internal_prelude::*;
2 | use crate::QString;
3 |
4 | cpp! {{
5 | #include
6 | #include
7 | #include
8 | }}
9 |
10 | cpp_class!(
11 | /// Wrapper around [`QSettings`][class] class.
12 | ///
13 | /// [class]: https://doc.qt.io/qt-5/qsettings.html
14 | pub unsafe struct QSettings as "std::unique_ptr"
15 | );
16 |
17 | impl QSettings {
18 | /// Wrapper around [`QSettings(const QString &organization, const QString &application = QString(), QObject *parent = nullptr)`][ctor] constructor.
19 | ///
20 | /// Note: Under the hood it uses `QSettings(format, scope, org, app)` (like Qt does internally already),
21 | /// with setting `format` set to `IniFormat` and `scope` to (default) `UserScope`
22 | ///
23 | /// [ctor]: https://doc.qt.io/qt-5/qsettings.html#QSettings-3
24 | pub fn new(organization: &str, application: &str) -> Self {
25 | let organization = QString::from(organization);
26 | let application = QString::from(application);
27 | cpp!(
28 | unsafe [organization as "QString", application as "QString"] -> QSettings as "std::unique_ptr" {
29 | return std::unique_ptr(new QSettings(QSettings::IniFormat, QSettings::UserScope, organization, application));
30 | }
31 | )
32 | }
33 |
34 | /// Wrapper around [`QSettings(const QString &fileName, QSettings::Format format, QObject *parent = nullptr)`][ctor] constructor.
35 | ///
36 | /// [ctor]: https://doc.qt.io/qt-5/qsettings.html#QSettings
37 | pub fn from_path(file_name: &str) -> Self {
38 | let file_name = QString::from(file_name);
39 | cpp!(
40 | unsafe [file_name as "QString"] -> QSettings as "std::unique_ptr" {
41 | return std::unique_ptr(new QSettings(file_name, QSettings::IniFormat));
42 | }
43 | )
44 | }
45 |
46 | pub fn filename(&self) -> String {
47 | let filename: QString = cpp!(
48 | unsafe [self as "QSettings **"] -> QString as "QString" {
49 | return (*self)->fileName();
50 | }
51 | );
52 | filename.to_string()
53 | }
54 |
55 | pub fn contains(&self, key: &str) -> bool {
56 | let key = QString::from(key);
57 | unsafe {
58 | cpp!([self as "QSettings **", key as "QString"] -> bool as "bool" {
59 | return (*self)->contains(key);
60 | })
61 | }
62 | }
63 |
64 | pub fn value_bool(&self, key: &str) -> bool {
65 | let key = QString::from(key);
66 | unsafe {
67 | cpp!([self as "QSettings **", key as "QString"] -> bool as "bool" {
68 | return (*self)->value(key).toBool();
69 | })
70 | }
71 | }
72 |
73 | pub fn set_bool(&mut self, key: &str, value: bool) {
74 | let key = QString::from(key);
75 | unsafe {
76 | cpp!([self as "QSettings **", key as "QString", value as "bool"] {
77 | (*self)->setValue(key, value);
78 | })
79 | };
80 | }
81 |
82 | pub fn value_string(&self, key: &str) -> String {
83 | let key = QString::from(key);
84 | let val = unsafe {
85 | cpp!([self as "QSettings **", key as "QString"] -> QString as "QString" {
86 | return (*self)->value(key).toString();
87 | })
88 | };
89 | val.into()
90 | }
91 |
92 | pub fn set_string(&mut self, key: &str, value: &str) {
93 | let key = QString::from(key);
94 | let value = QString::from(value);
95 | unsafe {
96 | cpp!([self as "QSettings **", key as "QString", value as "QString"] {
97 | (*self)->setValue(key, value);
98 | })
99 | };
100 | }
101 |
102 | pub fn sync(&self) {
103 | unsafe {
104 | cpp!([self as "QSettings **"] {
105 | (*self)->sync();
106 | })
107 | };
108 | }
109 | }
110 |
111 | #[test]
112 | fn test_qsettings_filename() {
113 | let qsettings = QSettings::new("qmetaobject", "qsettings");
114 |
115 | assert!(
116 | qsettings.filename().ends_with("/qmetaobject/qsettings.ini"),
117 | "'{}' does not end with '/qmetaobject/qsettings.ini'",
118 | qsettings.filename()
119 | );
120 | }
121 |
122 | #[test]
123 | fn test_qsettings_new_from_path() {
124 | let qsettings = QSettings::from_path("/tmp/my_settings.conf");
125 |
126 | assert!(
127 | qsettings.filename().ends_with("/tmp/my_settings.conf"),
128 | "'{}' does not end with '/tmp/my_settings.conf'",
129 | qsettings.filename()
130 | );
131 | }
132 |
133 | #[test]
134 | fn test_qsettings_values() {
135 | let temp_dir = tempfile::tempdir().unwrap();
136 | let config_pathbuf = temp_dir.path().join("qsettings.conf");
137 | let config_file = config_pathbuf.to_str().unwrap();
138 |
139 | let mut qsettings = QSettings::from_path(config_file);
140 |
141 | qsettings.set_bool("test_true", false);
142 | qsettings.set_bool("test_false", true);
143 | qsettings.set_string("test_empty", "");
144 | qsettings.set_string("test_string", "Lorem Ipsum");
145 | qsettings.set_string("test_emoji", "🦀");
146 |
147 | qsettings.sync();
148 |
149 | assert_eq!(qsettings.value_bool("test_true"), false);
150 | assert_eq!(qsettings.value_bool("test_false"), true);
151 | assert_eq!(qsettings.value_string("test_empty"), "");
152 | assert_eq!(qsettings.value_string("test_string"), "Lorem Ipsum");
153 | assert_eq!(qsettings.value_string("test_emoji"), "🦀");
154 |
155 | drop(qsettings);
156 |
157 | let qsettings = QSettings::from_path(config_file);
158 |
159 | assert_eq!(qsettings.value_bool("test_true"), false);
160 | assert_eq!(qsettings.value_bool("test_false"), true);
161 | assert_eq!(qsettings.value_string("test_empty"), "");
162 | assert_eq!(qsettings.value_string("test_string"), "Lorem Ipsum");
163 | assert_eq!(qsettings.value_string("test_emoji"), "🦀");
164 |
165 | drop(qsettings);
166 |
167 | drop(temp_dir);
168 | assert!(!config_pathbuf.as_path().exists());
169 | }
170 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qlist/qvariantlist.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | iter::FromIterator,
3 | ops::{Index, IndexMut},
4 | };
5 |
6 | use crate::internal_prelude::*;
7 |
8 | use super::common::QListIterator;
9 | use crate::QVariant;
10 |
11 | cpp_class!(
12 | /// Wrapper around [`QVariantList`][type] typedef.
13 | ///
14 | /// [type]: https://doc.qt.io/qt-5/qvariant.html#QVariantList-typedef
15 | pub unsafe struct QVariantList as "QVariantList"
16 | );
17 | impl QVariantList {
18 | /// Wrapper around [`append(const T &)`][method] method.
19 | ///
20 | /// [method]: https://doc.qt.io/qt-5/qlist.html#append
21 | pub fn push(&mut self, value: QVariant) {
22 | cpp!(unsafe [self as "QVariantList*", value as "QVariant"] {
23 | self->append(std::move(value));
24 | })
25 | }
26 |
27 | /// Wrapper around [`insert(int, const QVariant &)`][method] method.
28 | ///
29 | /// [method]: https://doc.qt.io/qt-5/qlist.html#insert
30 | pub fn insert(&mut self, index: usize, element: QVariant) {
31 | cpp!(unsafe [self as "QVariantList*", index as "size_t", element as "QVariant"] {
32 | self->insert(index, std::move(element));
33 | })
34 | }
35 |
36 | /// Wrapper around [`takeAt(int)`][method] method.
37 | ///
38 | /// [method]: https://doc.qt.io/qt-5/qlist.html#takeAt
39 | pub fn remove(&mut self, index: usize) -> QVariant {
40 | cpp!(unsafe [self as "QVariantList*", index as "size_t"] -> QVariant as "QVariant" {
41 | return self->takeAt(index);
42 | })
43 | }
44 |
45 | /// Wrapper around [`size()`][method] method.
46 | ///
47 | /// [method]: https://doc.qt.io/qt-5/qlist.html#size
48 | pub fn len(&self) -> usize {
49 | cpp!(unsafe [self as "QVariantList*"] -> usize as "size_t" {
50 | return self->size();
51 | })
52 | }
53 |
54 | /// Wrapper around [`isEmpty()`][method] method.
55 | ///
56 | /// [method]: https://doc.qt.io/qt-5/qlist.html#isEmpty
57 | pub fn is_empty(&self) -> bool {
58 | cpp!(unsafe [self as "QVariantList*"] -> bool as "bool" {
59 | return self->isEmpty();
60 | })
61 | }
62 | }
63 |
64 | impl Index for QVariantList {
65 | type Output = QVariant;
66 |
67 | /// Wrapper around [`at(int)`][method] method.
68 | ///
69 | /// [method]: https://doc.qt.io/qt-5/qlist.html#at
70 | fn index(&self, index: usize) -> &QVariant {
71 | assert!(index < self.len());
72 | unsafe {
73 | &*cpp!([self as "QVariantList*", index as "size_t"] -> *const QVariant as "const QVariant*" {
74 | return &self->at(index);
75 | })
76 | }
77 | }
78 | }
79 |
80 | impl IndexMut for QVariantList {
81 | /// Wrapper around [`operator[](int)`][method] operator method.
82 | ///
83 | /// [method]: https://doc.qt.io/qt-5/qlist.html#operator-5b-5d
84 | fn index_mut(&mut self, index: usize) -> &mut QVariant {
85 | assert!(index < self.len());
86 | unsafe {
87 | &mut *cpp!([self as "QVariantList*", index as "size_t"] -> *mut QVariant as "QVariant*" {
88 | return &(*self)[index];
89 | })
90 | }
91 | }
92 | }
93 |
94 | impl std::fmt::Debug for QVariantList {
95 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 | f.debug_map().entries(self.into_iter().enumerate()).finish()
97 | }
98 | }
99 |
100 | impl<'a> IntoIterator for &'a QVariantList {
101 | type Item = &'a QVariant;
102 | type IntoIter = QListIterator<'a, QVariantList, QVariant>;
103 |
104 | fn into_iter(self) -> Self::IntoIter {
105 | QListIterator::new(self, 0, self.len())
106 | }
107 | }
108 |
109 | impl FromIterator for QVariantList
110 | where
111 | T: Into,
112 | {
113 | fn from_iter>(iter: I) -> QVariantList {
114 | let mut l = QVariantList::default();
115 | for i in iter {
116 | l.push(i.into());
117 | }
118 | l
119 | }
120 | }
121 |
122 | #[cfg(test)]
123 | mod tests {
124 | use super::*;
125 | use crate::{QByteArray, QString};
126 |
127 | #[test]
128 | fn test_qvariantlist() {
129 | let mut q = QVariantList::default();
130 | q.push(42.into());
131 | q.push(QString::from("Hello").into());
132 | q.push(QByteArray::from("Hello").into());
133 | assert_eq!(q[0].to_qbytearray().to_string(), "42");
134 | assert_eq!(q[1].to_qbytearray().to_string(), "Hello");
135 | assert_eq!(q[2].to_qbytearray().to_string(), "Hello");
136 | let x: Vec = q.into_iter().map(|x| x.to_qbytearray()).collect();
137 | assert_eq!(x[0].to_string(), "42");
138 | assert_eq!(x[1].to_string(), "Hello");
139 | assert_eq!(x[2].to_string(), "Hello");
140 | }
141 |
142 | #[test]
143 | fn test_qvariantlist_from_iter() {
144 | let v = vec![1u32, 2u32, 3u32];
145 | let qvl: QVariantList = v.iter().collect();
146 | assert_eq!(qvl.len(), 3);
147 | assert_eq!(qvl[1].to_qbytearray().to_string(), "2");
148 | }
149 |
150 | #[test]
151 | fn test_qstring_and_qbytearray() {
152 | let qba1: QByteArray = (b"hello" as &[u8]).into();
153 | let qba2: QByteArray = "hello".into();
154 | let s: String = "hello".into();
155 | let qba3: QByteArray = s.clone().into();
156 |
157 | assert_eq!(qba1.to_string(), "hello");
158 | assert_eq!(qba2.to_string(), "hello");
159 | assert_eq!(qba3.to_string(), "hello");
160 |
161 | let qs1: QString = "hello".into();
162 | let qs2: QString = s.into();
163 | let qba4: QByteArray = qs1.clone().into();
164 |
165 | assert_eq!(qs1.to_string(), "hello");
166 | assert_eq!(qs2.to_string(), "hello");
167 | assert_eq!(qba4.to_string(), "hello");
168 | }
169 |
170 | #[test]
171 | fn qvariantlist_debug() {
172 | let mut list = QVariantList::default();
173 | list.push(42.into());
174 | list.push(QString::from("String!").into());
175 | list.push(QByteArray::from("Bytearray!").into());
176 | assert_eq!(
177 | format!("{:?}", list),
178 | "{0: QVariant(int: \"42\"), 1: QVariant(QString: \"String!\"), 2: QVariant(QByteArray: \"Bytearray!\")}"
179 | );
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/qttypes/src/qtcore/qlist/qstringlist.rs:
--------------------------------------------------------------------------------
1 | use std::{fmt, iter::FromIterator, ops::Index};
2 |
3 | use crate::internal_prelude::*;
4 |
5 | use crate::QString;
6 |
7 | use super::common::QListIterator;
8 |
9 | cpp_class!(
10 | /// Wrapper around [`QStringList`][class] class.
11 | ///
12 | /// [class]: https://doc.qt.io/qt-5/qstringlist.html
13 | #[derive(Default, Clone, PartialEq, Eq)]
14 | pub unsafe struct QStringList as "QStringList"
15 | );
16 | impl QStringList {
17 | pub fn new() -> QStringList {
18 | cpp!(unsafe [] -> QStringList as "QStringList" {
19 | return QStringList();
20 | })
21 | }
22 |
23 | pub fn insert(&mut self, index: usize, value: QString) {
24 | cpp!(unsafe [self as "QStringList*", index as "size_t", value as "QString"] {
25 | self->insert(index, value);
26 | });
27 | }
28 |
29 | pub fn push(&mut self, value: QString) {
30 | cpp!(unsafe [self as "QStringList*", value as "QString"] {
31 | self->append(value);
32 | });
33 | }
34 |
35 | pub fn clear(&mut self) {
36 | cpp!(unsafe [self as "QStringList*"] {
37 | self->clear();
38 | });
39 | }
40 |
41 | pub fn remove(&mut self, index: usize) {
42 | cpp!(unsafe [self as "QStringList*", index as "size_t"] {
43 | self->removeAt(index);
44 | })
45 | }
46 |
47 | pub fn len(&self) -> usize {
48 | cpp!(unsafe [self as "QStringList*"] -> usize as "size_t" { return self->size(); })
49 | }
50 | }
51 |
52 | impl Index for QStringList {
53 | type Output = QString;
54 |
55 | fn index(&self, index: usize) -> &Self::Output {
56 | unsafe {
57 | &*cpp!([self as "QStringList*", index as "size_t"] -> *const QString as "const QString*" {
58 | return &(*self)[index];
59 | })
60 | }
61 | }
62 | }
63 |
64 | impl fmt::Debug for QStringList {
65 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66 | f.debug_list().entries(self.into_iter()).finish()
67 | }
68 | }
69 |
70 | impl From<[T; N]> for QStringList
71 | where
72 | QString: From,
73 | {
74 | fn from(s: [T; N]) -> Self {
75 | let mut list = QStringList::new();
76 | for i in s {
77 | list.push(QString::from(i));
78 | }
79 | list
80 | }
81 | }
82 |
83 | impl From> for QStringList
84 | where
85 | QString: From,
86 | {
87 | fn from(s: Vec) -> Self {
88 | s.into_iter().map(QString::from).collect()
89 | }
90 | }
91 |
92 | impl From<&[T]> for QStringList
93 | where
94 | T: Clone,
95 | QString: From,
96 | {
97 | fn from(s: &[T]) -> Self {
98 | s.iter().cloned().map(QString::from).collect()
99 | }
100 | }
101 |
102 | impl From for Vec
103 | where
104 | T: Clone,
105 | QString: Into,
106 | {
107 | fn from(arr: QStringList) -> Self {
108 | arr.into_iter().cloned().map(|x| x.into()).collect()
109 | }
110 | }
111 |
112 | impl<'a> IntoIterator for &'a QStringList {
113 | type Item = &'a QString;
114 | type IntoIter = QListIterator<'a, QStringList, QString>;
115 |
116 | fn into_iter(self) -> Self::IntoIter {
117 | QListIterator::new(self, 0, self.len())
118 | }
119 | }
120 |
121 | impl FromIterator for QStringList
122 | where
123 | T: Into,
124 | {
125 | fn from_iter>(iter: I) -> Self {
126 | let mut l = QStringList::default();
127 | for i in iter {
128 | l.push(i.into());
129 | }
130 | l
131 | }
132 | }
133 |
134 | #[cfg(test)]
135 | mod tests {
136 | use super::*;
137 |
138 | #[test]
139 | fn test_qstringlist() {
140 | let mut qstringlist = QStringList::new();
141 | qstringlist.push("One".into());
142 | qstringlist.push("Two".into());
143 |
144 | assert_eq!(qstringlist.len(), 2);
145 | assert_eq!(qstringlist[0], QString::from("One"));
146 |
147 | qstringlist.remove(0);
148 | assert_eq!(qstringlist[0], QString::from("Two"));
149 |
150 | qstringlist.insert(0, "Three".into());
151 | assert_eq!(qstringlist[0], QString::from("Three"));
152 |
153 | qstringlist.clear();
154 | assert_eq!(qstringlist.len(), 0);
155 | }
156 |
157 | #[test]
158 | fn test_qstringlist_from_iter() {
159 | let v = vec!["abc", "efg", "hij"];
160 | let qvl: QStringList = v.clone().into_iter().collect();
161 | assert_eq!(qvl.len(), 3);
162 | assert_eq!(qvl[1].to_string(), v[1].to_string());
163 | }
164 |
165 | #[test]
166 | fn test_vec_from_qstringlist() {
167 | let qstringlist = generate_qstring_list();
168 | let temp: Vec = qstringlist.clone().into();
169 | assert_eq!(temp, vec!["Three".to_string(), "Two".to_string()]);
170 | let temp: Vec = qstringlist.clone().into();
171 | assert_eq!(temp, vec![QString::from("Three"), QString::from("Two")]);
172 | }
173 |
174 | #[test]
175 | fn test_qstringlist_from_slice_ref() {
176 | let qstringlist = generate_qstring_list();
177 | let t = ["Three", "Two"];
178 | assert_eq!(qstringlist, QStringList::from(t));
179 | let t = ["Three".to_string(), "Two".to_string()];
180 | assert_eq!(qstringlist, QStringList::from(t));
181 | let t = [QString::from("Three"), QString::from("Two")];
182 | assert_eq!(qstringlist, QStringList::from(t));
183 | }
184 |
185 | #[test]
186 | fn test_qstringlist_from_slice() {
187 | let qstringlist = generate_qstring_list();
188 |
189 | assert_eq!(qstringlist, QStringList::from(["Three", "Two"]));
190 | assert_eq!(qstringlist, QStringList::from(["Three".to_string(), "Two".to_string()]));
191 | assert_eq!(qstringlist, QStringList::from([QString::from("Three"), QString::from("Two")]));
192 | }
193 |
194 | #[test]
195 | fn test_qstringlist_from_vec() {
196 | let qstringlist = generate_qstring_list();
197 | assert_eq!(qstringlist, QStringList::from(vec!["Three", "Two"]));
198 | assert_eq!(qstringlist, QStringList::from(vec!["Three".to_string(), "Two".to_string()]));
199 | assert_eq!(
200 | qstringlist,
201 | QStringList::from(vec![QString::from("Three"), QString::from("Two")])
202 | );
203 | }
204 |
205 | fn generate_qstring_list() -> QStringList {
206 | let mut qstringlist = QStringList::new();
207 | qstringlist.push("Three".into());
208 | qstringlist.push("Two".into());
209 | return qstringlist;
210 | }
211 | }
212 |
--------------------------------------------------------------------------------
/examples/todos/src/implementation.rs:
--------------------------------------------------------------------------------
1 | /*
2 | * Based on an example from rust-qt-binding-generator
3 | * Copyright 2017 Jos van den Oever
4 | *
5 | * This program is free software; you can redistribute it and/or
6 | * modify it under the terms of the GNU General Public License as
7 | * published by the Free Software Foundation; either version 2 of
8 | * the License or (at your option) version 3 or any later version
9 | * accepted by the membership of KDE e.V. (or its successor approved
10 | * by the membership of KDE e.V.), which shall act as a proxy
11 | * defined in Section 14 of version 3 of the license.
12 | *
13 | * This program is distributed in the hope that it will be useful,
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 | * GNU General Public License for more details.
17 | *
18 | * You should have received a copy of the GNU General Public License
19 | * along with this program. If not, see .
20 | */
21 | use std::collections::HashMap;
22 |
23 | use qmetaobject::*;
24 |
25 | #[derive(Default, Clone)]
26 | struct TodosItem {
27 | completed: bool,
28 | description: String,
29 | }
30 |
31 | #[allow(non_snake_case)]
32 | #[derive(Default, QObject)]
33 | pub struct Todos {
34 | base: qt_base_class!(trait QAbstractListModel),
35 | count: qt_property!(i32; READ row_count NOTIFY count_changed),
36 | count_changed: qt_signal!(),
37 | list: Vec,
38 | activeCount: qt_property!(usize; NOTIFY active_count_changed),
39 | active_count_changed: qt_signal!(),
40 |
41 | setCompleted: qt_method!(fn(&mut self, item: usize, v: bool) -> bool),
42 | setDescription: qt_method!(fn(&mut self, item: usize, v: String) -> bool),
43 | insert_rows: qt_method!(fn(&mut self, row: usize, count: usize) -> bool),
44 | remove_rows: qt_method!(fn(&mut self, row: usize, count: usize) -> bool),
45 | clearCompleted: qt_method!(fn(&mut self)),
46 | add: qt_method!(fn(&mut self, description: String)),
47 | remove: qt_method!(fn(&mut self, index: u64) -> bool),
48 | setAll: qt_method!(fn(&mut self, completed: bool)),
49 | }
50 |
51 | impl Todos {
52 | fn update_active_count(&mut self) {
53 | let ac = self.list.iter().filter(|i| !i.completed).count();
54 | if self.activeCount != ac {
55 | self.activeCount = ac;
56 | self.active_count_changed();
57 | }
58 | }
59 |
60 | #[allow(non_snake_case)]
61 | fn setCompleted(&mut self, item: usize, v: bool) -> bool {
62 | if item >= self.list.len() {
63 | return false;
64 | }
65 | self.list[item].completed = v;
66 | let idx = (self as &mut dyn QAbstractListModel).row_index(item as i32);
67 | (self as &mut dyn QAbstractListModel).data_changed(idx.clone(), idx);
68 | self.update_active_count();
69 | true
70 | }
71 |
72 | #[allow(non_snake_case)]
73 | fn setDescription(&mut self, item: usize, v: String) -> bool {
74 | if item >= self.list.len() {
75 | return false;
76 | }
77 | self.list[item].description = v;
78 | let idx = (self as &mut dyn QAbstractListModel).row_index(item as i32);
79 | (self as &mut dyn QAbstractListModel).data_changed(idx.clone(), idx);
80 | true
81 | }
82 |
83 | fn insert_rows(&mut self, row: usize, count: usize) -> bool {
84 | if count == 0 || row > self.list.len() {
85 | return false;
86 | }
87 | (self as &mut dyn QAbstractListModel)
88 | .begin_insert_rows(row as i32, (row + count - 1) as i32);
89 | for i in 0..count {
90 | self.list.insert(row + i, TodosItem::default());
91 | }
92 | (self as &mut dyn QAbstractListModel).end_insert_rows();
93 | self.activeCount += count;
94 | self.active_count_changed();
95 | self.count_changed();
96 | true
97 | }
98 |
99 | fn remove_rows(&mut self, row: usize, count: usize) -> bool {
100 | if count == 0 || row + count > self.list.len() {
101 | return false;
102 | }
103 | (self as &mut dyn QAbstractListModel)
104 | .begin_remove_rows(row as i32, (row + count - 1) as i32);
105 | self.list.drain(row..row + count);
106 | (self as &mut dyn QAbstractListModel).end_remove_rows();
107 | self.count_changed();
108 | self.update_active_count();
109 | true
110 | }
111 |
112 | #[allow(non_snake_case)]
113 | fn clearCompleted(&mut self) {
114 | (self as &mut dyn QAbstractListModel).begin_reset_model();
115 | self.list.retain(|i| !i.completed);
116 | (self as &mut dyn QAbstractListModel).end_reset_model();
117 | self.count_changed();
118 | }
119 |
120 | fn add(&mut self, description: String) {
121 | let end = self.list.len();
122 | (self as &mut dyn QAbstractListModel).begin_insert_rows(end as i32, end as i32);
123 | self.list.insert(end, TodosItem { completed: false, description });
124 | (self as &mut dyn QAbstractListModel).end_insert_rows();
125 | self.activeCount += 1;
126 | self.active_count_changed();
127 | self.count_changed();
128 | }
129 |
130 | fn remove(&mut self, index: u64) -> bool {
131 | self.remove_rows(index as usize, 1)
132 | }
133 |
134 | #[allow(non_snake_case)]
135 | fn setAll(&mut self, completed: bool) {
136 | for i in &mut self.list {
137 | i.completed = completed;
138 | }
139 |
140 | let idx1 = (self as &mut dyn QAbstractListModel).row_index(0);
141 | let end = self.list.len() as i32;
142 | let idx2 = (self as &mut dyn QAbstractListModel).row_index(end - 1);
143 | (self as &mut dyn QAbstractListModel).data_changed(idx1, idx2);
144 | self.update_active_count();
145 | }
146 | }
147 |
148 | impl QAbstractListModel for Todos {
149 | fn row_count(&self) -> i32 {
150 | self.list.len() as i32
151 | }
152 | fn data(&self, index: QModelIndex, role: i32) -> QVariant {
153 | let idx = index.row() as usize;
154 | if idx < self.list.len() {
155 | if role == USER_ROLE {
156 | self.list[idx].completed.into()
157 | } else if role == USER_ROLE + 1 {
158 | QString::from(self.list[idx].description.clone()).into()
159 | } else {
160 | QVariant::default()
161 | }
162 | } else {
163 | QVariant::default()
164 | }
165 | }
166 | fn role_names(&self) -> HashMap {
167 | let mut map = HashMap::new();
168 | map.insert(USER_ROLE, "completed".into());
169 | map.insert(USER_ROLE + 1, "description".into());
170 | map
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/qmetaobject/src/future.rs:
--------------------------------------------------------------------------------
1 | use std::future::Future;
2 | use std::mem::replace;
3 | use std::os::raw::c_void;
4 | use std::pin::Pin;
5 | use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};
6 |
7 | use cpp::cpp;
8 |
9 | use crate::connections::SignalArgArrayToTuple;
10 |
11 | static QT_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(
12 | |s: *const ()| {
13 | RawWaker::new(
14 | cpp!(unsafe [s as "Waker *"] -> *const() as "Waker *" {
15 | s->refs++;
16 | return s;
17 | }),
18 | &QT_WAKER_VTABLE,
19 | )
20 | },
21 | |s: *const ()| {
22 | cpp!(unsafe [s as "Waker *"] {
23 | s->wake();
24 | s->deref();
25 | })
26 | },
27 | |s: *const ()| {
28 | cpp!(unsafe [s as "Waker *"] {
29 | s->wake();
30 | })
31 | },
32 | |s: *const ()| {
33 | cpp!(unsafe [s as "Waker *"] {
34 | s->deref();
35 | })
36 | },
37 | );
38 |
39 | cpp! {{
40 |
41 | #include
42 |
43 | /// Special QObject subclass to glue together internals of Rust's futures and Qt's events.
44 | /// It's lifetime is determined through reference counting, and its lifecycle is based on
45 | /// Qt's QObject rather than C++ RAII.
46 | struct Waker : QObject {
47 | /// Wrapped Rust's Future as a dynamic trait object.
48 | TraitObject future;
49 | /// Guard against redundant processing of multiple consecutive wake-up calls.
50 | bool woken = false;
51 | /// Guard against polling a future after it has been completed.
52 | bool completed = false;
53 | /// Reference counter.
54 | QAtomicInt refs = 0;
55 |
56 | // start with refs count of 1, because caller gets the ownership.
57 | Waker(TraitObject f): future(f), refs(1) {}
58 |
59 | void customEvent(QEvent *e) override {
60 | Q_UNUSED(e);
61 | woken = false;
62 | // future must not be polled after it returned `Poll::Ready`
63 | if (completed) {
64 | return;
65 | }
66 | completed = rust!(ProcessQtEvent [
67 | this: *const () as "Waker *",
68 | future: *mut dyn Future