Repository: flxzt/rnote (language: rust)

Issue:
exporting selection doesn't work
**Describe the bug**  
made a sketch and tried exporting it to png,svg using selection tool but it fails and doesn't export ...no error is show in the UI like "exporting failed" it just doesn't export.

**To Reproduce**  
Steps to reproduce the behavior:
simply select your sketch using all strokes and try to export it in png,svg it doesn'k work,fails without warning.

**Expected behavior**  
I should be able to export the selected area of my sketch using selection tool to the formats png,svg.

**Console Output**  
(rnote:2): Gtk-WARNING **: 00:31:33.440: No IM module matching GTK_IM_MODULE=cedilla found

(rnote:2): Gtk-CRITICAL **: 00:33:14.868: The layout manager of type GtkBoxLayout 0x5593ecd63090 does not create GtkLayoutChild instances



**Screenshots**  
![ksnip_20240902-003943](https://github.com/user-attachments/assets/18968dcc-1556-4aaf-8d5f-75a9ee43e689)

selected this whole sketch and tried to export it to png,svg it fails.


![ksnip_20240902-003948](https://github.com/user-attachments/assets/26dda7b8-0f80-47ee-9851-76736835e949)


selected this whole sketch and tried to export it to png,svg it fails.


**Desktop (please complete the following information):**  
 - OS: [suse tumbleweed]
 - App Version: [ Rnote v0.11.0]
 - Installation Source: [Flatpak]
 - Desktop Environment: [kde 6.1.4]
 - Display Server: [ X11]
 - Input Source: [ External Graphics Tablet,Huion]



Export selection potential fix
make export selection match the other output modes

There is a minute difference.
On the two other modes we have
`if let Some(file)`
then we call `span_future_local`

This was the reverse for the selection export.
Trying to see if this fixes https://github.com/flxzt/rnote/issues/1199.
I've added a few debug trace to help with debugging for this issue

(it will only be a style PR otherwise)


Discussion / hints:
Is it only that mode or all export modes (export document or export document page) that don't work with any file ?
Is this on all or some file types (for selections there is svg, png and jpeg export type) ?
Did you choose a file to save to (as of now you always have to select a file first in the `export file` option) ? (If you don't the export button is greyed out so it won't trigger the export)
Normally there should always be either a confirmation or error message on all export options.

Could that be a flatpak file permission issue ?




> Is it only that mode or all export modes (export document or export document page) that don't work with any file ? Is this on all or some file types (for selections there is svg, png and jpeg export type) ? Did you choose a file to save to (as of now you always have to select a file first in the `export file` option) ? (If you don't the export button is greyed out so it won't trigger the export) Normally there should always be either a confirmation or error message on all export options.
> 
> Could that be a flatpak file permission issue ?

yes I am able to export documents but not selection and no error message is show in UI it just doesn't do anything...when I eport document by selecting a file a message is shown "exported successfully" but while exporting selection it shows nothing no error message nothing.
So it says "exported successfully" but there is no file when you do "open in file manager" (though that currently opens the parent folder, not highlight the exported file) ?
> So it says "exported successfully" but there is no file when you do "open in file manager" (though that currently opens the parent folder, not highlight the exported file) ?

It says "exported successfully" Only when  I export document or document pages and I am able to view it generates after "exported sucessfull"  Message. But when I try to export a selection of my sketch by selecting the file no message is shown and no file is generated... Basically export selection doesn't work for my sketch. 



Ran it with command line , when I try to export selection by selecting file a critical warning is given. 
After you clicked on the `export selection` could you see the dialog box, choose the file, click export and see the dialog window close ?

(this would mean the export.rs:854 line to close the dialog did run, and the issue is the block just after, that actually does the saving part)


Did you run it with `flatpak --env=RUST_LOG=rnote=debug --env=RUST_BACKTRACE=1 run com.github.flxzt.rnote` ?
Or `flatpak --env=RUST_LOG=rnote=error --env=RUST_BACKTRACE=1 run com.github.flxzt.rnote`
I want to check if you get a message like this
```
Did not export selection (Error or dialog dismissed by user), Err: {e:?}
```
with the first command and 
```
Exporting selection failed, Err: {e:?}
```
for the second one 

(or any other errors that could be of interest)

> After you clicked on the `export selection` could you see the dialog box, choose the file, click export and see the dialog window close ?
> 
> (this would mean the export.rs:854 line to close the dialog did run, and the issue is the block just after, that actually does the saving part)
> 
> Did you run it with `flatpak --env=RUST_LOG=rnote=debug --env=RUST_BACKTRACE=1 run com.github.flxzt.rnote` ? Or `flatpak --env=RUST_LOG=rnote=error --env=RUST_BACKTRACE=1 run com.github.flxzt.rnote` I want to check if you get a message like this
> 
> ```
> Did not export selection (Error or dialog dismissed by user), Err: {e:?}
> ```
> 
> with the first command and
> 
> ```
> Exporting selection failed, Err: {e:?}
> ```
> 
> for the second one
> 
> (or any other errors that could be of interest)

yeah I ran it in command line using  "flatpak --env=RUST_LOG=rnote=debug --env=RUST_BACKTRACE=1 run com.github.flxzt.rnote"

and  it shows this error:

(rnote:2): Gtk-CRITICAL **: 18:06:35.641: The layout manager of type GtkBoxLayout 0x55dbce144e10 does not create GtkLayoutChild instances


this error is shown when i try to export a selection ,exporting document or document pages works fine ...but when i export selection I select the file then click on export  and nothing happens.
@Doublonmousse 

https://github.com/user-attachments/assets/ffac322e-c1da-486d-b884-62901c6927ae

see in this video I try to export selection but nothing happens no message is shown nothing the application doesnt crash ,but if i Run it from cli  it shows this error :
`(rnote:2): Gtk-CRITICAL **: 18:06:35.641: The layout manager of type GtkBoxLayout 0x55dbce144e10 does not create GtkLayoutChild instances`

I am able to export selection in windows but not in linux.

So there was a (seemingly) minor difference between the export selection mode and the other two. I've opened a PR that makes this homogeneous between all three modes.

Not sure if this will fix the issue, but I'm at a loss if this doesn't (if this doesn't, this will be a style PR)

This might have to do with [glib](https://gtk-rs.org/gtk-rs-core/stable/0.20/docs/glib/index.html)::[clone](https://gtk-rs.org/gtk-rs-core/stable/0.20/docs/glib/macro.clone.html#) failing for some reason and returning `()` instead of the function that would export the document.

I've added a few `debug` trace as well to have a little more detail on what's happening



> So there was a (seemingly) minor difference between the export selection mode and the other two. I've opened a PR that makes this homogeneous between all three modes.
> 
> Not sure if this will fix the issue, but I'm at a loss if this doesn't (if this doesn't, this will be a style PR)
> 
> This might have to do with [glib](https://gtk-rs.org/gtk-rs-core/stable/0.20/docs/glib/index.html)::[clone](https://gtk-rs.org/gtk-rs-core/stable/0.20/docs/glib/macro.clone.html#) failing for some reason and returning `()` instead of the function that would export the document.
> 
> I've added a few `debug` trace as well to have a little more detail on what's happening
> 
> 
> 

Thanks, It doesn't work with linux only, in windows I was  able export selection. 
@ashish111333 Can you install the nightly flatpak following https://github.com/flxzt/rnote/blob/fbd056cde41a24c1d0b25dbeebc06893611661f5/BUILDING.md#nighties
But with the nightly found here :

https://github.com/Doublonmousse/rnote/actions/runs/10860824536 

And check whether this version works or not ?
@Doublonmousse hey thanks a lot. It's working now ,now when i export a selection I see a popup  and I also get the file 
(png,svg,jpeg). curious to know what was the problem  ?
This needs to be rewritten to the new `glib::clone` syntax. Maybe things _would_ work with the new glib version but in the current state, this was rewritten to the new syntax with potentially the same bug.

The fix was confirmed to work. 



Fix patch:
diff --git a/crates/rnote-ui/src/dialogs/export.rs b/crates/rnote-ui/src/dialogs/export.rs
index 592de47347..ab938b3ef8 100644
--- a/crates/rnote-ui/src/dialogs/export.rs
+++ b/crates/rnote-ui/src/dialogs/export.rs
@@ -271,49 +271,51 @@ pub(crate) async fn dialog_export_doc_w_prefs(appwindow: &RnAppWindow, canvas: &
     export_doc_button_confirm.connect_clicked(clone!(#[weak] dialog, #[weak] canvas, #[weak] appwindow , move |_| {
         dialog.close();
 
-        if let Some(file) = selected_file.take() {
-            glib::spawn_future_local(clone!(#[weak] canvas, #[weak] appwindow , async move {
-                appwindow.overlays().progressbar_start_pulsing();
-
-                let file_title = crate::utils::default_file_title_for_export(
-                    Some(file.clone()),
-                    Some(&canvas::OUTPUT_FILE_NEW_TITLE),
-                    None,
-                );
-                if let Err(e) = canvas.export_doc(&file, file_title, None).await {
-                    error!("Exporting document failed, Err: `{e:?}`");
-
-                    appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed"));
-                    appwindow.overlays().progressbar_abort();
-                } else {
-                    appwindow.overlays().dispatch_toast_w_button(
-                        &gettext("Exported document successfully"),
-                        &gettext("View in file manager"),
-                        clone!(#[weak] appwindow , move |_reload_toast| {
-                            let Some(folder_path_string) = file
-                                .parent()
-                                .and_then(|p|
-                                    p.path())
-                                .and_then(|p| p.into_os_string().into_string().ok()) else {
-                                    error!("Failed to get the parent folder of the output file `{file:?}.");
-                                    appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed"));
-                                    return;
-                            };
-
-                            if let Err(e) = open::that(&folder_path_string) {
-                                error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}");
-                                appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager"));
-                            }
-                        }
-                    ), crate::overlays::TEXT_TOAST_TIMEOUT_DEFAULT);
-                    appwindow.overlays().progressbar_finish();
-                }
-            }));
-        } else {
+        let Some(file) = selected_file.take() else {
             appwindow
                 .overlays()
                 .dispatch_toast_error(&gettext("Exporting document failed, no file selected"));
-        }
+            return;
+        };
+
+        glib::spawn_future_local(clone!(#[weak] canvas, #[weak] appwindow , async move {
+            appwindow.overlays().progressbar_start_pulsing();
+
+            let file_title = crate::utils::default_file_title_for_export(
+                Some(file.clone()),
+                Some(&canvas::OUTPUT_FILE_NEW_TITLE),
+                None,
+            );
+
+            if let Err(e) = canvas.export_doc(&file, file_title, None).await {
+                error!("Exporting document failed, Err: `{e:?}`");
+                appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed"));
+                appwindow.overlays().progressbar_abort();
+                return
+            }
+
+            appwindow.overlays().dispatch_toast_w_button(
+                &gettext("Exported document successfully"),
+                &gettext("View in file manager"),
+                clone!(#[weak] appwindow , move |_reload_toast| {
+                    let Some(folder_path_string) = file
+                        .parent()
+                        .and_then(|p|
+                            p.path())
+                        .and_then(|p| p.into_os_string().into_string().ok()) else {
+                            error!("Failed to get the parent folder of the output file `{file:?}.");
+                            appwindow.overlays().dispatch_toast_error(&gettext("Failed to view the file in the file manager"));
+                            return;
+                    };
+
+                    if let Err(e) = open::that(&folder_path_string) {
+                        error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}");
+                        appwindow.overlays().dispatch_toast_error(&gettext("Failed to view the file in the file manager"));
+                    }
+                }
+            ), crate::overlays::TEXT_TOAST_TIMEOUT_DEFAULT);
+            appwindow.overlays().progressbar_finish();
+        }));
     }));
 
     dialog.present(appwindow.root().as_ref());
