Skip to content

Commit 19cf07f

Browse files
committed
Move the qttypes module to its own crate
1 parent 7737c1c commit 19cf07f

File tree

7 files changed

+196
-40
lines changed

7 files changed

+196
-40
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
[workspace]
22
members = [
3+
'qttypes',
34
'qmetaobject_impl',
45
'qmetaobject',
56
'examples/todos',

qmetaobject/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ repository = "https://github.com/woboq/qmetaobject-rs"
1212

1313
[features]
1414
default = ["log"]
15-
chrono_qdatetime = ["chrono"]
15+
chrono_qdatetime = ["qttypes/chrono"]
1616
webengine = []
1717

1818
[dependencies]
19+
qttypes = { path = "../qttypes", version = "0.1.4" }
1920
qmetaobject_impl = { path = "../qmetaobject_impl", version = "=0.1.4"}
2021
lazy_static = "1.0"
2122
cpp = "0.5.4"
22-
chrono = { version = "0.4", optional = true }
2323
log = { version = "0.4", optional = true }
2424

2525
[build-dependencies]

qmetaobject/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7575
7676
# Basic types
7777
78-
The re-exported module [qttypes](qttypes/index.html) contains binding to the most usefull
79-
basic types such as [QString](qttypes/struct.QString.html),
80-
[QVariant](qttypes/struct.QVariant.html), ...
78+
The re-exported crate [`qttypes`] contains binding to the most usefull
79+
basic types such as [`QString`], [`QVariant`], ...
8180
8281
You can also simply use rust type `String`, but using QString might avoid unecessary
8382
conversions in some case.
@@ -96,7 +95,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
9695
impl QMetaType for MyPoint {};
9796
```
9897
99-
With that it is also possible to put the type in a [QVariant](qttypes/struct.QVariant.html)
98+
With that it is also possible to put the type in a [`QVariant`]
10099
101100
# Object pinning
102101
@@ -177,6 +176,8 @@ macro_rules! qmetaobject_lazy_static { ($($t:tt)*) => { lazy_static!($($t)*) } }
177176
use std::cell::RefCell;
178177
use std::os::raw::{c_char, c_void};
179178

179+
pub use qttypes;
180+
180181
pub use crate::log::*;
181182
pub use connections::RustSignal;
182183
pub use connections::{connect, Signal, SignalInner};
@@ -200,7 +201,6 @@ pub mod qrc;
200201
pub mod qtdeclarative;
201202
#[cfg(qt_5_7)]
202203
pub mod qtquickcontrols2;
203-
pub mod qttypes;
204204
pub mod scenegraph;
205205
pub mod tablemodel;
206206
#[cfg(feature = "webengine")]

qmetaobject/src/qmetatype.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,26 @@ fn test_qmetatype_register_wrong_type2() {
415415
// registering with the name of an existing type should panic
416416
MyType::register(Some(&std::ffi::CString::new("String").unwrap()));
417417
}
418+
419+
#[test]
420+
fn test_qvariant_datetime() {
421+
let dt = QDateTime::from_date_time_local_timezone(
422+
QDate::from_y_m_d(2019, 10, 23),
423+
QTime::from_h_m_s_ms(10, 30, Some(40), Some(100)),
424+
);
425+
let v = QVariant::from(dt);
426+
let qstring = QString::from_qvariant(v.clone()).unwrap();
427+
let mut s = qstring.to_string();
428+
if s.ends_with(".100") {
429+
// Old version of qt did not include the milliseconds, so remove it
430+
s.truncate(s.len() - 4);
431+
}
432+
assert_eq!(s, "2019-10-23T10:30:40");
433+
let qdate = QDate::from_qvariant(v.clone()).unwrap();
434+
assert!(qdate == QDate::from_y_m_d(2019, 10, 23));
435+
assert!(qdate != QDate::from_y_m_d(2019, 10, 24));
436+
437+
let qtime = QTime::from_qvariant(v.clone()).unwrap();
438+
assert!(qtime == QTime::from_h_m_s_ms(10, 30, Some(40), Some(100)));
439+
assert!(qtime != QTime::from_h_m_s_ms(10, 30, Some(40), None));
440+
}

qttypes/Cargo.toml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[package]
2+
name = "qttypes"
3+
version = "0.1.4"
4+
edition = "2018"
5+
authors = ["Olivier Goffart <ogoffart@woboq.com>"]
6+
build = "build.rs"
7+
description = "Manually maintained building for Qt basic types"
8+
readme = "README.md"
9+
license = "MIT"
10+
keywords = ["Qt"]
11+
repository = "https://github.com/woboq/qmetaobject-rs"
12+
13+
[dependencies]
14+
cpp = "0.5.6"
15+
chrono = { version = "0.4", optional = true }
16+
17+
[build-dependencies]
18+
cpp_build = "0.5.6"
19+
semver = "0.11"
20+
21+
[package.metadata.docs.rs]
22+
dependencies = [ "qtbase5-dev", "qtdeclarative5-dev" ]
23+
rustc-args = [ "--cfg feature=\"docs-only\"" ]

qttypes/build.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/* Copyright (C) 2018 Olivier Goffart <ogoffart@woboq.com>
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+
extern crate cpp_build;
19+
use semver::Version;
20+
use std::io::prelude::*;
21+
use std::io::BufReader;
22+
use std::path::Path;
23+
use std::process::Command;
24+
25+
fn qmake_query(var: &str) -> String {
26+
let qmake = std::env::var("QMAKE").unwrap_or("qmake".to_string());
27+
String::from_utf8(
28+
Command::new(qmake)
29+
.env("QT_SELECT", "qt5")
30+
.args(&["-query", var])
31+
.output()
32+
.expect("Failed to execute qmake. Make sure 'qmake' is in your path")
33+
.stdout,
34+
)
35+
.expect("UTF-8 conversion failed")
36+
}
37+
38+
// qreal is a double, unless QT_COORD_TYPE says otherwise:
39+
// https://doc.qt.io/qt-5/qtglobal.html#qreal-typedef
40+
fn detect_qreal_size(qt_include_path: &str) {
41+
let path = Path::new(qt_include_path).join("QtCore").join("qconfig.h");
42+
let f = std::fs::File::open(&path).expect(&format!("Cannot open `{:?}`", path));
43+
let b = BufReader::new(f);
44+
45+
// Find declaration of QT_COORD_TYPE
46+
for line in b.lines() {
47+
let line = line.expect("qconfig.h is valid UTF-8");
48+
if line.contains("QT_COORD_TYPE") {
49+
if line.contains("float") {
50+
println!("cargo:rustc-cfg=qreal_is_float");
51+
return;
52+
} else {
53+
panic!("QT_COORD_TYPE with unknown declaration {}", line);
54+
}
55+
}
56+
}
57+
}
58+
59+
fn main() {
60+
let qt_include_path = qmake_query("QT_INSTALL_HEADERS");
61+
let qt_library_path = qmake_query("QT_INSTALL_LIBS");
62+
let qt_version =
63+
qmake_query("QT_VERSION").parse::<Version>().expect("Parsing Qt version failed");
64+
let mut config = cpp_build::Config::new();
65+
66+
if cfg!(target_os = "macos") {
67+
config.flag("-F");
68+
config.flag(qt_library_path.trim());
69+
}
70+
71+
for minor in 7..=15 {
72+
if qt_version >= Version::new(5, minor, 0) {
73+
println!("cargo:rustc-cfg=qt_{}_{}", 5, minor);
74+
}
75+
}
76+
77+
detect_qreal_size(&qt_include_path.trim());
78+
79+
config.include(qt_include_path.trim()).build("src/lib.rs");
80+
81+
let macos_lib_search = if cfg!(target_os = "macos") { "=framework" } else { "" };
82+
let macos_lib_framework = if cfg!(target_os = "macos") { "" } else { "5" };
83+
84+
let debug = std::env::var("DEBUG").ok().map_or(false, |s| s == "true");
85+
let windows_dbg_suffix = if debug {
86+
if cfg!(target_os = "windows") {
87+
println!("cargo:rustc-link-lib=msvcrtd");
88+
"d"
89+
} else {
90+
""
91+
}
92+
} else {
93+
""
94+
};
95+
println!("cargo:rustc-link-search{}={}", macos_lib_search, qt_library_path.trim());
96+
println!(
97+
"cargo:rustc-link-lib{}=Qt{}Widgets{}",
98+
macos_lib_search, macos_lib_framework, windows_dbg_suffix
99+
);
100+
println!(
101+
"cargo:rustc-link-lib{}=Qt{}Gui{}",
102+
macos_lib_search, macos_lib_framework, windows_dbg_suffix
103+
);
104+
println!(
105+
"cargo:rustc-link-lib{}=Qt{}Core{}",
106+
macos_lib_search, macos_lib_framework, windows_dbg_suffix
107+
);
108+
println!(
109+
"cargo:rustc-link-lib{}=Qt{}Quick{}",
110+
macos_lib_search, macos_lib_framework, windows_dbg_suffix
111+
);
112+
println!(
113+
"cargo:rustc-link-lib{}=Qt{}Qml{}",
114+
macos_lib_search, macos_lib_framework, windows_dbg_suffix
115+
);
116+
if cfg!(feature = "webengine") {
117+
println!(
118+
"cargo:rustc-link-lib{}=Qt{}WebEngine{}",
119+
macos_lib_search, macos_lib_framework, windows_dbg_suffix
120+
);
121+
}
122+
}

qmetaobject/src/qttypes.rs renamed to qttypes/src/lib.rs

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,29 @@ OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
1616
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1717
*/
1818
//! Various bindings and wrappers for Qt classes, enums, member/static methods and functions.
19-
extern crate std;
19+
20+
use cpp::{cpp, cpp_class};
2021
use std::convert::From;
2122
use std::fmt::Display;
2223
use std::iter::FromIterator;
2324
use std::ops::{Index, IndexMut};
2425
use std::os::raw::c_char;
2526
use std::str::Utf8Error;
2627

27-
#[cfg(feature = "chrono_qdatetime")]
28+
#[cfg(feature = "chrono")]
2829
use chrono::prelude::*;
2930

31+
cpp! {{
32+
#include <QtCore/QByteArray>
33+
#include <QtCore/QString>
34+
#include <QtCore/QDateTime>
35+
#include <QtCore/QVariant>
36+
#include <QtCore/QModelIndex>
37+
#include <QtCore/QUrl>
38+
39+
#include <QtGui/QImage>
40+
}}
41+
3042
cpp_class!(
3143
/// Wrapper around [`QByteArray`][class] class.
3244
///
@@ -144,13 +156,13 @@ impl QDate {
144156
})
145157
}
146158
}
147-
#[cfg(feature = "chrono_qdatetime")]
159+
#[cfg(feature = "chrono")]
148160
impl From<NaiveDate> for QDate {
149161
fn from(a: NaiveDate) -> QDate {
150162
QDate::from_y_m_d(a.year() as i32, a.month() as i32, a.day() as i32)
151163
}
152164
}
153-
#[cfg(feature = "chrono_qdatetime")]
165+
#[cfg(feature = "chrono")]
154166
impl Into<NaiveDate> for QDate {
155167
fn into(self) -> NaiveDate {
156168
let (y, m, d) = self.get_y_m_d();
@@ -173,7 +185,7 @@ fn test_qdate_is_valid() {
173185
assert!(!invalid_qdate.is_valid());
174186
}
175187

176-
#[cfg(feature = "chrono_qdatetime")]
188+
#[cfg(feature = "chrono")]
177189
#[test]
178190
fn test_qdate_chrono() {
179191
let chrono_date = NaiveDate::from_ymd(2019, 10, 22);
@@ -260,7 +272,7 @@ impl QTime {
260272
}
261273
}
262274

263-
#[cfg(feature = "chrono_qdatetime")]
275+
#[cfg(feature = "chrono")]
264276
impl From<NaiveTime> for QTime {
265277
fn from(a: NaiveTime) -> QTime {
266278
QTime::from_h_m_s_ms(
@@ -272,7 +284,7 @@ impl From<NaiveTime> for QTime {
272284
}
273285
}
274286

275-
#[cfg(feature = "chrono_qdatetime")]
287+
#[cfg(feature = "chrono")]
276288
impl Into<NaiveTime> for QTime {
277289
fn into(self) -> NaiveTime {
278290
let (h, m, s, ms) = self.get_h_m_s_ms();
@@ -286,7 +298,7 @@ fn test_qtime() {
286298
assert_eq!((10, 30, 40, 300), qtime.get_h_m_s_ms());
287299
}
288300

289-
#[cfg(feature = "chrono_qdatetime")]
301+
#[cfg(feature = "chrono")]
290302
#[test]
291303
fn test_qtime_chrono() {
292304
let chrono_time = NaiveTime::from_hms(10, 30, 50);
@@ -874,31 +886,6 @@ mod tests {
874886
assert_eq!(qs2.to_string(), "hello");
875887
assert_eq!(qba4.to_string(), "hello");
876888
}
877-
878-
#[test]
879-
fn test_qvariant_datetime() {
880-
use crate::QMetaType;
881-
882-
let dt = QDateTime::from_date_time_local_timezone(
883-
QDate::from_y_m_d(2019, 10, 23),
884-
QTime::from_h_m_s_ms(10, 30, Some(40), Some(100)),
885-
);
886-
let v = QVariant::from(dt);
887-
let qstring = QString::from_qvariant(v.clone()).unwrap();
888-
let mut s = qstring.to_string();
889-
if s.ends_with(".100") {
890-
// Old version of qt did not include the milliseconds, so remove it
891-
s.truncate(s.len() - 4);
892-
}
893-
assert_eq!(s, "2019-10-23T10:30:40");
894-
let qdate = QDate::from_qvariant(v.clone()).unwrap();
895-
assert!(qdate == QDate::from_y_m_d(2019, 10, 23));
896-
assert!(qdate != QDate::from_y_m_d(2019, 10, 24));
897-
898-
let qtime = QTime::from_qvariant(v.clone()).unwrap();
899-
assert!(qtime == QTime::from_h_m_s_ms(10, 30, Some(40), Some(100)));
900-
assert!(qtime != QTime::from_h_m_s_ms(10, 30, Some(40), None));
901-
}
902889
}
903890

904891
cpp_class!(

0 commit comments

Comments
 (0)