i_slint_backend_qt/qt_widgets/
tableheadersection.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4use i_slint_core::{input::FocusEventResult, items::SortOrder};
5
6use super::*;
7
8#[repr(C)]
9#[derive(FieldOffsets, Default, SlintElement)]
10#[pin]
11pub struct NativeTableHeaderSection {
12    pub item: Property<i_slint_core::model::TableColumn>,
13    pub index: Property<i32>,
14    pub cached_rendering_data: CachedRenderingData,
15    pub has_hover: Property<bool>,
16    widget_ptr: std::cell::Cell<SlintTypeErasedWidgetPtr>,
17    animation_tracker: Property<i32>,
18}
19
20impl Item for NativeTableHeaderSection {
21    fn init(self: Pin<&Self>, _self_rc: &ItemRc) {
22        let animation_tracker_property_ptr = Self::FIELD_OFFSETS.animation_tracker.apply_pin(self);
23        self.widget_ptr.set(cpp! { unsafe [animation_tracker_property_ptr as "void*"] -> SlintTypeErasedWidgetPtr as "std::unique_ptr<SlintTypeErasedWidget>" {
24            return make_unique_animated_widget<QWidget>(animation_tracker_property_ptr);
25        }});
26    }
27
28    fn layout_info(
29        self: Pin<&Self>,
30        orientation: Orientation,
31        _window_adapter: &Rc<dyn WindowAdapter>,
32        _self_rc: &ItemRc,
33    ) -> LayoutInfo {
34        let index: i32 = self.index();
35        let item = self.item();
36        let text: qttypes::QString = item.title.as_str().into();
37        let widget: NonNull<()> = SlintTypeErasedWidgetPtr::qwidget_ptr(&self.widget_ptr);
38
39        let s = cpp!(unsafe [
40            index as "int",
41            text as "QString",
42            widget as "QWidget*"
43        ] -> qttypes::QSize as "QSize" {
44            ensure_initialized();
45
46            QStyleOptionHeader option;
47            option.state |= QStyle::State_Horizontal;
48            option.section = index;
49
50            option.text = text;
51
52            option.textAlignment = Qt::AlignCenter | Qt::AlignVCenter;
53            return qApp->style()->sizeFromContents(QStyle::CT_HeaderSection, &option, QSize{}, widget);
54        });
55        let min = match orientation {
56            Orientation::Horizontal => s.width,
57            Orientation::Vertical => s.height,
58        } as f32;
59        LayoutInfo { min, preferred: min, ..LayoutInfo::default() }
60    }
61
62    fn input_event_filter_before_children(
63        self: Pin<&Self>,
64        _: &MouseEvent,
65        _window_adapter: &Rc<dyn WindowAdapter>,
66        _self_rc: &ItemRc,
67    ) -> InputEventFilterResult {
68        InputEventFilterResult::ForwardAndIgnore
69    }
70
71    fn input_event(
72        self: Pin<&Self>,
73        _event: &MouseEvent,
74        _window_adapter: &Rc<dyn WindowAdapter>,
75        _self_rc: &i_slint_core::items::ItemRc,
76    ) -> InputEventResult {
77        InputEventResult::EventIgnored
78    }
79
80    fn capture_key_event(
81        self: Pin<&Self>,
82        _event: &KeyEvent,
83        _window_adapter: &Rc<dyn WindowAdapter>,
84        _self_rc: &ItemRc,
85    ) -> KeyEventResult {
86        KeyEventResult::EventIgnored
87    }
88
89    fn key_event(
90        self: Pin<&Self>,
91        _: &KeyEvent,
92        _window_adapter: &Rc<dyn WindowAdapter>,
93        _self_rc: &ItemRc,
94    ) -> KeyEventResult {
95        KeyEventResult::EventIgnored
96    }
97
98    fn focus_event(
99        self: Pin<&Self>,
100        _: &FocusEvent,
101        _window_adapter: &Rc<dyn WindowAdapter>,
102        _self_rc: &ItemRc,
103    ) -> FocusEventResult {
104        FocusEventResult::FocusIgnored
105    }
106
107    fn_render! { this dpr size painter widget initial_state =>
108        let index: i32 = this.index();
109        let has_hover: bool = this.has_hover();
110        let item = this.item();
111        let text: qttypes::QString = item.title.as_str().into();
112        let ascending: bool = item.sort_order == SortOrder::Ascending;
113        let descending: bool = item.sort_order == SortOrder::Descending;
114
115        cpp!(unsafe [
116            painter as "QPainterPtr*",
117            widget as "QWidget*",
118            size as "QSize",
119            dpr as "float",
120            index as "int",
121            has_hover as "bool",
122            text as "QString",
123            initial_state as "int",
124            ascending as "bool",
125            descending as "bool"
126        ] {
127            QPainter *painter_ = painter->get();
128
129            #if defined(Q_OS_MAC)
130                QImage header_image(size, QImage::Format_ARGB32_Premultiplied);
131                header_image.fill(Qt::transparent);
132                {QPainter p(&header_image); QPainter *painter_ = &p;
133            #endif
134
135            QStyleOptionHeader option;
136            option.styleObject = widget;
137            option.state |= QStyle::State(initial_state);
138            option.state |= QStyle::State_Horizontal | QStyle::State_Enabled;
139            option.rect = QRect(QPoint(), size / dpr);
140
141            option.section = index;
142
143            option.textAlignment = Qt::AlignLeft | Qt::AlignVCenter;
144
145            if (ascending) {
146                option.sortIndicator = QStyleOptionHeader::SortDown;
147            } else if (descending) {
148                option.sortIndicator = QStyleOptionHeader::SortUp;
149            } else {
150                option.sortIndicator = QStyleOptionHeader::None;
151            }
152
153            if (has_hover) {
154                option.state |= QStyle::State_MouseOver;
155            }
156
157            option.text = text;
158
159            qApp->style()->drawControl(QStyle::CE_Header, &option, painter_, widget);
160
161            #if defined(Q_OS_MAC)
162                }
163                (painter_)->drawImage(QPoint(), header_image);
164            #endif
165        });
166    }
167
168    fn bounding_rect(
169        self: core::pin::Pin<&Self>,
170        _window_adapter: &Rc<dyn WindowAdapter>,
171        _self_rc: &ItemRc,
172        geometry: LogicalRect,
173    ) -> LogicalRect {
174        geometry
175    }
176
177    fn clips_children(self: core::pin::Pin<&Self>) -> bool {
178        false
179    }
180}
181
182impl ItemConsts for NativeTableHeaderSection {
183    const cached_rendering_data_offset: const_field_offset::FieldOffset<Self, CachedRenderingData> =
184        Self::FIELD_OFFSETS.cached_rendering_data.as_unpinned_projection();
185}
186
187declare_item_vtable! {
188fn slint_get_NativeTableHeaderSectionVTable() -> NativeTableHeaderSectionVTable for NativeTableHeaderSection
189}