fractal/components/camera/
viewfinder.rs1use gettextrs::gettext;
4use gtk::{glib, glib::closure_local, prelude::*, subclass::prelude::*};
5use matrix_sdk::encryption::verification::QrVerificationData;
6
7use super::QrVerificationDataBoxed;
8
9#[derive(Default, Debug, Copy, Clone, glib::Enum, PartialEq)]
11#[enum_type(name = "CameraViewfinderState")]
12pub enum CameraViewfinderState {
13 #[default]
15 Loading,
16 Ready,
18 NoCameras,
20 Error,
22}
23
24mod imp {
25 use std::{cell::Cell, sync::LazyLock};
26
27 use glib::subclass::Signal;
28
29 use super::*;
30
31 #[repr(C)]
32 pub struct CameraViewfinderClass {
33 parent_class: glib::object::Class<gtk::Widget>,
34 }
35
36 unsafe impl ClassStruct for CameraViewfinderClass {
37 type Type = CameraViewfinder;
38 }
39
40 #[derive(Debug, Default, glib::Properties)]
41 #[properties(wrapper_type = super::CameraViewfinder)]
42 pub struct CameraViewfinder {
43 #[property(get, set = Self::set_state, explicit_notify, builder(CameraViewfinderState::default()))]
45 state: Cell<CameraViewfinderState>,
46 }
47
48 #[glib::object_subclass]
49 impl ObjectSubclass for CameraViewfinder {
50 const NAME: &'static str = "CameraViewfinder";
51 type Type = super::CameraViewfinder;
52 type ParentType = gtk::Widget;
53 type Class = CameraViewfinderClass;
54 }
55
56 #[glib::derived_properties]
57 impl ObjectImpl for CameraViewfinder {
58 fn signals() -> &'static [Signal] {
59 static SIGNALS: LazyLock<Vec<Signal>> = LazyLock::new(|| {
60 vec![
61 Signal::builder("qrcode-detected")
62 .param_types([QrVerificationDataBoxed::static_type()])
63 .run_first()
64 .build(),
65 ]
66 });
67 SIGNALS.as_ref()
68 }
69
70 fn constructed(&self) {
71 self.parent_constructed();
72
73 self.obj()
74 .update_property(&[gtk::accessible::Property::Label(&gettext("Viewfinder"))]);
75 }
76 }
77
78 impl WidgetImpl for CameraViewfinder {}
79
80 impl CameraViewfinder {
81 fn set_state(&self, state: CameraViewfinderState) {
83 if self.state.get() == state {
84 return;
85 }
86
87 self.state.set(state);
88 self.obj().notify_state();
89 }
90 }
91}
92
93glib::wrapper! {
94 pub struct CameraViewfinder(ObjectSubclass<imp::CameraViewfinder>)
100 @extends gtk::Widget,
101 @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget;
102}
103
104#[allow(dead_code)]
106pub(super) trait CameraViewfinderExt: 'static {
107 fn state(&self) -> CameraViewfinderState;
109
110 fn set_state(&self, state: CameraViewfinderState);
112
113 fn connect_qrcode_detected<F: Fn(&Self, QrVerificationData) + 'static>(
115 &self,
116 f: F,
117 ) -> glib::SignalHandlerId;
118
119 fn emit_qrcode_detected(&self, data: QrVerificationData);
121}
122
123impl<O: IsA<CameraViewfinder>> CameraViewfinderExt for O {
124 fn state(&self) -> CameraViewfinderState {
125 self.upcast_ref().state()
126 }
127
128 fn set_state(&self, state: CameraViewfinderState) {
130 self.upcast_ref().set_state(state);
131 }
132
133 fn connect_qrcode_detected<F: Fn(&Self, QrVerificationData) + 'static>(
134 &self,
135 f: F,
136 ) -> glib::SignalHandlerId {
137 self.connect_closure(
138 "qrcode-detected",
139 true,
140 closure_local!(|obj: Self, data: QrVerificationDataBoxed| {
141 f(&obj, data.0);
142 }),
143 )
144 }
145
146 fn emit_qrcode_detected(&self, data: QrVerificationData) {
147 self.emit_by_name::<()>("qrcode-detected", &[&QrVerificationDataBoxed(data)]);
148 }
149}
150
151pub(super) trait CameraViewfinderImpl: ObjectImpl {}
156
157unsafe impl<T> IsSubclassable<T> for CameraViewfinder
158where
159 T: CameraViewfinderImpl + WidgetImpl,
160 T::Type: IsA<CameraViewfinder>,
161{
162 fn class_init(class: &mut glib::Class<Self>) {
163 Self::parent_class_init::<T>(class.upcast_ref_mut());
164 }
165}