1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
/* Copyright (C) 2018 Olivier Goffart <ogoffart@woboq.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

/*! This crate implements binding to the Qt API which allow to use QML from a rust application.

    # Example:

    ```
    use cstr::cstr;
    use qmetaobject::prelude::*;

    // The `QObject` custom derive macro allows to expose a class to Qt and QML
    #[derive(QObject,Default)]
    struct Greeter {
        // Specify the base class with the qt_base_class macro
        base: qt_base_class!(trait QObject),
        // Declare `name` as a property usable from Qt
        name: qt_property!(QString; NOTIFY name_changed),
        // Declare a signal
        name_changed: qt_signal!(),
        // And even a slot
        compute_greetings: qt_method!(fn compute_greetings(&self, verb: String) -> QString {
            format!("{} {}", verb, self.name.to_string()).into()
        })
    }

    fn main() {
        // Register the `Greeter` struct to QML
        qml_register_type::<Greeter>(cstr!("Greeter"), 1, 0, cstr!("Greeter"));
        // Create a QML engine from rust
        let mut engine = QmlEngine::new();
    # return; // We can't create a window in the CI
        // (Here the QML code is inline, but one can also load from a file)
        engine.load_data(r#"
            import QtQuick 2.6
            import QtQuick.Window 2.0
            // Import our Rust classes
            import Greeter 1.0

            Window {
                visible: true
                // Instantiate the rust struct
                Greeter {
                    id: greeter;
                    // Set a property
                    name: "World"
                }
                Text {
                    anchors.centerIn: parent
                    // Call a method
                    text: greeter.compute_greetings("hello")
                }
            }
        "#.into());
        engine.exec();
    }
    ```

    # Basic types

    The re-exported crate [`qttypes`] contains binding to the most usefull
    basic types such as [`QString`], [`QVariant`], ...

    You can also simply use rust type `String`, but using QString might avoid unecessary
    conversions in some case.

    # Meta type

    In order to be able to use a type in a signal or method parameter, or as a property type,
    the type need to implement the [QMetaType](qmetatype/trait.QMetaType.html) trait.
    All the method are provided so you can just implement the QMetaType like this:

    ```rust
    use qmetaobject::QMetaType;

    #[derive(Default, Clone)]
    struct MyPoint(u32, u32);

    impl QMetaType for MyPoint {};
    ```

    With that it is also possible to put the type in a  [`QVariant`]

    # Object pinning

    Once an object that derives from QObject is exposed to C++, it needs to be pinned, and cannot
    be moved in memory.
    Also, since the Qt code can be re-entrant, the object must be placed in a RefCell.
    The [QObjectPinned](struct.QObjectPinned.html) object is used to enforce the pinning.

    If you want to keep pointer to reference, you can use [QPointer](struct.QPointer.html).

    # Threading

    The QML engine only runs in a single thread. And probably all the `QObject`s needs to be living
    in the Qt thread. But you can use the [queued_callback](fn.queued_callback.html) function to
    create callback that can be called from any thread and are going to run in the Qt thread.

    This can be done like so:

    ```
    use qmetaobject::prelude::*;
    # use std::cell::RefCell;

    #[derive(QObject, Default)]
    struct MyAsyncObject {
        base: qt_base_class!(trait QObject),
        result: qt_property!(QString; NOTIFY result_changed),
        result_changed: qt_signal!(),
        recompute_result: qt_method!(fn recompute_result(&self, name: String) {
            let qptr = QPointer::from(&*self);
            let set_value = qmetaobject::queued_callback(move |val: QString| {
                qptr.as_pinned().map(|this| {
                    this.borrow_mut().result = val;
                    this.borrow().result_changed();
                });
            });
            std::thread::spawn(move || {
                // do stuff asynchronously ...
                let r = QString::from("Hello ".to_owned() + &name);
                set_value(r);
            }).join();
        })
    }
    # let obj = RefCell::new(MyAsyncObject::default());
    # let mut engine = QmlEngine::new();
    # unsafe { qmetaobject::connect(
    #     QObject::cpp_construct(&obj),
    #     obj.borrow().result_changed.to_cpp_representation(&*obj.borrow()),
    #     || engine.quit()
    # ) };
    # obj.borrow().recompute_result("World".into());
    # engine.exec();
    # assert_eq!(obj.borrow().result, QString::from("Hello World"));
    ```
*/

#![recursion_limit = "10240"]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::needless_pass_by_value))] // Too many of that for qt types. (FIXME)
#![cfg_attr(feature = "cargo-clippy", allow(clippy::cognitive_complexity))]

#[doc(hidden)]
pub use qmetaobject_impl::{qrc_internal, SimpleListItem};

