qt_core/
impl_q_object.rs

1use crate::{QObject, QPtr, QString};
2use cpp_core::{DynamicCast, StaticUpcast};
3use std::error::Error;
4use std::fmt;
5
6/// An error returned by `QObject::find_child`.
7pub struct FindChildError(FindChildErrorInner);
8
9enum FindChildErrorInner {
10    NotFound {
11        name: String,
12    },
13    TypeMismatch {
14        name: String,
15        target_type: &'static str,
16    },
17}
18
19impl fmt::Display for FindChildError {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        match &self.0 {
22            FindChildErrorInner::NotFound { name } => write!(f, "child \"{}\" not found", name),
23            FindChildErrorInner::TypeMismatch { name, target_type } => write!(
24                f,
25                "child \"{}\" cannot be converted to type {}",
26                name, target_type
27            ),
28        }
29    }
30}
31
32impl fmt::Debug for FindChildError {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        write!(f, "{}", self)
35    }
36}
37
38impl Error for FindChildError {}
39
40impl QObject {
41    /// Finds a child of `self` with the specified object name
42    /// and casts it to type `T`.
43    ///
44    /// The search is performed recursively. If there is more than one child matching the search,
45    /// the most direct ancestor is returned. If there are several direct ancestors,
46    /// it is undefined which one will be returned.
47    ///
48    /// Returns an error if there is no child object with object name `name` or
49    /// the found object cannot be cast to `T`.
50    pub unsafe fn find_child<T>(&self, name: &str) -> Result<QPtr<T>, FindChildError>
51    where
52        QObject: DynamicCast<T>,
53        T: StaticUpcast<QObject>,
54    {
55        let ptr = self.find_child_q_object_1a(&QString::from_std_str(name));
56        if ptr.is_null() {
57            return Err(FindChildError(FindChildErrorInner::NotFound {
58                name: name.into(),
59            }));
60        }
61
62        let ptr = ptr.dynamic_cast();
63        if ptr.is_null() {
64            return Err(FindChildError(FindChildErrorInner::TypeMismatch {
65                name: name.into(),
66                target_type: std::any::type_name::<T>(),
67            }));
68        }
69        Ok(ptr)
70    }
71}