fractal/components/camera/
viewfinder.rsuse gettextrs::gettext;
use gtk::{glib, glib::closure_local, prelude::*, subclass::prelude::*};
use matrix_sdk::encryption::verification::QrVerificationData;
use super::QrVerificationDataBoxed;
#[derive(Default, Debug, Copy, Clone, glib::Enum, PartialEq)]
#[enum_type(name = "CameraViewfinderState")]
pub enum CameraViewfinderState {
#[default]
Loading,
Ready,
NoCameras,
Error,
}
mod imp {
use std::{cell::Cell, sync::LazyLock};
use glib::subclass::Signal;
use super::*;
#[repr(C)]
pub struct CameraViewfinderClass {
parent_class: glib::object::Class<gtk::Widget>,
}
unsafe impl ClassStruct for CameraViewfinderClass {
type Type = CameraViewfinder;
}
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::CameraViewfinder)]
pub struct CameraViewfinder {
#[property(get, set = Self::set_state, explicit_notify, builder(CameraViewfinderState::default()))]
state: Cell<CameraViewfinderState>,
}
#[glib::object_subclass]
impl ObjectSubclass for CameraViewfinder {
const NAME: &'static str = "CameraViewfinder";
type Type = super::CameraViewfinder;
type ParentType = gtk::Widget;
type Class = CameraViewfinderClass;
}
#[glib::derived_properties]
impl ObjectImpl for CameraViewfinder {
fn signals() -> &'static [Signal] {
static SIGNALS: LazyLock<Vec<Signal>> = LazyLock::new(|| {
vec![Signal::builder("qrcode-detected")
.param_types([QrVerificationDataBoxed::static_type()])
.run_first()
.build()]
});
SIGNALS.as_ref()
}
fn constructed(&self) {
self.parent_constructed();
self.obj()
.update_property(&[gtk::accessible::Property::Label(&gettext("Viewfinder"))]);
}
}
impl WidgetImpl for CameraViewfinder {}
impl CameraViewfinder {
fn set_state(&self, state: CameraViewfinderState) {
if self.state.get() == state {
return;
}
self.state.set(state);
self.obj().notify_state();
}
}
}
glib::wrapper! {
pub struct CameraViewfinder(ObjectSubclass<imp::CameraViewfinder>)
@extends gtk::Widget, @implements gtk::Accessible;
}
#[allow(dead_code)]
pub(super) trait CameraViewfinderExt: 'static {
fn state(&self) -> CameraViewfinderState;
fn set_state(&self, state: CameraViewfinderState);
fn connect_qrcode_detected<F: Fn(&Self, QrVerificationData) + 'static>(
&self,
f: F,
) -> glib::SignalHandlerId;
fn emit_qrcode_detected(&self, data: QrVerificationData);
}
impl<O: IsA<CameraViewfinder>> CameraViewfinderExt for O {
fn state(&self) -> CameraViewfinderState {
self.upcast_ref().state()
}
fn set_state(&self, state: CameraViewfinderState) {
self.upcast_ref().set_state(state);
}
fn connect_qrcode_detected<F: Fn(&Self, QrVerificationData) + 'static>(
&self,
f: F,
) -> glib::SignalHandlerId {
self.connect_closure(
"qrcode-detected",
true,
closure_local!(|obj: Self, data: QrVerificationDataBoxed| {
f(&obj, data.0);
}),
)
}
fn emit_qrcode_detected(&self, data: QrVerificationData) {
self.emit_by_name::<()>("qrcode-detected", &[&QrVerificationDataBoxed(data)]);
}
}
pub(super) trait CameraViewfinderImpl: ObjectImpl {}
unsafe impl<T> IsSubclassable<T> for CameraViewfinder
where
T: CameraViewfinderImpl + WidgetImpl,
T::Type: IsA<CameraViewfinder>,
{
fn class_init(class: &mut glib::Class<Self>) {
Self::parent_class_init::<T>(class.upcast_ref_mut());
}
}