#[doc(hidden)]
#[cfg(not(qt_6_0))]
pub use qmetaobject_impl::{QEnum, QGadget, QObject};
#[doc(hidden)]
#[cfg(qt_6_0)]
pub use qmetaobject_impl::{QEnum6 as QEnum, QGadget6 as QGadget, QObject6 as QObject};

// In order to be able to use the lazy_static macro from the QObject custom derive, we re-export
// it under a new name qmetaobject_lazy_static.
#[allow(unused_imports)]
#[doc(hidden)]
pub use lazy_static::lazy_static;
#[doc(hidden)]
#[macro_export]
macro_rules! qmetaobject_lazy_static { ($($t:tt)*) => { $crate::lazy_static!($($t)*) } }

use std::cell::{RefCell, RefMut};
use std::ffi::{CStr, CString};
use std::os::raw::{c_char, c_void};

use cpp::{cpp, cpp_class};

pub use qttypes;

pub use crate::log::*;
pub use connections::RustSignal;
pub use connections::{connect, Signal, SignalInner};
pub use future::*;
pub use itemmodel::*;
pub use listmodel::*;
pub use qmetatype::*;
pub use qtdeclarative::*;
#[cfg(qt_5_7)]
pub use qtquickcontrols2::*;
pub use qttypes::*;
pub use tablemodel::*;

pub mod connections;
pub mod future;
pub mod itemmodel;
pub mod listmodel;
pub mod log;
pub mod qmetatype;
pub mod qrc;
pub mod qtcore;
pub mod qtdeclarative;
#[cfg(qt_5_7)]
pub mod qtquickcontrols2;
pub mod scenegraph;
pub mod tablemodel;
#[cfg(feature = "webengine")]
#[cfg(not(all(qt_6_0, not(qt_6_2))))]
#[cfg(not(all(target_os = "windows", not(target_env = "msvc"))))]
pub mod webengine;

/// Module intended for glob import.
pub mod prelude {
    #[cfg(qt_5_8)]
    pub use crate::qtdeclarative::qml_register_enum;
    #[cfg(qt_5_9)]
    pub use crate::qtdeclarative::qml_register_module;
    pub use crate::{
        qml_register_type, qrc, qt_base_class, qt_method, qt_plugin, qt_property, qt_signal,
        QAbstractListModel, QByteArray, QColor, QDate, QDateTime, QEnum, QModelIndex, QObject,
        QObjectBox, QPointer, QQmlExtensionPlugin, QQuickItem, QQuickView, QRectF, QString, QTime,
        QVariant, QmlEngine,
    };
}

cpp! {{
    #include <qmetaobject_rust.hpp>
}}

#[doc(hidden)]
pub struct QObjectCppWrapper {
    ptr: *mut c_void,
}

impl Drop for QObjectCppWrapper {
    fn drop(&mut self) {
        let ptr = self.ptr;
        cpp!(unsafe [ptr as "QObject *"] {
            // The event 513 is caught by RustObject and deletes the object.
            QEvent e = QEvent(QEvent::Type(QtJambi_EventType_DeleteOnMainThread));
            if (ptr) {
                ptr->event(&e);
            }
        });
    }
}

impl Default for QObjectCppWrapper {
    fn default() -> QObjectCppWrapper {
        QObjectCppWrapper { ptr: std::ptr::null_mut() }
    }
}

impl QObjectCppWrapper {
    pub fn get(&self) -> *mut c_void {
        self.ptr
    }

    pub fn set(&mut self, val: *mut c_void) {
        self.ptr = val;
    }
}

// TODO: Remove before 1.0
#[doc(hidden)]
#[deprecated]
pub type QObjectDescription = QObjectDescriptor;

#[doc(hidden)]
#[repr(C)]
pub struct QObjectDescriptor {
    pub size: usize,
    pub meta_object: *const QMetaObject,
    pub create: unsafe extern "C" fn(
        pinned_object: *const c_void,
        trait_object_ptr: *const c_void,
    ) -> *mut c_void,
    pub qml_construct: unsafe extern "C" fn(
        mem: *mut c_void,
        pinned_object: *const c_void,
        trait_object_ptr: *const c_void,
        extra_destruct: extern "C" fn(*mut c_void),
    ),
    pub get_rust_refcell: unsafe extern "C" fn(*mut c_void) -> *const RefCell<dyn QObject>,
}

/// Trait that is implemented by the QObject custom derive macro
///
/// Do not implement this trait yourself, use `#[derive(QObject)]`.
///
/// The method of this trait fits into two categories: the ones that are re-implemented by
/// the custom derive, and the ones that are used by this macro and need to be implemented
/// by other QObject-like trait which you use in the qt_base_class! macro.
pub trait QObject {
    // Functions re-implemented by the custom derive:

