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
//! Static text label widget.
//!
//! Wraps [`QLabel`](https://doc.qt.io/qt-6/qlabel.html) for displaying
//! read-only text in a window.
use cxx::let_cxx_string;
use crate::ffi;
use crate::widget::AsWidget;
/// A static text label.
///
/// `Label` uses a **builder pattern**: call [`Label::new`] to obtain a
/// [`Builder`], set the parent, then call `.build()`.
///
/// # Example
///
/// ```no_run
/// use qtrs::Label;
///
/// let label = Label::new("Hello, world!").build();
/// ```
pub struct Label {
ptr: *mut ffi::QLabel,
has_parent: bool,
#[allow(dead_code)]
text: String,
}
impl Label {
/// Start building a new `QLabel`.
///
/// Returns a [`Builder`]. Set an optional parent, then call `.build()`.
pub fn new(text: impl Into<String>) -> Builder {
Builder::new(text.into())
}
/// Get the current label text.
///
/// Returns the cached copy — this is updated automatically when you
/// call [`set_text`](Self::set_text).
pub fn text(&self) -> &str {
&self.text
}
/// Update the label text at runtime.
///
/// This calls
/// [`QLabel::setText`](https://doc.qt.io/qt-6/qlabel.html#text-prop).
pub fn set_text(&mut self, text: impl Into<String>) {
debug_assert!(!self.ptr.is_null(), "Label::set_text on null pointer");
self.text = text.into();
let_cxx_string!(c_text = &self.text);
unsafe {
ffi::QLabel_setText(self.ptr, &c_text);
}
}
#[doc(hidden)]
pub(crate) fn from_raw(ptr: *mut ffi::QLabel, text: &str) -> Self {
debug_assert!(!ptr.is_null());
Self { ptr, has_parent: true, text: text.to_string() }
}
}
impl AsWidget for Label {
fn widget_ptr(&self) -> *mut ffi::QWidget {
debug_assert!(!self.ptr.is_null(), "Label::widget_ptr on null pointer");
unsafe { ffi::toQWidget_QLabel(self.ptr) }
}
fn set_has_parent(&mut self) {
self.has_parent = true;
}
}
impl Drop for Label {
fn drop(&mut self) {
if self.ptr.is_null() {
return;
}
if !self.has_parent {
unsafe { ffi::QLabel_delete(self.ptr) };
}
self.ptr = std::ptr::null_mut();
}
}
// ============================================================
// Builder
// ============================================================
/// Builder for [`Label`].
pub struct Builder {
text: String,
parent: Option<*mut ffi::QWidget>,
}
impl Builder {
fn new(text: String) -> Self {
Self {
text,
parent: None,
}
}
/// Set the parent widget.
///
/// The parent manages the label's C++ lifetime.
pub fn parent(mut self, parent: &dyn AsWidget) -> Self {
self.parent = Some(parent.widget_ptr());
self
}
/// Create the C++ `QLabel` and return the Rust wrapper.
pub fn build(self) -> Label {
let_cxx_string!(c_text = &self.text);
let ptr = unsafe {
ffi::QLabel_new(
&c_text,
self.parent.unwrap_or(std::ptr::null_mut()),
)
};
debug_assert!(!ptr.is_null(), "QLabel_new returned null");
Label {
ptr,
has_parent: self.parent.is_some(),
text: self.text,
}
}
}