From 3a11e9c9ce72e36c6124e9dc2f8379df4f004ea9 Mon Sep 17 00:00:00 2001
From: Sophie Herold <sophie@hemio.de>
Date: Thu, 28 Sep 2023 12:58:46 +0200
Subject: [PATCH] print: Use same print operation throughout

Use a hack to wait in print signal for the layout dialog to be ready
instead of creating a new print operation with the same settings.

This works around a bug in GTK where the wrong printer gets selected
(issue #243), as well as the print dialog getting shown twice when
using the print portal (part of #61).
---
 src/widgets/print.rs | 60 +++++++++++++++++++++++++-------------------
 1 file changed, 34 insertions(+), 26 deletions(-)

diff --git a/src/widgets/print.rs b/src/widgets/print.rs
index 2ad0efb4..7c8a4657 100644
--- a/src/widgets/print.rs
+++ b/src/widgets/print.rs
@@ -53,6 +53,14 @@ enum VAlignment {
     Bottom,
 }
 
+#[derive(Debug, Clone, Copy, Default)]
+enum Status {
+    #[default]
+    Prepare,
+    Print,
+    Abort,
+}
+
 /// Scope guard for non user ui changes
 ///
 /// Creates a context in which other signals know that changes are not user input.
@@ -250,6 +258,8 @@ mod imp {
         pub(super) orientation: RefCell<String>,
 
         pub(super) ui_updates: UiUpdates,
+
+        pub(super) status: Cell<Status>,
     }
 
     #[glib::object_subclass]
@@ -291,6 +301,11 @@ mod imp {
             obj.set_transient_for(Some(&obj.parent_window()));
             obj.set_modal(true);
 
+            obj.connect_close_request(|obj| {
+                obj.imp().status.set(Status::Abort);
+                glib::Propagation::Proceed
+            });
+
             self.alignment
                 .connect_selected_notify(glib::clone!(@weak obj => move |_| obj.draw_preview()));
 
@@ -341,7 +356,7 @@ mod imp {
             });
 
             self.print_operation.connect_draw_page(glib::clone!(@weak obj =>
-                move |operation, _context, _page_nr| {
+                move |operation, context, _page_nr| {
                     let imp = obj.imp();
 
                     let basename = obj
@@ -394,8 +409,6 @@ mod imp {
                         }
                     }
 
-                    imp.print_operation.cancel();
-
                     let orientation = match obj.page_setup().orientation() {
                         gtk::PageOrientation::Portrait => "portrait",
                         gtk::PageOrientation::Landscape => "landscape",
@@ -404,6 +417,23 @@ mod imp {
                     obj.set_orientation(orientation);
 
                     obj.present();
+
+                    loop {
+                        match imp.status.get() {
+                             Status::Prepare  => {
+                                glib::MainContext::default().iteration(true);
+                             }
+                            Status::Print => {
+                                log::debug!("Layout dialog confirmed");
+                                obj.draw_page(context);
+                                break;}
+                            Status::Abort => {
+                                log::debug!("Layout dialog aborted");
+                                imp.print_operation.cancel();
+                                break;
+                            }
+                        }
+                    }
                 }
             ));
         }
@@ -802,8 +832,6 @@ impl LpPrint {
     fn print(&self) {
         self.close();
 
-        let print_operation = gtk::PrintOperation::new();
-
         let print_settings = self.print_operation().print_settings();
 
         if let Some(print_settings) = &print_settings {
@@ -812,27 +840,7 @@ impl LpPrint {
             }
         }
 
-        print_operation.set_print_settings(print_settings.as_ref());
-        print_operation.set_default_page_setup(Some(&self.print_operation().default_page_setup()));
-
-        print_operation.connect_begin_print(move |op, _ctx| {
-            op.set_n_pages(1);
-        });
-
-        print_operation.connect_draw_page(
-            glib::clone!(@weak self as obj => move |_operation, context, _page_nr| {
-            obj.draw_page(context);
-            }),
-        );
-
-        let res = print_operation.run(
-            gtk::PrintOperationAction::Print,
-            Some(&self.parent_window()),
-        );
-
-        if let Err(err) = res {
-            log::warn!("Print error: {err}");
-        }
+        self.imp().status.set(Status::Print);
     }
 
     /// Draw PDF for printing
-- 
GitLab