    /// Returns a pointer to a meta object
    fn meta_object(&self) -> *const QMetaObject;

    /// Returns a pointer to a meta object
    fn static_meta_object() -> *const QMetaObject
    where
        Self: Sized;

    /// return a C++ pointer to the QObject*  (can be null if not yet initialized)
    fn get_cpp_object(&self) -> *mut c_void;

    /// Construct the C++ Object.
    ///
    /// Note, once this function is called, the object must not be moved in memory.
    unsafe fn cpp_construct(pined: &RefCell<Self>) -> *mut c_void
    where
        Self: Sized;

    /// Construct the C++ Object, suitable for callbacks to construct QML objects.
    unsafe fn qml_construct(
        pined: &RefCell<Self>,
        mem: *mut c_void,
        extra_destruct: extern "C" fn(*mut c_void),
    ) where
        Self: Sized;

    /// Return the size of the C++ object
    fn cpp_size() -> usize
    where
        Self: Sized;

    /// Return a rust object belonging to a C++ object
    unsafe fn get_from_cpp<'a>(p: *mut c_void) -> QObjectPinned<'a, Self>
    where
        Self: Sized;

    // Part of the trait structure that sub trait must have.
    // Copy/paste this code replacing QObject with the type.

    /// Returns a QObjectDescriptor for this type
    fn get_object_description() -> &'static QObjectDescriptor
    where
        Self: Sized,
    {
        unsafe {
            &*cpp!([]-> *const QObjectDescriptor as "RustQObjectDescriptor const*" {
                return RustQObjectDescriptor::instance<RustObject<QObject>>();
            })
        }
    }
}

impl dyn QObject {
    /// Creates a C++ object and construct a QVariant containing a pointer to it.
    ///
    /// The cpp_construct function must already have been called.
    ///
    /// FIXME: should probably not be used. Prefer using a QmlEngine::new_qobject.
    /// QVariant is unsafe as it does not manage life time
    pub unsafe fn as_qvariant(&self) -> QVariant {
        let self_ = self.get_cpp_object();
        cpp!([self_ as "QObject*"] -> QVariant as "QVariant"  {
            return QVariant::fromValue(self_);
        })
    }

    /// See Qt documentation for QObject::destroyed
    pub fn destroyed_signal() -> Signal<fn()> {
        unsafe {
            Signal::new(cpp!([] -> SignalInner as "SignalInner"  {
                return &QObject::destroyed;
            }))
        }
    }

    /// See Qt documentation for QObject::setObjectName
    // FIXME. take self by special reference?  panic if cpp_object does not exist?
    pub fn set_object_name(&self, name: QString) {
        let self_ = self.get_cpp_object();
        unsafe {
            cpp!([self_ as "QObject*", name as "QString"] {
                if (self_) self_->setObjectName(std::move(name));
            })
        }
    }

    /// See Qt documentation for QObject::objectNameChanged
    pub fn object_name_changed_signal() -> Signal<fn(QString)> {
        unsafe {
            Signal::new(cpp!([] -> SignalInner as "SignalInner"  {
                return &QObject::objectNameChanged;
            }))
        }
    }
}

cpp_class!(unsafe struct QPointerImpl as "QPointer<QObject>");

/// A Wrapper around a QPointer
// (we only need a *const T to support the !Sized case. (Maybe there is a better way)
pub struct QPointer<T: QObject + ?Sized>(QPointerImpl, *const T);
impl<T: QObject + ?Sized> QPointer<T> {
    /// Returns a pointer to the cpp object (null if it was deleted)
    pub fn cpp_ptr(&self) -> *mut c_void {
        let x = &self.0;
        cpp!(unsafe [x as "QPointer<QObject> *"] -> *mut c_void as "QObject *" {
            return x->data();
        })
    }

    /// Returns a reference to the `QObject`, or None if it was deleted
    pub fn as_ref(&self) -> Option<&T> {
        let x = self.cpp_ptr();
        if x.is_null() {
            None
        } else {
            unsafe { Some(&*self.1) }
        }
    }

    /// Returns true if the object was default constructed or constructed with an object which
    /// is now deleted
    pub fn is_null(&self) -> bool {
        self.cpp_ptr().is_null()
    }
}

impl<T: QObject> QPointer<T> {
    /// Returns a pinned reference to the QObject, or None if it was deleted
    pub fn as_pinned(&self) -> Option<QObjectPinned<T>> {
        let x = self.cpp_ptr();
        if x.is_null() {
            None
        } else {
            Some(unsafe { T::get_from_cpp(x) })
        }
    }
}