@@ -685,41 +687,43 @@ pub(crate) async fn dialog_export_doc_pages_w_prefs(appwindow: &RnAppWindow, can
     export_doc_pages_button_confirm.connect_clicked(clone!(#[weak] export_files_stemname_entryrow, #[weak] dialog, #[weak] canvas, #[weak] appwindow,  move |_| {
         dialog.close();
 
-        if let Some(dir) = selected_file.take() {
-            glib::spawn_future_local(clone!(#[weak] export_files_stemname_entryrow, #[weak] canvas, #[weak] appwindow,  async move {
-                appwindow.overlays().progressbar_start_pulsing();
-
-                let file_stem_name = export_files_stemname_entryrow.text().to_string();
-                if let Err(e) = canvas.export_doc_pages(&dir, file_stem_name, None).await {
-                    error!("Exporting document pages failed, Err: {e:?}");
-
-                    appwindow.overlays().dispatch_toast_error(&gettext("Exporting document pages failed"));
-                    appwindow.overlays().progressbar_abort();
-                } else {
-                    appwindow.overlays().dispatch_toast_w_button(
-                        &gettext("Exported document pages successfully"),
-                        &gettext("View in file manager"),
-                        clone!(#[weak] appwindow,  move |_reload_toast| {
-                            let Some(folder_path_string) = dir.path().and_then(|p| p.into_os_string().into_string().ok()) else {
-                                error!("Failed to get the path of the parent folder");
-                                appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed"));
-                                return;
-                            };
-
-                            if let Err(e) = open::that(&folder_path_string) {
-                                error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}");
-                                appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager"));
-                            }
-                        }
-                    ), crate::overlays::TEXT_TOAST_TIMEOUT_DEFAULT);
-                    appwindow.overlays().progressbar_finish();
-                }
-            }));
-        } else {
+        let Some(dir) = selected_file.take() else {
             appwindow.overlays().dispatch_toast_error(&gettext(
                 "Exporting document pages failed, no directory selected",
             ));
-        }
+            return;
+        };
+
+        glib::spawn_future_local(clone!(#[weak] export_files_stemname_entryrow, #[weak] canvas, #[weak] appwindow,  async move {
+            appwindow.overlays().progressbar_start_pulsing();
+
+            let file_stem_name = export_files_stemname_entryrow.text().to_string();
+
+            if let Err(e) = canvas.export_doc_pages(&dir, file_stem_name, None).await {
+                error!("Exporting document pages failed, Err: {e:?}");
+                appwindow.overlays().dispatch_toast_error(&gettext("Exporting document pages failed"));
+                appwindow.overlays().progressbar_abort();
+                return
+            }
+
+            appwindow.overlays().dispatch_toast_w_button(
+                &gettext("Exported document pages successfully"),
+                &gettext("View in file manager"),
+                clone!(#[weak] appwindow,  move |_reload_toast| {
+                    let Some(folder_path_string) = dir.path().and_then(|p| p.into_os_string().into_string().ok()) else {
+                        error!("Failed to get the path of the parent folder");
+                        appwindow.overlays().dispatch_toast_error(&gettext("Failed to view the file in the file manager"));
+                        return;
+                    };
+
+                    if let Err(e) = open::that(&folder_path_string) {
+                        error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}");
+                        appwindow.overlays().dispatch_toast_error(&gettext("Failed to view the file in the file manager"));
+                    }
+                }
+            ), crate::overlays::TEXT_TOAST_TIMEOUT_DEFAULT);
+            appwindow.overlays().progressbar_finish();
+        }));
     }));
 
     dialog.present(appwindow.root().as_ref());
