1use crate::{ffi, SaveDelegate};
7use glib::{
8 prelude::*,
9 signal::{connect_raw, SignalHandlerId},
10 translate::*,
11};
12use std::{boxed::Box as Box_, pin::Pin};
13
14#[cfg(feature = "adw_v1_2")]
15#[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
16glib::wrapper! {
17 #[doc(alias = "PanelSaveDialog")]
18 pub struct SaveDialog(Object<ffi::PanelSaveDialog, ffi::PanelSaveDialogClass>) @extends adw::MessageDialog, gtk::Widget, @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::ShortcutManager;
19
20 match fn {
21 type_ => || ffi::panel_save_dialog_get_type(),
22 }
23}
24
25#[cfg(not(any(feature = "adw_v1_2")))]
26glib::wrapper! {
27 #[doc(alias = "PanelSaveDialog")]
28 pub struct SaveDialog(Object<ffi::PanelSaveDialog, ffi::PanelSaveDialogClass>) @extends gtk::Widget, @implements gtk::Accessible, gtk::Buildable, gtk::ConstraintTarget, gtk::ShortcutManager;
29
30 match fn {
31 type_ => || ffi::panel_save_dialog_get_type(),
32 }
33}
34
35impl SaveDialog {
36 #[doc(alias = "panel_save_dialog_new")]
37 pub fn new() -> SaveDialog {
38 assert_initialized_main_thread!();
39 unsafe { gtk::Widget::from_glib_none(ffi::panel_save_dialog_new()).unsafe_cast() }
40 }
41
42 pub fn builder() -> SaveDialogBuilder {
47 SaveDialogBuilder::new()
48 }
49
50 #[doc(alias = "panel_save_dialog_add_delegate")]
51 pub fn add_delegate(&self, delegate: &impl IsA<SaveDelegate>) {
52 unsafe {
53 ffi::panel_save_dialog_add_delegate(
54 self.to_glib_none().0,
55 delegate.as_ref().to_glib_none().0,
56 );
57 }
58 }
59
60 #[doc(alias = "panel_save_dialog_get_close_after_save")]
61 #[doc(alias = "get_close_after_save")]
62 #[doc(alias = "close-after-save")]
63 pub fn closes_after_save(&self) -> bool {
64 unsafe {
65 from_glib(ffi::panel_save_dialog_get_close_after_save(
66 self.to_glib_none().0,
67 ))
68 }
69 }
70
71 #[doc(alias = "panel_save_dialog_run_async")]
72 pub fn run_async<P: FnOnce(Result<(), glib::Error>) + 'static>(
73 &self,
74 cancellable: Option<&impl IsA<gio::Cancellable>>,
75 callback: P,
76 ) {
77 let main_context = glib::MainContext::ref_thread_default();
78 let is_main_context_owner = main_context.is_owner();
79 let has_acquired_main_context = (!is_main_context_owner)
80 .then(|| main_context.acquire().ok())
81 .flatten();
82 assert!(
83 is_main_context_owner || has_acquired_main_context.is_some(),
84 "Async operations only allowed if the thread is owning the MainContext"
85 );
86
87 let user_data: Box_<glib::thread_guard::ThreadGuard<P>> =
88 Box_::new(glib::thread_guard::ThreadGuard::new(callback));
89 unsafe extern "C" fn run_async_trampoline<P: FnOnce(Result<(), glib::Error>) + 'static>(
90 _source_object: *mut glib::gobject_ffi::GObject,
91 res: *mut gio::ffi::GAsyncResult,
92 user_data: glib::ffi::gpointer,
93 ) {
94 let mut error = std::ptr::null_mut();
95 ffi::panel_save_dialog_run_finish(_source_object as *mut _, res, &mut error);
96 let result = if error.is_null() {
97 Ok(())
98 } else {
99 Err(from_glib_full(error))
100 };
101 let callback: Box_<glib::thread_guard::ThreadGuard<P>> =
102 Box_::from_raw(user_data as *mut _);
103 let callback: P = callback.into_inner();
104 callback(result);
105 }
106 let callback = run_async_trampoline::<P>;
107 unsafe {
108 ffi::panel_save_dialog_run_async(
109 self.to_glib_none().0,
110 cancellable.map(|p| p.as_ref()).to_glib_none().0,
111 Some(callback),
112 Box_::into_raw(user_data) as *mut _,
113 );
114 }
115 }
116
117 pub fn run_future(
118 &self,
119 ) -> Pin<Box_<dyn std::future::Future<Output = Result<(), glib::Error>> + 'static>> {
120 Box_::pin(gio::GioFuture::new(self, move |obj, cancellable, send| {
121 obj.run_async(Some(cancellable), move |res| {
122 send.resolve(res);
123 });
124 }))
125 }
126
127 #[doc(alias = "panel_save_dialog_set_close_after_save")]
128 #[doc(alias = "close-after-save")]
129 pub fn set_close_after_save(&self, close_after_save: bool) {
130 unsafe {
131 ffi::panel_save_dialog_set_close_after_save(
132 self.to_glib_none().0,
133 close_after_save.into_glib(),
134 );
135 }
136 }
137
138 #[cfg_attr(feature = "v1_8", deprecated = "Since 1.8")]
139 #[doc(alias = "close-after-save")]
140 pub fn connect_close_after_save_notify<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
141 unsafe extern "C" fn notify_close_after_save_trampoline<F: Fn(&SaveDialog) + 'static>(
142 this: *mut ffi::PanelSaveDialog,
143 _param_spec: glib::ffi::gpointer,
144 f: glib::ffi::gpointer,
145 ) {
146 let f: &F = &*(f as *const F);
147 f(&from_glib_borrow(this))
148 }
149 unsafe {
150 let f: Box_<F> = Box_::new(f);
151 connect_raw(
152 self.as_ptr() as *mut _,
153 c"notify::close-after-save".as_ptr() as *const _,
154 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
155 notify_close_after_save_trampoline::<F> as *const (),
156 )),
157 Box_::into_raw(f),
158 )
159 }
160 }
161}
162
163impl Default for SaveDialog {
164 fn default() -> Self {
165 Self::new()
166 }
167}
168
169#[must_use = "The builder must be built to be used"]
174pub struct SaveDialogBuilder {
175 builder: glib::object::ObjectBuilder<'static, SaveDialog>,
176}
177
178impl SaveDialogBuilder {
179 fn new() -> Self {
180 Self {
181 builder: glib::object::Object::builder(),
182 }
183 }
184
185 #[cfg_attr(feature = "v1_8", deprecated = "Since 1.8")]
186 pub fn close_after_save(self, close_after_save: bool) -> Self {
187 Self {
188 builder: self.builder.property("close-after-save", close_after_save),
189 }
190 }
191
192 #[cfg(feature = "adw_v1_2")]
193 #[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
194 #[cfg_attr(feature = "v1_6", deprecated = "Since 1.6")]
195 pub fn body(self, body: impl Into<glib::GString>) -> Self {
196 Self {
197 builder: self.builder.property("body", body.into()),
198 }
199 }
200
201 #[cfg(feature = "adw_v1_2")]
202 #[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
203 #[cfg_attr(feature = "v1_6", deprecated = "Since 1.6")]
204 pub fn body_use_markup(self, body_use_markup: bool) -> Self {
205 Self {
206 builder: self.builder.property("body-use-markup", body_use_markup),
207 }
208 }
209
210 #[cfg(feature = "adw_v1_2")]
211 #[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
212 #[cfg_attr(feature = "v1_6", deprecated = "Since 1.6")]
213 pub fn close_response(self, close_response: impl Into<glib::GString>) -> Self {
214 Self {
215 builder: self
216 .builder
217 .property("close-response", close_response.into()),
218 }
219 }
220
221 #[cfg(feature = "adw_v1_2")]
222 #[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
223 #[cfg_attr(feature = "v1_6", deprecated = "Since 1.6")]
224 pub fn default_response(self, default_response: impl Into<glib::GString>) -> Self {
225 Self {
226 builder: self
227 .builder
228 .property("default-response", default_response.into()),
229 }
230 }
231
232 #[cfg(feature = "adw_v1_2")]
233 #[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
234 #[cfg_attr(feature = "v1_6", deprecated = "Since 1.6")]
235 pub fn extra_child(self, extra_child: &impl IsA<gtk::Widget>) -> Self {
236 Self {
237 builder: self
238 .builder
239 .property("extra-child", extra_child.clone().upcast()),
240 }
241 }
242
243 #[cfg(feature = "adw_v1_2")]
244 #[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
245 #[cfg_attr(feature = "v1_6", deprecated = "Since 1.6")]
246 pub fn heading(self, heading: impl Into<glib::GString>) -> Self {
247 Self {
248 builder: self.builder.property("heading", heading.into()),
249 }
250 }
251
252 #[cfg(feature = "adw_v1_2")]
253 #[cfg_attr(docsrs, doc(cfg(feature = "adw_v1_2")))]
254 #[cfg_attr(feature = "v1_6", deprecated = "Since 1.6")]
255 pub fn heading_use_markup(self, heading_use_markup: bool) -> Self {
256 Self {
257 builder: self
258 .builder
259 .property("heading-use-markup", heading_use_markup),
260 }
261 }
262
263 pub fn can_focus(self, can_focus: bool) -> Self {
264 Self {
265 builder: self.builder.property("can-focus", can_focus),
266 }
267 }
268
269 pub fn can_target(self, can_target: bool) -> Self {
270 Self {
271 builder: self.builder.property("can-target", can_target),
272 }
273 }
274
275 pub fn css_classes(self, css_classes: impl Into<glib::StrV>) -> Self {
276 Self {
277 builder: self.builder.property("css-classes", css_classes.into()),
278 }
279 }
280
281 pub fn css_name(self, css_name: impl Into<glib::GString>) -> Self {
282 Self {
283 builder: self.builder.property("css-name", css_name.into()),
284 }
285 }
286
287 pub fn cursor(self, cursor: &gdk::Cursor) -> Self {
288 Self {
289 builder: self.builder.property("cursor", cursor.clone()),
290 }
291 }
292
293 pub fn focus_on_click(self, focus_on_click: bool) -> Self {
294 Self {
295 builder: self.builder.property("focus-on-click", focus_on_click),
296 }
297 }
298
299 pub fn focusable(self, focusable: bool) -> Self {
300 Self {
301 builder: self.builder.property("focusable", focusable),
302 }
303 }
304
305 pub fn halign(self, halign: gtk::Align) -> Self {
306 Self {
307 builder: self.builder.property("halign", halign),
308 }
309 }
310
311 pub fn has_tooltip(self, has_tooltip: bool) -> Self {
312 Self {
313 builder: self.builder.property("has-tooltip", has_tooltip),
314 }
315 }
316
317 pub fn height_request(self, height_request: i32) -> Self {
318 Self {
319 builder: self.builder.property("height-request", height_request),
320 }
321 }
322
323 pub fn hexpand(self, hexpand: bool) -> Self {
324 Self {
325 builder: self.builder.property("hexpand", hexpand),
326 }
327 }
328
329 pub fn hexpand_set(self, hexpand_set: bool) -> Self {
330 Self {
331 builder: self.builder.property("hexpand-set", hexpand_set),
332 }
333 }
334
335 pub fn layout_manager(self, layout_manager: &impl IsA<gtk::LayoutManager>) -> Self {
336 Self {
337 builder: self
338 .builder
339 .property("layout-manager", layout_manager.clone().upcast()),
340 }
341 }
342
343 #[cfg(feature = "gtk_v4_18")]
344 #[cfg_attr(docsrs, doc(cfg(feature = "gtk_v4_18")))]
345 pub fn limit_events(self, limit_events: bool) -> Self {
346 Self {
347 builder: self.builder.property("limit-events", limit_events),
348 }
349 }
350
351 pub fn margin_bottom(self, margin_bottom: i32) -> Self {
352 Self {
353 builder: self.builder.property("margin-bottom", margin_bottom),
354 }
355 }
356
357 pub fn margin_end(self, margin_end: i32) -> Self {
358 Self {
359 builder: self.builder.property("margin-end", margin_end),
360 }
361 }
362
363 pub fn margin_start(self, margin_start: i32) -> Self {
364 Self {
365 builder: self.builder.property("margin-start", margin_start),
366 }
367 }
368
369 pub fn margin_top(self, margin_top: i32) -> Self {
370 Self {
371 builder: self.builder.property("margin-top", margin_top),
372 }
373 }
374
375 pub fn name(self, name: impl Into<glib::GString>) -> Self {
376 Self {
377 builder: self.builder.property("name", name.into()),
378 }
379 }
380
381 pub fn opacity(self, opacity: f64) -> Self {
382 Self {
383 builder: self.builder.property("opacity", opacity),
384 }
385 }
386
387 pub fn overflow(self, overflow: gtk::Overflow) -> Self {
388 Self {
389 builder: self.builder.property("overflow", overflow),
390 }
391 }
392
393 pub fn receives_default(self, receives_default: bool) -> Self {
394 Self {
395 builder: self.builder.property("receives-default", receives_default),
396 }
397 }
398
399 pub fn sensitive(self, sensitive: bool) -> Self {
400 Self {
401 builder: self.builder.property("sensitive", sensitive),
402 }
403 }
404
405 pub fn tooltip_markup(self, tooltip_markup: impl Into<glib::GString>) -> Self {
406 Self {
407 builder: self
408 .builder
409 .property("tooltip-markup", tooltip_markup.into()),
410 }
411 }
412
413 pub fn tooltip_text(self, tooltip_text: impl Into<glib::GString>) -> Self {
414 Self {
415 builder: self.builder.property("tooltip-text", tooltip_text.into()),
416 }
417 }
418
419 pub fn valign(self, valign: gtk::Align) -> Self {
420 Self {
421 builder: self.builder.property("valign", valign),
422 }
423 }
424
425 pub fn vexpand(self, vexpand: bool) -> Self {
426 Self {
427 builder: self.builder.property("vexpand", vexpand),
428 }
429 }
430
431 pub fn vexpand_set(self, vexpand_set: bool) -> Self {
432 Self {
433 builder: self.builder.property("vexpand-set", vexpand_set),
434 }
435 }
436
437 pub fn visible(self, visible: bool) -> Self {
438 Self {
439 builder: self.builder.property("visible", visible),
440 }
441 }
442
443 pub fn width_request(self, width_request: i32) -> Self {
444 Self {
445 builder: self.builder.property("width-request", width_request),
446 }
447 }
448
449 pub fn accessible_role(self, accessible_role: gtk::AccessibleRole) -> Self {
450 Self {
451 builder: self.builder.property("accessible-role", accessible_role),
452 }
453 }
454
455 #[must_use = "Building the object from the builder is usually expensive and is not expected to have side effects"]
458 pub fn build(self) -> SaveDialog {
459 assert_initialized_main_thread!();
460 self.builder.build()
461 }
462}