impl<'a, T: QObject + ?Sized> From<&'a T> for QPointer<T> {
    /// Creates a QPointer from a reference to a QObject.
    /// The corresponding C++ object must have already been created.
    fn from(obj: &'a T) -> Self {
        let cpp_obj = obj.get_cpp_object();
        QPointer(
            cpp!(unsafe [cpp_obj as "QObject *"] -> QPointerImpl  as "QPointer<QObject>" {
                return cpp_obj; // implicit constructor
            }),
            obj as *const T,
        )
    }
}

impl<T: QObject> Default for QPointer<T> {
    fn default() -> Self {
        QPointer(Default::default(), std::ptr::null())
    }
}

impl<T: QObject + ?Sized> Clone for QPointer<T> {
    fn clone(&self) -> Self {
        QPointer(self.0.clone(), self.1)
    }
}

/// Same as std::cell::RefMut, but does not allow to move from
pub struct QObjectRefMut<'b, T: QObject + ?Sized + 'b> {
    old_value: *mut c_void,
    inner: RefMut<'b, T>,
}

impl<'b, T: QObject + ?Sized> std::ops::Deref for QObjectRefMut<'b, T> {
    type Target = RefMut<'b, T>;

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.inner
    }
}

impl<'b, T: QObject + ?Sized> std::ops::DerefMut for QObjectRefMut<'b, T> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.inner
    }
}

impl<'b, T: QObject + ?Sized + 'b> Drop for QObjectRefMut<'b, T> {
    #[inline]
    fn drop(&mut self) {
        assert_eq!(
            self.old_value,
            self.get_cpp_object(),
            "Internal pointer changed while borrowed"
        );
    }
}

/// A reference to a RefCell<T>, where T is a QObject, which does not move in memory
#[repr(transparent)]
pub struct QObjectPinned<'pin, T: QObject + ?Sized + 'pin>(&'pin RefCell<T>);

impl<'pin, T: QObject + ?Sized + 'pin> Clone for QObjectPinned<'pin, T> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'pin, T: QObject + ?Sized + 'pin> Copy for QObjectPinned<'pin, T> {}

impl<'pin, T: QObject + ?Sized + 'pin> QObjectPinned<'pin, T> {
    /// Borrow the object
    // FIXME: there are too many cases for which we want reentrance after borrowing
    //pub fn borrow(&self) -> std::cell::Ref<T> { self.0.borrow() }
    #[cfg_attr(feature = "cargo-clippy", allow(clippy::should_implement_trait))]
    pub fn borrow(&self) -> &T {
        unsafe { &*self.0.as_ptr() }
    }
    pub fn borrow_mut(&self) -> QObjectRefMut<T> {
        let x = self.0.borrow_mut();
        QObjectRefMut { old_value: x.get_cpp_object(), inner: x }
    }
    pub fn as_ptr(&self) -> *mut T {
        self.0.as_ptr()
    }
}

impl<'pin, T: QObject + ?Sized + 'pin> QObjectPinned<'pin, T> {
    /// Internal function used from the code generated by the QObject derive macro.
    /// Unsafe because one must ensure it does not move in memory.
    pub unsafe fn new(inner: &'pin RefCell<T>) -> Self {
        QObjectPinned(inner)
    }
}

impl<'pin, T: QObject + 'pin> QObjectPinned<'pin, T> {
    /// Get the pointer ot the C++ Object, or crate it if it was not yet created
    pub fn get_or_create_cpp_object(self) -> *mut c_void {
        let r = unsafe { &*self.0.as_ptr() }.get_cpp_object();
        if r.is_null() {
            unsafe { QObject::cpp_construct(self.0) }
        } else {
            r
        }
    }
}

impl<'pin, T: QObject + 'pin> From<QObjectPinned<'pin, T>> for QVariant {
    fn from(obj: QObjectPinned<'pin, T>) -> Self {
        let x = obj.get_or_create_cpp_object();
        cpp!(unsafe [x as "QObject *"] -> QVariant as "QVariant" {
            return QVariant::fromValue(x);
        })
    }
}

/// A wrapper around RefCell<T>, whose content cannot be move in memory
pub struct QObjectBox<T: QObject + ?Sized>(Box<RefCell<T>>);

impl<T: QObject> QObjectBox<T> {
    pub fn new(obj: T) -> Self {
        QObjectBox(Box::new(RefCell::new(obj)))
    }
}

impl<T: QObject + Default> Default for QObjectBox<T> {
    fn default() -> Self {
        Self::new(Default::default())
    }
}

