i_slint_backend_qt/qt_widgets/
progress_indicator.rs1use i_slint_core::input::FocusEventResult;
5
6use super::*;
7
8#[repr(C)]
9#[derive(FieldOffsets, Default, SlintElement)]
10#[pin]
11pub struct NativeProgressIndicator {
12 pub indeterminate: Property<bool>,
13 pub progress: Property<f32>,
14 widget_ptr: std::cell::Cell<SlintTypeErasedWidgetPtr>,
15 animation_tracker: Property<i32>,
16 pub cached_rendering_data: CachedRenderingData,
17}
18
19impl Item for NativeProgressIndicator {
20 fn init(self: Pin<&Self>, _self_rc: &ItemRc) {
21 let animation_tracker_property_ptr = Self::FIELD_OFFSETS.animation_tracker.apply_pin(self);
22 self.widget_ptr.set(
23 cpp! { unsafe [animation_tracker_property_ptr as "void*"] -> SlintTypeErasedWidgetPtr as "std::unique_ptr<SlintTypeErasedWidget>" {
24 return make_unique_animated_widget<QProgressBar>(animation_tracker_property_ptr);
25 }},
26 )
27 }
28
29 fn layout_info(
30 self: Pin<&Self>,
31 orientation: Orientation,
32 _window_adapter: &Rc<dyn WindowAdapter>,
33 _self_rc: &ItemRc,
34 ) -> LayoutInfo {
35 let indeterminate = self.indeterminate();
36 let progress =
37 if indeterminate { 0 } else { (self.progress().max(0.0).min(1.0) * 100.) as i32 };
38 let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);
39
40 let size = cpp!(unsafe [
41 progress as "int",
42 widget as "QWidget*"
43 ] -> qttypes::QSize as "QSize" {
44 ensure_initialized();
45 QStyleOptionProgressBar option;
46 option.maximum = 100;
47 option.minimum = 0;
48 option.progress = progress;
49 option.textVisible = false;
50 option.state |= QStyle::State_Horizontal;
51
52 int chunkWidth = qApp->style()->pixelMetric(QStyle::PM_ProgressBarChunkWidth, &option, widget);
53 auto size = QSize(chunkWidth * 10, option.fontMetrics.height() + 10);
54 return qApp->style()->sizeFromContents(QStyle::CT_ProgressBar, &option, size, widget);
55 });
56
57 match orientation {
58 Orientation::Horizontal => LayoutInfo {
59 min: size.width as f32,
60 preferred: size.width as f32,
61 stretch: 1.,
62 ..LayoutInfo::default()
63 },
64 Orientation::Vertical => LayoutInfo {
65 min: size.height as f32,
66 preferred: size.height as f32,
67 max: size.height as f32,
68 ..LayoutInfo::default()
69 },
70 }
71 }
72
73 fn input_event_filter_before_children(
74 self: Pin<&Self>,
75 _: &MouseEvent,
76 _window_adapter: &Rc<dyn WindowAdapter>,
77 _self_rc: &ItemRc,
78 ) -> InputEventFilterResult {
79 InputEventFilterResult::ForwardEvent
80 }
81
82 fn input_event(
83 self: Pin<&Self>,
84 _: &MouseEvent,
85 _window_adapter: &Rc<dyn WindowAdapter>,
86 _self_rc: &i_slint_core::items::ItemRc,
87 ) -> InputEventResult {
88 InputEventResult::EventIgnored
89 }
90
91 fn capture_key_event(
92 self: Pin<&Self>,
93 _event: &KeyEvent,
94 _window_adapter: &Rc<dyn WindowAdapter>,
95 _self_rc: &ItemRc,
96 ) -> KeyEventResult {
97 KeyEventResult::EventIgnored
98 }
99
100 fn key_event(
101 self: Pin<&Self>,
102 _: &KeyEvent,
103 _window_adapter: &Rc<dyn WindowAdapter>,
104 _self_rc: &ItemRc,
105 ) -> KeyEventResult {
106 KeyEventResult::EventIgnored
107 }
108
109 fn focus_event(
110 self: Pin<&Self>,
111 _: &FocusEvent,
112 _window_adapter: &Rc<dyn WindowAdapter>,
113 _self_rc: &ItemRc,
114 ) -> FocusEventResult {
115 FocusEventResult::FocusIgnored
116 }
117
118 fn_render! { this dpr size painter widget initial_state =>
119 let indeterminate = this.indeterminate();
120 let progress = if indeterminate { -1 } else { (this.progress().max(0.0).min(1.0) * 100.) as i32 };
121
122 cpp!(unsafe [
123 painter as "QPainterPtr*",
124 widget as "QWidget*",
125 size as "QSize",
126 progress as "int",
127 dpr as "float",
128 initial_state as "int"
129 ] {
130 QPainter *painter_ = painter->get();
131 QStyleOptionProgressBar option;
132 option.styleObject = widget;
133 option.state |= QStyle::State(initial_state) | QStyle::State_Horizontal | QStyle::State_Enabled;
134 option.rect = QRect(QPoint(), size / dpr);
135 option.maximum = progress < 0 ? 0 : 100;
136 option.minimum = 0;
137 option.progress = progress;
138
139 qApp->style()->drawControl(QStyle::CE_ProgressBar, &option, painter_, widget);
140 });
141 }
142
143 fn bounding_rect(
144 self: core::pin::Pin<&Self>,
145 _window_adapter: &Rc<dyn WindowAdapter>,
146 _self_rc: &ItemRc,
147 geometry: LogicalRect,
148 ) -> LogicalRect {
149 geometry
150 }
151
152 fn clips_children(self: core::pin::Pin<&Self>) -> bool {
153 false
154 }
155}
156
157impl ItemConsts for NativeProgressIndicator {
158 const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
159 Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
160}
161
162declare_item_vtable! {
163fn slint_get_NativeProgressIndicatorVTable() -> NativeProgressIndicatorVTable for NativeProgressIndicator
164}