Skip to main content

qtrs/
progressbar.rs

1//! Progress bar widget.
2//!
3//! Wraps [`QProgressBar`](https://doc.qt.io/qt-6/qprogressbar.html).
4
5use cxx::let_cxx_string;
6
7use crate::ffi;
8use crate::widget::AsWidget;
9
10/// A progress bar.
11///
12/// `ProgressBar` uses a builder pattern: call [`ProgressBar::new`] to obtain
13/// a [`Builder`], chain configuration methods, then call `.build()`.
14///
15/// # Example
16///
17/// ```no_run
18/// use qtrs::ProgressBar;
19///
20/// let bar = ProgressBar::new()
21///     .range(0, 100)
22///     .format("%p%")
23///     .build();
24///
25/// bar.set_value(50); // 50%
26/// ```
27pub struct ProgressBar {
28    ptr: *mut ffi::QProgressBar,
29    has_parent: bool,
30}
31
32impl ProgressBar {
33    /// Start building a new progress bar.
34    pub fn new() -> Builder {
35        Builder::new()
36    }
37
38    /// Set the current value.
39    pub fn set_value(&self, value: i32) {
40        debug_assert!(!self.ptr.is_null());
41        unsafe { ffi::QProgressBar_setValue(self.ptr, value); }
42    }
43
44    /// Get the current value.
45    pub fn value(&self) -> i32 {
46        debug_assert!(!self.ptr.is_null());
47        unsafe { ffi::QProgressBar_value(self.ptr) }
48    }
49
50    /// Set the range (minimum and maximum).
51    pub fn set_range(&self, min: i32, max: i32) {
52        debug_assert!(!self.ptr.is_null());
53        unsafe { ffi::QProgressBar_setRange(self.ptr, min, max); }
54    }
55
56    /// Set the minimum value.
57    pub fn set_minimum(&self, min: i32) {
58        debug_assert!(!self.ptr.is_null());
59        unsafe { ffi::QProgressBar_setMinimum(self.ptr, min); }
60    }
61
62    /// Set the maximum value.
63    pub fn set_maximum(&self, max: i32) {
64        debug_assert!(!self.ptr.is_null());
65        unsafe { ffi::QProgressBar_setMaximum(self.ptr, max); }
66    }
67
68    /// Set the display format.
69    ///
70    /// - `"%p%"` — percentage (default)
71    /// - `"%v"` — current value
72    /// - `"%m"` — maximum value
73    /// - `"%v/%m"` — value/maximum
74    pub fn set_format(&self, format: &str) {
75        debug_assert!(!self.ptr.is_null());
76        let_cxx_string!(c_format = format);
77        unsafe { ffi::QProgressBar_setFormat(self.ptr, &c_format); }
78    }
79
80    #[doc(hidden)]
81    pub(crate) fn from_raw(ptr: *mut ffi::QProgressBar) -> Self {
82        debug_assert!(!ptr.is_null());
83        Self {
84            ptr,
85            has_parent: true,
86        }
87    }
88}
89
90impl AsWidget for ProgressBar {
91    fn widget_ptr(&self) -> *mut ffi::QWidget {
92        debug_assert!(!self.ptr.is_null());
93        unsafe { ffi::toQWidget_QProgressBar(self.ptr) }
94    }
95
96    fn set_has_parent(&mut self) {
97        self.has_parent = true;
98    }
99}
100
101impl Drop for ProgressBar {
102    fn drop(&mut self) {
103        if self.ptr.is_null() {
104            return;
105        }
106        if !self.has_parent {
107            unsafe { ffi::QProgressBar_delete(self.ptr) };
108        }
109        self.ptr = std::ptr::null_mut();
110    }
111}
112
113// ============================================================
114// Builder
115// ============================================================
116
117/// Builder for [`ProgressBar`].
118pub struct Builder {
119    min: i32,
120    max: i32,
121    value: i32,
122    format: Option<String>,
123    parent: Option<*mut ffi::QWidget>,
124}
125
126impl Builder {
127    fn new() -> Self {
128        Self {
129            min: 0,
130            max: 100,
131            value: 0,
132            format: None,
133            parent: None,
134        }
135    }
136
137    /// Set the range.
138    pub fn range(mut self, min: i32, max: i32) -> Self {
139        self.min = min;
140        self.max = max;
141        self
142    }
143
144    /// Set the initial value.
145    pub fn value(mut self, value: i32) -> Self {
146        self.value = value;
147        self
148    }
149
150    /// Set the display format.
151    pub fn format(mut self, format: impl Into<String>) -> Self {
152        self.format = Some(format.into());
153        self
154    }
155
156    /// Set the parent widget.
157    pub fn parent(mut self, parent: &dyn AsWidget) -> Self {
158        self.parent = Some(parent.widget_ptr());
159        self
160    }
161
162    /// Create the C++ `QProgressBar` and return the Rust wrapper.
163    pub fn build(self) -> ProgressBar {
164        let ptr = unsafe {
165            ffi::QProgressBar_new(self.parent.unwrap_or(std::ptr::null_mut()))
166        };
167        debug_assert!(!ptr.is_null(), "QProgressBar_new returned null");
168
169        let bar = ProgressBar {
170            ptr,
171            has_parent: self.parent.is_some(),
172        };
173
174        unsafe {
175            ffi::QProgressBar_setRange(ptr, self.min, self.max);
176            ffi::QProgressBar_setValue(ptr, self.value);
177            if let Some(ref fmt) = self.format {
178                let_cxx_string!(c_fmt = fmt);
179                ffi::QProgressBar_setFormat(ptr, &c_fmt);
180            }
181        }
182
183        bar
184    }
185}