impl<T: QObject + ?Sized> QObjectBox<T> {
    pub fn pinned(&self) -> QObjectPinned<T> {
        unsafe { QObjectPinned::new(&self.0) }
    }
}

/// Create the C++ object and return a C++ pointer to a QObject.
///
/// The ownership is given to CPP, the resulting QObject* ptr need to be used somewhere
/// that takes ownership
///
/// Panics if the C++ object was already created.
pub fn into_leaked_cpp_ptr<T: QObject>(obj: T) -> *mut c_void {
    let b = Box::new(RefCell::new(obj));
    let obj_ptr = unsafe { QObject::cpp_construct(&b) };
    Box::into_raw(b);
    obj_ptr
}

/// Trait that is implemented by the QGadget custom derive macro
///
/// Do not implement this trait yourself, use `#[derive(QGadget)]`.
pub trait QGadget {
    /// Returns a pointer to a meta object
    fn meta_object(&self) -> *const QMetaObject;

    /// Returns a pointer to a meta object
    fn static_meta_object() -> *const QMetaObject
    where
        Self: Sized;
}

/// Trait that is implemented by the QEnum custom derive macro
///
/// Do not implement this trait yourself, use `#[derive(QEnum)]`.
pub trait QEnum {
    /// Returns a pointer to a meta object
    fn static_meta_object() -> *const QMetaObject
    where
        Self: Sized;
}

#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn RustObject_metaObject(p: *mut RefCell<dyn QObject>) -> *const QMetaObject {
    (*(*p).as_ptr()).meta_object()
}

#[doc(hidden)]
#[no_mangle]
pub unsafe extern "C" fn RustObject_destruct(p: *mut RefCell<dyn QObject>) {
    // We are destroyed from the C++ code, which means that the object was owned by C++ and we
    // can destroy the rust object as well
    let _b = Box::from_raw(p);
}

/// This function is called from the implementation of the signal.
#[doc(hidden)]
pub unsafe fn invoke_signal(
    object: *mut c_void,
    meta: *const QMetaObject,
    id: u32,
    a: &[*mut c_void],
) {
    let a = a.as_ptr();
    cpp!([
        object as "QObject *",
        meta as "const QMetaObject *",
        id as "int",
        a as "void **"
    ] {
        if (!object) {
            return;
        }
        QMetaObject::activate(object, meta, id, a);
    })
}

/// Wrapper for `QMetaObject`'s private data's `StaticMetacallFunction` typedef.
type StaticMetacallFunction = Option<
    extern "C" fn(
        o: *mut c_void, // FIXME: should be QObject or something
        c: u32,
        idx: u32,
        a: *const *mut c_void,
    ),
>;

/// Same as a C++ QMetaObject.
#[doc(hidden)]
#[repr(C)]
pub struct QMetaObject {
    // fields are slightly renamed from Qt to match Rust code style
    pub super_data: *const QMetaObject,
    #[cfg(all(qt_6_0, target_os = "windows"))] // QT_NO_DATA_RELOCATION
    pub super_data_getter: Option<extern "C" fn() -> *const QMetaObject>,
    pub string_data: *const u8,
    pub data: *const u32,
    pub static_metacall: StaticMetacallFunction,
    pub related_meta_objects: *const c_void,
    pub meta_types: *const c_void,
    pub extra_data: *const c_void,
}

unsafe impl Sync for QMetaObject {}
unsafe impl Send for QMetaObject {}

/// This macro must be used once as a type in a struct that derives from QObject.
/// It is anotate from which QObject like trait it is supposed to derive.
/// the field which it annotate will be an internal property holding a pointer
/// to the actual C++ object
///
/// The trait needs to be like the QObject trait, see the documentation of the QObject trait.
///
/// ```
/// use qmetaobject::*;
///
/// #[derive(QObject)]
/// struct Foo {
///    base : qt_base_class!(trait QObject),
/// }
/// ```
///
/// Note: in the future, the plan is to extent so you could derive from other struct by doing
/// `base : qt_base_class(struct Foo)`. But this is not yet implemented
#[macro_export]
macro_rules! qt_base_class {
    ($($t:tt)*) => {
        $crate::QObjectCppWrapper
    };
}