@@ -1033,50 +1037,51 @@ pub(crate) async fn dialog_export_selection_w_prefs(appwindow: &RnAppWindow, can
         }
     ));
 
-    export_selection_button_confirm.connect_clicked(clone!(#[weak] selected_file, #[weak] dialog, #[weak] canvas, #[weak] appwindow , move |_| {
+    export_selection_button_confirm.connect_clicked(clone!(#[weak] dialog, #[weak] canvas, #[weak] appwindow , move |_| {
         dialog.close();
 
-        glib::spawn_future_local(clone!(#[weak] selected_file, #[weak] canvas, #[weak] appwindow , async move {
-            let Some(file) = selected_file.take() else {
-                appwindow
-                    .overlays()
-                    .dispatch_toast_error(&gettext("Exporting selection failed, no file selected"));
-                return;
-            };
+        let Some(file) = selected_file.take() else {
+            appwindow
+                .overlays()
+                .dispatch_toast_error(&gettext("Exporting selection failed, no file selected"));
+            return;
+        };
+
+        glib::spawn_future_local(clone!(#[weak] canvas, #[weak] appwindow , async move {
             appwindow.overlays().progressbar_start_pulsing();
 
             if let Err(e) = canvas.export_selection(&file, None).await {
                 error!("Exporting selection failed, Err: {e:?}");
-
                 appwindow
                     .overlays()
                     .dispatch_toast_error(&gettext("Exporting selection failed"));
                 appwindow.overlays().progressbar_abort();
-            } else {
-                appwindow.overlays().dispatch_toast_w_button(
-                    &gettext("Exported selection successfully"),
-                    &gettext("View in file manager"),
-                    clone!(#[weak] appwindow , move |_reload_toast| {
-                                let Some(folder_path_string) = file
-                                    .parent()
-                                    .and_then(|p|
-                                        p.path())
-                                    .and_then(|p| p.into_os_string().into_string().ok()) else {
-                                        error!("Failed to get the parent folder of the output file `{file:?}.");
-                                        appwindow.overlays().dispatch_toast_error(&gettext("Exporting document failed"));
-                                        return;
-                                };
-
-                                if let Err(e) = open::that(&folder_path_string) {
-                                    error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}");
-                                    appwindow.overlays().dispatch_toast_error(&gettext("Failed to open the file in the file manager"));
-                                }
-                    }),
-                    crate::overlays::TEXT_TOAST_TIMEOUT_DEFAULT,
-                );
-                appwindow.overlays().progressbar_finish();
+                return;
             }
-            }));
+
+            appwindow.overlays().dispatch_toast_w_button(
+                &gettext("Exported selection successfully"),
+                &gettext("View in file manager"),
+                clone!(#[weak] appwindow , move |_| {
+                    let Some(folder_path_string) = file
+                        .parent()
+                        .and_then(|p|
+                            p.path())
+                        .and_then(|p| p.into_os_string().into_string().ok()) else {
+                            error!("Failed to get the parent folder of the output file `{file:?}.");
+                            appwindow.overlays().dispatch_toast_error(&gettext("Failed to view the file in the file manager"));
+                            return;
+                    };
+
+                    if let Err(e) = open::that(&folder_path_string) {
+                        error!("Opening the parent folder '{folder_path_string}' in the file manager failed, Err: {e:?}");
+                        appwindow.overlays().dispatch_toast_error(&gettext("Failed to view the file in the file manager"));
+                    }
+                }),
+                crate::overlays::TEXT_TOAST_TIMEOUT_DEFAULT,
+            );
+            appwindow.overlays().progressbar_finish();
+        }));
     }));
 
     dialog.present(appwindow.root().as_ref());


Test patch: