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 | //! This crate contains manually generated bindings to Qt basic value types. |
19 | //! It is meant to be used by other crates, such as the `qmetaobject` crate which re-expose them. |
20 | //! |
21 | //! The Qt types are basically exposed using the [`mod@cpp`] crate. They have manually writen rust idiomatic |
22 | //! API which expose the C++ API. |
23 | //! These types are the direct equivalent of the Qt types and are exposed on the stack. |
24 | //! |
25 | //! In addition, the build script of this crate expose some metadata to downstream crate that also |
26 | //! want to use Qt's C++ API. |
27 | //! Build scripts of crates that depends directly from this crate will have the following |
28 | //! environment variables set when the build script is run: |
29 | //! - `DEP_QT_VERSION`: The Qt version as given by qmake. |
30 | //! - `DEP_QT_INCLUDE_PATH`: The include directory to give to the `cpp_build` crate to locate the Qt headers. |
31 | //! - `DEP_QT_LIBRARY_PATH`: The path containing the Qt libraries. |
32 | //! - `DEP_QT_COMPILE_FLAGS`: A list of flags separated by `;` |
33 | //! - `DEP_QT_FOUND`: Set to 1 when qt was found, or 0 if qt was not found and the `required` feature is not set. |
34 | //! - `DEP_QT_ERROR_MESSAGE`: when `DEP_QT_FOUND` is 0, contains the error that caused the build to fail |
35 | //! |
36 | //! ## Finding Qt |
37 | //! |
38 | //! This is the algorithm used to find Qt. |
39 | //! |
40 | //! - You can set the environment variable `QT_INCLUDE_PATH` and `QT_LIBRARY_PATH` to be a single |
41 | //! directory where the Qt headers and Qt libraries are installed. |
42 | //! - Otherwise you can specify a `QMAKE` environment variable with the absolute path of the |
43 | //! `qmake` executable which will be used to query these paths. |
44 | //! - If none of these environment variable is set, the `qmake` executable found in `$PATH`. |
45 | //! |
46 | //! ## Philosophy |
47 | //! |
48 | //! The goal of this crate is to expose a idiomatic Qt API for the core value type classes. |
49 | //! The API is manually generated to expose required feature in the most rust-like API, while |
50 | //! still keeping the similarities with the Qt API itself. |
51 | //! |
52 | //! It is not meant to expose all of the Qt API exhaustively, but only the part which is |
53 | //! relevant for the usage in other crate. |
54 | //! If you see a feature missing, feel free to write a issue or a pull request. |
55 | //! |
56 | //! Note that this crate concentrate on the value types, not the widgets or the |
57 | //! the `QObject`. For that, there is the `qmetaobject` crate. |
58 | //! |
59 | //! ## Usage with the `cpp` crate |
60 | //! |
61 | //! Here is an example that make use of the types exposed by this crate in combination |
62 | //! with the [`mod@cpp`] crate to call native API: |
63 | //! |
64 | //! In `Cargo.toml` |
65 | //! ```toml |
66 | //! #... |
67 | //! [dependencies] |
68 | //! qttype = "0.1" |
69 | //! cpp = "0.5" |
70 | //! #... |
71 | //! [build-dependencies] |
72 | //! cpp_build = "0.5" |
73 | //! ``` |
74 | //! |
75 | //! Note: It is important to depend directly on `qttype`, it is not enough to rely on the |
76 | //! dependency coming transitively from another dependencies, otherwise the `DEP_QT_*` |
77 | //! environment variables won't be defined. |
78 | //! |
79 | //! Then in the `build.rs` file: |
80 | //! ```rust,no_run |
81 | //! fn main() { |
82 | //! let mut config = cpp_build::Config::new(); |
83 | //! config.include(std::env::var("DEP_QT_INCLUDE_PATH" ).unwrap()); |
84 | //! for f in std::env::var("DEP_QT_COMPILE_FLAGS" ).unwrap().split_terminator(";" ) { |
85 | //! config.flag(f); |
86 | //! } |
87 | //! config.build("src/main.rs" ); |
88 | //! } |
89 | //! ``` |
90 | //! |
91 | //! With that, you can now use the types inside your .rs files: |
92 | //! |
93 | //! ```ignore |
94 | //! let byte_array = qttypes::QByteArray::from("Hello World!" ); |
95 | //! cpp::cpp!([byte_array as "QByteArray" ] { qDebug() << byte_array; }); |
96 | //! ``` |
97 | //! |
98 | //! You will find a small but working example in the |
99 | //! [qmetaobject-rs repository](https://github.com/woboq/qmetaobject-rs/tree/master/examples/graph). |
100 | //! |
101 | //! ## Cargo Features |
102 | //! |
103 | //! - **`required`**: When this feature is enabled (the default), the build script will panic with an error |
104 | //! if Qt is not found. Otherwise, when not enabled, the build will continue, but any use of the classes will |
105 | //! panic at runtime. |
106 | //! - **`chrono`**: enable the conversion between [`QDateTime`] related types and the types from the `chrono` crate. |
107 | //! |
108 | //! Link against these Qt modules using cargo features: |
109 | //! |
110 | //! | Cargo feature | Qt module | |
111 | //! | ------------------------- | --------------------- | |
112 | //! | **`qtmultimedia`** | Qt Multimedia | |
113 | //! | **`qtmultimediawidgets`** | Qt Multimedia Widgets | |
114 | //! | **`qtquick`** | Qt Quick | |
115 | //! | **`qtquickcontrols2`** | Qt Quick Controls | |
116 | //! | **`qtsql`** | Qt SQL | |
117 | //! | **`qttest`** | Qt Test | |
118 | //! | **`qtwebengine`** | Qt WebEngine | |
119 | //! |
120 | |
121 | #![cfg_attr (no_qt, allow(unused))] |
122 | |
123 | use std::collections::HashMap; |
124 | use std::convert::From; |
125 | use std::fmt; |
126 | use std::hash::Hash; |
127 | use std::iter::FromIterator; |
128 | use std::ops::{Index, IndexMut}; |
129 | |
130 | #[cfg (feature = "chrono" )] |
131 | use chrono::prelude::*; |
132 | |
133 | #[cfg (no_qt)] |
134 | pub(crate) mod no_qt { |
135 | pub fn panic<T>() -> T { |
136 | panic!("Qt was not found during build" ) |
137 | } |
138 | } |
139 | |
140 | pub(crate) mod internal_prelude { |
141 | #[cfg (not(no_qt))] |
142 | pub(crate) use cpp::{cpp, cpp_class}; |
143 | #[cfg (no_qt)] |
144 | macro_rules! cpp { |
145 | {{ $($t:tt)* }} => {}; |
146 | {$(unsafe)? [$($a:tt)*] -> $ret:ty as $b:tt { $($t:tt)* } } => { |
147 | crate::no_qt::panic::<$ret>() |
148 | }; |
149 | { $($t:tt)* } => { |
150 | crate::no_qt::panic::<()>() |
151 | }; |
152 | } |
153 | |
154 | #[cfg (no_qt)] |
155 | macro_rules! cpp_class { |
156 | ($(#[$($attrs:tt)*])* $vis:vis unsafe struct $name:ident as $type:expr) => { |
157 | #[derive(Default, Ord, Eq, PartialEq, PartialOrd, Clone, Copy)] |
158 | #[repr(C)] |
159 | $vis struct $name; |
160 | }; |
161 | } |
162 | #[cfg (no_qt)] |
163 | pub(crate) use cpp; |
164 | #[cfg (no_qt)] |
165 | pub(crate) use cpp_class; |
166 | } |
167 | use internal_prelude::*; |
168 | |
169 | mod qtcore; |
170 | pub use crate::qtcore::{ |
171 | qreal, NormalizationForm, QByteArray, QListIterator, QSettings, QString, QStringList, QUrl, |
172 | QVariant, QVariantList, UnicodeVersion, |
173 | }; |
174 | |
175 | mod qtgui; |
176 | pub use crate::qtgui::{QColor, QColorNameFormat, QColorSpec, QRgb, QRgba64}; |
177 | |
178 | cpp! {{ |
179 | #include <QtCore/QByteArray> |
180 | #include <QtCore/QDateTime> |
181 | #include <QtCore/QModelIndex> |
182 | #include <QtCore/QString> |
183 | #include <QtCore/QUrl> |
184 | #include <QtCore/QVariant> |
185 | |
186 | #include <QtGui/QImage> |
187 | #include <QtGui/QPixmap> |
188 | #include <QtGui/QPainter> |
189 | #include <QtGui/QPen> |
190 | #include <QtGui/QBrush> |
191 | }} |
192 | |
193 | cpp_class!( |
194 | /// Wrapper around [`QDate`][class] class. |
195 | /// |
196 | /// [class]: https://doc.qt.io/qt-5/qdate.html |
197 | #[derive(PartialEq, PartialOrd, Eq, Ord)] |
198 | pub unsafe struct QDate as "QDate" |
199 | ); |
200 | impl QDate { |
201 | /// Wrapper around [`QDate(int y, int m, int d)`][ctor] constructor. |
202 | /// |
203 | /// [ctor]: https://doc.qt.io/qt-5/qdate.html#QDate-2 |
204 | pub fn from_y_m_d(y: i32, m: i32, d: i32) -> Self { |
205 | cpp!(unsafe [y as "int" , m as "int" , d as "int" ] -> QDate as "QDate" { |
206 | return QDate(y, m, d); |
207 | }) |
208 | } |
209 | |
210 | /// Wrapper around [`QDate::getDate(int *year, int *month, int *day)`][method] method. |
211 | /// |
212 | /// # Wrapper-specific |
213 | /// |
214 | /// Returns the year, month and day components as a tuple, instead of mutable references. |
215 | /// |
216 | /// [method]: https://doc.qt.io/qt-5/qdate.html#getDate |
217 | pub fn get_y_m_d(&self) -> (i32, i32, i32) { |
218 | let mut res = (0, 0, 0); |
219 | let (ref mut y, ref mut m, ref mut d) = res; |
220 | |
221 | // In version prior to Qt 5.7, this method was marked non-const. |
222 | // A #[cfg(qt_5_7)] attribute does not solve that issue, because the cpp_build crate is not |
223 | // smart enough not to compile the non-qualifying closure. |
224 | cpp!(unsafe [self as "QDate*" , y as "int*" , m as "int*" , d as "int*" ] { |
225 | return self->getDate(y, m, d); |
226 | }); |
227 | |
228 | res |
229 | } |
230 | |
231 | /// Wrapper around [`QDate::isValid()`][method] method. |
232 | /// |
233 | /// [method]: https://doc.qt.io/qt-5/qdate.html#isValid |
234 | pub fn is_valid(&self) -> bool { |
235 | cpp!(unsafe [self as "const QDate*" ] -> bool as "bool" { |
236 | return self->isValid(); |
237 | }) |
238 | } |
239 | } |
240 | #[cfg (feature = "chrono" )] |
241 | impl From<NaiveDate> for QDate { |
242 | fn from(a: NaiveDate) -> QDate { |
243 | QDate::from_y_m_d(a.year() as i32, a.month() as i32, a.day() as i32) |
244 | } |
245 | } |
246 | #[cfg (feature = "chrono" )] |
247 | impl Into<NaiveDate> for QDate { |
248 | fn into(self) -> NaiveDate { |
249 | let (y, m, d) = self.get_y_m_d(); |
250 | NaiveDate::from_ymd(y, m as u32, d as u32) |
251 | } |
252 | } |
253 | |
254 | #[test ] |
255 | fn test_qdate() { |
256 | let date: QDate = QDate::from_y_m_d(y:2019, m:10, d:22); |
257 | assert_eq!((2019, 10, 22), date.get_y_m_d()); |
258 | } |
259 | |
260 | #[test ] |
261 | fn test_qdate_is_valid() { |
262 | let valid_qdate: QDate = QDate::from_y_m_d(y:2019, m:10, d:26); |
263 | assert!(valid_qdate.is_valid()); |
264 | |
265 | let invalid_qdate: QDate = QDate::from_y_m_d(y:-1, m:-1, d:-1); |
266 | assert!(!invalid_qdate.is_valid()); |
267 | } |
268 | |
269 | #[cfg (feature = "chrono" )] |
270 | #[test ] |
271 | fn test_qdate_chrono() { |
272 | let chrono_date = NaiveDate::from_ymd(2019, 10, 22); |
273 | let qdate: QDate = chrono_date.into(); |
274 | let actual_chrono_date: NaiveDate = qdate.into(); |
275 | |
276 | // Ensure that conversion works for both the Into trait and get_y_m_d() function |
277 | assert_eq!((2019, 10, 22), qdate.get_y_m_d()); |
278 | assert_eq!(chrono_date, actual_chrono_date); |
279 | } |
280 | |
281 | cpp_class!( |
282 | /// Wrapper around [`QTime`][class] class. |
283 | /// |
284 | /// [class]: https://doc.qt.io/qt-5/qtime.html |
285 | #[derive(PartialEq, PartialOrd, Eq, Ord)] |
286 | pub unsafe struct QTime as "QTime" |
287 | ); |
288 | impl QTime { |
289 | /// Wrapper around [`QTime(int h, int m, int s = 0, int ms = 0)`][ctor] constructor. |
290 | /// |
291 | /// # Wrapper-specific |
292 | /// |
293 | /// Default arguments converted to `Option`s. |
294 | /// |
295 | /// [ctor]: https://doc.qt.io/qt-5/qtime.html#QTime-2 |
296 | pub fn from_h_m_s_ms(h: i32, m: i32, s: Option<i32>, ms: Option<i32>) -> Self { |
297 | let s = s.unwrap_or(0); |
298 | let ms = ms.unwrap_or(0); |
299 | |
300 | cpp!(unsafe [h as "int" , m as "int" , s as "int" , ms as "int" ] -> QTime as "QTime" { |
301 | return QTime(h, m, s, ms); |
302 | }) |
303 | } |
304 | |
305 | /// Wrapper around [`QTime::hour()`][method] method. |
306 | /// |
307 | /// [method]: https://doc.qt.io/qt-5/qtime.html#hour |
308 | pub fn get_hour(&self) -> i32 { |
309 | cpp!(unsafe [self as "const QTime*" ] -> i32 as "int" { |
310 | return self->hour(); |
311 | }) |
312 | } |
313 | |
314 | /// Wrapper around [`QTime::minute()`][method] method. |
315 | /// |
316 | /// [method]: https://doc.qt.io/qt-5/qtime.html#minute |
317 | pub fn get_minute(&self) -> i32 { |
318 | cpp!(unsafe [self as "const QTime*" ] -> i32 as "int" { |
319 | return self->minute(); |
320 | }) |
321 | } |
322 | |
323 | /// Wrapper around [`QTime::second()`][method] method. |
324 | /// |
325 | /// [method]: https://doc.qt.io/qt-5/qtime.html#second |
326 | pub fn get_second(&self) -> i32 { |
327 | cpp!(unsafe [self as "const QTime*" ] -> i32 as "int" { |
328 | return self->second(); |
329 | }) |
330 | } |
331 | |
332 | /// Wrapper around [`QTime::msec()`][method] method. |
333 | /// |
334 | /// [method]: https://doc.qt.io/qt-5/qtime.html#msec |
335 | pub fn get_msec(&self) -> i32 { |
336 | cpp!(unsafe [self as "const QTime*" ] -> i32 as "int" { |
337 | return self->msec(); |
338 | }) |
339 | } |
340 | |
341 | /// Convenience function for obtaining the hour, minute, second and millisecond components. |
342 | pub fn get_h_m_s_ms(&self) -> (i32, i32, i32, i32) { |
343 | (self.get_hour(), self.get_minute(), self.get_second(), self.get_msec()) |
344 | } |
345 | |
346 | /// Wrapper around [`QTime::isValid()`][method] method. |
347 | /// |
348 | /// [method]: https://doc.qt.io/qt-5/qtime.html#isValid |
349 | pub fn is_valid(&self) -> bool { |
350 | cpp!(unsafe [self as "const QTime*" ] -> bool as "bool" { |
351 | return self->isValid(); |
352 | }) |
353 | } |
354 | } |
355 | |
356 | #[cfg (feature = "chrono" )] |
357 | impl From<NaiveTime> for QTime { |
358 | fn from(a: NaiveTime) -> QTime { |
359 | QTime::from_h_m_s_ms( |
360 | a.hour() as i32, |
361 | a.minute() as i32, |
362 | Some(a.second() as i32), |
363 | Some(a.nanosecond() as i32 / 1_000_000), |
364 | ) |
365 | } |
366 | } |
367 | |
368 | #[cfg (feature = "chrono" )] |
369 | impl Into<NaiveTime> for QTime { |
370 | fn into(self) -> NaiveTime { |
371 | let (h, m, s, ms) = self.get_h_m_s_ms(); |
372 | NaiveTime::from_hms_milli(h as u32, m as u32, s as u32, ms as u32) |
373 | } |
374 | } |
375 | |
376 | #[test ] |
377 | fn test_qtime() { |
378 | let qtime: QTime = QTime::from_h_m_s_ms(h:10, m:30, s:Some(40), ms:Some(300)); |
379 | assert_eq!((10, 30, 40, 300), qtime.get_h_m_s_ms()); |
380 | } |
381 | |
382 | #[cfg (feature = "chrono" )] |
383 | #[test ] |
384 | fn test_qtime_chrono() { |
385 | let chrono_time = NaiveTime::from_hms(10, 30, 50); |
386 | let qtime: QTime = chrono_time.into(); |
387 | let actual_chrono_time: NaiveTime = qtime.into(); |
388 | |
389 | // Ensure that conversion works for both the Into trait and get_h_m_s_ms() function |
390 | assert_eq!((10, 30, 50, 0), qtime.get_h_m_s_ms()); |
391 | assert_eq!(chrono_time, actual_chrono_time); |
392 | } |
393 | |
394 | #[test ] |
395 | fn test_qtime_is_valid() { |
396 | let valid_qtime: QTime = QTime::from_h_m_s_ms(h:10, m:30, s:Some(40), ms:Some(300)); |
397 | assert!(valid_qtime.is_valid()); |
398 | |
399 | let invalid_qtime: QTime = QTime::from_h_m_s_ms(h:10, m:30, s:Some(40), ms:Some(9999)); |
400 | assert!(!invalid_qtime.is_valid()); |
401 | } |
402 | |
403 | cpp_class!( |
404 | /// Wrapper around [`QDateTime`][class] class. |
405 | /// |
406 | /// [class]: https://doc.qt.io/qt-5/qdatetime.html |
407 | #[derive(PartialEq, PartialOrd, Eq, Ord)] |
408 | pub unsafe struct QDateTime as "QDateTime" |
409 | ); |
410 | impl QDateTime { |
411 | /// Wrapper around [`QDateTime(const QDateTime &other)`][ctor] constructor. |
412 | /// |
413 | /// [ctor]: https://doc.qt.io/qt-5/qdatetime.html#QDateTime-1 |
414 | pub fn from_date(date: QDate) -> Self { |
415 | cpp!(unsafe [date as "QDate" ] -> QDateTime as "QDateTime" { |
416 | #if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) |
417 | return date.startOfDay(); |
418 | #else |
419 | return QDateTime(date); |
420 | #endif |
421 | }) |
422 | } |
423 | |
424 | /// Wrapper around [`QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec = Qt::LocalTime)`][ctor] constructor. |
425 | /// |
426 | /// # Wrapper-specific |
427 | /// |
428 | /// `spec` is left as it is, thus it is always `Qt::LocalTime`. |
429 | /// |
430 | /// [ctor]: https://doc.qt.io/qt-5/qdatetime.html#QDateTime-2 |
431 | pub fn from_date_time_local_timezone(date: QDate, time: QTime) -> Self { |
432 | cpp!(unsafe [date as "QDate" , time as "QTime" ] -> QDateTime as "QDateTime" { |
433 | return QDateTime(date, time); |
434 | }) |
435 | } |
436 | |
437 | /// Wrapper around [`QDateTime::date()`][method] method. |
438 | /// |
439 | /// [method]: https://doc.qt.io/qt-5/qdatetime.html#date |
440 | pub fn get_date(&self) -> QDate { |
441 | cpp!(unsafe [self as "const QDateTime*" ] -> QDate as "QDate" { |
442 | return self->date(); |
443 | }) |
444 | } |
445 | |
446 | /// Wrapper around [`QDateTime::time()`][method] method. |
447 | /// |
448 | /// [method]: https://doc.qt.io/qt-5/qdatetime.html#time |
449 | pub fn get_time(&self) -> QTime { |
450 | cpp!(unsafe [self as "const QDateTime*" ] -> QTime as "QTime" { |
451 | return self->time(); |
452 | }) |
453 | } |
454 | |
455 | /// Convenience function for obtaining both date and time components. |
456 | pub fn get_date_time(&self) -> (QDate, QTime) { |
457 | (self.get_date(), self.get_time()) |
458 | } |
459 | |
460 | /// Wrapper around [`QDateTime::isValid()`][method] method. |
461 | /// |
462 | /// [method]: https://doc.qt.io/qt-5/qdatetime.html#isValid |
463 | pub fn is_valid(&self) -> bool { |
464 | cpp!(unsafe [self as "const QDateTime*" ] -> bool as "bool" { |
465 | return self->isValid(); |
466 | }) |
467 | } |
468 | } |
469 | |
470 | #[test ] |
471 | fn test_qdatetime_from_date() { |
472 | let qdate: QDate = QDate::from_y_m_d(y:2019, m:10, d:22); |
473 | let qdatetime: QDateTime = QDateTime::from_date(qdate); |
474 | let actual_qdate: QDate = qdatetime.get_date(); |
475 | |
476 | assert_eq!((2019, 10, 22), actual_qdate.get_y_m_d()); |
477 | } |
478 | |
479 | #[test ] |
480 | fn test_qdatetime_from_date_time_local_timezone() { |
481 | let qdate: QDate = QDate::from_y_m_d(y:2019, m:10, d:22); |
482 | let qtime: QTime = QTime::from_h_m_s_ms(h:10, m:30, s:Some(40), ms:Some(300)); |
483 | let qdatetime: QDateTime = QDateTime::from_date_time_local_timezone(date:qdate, time:qtime); |
484 | let (actual_qdate: QDate, actual_qtime: QTime) = qdatetime.get_date_time(); |
485 | |
486 | assert_eq!((2019, 10, 22), actual_qdate.get_y_m_d()); |
487 | assert_eq!((10, 30, 40, 300), actual_qtime.get_h_m_s_ms()); |
488 | |
489 | assert_eq!(10, actual_qtime.get_hour()); |
490 | assert_eq!(30, actual_qtime.get_minute()); |
491 | assert_eq!(40, actual_qtime.get_second()); |
492 | assert_eq!(300, actual_qtime.get_msec()); |
493 | } |
494 | |
495 | #[test ] |
496 | fn test_qdatetime_is_valid() { |
497 | let valid_qdate = QDate::from_y_m_d(2019, 10, 26); |
498 | let invalid_qdate = QDate::from_y_m_d(-1, -1, -1); |
499 | |
500 | let valid_qtime = QTime::from_h_m_s_ms(10, 30, Some(40), Some(300)); |
501 | let invalid_qtime = QTime::from_h_m_s_ms(10, 30, Some(40), Some(9999)); |
502 | |
503 | let valid_qdatetime_from_date = QDateTime::from_date(valid_qdate); |
504 | assert!(valid_qdatetime_from_date.is_valid()); |
505 | |
506 | let valid_qdatetime_from_valid_date_valid_time = |
507 | QDateTime::from_date_time_local_timezone(valid_qdate, valid_qtime); |
508 | assert!(valid_qdatetime_from_valid_date_valid_time.is_valid()); |
509 | |
510 | // Refer to the documentation for QDateTime's constructors using QDate, QTime. |
511 | // If the date is valid, but the time is not, the time will be set to midnight |
512 | let valid_qdatetime_from_valid_date_invalid_time = |
513 | QDateTime::from_date_time_local_timezone(valid_qdate, invalid_qtime); |
514 | assert!(valid_qdatetime_from_valid_date_invalid_time.is_valid()); |
515 | |
516 | let invalid_qdatetime_from_invalid_date_valid_time = |
517 | QDateTime::from_date_time_local_timezone(invalid_qdate, valid_qtime); |
518 | assert!(!invalid_qdatetime_from_invalid_date_valid_time.is_valid()); |
519 | |
520 | let invalid_qdatetime_from_invalid_date_invalid_time = |
521 | QDateTime::from_date_time_local_timezone(invalid_qdate, invalid_qtime); |
522 | assert!(!invalid_qdatetime_from_invalid_date_invalid_time.is_valid()); |
523 | } |
524 | |
525 | cpp_class!( |
526 | /// Wrapper around [`QVariantMap`][type] typedef. |
527 | /// |
528 | /// [type]: https://doc.qt.io/qt-5/qvariant.html#QVariantMap-typedef |
529 | #[derive(Default, PartialEq, Eq)] |
530 | pub unsafe struct QVariantMap as "QVariantMap" |
531 | ); |
532 | |
533 | impl QVariantMap { |
534 | /// Wrapper around [`insert(int, const QString &, const QVariant &)`][method] method. |
535 | /// |
536 | /// [method]: https://doc.qt.io/qt-5/qlist.html#insert |
537 | pub fn insert(&mut self, key: QString, element: QVariant) { |
538 | cpp!(unsafe [self as "QVariantMap*" , key as "QString" , element as "QVariant" ] { |
539 | self->insert(key, std::move(element)); |
540 | }) |
541 | } |
542 | |
543 | /// Wrapper around [`remove(const QString &)`][method] method. |
544 | /// |
545 | /// [method]: https://doc.qt.io/qt-5/qmap.html#remove |
546 | pub fn remove(&mut self, key: QString) -> usize { |
547 | cpp!(unsafe [self as "QVariantMap*" , key as "QString" ] -> usize as "size_t" { |
548 | return self->remove(key); |
549 | }) |
550 | } |
551 | |
552 | /// Wrapper around [`take(const QString &)`][method] method. |
553 | /// |
554 | /// [method]: https://doc.qt.io/qt-5/qmap.html#take |
555 | pub fn take(&mut self, key: QString) -> QVariant { |
556 | cpp!(unsafe [self as "QVariantMap*" , key as "QString" ] -> QVariant as "QVariant" { |
557 | return self->take(key); |
558 | }) |
559 | } |
560 | |
561 | /// Wrapper around [`size()`][method] method. |
562 | /// |
563 | /// [method]: https://doc.qt.io/qt-5/qmap.html#size |
564 | pub fn len(&self) -> usize { |
565 | cpp!(unsafe [self as "const QVariantMap*" ] -> usize as "size_t" { |
566 | return self->size(); |
567 | }) |
568 | } |
569 | |
570 | /// Wrapper around [`isEmpty()`][method] method. |
571 | /// |
572 | /// [method]: https://doc.qt.io/qt-5/qmap.html#isEmpty |
573 | pub fn is_empty(&self) -> bool { |
574 | cpp!(unsafe [self as "const QVariantMap*" ] -> bool as "bool" { |
575 | return self->isEmpty(); |
576 | }) |
577 | } |
578 | |
579 | /// Wrapper around [`contains(const QString &)`][method] method. |
580 | /// |
581 | /// [method]: https://doc.qt.io/qt-5/qmap.html#contains |
582 | pub fn contains(&self, key: QString) -> bool { |
583 | cpp!(unsafe [self as "const QVariantMap*" , key as "QString" ] -> bool as "bool" { |
584 | return self->contains(key); |
585 | }) |
586 | } |
587 | |
588 | /// Wrapper around [`clear()`][method] method. |
589 | /// |
590 | /// [method]: https://doc.qt.io/qt-5/qmap.html#clear |
591 | pub fn clear(&mut self) { |
592 | cpp!(unsafe [self as "QVariantMap*" ] { |
593 | self->clear(); |
594 | }) |
595 | } |
596 | |
597 | /// Wrapper around [`value(const QString &, const QVariant &)`][method] method. |
598 | /// |
599 | /// [method]: https://doc.qt.io/qt-5/qmap.html#value |
600 | pub fn value(&self, key: QString, default_value: QVariant) -> QVariant { |
601 | cpp!(unsafe [self as "const QVariantMap*" , key as "QString" , default_value as "QVariant" ] -> QVariant as "QVariant" { |
602 | return self->value(key, default_value); |
603 | }) |
604 | } |
605 | |
606 | /// Wrapper around [`key(const QVariant &, const QString &)`][method] method. |
607 | /// |
608 | /// [method]: https://doc.qt.io/qt-5/qmap.html#key |
609 | pub fn key(&self, value: QVariant, default_key: QString) -> QString { |
610 | cpp!(unsafe [self as "const QVariantMap*" , default_key as "QString" , value as "QVariant" ] -> QString as "QString" { |
611 | return self->key(value, default_key); |
612 | }) |
613 | } |
614 | } |
615 | |
616 | impl Index<QString> for QVariantMap { |
617 | type Output = QVariant; |
618 | |
619 | /// Wrapper around [`at(int)`][method] method. |
620 | /// |
621 | /// [method]: https://doc.qt.io/qt-5/qlist.html#at |
622 | #[track_caller ] |
623 | fn index(&self, key: QString) -> &Self::Output { |
624 | cpp!(unsafe [self as "const QVariantMap*" , key as "QString" ] -> Option<&QVariant> as "const QVariant*" { |
625 | auto x = self->constFind(key); |
626 | if (x == self->constEnd()) { |
627 | return NULL; |
628 | } else { |
629 | return &x.value(); |
630 | } |
631 | }).expect(msg:"key not in the QVariant" ) |
632 | } |
633 | } |
634 | impl IndexMut<QString> for QVariantMap { |
635 | /// Wrapper around [`operator[](int)`][method] operator method. |
636 | /// |
637 | /// [method]: https://doc.qt.io/qt-5/qlist.html#operator-5b-5d |
638 | fn index_mut(&mut self, key: QString) -> &mut Self::Output { |
639 | unsafe { |
640 | &mut *cpp!([self as "QVariantMap*" , key as "QString" ] -> *mut QVariant as "QVariant*" { |
641 | return &(*self)[key]; |
642 | }) |
643 | } |
644 | } |
645 | } |
646 | |
647 | impl fmt::Debug for QVariantMap { |
648 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
649 | f.debug_map().entries(self.into_iter()).finish() |
650 | } |
651 | } |
652 | |
653 | cpp_class!(unsafe struct QVariantMapIteratorInternal as "QVariantMap::iterator" ); |
654 | |
655 | /// Internal class used to iterate over a [`QVariantMap`] |
656 | pub struct QVariantMapIterator<'a> { |
657 | map: &'a QVariantMap, |
658 | iterator: QVariantMapIteratorInternal, |
659 | } |
660 | |
661 | impl<'a> QVariantMapIterator<'a> { |
662 | fn key(&self) -> Option<&'a QString> { |
663 | let iterator = &self.iterator; |
664 | cpp!(unsafe [iterator as "const QVariantMap::iterator*" ] -> Option<&QString> as "const QString*" { |
665 | return &iterator->key(); |
666 | }) |
667 | } |
668 | |
669 | fn value(&self) -> Option<&'a QVariant> { |
670 | let iterator = &self.iterator; |
671 | cpp!(unsafe [iterator as "const QVariantMap::iterator*" ] -> Option<&QVariant> as "QVariant*" { |
672 | return &iterator->value(); |
673 | }) |
674 | } |
675 | |
676 | fn check_end(&self) -> bool { |
677 | let map = self.map; |
678 | let iterator = &self.iterator; |
679 | cpp!(unsafe [iterator as "const QVariantMap::iterator*" , map as "const QVariantMap*" ] -> bool as "bool" { |
680 | return (*iterator == map->end()); |
681 | }) |
682 | } |
683 | |
684 | fn increment(&mut self) { |
685 | let iterator = &self.iterator; |
686 | cpp!(unsafe [iterator as "QVariantMap::iterator*" ] { |
687 | ++(*iterator); |
688 | }) |
689 | } |
690 | } |
691 | |
692 | impl<'a> Iterator for QVariantMapIterator<'a> { |
693 | type Item = (&'a QString, &'a QVariant); |
694 | |
695 | fn next(&mut self) -> Option<Self::Item> { |
696 | if self.check_end() { |
697 | return None; |
698 | } |
699 | |
700 | let key: Option<&QString> = self.key(); |
701 | let value: Option<&QVariant> = self.value(); |
702 | |
703 | self.increment(); |
704 | |
705 | match (key, value) { |
706 | (Some(k: &QString), Some(v: &QVariant)) => Some((k, v)), |
707 | _ => None, |
708 | } |
709 | } |
710 | } |
711 | |
712 | impl<'a> IntoIterator for &'a QVariantMap { |
713 | type Item = (&'a QString, &'a QVariant); |
714 | type IntoIter = QVariantMapIterator<'a>; |
715 | |
716 | fn into_iter(self) -> Self::IntoIter { |
717 | let iter: QVariantMapIteratorInternal = cpp!(unsafe [self as "QVariantMap*" ] -> QVariantMapIteratorInternal as "QVariantMap::iterator" { |
718 | return self->begin(); |
719 | }); |
720 | Self::IntoIter { map: self, iterator: iter } |
721 | } |
722 | } |
723 | |
724 | impl<K, V> FromIterator<(K, V)> for QVariantMap |
725 | where |
726 | K: Into<QString>, |
727 | V: Into<QVariant>, |
728 | { |
729 | fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> Self { |
730 | let mut m: QVariantMap = QVariantMap::default(); |
731 | for i: (K, V) in iter { |
732 | let (k: K, v: V) = i; |
733 | m.insert(key:k.into(), element:v.into()); |
734 | } |
735 | m |
736 | } |
737 | } |
738 | |
739 | impl<K, V> From<HashMap<K, V>> for QVariantMap |
740 | where |
741 | K: Into<QString>, |
742 | V: Into<QVariant>, |
743 | { |
744 | fn from(m: HashMap<K, V>) -> Self { |
745 | m.into_iter().collect() |
746 | } |
747 | } |
748 | |
749 | impl<K, V, const N: usize> From<[(K, V); N]> for QVariantMap |
750 | where |
751 | K: Into<QString>, |
752 | V: Into<QVariant>, |
753 | { |
754 | fn from(m: [(K, V); N]) -> Self { |
755 | let mut temp: QVariantMap = QVariantMap::default(); |
756 | for (key: K, val: V) in m { |
757 | temp.insert(key:key.into(), element:val.into()); |
758 | } |
759 | temp |
760 | } |
761 | } |
762 | |
763 | impl<K, V> From<QVariantMap> for HashMap<K, V> |
764 | where |
765 | K: Hash + Eq, |
766 | V: Eq, |
767 | QString: Into<K>, |
768 | QVariant: Into<V>, |
769 | { |
770 | fn from(m: QVariantMap) -> Self { |
771 | m.into_iter().map(|(k: &QString, v: &QVariant)| (k.clone().into(), v.clone().into())).collect() |
772 | } |
773 | } |
774 | |
775 | #[cfg (test)] |
776 | mod qvariantmap_tests { |
777 | use super::*; |
778 | |
779 | #[test ] |
780 | fn test_qvariantmap() { |
781 | let mut map = QVariantMap::default(); |
782 | |
783 | let key1 = QString::from("a" ); |
784 | let val1 = QString::from("abc" ); |
785 | |
786 | assert!(map.is_empty()); |
787 | map.insert(key1.clone(), val1.clone().into()); |
788 | assert_eq!(map.len(), 1); |
789 | assert_eq!(map[key1.clone()].to_qbytearray().to_string(), val1.to_string()); |
790 | |
791 | assert_eq!(map.take(key1.clone()).to_qbytearray().to_string(), val1.to_string()); |
792 | assert!(map.is_empty()); |
793 | |
794 | map[key1.clone()] = val1.clone().into(); |
795 | |
796 | let default_value = QVariant::from(10); |
797 | |
798 | assert_eq!(map[key1.clone()].to_qbytearray().to_string(), val1.to_string()); |
799 | assert_eq!(map.value(key1.clone(), default_value.clone()), val1.clone().into()); |
800 | assert_eq!(map.value(val1.clone(), default_value.clone()), default_value.clone()); |
801 | |
802 | assert_eq!(map.key(val1.clone().into(), val1.clone()), key1.clone()); |
803 | assert_eq!(map.key(key1.clone().into(), val1.clone()), val1.clone()); |
804 | } |
805 | |
806 | #[test ] |
807 | #[should_panic (expected = "key not in the QVariant" )] |
808 | fn test_index_panic() { |
809 | let map = QVariantMap::default(); |
810 | |
811 | map[QString::from("t" )].to_qbytearray().to_string(); |
812 | } |
813 | |
814 | #[test ] |
815 | fn test_iter() { |
816 | let hashmap = |
817 | HashMap::from([("Mercury" , 0.4), ("Venus" , 0.7), ("Earth" , 1.0), ("Mars" , 1.5)]); |
818 | let map: QVariantMap = hashmap.clone().into(); |
819 | |
820 | assert_eq!(map.len(), hashmap.len()); |
821 | |
822 | for (k, v) in map.into_iter() { |
823 | assert_eq!(hashmap[k.to_string().as_str()].to_string(), v.to_qbytearray().to_string()); |
824 | } |
825 | } |
826 | |
827 | #[test ] |
828 | fn test_from() { |
829 | let hashmap1 = HashMap::from([ |
830 | ("A" .to_string(), QVariant::from(QString::from("abc" ))), |
831 | ("B" .to_string(), QVariant::from(QString::from("def" ))), |
832 | ]); |
833 | let qvariantmap1: QVariantMap = hashmap1.clone().into(); |
834 | let hashmap2 = qvariantmap1.clone().into(); |
835 | assert_eq!(hashmap1, hashmap2); |
836 | |
837 | let qvariantmap2 = QVariantMap::from([ |
838 | ("A" .to_string(), QVariant::from(QString::from("abc" ))), |
839 | ("B" .to_string(), QVariant::from(QString::from("def" ))), |
840 | ]); |
841 | assert_eq!(qvariantmap1, qvariantmap2); |
842 | } |
843 | } |
844 | |
845 | cpp_class!( |
846 | /// Wrapper around [`QModelIndex`][class] class. |
847 | /// |
848 | /// [class]: https://doc.qt.io/qt-5/qmodelindex.html |
849 | #[derive(PartialEq, Eq)] |
850 | pub unsafe struct QModelIndex as "QModelIndex" |
851 | ); |
852 | impl QModelIndex { |
853 | /// Wrapper around [`internalId()`][method] method. |
854 | /// |
855 | /// [method]: https://doc.qt.io/qt-5/qmodelindex.html#internalId |
856 | pub fn id(&self) -> usize { |
857 | cpp!(unsafe [self as "const QModelIndex*" ] -> usize as "uintptr_t" { return self->internalId(); }) |
858 | } |
859 | |
860 | /// Wrapper around [`column()`][method] method. |
861 | /// |
862 | /// [method]: https://doc.qt.io/qt-5/qmodelindex.html#column |
863 | pub fn column(&self) -> i32 { |
864 | cpp!(unsafe [self as "const QModelIndex*" ] -> i32 as "int" { return self->column(); }) |
865 | } |
866 | |
867 | /// Wrapper around [`row()`][method] method. |
868 | /// |
869 | /// [method]: https://doc.qt.io/qt-5/qmodelindex.html#row |
870 | pub fn row(&self) -> i32 { |
871 | cpp!(unsafe [self as "const QModelIndex*" ] -> i32 as "int" { return self->row(); }) |
872 | } |
873 | |
874 | /// Wrapper around [`isValid()`][method] method. |
875 | /// |
876 | /// [method]: https://doc.qt.io/qt-5/qmodelindex.html#isValid |
877 | pub fn is_valid(&self) -> bool { |
878 | cpp!(unsafe [self as "const QModelIndex*" ] -> bool as "bool" { return self->isValid(); }) |
879 | } |
880 | } |
881 | |
882 | /// Bindings for [`QRectF`][class] class. |
883 | /// |
884 | /// [class]: https://doc.qt.io/qt-5/qrectf.html |
885 | #[repr (C)] |
886 | #[derive (Default, Clone, Copy, PartialEq, Debug)] |
887 | pub struct QRectF { |
888 | pub x: qreal, |
889 | pub y: qreal, |
890 | pub width: qreal, |
891 | pub height: qreal, |
892 | } |
893 | impl QRectF { |
894 | /// Wrapper around [`contains(const QPointF &)`][method] method. |
895 | /// |
896 | /// [method]: https://doc.qt.io/qt-5/qrectf.html#contains |
897 | pub fn contains(&self, pos: QPointF) -> bool { |
898 | cpp!(unsafe [self as "const QRectF*" , pos as "QPointF" ] -> bool as "bool" { |
899 | return self->contains(pos); |
900 | }) |
901 | } |
902 | |
903 | /// Same as the [`topLeft`][method] method. |
904 | /// |
905 | /// [method]: https://doc.qt.io/qt-5/qrectf.html#topLeft |
906 | pub fn top_left(&self) -> QPointF { |
907 | QPointF { x: self.x, y: self.y } |
908 | } |
909 | |
910 | /// Same as the [`isValid`][method] method. |
911 | /// |
912 | /// [method]: https://doc.qt.io/qt-5/qrectf.html#isValid |
913 | pub fn is_valid(&self) -> bool { |
914 | self.width > 0. && self.height > 0. |
915 | } |
916 | } |
917 | |
918 | /// Bindings for [`QPointF`][class] class. |
919 | /// |
920 | /// [class]: https://doc.qt.io/qt-5/qpointf.html |
921 | #[repr (C)] |
922 | #[derive (Default, Clone, Copy, PartialEq, Debug)] |
923 | pub struct QPointF { |
924 | pub x: qreal, |
925 | pub y: qreal, |
926 | } |
927 | impl std::ops::Add for QPointF { |
928 | type Output = QPointF; |
929 | /// Wrapper around [`operator+(const QPointF &, const QPointF &)`][func] function. |
930 | /// |
931 | /// [func]: https://doc.qt.io/qt-5/qpointf.html#operator-2b |
932 | fn add(self, other: QPointF) -> QPointF { |
933 | QPointF { x: self.x + other.x, y: self.y + other.y } |
934 | } |
935 | } |
936 | impl std::ops::AddAssign for QPointF { |
937 | /// Wrapper around [`operator+=(const QPointF &`][method] method. |
938 | /// |
939 | /// [method]: https://doc.qt.io/qt-5/qpointf.html#operator-2b-eq |
940 | fn add_assign(&mut self, other: QPointF) { |
941 | *self = QPointF { x: self.x + other.x, y: self.y + other.y }; |
942 | } |
943 | } |
944 | |
945 | /// Bindings for [`QSizeF`][class] class. |
946 | /// |
947 | /// [class]: https://doc.qt.io/qt-5/qsizef.html |
948 | #[repr (C)] |
949 | #[derive (Default, Clone, Copy, PartialEq, Debug)] |
950 | pub struct QSizeF { |
951 | pub width: qreal, |
952 | pub height: qreal, |
953 | } |
954 | |
955 | #[test ] |
956 | fn test_qpointf_qrectf() { |
957 | let rect: QRectF = QRectF { x: 200., y: 150., width: 60., height: 75. }; |
958 | let pt: QPointF = QPointF { x: 12., y: 5.5 }; |
959 | assert!(!rect.contains(pt)); |
960 | assert!(rect.contains(pt + rect.top_left())); |
961 | } |
962 | |
963 | /// Bindings for [`QSize`][class] class. |
964 | /// |
965 | /// [class]: https://doc.qt.io/qt-5/qsize.html |
966 | #[repr (C)] |
967 | #[derive (Default, Clone, Copy, PartialEq, Debug)] |
968 | pub struct QSize { |
969 | pub width: u32, |
970 | pub height: u32, |
971 | } |
972 | |
973 | /// Bindings for [`QPoint`][class] class. |
974 | /// |
975 | /// [class]: https://doc.qt.io/qt-5/qpoint.html |
976 | #[repr (C)] |
977 | #[derive (Default, Clone, Copy, PartialEq, Debug)] |
978 | pub struct QPoint { |
979 | pub x: i32, |
980 | pub y: i32, |
981 | } |
982 | |
983 | /// Bindings for [`QMargins`][class] class. |
984 | /// |
985 | /// [class]: https://doc.qt.io/qt-5/qmargins.html |
986 | #[repr (C)] |
987 | #[derive (Default, Clone, Copy, PartialEq, Debug)] |
988 | pub struct QMargins { |
989 | pub left: i32, |
990 | pub top: i32, |
991 | pub right: i32, |
992 | pub bottom: i32, |
993 | } |
994 | |
995 | /// Bindings for [`QImage::Format`][class] enum class. |
996 | /// |
997 | /// [class]: https://doc.qt.io/qt-5/qimage.html#Format-enum |
998 | #[repr (C)] |
999 | #[derive (Clone, Copy, PartialEq, Debug)] |
1000 | #[allow (non_camel_case_types)] |
1001 | pub enum ImageFormat { |
1002 | Invalid = 0, |
1003 | Mono = 1, |
1004 | MonoLSB = 2, |
1005 | Indexed8 = 3, |
1006 | RGB32 = 4, |
1007 | ARGB32 = 5, |
1008 | ARGB32_Premultiplied = 6, |
1009 | RGB16 = 7, |
1010 | ARGB8565_Premultiplied = 8, |
1011 | RGB666 = 9, |
1012 | ARGB6666_Premultiplied = 10, |
1013 | RGB555 = 11, |
1014 | ARGB8555_Premultiplied = 12, |
1015 | RGB888 = 13, |
1016 | RGB444 = 14, |
1017 | ARGB4444_Premultiplied = 15, |
1018 | RGBX8888 = 16, |
1019 | RGBA8888 = 17, |
1020 | RGBA8888_Premultiplied = 18, |
1021 | BGR30 = 19, |
1022 | A2BGR30_Premultiplied = 20, |
1023 | RGB30 = 21, |
1024 | A2RGB30_Premultiplied = 22, |
1025 | Alpha8 = 23, |
1026 | Grayscale8 = 24, |
1027 | Grayscale16 = 28, |
1028 | RGBX64 = 25, |
1029 | RGBA64 = 26, |
1030 | RGBA64_Premultiplied = 27, |
1031 | BGR888 = 29, |
1032 | } |
1033 | cpp_class!( |
1034 | /// Wrapper around [`QImage`][class] class. |
1035 | /// |
1036 | /// [class]: https://doc.qt.io/qt-5/qimage.html |
1037 | #[derive(Default, Clone, PartialEq)] |
1038 | pub unsafe struct QImage as "QImage" |
1039 | ); |
1040 | impl QImage { |
1041 | /// Wrapper around [`QImage(const QString &fileName, const char *format = nullptr)`][ctor] constructor. |
1042 | /// |
1043 | /// [ctor]: https://doc.qt.io/qt-5/qimage.html#QImage-8 |
1044 | pub fn load_from_file(filename: QString) -> Self { |
1045 | cpp!(unsafe [filename as "QString" ] -> QImage as "QImage" { |
1046 | return QImage(filename); |
1047 | }) |
1048 | } |
1049 | |
1050 | /// Wrapper around [`QImage(const QSize &, QImage::Format)`][ctor] constructor. |
1051 | /// |
1052 | /// [ctor]: https://doc.qt.io/qt-5/qimage.html#QImage-1 |
1053 | pub fn new(size: QSize, format: ImageFormat) -> Self { |
1054 | cpp!(unsafe [size as "QSize" , format as "QImage::Format" ] -> QImage as "QImage" { |
1055 | return QImage(size, format); |
1056 | }) |
1057 | } |
1058 | |
1059 | /// Wrapper around [`size()`][method] method. |
1060 | /// |
1061 | /// [method]: https://doc.qt.io/qt-5/qimage.html#size |
1062 | pub fn size(&self) -> QSize { |
1063 | cpp!(unsafe [self as "const QImage*" ] -> QSize as "QSize" { return self->size(); }) |
1064 | } |
1065 | |
1066 | /// Wrapper around [`format()`][method] method. |
1067 | /// |
1068 | /// [method]: https://doc.qt.io/qt-5/qimage.html#format |
1069 | pub fn format(&self) -> ImageFormat { |
1070 | cpp!(unsafe [self as "const QImage*" ] -> ImageFormat as "QImage::Format" { return self->format(); }) |
1071 | } |
1072 | |
1073 | /// Wrapper around [`fill(const QColor &)`][method] method. |
1074 | /// |
1075 | /// [method]: https://doc.qt.io/qt-5/qimage.html#fill-1 |
1076 | pub fn fill(&mut self, color: QColor) { |
1077 | cpp!(unsafe [self as "QImage*" , color as "QColor" ] { self->fill(color); }) |
1078 | } |
1079 | |
1080 | /// Wrapper around [`setPixelColor(const QPoint &, const QColor &)`][method] method. |
1081 | /// |
1082 | /// [method]: https://doc.qt.io/qt-5/qimage.html#setPixelColor |
1083 | pub fn set_pixel_color(&mut self, x: u32, y: u32, color: QColor) { |
1084 | cpp!(unsafe [self as "QImage*" , x as "int" , y as "int" , color as "QColor" ] { |
1085 | self->setPixelColor(x, y, color); |
1086 | }) |
1087 | } |
1088 | |
1089 | /// Wrapper around [`pixelColor(const QPoint &)`][method] method. |
1090 | /// |
1091 | /// [method]: https://doc.qt.io/qt-5/qimage.html#pixelColor |
1092 | pub fn get_pixel_color(&self, x: u32, y: u32) -> QColor { |
1093 | cpp!(unsafe [self as "const QImage*" , x as "int" , y as "int" ] -> QColor as "QColor" { |
1094 | return self->pixelColor(x, y); |
1095 | }) |
1096 | } |
1097 | } |
1098 | |
1099 | cpp_class!( |
1100 | /// Wrapper around [`QPixmap`][class] class. |
1101 | /// |
1102 | /// [class]: https://doc.qt.io/qt-5/qpixmap.html |
1103 | pub unsafe struct QPixmap as "QPixmap" |
1104 | ); |
1105 | |
1106 | impl QPixmap { |
1107 | /// Wrapper around [`size()`][method] method. |
1108 | /// |
1109 | /// [method]: https://doc.qt.io/qt-5/qpixmap.html#size |
1110 | pub fn size(&self) -> QSize { |
1111 | cpp!(unsafe [self as "const QPixmap*" ] -> QSize as "QSize" { return self->size(); }) |
1112 | } |
1113 | } |
1114 | |
1115 | impl From<QPixmap> for QImage { |
1116 | fn from(pixmap: QPixmap) -> Self { |
1117 | cpp!(unsafe [pixmap as "QPixmap" ] -> QImage as "QImage" { return pixmap.toImage(); }) |
1118 | } |
1119 | } |
1120 | |
1121 | impl From<QImage> for QPixmap { |
1122 | fn from(image: QImage) -> Self { |
1123 | cpp!(unsafe [image as "QImage" ] -> QPixmap as "QPixmap" { return QPixmap::fromImage(image); }) |
1124 | } |
1125 | } |
1126 | |
1127 | /// Bindings for [`Qt::PenStyle`][enum] enum. |
1128 | /// |
1129 | /// [enum]: https://doc.qt.io/qt-5/qt.html#PenStyle-enum |
1130 | #[repr (C)] |
1131 | #[derive (Clone, Copy, PartialEq, Debug)] |
1132 | #[allow (non_camel_case_types)] |
1133 | pub enum PenStyle { |
1134 | NoPen = 0, |
1135 | SolidLine = 1, |
1136 | DashLine = 2, |
1137 | DotLine = 3, |
1138 | DashDotLine = 4, |
1139 | DashDotDotLine = 5, |
1140 | CustomDashLine = 6, |
1141 | } |
1142 | cpp_class!( |
1143 | /// Wrapper around [`QPen`][class] class. |
1144 | /// |
1145 | /// [class]: https://doc.qt.io/qt-5/qpen.html |
1146 | #[derive(Default)] |
1147 | pub unsafe struct QPen as "QPen" |
1148 | ); |
1149 | |
1150 | impl QPen { |
1151 | pub fn from_color(color: QColor) -> Self { |
1152 | cpp!(unsafe [color as "QColor" ] -> QPen as "QPen" { return QPen(color); }) |
1153 | } |
1154 | pub fn from_style(style: PenStyle) -> Self { |
1155 | cpp!(unsafe [style as "Qt::PenStyle" ] -> QPen as "QPen" { return QPen(style); }) |
1156 | } |
1157 | pub fn set_color(&mut self, color: QColor) { |
1158 | cpp!(unsafe [self as "QPen*" , color as "QColor" ] { return self->setColor(color); }); |
1159 | } |
1160 | pub fn set_style(&mut self, style: PenStyle) { |
1161 | cpp!(unsafe [self as "QPen*" , style as "Qt::PenStyle" ] { return self->setStyle(style); }); |
1162 | } |
1163 | pub fn set_width(&mut self, width: i32) { |
1164 | cpp!(unsafe [self as "QPen*" , width as "int" ] { return self->setWidth(width); }); |
1165 | } |
1166 | pub fn set_width_f(&mut self, width: qreal) { |
1167 | cpp!(unsafe [self as "QPen*" , width as "qreal" ] { return self->setWidthF(width); }); |
1168 | } |
1169 | |
1170 | // QBrush brush() const |
1171 | // Qt::PenCapStyle capStyle() const |
1172 | // QColor color() const |
1173 | // qreal dashOffset() const |
1174 | // QVector<qreal> dashPattern() const |
1175 | // bool isCosmetic() const |
1176 | // bool isSolid() const |
1177 | // Qt::PenJoinStyle joinStyle() const |
1178 | // qreal miterLimit() const |
1179 | // void setBrush(const QBrush &brush) |
1180 | // void setCapStyle(Qt::PenCapStyle style) |
1181 | // void setCosmetic(bool cosmetic) |
1182 | // void setDashOffset(qreal offset) |
1183 | // void setDashPattern(const QVector<qreal> &pattern) |
1184 | // void setJoinStyle(Qt::PenJoinStyle style) |
1185 | // void setMiterLimit(qreal limit) |
1186 | // Qt::PenStyle style() const |
1187 | // void swap(QPen &other) |
1188 | // int width() const |
1189 | // qreal widthF() const |
1190 | } |
1191 | |
1192 | /// Bindings for [`QStandardPaths::StandardLocation`][enum] enum. |
1193 | /// |
1194 | /// [enum]: https://doc.qt.io/qt-5/qstandardpaths.html#StandardLocation-enum |
1195 | #[repr (C)] |
1196 | #[derive (Clone, Copy, PartialEq, Debug)] |
1197 | #[allow (non_camel_case_types)] |
1198 | pub enum QStandardPathLocation { |
1199 | DesktopLocation = 0, |
1200 | DocumentsLocation = 1, |
1201 | FontsLocation = 2, |
1202 | ApplicationsLocation = 3, |
1203 | MusicLocation = 4, |
1204 | MoviesLocation = 5, |
1205 | PicturesLocation = 6, |
1206 | TempLocation = 7, |
1207 | HomeLocation = 8, |
1208 | AppLocalDataLocation = 9, |
1209 | CacheLocation = 10, |
1210 | GenericDataLocation = 11, |
1211 | RuntimeLocation = 12, |
1212 | ConfigLocation = 13, |
1213 | DownloadLocation = 14, |
1214 | GenericCacheLocation = 15, |
1215 | GenericConfigLocation = 16, |
1216 | AppDataLocation = 17, |
1217 | AppConfigLocation = 18, |
1218 | } |
1219 | |
1220 | /// Bindings for [`Qt::BrushStyle`][enum] enum. |
1221 | /// |
1222 | /// [enum]: https://doc.qt.io/qt-5/qt.html#BrushStyle-enum |
1223 | #[repr (C)] |
1224 | #[derive (Clone, Copy, PartialEq, Debug)] |
1225 | #[allow (non_camel_case_types)] |
1226 | pub enum BrushStyle { |
1227 | NoBrush = 0, |
1228 | SolidPattern = 1, |
1229 | Dense1Pattern = 2, |
1230 | Dense2Pattern = 3, |
1231 | Dense3Pattern = 4, |
1232 | Dense4Pattern = 5, |
1233 | Dense5Pattern = 6, |
1234 | Dense6Pattern = 7, |
1235 | Dense7Pattern = 8, |
1236 | HorPattern = 9, |
1237 | VerPattern = 10, |
1238 | CrossPattern = 11, |
1239 | BDiagPattern = 12, |
1240 | FDiagPattern = 13, |
1241 | DiagCrossPattern = 14, |
1242 | LinearGradientPattern = 15, |
1243 | ConicalGradientPattern = 17, |
1244 | RadialGradientPattern = 16, |
1245 | TexturePattern = 24, |
1246 | } |
1247 | cpp_class!( |
1248 | /// Wrapper around [`QBrush`][class] class. |
1249 | /// |
1250 | /// [class]: https://doc.qt.io/qt-5/qbrush.html |
1251 | #[derive(Default)] |
1252 | pub unsafe struct QBrush as "QBrush " |
1253 | ); |
1254 | impl QBrush { |
1255 | pub fn from_color(color: QColor) -> Self { |
1256 | cpp!(unsafe [color as "QColor" ] -> QBrush as "QBrush" { return QBrush(color); }) |
1257 | } |
1258 | pub fn from_style(style: BrushStyle) -> Self { |
1259 | cpp!(unsafe [style as "Qt::BrushStyle" ] -> QBrush as "QBrush" { return QBrush(style); }) |
1260 | } |
1261 | pub fn set_color(&mut self, color: QColor) { |
1262 | cpp!(unsafe [self as "QBrush*" , color as "QColor" ] { return self->setColor(color); }); |
1263 | } |
1264 | pub fn set_style(&mut self, style: BrushStyle) { |
1265 | cpp!(unsafe [self as "QBrush*" , style as "Qt::BrushStyle" ] { return self->setStyle(style); }); |
1266 | } |
1267 | } |
1268 | |
1269 | /// Bindings for [`QLineF`][class] class. |
1270 | /// |
1271 | /// [class]: https://doc.qt.io/qt-5/qlinef.html |
1272 | #[repr (C)] |
1273 | #[derive (Default, Clone, Copy, PartialEq, Debug)] |
1274 | pub struct QLineF { |
1275 | pub pt1: QPointF, |
1276 | pub pt2: QPointF, |
1277 | } |
1278 | |
1279 | cpp_class!( |
1280 | /// Wrapper around [`QPainter`][class] class. |
1281 | /// |
1282 | /// [class]: https://doc.qt.io/qt-5/qpainter.html |
1283 | pub unsafe struct QPainter as "QPainter " |
1284 | ); |
1285 | impl QPainter { |
1286 | pub fn draw_arc(&mut self, rectangle: QRectF, start_angle: i32, span_angle: i32) { |
1287 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" , start_angle as "int" , span_angle as "int" ] { |
1288 | self->drawArc(rectangle, start_angle, span_angle); |
1289 | }); |
1290 | } |
1291 | pub fn draw_chord(&mut self, rectangle: QRectF, start_angle: i32, span_angle: i32) { |
1292 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" , start_angle as "int" , span_angle as "int" ] { |
1293 | self->drawChord(rectangle, start_angle, span_angle); |
1294 | }); |
1295 | } |
1296 | |
1297 | pub fn draw_convex_polygon(&mut self, points: &[QPointF]) { |
1298 | let points_ptr = points.as_ptr(); |
1299 | let points_count = points.len() as u64; |
1300 | cpp!(unsafe [self as "QPainter *" , points_ptr as "QPointF*" , points_count as "uint64_t" ] { |
1301 | self->drawConvexPolygon(points_ptr, points_count); |
1302 | }); |
1303 | } |
1304 | |
1305 | pub fn draw_ellipse(&mut self, rectangle: QRectF) { |
1306 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" ] { |
1307 | self->drawEllipse(rectangle); |
1308 | }); |
1309 | } |
1310 | pub fn draw_ellipse_with_center(&mut self, center: QPointF, rx: qreal, ry: qreal) { |
1311 | cpp!(unsafe [self as "QPainter *" , center as "QPointF" , rx as "qreal" , ry as "qreal" ] { |
1312 | self->drawEllipse(center, rx, ry); |
1313 | }); |
1314 | } |
1315 | |
1316 | pub fn draw_image_fit_rect(&mut self, rectangle: QRectF, image: QImage) { |
1317 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" , image as "QImage" ] { |
1318 | self->drawImage(rectangle, image); |
1319 | }); |
1320 | } |
1321 | pub fn draw_image_at_point(&mut self, point: QPointF, image: QImage) { |
1322 | cpp!(unsafe [self as "QPainter *" , point as "QPointF" , image as "QImage" ] { |
1323 | self->drawImage(point, image); |
1324 | }); |
1325 | } |
1326 | pub fn draw_image_fit_rect_with_source( |
1327 | &mut self, |
1328 | rectangle: QRectF, |
1329 | image: QImage, |
1330 | source_rect: QRectF, |
1331 | ) { |
1332 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" , image as "QImage" , source_rect as "QRectF" ] { |
1333 | self->drawImage(rectangle, image, source_rect); |
1334 | }); |
1335 | } |
1336 | pub fn draw_image_at_point_with_source( |
1337 | &mut self, |
1338 | point: QPointF, |
1339 | image: QImage, |
1340 | source_rect: QRectF, |
1341 | ) { |
1342 | cpp!(unsafe [self as "QPainter *" , point as "QPointF" , image as "QImage" , source_rect as "QRectF" ] { |
1343 | self->drawImage(point, image, source_rect); |
1344 | }); |
1345 | } |
1346 | |
1347 | pub fn draw_line(&mut self, line: QLineF) { |
1348 | cpp!(unsafe [self as "QPainter *" , line as "QLineF" ] { |
1349 | self->drawLine(line); |
1350 | }); |
1351 | } |
1352 | pub fn draw_lines(&mut self, lines: &[QLineF]) { |
1353 | let lines_ptr = lines.as_ptr(); |
1354 | let lines_count = lines.len() as u64; |
1355 | cpp!(unsafe [self as "QPainter *" , lines_ptr as "QLineF*" , lines_count as "uint64_t" ] { |
1356 | self->drawLines(lines_ptr, lines_count); |
1357 | }); |
1358 | } |
1359 | pub fn draw_lines_from_points(&mut self, point_pairs: &[QPointF]) { |
1360 | let point_pairs_ptr = point_pairs.as_ptr(); |
1361 | let point_pairs_count = point_pairs.len() as u64; |
1362 | cpp!(unsafe [self as "QPainter *" , point_pairs_ptr as "QLineF*" , point_pairs_count as "uint64_t" ] { |
1363 | self->drawLines(point_pairs_ptr, point_pairs_count); |
1364 | }); |
1365 | } |
1366 | |
1367 | pub fn draw_pie(&mut self, rectangle: QRectF, start_angle: i32, span_angle: i32) { |
1368 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" , start_angle as "int" , span_angle as "int" ] { |
1369 | self->drawPie(rectangle, start_angle, span_angle); |
1370 | }); |
1371 | } |
1372 | |
1373 | pub fn draw_point(&mut self, point: QPointF) { |
1374 | cpp!(unsafe [self as "QPainter *" , point as "QPointF" ] { |
1375 | self->drawPoint(point); |
1376 | }); |
1377 | } |
1378 | pub fn draw_points(&mut self, points: &[QPointF]) { |
1379 | let points_ptr = points.as_ptr(); |
1380 | let points_count = points.len() as u64; |
1381 | cpp!(unsafe [self as "QPainter *" , points_ptr as "QPointF*" , points_count as "uint64_t" ] { |
1382 | self->drawPoints(points_ptr, points_count); |
1383 | }); |
1384 | } |
1385 | |
1386 | pub fn draw_polygon(&mut self, points: &[QPointF]) { |
1387 | let points_ptr = points.as_ptr(); |
1388 | let points_count = points.len() as u64; |
1389 | cpp!(unsafe [self as "QPainter *" , points_ptr as "QPointF*" , points_count as "uint64_t" ] { |
1390 | self->drawPolygon(points_ptr, points_count); |
1391 | }); |
1392 | } |
1393 | pub fn draw_polyline(&mut self, points: &[QPointF]) { |
1394 | let points_ptr = points.as_ptr(); |
1395 | let points_count = points.len() as u64; |
1396 | cpp!(unsafe [self as "QPainter *" , points_ptr as "QPointF*" , points_count as "uint64_t" ] { |
1397 | self->drawPolyline(points_ptr, points_count); |
1398 | }); |
1399 | } |
1400 | |
1401 | pub fn draw_rect(&mut self, rectangle: QRectF) { |
1402 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" ] { |
1403 | self->drawRect(rectangle); |
1404 | }); |
1405 | } |
1406 | pub fn draw_rects(&mut self, rects: &[QRectF]) { |
1407 | let rects_ptr = rects.as_ptr(); |
1408 | let rects_count = rects.len() as u64; |
1409 | cpp!(unsafe [self as "QPainter *" , rects_ptr as "QRectF*" , rects_count as "uint64_t" ] { |
1410 | self->drawRects(rects_ptr, rects_count); |
1411 | }); |
1412 | } |
1413 | pub fn draw_rounded_rect(&mut self, rect: QRectF, x_radius: qreal, y_radius: qreal) { |
1414 | cpp!(unsafe [self as "QPainter *" , rect as "QRectF" , x_radius as "qreal" , y_radius as "qreal" ] { |
1415 | self->drawRoundedRect(rect, x_radius, y_radius); |
1416 | }); |
1417 | } |
1418 | |
1419 | pub fn draw_text(&mut self, position: QPointF, text: QString) { |
1420 | cpp!(unsafe [self as "QPainter *" , position as "QPointF" , text as "QString" ] { |
1421 | self->drawText(position, text); |
1422 | }); |
1423 | } |
1424 | pub fn draw_text_in_rect(&mut self, rectangle: QRectF, flags: u32, text: QString) -> QRectF { |
1425 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" , flags as "uint32_t" , text as "QString" ] -> QRectF as "QRectF" { |
1426 | QRectF boundingRect; |
1427 | self->drawText(rectangle, flags, text, &boundingRect); |
1428 | return boundingRect; |
1429 | }) |
1430 | } |
1431 | |
1432 | pub fn erase_rect(&mut self, rectangle: QRectF) { |
1433 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" ] { |
1434 | self->eraseRect(rectangle); |
1435 | }); |
1436 | } |
1437 | |
1438 | pub fn fill_rect(&mut self, rectangle: QRectF, brush: QBrush) { |
1439 | cpp!(unsafe [self as "QPainter *" , rectangle as "QRectF" , brush as "QBrush" ] { |
1440 | self->fillRect(rectangle, brush); |
1441 | }); |
1442 | } |
1443 | |
1444 | pub fn reset_transform(&mut self) { |
1445 | cpp!(unsafe [self as "QPainter *" ] { |
1446 | self->resetTransform(); |
1447 | }); |
1448 | } |
1449 | |
1450 | pub fn restore(&mut self) { |
1451 | cpp!(unsafe [self as "QPainter *" ] { |
1452 | self->restore(); |
1453 | }); |
1454 | } |
1455 | |
1456 | pub fn rotate(&mut self, angle: qreal) { |
1457 | cpp!(unsafe [self as "QPainter *" , angle as "qreal" ] { |
1458 | self->rotate(angle); |
1459 | }); |
1460 | } |
1461 | |
1462 | pub fn save(&mut self) { |
1463 | cpp!(unsafe [self as "QPainter *" ] { |
1464 | self->save(); |
1465 | }); |
1466 | } |
1467 | |
1468 | pub fn scale(&mut self, sx: qreal, sy: qreal) { |
1469 | cpp!(unsafe [self as "QPainter *" , sx as "qreal" , sy as "qreal" ] { |
1470 | self->scale(sx, sy); |
1471 | }); |
1472 | } |
1473 | |
1474 | pub fn set_background(&mut self, brush: QBrush) { |
1475 | cpp!(unsafe [self as "QPainter *" , brush as "QBrush" ] { |
1476 | self->setBackground(brush); |
1477 | }); |
1478 | } |
1479 | |
1480 | pub fn set_brush(&mut self, brush: QBrush) { |
1481 | cpp!(unsafe [self as "QPainter *" , brush as "QBrush" ] { |
1482 | self->setBrush(brush); |
1483 | }); |
1484 | } |
1485 | |
1486 | pub fn set_opacity(&mut self, opacity: qreal) { |
1487 | cpp!(unsafe [self as "QPainter *" , opacity as "qreal" ] { |
1488 | self->setOpacity(opacity); |
1489 | }); |
1490 | } |
1491 | |
1492 | pub fn set_pen(&mut self, pen: QPen) { |
1493 | cpp!(unsafe [self as "QPainter *" , pen as "QPen" ] { |
1494 | self->setPen(pen); |
1495 | }); |
1496 | } |
1497 | |
1498 | pub fn translate(&mut self, offset: QPointF) { |
1499 | cpp!(unsafe [self as "QPainter *" , offset as "QPointF" ] { |
1500 | self->translate(offset); |
1501 | }); |
1502 | } |
1503 | pub fn set_render_hint(&mut self, hint: QPainterRenderHint, on: bool) { |
1504 | cpp!(unsafe [self as "QPainter *" , hint as "QPainter::RenderHint" , on as "bool" ] { |
1505 | self->setRenderHint(hint, on); |
1506 | }); |
1507 | } |
1508 | |
1509 | // void setBackgroundMode(Qt::BGMode mode) |
1510 | // void setCompositionMode(QPainter::CompositionMode mode) |
1511 | // void setFont(const QFont &font) |
1512 | } |
1513 | |
1514 | /// Bindings for [`QPainter::RenderHint`][enum] enum. |
1515 | /// |
1516 | /// [enum]: https://doc.qt.io/qt-5/qpainter.html#RenderHint-enum |
1517 | #[repr (C)] |
1518 | #[derive (Clone, Copy, PartialEq, Debug)] |
1519 | #[allow (non_camel_case_types)] |
1520 | pub enum QPainterRenderHint { |
1521 | Antialiasing = 0x01, |
1522 | TextAntialiasing = 0x02, |
1523 | SmoothPixmapTransform = 0x04, |
1524 | HighQualityAntialiasing = 0x08, |
1525 | NonCosmeticDefaultPen = 0x10, |
1526 | Qt4CompatiblePainting = 0x20, |
1527 | LosslessImageRendering = 0x40, |
1528 | } |
1529 | |
1530 | cpp! {{ |
1531 | #include <QtCore/QJsonDocument> |
1532 | #include <QtCore/QJsonValue> |
1533 | #include <QtCore/QJsonObject> |
1534 | #include <QtCore/QJsonArray> |
1535 | }} |
1536 | cpp_class!( |
1537 | /// Wrapper around [`QJsonValue`][class] class. |
1538 | /// |
1539 | /// [class]: https://doc.qt.io/qt-5/qjsonvalue.html |
1540 | #[derive(Default, PartialEq, Eq, Clone)] |
1541 | pub unsafe struct QJsonValue as "QJsonValue" |
1542 | ); |
1543 | |
1544 | impl Into<QVariant> for QJsonValue { |
1545 | fn into(self) -> QVariant { |
1546 | cpp!(unsafe [self as "QJsonValue" ] -> QVariant as "QVariant" { return self.toVariant(); }) |
1547 | } |
1548 | } |
1549 | impl From<QVariant> for QJsonValue { |
1550 | fn from(v: QVariant) -> QJsonValue { |
1551 | cpp!(unsafe [v as "QVariant" ] -> QJsonValue as "QJsonValue" { return QJsonValue::fromVariant(v); }) |
1552 | } |
1553 | } |
1554 | |
1555 | impl Into<QJsonObject> for QJsonValue { |
1556 | fn into(self) -> QJsonObject { |
1557 | cpp!(unsafe [self as "QJsonValue" ] -> QJsonObject as "QJsonObject" { return self.toObject(); }) |
1558 | } |
1559 | } |
1560 | impl From<QJsonObject> for QJsonValue { |
1561 | fn from(v: QJsonObject) -> QJsonValue { |
1562 | cpp!(unsafe [v as "QJsonObject" ] -> QJsonValue as "QJsonValue" { return QJsonValue(v); }) |
1563 | } |
1564 | } |
1565 | impl Into<QJsonArray> for QJsonValue { |
1566 | fn into(self) -> QJsonArray { |
1567 | cpp!(unsafe [self as "QJsonValue" ] -> QJsonArray as "QJsonArray" { return self.toArray(); }) |
1568 | } |
1569 | } |
1570 | impl From<QJsonArray> for QJsonValue { |
1571 | fn from(v: QJsonArray) -> QJsonValue { |
1572 | cpp!(unsafe [v as "QJsonArray" ] -> QJsonValue as "QJsonValue" { return QJsonValue(v); }) |
1573 | } |
1574 | } |
1575 | |
1576 | impl Into<QString> for QJsonValue { |
1577 | fn into(self) -> QString { |
1578 | cpp!(unsafe [self as "QJsonValue" ] -> QString as "QString" { return self.toString(); }) |
1579 | } |
1580 | } |
1581 | impl From<QString> for QJsonValue { |
1582 | fn from(v: QString) -> QJsonValue { |
1583 | cpp!(unsafe [v as "QString" ] -> QJsonValue as "QJsonValue" { return QJsonValue(v); }) |
1584 | } |
1585 | } |
1586 | |
1587 | impl Into<bool> for QJsonValue { |
1588 | fn into(self) -> bool { |
1589 | cpp!(unsafe [self as "QJsonValue" ] -> bool as "bool" { return self.toBool(); }) |
1590 | } |
1591 | } |
1592 | impl From<bool> for QJsonValue { |
1593 | fn from(v: bool) -> QJsonValue { |
1594 | cpp!(unsafe [v as "bool" ] -> QJsonValue as "QJsonValue" { return QJsonValue(v); }) |
1595 | } |
1596 | } |
1597 | |
1598 | impl Into<f64> for QJsonValue { |
1599 | fn into(self) -> f64 { |
1600 | cpp!(unsafe [self as "QJsonValue" ] -> f64 as "double" { return self.toDouble(); }) |
1601 | } |
1602 | } |
1603 | impl From<f64> for QJsonValue { |
1604 | fn from(v: f64) -> QJsonValue { |
1605 | cpp!(unsafe [v as "double" ] -> QJsonValue as "QJsonValue" { return QJsonValue(v); }) |
1606 | } |
1607 | } |
1608 | |
1609 | #[test ] |
1610 | fn test_qjsonvalue() { |
1611 | let test_str = QJsonValue::from(QVariant::from(QString::from("test" ))); |
1612 | let test_str2 = QJsonValue::from(QString::from("test" )); |
1613 | assert!(test_str == test_str2); |
1614 | assert_eq!(<QJsonValue as Into<QString>>::into(test_str), QString::from("test" )); |
1615 | |
1616 | let test_bool = QJsonValue::from(true); |
1617 | let test_bool_variant: QVariant = QJsonValue::from(true).into(); |
1618 | let test_bool_variant2 = QVariant::from(true); |
1619 | assert!(test_bool_variant == test_bool_variant2); |
1620 | assert_eq!(<QJsonValue as Into<bool>>::into(test_bool), true); |
1621 | |
1622 | let test_f64 = QJsonValue::from(1.2345); |
1623 | let test_f64_variant: QVariant = QJsonValue::from(1.2345).into(); |
1624 | let test_f64_variant2 = QVariant::from(1.2345); |
1625 | assert!(test_f64_variant == test_f64_variant2); |
1626 | assert_eq!(<QJsonValue as Into<f64>>::into(test_f64), 1.2345); |
1627 | |
1628 | let values = QJsonArray::from(vec![ |
1629 | QJsonValue::from(QString::from("test" )), |
1630 | QJsonValue::from(true), |
1631 | QJsonValue::from(false), |
1632 | QJsonValue::from(1.2345), |
1633 | QJsonValue::from(456.0), |
1634 | ]); |
1635 | |
1636 | assert_eq!(values.to_json().to_string(), "[ \"test \",true,false,1.2345,456]" ); |
1637 | } |
1638 | |
1639 | cpp_class!( |
1640 | /// Wrapper around [`QJsonObject`][class] class. |
1641 | /// |
1642 | /// [class]: https://doc.qt.io/qt-5/qjsonobject.html |
1643 | #[derive(Default, PartialEq, Eq, Clone)] |
1644 | pub unsafe struct QJsonObject as "QJsonObject" |
1645 | ); |
1646 | |
1647 | impl QJsonObject { |
1648 | pub fn to_json(&self) -> QByteArray { |
1649 | cpp!(unsafe [self as "QJsonObject*" ] -> QByteArray as "QByteArray" { return QJsonDocument(*self).toJson(QJsonDocument::Compact); }) |
1650 | } |
1651 | pub fn to_json_pretty(&self) -> QByteArray { |
1652 | cpp!(unsafe [self as "QJsonObject*" ] -> QByteArray as "QByteArray" { return QJsonDocument(*self).toJson(QJsonDocument::Indented); }) |
1653 | } |
1654 | pub fn insert(&mut self, key: &str, value: QJsonValue) { |
1655 | let len = key.len(); |
1656 | let ptr = key.as_ptr(); |
1657 | cpp!(unsafe [self as "QJsonObject*" , len as "size_t" , ptr as "char*" , value as "QJsonValue" ] { self->insert(QString::fromUtf8(ptr, len), std::move(value)); }) |
1658 | } |
1659 | pub fn value(&self, key: &str) -> QJsonValue { |
1660 | let len = key.len(); |
1661 | let ptr = key.as_ptr(); |
1662 | cpp!(unsafe [self as "QJsonObject*" , len as "size_t" , ptr as "char*" ] -> QJsonValue as "QJsonValue" { return self->value(QString::fromUtf8(ptr, len)); }) |
1663 | } |
1664 | pub fn take(&mut self, key: &str) -> QJsonValue { |
1665 | let len = key.len(); |
1666 | let ptr = key.as_ptr(); |
1667 | cpp!(unsafe [self as "QJsonObject*" , len as "size_t" , ptr as "char*" ] -> QJsonValue as "QJsonValue" { return self->take(QString::fromUtf8(ptr, len)); }) |
1668 | } |
1669 | pub fn remove(&mut self, key: &str) { |
1670 | let len = key.len(); |
1671 | let ptr = key.as_ptr(); |
1672 | cpp!(unsafe [self as "QJsonObject*" , len as "size_t" , ptr as "char*" ] { return self->remove(QString::fromUtf8(ptr, len)); }) |
1673 | } |
1674 | pub fn len(&self) -> usize { |
1675 | cpp!(unsafe [self as "QJsonObject*" ] -> usize as "size_t" { return self->size(); }) |
1676 | } |
1677 | pub fn is_empty(&self) -> bool { |
1678 | cpp!(unsafe [self as "QJsonObject*" ] -> bool as "bool" { return self->isEmpty(); }) |
1679 | } |
1680 | pub fn contains(&self, key: &str) -> bool { |
1681 | let len = key.len(); |
1682 | let ptr = key.as_ptr(); |
1683 | cpp!(unsafe [self as "QJsonObject*" , len as "size_t" , ptr as "char*" ] -> bool as "bool" { return self->contains(QString::fromUtf8(ptr, len)); }) |
1684 | } |
1685 | pub fn keys(&self) -> Vec<String> { |
1686 | let len = self.len(); |
1687 | let mut vec = Vec::with_capacity(len); |
1688 | |
1689 | let keys = cpp!(unsafe [self as "QJsonObject*" ] -> QStringList as "QStringList" { return self->keys(); }); |
1690 | |
1691 | for i in 0..len { |
1692 | vec.push(keys[i].to_string()); |
1693 | } |
1694 | vec |
1695 | } |
1696 | } |
1697 | |
1698 | impl From<HashMap<String, String>> for QJsonObject { |
1699 | fn from(v: HashMap<String, String>) -> QJsonObject { |
1700 | let keys: Vec<QString> = v.keys().cloned().map(QString::from).collect(); |
1701 | let values: Vec<QString> = v.values().cloned().map(QString::from).collect(); |
1702 | let keys_ptr: *const QString = keys.as_ptr(); |
1703 | let values_ptr: *const QString = values.as_ptr(); |
1704 | let len: usize = keys.len(); |
1705 | cpp!(unsafe [keys_ptr as "const QString*" , values_ptr as "const QString*" , len as "size_t" ] -> QJsonObject as "QJsonObject" { |
1706 | QJsonObject obj; |
1707 | for (size_t i = 0; i < len; ++i) { |
1708 | obj.insert(keys_ptr[i], values_ptr[i]); |
1709 | } |
1710 | return obj; |
1711 | }) |
1712 | } |
1713 | } |
1714 | impl From<HashMap<String, QJsonValue>> for QJsonObject { |
1715 | fn from(v: HashMap<String, QJsonValue>) -> QJsonObject { |
1716 | let keys: Vec<QString> = v.keys().cloned().map(QString::from).collect(); |
1717 | let values: Vec<QJsonValue> = v.values().cloned().collect(); |
1718 | let keys_ptr: *const QString = keys.as_ptr(); |
1719 | let values_ptr: *const QJsonValue = values.as_ptr(); |
1720 | let len: usize = keys.len(); |
1721 | cpp!(unsafe [keys_ptr as "const QString*" , values_ptr as "const QJsonValue*" , len as "size_t" ] -> QJsonObject as "QJsonObject" { |
1722 | QJsonObject obj; |
1723 | for (size_t i = 0; i < len; ++i) { |
1724 | obj.insert(keys_ptr[i], values_ptr[i]); |
1725 | } |
1726 | return obj; |
1727 | }) |
1728 | } |
1729 | } |
1730 | |
1731 | cpp! {{ #include <QtCore/QDebug> }} |
1732 | |
1733 | #[test ] |
1734 | fn test_qjsonobject() { |
1735 | let mut hashmap = HashMap::new(); |
1736 | hashmap.insert("key" .to_owned(), "value" .to_owned()); |
1737 | hashmap.insert("test" .to_owned(), "hello" .to_owned()); |
1738 | let object = QJsonObject::from(hashmap); |
1739 | assert_eq!(object.to_json().to_string(), "{ \"key \": \"value \", \"test \": \"hello \"}" ); |
1740 | |
1741 | let array = QJsonArray::from(vec![ |
1742 | QJsonValue::from(QString::from("test" )), |
1743 | QJsonValue::from(true), |
1744 | QJsonValue::from(false), |
1745 | QJsonValue::from(1.2345), |
1746 | QJsonValue::from(456.0), |
1747 | ]); |
1748 | |
1749 | let mut valuemap = HashMap::new(); |
1750 | valuemap.insert("1_string" .to_owned(), QJsonValue::from(QString::from("test" ))); |
1751 | valuemap.insert("2_bool" .to_owned(), QJsonValue::from(true)); |
1752 | valuemap.insert("3_f64" .to_owned(), QJsonValue::from(1.2345)); |
1753 | valuemap.insert("4_int" .to_owned(), QJsonValue::from(456.0)); |
1754 | valuemap.insert("5_array" .to_owned(), QJsonValue::from(array)); |
1755 | valuemap.insert("6_object" .to_owned(), QJsonValue::from(object)); |
1756 | let object = QJsonObject::from(valuemap); |
1757 | assert_eq!(object.to_json().to_string(), "{ \"1_string \": \"test \", \"2_bool \":true, \"3_f64 \":1.2345, \"4_int \":456, \"5_array \":[ \"test \",true,false,1.2345,456], \"6_object \":{ \"key \": \"value \", \"test \": \"hello \"}}" ); |
1758 | |
1759 | let at_f64: f64 = object.value("3_f64" ).into(); |
1760 | assert_eq!(at_f64, 1.2345); |
1761 | |
1762 | let at_string = object.value("1_string" ); |
1763 | assert_eq!(<QJsonValue as Into<QString>>::into(at_string).to_string(), "test" ); |
1764 | |
1765 | let mut object = QJsonObject::default(); |
1766 | object.insert("key" , QJsonValue::from(QString::from("value" ))); |
1767 | object.insert("test" , QJsonValue::from(QString::from("hello" ))); |
1768 | assert_eq!(object.to_json().to_string(), "{ \"key \": \"value \", \"test \": \"hello \"}" ); |
1769 | |
1770 | assert_eq!(object.keys(), vec!["key" .to_owned(), "test" .to_owned()]); |
1771 | } |
1772 | |
1773 | #[test ] |
1774 | fn test_qjsonobject_utf8() { |
1775 | let emoji: String = String::from("🦀" ); |
1776 | let expected: String = String::from("{ \"🦀 \":1}" ); |
1777 | |
1778 | let mut qmap: QJsonObject = QJsonObject::default(); |
1779 | qmap.insert(&emoji, value:QVariant::from(1).into()); |
1780 | |
1781 | let actual: QByteArray = qmap.to_json(); |
1782 | let actual: &str = actual.to_str().unwrap(); |
1783 | |
1784 | assert_eq!(actual, expected); |
1785 | } |
1786 | |
1787 | cpp_class!( |
1788 | /// Wrapper around [`QJsonArray`][class] class. |
1789 | /// |
1790 | /// [class]: https://doc.qt.io/qt-5/qjsonarray.html |
1791 | #[derive(Default, PartialEq, Eq, Clone)] |
1792 | pub unsafe struct QJsonArray as "QJsonArray" |
1793 | ); |
1794 | |
1795 | impl QJsonArray { |
1796 | pub fn to_json(&self) -> QByteArray { |
1797 | cpp!(unsafe [self as "QJsonArray*" ] -> QByteArray as "QByteArray" { return QJsonDocument(*self).toJson(QJsonDocument::Compact); }) |
1798 | } |
1799 | pub fn to_json_pretty(&self) -> QByteArray { |
1800 | cpp!(unsafe [self as "QJsonArray*" ] -> QByteArray as "QByteArray" { return QJsonDocument(*self).toJson(QJsonDocument::Indented); }) |
1801 | } |
1802 | pub fn push(&mut self, value: QJsonValue) { |
1803 | cpp!(unsafe [self as "QJsonArray*" , value as "QJsonValue" ] { self->append(std::move(value)); }) |
1804 | } |
1805 | pub fn insert(&mut self, index: usize, element: QJsonValue) { |
1806 | cpp!(unsafe [self as "QJsonArray*" , index as "size_t" , element as "QJsonValue" ] { self->insert(index, std::move(element)); }) |
1807 | } |
1808 | pub fn at(&self, index: usize) -> QJsonValue { |
1809 | cpp!(unsafe [self as "QJsonArray*" , index as "size_t" ] -> QJsonValue as "QJsonValue" { return self->at(index); }) |
1810 | } |
1811 | pub fn take_at(&mut self, index: usize) -> QJsonValue { |
1812 | cpp!(unsafe [self as "QJsonArray*" , index as "size_t" ] -> QJsonValue as "QJsonValue" { return self->takeAt(index); }) |
1813 | } |
1814 | pub fn remove_at(&mut self, index: usize) { |
1815 | cpp!(unsafe [self as "QJsonArray*" , index as "size_t" ] { return self->removeAt(index); }) |
1816 | } |
1817 | pub fn len(&self) -> usize { |
1818 | cpp!(unsafe [self as "QJsonArray*" ] -> usize as "size_t" { return self->size(); }) |
1819 | } |
1820 | pub fn is_empty(&self) -> bool { |
1821 | cpp!(unsafe [self as "QJsonArray*" ] -> bool as "bool" { return self->isEmpty(); }) |
1822 | } |
1823 | } |
1824 | |
1825 | impl From<Vec<QJsonValue>> for QJsonArray { |
1826 | fn from(v: Vec<QJsonValue>) -> QJsonArray { |
1827 | let ptr: *const QJsonValue = v.as_ptr(); |
1828 | let len: usize = v.len(); |
1829 | cpp!(unsafe [ptr as "const QJsonValue*" , len as "size_t" ] -> QJsonArray as "QJsonArray" { |
1830 | QJsonArray arr; |
1831 | for (size_t i = 0; i < len; ++i) { |
1832 | arr.append(ptr[i]); |
1833 | } |
1834 | return arr; |
1835 | }) |
1836 | } |
1837 | } |
1838 | |
1839 | #[test ] |
1840 | fn test_qjsonarray() { |
1841 | let mut array: QJsonArray = QJsonArray::default(); |
1842 | array.push(QJsonValue::from(QString::from("test" ))); |
1843 | array.push(QJsonValue::from(true)); |
1844 | array.push(QJsonValue::from(false)); |
1845 | array.push(QJsonValue::from(1.2345)); |
1846 | assert_eq!(array.to_json().to_string(), "[ \"test \",true,false,1.2345]" ); |
1847 | |
1848 | let mut vec: Vec = Vec::new(); |
1849 | vec.push(QJsonValue::from(QString::from("test" ))); |
1850 | vec.push(QJsonValue::from(true)); |
1851 | vec.push(QJsonValue::from(false)); |
1852 | vec.push(QJsonValue::from(1.2345)); |
1853 | assert!(QJsonArray::from(vec) == array); |
1854 | |
1855 | assert_eq!(array.len(), 4); |
1856 | |
1857 | assert_eq!(<QJsonValue as Into<QString>>::into(array.at(0)).to_string(), "test" ); |
1858 | assert!(array.at(3) == QJsonValue::from(1.2345)); |
1859 | } |
1860 | |