/// This macro can be used as a type of a field and can then turn this field in a Qt property.
/// The first parameter is the type of this property. Then we can have the meta keywords similar
/// to these found in Q_PROPERTY.
///
/// Can be used within a struct that derives from QObject or QGadget
///
/// `NOTIFY` followed by the name of a signal that need to be declared separately.
/// `WRITE` followed by the name of a setter. `READ` follow by the name of a getter. Note that
/// these are not mandatory and if no setter or no getter exist, it will set the field.
/// `CONST` is also supported.
///
/// `ALIAS` followed by an identifier allow to give a different name than the actual field name.
///
/// ```
/// use qmetaobject::*;
///
/// #[derive(QObject)]
/// struct Foo {
///    base: qt_base_class!(trait QObject),
///    foo: qt_property!(u32; NOTIFY foo_changed WRITE set_foo),
///    foo_changed: qt_signal!(),
/// }
///
/// impl Foo {
///    fn set_foo(&mut self, val: u32) { self.foo = val; }
/// }
/// ```
#[macro_export]
macro_rules! qt_property {
    ($t:ty $(; $($rest:tt)*)*) => {
        $t
    };
}

/// This macro can be used to declare a method which will become a meta method.
///
/// Inside you can either declare the method signature, or write the full method.
///
/// Can be used within a struct that derives from QObject or QGadget
///
/// ```
/// use qmetaobject::*;
///
/// #[derive(QObject)]
/// struct Foo {
///    base: qt_base_class!(trait QObject),
///    defined_method: qt_method!(fn defined_method(&self, foo: u32) -> u32 {
///       println!("contents goes here.");
///       return 42;
///    }),
///    out_of_line_method: qt_method!(fn(&self, foo: u32)-> u32),
/// }
///
/// impl Foo {
///    fn out_of_line_method(&mut self, foo: u32) -> u32 {
///       println!("Or here.");
///       return 69;
///    }
/// }
/// ```
#[macro_export]
macro_rules! qt_method {
    ($($t:tt)*) => { ::std::marker::PhantomData<()> };
}

/// Declares a signal
///
/// Inside you can either declare the method signature, or write the full method.
///
/// To be used within a struct that derives from QObject
///
/// ```
/// use qmetaobject::*;
///
/// #[derive(QObject)]
/// struct Foo {
///    base: qt_base_class!(trait QObject),
///    my_signal: qt_signal!(xx: u32, yy: String),
/// }
///
/// fn some_code(foo: &mut Foo) {
///    foo.my_signal(42, "42".into()); // emits the signal
/// }
/// ```
#[macro_export]
macro_rules! qt_signal {
    ($( $name:ident : $ty:ty ),*) => { $crate::RustSignal<fn( $( $ty ),* )> };
}

/// Equivalent to the Q_PLUGIN_METADATA macro.
///
/// To be used within a struct that derives from QObject, and it should contain a string which is
/// the IID
///
/// ```
/// use qmetaobject::*;
/// # use std::ffi::CStr;
///
/// #[derive(Default, QObject)]
/// struct MyPlugin {
///     base: qt_base_class!(trait QQmlExtensionPlugin),
///     plugin: qt_plugin!("org.qt-project.Qt.QQmlExtensionInterface/1.0")
/// }
/// # impl QQmlExtensionPlugin for MyPlugin {
/// #     fn register_types(&mut self, uri: &CStr) {}
/// # }
/// ```
#[macro_export]
macro_rules! qt_plugin {
    ($($t:tt)*) => { std::marker::PhantomData<()> };
}

cpp! {{
    struct FnBoxWrapper {
        /// Wrapped Box<dyn FnMut()>
        TraitObject fnbox;

        ~FnBoxWrapper() {
            if (fnbox.isValid()) {
                rust!(FnBoxWrapper_destructor [fnbox: *mut dyn FnMut() as "TraitObject"] {
                    unsafe { let _ = Box::from_raw(fnbox); }
                });
            }
        }

        /// Copying is not allowed.
        FnBoxWrapper &operator=(const FnBoxWrapper&) = delete;
#if false && QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
        FnBoxWrapper(const FnBoxWrapper&) = delete;
#else
        // Prior to Qt 5.10 we can't have move-only wrapper. Just do the auto_ptr kind of hack.
        FnBoxWrapper(const FnBoxWrapper &o) : fnbox(o.fnbox) {
            const_cast<FnBoxWrapper &>(o).fnbox = {};
        }
#endif

        /// Moving is allowed, since `Box<FnMut()>` itself is not pinned.
        FnBoxWrapper(FnBoxWrapper &&o) : fnbox(o.fnbox) {
            o.fnbox = {};
        }
        FnBoxWrapper &operator=(FnBoxWrapper &&o) {
            std::swap(o.fnbox, fnbox);
            return *this;
        }

        /// Call boxed function in rust.
        void operator()() {
            rust!(FnBoxWrapper_operator [fnbox : *mut dyn FnMut() as "TraitObject"] {
                unsafe { (*fnbox)(); }
            });
        }
    };

    template<typename T>
    static void invokeMethod(QObject *reciever, T &&func) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
        QMetaObject::invokeMethod(reciever, std::forward<T>(func), Qt::QueuedConnection); // does not allow move-only
#else
        // We can't use QTimer::singleShot because "Timers can only be used with threads started with QThread"
        QObject o;
        QObject::connect(&o, &QObject::destroyed, reciever, std::forward<T>(func), Qt::QueuedConnection);
#endif
    }
}}

