use cxx::let_cxx_string;
use crate::ffi;
use crate::Point;
pub trait AsWidget {
fn widget_ptr(&self) -> *mut ffi::QWidget;
fn set_has_parent(&mut self);
}
pub struct Widget {
ptr: *mut ffi::QWidget,
has_parent: bool,
#[allow(dead_code)]
title: Option<String>,
#[allow(dead_code)]
width: i32,
#[allow(dead_code)]
height: i32,
signal_handles: Vec<crate::signal::SignalHandle>,
}
impl Widget {
pub fn new() -> Builder {
Builder::new()
}
#[doc(hidden)]
pub(crate) fn from_raw(ptr: *mut ffi::QWidget, has_parent: bool) -> Self {
debug_assert!(!ptr.is_null(), "from_raw called with null pointer");
Self {
ptr,
has_parent,
title: None,
width: 0,
height: 0,
signal_handles: Vec::new(),
}
}
pub fn show(&self) {
debug_assert!(!self.ptr.is_null(), "Widget::show on null pointer");
unsafe { ffi::QWidget_show(self.ptr) };
}
pub fn hide(&self) {
debug_assert!(!self.ptr.is_null(), "Widget::hide on null pointer");
unsafe { ffi::QWidget_hide(self.ptr) };
}
pub fn set_title(&self, title: &str) {
debug_assert!(!self.ptr.is_null(), "Widget::set_title on null pointer");
let_cxx_string!(c_title = title);
unsafe {
ffi::QWidget_setWindowTitle(self.ptr, &c_title);
}
}
pub fn resize(&self, width: i32, height: i32) {
debug_assert!(!self.ptr.is_null(), "Widget::resize on null pointer");
unsafe {
ffi::QWidget_resize(self.ptr, width, height);
}
}
pub fn set_vlayout(&mut self, layout_ptr: *mut ffi::QVBoxLayout) {
debug_assert!(!self.ptr.is_null(), "Widget::set_vlayout on null pointer");
debug_assert!(!layout_ptr.is_null(), "set_vlayout with null layout");
unsafe {
ffi::QWidget_setLayout(
self.ptr,
layout_ptr as *mut u8 as *mut ffi::QLayout,
);
}
}
pub fn set_grid(&mut self, grid: &crate::GridLayout) {
debug_assert!(!self.ptr.is_null());
unsafe {
ffi::QWidget_setLayout(
self.ptr,
grid.layout_ptr() as *mut u8 as *mut ffi::QLayout,
);
}
}
pub fn set_hlayout(&mut self, layout_ptr: *mut ffi::QHBoxLayout) {
debug_assert!(!self.ptr.is_null(), "Widget::set_hlayout on null pointer");
debug_assert!(!layout_ptr.is_null(), "set_hlayout with null layout");
unsafe {
ffi::QWidget_setLayout(
self.ptr,
layout_ptr as *mut u8 as *mut ffi::QLayout,
);
}
}
pub fn set_icon(&self, icon_path: &str) {
debug_assert!(!self.ptr.is_null(), "Widget::set_icon on null pointer");
let_cxx_string!(c_path = icon_path);
unsafe { ffi::QWidget_setWindowIcon(self.ptr, &c_path); }
}
pub fn set_enabled(&self, enabled: bool) {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QWidget_setEnabled(self.ptr, enabled); }
}
pub fn set_visible(&self, visible: bool) {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QWidget_setVisible(self.ptr, visible); }
}
pub fn set_tooltip(&self, tip: &str) {
debug_assert!(!self.ptr.is_null());
let_cxx_string!(c_tip = tip);
unsafe { ffi::QWidget_setToolTip(self.ptr, &c_tip); }
}
pub fn set_min_size(&self, w: i32, h: i32) {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QWidget_setMinimumSize(self.ptr, w, h); }
}
pub fn set_max_size(&self, w: i32, h: i32) {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QWidget_setMaximumSize(self.ptr, w, h); }
}
pub fn set_fixed_size(&self, w: i32, h: i32) {
debug_assert!(!self.ptr.is_null());
unsafe { ffi::QWidget_setFixedSize(self.ptr, w, h); }
}
pub fn set_style_sheet(&self, css: &str) {
debug_assert!(!self.ptr.is_null());
let_cxx_string!(c_css = css);
unsafe { ffi::QWidget_setStyleSheet(self.ptr, &c_css); }
}
pub fn move_to(&self, x: i32, y: i32) {
debug_assert!(!self.ptr.is_null(), "Widget::move_to on null pointer");
unsafe { ffi::QWidget_move(self.ptr, x, y); }
}
pub fn move_to_point(&self, point: Point) {
debug_assert!(!self.ptr.is_null(), "Widget::move_to_point on null pointer");
unsafe { ffi::QWidget_moveToPoint(self.ptr, point.to_raw()); }
}
pub fn find(&self, kind: WidgetKind, name: &str) -> Option<FoundWidget> {
debug_assert!(!self.ptr.is_null());
let_cxx_string!(c_name = name);
match kind {
WidgetKind::PushButton => {
let ptr = unsafe { ffi::QWidget_findPushButton(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::PushButton(crate::PushButton::from_raw(ptr, name))) }
}
WidgetKind::LineEdit => {
let ptr = unsafe { ffi::QWidget_findLineEdit(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::LineEdit(crate::LineEdit::from_raw(ptr, name))) }
}
WidgetKind::CheckBox => {
let ptr = unsafe { ffi::QWidget_findCheckBox(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::CheckBox(crate::CheckBox::from_raw(ptr, name))) }
}
WidgetKind::ComboBox => {
let ptr = unsafe { ffi::QWidget_findComboBox(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::ComboBox(crate::ComboBox::from_raw(ptr, name))) }
}
WidgetKind::Slider => {
let ptr = unsafe { ffi::QWidget_findSlider(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::Slider(crate::Slider::from_raw(ptr, name))) }
}
WidgetKind::TextEdit => {
let ptr = unsafe { ffi::QWidget_findTextEdit(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::TextEdit(crate::TextEdit::from_raw(ptr, name))) }
}
WidgetKind::Label => {
let ptr = unsafe { ffi::QWidget_findLabel(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::Label(crate::Label::from_raw(ptr, name))) }
}
WidgetKind::ProgressBar => {
let ptr = unsafe { ffi::QWidget_findProgressBar(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::ProgressBar(crate::ProgressBar::from_raw(ptr))) }
}
WidgetKind::RadioButton => {
let ptr = unsafe { ffi::QWidget_findRadioButton(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::RadioButton(crate::RadioButton::from_raw(ptr))) }
}
WidgetKind::GroupBox => {
let ptr = unsafe { ffi::QWidget_findGroupBox(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::GroupBox(crate::GroupBox::from_raw(ptr))) }
}
WidgetKind::TabWidget => {
let ptr = unsafe { ffi::QWidget_findTabWidget(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::TabWidget(crate::TabWidget::from_raw(ptr))) }
}
WidgetKind::SpinBox => {
let ptr = unsafe { ffi::QWidget_findSpinBox(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::SpinBox(crate::SpinBox::from_raw(ptr))) }
}
WidgetKind::Any => {
let ptr = unsafe { ffi::QWidget_findWidget(self.ptr, &c_name) };
if ptr.is_null() { None }
else { Some(FoundWidget::Widget(Widget::from_raw(ptr, true))) }
}
}
}
}
#[derive(Clone, Copy)]
pub enum WidgetKind {
PushButton,
LineEdit,
CheckBox,
ComboBox,
Slider,
TextEdit,
Label,
ProgressBar,
RadioButton,
GroupBox,
TabWidget,
SpinBox,
Any,
}
pub enum FoundWidget {
PushButton(crate::PushButton),
LineEdit(crate::LineEdit),
CheckBox(crate::CheckBox),
ComboBox(crate::ComboBox),
Slider(crate::Slider),
TextEdit(crate::TextEdit),
Label(crate::Label),
ProgressBar(crate::ProgressBar),
RadioButton(crate::RadioButton),
GroupBox(crate::GroupBox),
TabWidget(crate::TabWidget),
SpinBox(crate::SpinBox),
Widget(Widget),
}
impl AsWidget for Widget {
fn widget_ptr(&self) -> *mut ffi::QWidget {
debug_assert!(!self.ptr.is_null(), "widget_ptr on null pointer");
unsafe { ffi::toQWidget_QWidget(self.ptr) }
}
fn set_has_parent(&mut self) {
self.has_parent = true;
}
}
impl Drop for Widget {
fn drop(&mut self) {
if self.ptr.is_null() { return; }
if self.has_parent {
unsafe { ffi::QWidget_disconnectAll(self.ptr); }
for h in self.signal_handles.drain(..) {
unsafe { h.reclaim(); }
}
} else {
for h in self.signal_handles.drain(..) {
unsafe { h.reclaim(); }
}
unsafe { ffi::QWidget_delete(self.ptr) };
}
self.ptr = std::ptr::null_mut();
}
}
pub struct Builder {
title: Option<String>,
icon: Option<String>,
width: i32,
height: i32,
parent: Option<*mut ffi::QWidget>,
}
impl Builder {
fn new() -> Self {
Self {
title: None,
icon: None,
width: 400,
height: 300,
parent: None,
}
}
pub fn title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn icon(mut self, path: impl Into<String>) -> Self {
self.icon = Some(path.into());
self
}
pub fn size(mut self, width: i32, height: i32) -> Self {
self.width = width;
self.height = height;
self
}
pub fn parent(mut self, parent: &dyn AsWidget) -> Self {
self.parent = Some(parent.widget_ptr());
self
}
pub fn build(self) -> Widget {
let ptr = unsafe {
ffi::QWidget_new(
self.parent.unwrap_or(std::ptr::null_mut()),
)
};
debug_assert!(!ptr.is_null(), "QWidget_new returned null");
let has_parent = self.parent.is_some();
let widget = Widget {
ptr,
has_parent,
title: self.title.clone(),
width: self.width,
height: self.height,
signal_handles: Vec::new(),
};
if let Some(ref t) = self.title {
let_cxx_string!(c_title = t);
unsafe { ffi::QWidget_setWindowTitle(widget.ptr, &c_title) };
}
if let Some(ref icon_path) = self.icon {
let_cxx_string!(c_icon = icon_path);
unsafe { ffi::QWidget_setWindowIcon(widget.ptr, &c_icon) };
}
unsafe { ffi::QWidget_resize(widget.ptr, self.width, self.height) };
widget
}
pub fn show(self) -> Widget {
let w = self.build();
w.show();
w
}
}