/// Call the callback once, after a given duration.
pub fn single_shot<F>(interval: std::time::Duration, func: F)
where
    F: FnMut() + 'static,
{
    let func_box: Box<dyn FnMut()> = Box::new(func);
    let mut func_raw = Box::into_raw(func_box);

    let interval_ms: u32 = interval.as_secs() as u32 * 1000 + interval.subsec_nanos() * 1e-6 as u32;

    cpp!(unsafe [interval_ms as "int", mut func_raw as "FnBoxWrapper"] {
        QTimer::singleShot(interval_ms, std::move(func_raw));
    });
}

/// Create a callback to invoke a queued callback in the current thread.
///
/// Returns a callback that can be called in any thread. Calling the callback will then call the
/// given closure in the current Qt thread.
///
/// If the current thread does no longer have an event loop when the callback is sent, the
/// callback will not be recieved.
///
/// ```
/// use qmetaobject::queued_callback;
///
/// let callback = queued_callback(|()| println!("hello from main thread"));
/// std::thread::spawn(move || {callback(());}).join();
/// ```
pub fn queued_callback<T: Send, F: FnMut(T) + 'static>(
    func: F,
) -> impl Fn(T) + Send + Sync + Clone {
    let current_thread = cpp!(unsafe [] -> QPointerImpl as "QPointer<QThread>" {
        return QThread::currentThread();
    });

    // In this case, it is safe to send the function to another thread, as we will only call it
    // from this thread.
    // We put it in a RefCell so we can call it mutably.
    struct UnsafeSendFn<T>(RefCell<T>);
    unsafe impl<T> Send for UnsafeSendFn<T> {}
    unsafe impl<T> Sync for UnsafeSendFn<T> {}
    // put func in an arc because we need to keep it alive as long as the internal Box<FnMut> is
    // alive. (And we can't just move it there because the returned closure can be called several
    // times.
    let func = std::sync::Arc::new(UnsafeSendFn(RefCell::new(func)));

    move |x| {
        let mut x = Some(x); // Workaround the fact we can't have a Box<FnOnce>
        let func = func.clone();
        let func: Box<dyn FnMut()> = Box::new(move || {
            // the borrow_mut could panic if the function was called recursively. This could happen
            // if the event-loop re-enter.
            let f = &mut (*(func.0).borrow_mut());
            if let Some(x) = x.take() {
                f(x);
            };
        });
        // C++ destructor `~FnBoxWrapper` takes care of the memory.
        let mut func_raw = Box::into_raw(func);
        cpp!(unsafe [mut func_raw as "FnBoxWrapper", current_thread as "QPointer<QThread>"] {
            if (!current_thread) {
                return;
            }
            if (!qApp || current_thread != qApp->thread()) {
                QObject *reciever = new QObject();
                reciever->moveToThread(current_thread);
                invokeMethod(reciever, std::move(func_raw));
                reciever->deleteLater();
            } else {
                invokeMethod(qApp, std::move(func_raw));
            }
        });
    }
}

/* Small helper function for Rust_QAbstractItemModel::roleNames */
fn add_to_hash(hash: *mut c_void, key: i32, value: QByteArray) {
    cpp!(unsafe [
        hash as "QHash<int, QByteArray> *",
        key as "int",
        value as "QByteArray"
    ] {
        (*hash)[key] = std::move(value);
    });
}

/// Refer to the documentation of Qt::UserRole
pub const USER_ROLE: i32 = 0x0100;

/// Embed files and made them available to the Qt resource system.
///
/// The macro accepts an identifier with optional preceding visibility modifier,
/// and a comma-separated list of resources. Then macro generates a function
/// with given name and visibility, which can be used to register all the
/// resources.
///
/// # Input
///
/// The macro accepts the following formal grammar in pseudo [rust macro syntax][macro-doc]:
///
/// ```txt
/// macro call ::= qrc!( $f:Function $( $r:Recource ),* )
/// Function   ::= $v:vis $name:ident
/// Resource   ::= $( $base_dir:physical as )? $prefix:virtual { $( $f:File ),* }
/// File       ::= $path:physical $( as $alias:virtual )?
///
/// physical   ::= $path:literal
/// virtual    ::= $path:literal
/// ```
///
/// _Function_ is the name for the generated function, optionally preceded by
/// the visibility modifier (`pub(crate)` etc.)
///
/// _Physical_ path literal represents path on a local file system;
/// _virtual_ path represents virtual path in the generated qrc
/// resource tree accessible at `qrc:///virtual/path` URI.
///
/// **Note** that for _Resource_ physical part is optional,
/// meanwhile _File_ has optional _Virtual_ part.
///
/// _Resources_ and _Files_ are comma-separated lists.
///
/// _Resources_ consist of a
///  - `$base_dir:physical`: optional path to base directory on local file
///    system, separated from the prefix by the `as` keyword.
///    By default, base directory is the cargo project's root - directory with
///    _Cargo.toml_, a.k.a. [`$CARGO_MANIFEST_DIR`][].
///    (Custom extention which does not interfere with qrc format,
///    but merely resolves physical path of files in this resource relative
///    to the base directory, and helps keeping both project's root directory
///    and resource definitions clean and short.)
///  - `$prefix:virtual`: prefix directory path in qrc's virtual file system.
///    It will be prepended to every file's virtual path.
///    (Corresponds to qrc format.)
///  - A curly-braced list of comma-separated _Files_.
///
/// _Files_ are specified as
///  - `$path:physical`: path to the file on local file system.
///    Relative to the resource's base directory.
///    (Corresponds to qrc format, with the exception below.)
///  - `$alias:virtual`: an optional alias in qrc's virtual file system,
///    separated from the physical path by the `as` keyword.
///    By default, virtual path of a file is the same as its phisycal path.
///    (Corresponds to qrc format).
///  - **Note** about physical path: _resource_'s base directory is prepended to
///    the file's physical path before looking for the file on the local file
///    system, but after the physical path is cloned to the virtual counterpart
///    (if the later one was omitted, i.e. no explicit alias was given).
///
/// It does not matter if the prefix has leading '/' or not.
///
/// # Output
///
/// The macro creates a function with given name and visibility modifier,
/// that needs to be run in order to register the resource. Function is
/// idempotent, i.e. calling it more than once is allowed but has no effect.
///
/// # Example
///
/// Consider this project files structure:
///
/// ```text
/// .
/// ├── Cargo.toml
/// ├── tests/qml
/// │   ├── qml.qrc
/// │   ├── main.qml
/// │   └── Bar.qml
/// └── src
///     └── main.rs
/// ```
///
/// then the following Rust code:
///
/// ```
/// use qmetaobject::qrc;
/// # // For maintainers: this is actually tested against real files.
/// // private fn, base directory shortcut
/// qrc!(my_resource_1,
///     "tests/qml" as "foo1" {
///         "main.qml",
///         "Bar.qml" as "baz/Foo.qml",
///      }
/// );
///
/// # // this is a test of visibility modifier
/// # mod private {
/// # use super::*;
/// // public fn, no shortcuts
/// qrc!(pub my_resource_2,
///     "foo2" {
///         // either use file alias or re-organize files
///         "tests/qml/main.qml" as "main.qml",
///         "tests/qml/Bar.qml" as "baz/Foo.qml",
///      }
/// );
/// # }
///
/// # fn use_resource(_r: &str) {
/// #     // at the time of writing, it is the only way to test the existence of a resource.
/// #     use qmetaobject::*;
/// #
/// #     let mut engine = QmlEngine::new();
/// #     let mut c = QmlComponent::new(&engine);
/// #     c.load_url(QUrl::from(QString::from("qrc:/foo2/baz/Foo.qml")), CompilationMode::PreferSynchronous);
/// #     assert_eq!(ComponentStatus::Ready, c.status());
/// #     engine.quit();
/// # }
/// # fn main() {
/// // registers the resource to Qt
/// my_resource_1();
/// # private::
/// my_resource_2();
/// // do something with resources
/// use_resource("qrc:/foo1/baz/Foo.qml");
/// use_resource("qrc:/foo2/baz/Foo.qml");
/// # }
/// ```
///
/// corresponds to the .qrc (`tests/qml/qml.qrc`) file:
///
/// ```xml
/// <RCC>
///     <qresource prefix="/foo">
///         <file>main.qml</file>
///         <file alias="baz/Foo.qml">Bar.qml</file>
///     </qresource>
/// </RCC>
/// ```
///
/// [macro-doc]: https://doc.rust-lang.org/reference/macros-by-example.html#metavariables
/// [`$CARGO_MANIFEST_DIR`]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
pub use qmetaobject_impl::qrc_internal as qrc;
// XXX: The line above re-exports the macro with proper documentation and doctests.